एआरएम कोर्टेक्स ए 9 पर महत्वपूर्ण अनुभागों को कैसे लागू किया जाए


15

मैं एक ARM926 कोर से CortexA9 के लिए कुछ विरासत कोड पोर्ट कर रहा हूं। यह कोड नंगे है और इसमें OS या मानक लाइब्रेरी, सभी कस्टम शामिल नहीं हैं। मुझे एक विफलता हो रही है जो एक दौड़ की स्थिति से संबंधित प्रतीत होती है जिसे कोड के महत्वपूर्ण खंड द्वारा रोका जाना चाहिए।

मैं अपने दृष्टिकोण पर कुछ प्रतिक्रिया चाहता हूं यह देखने के लिए कि क्या इस सीपीयू के लिए मेरे महत्वपूर्ण खंडों को सही ढंग से लागू नहीं किया जा सकता है। मैं जीसीसी का उपयोग कर रहा हूं। मुझे संदेह है कि कुछ सूक्ष्म त्रुटि है।

इसके अलावा, वहाँ एक ओपनसोर्स पुस्तकालय है जिसमें एआरएम (या यहां तक ​​कि एक अच्छा हल्का स्पिनलॉक / सेफ़होर पुस्तकालय) के लिए इस प्रकार की आदिम हैं?

#define ARM_INT_KEY_TYPE            unsigned int
#define ARM_INT_LOCK(key_)   \
asm volatile(\
    "mrs %[key], cpsr\n\t"\
    "orr r1, %[key], #0xC0\n\t"\
    "msr cpsr_c, r1\n\t" : [key]"=r"(key_) :: "r1", "cc" );

#define ARM_INT_UNLOCK(key_) asm volatile ("MSR cpsr_c,%0" : : "r" (key_))

कोड निम्नानुसार उपयोग किया जाता है:

/* lock interrupts */
ARM_INT_KEY_TYPE key;
ARM_INT_LOCK(key);

<access registers, shared globals, etc...>

ARM_INT_UNLOCK(key);

"कुंजी" का विचार नेस्टेड क्रिटिकल सेक्शन को अनुमति देने के लिए है, और इनका उपयोग रीक्रेंट फ़ंक्शंस बनाने के लिए फ़ंक्शंस की शुरुआत और अंत में किया जाता है।

धन्यवाद!


1
कृपया infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/… पर सन्दर्भित आसन btw में न करें। यह एक समारोह के रूप में लेख करता है।
जेसन हू

मुझे एआरएम के बारे में कुछ भी नहीं पता है, लेकिन मुझे उम्मीद है कि म्यूटेक्स (या किसी भी क्रॉस-थ्रेड या क्रॉस-प्रोसेस सिंक फ़ंक्शन) के लिए, आपको यह सुनिश्चित करने के लिए "मेमोरी" क्लोबर का उपयोग करना चाहिए कि ए) वर्तमान में रजिस्टरों में कैश किए गए सभी मेमोरी वैल्यू फ्लश हो गए हैं asm और b को निष्पादित करने से पहले मेमोरी में वापस आ जाएं ) asm को पुनः लोड होने के बाद एक्सेस की जाने वाली मेमोरी में कोई भी मान। ध्यान दें कि एक कॉल करना (जैसा कि HuStmpHrrr अनुशंसा करता है) को आपके लिए इस क्लोब का प्रदर्शन करना चाहिए।

इसके अलावा, जब मैं अभी भी एआरएम नहीं बोलता, तो 'की_' के लिए आपकी अड़चनें सही नहीं लगती हैं। चूंकि आप कहते हैं कि इसका उपयोग पुनः प्रवेश के लिए किया जाना है, इसलिए इसे लॉक में "= r" घोषित करना संदेहास्पद लगता है। '=' का अर्थ है कि आप इसे अधिलेखित करने का इरादा रखते हैं, और मौजूदा मूल्य महत्वहीन है। ऐसा लगता है कि आपने मौजूदा मूल्य को अद्यतन करने के अपने इरादे को इंगित करने के लिए '+' का उपयोग करने का इरादा किया है। और फिर से अनलॉक करने के लिए, इसे इनपुट के रूप में सूचीबद्ध करना बताता है कि आप इसे बदलने का इरादा नहीं रखते हैं, लेकिन अगर मैं गलत नहीं हूं, तो आप इसे बदल दें। मुझे लगता है कि इसे भी '+' आउटपुट के रूप में सूचीबद्ध किया जाना चाहिए।

