當活動(即由TR寄存器指向的那個)TSS的字段發生改變時會發生什麼?特別是,對ESP0/RSP0字段的更改是否立即生效?或者處理器是否像段選擇器一樣保留TSS緩存,所以需要LTR指令來強制處理器重新加載TSS字段?x86/x64:修改TSS字段
回答
處理器使用TSS存儲當前上下文,並在任務切換期間加載下一個要調度的上下文。
在CPU切換到此類TSS之前,更改TSS結構不會影響任何上下文。
CPU執行任務切換時
軟件或處理器可以通過以下方式之一派遣執行一個任務:
•與CALL指令任務的顯式調用。
•使用JMP指令顯式跳轉到任務。
•(由處理器)隱式調用中斷處理程序任務。
•對異常處理程序任務的隱式調用。
•當設置EFLAGS寄存器中的NT標誌時,返回(由IRET指令啓動)。
可以在英特爾手冊的第七章讀到TSS 3.
的ltr
不執行開關,從英特爾手冊2:
段之後選擇器加載到任務寄存器中,處理器使用段選擇器爲全局描述符表(GDT)中的TSS定位段描述符。
然後,它會從段描述符中將TSS的段限制和基地址 加載到任務寄存器中。
任務寄存器指向的任務是 標記爲忙,但不發生切換到任務。
編輯:如果CPU緩存從TSS的靜態值,我實際測試。在引導程序(附後)
- 與DPL 0兩個代碼段和圖3,兩個數據段與DPL 0和3,TSS與DPL 3呼叫柵極創建GDT
測試包括與DPL 0 - 切換到保護模式的代碼段,ESP0在TSS值設置爲V1並加載
tr
。 - 返回到帶DPL 3的代碼段,將ESP0的值更改爲v2並調用Call門。
- 檢查ESP是否爲v1 -10h或v2 -10h,分別打印1或2(或者如果由於某種原因沒有匹配,則爲0)。
在我的Haswell和Bochs上,結果是2,表示CPU在需要時從內存(層次結構)中讀取TSS。
儘管對模型的測試不能推廣到ISA,但事實並非如此。
BITS 16
xor ax, ax ;Most EFI CPS need the first instruction to be this
;But I like to have my offset to be close to 0, not 7c00h
jmp 7c0h : WORD __START__
__START__:
cli
;Set up the segments to 7c0h
mov ax, cs
mov ss, ax
xor sp, sp
mov ds, ax
;Switch to PM
lgdt [GDT]
mov eax, cr0
or ax, 1
mov cr0, eax
;Set CS
jmp CS_DPL0 : WORD __PM__ + 7c00h
__PM__:
BITS 32
;Set segments
mov ax, DS_DPL0
mov ss, ax
mov ds, ax
mov es, ax
mov esp, ESP_VALUE0
;Make a minimal TSS BEFORE loading TR
mov eax, DS_DPL0
mov DWORD [TSS_BASE + TSS_SS0], eax
mov DWORD [TSS_BASE + TSS_ESP0], ESP_VALUE1
;Load TSS in TR
mov ax, TSS_SEL
ltr ax
;Go to CPL = 3
push DWORD DS_DPL3 | RPL_3
push DWORD ESP_VALUE0
push DWORD CS_DPL3 | RPL_3
push DWORD __PMCPL3__ + 7c00h
retf
__PMCPL3__:
;UPDATE ESP IN TSS
mov ax, DS_DPL3 | RPL_3
mov ds, ax
mov DWORD [TSS_BASE + TSS_ESP0], ESP_VALUE2
;SWITCH STACK
call CALL_GATE : 0
jmp $
__PMCG__:
mov eax, esp
mov bx, 0900h | '1'
cmp eax, ESP_VALUE1 - 10h
je __write
mov bl, '2'
cmp eax, ESP_VALUE2 - 10h
je __write
mov bl, '0'
__write:
mov WORD [0b8000h + 80*5*2], bx
cli
hlt
GDT dw 37h
dd GDT + 7c00h ;GDT symbol is relative to 0 for the assembler
;We translate it to linear
dw 0
;Index 1 (Selector 08h)
;TSS starting at 8000h and with length = 64KiB
dw 0ffffh
dw TSS_BASE
dd 0000e900h
;Index 2 (Selector 10h)
;Code segment with DPL=3
dd 0000ffffh, 00cffa00h
;Index 3 (Selector 18h)
;Data segment with DPL=0
dd 0000ffffh, 00cff200h
;Index 4 (Selector 20h)
;Code segment with DPL=0
dd 0000ffffh, 00cf9a00h
;Index 5 (Selector 28h)
;Data segment with DPL=0
dd 0000ffffh, 00cf9200h
;Index 6 (Selector 30h)
;Call gate with DPL = 3 for SEL=20
dw __PMCG__ + 7c00h
dw CS_DPL0
dd 0000ec00h
;Fake partition table entry
TIMES 446-($-$$) db 0
db 80h, 0,0,0, 07h
TIMES 510-($-$$) db 0
dw 0aa55h
TSS_BASE EQU 8000h
TSS_ESP0 EQU 4
TSS_SS0 EQU 8
ESP_VALUE0 EQU 7c00h
ESP_VALUE1 EQU 6000h
ESP_VALUE2 EQU 7000h
CS_DPL0 EQU 20h
CS_DPL3 EQU 10h
DS_DPL0 EQU 28h
DS_DPL3 EQU 18h
TSS_SEL EQU 08h
CALL_GATE EQU 30h
RPL_3 EQU 03h
的TSS是隻在需要時閱讀,而且也沒有特別的TSS緩存。 (GDT中的TSS描述符與段描述符一樣被高速緩存,但不是TSS本身的內容.TSS可像其他任何內存區域一樣高速緩存在正常的L1/L2/L3內存中)。在不同情況下讀取TSS的三個不同領域。在恰當的情況發生之前,更改TSS中的任何值都不起作用。它們是:
- I/O指令(IN,INS,OUT,OUTS)在Virtual 8086模式或CPL> IOPL時執行。這會導致讀取I/O映射基址字段和它指向的I/O映射。
- 當CR4.VME爲1時,將在虛擬8086模式下執行軟件中斷(INT)。這會導致讀取I/O映射基本字段和它指向的中斷重定向位圖。
- 從較低特權級別改變爲較高特權級別(從較高編號的環到較低編號的環)導致堆疊交換機。這會根據新的權限級別讀取SS0/ESP0,SS1/ESP1,SS2/ESP2,RSP0,RSP1或RSP2字段。
- 發生任務切換,導致除了I/O映射基地址,SS0/ESP0,SS1/ESP1,SS2/ESP2和先前的任務鏈接字段外,讀取新TSS中的所有定義字段。當IRET指令導致任務切換回嵌套任務時,將讀取舊TSS的「先前任務鏈接」字段。
- 在64位模式下發生任何類型的中斷或異常,並且對應的IDT條目的IST字段不爲0.這導致TSS的相應ISTn字段被讀取。
請注意,在64位模式下,由於64位模式不支持Virtual 8086模式,因此只能出現1,3和5情況,也不支持任務切換。
LTR指令不會導致讀取任何區域的內存,除非GDT中的條目與給定的選擇器相對應,也沒有任何內部TSS高速緩存供它刷新。
我的問題特別是關於第(3)點。我想知道RSPx中的更改是否足以影響後續的授權更改,或者需要某種「刷新/重新加載」操作。你的答案意味着RSPx的變化已經足夠了,而瑪格麗特布魯姆的建議卻恰恰相反(見上面我的評論) –
@GiuseppeGuerrini我相信Ross和我說的是同樣的事情,TSS在需要時從內存層次結構中讀取。 –
- 1. 隨時修改一個字段另一個字段被修改
- 2. 修改Django ModelForms字段
- 3. 修改對象的字段
- 4. mysql修改重複字段
- 5. 字段 'Invoice_Date' 不能修改
- 6. Bash修改CSV以更改字段
- 7. 修改多個字符串字段
- 8. 修改項目 - 狀態字段
- 9. 從前端修改自定義字段
- 10. SharePoint/WSS:修改「由...創建」字段?
- 11. 修改表單輸入字段
- 12. 的Symfony驗證修改表單字段
- 13. 修改輸入字段與JSON數據
- 14. 動態修改文本字段。 Angular.js
- 15. 如何修改android.os.Build的靜態字段?
- 16. 返回修改的字段中的LinqDataSource
- 17. 克隆對象,然後修改字段
- 18. Rails:檢查修改後的字段
- 19. Wakanda:創建條目時修改字段
- 20. 修改CTE引用另一個字段?
- 21. 如何修改屬性中的字段
- 22. 保存並不更新「修改」字段
- 23. 最後修改的字段和外鍵
- 24. 段違規修改字符串
- 25. Visual Foxpro修改一般字段
- 26. 在修改時將字段添加到字段
- 27. 修改綁定字段和模板字段
- 28. 複製TableView字段的字段(爲了修改它)
- 29. 特定字段的作者 - 哪位用戶修改了字段
- 30. TPM/TSS的Linux API替代
正確,但仍有一個細節:TSS還包含用於權限級別更改的堆棧指針。它們不會立即用於上下文切換。處理器是否將它們加載到「影子副本」中的上下文切換上,然後在需要時使用這些副本? –
@GiuseppeGuerrini我相信他們在需要的時候被閱讀,手冊中的'call'指令描述和調用門描述似乎暗示了這一點。這可以很容易地通過測試,也許我可以調查。 –
@GiuseppeGuerrini我已經測試了CPU的行爲,在我的模型中,需要時會從內存中讀取值。我相信這可以推廣到任何模型。 –