इंटेल और एएमडी के बीच प्रलेखन को पढ़ना और कोड को देखना कई बार यह समझना मुश्किल हो जाता है कि एक उचित टास्क स्टेट सेगमेंट (TSS) कैसे बनाया जाए जिसमें कोई IO पोर्ट बिटमैप (IOPB) न हो। आईओपीबी के साथ टीएसएस बनाने पर भी भ्रम की स्थिति प्रतीत होती है क्योंकि यह अस्पष्ट लगता है कि क्या आईओ बिटमैप (आईओपीबी) को पिछली 0xff बाइट की आवश्यकता है।

मुझे पता है कि टीएसएस और टीएसएस डिस्क्रिप्टर (जीडीटी में) के बीच एक निर्भरता है। टीएसएस डिस्क्रिप्टर टीएसएस के आधार पते के साथ-साथ सीमा को नियंत्रित करता है। डिस्क्रिप्टर में सीमा संरचना के वास्तविक आकार (जीडीटी और आईडीटी रिकॉर्ड में निर्दिष्ट आकार के समान) से एक कम है। IOPB के आकार को निर्धारित करने के लिए TSS सीमा चलन में आती है।

मुझे पता है कि:

  • TSS डिस्क्रिप्टर सीमा संपूर्ण TSS संरचना के आकार से एक कम है
  • 16-बिट TSS में IOPB नहीं होता है और संरचना एक निश्चित आकार की होती है
  • मूल 32-बिट और 64-बिट TSS संरचनाएं आकार में समान हैं (डेटा का अलग अर्थ है)
  • 32-बिट TSS आधार संरचना में एक अतिरिक्त DWORD जोड़कर नियंत्रण-प्रवाह प्रवर्तन का समर्थन कर सकता है।
  • TSS में IOPB ऑफ़सेट (शब्द) टास्क सेगमेंट की शुरुआत के सापेक्ष ऑफ़सेट की ओर इशारा करता है।
  • IOPB ऑफ़सेट एक IOPB संरचना की शुरुआत की ओर इशारा करता है, और वर्चुअल मोड एन्हांसमेंट (VME) IOPB इंटरप्ट पुनर्निर्देशन तालिका होने से पहले 32 बाइट्स सक्षम करें।
  • यदि VME सक्षम नहीं है, तो कर्नेल मूल TSS संरचना के अंत और IOPB ऑफ़सेट के बीच अतिरिक्त प्रति कार्य इंस्टेंस डेटा रख सकता है
  • यदि VME सक्षम है, तो कर्नेल मूल TSS संरचना के अंत और IOPB के नीचे ऑफ़सेट 32 बाइट्स के बीच अतिरिक्त प्रति कार्य इंस्टेंस डेटा रख सकता है।
  • यदि कोई IOPB मौजूद है, तो प्रत्येक 0 बिट पोर्ट एक्सेस की अनुमति है और 1 अनुमति से इनकार करता है।

32-बिट TSS संरचना को इस तरह से देखा जा सकता है:

enter image description here

लिंक में 16-बिट TSS और 64-बिट TSS संरचनाओं का लेआउट भी शामिल है।


प्रश्न:

  • यदि मुझे IOPB के बिना TSS चाहिए, तो IOPB ऑफ़सेट के लिए +66h पर मुझे क्या मान भरना चाहिए?
  • अगर मुझे IOPB वाला TSS चाहिए तो क्या मुझे IOPB के अंत में एक 0xff बाइट जोड़नी होगी?
  • ऊपर दिए गए आरेख में अंत में अतिरिक्त बाइट को xxxxx111 के रूप में क्यों दर्शाया जाता है। यदि अंतिम बाइट को 0xff माना जाता है, तो क्या वह 11111111 नहीं होगा?
3
Michael Petch 26 फरवरी 2019, 02:04

1 उत्तर

सबसे बढ़िया उत्तर

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

स्पष्ट रूप से IOPB का सही उपयोग करना तुच्छ नहीं है। इसके अलावा, गलत तरीके से स्थापित IOPB से स्पष्ट समस्याएं होने की संभावना नहीं है, लेकिन वांछित बंदरगाहों तक पहुंच की अनुमति नहीं दे सकता है या (बहुत खराब, सुरक्षा-वार) अवांछित बंदरगाहों तक पहुंच की अनुमति देता है।

