diff --git a/Cargo.lock b/Cargo.lock index d62066c44429bb77746db14b33aeddc63283bf0a..6c52bb13f89484614e10bc1ee6ab27212b711560 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,13 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "bit_field" version = "0.10.1" @@ -66,6 +74,7 @@ dependencies = [ "goblin", "linked_list_allocator 0.9.0", "log", + "memoffset", "paste", "raw-cpuid 8.1.2", "redox_syscall", @@ -113,6 +122,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memoffset" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +dependencies = [ + "autocfg", +] + [[package]] name = "paste" version = "1.0.5" diff --git a/Cargo.toml b/Cargo.toml index def826daf74260b8fdb8ba9f7dfa4a5673b59350..766f1bdc50e6b2661f1ff8dd2905fb53e2b239ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,8 @@ rustc-cfg = "0.3.0" bitflags = "1.2.1" bitfield = "0.13.2" linked_list_allocator = "0.9.0" -log = { version = "0.4" } +log = "0.4" +memoffset = { version = "0.6", features = ["unstable_const"] } redox_syscall = { path = "syscall" } slab_allocator = { path = "slab_allocator", optional = true } spin = "0.9" diff --git a/src/context/arch/x86_64.rs b/src/context/arch/x86_64.rs index ceffbb03fa83835fd0cdde037388598b929907bb..b8959658ef44c22aa8ba0bc62f269aca1dedac68 100644 --- a/src/context/arch/x86_64.rs +++ b/src/context/arch/x86_64.rs @@ -3,6 +3,8 @@ use core::sync::atomic::AtomicBool; use crate::syscall::FloatRegisters; +use memoffset::offset_of; + /// This must be used by the kernel to ensure that context switches are done atomically /// Compare and exchange this to true when beginning a context switch on any CPU /// The `Context::switch_to` function will set it back to false, allowing other CPU's to switch @@ -138,10 +140,11 @@ impl Context { /// Switch to the next context by restoring its stack and registers /// Check disassembly! -#[cold] #[inline(never)] #[naked] pub unsafe extern "C" fn switch_to(_prev: &mut Context, _next: &mut Context) { + use Context as Cx; + asm!( // As a quick reminder for those who are unfamiliar with the System V ABI (extern "C"): // @@ -151,29 +154,29 @@ pub unsafe extern "C" fn switch_to(_prev: &mut Context, _next: &mut Context) { // store them here in the first place. " // load `prev.fx` - mov rax, [rdi + 0x00] + mov rax, [rdi + {off_fx}] // save processor SSE/FPU/AVX state in `prev.fx` pointee fxsave64 [rax] // set `prev.loadable` to true - mov BYTE PTR [rdi + 0x50], {true} + mov BYTE PTR [rdi + {off_loadable}], {true} // compare `next.loadable` with true - cmp BYTE PTR [rsi + 0x50], {true} + cmp BYTE PTR [rsi + {off_loadable}], {true} je switch_to.next_is_loadable fninit jmp switch_to.after_fx switch_to.next_is_loadable: - mov rax, [rsi + 0x00] + mov rax, [rsi + {off_fx}] fxrstor64 [rax] switch_to.after_fx: // Save the current CR3, and load the next CR3 if not identical mov rcx, cr3 - mov [rdi + 0x08], rcx - mov rax, [rsi + 0x08] + mov [rdi + {off_cr3}], rcx + mov rax, [rsi + {off_cr3}] cmp rax, rcx je switch_to.same_cr3 @@ -181,34 +184,34 @@ pub unsafe extern "C" fn switch_to(_prev: &mut Context, _next: &mut Context) { switch_to.same_cr3: // Save old registers, and load new ones - mov [rdi + 0x18], rbx - mov rbx, [rsi + 0x18] + mov [rdi + {off_rbx}], rbx + mov rbx, [rsi + {off_rbx}] - mov [rdi + 0x20], r12 - mov r12, [rsi + 0x20] + mov [rdi + {off_r12}], r12 + mov r12, [rsi + {off_r12}] - mov [rdi + 0x28], r13 - mov r13, [rsi + 0x28] + mov [rdi + {off_r13}], r13 + mov r13, [rsi + {off_r13}] - mov [rdi + 0x30], r14 - mov r14, [rsi + 0x30] + mov [rdi + {off_r14}], r14 + mov r14, [rsi + {off_r14}] - mov [rdi + 0x38], r15 - mov r15, [rsi + 0x38] + mov [rdi + {off_r15}], r15 + mov r15, [rsi + {off_r15}] - mov [rdi + 0x40], rbp - mov rbp, [rsi + 0x40] + mov [rdi + {off_rbp}], rbp + mov rbp, [rsi + {off_rbp}] - mov [rdi + 0x48], rsp - mov rsp, [rsi + 0x48] + mov [rdi + {off_rsp}], rsp + mov rsp, [rsi + {off_rsp}] // push RFLAGS (can only be modified via stack) pushfq // pop RFLAGS into `self.rflags` - pop QWORD PTR [rdi + 0x10] + pop QWORD PTR [rdi + {off_rflags}] // push `next.rflags` - push QWORD PTR [rsi + 0x10] + push QWORD PTR [rsi + {off_rflags}] // pop into RFLAGS popfq @@ -221,6 +224,19 @@ pub unsafe extern "C" fn switch_to(_prev: &mut Context, _next: &mut Context) { ", + off_fx = const(offset_of!(Cx, fx)), + off_cr3 = const(offset_of!(Cx, cr3)), + off_rflags = const(offset_of!(Cx, rflags)), + off_loadable = const(offset_of!(Cx, loadable)), + + off_rbx = const(offset_of!(Cx, rbx)), + off_r12 = const(offset_of!(Cx, r12)), + off_r13 = const(offset_of!(Cx, r13)), + off_r14 = const(offset_of!(Cx, r14)), + off_r15 = const(offset_of!(Cx, r15)), + off_rbp = const(offset_of!(Cx, rbp)), + off_rsp = const(offset_of!(Cx, rsp)), + true = const(AbiCompatBool::True as u8), switch_hook = sym crate::context::switch_finish_hook, options(noreturn), diff --git a/src/lib.rs b/src/lib.rs index d0cc4fde6ff56057235dde18a0bbe79b202164de..7f54feb940e0abb6c4aeb97ee6af0b9460ea7c0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,9 @@ #![cfg_attr(target_arch = "aarch64", feature(llvm_asm))] // TODO: Rewrite using asm! #![feature(concat_idents)] #![feature(const_btree_new)] +#![feature(const_maybe_uninit_as_ptr)] +#![feature(const_ptr_offset_from)] +#![feature(const_raw_ptr_deref)] #![feature(core_intrinsics)] #![feature(global_asm)] #![feature(integer_atomics)]