1
इस तरह के एक उच्च कल्पना कोर के लिए विधानसभा में कोडिंग के लिए +1। वैसे भी, यह विशेषाधिकार मोड से संबंधित हो सकता है?
दजार्दा

मुझे पूरा यकीन है कि आपको इसका उपयोग करने ldrexऔर strexइसे ठीक से करने की आवश्यकता होगी । यहाँ एक वेबपेज दिखाया गया है कि आप कैसे उपयोग कर सकते हैं ldrexऔर strexएक स्पिनलॉक लागू कर सकते हैं।

जवाबों:


14

ओएस के बिना एक महत्वपूर्ण अनुभाग को संभालने का सबसे कठिन हिस्सा वास्तव में म्यूटेक्स नहीं बना रहा है, बल्कि यह पता लगाना है कि क्या होना चाहिए अगर कोड एक संसाधन का उपयोग करना चाहता है जो वर्तमान में उपलब्ध नहीं है। लोड-अनन्य और सशर्त-स्टोर-अनन्य निर्देश एक "स्वैप" फ़ंक्शन बनाने में काफी आसान बनाते हैं, जो एक पूर्णांक के लिए एक संकेतक दिया जाता है, जो परमाणु मूल्य को एक नया स्टोर करेगा, लेकिन इंगित किए गए पूर्णांक में निहित था:

