Set up syscall handler Note: This depends on the order of the GDT table
()
| 113 | /// |
| 114 | /// <https://nfil.dev/kernel/rust/coding/rust-kernel-to-userspace-and-back/> |
| 115 | pub fn init() { |
| 116 | let handler_addr = handle_syscall as *const () as u64; |
| 117 | unsafe { |
| 118 | // Enable System Call Extensions (SCE) to be able to use the |
| 119 | // syscall/sysret opcodes by setting the last bit in the MSR |
| 120 | // IA32_EFER |
| 121 | asm!("mov ecx, 0xC0000080", |
| 122 | "rdmsr", |
| 123 | "or eax, 1", |
| 124 | "wrmsr"); |
| 125 | |
| 126 | // clear Trap and Interrupt flag on syscall with AMD's |
| 127 | // MSR_FMASK register |
| 128 | asm!("xor rdx, rdx", |
| 129 | "mov rax, 0x300", |
| 130 | "wrmsr", |
| 131 | in("rcx") MSR_FMASK); |
| 132 | |
| 133 | // write handler address to AMD's MSR_LSTAR register |
| 134 | asm!("mov rdx, rax", |
| 135 | "shr rdx, 32", |
| 136 | "wrmsr", |
| 137 | in("rax") handler_addr, |
| 138 | in("rcx") MSR_LSTAR); |
| 139 | |
| 140 | // write segments to use on syscall/sysret to AMD'S MSR_STAR register |
| 141 | asm!( |
| 142 | "xor rax, rax", |
| 143 | "mov rdx, 0x230008", // use seg selectors 8, 16 for syscall and 43, 51 for sysret |
| 144 | "wrmsr", |
| 145 | in("rcx") MSR_STAR); |
| 146 | |
| 147 | // Write TSS address into kernel GS MSR |
| 148 | // |
| 149 | // On a syscall SWAPGS will put this into GS. The layout of |
| 150 | // the TSS is here: <https://wiki.osdev.org/Task_State_Segment> |
| 151 | // The first IST slot is at an offset of 0x24 and there are 7 |
| 152 | // available. |
| 153 | asm!( |
| 154 | // Want to move RDX into MSR but wrmsr takes EDX:EAX i.e. EDX |
| 155 | // goes to high 32 bits of MSR, and EAX goes to low order bits |
| 156 | // <https://www.felixcloutier.com/x86/wrmsr> |
| 157 | "mov eax, edx", |
| 158 | "shr rdx, 32", // Shift high bits into EDX |
| 159 | "wrmsr", |
| 160 | in("rcx") MSR_KERNEL_GS_BASE, |
| 161 | in("rdx") gdt::tss_address() |
| 162 | ); |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | /// Syscall entry point |
| 167 | /// |
nothing calls this directly
no outgoing calls
no test coverage detected