kernel - 当 RCX 保存正确的返回地址时,为什么 SYSRET 返回地址 0?

标签 kernel system-calls

我用我的爱好 x86_64 UEFI 内核达到了用户代码调用系统代码的目的,但它会在 0x1B:0x0(0x1B 是用户模式代码段选择器)处生成错误代码 0 的一般保护错误。单步执行,我意识到 SYSRET 不会返回到 RCX 中保存的地址,而是返回到零。我使用带有和不带有 KVM 的 qemu-system-x86_64 进行调试。附上两张关于该现象的截图。谁能解释一下,并告诉我我做错了什么?

MSR 0xC0000080 = 0x0000000000000501
MSR 0xC0000081 = 0x001B00083D906D79
MSR 0xC0000082 = 0x000000003D906D79
MSR 0xC0000083 = 0x000000003D906D79
MSR 0xC0000084 = 0x0000000000000300

使用 cli 和本地 APIC 的条目禁用中断。

Before the deadly step

After

GDT:
{ 0, 0, 0, 0x9A, 0x20, 0 }; // 0x08 ring 0 code
{ 0, 0, 0, 0x92, 0x00, 0 }; // 0x10 ring 0 data
{ 0, 0, 0, 0xFA, 0x20, 0 }; // 0x1B ring 3 code
{ 0, 0, 0, 0xF2, 0x00, 0 }; // 0x23 ring 3 data
{ 0, 0, 0, 0xFA, 0x20, 0 }; // 0x2B ring 3 code
{ 0, 0, 0, 0xF2, 0x00, 0 }; // 0x33 ring 3 data

typedef struct PACKED ENTRY
{
    U16 limit_0_15;
    U16 base_0_15;
    U8  base_16_23;
    U8  access;
    U8  granularity;
    U8  base_24_31;
} ENTRY, *PENTRY;

编辑:再次阅读说明手册后,我注意到在长模式下返回 CS 将是 (STAR.SYSRET_CS + 16) | 3 所以我复制了用户模式段描述符只是为了确定,但结果是一样的。

最佳答案

在 SYSEXIT 上,RCX == 返回 RSP 和 RDX == 返回 RIP。请参阅英特尔指令集引用。

关于kernel - 当 RCX 保存正确的返回地址时,为什么 SYSRET 返回地址 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46456616/

相关文章:

windows - 具有 NDIS 的用户模式驱动程序

c - load_seg_reg(ES,0xfffc): invalid segment when trying to run kernel code from boot sector

linux - memcachedslab和linux内核slab之间有什么关系

assembly - 如何使用汇编 (NASM) 从 CD-ROM 将内核加载到内存中

linux - 在基于 SMP 的 linux 系统中访问另一个 cpu 的 "current_task"指针

linux - 在运行时获取 Linux 内核函数的结束地址

linux - Supervisord 中的命令失败 'stdout_log and system command'

c 系统调用 connect() 在客户端挂起(网络编程)

c - <linux/unistd.h> 中的 _syscallN 宏在哪里?

c - 利用 C 中的 system() 调用