int32_t atomic_swap(int32_t *dest, int32_t new_value)
{
  int32_t old_value;
  do
  {
    old_value = __LDREXW(&dest);
  } while(__STREXW(new_value,&dest);
  return old_value;
}

उपरोक्त जैसे एक फंक्शन को देखते हुए, कोई आसानी से किसी चीज़ के माध्यम से म्यूटेक्स में प्रवेश कर सकता है

if (atomic_swap(&mutex, 1)==0)
{
   ... do stuff in mutex ... ;
   mutex = 0; // Leave mutex
}
else
{ 
  ... couldn't get mutex...
}

ओएस की अनुपस्थिति में, मुख्य कठिनाई अक्सर "म्यूटेक्स नहीं पा सके" कोड के साथ होती है। यदि म्यूटेक्स-गार्ड किए गए संसाधन व्यस्त होने पर कोई व्यवधान उत्पन्न होता है, तो यह आवश्यक हो सकता है कि इंटरप्ट-हैंडलिंग कोड एक ध्वज सेट किया जाए और कुछ सूचनाओं को सहेजने के लिए यह इंगित किया जाए कि वह क्या करना चाहता था, और फिर कोई भी मुख्य-जैसा कोड प्राप्त करता है mutex की जाँच करें जब भी यह देखने के लिए mutex को जारी करने जा रहा है कि क्या mutex आयोजित करते समय कोई व्यवधान कुछ करना चाहता था और, यदि ऐसा है, तो व्यवधान की ओर से कार्रवाई करें।

हालाँकि यह संभव है कि केवल व्यवधान (और वास्तव में, किसी अन्य प्रकार के म्यूटेक्स की आवश्यकता को समाप्त कर सकता है) को बाधित करके म्यूटेक्स-गार्ड किए गए संसाधनों का उपयोग करने में बाधा डालने वाली समस्याओं से बचना संभव है, सामान्य तौर पर आवश्यक से अधिक लंबे समय तक बाधित होने से बचने के लिए यह वांछनीय है।

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

किसी भी मामले में, जो सबसे महत्वपूर्ण होगा वह यह होगा कि किस कोड के द्वारा म्यूटेक्स-गार्ड किए गए संसाधन का उपयोग करने की कोशिश की जाती है जब यह अनुपलब्ध होता है जब संसाधन जारी होने के बाद अपने प्रयास को दोहराने का साधन होगा।


7

यह महत्वपूर्ण वर्गों को करने के लिए एक भारी हाथ है; अक्षम करें। यदि आपके सिस्टम में डेटा दोष हैं, तो यह काम नहीं कर सकता है। यह रुकावट विलंबता भी बढ़ाएगा। लिनक्स irqflags.h कुछ मैक्रो है कि इस संभाल है। cpsieऔर cpsidनिर्देश शायद उपयोगी; हालांकि, वे राज्य नहीं बचाते हैं और घोंसले के शिकार के लिए अनुमति नहीं देंगे। cpsएक रजिस्टर का उपयोग नहीं करता है।

के लिए कॉर्टेक्स-ए श्रृंखला, ldrex/strexअधिक कुशल हैं और एक के रूप में काम कर सकते हैं म्युटेक्स महत्वपूर्ण अनुभाग के लिए या वे के साथ इस्तेमाल किया जा सकता ताला मुक्त महत्वपूर्ण अनुभाग से छुटकारा पाने के एल्गोरिदम।

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

मुझे संदेह है कि कुछ सूक्ष्म त्रुटि है।

mrs %[key], cpsr
orr r1, %[key], #0xC0  ; context switch here?
msr cpsr_c, r1

आपको यह सुनिश्चित करने की आवश्यकता है कि अनुक्रम कभी भी पूर्व-खाली नहीं हो सकता है । अन्यथा, आपको दो प्रमुख चर मिल सकते हैं, जिसमें इंटरप्ट सक्षम है और लॉक रिलीज गलत होगा। आप ARMv5 पर स्थिरता सुनिश्चित करने के लिए प्रमुख मेमोरी के swpसाथ निर्देश का उपयोग कर सकते हैं , लेकिन यह निर्देश Cortex-A के पक्ष में हटा दिया गया हैldrex/strex क्योंकि यह मल्टी-सीपीयू सिस्टम के लिए बेहतर काम करता है।

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

इसके अलावा, वहाँ एक ओपनसोर्स पुस्तकालय है जिसमें एआरएम (या यहां तक ​​कि एक अच्छा हल्का स्पिनलॉक / सेफ़होर पुस्तकालय) के लिए इस प्रकार की आदिम हैं?

यह पोर्टेबल तरीके से लिखना मुश्किल है। यानी, एआरएम सीपीयू के कुछ संस्करणों और विशिष्ट ओएस के लिए ऐसी लाइब्रेरी मौजूद हो सकती है।


2

मैं उन महत्वपूर्ण वर्गों के साथ कई संभावित समस्याओं को देखता हूं। इन सभी के लिए गुहिकायन और समाधान हैं, लेकिन सारांश के रूप में:

  • अनुकूलन या यादृच्छिक अन्य कारणों से इन मैक्रोज़ में संकलक को कोड को बढ़ने से रोकने के लिए कुछ भी नहीं है।
  • वे प्रोसेसर के कुछ हिस्सों को सहेजते हैं और पुनर्स्थापित करते हैं, संकलक इनलाइन असेंबली को अकेले छोड़ने की उम्मीद करता है (जब तक कि इसे अन्यथा नहीं बताया जाता है)।
  • अनुक्रम के बीच में होने और जब वह पढ़ा जाता है और जब यह लिखा जाता है, तब के बीच की स्थिति को बदलने से रोकना कुछ भी नहीं है।

सबसे पहले, आपको निश्चित रूप से कुछ संकलक मेमोरी बाधाओं की आवश्यकता है । GCC इन्हें क्लोबर्स के रूप में लागू करता है । मूल रूप से, यह संकलक को बताने का एक तरीका है "नहीं, आप इनलाइन असेंबली के इस हिस्से में मेमोरी एक्सेस को स्थानांतरित नहीं कर सकते क्योंकि यह मेमोरी एक्सेस के परिणाम को प्रभावित कर सकता है।" विशेष रूप से, आप दोनों की जरूरत है "memory"और "cc"clobbers, शुरू और समाप्त मैक्रो दोनों पर। ये इनलाइन असेंबली के सापेक्ष अन्य चीजों (जैसे फंक्शन कॉल्स) को फिर से होने से रोकेंगे, क्योंकि कंपाइलर को पता है कि उनके पास मेमोरी एक्सेस हो सकती है। मैंने "memory"क्लोबर्स के साथ इनलाइन असेंबली में हालत कोड रजिस्टर में एआरएम होल्ड स्टेट के लिए जीसीसी देखा है , इसलिए आपको क्लोबर की निश्चित रूप से आवश्यकता है "cc"

दूसरे, ये महत्वपूर्ण खंड बचत कर रहे हैं और बहुत अधिक बहाल कर रहे हैं या नहीं कि क्या व्यवधान सक्षम हैं। विशेष रूप से, वे अधिकांश सीपीएसआर (वर्तमान कार्यक्रम स्थिति रजिस्टर) को सहेज रहे हैं और पुनर्स्थापित कर रहे हैं (लिंक कोर्टेक्स-आर 4 के लिए है क्योंकि मुझे ए 9 के लिए एक अच्छा आरेख नहीं मिल सका है, लेकिन यह समान होना चाहिए)। ऐसे सूक्ष्म प्रतिबंध हैं जिनके आसपास राज्य के टुकड़े वास्तव में संशोधित किए जा सकते हैं, लेकिन यह यहां आवश्यक से अधिक है।

अन्य बातों के अलावा, इसमें शर्त कोड शामिल हैं (जहां निर्देशों के परिणाम cmpसंग्रहीत हैं, इसलिए बाद के सशर्त निर्देश परिणाम पर कार्य कर सकते हैं)। संकलक निश्चित रूप से इससे भ्रमित होंगे। "cc"जैसा कि ऊपर बताया गया है, यह क्लोबर का उपयोग करके आसानी से हल किया जा सकता है। हालाँकि, यह कोड को हर बार विफल बना देगा, इसलिए यह ध्वनि नहीं करता है कि आप क्या समस्याएँ देख रहे हैं। हालांकि, कुछ समय के टिक बम में, यादृच्छिक रूप से अन्य कोड को संशोधित करने से कंपाइलर को कुछ अलग करने का कारण हो सकता है, जो इस से टूट जाएगा।

यह आईटी बिट्स को बचाने / पुनर्स्थापित करने का भी प्रयास करेगा, जिनका उपयोग थम्ब सशर्त निष्पादन को लागू करने के लिए किया जाता है । ध्यान दें कि यदि आप कभी भी Thumb कोड निष्पादित नहीं करते हैं, तो इससे कोई फर्क नहीं पड़ता। मैंने कभी यह नहीं सोचा है कि जीसीसी की इनलाइन असेंबली आईटी बिट्स के साथ कैसे निपटती है, यह निष्कर्ष निकालने के अलावा, इसका मतलब यह नहीं है कि कंपाइलर को कभी भी इनलाइन असेंबली को आईटी ब्लॉक में नहीं डालना चाहिए और हमेशा असेंबली को आईटी ब्लॉक के बाहर समाप्त होने की उम्मीद है। मैंने कभी जीसीसी को इन मान्यताओं का उल्लंघन करते हुए कोड नहीं देखा है, और मैंने भारी अनुकूलन के साथ कुछ काफी जटिल इनलाइन असेंबली की है, इसलिए मुझे यकीन है कि वे पकड़ लेंगे। इसका मतलब यह है कि यह वास्तव में आईटी बिट्स को बदलने का प्रयास नहीं करेगा, जिस स्थिति में सब कुछ ठीक है। इन बिट्स को संशोधित करने का प्रयास किया जा रहा है "आर्किटेक्चरली अप्रत्याशित" के रूप वर्गीकृत किया गया है, इसलिए यह सभी प्रकार के बुरे काम कर सकता है, लेकिन शायद जीता '

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

तीसरा, वहाँ कुछ भी नहीं के बीच CPSR के अन्य भागों में बदलाव करने से व्यवधान रोक रही है MRSऔर MSRमें ARM_INT_LOCK। ऐसा कोई भी परिवर्तन अधिलेखित किया जा सकता है। अधिकांश उचित प्रणालियों में, अतुल्यकालिक व्यवधान उस कोड की स्थिति को नहीं बदलते हैं जो वे बाधित कर रहे हैं (सीपीएसआर सहित)। यदि वे करते हैं, तो यह बहुत कठिन हो जाता है कि कोड क्या करेगा। हालांकि, यह संभव है (FIQ अक्षम बिट मुझे बदलने की संभावना है), इसलिए आपको विचार करना चाहिए कि क्या आपका सिस्टम ऐसा करता है।

यहां बताया गया है कि मैं इन्हें किस तरह से लागू करूंगा, जो मेरे द्वारा बताए गए सभी संभावित मुद्दों को संबोधित करता है:

#define ARM_INT_KEY_TYPE            unsigned int
#define ARM_INT_LOCK(key_)   \
asm volatile(\
    "mrs %[key], cpsr\n\t"\
    "ands %[key], %[key], #0xC0\n\t"\
    "cpsid if\n\t" : [key]"=r"(key_) :: "memory", "cc" );
#define ARM_INT_UNLOCK(key_) asm volatile (\
    "tst %[key], #0x40\n\t"\
    "beq 0f\n\t"\
    "cpsie f\n\t"\
    "0: tst %[key], #0x80\n\t"\
    "beq 1f\n\t"\
    "cpsie i\n\t"
    "1:\n\t" :: [key]"r" (key_) : "memory", "cc")

