中断处理和系统调用

NUDT-OS是x64架构的,由于采用了syscall快速系统调用指令,系统调用控制流和中断控制流不同。本章分别介绍中断和系统调用的控制流和处理过程。

根据X64调用约定,可以将通用寄存器分为调用者保存和被调用者保存两个部分:

#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct CallerRegs {
    pub rax: usize,
    pub rcx: usize,
    pub rdx: usize,
    pub rsi: usize,
    pub rdi: usize,
    pub r8: usize,
    pub r9: usize,
    pub r10: usize,
    pub r11: usize,
}

#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct CalleeRegs {
    pub rsp: usize,
    pub rbx: usize,
    pub rbp: usize,
    pub r12: usize,
    pub r13: usize,
    pub r14: usize,
    pub r15: usize,
}

我们知道,CPU使用特权级机制来隔离用户态和内核态,x64中3表示用户特权级,0表示内核特权级,当发生特权级的切换时,CPU要切换栈。每个用户线程都有自己的内核栈,系统调用发生时,其切换到内核栈,将自己用户态现场保存在内核栈上,调用系统调用总控函数,完成后从内核栈恢复用户态现场,返回用户态。

用户态中断时类似系统调用处理流程。内核线程中断时不需要切换栈,在当前栈保存现场调用中断处理函数再恢复现场并返回即可。

下面两节将上面描述的控制流用代码表示。