引言

系统调用是用户空间程序请求内核服务的唯一受控入口。每次read()、write()、open()的背后,都涉及一次完整的特权级切换——从Ring 3用户态陷入Ring 0内核态,执行完毕后再安全返回。本文从汇编指令层面,逐层剖析这条通路上每一个关键节点。

1. 用户态发起:syscall指令的微观操作

在x86_64架构上,syscall指令替代了传统的int 0x80软件中断。它的执行动作如下(Intel手册定义):

; 用户态执行 syscall 前:
; rax = 系统调用号 (如 __NR_write = 1)
; rdi = 第1参数 (fd)
; rsi = 第2参数 (buf)
; rdx = 第3参数 (count)

syscall          ; 原子性地完成:
                 ; 1. RCX = RIP (返回地址)
                 ; 2. R11 = RFLAGS (标志寄存器)
                 ; 3. RIP = IA32_LSTAR (内核入口)
                 ; 4. CS = IA32_STAR[47:32]
                 ; 5. SS  = IA32_STAR[47:32]   8

syscall不会保存栈指针(RSP),这是与int指令的关键区别——内核入口必须立即切换栈。

2. MSR寄存器:内核配置的秘密

系统调用的路由信息存储在MSR(Model Specific Register)中,内核在启动时通过wrmsr指令配置:

// arch/x86/kernel/cpu/common.c
void syscall_init(void)
{
    wrmsr(MSR_LSTAR, (unsigned long)entry_SYSCALL_64, 0);    // 入口点
    wrmsr(MSR_STAR,  segments, 0);                            // 段选择子
    wrmsr(MSR_FMASK, TF_WORK_SYSCALL|MASK, 0);                // 入口屏蔽的RFLAGS位
    
    // MSR_GS_BASE 指向 per-CPU 的 pcpu_hot 结构
    wrmsrl(MSR_GS_BASE, (unsigned long)                        
                    
点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部