2013-05-03 5 views
6

पोस्ट-बूट वातावरण (कोई ओएस) में, एपी (अन्य सभी कोर/प्रोसेसर) के लिए आईपीआई बनाने के लिए कोई बीएसपी (पहला कोर/प्रोसेसर) का उपयोग कैसे करेगा? अनिवार्य रूप से, एक से शुरू होने पर अन्य कोरों के लिए निर्देश सूचक को कैसे जगाया जाता है और सेट किया जाता है?x86 असेंबली में एसएमपी के लिए एपी जागने के लिए आईपीआई बनाने के लिए एपीआईसी का उपयोग कैसे करें?

+0

[यह सवाल] (http://stackoverflow.com/questions/1622388/running-code-on-different-processor-x86-assembly) बुनियादी एल्गोरिथ्म एक और प्रोसेसर शुरू करने के लिए पता चलता है। क्या आप यही खोज रहे हैं, या आप आईपीआई को विशेष रूप से भेजने के विवरण चाहते हैं? (किसी भी तरह से मैं [OSDev विकि] करने के लिए बात करेंगे (http://wiki.osdev.org) और [मंचों] (http://forum.osdev.org) है, जो उपयोगी जानकारी के बहुत सारे है।) – ughoavgfhw

+0

मिनिमल उदाहरण: http://stackoverflow.com/a/33651438/895245 –

उत्तर

9

चेतावनी: मैंने यहां 80x86 माना है। यदि यह 80x86 नहीं है तो मुझे नहीं पता :-)

सबसे पहले आपको यह पता लगाना होगा कि कितने अन्य सीपीयू मौजूद हैं और उनके एपीआईसी आईडी क्या हैं, और स्थानीय एपीआईसी का भौतिक पता निर्धारित करते हैं। ऐसा करने के लिए आप एसीपीआई टेबल को पार्स करें (एसीपीआई विनिर्देश में एमएडीटी/एपीआईसी देखें)। यदि आपको वैध एसीपीआई टेबल नहीं मिलते हैं (उदा। कंप्यूटर बहुत पुराना है) वहां एक पुराना "मल्टीप्रोसेसर विशिष्टता" है जो इसकी अपनी तालिका को उसी जानकारी के साथ परिभाषित करता है। ध्यान दें कि "मल्टीप्रोसेसर विशिष्टता" अब बहिष्कृत है (और डमी मल्टीप्रोसेसर टेबल वाले कुछ कंप्यूटर हैं) यही कारण है कि आपको पहले एसीपीआई टेबल की जांच करने की आवश्यकता है।

अगला चरण यह निर्धारित करना है कि आपके पास किस प्रकार का स्थानीय एपीआईसी है। 3 मामले हैं - पुराना बाहरी "82489 डीएक्स" स्थानीय एपीआईसी (सीपीयू में स्वयं नहीं बनाया गया), xAPIC और x2APIC।

यह निर्धारित करने के लिए CPUID की जांच करके प्रारंभ करें कि स्थानीय एपीआईसी x2APIC है या नहीं। यदि आपके पास 2 विकल्प हैं - आप x2APIC का उपयोग कर सकते हैं, या आप "xAPIC संगतता मोड" का उपयोग कर सकते हैं। "XAPIC संगतता मोड" के लिए आप केवल 8-बिट एपीआईसी आईडी का उपयोग कर सकते हैं और बहुत से CPUs (उदा। 255 या अधिक CPUs) वाले कंप्यूटर का समर्थन नहीं कर पाएंगे। मैं x2APIC का उपयोग करने की अनुशंसा करता हूं (भले ही आप बहुत सारे CPUs वाले कंप्यूटरों की परवाह न करें) इसके तेज़ी से। यदि आप x2APIC मोड का उपयोग करते हैं तो आपको स्थानीय एपीआईसी को इस मोड में स्विच करने की आवश्यकता होगी।

अन्यथा, यदि यह x2APIC नहीं है, तो स्थानीय एपीआईसी के संस्करण रजिस्टर को पढ़ें। यदि स्थानीय एपीआईसी का संस्करण 0x10 या उसके बाद का है तो उसके xAPIC, और यदि यह 0x0F या इससे कम है तो यह बाहरी "82489DX" स्थानीय एपीआईसी है।

