मैं उन महत्वपूर्ण वर्गों के साथ कई संभावित समस्याओं को देखता हूं। इन सभी के लिए गुहिकायन और समाधान हैं, लेकिन सारांश के रूप में:
- अनुकूलन या यादृच्छिक अन्य कारणों से इन मैक्रोज़ में संकलक को कोड को बढ़ने से रोकने के लिए कुछ भी नहीं है।
- वे प्रोसेसर के कुछ हिस्सों को सहेजते हैं और पुनर्स्थापित करते हैं, संकलक इनलाइन असेंबली को अकेले छोड़ने की उम्मीद करता है (जब तक कि इसे अन्यथा नहीं बताया जाता है)।
- अनुक्रम के बीच में होने और जब वह पढ़ा जाता है और जब यह लिखा जाता है, तब के बीच की स्थिति को बदलने से रोकना कुछ भी नहीं है।
सबसे पहले, आपको निश्चित रूप से कुछ संकलक मेमोरी बाधाओं की आवश्यकता है । 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