当激活(即TR寄存器指向的那个)TSS的字段时会发生什么?特别是,对ESP0 / RSP0字段的更改是否立即生效?还是处理器像段选择器一样保留了TSS的高速缓存,因此需要一条LTR指令来强制处理器重新加载TSS字段?
最佳答案
处理器使用TSS存储当前上下文,并在任务切换期间加载要调度的下一个上下文。
在CPU切换到TSS之前,更改TSS结构不会影响任何上下文。
CPU在以下情况下执行任务切换
软件或处理器可以通过以下方式之一调度任务以执行:
•使用CALL指令显式调用任务。
•使用JMP指令显式跳转到任务。
•(由处理器)隐式调用中断处理程序任务。
•对异常处理程序任务的隐式调用。
•当设置了EFLAGS寄存器中的NT标志时,返回(由IRET指令启动)。
您可以在Intel手册3的第7章中阅读有关TSS的信息。
从Intel手册2:ltr
不执行切换:
将段选择器加载到任务寄存器中之后,处理器使用段选择器来定位
全局描述符表(GDT)中TSS的段描述符。
然后加载细分限制和基准
从段描述符到任务寄存器的TSS的地址。
任务寄存器指向的任务是
标记为忙,但是切换到任务不会发生。
编辑:我实际上已经测试过CPU是否从TSS缓存了静态值。
该测试包含一个引导程序(附带),该程序可以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