- 论坛徽章:
- 0
|
根据intel的volume3的7.2.4对任务寄存器的描述:
The STR (store task register) instruction stores the visible portion of the task register
in a general-purpose register or memory. This instruction can be executed by code
running at any privilege level in order to identify the currently running task. However,
it is normally used only by operating system software.
str指令在用户态也可以使用,可是用户态和内核态读取的结果不一样,内核态得到的结果与预期一致。
用户态代码如下:- #include <stdio.h>
- #define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
- int main(void)
- {
- unsigned short tr = 0;
- store_tr(tr);
- printf("tr=0x%x\n", tr);
- return 0;
- }
复制代码 结果为:tr=0x4000
内核模块代码:- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/init.h>
- #include <linux/kernel.h> /* printk() */
- #define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
- static int
- tr_module_init(void)
- {
- unsigned short tr = 0;
- printk(KERN_WARNING "tr_module_init\n");
- store_tr(tr);
- printk(KERN_WARNING "tr=0x%x\n", tr);
- return 0;
- }
- static void
- tr_module_exit(void)
- {
- printk(KERN_WARNING "tr_module_exit\n");
- }
- MODULE_AUTHOR("nobody");
- MODULE_LICENSE("Dual BSD/GPL");
- module_init(tr_module_init);
- module_exit(tr_module_exit);
复制代码 结果为tr=0x80
我的环境是CENTOS5,内核为2.6.18. 根据arch/i386/kernel/head.S中的全局段描述符的定义:- ENTRY(cpu_gdt_table)
- .quad 0x0000000000000000 /* NULL descriptor */
- .quad 0x0000000000000000 /* 0x0b reserved */
- .quad 0x0000000000000000 /* 0x13 reserved */
- .quad 0x0000000000000000 /* 0x1b reserved */
- .quad 0x0000000000000000 /* 0x20 unused */
- .quad 0x0000000000000000 /* 0x28 unused */
- .quad 0x0000000000000000 /* 0x33 TLS entry 1 */
- .quad 0x0000000000000000 /* 0x3b TLS entry 2 */
- .quad 0x0000000000000000 /* 0x43 TLS entry 3 */
- .quad 0x0000000000000000 /* 0x4b reserved */
- .quad 0x0000000000000000 /* 0x53 reserved */
- .quad 0x0000000000000000 /* 0x5b reserved */
- .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
- .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
- .quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */
- .quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */
- .quad 0x0000000000000000 /* 0x80 TSS descriptor */
- .quad 0x0000000000000000 /* 0x88 LDT descriptor */
- /*
- * Segments used for calling PnP BIOS have byte granularity.
- * They code segments and data segments have fixed 64k limits,
- * the transfer segment sizes are set at run time.
- */
- .quad 0x00409a000000ffff /* 0x90 32-bit code */
- .quad 0x00009a000000ffff /* 0x98 16-bit code */
- .quad 0x000092000000ffff /* 0xa0 16-bit data */
- .quad 0x0000920000000000 /* 0xa8 16-bit data */
- .quad 0x0000920000000000 /* 0xb0 16-bit data */
- ...
复制代码 TSS descriptor是第16个entry,每个entry是8bytes,所以tr中的段选择子为16*8=128=0x80.
请教各位大牛为什么同样的指令在用户态得到的结果不对呢?
小弟为内核菜鸟,请各位前辈多多赐教 |
|