मुझे हाल ही में एक कस्टम लिनक्स कर्नेल (2.6.31.5, x86) ड्राइवर में एक समस्या का सामना करना पड़ा जहां copy_to_user समय-समय पर उपयोगकर्ता बाइट को किसी बाइट की प्रतिलिपि नहीं बनायेगा। यह इसे पारित बाइट्स की गिनती वापस कर देगा, जो दर्शाता है कि उसने कुछ भी कॉपी नहीं किया था। कोड निरीक्षण के बाद हमने पाया कि कोड copy_to_user को कॉल करते समय इंटरप्ट को अक्षम कर रहा था जो इसके अनुबंध का उल्लंघन करता है। इसे ठीक करने के बाद, समस्या उत्पन्न हो गई। चूंकि यह मुद्दा इतनी बार हुआ, मुझे यह साबित करने की ज़रूरत है कि बाधाओं को अक्षम करने से समस्या उत्पन्न हुई।क्या होता है जब एक mov निर्देश x86 पर अक्षम इंटरप्ट के साथ पेज गलती का कारण बनता है?
यदि आप आर्क/x86/lib/usercopy_32.c प्रतिनिधि से नीचे कोड स्निपेट देखते हैं; movsl शब्दों को सीएक्स में गिनती से उपयोगकर्ता स्थान पर कॉपी करता है। बाहर निकलने पर सीएक्स के साथ आकार अपडेट किया गया है। यदि movsl सही ढंग से निष्पादित करता है तो सीएक्स 0 होगा। क्योंकि सीएक्स शून्य नहीं है, movs? copy_to_user और मनाए गए व्यवहार की परिभाषा को फिट करने के लिए निर्देशों को निष्पादित नहीं किया जाना चाहिए था।
/* Generic arbitrary sized copy. */
#define __copy_user(to, from, size) \
do { \
int __d0, __d1, __d2; \
__asm__ __volatile__( \
" cmp $7,%0\n" \
" jbe 1f\n" \
" movl %1,%0\n" \
" negl %0\n" \
" andl $7,%0\n" \
" subl %0,%3\n" \
"4: rep; movsb\n" \
" movl %3,%0\n" \
" shrl $2,%0\n" \
" andl $3,%3\n" \
" .align 2,0x90\n" \
"0: rep; movsl\n" \
" movl %3,%0\n" \
"1: rep; movsb\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"5: addl %3,%0\n" \
" jmp 2b\n" \
"3: lea 0(%3,%0,4),%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 4b,5b\n" \
" .long 0b,3b\n" \
" .long 1b,2b\n" \
".previous" \
: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
: "3"(size), "0"(size), "1"(to), "2"(from) \
: "memory"); \
} while (0)
2 विचारों है कि मैं कर रहे हैं:
- जब बीच में आता है अक्षम हैं, पृष्ठ दोष नहीं होती है और तो प्रतिनिधि; movs? कुछ भी किए बिना छोड़ दिया गया है। वापसी मूल्य तब सीएक्स होगा, या उपयोगकर्ता स्पेस की प्रतिलिपि नहीं की गई राशि, क्योंकि परिभाषा निर्दिष्ट करती है और व्यवहार देखा जाता है।
- पेज गलती होती है, लेकिन लिनक्स इसे संसाधित नहीं कर सकता क्योंकि इंटरप्ट अक्षम हैं, इसलिए पेज गलती हैंडलर निर्देश छोड़ देता है, हालांकि मुझे नहीं पता कि पेज गलती हैंडलर यह कैसे करेगा। फिर, इस मामले में सीएक्स अनमोडिफाइड रहेगा और वापसी मूल्य सही होगा।
क्या कोई मुझे इंटेल मैनुअल में सेक्शन में इंगित कर सकता है जो इस व्यवहार को निर्दिष्ट करता है, या मुझे किसी भी अतिरिक्त लिनक्स स्रोत को इंगित करता है जो उपयोगी हो सकता है?
आप उल्लेख करते हैं कि "कोड इंटरप्ट अक्षम कर रहा था"। क्या आप विस्तारित कर सकते हैं कि कौन सा इंटरप्ट करता है और कैसे? ... – TheCodeArtist
@TheCodeArtist: write_lock_bh(); आयोजित किया गया था, जो मेरी समझ से सॉफ्टवेयर इंटरप्ट अक्षम करता है। – Edward
@TheCodeArtist: धन्यवाद! आपकी टिप्पणी ने मुझे write_lock_bh() में बहुत अधिक बारीकी से देखा, मुझे रास्ता दिखा रहा है! – Edward