当事件(即 TR 寄存器指向的那个)TSS 的字段发生变化时会发生什么?特别是,对 ESP0/RSP0 字段的更改是否会立即生效?或者处理器是否像使用段选择器一样维护 TSS 缓存,因此需要 LTR 指令来强制处理器重新加载 TSS 字段?
最佳答案
在任务切换 期间,处理器使用 TSS 存储当前上下文并加载下一个要调度的上下文 。 Software or the processor can dispatch a task for execution in one of the following ways: • A explicit call to a task with the CALL instruction. After the segment selector is loaded in the task register, the processor uses the segment selector to locate the
segment descriptor for the TSS in the global descriptor table (GDT).
在 CPU 切换到此类 TSS 之前,更改 TSS 结构不会影响任何上下文。
当 CPU 执行任务切换时
• A explicit jump to a task with the JMP instruction.
• An implicit call (by the processor) to an interrupt-handler task.
• An implicit call to an exception-handler task.
• A return (initiated with an IRET instruction) when the NT flag in the EFLAGS register is set.
您可以在英特尔手册 3 的第 7 章中阅读有关 TSS 的信息。ltr
不执行开关,来自英特尔手册 2:
It then loads the segment limit and base
address for the TSS from the segment descriptor into the task register.
The task pointed to by the task register is
marked busy, but a switch to the task does not occur.
编辑 :我实际上已经测试过 CPU 是否缓存了来自 TSS 的静态值。
测试包括一个 bootstrap (附加)tr
。
在我的 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
关于assembly - x86/x64 : modifying TSS fields,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40653480/