TSS और IOPB का घिनौना इतिहास, क्योंकि यह 386BSD, NetBSD, OpenBSD में सुरक्षा खामियों और बगों से संबंधित है, एक दिलचस्प पढ़ने के लिए बनाता है और यह एक संकेतक होना चाहिए कि यदि आप बग्स को पेश करने से बचना चाहते हैं तो आपके द्वारा पूछे गए प्रश्न उचित हैं।


सवालों के जवाब

यदि आप कोई IOPB नहीं चाहते हैं, तो आप बस IOPB ऑफ़सेट फ़ील्ड को अपनी संपूर्ण TSS संरचना की लंबाई से भर सकते हैं (1 घटाएँ नहीं)। आपकी TSS संरचना में कोई पिछला 0xff बाइट नहीं होना चाहिए। टीएसएस डिस्क्रिप्टर में टीएसएस सीमा (जैसा कि आप पहले से ही जानते हैं) उस मूल्य से एक कम होगी। इंटेल मैनुअल कहता है कि कोई IOPB नहीं है यदि IOPB ऑफ़सेट मान में मान TSS सीमा से अधिक है। यदि IOPB ऑफ़सेट फ़ील्ड में मान हमेशा सीमा से 1 अधिक होता है, तो यह शर्त संतुष्ट होती है। इस प्रकार आधुनिक Microsoft Windows इसे संभालता है।

यदि IOPB का उपयोग कर रहे हैं तो अंत में एक अतिरिक्त बाइट को 0xff प्रति Intel दस्तावेज़ीकरण पर सेट करें। सभी 0xff के लिए एक अतिरिक्त बाइट सेट करने से किसी भी मल्टी पोर्ट एक्सेस (INW/OUTW/INL/OUTL) को अंतिम 8 पोर्ट में शुरू या समाप्त होने से रोका जा सकेगा। यह उस स्थिति से बच जाएगा जहां एक मल्टी पोर्ट पढ़ने/लिखने से आईओपीबी के अंत में फैल सकता है जिससे आईओपीबी की सीमा से बाहर आने वाले बंदरगाहों तक पहुंच हो सकती है। यह मल्टी पोर्ट एक्सेस को भी अस्वीकार कर देगा जो पिछले 8 पोर्ट से पहले वाले पोर्ट पर शुरू हुआ था जो निम्नलिखित 8 पोर्ट्स को पार करता है। यदि मल्टी पोर्ट एक्सेस के किसी पोर्ट में अनुमति बिट 1 पर सेट है, तो संपूर्ण पोर्ट एक्सेस अस्वीकार कर दिया गया है (इंटेल दस्तावेज़ के अनुसार)

यह स्पष्ट नहीं है कि आरेख के संदर्भ में x क्या दर्शाता है, लेकिन यदि उन बिट्स को 0 पर सेट किया गया था तो वे अनुमेय पोर्ट के रूप में दिखाई देंगे जो कि आप नहीं चाहते हैं। फिर से, इंटेल प्रलेखन के साथ चिपके रहें और एक अतिरिक्त अनुगामी बाइट को 0xff पर सेट करें (सभी बिट्स पहुंच से इनकार करने के लिए सेट हैं)।

Intel386 DX माइक्रोप्रोसेसर डेटा शीट से:

I/O अनुमति बिटमैप में प्रत्येक बिट एकल बाइट-वाइड I/O पोर्ट से मेल खाती है, जैसा कि चित्र 4-15a में दिखाया गया है। यदि बिट 0 है, तो संबंधित बाइट-वाइड पोर्ट के लिए I/O अपवाद उत्पन्न किए बिना हो सकता है। अन्यथा I/O निर्देश अपवाद 13 दोष का कारण बनता है। चूंकि प्रत्येक बाइट-वाइड I/O पोर्ट को संरक्षित किया जाना चाहिए, वर्ड-वाइड या dword-wide पोर्ट से संबंधित सभी बिट्स को वर्ड-वाइड या dword-wide I/O की अनुमति के लिए 0 होना चाहिए। यदि सभी संदर्भित बिट्स 0 हैं, तो I/O की अनुमति दी जाएगी। यदि कोई संदर्भित बिट 1 है, तो प्रयास किया गया I/O अपवाद 13 दोष का कारण बनेगा।