पुराने बाहरी "82489 डीएक्स" स्थानीय एपीआईसी 80486 और पुराने कंप्यूटरों में उपयोग किए जाते थे, और ये बेहद दुर्लभ होते हैं (वे 20 साल पहले बहुत दुर्लभ थे, तब अधिकांश की मृत्यु हो गई और/या उन्हें हटा दिया गया और बाद में फेंक दिया गया)। चूंकि अन्य सीपीयू शुरू करने के लिए एक अलग अनुक्रम का उपयोग किया जाता है, और क्योंकि इन स्थानीय एपीआईसी वाले कंप्यूटर बेहद दुर्लभ होते हैं (उदाहरण के लिए आप शायद कभी भी अपने कोड का परीक्षण नहीं कर पाएंगे) यह इन कंप्यूटरों का समर्थन करने से परेशान नहीं होने के लिए बहुत समझ में आता है। यदि आप इन पुराने कंप्यूटरों का बिल्कुल समर्थन करते हैं; मैं उन्हें "एकल-सीपीयू केवल" के रूप में इलाज करने की सलाह दूंगा और स्थानीय एपीआईसी "82489 डीएक्स" होने पर बस कोई अन्य सीपीयू/एस शुरू नहीं करूँगा। इस कारण से मैं उन्हें शुरू करने के लिए प्रयुक्त विधि का वर्णन नहीं करूंगा (यदि आप उत्सुक हैं तो इंटेल के "मल्टीप्रोसेस विशिष्टता" में वर्णित है)।

xAPIC और x2APIC के लिए, एक और सीपीयू शुरू करने के लिए अनुक्रम अनिवार्य रूप से वही है (स्थानीय एपीआईसी - एमएसआर या मेमोरी मैप किए जाने के बस अलग-अलग तरीकों)। मैं इन मतभेदों को छिपाने के लिए फ़ंक्शन पॉइंटर्स का उपयोग करने की अनुशंसा करता हूं; ताकि बाद में कोड "आईपीआई भेजें" फ़ंक्शन को कॉल कर सके। स्थानीय एपीआईसी x2APIC या xAPIC है, तो देखभाल किए बिना फ़ंक्शन पॉइंटर।

वास्तव में एक और सीपीयू शुरू करने के लिए आपको आईपीआई (इंटर प्रोसेसर इंटरप्ट्स) का अनुक्रम भेजने की आवश्यकता है। इंटेल की विधि इस प्रकार है:

Send an INIT IPI to the CPU you're starting 
Wait for 10 ms 
Send a STARTUP IPI to the CPU you're starting 
Wait for 200 us 
Send another STARTUP IPI to the CPU you're starting 
Wait for 200 us 
Wait for started CPU to set a flag (so you know it started) 
    If flag was set by other CPU, other CPU was started successfully 
    Else if time-out, other CPU failed to start 

