use core::arch::asm; #[repr(C)] pub struct Thread { id: usize, /// This shall be default before the program is interrupted, otherwise it will store /// CPU registers etc to be restored on context switch. ctx: ThreadContext, } /// CPU state to be saved on context switches. #[repr(C)] #[derive(Default)] pub struct ThreadContext { /// Accumulator register. rax: u64, /// Base register. rbx: u64, /// Counter register. rcx: u64, /// Data register. rdx: u64, /// Source index register. rsi: u64, /// Destination index register. rdi: u64, /// Base pointer register. rbp: u64, /// Stack pointer register. rsp: u64, /// An extended register. r8: u64, /// An extended register. r9: u64, /// An extended register. r10: u64, /// An extended register. r11: u64, /// An extended register. r12: u64, /// An extended register. r13: u64, /// An extended register. r14: u64, /// An extended register. r15: u64, /// The instruction pointer. rip: u64, /// RFLAGS register. rflags: u64, } impl ThreadContext { /// Saves the current registers of the CPU before a context switch /// to be restored later. /// /// # Notes /// /// This function should ONLY be called in interrupt handlers such /// as that of the timer. This will then save registers as required /// /// /// # Safety /// /// This function is unsafe because of the usage of inline ASM. #[inline(always)] pub unsafe fn save_registers() -> Self { let mut context = Self::default(); unsafe { asm!( "mov {0}, rax", "mov {1}, rbx", "mov {2}, rcx", "mov {3}, rdx", "mov {4}, rsi", "mov {5}, rdi", "mov {6}, rbp", "mov {7}, rsp", "mov {8}, r8", "mov {9}, r9", "mov {10}, r10", "mov {11}, r11", "mov {12}, r12", "mov {13}, r13", "mov {14}, r14", "mov {15}, r15", "lea {16}, [rip]", "pushf", "pop {17}", out(reg) context.rax, out(reg) context.rbx, out(reg) context.rcx, out(reg) context.rdx, out(reg) context.rsi, out(reg) context.rdi, out(reg) context.rbp, out(reg) context.rsp, out(reg) context.r8, out(reg) context.r9, out(reg) context.r10, out(reg) context.r11, out(reg) context.r12, out(reg) context.r13, out(reg) context.r14, out(reg) context.r15, out(reg) context.rip, out(reg) context.rflags, ); } context } }