तथा

**महत्वपूर्ण कार्यान्वयन नोट: I/O अनुमति में I/O मैपिंग जानकारी के अंतिम बाइट से परे बिटमैप एक बाइट होना चाहिए जिसमें सभी 1 हों। सभी 1 की बाइट Intel386 DX TSS सेगमेंट की सीमा के भीतर होनी चाहिए (चित्र 4-15a देखें)।


NASM असेंबली में आप एक संरचना बना सकते हैं जो इस तरह दिखती है:

tss_entry:
.back_link: dd 0
.esp0:      dd 0              ; Kernel stack pointer used on ring transitions
.ss0:       dd 0              ; Kernel stack segment used on ring transitions
.esp1:      dd 0
.ss1:       dd 0
.esp2:      dd 0
.ss2:       dd 0
.cr3:       dd 0
.eip:       dd 0
.eflags:    dd 0
.eax:       dd 0
.ecx:       dd 0
.edx:       dd 0
.ebx:       dd 0
.esp:       dd 0
.ebp:       dd 0
.esi:       dd 0
.edi:       dd 0
.es:        dd 0
.cs:        dd 0
.ss:        dd 0
.ds:        dd 0
.fs:        dd 0
.gs:        dd 0
.ldt:       dd 0
.trap:      dw 0
.iomap_base:dw TSS_SIZE         ; IOPB offset
;.cetssp:    dd 0              ; Need this if CET is enabled

; Insert any kernel defined task instance data here
; ...

; If using VME (Virtual Mode extensions) there need to bean additional 32 bytes
; available immediately preceding iomap. If using VME uncomment next 2 lines
;.vmeintmap:                     ; If VME enabled uncomment this line and the next
;TIMES 32    db 0                ;     32*8 bits = 256 bits (one bit for each interrupt)

.iomap:
TIMES TSS_IO_BITMAP_SIZE db 0x0
                                ; IO bitmap (IOPB) size 8192 (8*8192=65536) representing
                                ; all ports. An IO bitmap size of 0 would fault all IO
                                ; port access if IOPL < CPL (CPL=3 with v8086)
%if TSS_IO_BITMAP_SIZE > 0
.iomap_pad: db 0xff             ; Padding byte that has to be filled with 0xff
                                ; To deal with issues on some CPUs when using an IOPB
%endif
TSS_SIZE EQU $-tss_entry

विशेष नोट:

  • यदि आप एक उच्च स्तरीय भाषा का उपयोग कर रहे हैं और एक TSS संरचना बना रहे हैं, तो सुनिश्चित करें कि आप एक पैक्ड संरचना का उपयोग करते हैं (अर्थात: GCC के __attribute__((packed)) या MSVC के #pragma pack)। अधिक जानकारी के लिए अपने कंपाइलर दस्तावेज़ की समीक्षा करें। इस सलाह पर ध्यान न देने से आपकी TSS संरचना के अंत में अतिरिक्त बाइट जुड़ सकते हैं जो IOPB होने पर समस्याएँ पैदा कर सकता है। यदि टीएसएस में एक आईओपीबी मौजूद है और अतिरिक्त पैडिंग बाइट्स जोड़े जाते हैं तो वे बाइट्स आईओ बिटमैप का हिस्सा बन जाएंगे और उन अनुमतियों को अनुदान/अस्वीकार कर सकते हैं जिन्हें आप नहीं चाहते थे। यह बीएसडी कर्नेल में बग उत्पन्न करने वाली विफलताओं में से एक थी।
  • जब IOPB के साथ या उसके बिना TSS बनाने की बात आती है तो 64-बिट TSS के नियम समान होते हैं। एक 64-बिट TSS अभी भी लॉन्ग मोड्स (64-बिट और कम्पैटिबिलिटी मोड) में उपयोग किया जाता है और टास्क रजिस्टर में उसी तरह लोड किया जाता है जैसे कि यह LTR निर्देश।
3
Michael Petch 11 मई 2019, 00:05