1. 程式人生 > >作業系統分析——_TSS(n)巨集解析

作業系統分析——_TSS(n)巨集解析

在linux核心程式碼中,會遇到如下的巨集定義:

#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) 
#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
#define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n)))
#define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))

本人之前對_TSS(n)的理解是: n<<4表示每個任務都由tss,ldt構成;而每個tss和ldt都是一個描述符,各8個位元組。 FIRST_TSS_ENTRY <<3 是因為前面有4個gdt表項,共4*8=32個位元組 以為計算出來的值是基於gdt的偏移。 但實際上應該這麼理解是有錯誤的,這是因為ltr 指令接受的輸入是一個一個段選擇子。 我們應該從段選擇子的角度來看這個_TSS(n)和_LDT(n)的值。

LTR:

Load Task Register
Opcode	Mnemonic	Description
0F 00 /3	LTR r/m16	Load r/m16 into task register.
Description
Loads the source operand into the segment selector field of the task register. The source operand (a general-purpose register or a memory location) contains a segment selector that points to a task state segment (TSS). 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). 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.

The LTR instruction is provided for use in operating-system software; it should not be used in application programs. It can only be executed in protected mode when the CPL is 0. It is commonly used in initialization code to establish the first task to be executed.

The operand-size attribute has no effect on this instruction.
Loads the source operand into the segment selector field of the task register. The source operand (a general-purpose register or a memory location) contains a segment selector that points to a task state segment (TSS). 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). 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.

The LTR instruction is provided for use in operating-system software; it should not be used in application programs. It can only be executed in protected mode when the CPL is 0. It is commonly used in initialization code to establish the first task to be executed.

The operand-size attribute has no effect on this instruction.

如果這麼理解的話,FIRST_TSS_ENTRY<<3表示左移3位,把最後的3個0補出來,3個0表示 特權0,全域性描述表。 FIRST_TSS_ENTRY第4項開始+n<<4,每個程序佔用兩個段描述符,所以n先左移3位 在左移1位,一起拼接成在gdt表中的第幾項這個資訊。