इंटेल की विधि के साथ 2 समस्याएं हैं। अक्सर अन्य सीपीयू पहले स्टार्टअप आईपीआई द्वारा शुरू किया जाएगा, और कुछ मामलों में इससे समस्याएं पैदा हो सकती हैं (उदाहरण के लिए यदि अन्य सीपीयू का स्टार्टअप कोड total_CPUs++; जैसा कुछ करता है तो प्रत्येक सीपीयू इसे दो बार निष्पादित कर सकता है। इस समस्या से बचने के लिए आप अतिरिक्त जोड़ सकते हैं सिंक्रनाइज़ेशन (उदाहरण के लिए अन्य सीपीयू जारी रखने से पहले पहले सीपीयू द्वारा सेट किए जाने के लिए "मुझे पता है कि आपने शुरू किया" झंडा के लिए इंतजार कर रहा है)। इंटेल की विधि के साथ दूसरी समस्या उन देरी को माप रही है।आम तौर पर एक ओएस अन्य सीपीयू शुरू करता है, फिर यह पता लगाता है कि सीपीयू का समर्थन क्या है और बाद में कौन सा हार्डवेयर मौजूद है, और सटीक टाइमर/एस सेटअप में उन 200 हमें देरी को मापने के लिए सटीक नहीं है।

उन समस्याओं से बचने के लिए; मैं एक वैकल्पिक पद्धति है कि इस तरह से चला जाता है का उपयोग करें:

Send an INIT IPI to the CPU you're starting 
Wait for 10 ms 
Send a STARTUP IPI to the CPU you're starting 
Wait for started CPU to set a flag (so you know it started) with a short timeout (e.g. 1 ms) 
    If flag was set by other CPU, other CPU was started successfully 
    Else if time-out 
     Send another STARTUP IPI to the CPU you're starting 
     Wait for started CPU to set a flag with a long timeout (e.g. 200 ms) 
      If flag was set by other CPU, other CPU was started successfully 
      Else if time-out, other CPU failed to start 
If CPU started successfully 
    Set flag to tell other CPU it can continue 

भी ध्यान रखें कि आप व्यक्तिगत रूप से सीपीयू शुरू करने के लिए की जरूरत है। मैंने लोगों को "सभी के लिए प्रसारण आईपीआई" का उपयोग करके सभी CPUs एक ही समय में शुरू किया है - यह गलत और टूटा हुआ है और डोडी (जब तक आप फर्मवेयर लिख रहे हों तब तक ऐसा न करें)। इसके साथ समस्या यह है कि कुछ CPUs दोषपूर्ण हो सकते हैं (उदा। उनके BIST/अंतर्निहित स्वयं परीक्षण में विफल) और कुछ CPUs अक्षम हो सकते हैं (उदा। हाइपर-थ्रेडिंग जब फर्मवेयर में हाइपर-थ्रेडिंग अक्षम होती है); और "सभी के लिए प्रसारण आईपीआई स्वयं" विधि सीपीयू शुरू कर सकती है जिसे कभी शुरू नहीं किया जाना चाहिए था।

अंत में, सीपीयू की एक बड़ी संख्या के साथ कंप्यूटर के लिए यह एक अपेक्षाकृत लंबा समय लग उन सब को शुरू करने के लिए अगर आप उन्हें एक बार में एक ही शुरू कर रहे हैं कर सकते हैं। उदाहरण के लिए, यदि प्रत्येक सीपीयू शुरू करने में 11 एमएस लगते हैं और 128 सीपीयू हैं, तो इसमें 1.4 सेकंड लगेंगे। यदि आप तेजी से बूट करना चाहते हैं तो इससे बचने के तरीके हैं। उदाहरण के लिए, पहले सीपीयू दूसरी सीपीयू शुरू कर सकते हैं, तो 1 और 2 सीपीयू 3 और 4 सीपीयू शुरू कर सकते हैं, तो उन चार सीपीयू इस तरह अगले चार सीपीयू, आदि शुरू कर सकते हैं आप 77 एमएस में 128 सीपीयू शुरू कर सकते हैं 1.4 सेकंड के बजाय।

नोट: मैं केवल एक समय में सीपीयू शुरू करने की सिफारिश करता हूं और यह सुनिश्चित करता हूं कि किसी भी तरह के "समांतर स्टार्टअप" का प्रयास करने से पहले यह काम करता है (यह कुछ है जो आप बाकी कार्यों को जानने के बाद बाद में चिंता कर सकते हैं)।

अन्य सीपीयू/एस निष्पादन शुरू करने वाला पता STARTUP आईपीआई के "वेक्टर" क्षेत्र में एन्कोड किया गया है। सीपीयू CS = vector * 256 और IP = 0 के साथ कोड (वास्तविक मोड में) निष्पादित करना शुरू कर देगा। वेक्टर फ़ील्ड 8-बिट है, इसलिए आप जिस उच्चतम प्रारंभिक पते का उपयोग कर सकते हैं वह 0x000FF000 (0xFF00: 0x0000 वास्तविक मोड में) है। हालांकि, यह विरासत रोम क्षेत्र है (प्रैक्टिस में शुरुआती पता कम होना होगा)। आम तौर पर आप स्टार्टअप कोड का एक छोटा टुकड़ा एक उपयुक्त पते में कॉपी करेंगे; जहां स्टार्टअप कोड तुल्यकालन संभालती है (उदाहरण के लिए सेट करते समय एक "मैं शुरू कर दिया" झंडा है कि एक और सीपीयू को देख सकते हैं और यह जारी रखने के लिए ठीक है बताया जाने की प्रतीक्षा) और फिर संरक्षित/लंबे मोड को सक्षम और एक ढेर की स्थापना के लिए एक प्रवेश करने के लिए कूद से पहले की तरह काम करता है ओएस के सामान्य कोड में इंगित करें। स्टार्टअप कोड के इस छोटे टुकड़े को "एपी सीपीयू स्टार्टअप ट्रैम्पोलिन" कहा जाता है। यह भी "समानांतर स्टार्टअप" थोड़ा जटिल बनाता है; क्योंकि प्रत्येक सीपीयू को शुरू करने के लिए अपने स्वयं के/अलग सिंक्रनाइज़ेशन झंडे और ढेर की आवश्यकता होती है; और क्योंकि इन चीजों को आम तौर पर ट्रैम्पोलिन में चर के साथ कार्यान्वित किया जाता है (उदा। mov esp,[cs:stackTop]) इसका मतलब है कई ट्रैम्पोलिन के साथ समाप्त होता है।

+0

आप किसी दिए गए समय के लिए कैसे प्रतीक्षा करें? संबंधित http://stackoverflow.com/questions/9971405/assembly-display-in- स्क्रीन- और- सिस्टम- सो –

संबंधित मुद्दे