1. 程式人生 > >x86體系下linux中的任務切換與TSS

x86體系下linux中的任務切換與TSS

中斷 過去 c語言 line 人工 content 選擇符 以及 dff

tss的作用舉例:保存不同特權級別下任務所使用的寄存器,特別重要的是esp,因為比如中斷後,涉及特權級切換時(一個任務切換),首先要切換棧,這個棧顯然是內核棧,那麽如何找到該棧的地址呢,這需要從tss段中得到,這樣後續的執行才有所依托(在x86機器上,c語言的函數調用是通過棧實現的)。只要涉及地特權環到高特權環的任務切換,都需要找到高特權環對應的棧,因此需要esp2,esp1,esp0起碼三個esp,然而linux只使用esp0。
tss是什麽:tss是一個段,段是x86的概念,在保護模式下,段選擇符參與尋址,段選擇符在段寄存器中,而tss段則在tr寄存器中。
intel的建議:為每一個進程準備一個獨立的tss段,進程切換的時候切換tr寄存器使之指向該進程對應的tss段,然後在任務切換時(比如涉及特權級切換的中斷)使用該段保留所有的寄存器。
linux的做法:
1.linux沒有為每一個進程都準備一個tss段,而是每一個cpu使用一個tss段,tr寄存器保存該段。進程切換時,只更新唯一tss段中的esp0字段到新進程的內核棧。
2.linux的tss段中只使用esp0和iomap等字段,不用它來保存寄存器,在一個用戶進程被中斷進入ring0的時候,tss中取出esp0,然後切到esp0,其它的寄存器則保存在esp0指示的內核棧上而不保存在tss中。
3.結果,linux中每一個cpu只有一個tss段,tr寄存器永遠指向它。符合x86處理器的使用規範,但不遵循intel的建議,這樣的後果是開銷更小了,因為不必切換tr寄存器了。
linux的實現:
1.定義tss:
struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS };(arch/i386/kernel/init_task.c)
INIT_TSS定義為:
#define INIT_TSS { /
.esp0 = sizeof(init_stack) + (long)&init_stack, /
.ss0 = __KERNEL_DS, /
.esp1 = sizeof(init_tss[0]) + (long)&init_tss[0], /
.ss1 = __KERNEL_CS, /
.ldt = GDT_ENTRY_LDT, /
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET, /
.io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, /
}
2.初始化tss:
struct tss_struct * t = init_tss + cpu;
...
load_esp0(t, thread);
set_tss_desc(cpu,t);
cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
load_TR_desc();
相關函數或者宏為:
#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8))
static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
{
_set_tssldt_desc(&cpu_gdt_table[cpu][entry], (int)addr,
offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
}

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
經過上述的初始化,tr永遠指向唯一的tss段,然而tss段中的esp0以及iomap卻是不斷隨著進程切換而變化的。
3.進程切換時切換全局唯一tss段中的esp0以及iomap即可:
在__switch_to中:
struct tss_struct *tss = init_tss + cpu;
...
load_esp0(tss, next);
從而改變了tss的esp0。
此時如果進程在用戶態被中斷,機器切到ring0,從tr中取出唯一的tss段,找到它的esp0,將堆棧切過去即可,然後把所有的其它寄存器都保存在tss當前的esp0指示的內核也就是ring0的堆棧上。

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow

x86體系下linux中的任務切換與TSS