-mcpu=cortex-a9कम से कम कुछ जीसीसी संस्करण (जैसे मेरा) डिफ़ॉल्ट रूप से पुराने एआरएम सीपीयू जो समर्थन नहीं करता है cpsieऔर के साथ संकलित करना सुनिश्चित करें cpsid

मैं andsसिर्फ के बजाय में इस्तेमाल किया andहै ARM_INT_LOCKतो यह एक 16-बिट अनुदेश है अगर यह अंगूठे के कोड में उपयोग किया जाता है। "cc"मार-पीट, वैसे भी आवश्यक है तो यह सख्ती से एक प्रदर्शन / कोड आकार लाभ है।

0और संदर्भ के लिए स्थानीय लेबल1 हैं ।

ये आपके संस्करणों के समान सभी तरीकों से उपयोग करने योग्य होना चाहिए। ARM_INT_LOCKबस के रूप में तेजी से / लघु अपने मूल एक के रूप में है। दुर्भाग्य से, मैं ARM_INT_UNLOCKकुछ निर्देशों के रूप में कहीं भी सुरक्षित रूप से करने का एक तरीका नहीं ले सका ।

यदि IRQ और FIQ को अक्षम करने पर आपके सिस्टम में बाधा है, तो इसे सरल बनाया जा सकता है। उदाहरण के लिए, यदि वे हमेशा एक साथ अक्षम होते हैं, तो आप इस तरह एक cbz+ में जोड़ सकते हैं cpsie if:

#define ARM_INT_UNLOCK(key_) asm volatile (\
    "cbz %[key], 0f\n\t"\
    "cpsie if\n\t"\
    "0:\n\t" :: [key]"r" (key_) : "memory", "cc")

वैकल्पिक रूप से, यदि आप FIQ के बारे में बिल्कुल भी परवाह नहीं करते हैं, तो यह पूरी तरह से सक्षम करने / अक्षम करने को छोड़ने के समान है।

यदि आप जानते हैं कि लॉक और अनलॉक के बीच सीपीएसआर में किसी भी अन्य राज्य के बिट्स को कभी भी नहीं बदलता है, तो आप अपने मूल कोड के समान कुछ के साथ जारी रख सकते हैं, दोनों "memory"और "cc"क्लोब के साथ दोनों में ARM_INT_LOCKऔरARM_INT_UNLOCK


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.