diff --git a/Cargo.toml b/Cargo.toml index 005f893..f656dd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,11 @@ edition = "2018" #[profile.release] #panic = "abort" +[profile.release] +debug = true + [package.metadata.bootimage] +run-command = ["qemu-system-x86_64", "-drive", "format=raw,file={}", "-S", "-gdb", "tcp::9009"] test-args = ["-device", "isa-debug-exit,iobase=0xf4,iosize=0x04", "-serial", "stdio", "-display", "none"] test-success-exit-code = 33 # (0x10 << 1) | 1 diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..dd2e545 --- /dev/null +++ b/build.rs @@ -0,0 +1,13 @@ +use std::env; + +fn main() { + let mut input = std::fs::read_to_string("src/setup_process_stack.s").unwrap(); + let replacement= match env::var("OPT_LEVEL").unwrap().as_ref() { + "0" => "0x40", // Debug build + "3" => "0x90", // Release build + opt_lvl => panic!("Wtf is this opt level: {}", opt_lvl), + }; + + std::fs::write("src/setup_process_stack.s.out", + input.replace("", replacement)).unwrap(); +} \ No newline at end of file diff --git a/src/context_switch.rs b/src/context_switch.rs new file mode 100644 index 0000000..b441ded --- /dev/null +++ b/src/context_switch.rs @@ -0,0 +1,46 @@ +use crate::kernel::Pid; +use crate::println; +use crate::registers::Registers; +use crate::kernel::Process; + +// pub fn save_state(old_process: &mut Process) { +// +// } +// +// pub fn context_switch(new_process: &mut Process, old_pid: Option<&mut Process>, old_registers: Option) { +// if let Some(old_pid) = old_pid { +// let rax: u64 = 0; +// let rcx: u64 = 0; +// let rdx: u64 = 0; +// let rbx: u64 = 0; +// let rsp: u64 = 0; +// let rbp: u64 = 0; +// let rsi: u64 = 0; +// let rdi: u64 = 0; +// +// unsafe { +// llvm_asm!("mov %rdi, $0" : "=r" (rdi)); +// llvm_asm!("mov %rax, $0" : "=r" (rax)); +// llvm_asm!("mov %rdx, $0" : "=r" (rdx)); +// llvm_asm!("mov %rcx, $0" : "=r" (rcx)); +// llvm_asm!("mov %rsi, $0" : "=r" (rsi)); +// llvm_asm!("mov %rsp, $0" : "=r" (rsp)); +// llvm_asm!("mov %rbx, $0" : "=r" (rbx)); +// llvm_asm!("mov %rbp, $0" : "=r" (rbp)); +// } +// +// let regs = Registers { +// rax, +// rcx, +// rdx, +// rbx, +// rsp, +// rbp, +// rsi, +// rdi +// }; +// +// println!("DOES THIS WORK: {:?}", regs); +// old_pid.set_regs(regs); +// } +// } \ No newline at end of file diff --git a/src/helper.rs b/src/helper.rs new file mode 100644 index 0000000..8f41b23 --- /dev/null +++ b/src/helper.rs @@ -0,0 +1,13 @@ +use crate::println; + +#[inline(always)] +pub fn print_stack_pointer() { + let other: usize; + unsafe { + llvm_asm!( " + mov %rsp, $0 + ": "={rsp}"(other): : + : "volatile"); + } + println!("{:x}", other); +} diff --git a/src/interrupts/hardware.rs b/src/interrupts/hardware.rs index b040f77..fbe0d2b 100644 --- a/src/interrupts/hardware.rs +++ b/src/interrupts/hardware.rs @@ -2,9 +2,11 @@ use pic8259_simple::ChainedPics; use x86_64::structures::idt::InterruptStackFrame; use lazy_static::lazy_static; use crate::{print, println}; +use core::intrinsics::breakpoint; pub const PIC_1_OFFSET: u8 = 32; pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; +pub const SYSCALL_IDX: u8 = 0x80; pub static PICS: spin::Mutex = // Remap PIC ports via offset spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); @@ -12,17 +14,56 @@ pub static PICS: spin::Mutex = // Remap PIC ports via offset #[derive(Debug, Clone, Copy)] #[repr(u8)] pub enum InterruptIndex { + Syscall = SYSCALL_IDX, Timer = PIC_1_OFFSET, Keyboard, // +1 } -pub extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut InterruptStackFrame) { - print!("."); +#[inline(never)] +pub extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut InterruptStackFrame) { // NOTE: Please don't touch, everything relies on the fact that the compiler only uses 0x40 of the stack when executing this function + let stack_pointer: usize; + let return_pointer; + unsafe { + llvm_asm!( " + mov %rsp, $0 + ": "=r"(stack_pointer): : : "volatile"); + + return_pointer = crate::scheduling::check_schedule(stack_pointer); + // x86_64::registers::control::Cr3::read() + llvm_asm!( " + mov $0, %rsp + ": : "r" (return_pointer): "rsp" : "volatile"); + } unsafe { PICS.lock().notify_end_of_interrupt(InterruptIndex::Timer as u8); } + unsafe { + llvm_asm!( " + nop + ": : : "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rbp" : "volatile"); + } } +// #[inline(never)] +// pub extern "C" fn random_thing(_stack_frame: usize) { +// let stack_pointer: usize; +// unsafe { +// llvm_asm!( " +// mov %rsp, $0 +// ": "={rsp}"(stack_pointer): : +// "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" : +// "volatile"); +// +// let return_pointer = crate::scheduling::check_schedule(stack_pointer); +// +// llvm_asm!( " +// mov $0, %rsp +// ": : "{rsp}" (return_pointer): +// "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" : +// "volatile"); +// } +// } + pub extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: &mut InterruptStackFrame) { use x86_64::instructions::port::Port; use spin::{Mutex, MutexGuard}; diff --git a/src/interrupts/mod.rs b/src/interrupts/mod.rs index 575c982..238d4d8 100644 --- a/src/interrupts/mod.rs +++ b/src/interrupts/mod.rs @@ -1,9 +1,9 @@ -use x86_64::structures::idt::InterruptDescriptorTable; +use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; use hardware::InterruptIndex; use lazy_static::lazy_static; mod cpu; -mod hardware; +pub mod hardware; lazy_static! { static ref IDT: InterruptDescriptorTable = create_idt(); @@ -15,6 +15,10 @@ pub fn interrupt_init() { x86_64::instructions::interrupts::enable(); } +pub extern "x86-interrupt" fn syscall(_stack_frame: &mut InterruptStackFrame) { + println!("yay a syscall happened!"); +} + fn create_idt() -> InterruptDescriptorTable { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(cpu::breakpoint_handler); @@ -25,5 +29,6 @@ fn create_idt() -> InterruptDescriptorTable { } idt[InterruptIndex::Timer as u8 as usize].set_handler_fn(hardware::timer_interrupt_handler); idt[InterruptIndex::Keyboard as u8 as usize].set_handler_fn(hardware::keyboard_interrupt_handler); + idt[InterruptIndex::Syscall as u8 as usize].set_handler_fn(syscall); idt } \ No newline at end of file diff --git a/src/kernel.rs b/src/kernel.rs index 86bf175..9497420 100644 --- a/src/kernel.rs +++ b/src/kernel.rs @@ -1,56 +1,27 @@ use crate::interrupts::interrupt_init; use crate::gdt::gdt_init; -use crate::{println, print}; +use crate::{println, print, helper}; use crate::special_collections::{IncrementingPool, DynamicBitmap}; use x86_64::instructions::interrupts; use lazy_static::lazy_static; use spin::Mutex; use alloc::vec::Vec; +use alloc::vec; +use x86_64::{PhysAddr, VirtAddr}; +use x86_64::structures::idt::InterruptStackFrame; +use crate::memory::{StackBounds, alloc_stack}; +use volatile::Volatile; +use crate::kernel::SchedulingLevel::Periodic; +use x86_64::instructions::interrupts::without_interrupts; +use core::sync::atomic::AtomicUsize; +use crate::processes::process::SchedulingLevel::Periodic; -type Name = u64; -type Pid = u64; - -#[derive(Clone, Copy, Debug)] -struct Registers {} - -#[derive(Clone, Copy, Debug)] -struct Process { - pid: u64, - regs: Option, - level: SchedulingLevel, - name: Name, - arg: i32, -} - -impl Process { - // TODO: Implement error type - fn new(level: SchedulingLevel, name: Name, arg: i32) -> Result { - match level { - SchedulingLevel::Device => {}, - SchedulingLevel::Periodic => { - if !NAME_REGISTRY.lock().set_bit(name as usize) { - // Name already taken - return Err(()) - } - }, - SchedulingLevel::Sporadic => {}, - } - let pid = PID_POOL.lock().get_free_elem(); - - Ok(Process { - pid, - regs: None, - level, - name, - arg, - }) - } -} +pub static CURRENT_PROCESS: AtomicUsize = AtomicUsize::new(0); lazy_static! { - static ref PROCESSES: Mutex> = Mutex::new(Vec::new()); - static ref PID_POOL: Mutex = Mutex::new(IncrementingPool::new(2)); + pub static ref PROCESSES: Mutex>> = Mutex::new(vec![None; 2]); + static ref PID_POOL: Mutex = Mutex::new(IncrementingPool::new(1)); static ref NAME_REGISTRY: Mutex = Mutex::new(DynamicBitmap::new()); } @@ -59,20 +30,45 @@ pub fn os_init() { gdt_init(); } -pub fn os_start() {} +#[inline(never)] +pub fn os_start() { + // crate::interrupts::hardware::random_thing(123); + // crate::context_switch::context_switch(123, Some(123)); + os_create(123, Periodic, 333, *&test_app); + tester(1); +} + +extern "C" fn os_terminate() -> ! { + println!("We out of there!"); + loop {} +} -#[derive(Copy, Clone, Debug)] -enum SchedulingLevel { - Device = 0, - Periodic = 1, - Sporadic = 2, +#[inline(never)] +fn tester(item: usize) { + let other: usize; + helper::print_stack_pointer(); + loop {} } -fn os_create ()>(f: F, arg: i32, level: SchedulingLevel, name: i32) -> Result{ - // Process::new(level, name, arg); +fn os_create(arg: i32, level: SchedulingLevel, name: Name, f: extern "C" fn()) -> Result { + let process = Process::new(level, name, arg, f)?; + + Ok(without_interrupts(|| { + let mut lock = PROCESSES.lock(); + + if process.get_idx() >= lock.len() { + lock.resize(process.get_idx() + 1, None); + } + let out_pid = process.pid; + + assert!(lock[process.get_idx()].is_none(), "PID of new process is not empty"); + lock[process.get_idx()] = Some(process); + out_pid + })) +} - // Process::new() - unimplemented!() +extern "C" fn test_app() { + println!("YOLO!!"); } pub fn os_abort() { diff --git a/src/main.rs b/src/main.rs index 97148f3..e511a4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,9 @@ #![no_main] #![no_std] +#![feature(core_intrinsics)] +#![feature(global_asm)] +#![feature(llvm_asm)] #![feature(const_in_array_repeat_expressions)] #![feature(const_fn)] #![feature(abi_x86_interrupt)] @@ -18,22 +21,35 @@ mod tests; mod serial; mod interrupts; mod gdt; +mod context_switch; +mod helper; + +// Logic mod kernel; -// mod static_collections; +mod processes; + +// Collections mod special_collections; +use x86_64::VirtAddr; +use lazy_static::lazy_static; +use spin::Mutex; +use crate::memory::paging::BootInfoFrameAllocator; + +static FRAME_ALLOCATOR: Mutex = Mutex::new(BootInfoFrameAllocator::new()); +static TEMP_MAPPER: Mutex> = Mutex::new(None); + #[no_mangle] pub extern "C" fn _start(boot_info: &'static bootloader::BootInfo) -> ! { let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); let mut mapper = unsafe { memory::paging::init(phys_mem_offset) }; - let mut frame_allocator = unsafe { - BootInfoFrameAllocator::init(&boot_info.memory_map) - }; - - memory::allocator::init_heap(&mut mapper, &mut frame_allocator) + unsafe { FRAME_ALLOCATOR.lock().init(&boot_info.memory_map) }; + + memory::allocator::init_heap(&mut mapper, &mut *FRAME_ALLOCATOR.lock()) .expect("Failed to init heap"); - + *TEMP_MAPPER.lock() = Some(mapper); + kernel::os_init(); #[cfg(test)] @@ -42,14 +58,11 @@ pub extern "C" fn _start(boot_info: &'static bootloader::BootInfo) -> ! { kernel::os_start(); println!("Didn't quite crash"); - loop { - x86_64::instructions::hlt(); - } + loop {} } use core::panic::PanicInfo; -use x86_64::VirtAddr; -use crate::memory::paging::BootInfoFrameAllocator; +use x86_64::structures::paging::OffsetPageTable; /// This function is called on panic. diff --git a/src/memory/allocator.rs b/src/memory/allocator.rs index 5525b64..2c6f2c6 100644 --- a/src/memory/allocator.rs +++ b/src/memory/allocator.rs @@ -5,7 +5,7 @@ use x86_64::VirtAddr; // These are virtual addresses pub const HEAP_START: usize = 0x_1313_1313_0000; -pub const HEAP_SIZE: usize = 1024 * 1024; // 100 KiB +pub const HEAP_SIZE: usize = 64 * 1024; // 64 KiB pub fn init_heap(mapper: &mut impl Mapper, frame_allocator: &mut impl FrameAllocator) -> Result<(), MapToError> { @@ -15,6 +15,7 @@ pub fn init_heap(mapper: &mut impl Mapper, frame_allocator: &mut impl let heap_end = heap_start + HEAP_SIZE - 1u64; let heap_start_page = Page::containing_address(heap_start); let heap_end_page = Page::containing_address(heap_end); + Page::range_inclusive(heap_start_page, heap_end_page) }; diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 5dc9aa3..c5430e2 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,2 +1,60 @@ +use x86_64::VirtAddr; +use x86_64::structures::paging::{Page, Size4KiB, mapper, FrameAllocator, Mapper}; + pub mod paging; -pub mod allocator; \ No newline at end of file +pub mod allocator; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct StackBounds { + start: VirtAddr, + end: VirtAddr, +} + +impl StackBounds { + pub fn start(&self) -> VirtAddr { + self.start + } + + pub fn end(&self) -> VirtAddr { + self.end + } +} + +fn reserve_stack_memory(size_in_pages: u64) -> Page { + use core::sync::atomic::{AtomicU64, Ordering}; + static STACK_ALLOC_NEXT: AtomicU64 = AtomicU64::new(0x_5555_5555_0000); + let start_addr = VirtAddr::new(STACK_ALLOC_NEXT.fetch_add( + size_in_pages * Page::::SIZE, + Ordering::Relaxed, + )); + Page::from_start_address(start_addr) + .expect("`STACK_ALLOC_NEXT` not page aligned") +} + + +pub fn alloc_stack( + size_in_pages: u64, + mapper: &mut impl Mapper, + frame_allocator: &mut impl FrameAllocator, +) -> Result> { + use x86_64::structures::paging::PageTableFlags as Flags; + + let guard_page = reserve_stack_memory(size_in_pages + 1); + let stack_start = guard_page + 1; + let stack_end = stack_start + size_in_pages; + + for page in Page::range(stack_start, stack_end) { + let frame = frame_allocator + .allocate_frame() + .ok_or(mapper::MapToError::FrameAllocationFailed)?; + let flags = Flags::PRESENT | Flags::WRITABLE; + unsafe { + mapper.map_to(page, frame, flags, frame_allocator)?.flush(); + } + } + + Ok(StackBounds { + start: stack_start.start_address(), + end: stack_end.start_address(), + }) +} \ No newline at end of file diff --git a/src/memory/paging.rs b/src/memory/paging.rs index 492f38a..54b6d2a 100644 --- a/src/memory/paging.rs +++ b/src/memory/paging.rs @@ -12,27 +12,32 @@ unsafe impl FrameAllocator for EmptyFrameAllocator { /// A FrameAllocator that returns usable frames from the bootloader's memory map. pub struct BootInfoFrameAllocator { - memory_map: &'static MemoryMap, + memory_map: Option<&'static MemoryMap>, next: usize, } impl BootInfoFrameAllocator { + + pub const fn new() -> Self { + BootInfoFrameAllocator { + next: 0, + memory_map: None + } + } + /// Create a FrameAllocator from the passed memory map. /// /// This function is unsafe because the caller must guarantee that the passed /// memory map is valid. The main requirement is that all frames that are marked /// as `USABLE` in it are really unused. - pub unsafe fn init(memory_map: &'static MemoryMap) -> Self { - BootInfoFrameAllocator { - memory_map, - next: 0, - } + pub unsafe fn init(&mut self, memory_map: &'static MemoryMap) { + self.memory_map = Some(memory_map); } /// Returns an iterator over the usable frames specified in the memory map. fn usable_frames(&self) -> impl Iterator { let addr_ranges = - self.memory_map.iter() + self.memory_map.unwrap().iter() .filter(|r| r.region_type == MemoryRegionType::Usable) .map(|r| r.range.start_addr()..r.range.end_addr()); diff --git a/src/processes/mod.rs b/src/processes/mod.rs new file mode 100644 index 0000000..e94576b --- /dev/null +++ b/src/processes/mod.rs @@ -0,0 +1,33 @@ +pub mod scheduling; +pub mod process; + +pub use process::Process; +use spin::Mutex; +use alloc::vec::Vec; +use crate::processes::scheduling::Scheduler; +use crate::special_collections::{IncrementingPool, DynamicBitmap}; + +pub type Name = u64; +pub type Pid = u64; + +pub struct ProcessesManager { + processes_list: Mutex>>, + scheduler: Scheduler, + pid_pool: Mutex, + name_registry: Mutex, +} + +impl ProcessesManager { + pub fn new() -> Self { + Self { + processes_list: Mutex::new(vec![None; 2]), + scheduler: Scheduler::new(vec![(1, 10), (2, 5), (3, 5), (1, 5), (3 , 10), (4, 5)]), + pid_pool: Mutex::new(IncrementingPool::new(1)), + name_registry: Mutex::new(DynamicBitmap::new()), + } + } + + pub fn create_new_process() { + + } +} \ No newline at end of file diff --git a/src/processes/process.rs b/src/processes/process.rs new file mode 100644 index 0000000..0d82981 --- /dev/null +++ b/src/processes/process.rs @@ -0,0 +1,95 @@ +use x86_64::VirtAddr; +use super::Name; +use crate::memory::{alloc_stack, StackBounds}; +use crate::processes::Pid; + +global_asm!(include_str!("setup_process_stack.s.out")); + +extern "C" { + fn asm_fake_register(new_stack_addr: usize, terminate_func_addr: usize, program_start_addr: usize) -> usize; +} + +#[derive(Copy, Clone, Debug)] +pub enum SchedulingLevel { + Device = 0, + Periodic = 1, + Sporadic = 2, +} + +#[derive(Copy, Clone, Debug)] +pub enum ProcessStatus { + Yielded = 0, + Running = 1, + Scheduled = 2, +} + + +#[derive(Clone, Copy, Debug)] +pub struct Process { + pid: Pid, + // paging_4_address: PhysAddr, + level: SchedulingLevel, + status: ProcessStatus, + name: Name, + // TODO: Replace this with pages + stack_bounds: StackBounds, + stack_pointer: VirtAddr, + arg: i32, +} + +impl Process { + // TODO: Implement error type + pub fn new(pid: Pid, level: SchedulingLevel, name: Name, arg: i32, program_start: extern "C" fn()) -> Result { + match level { + SchedulingLevel::Device => {} + SchedulingLevel::Periodic => { + if !NAME_REGISTRY.lock().set_bit(name as usize) { + // Name already taken + return Err(()); + } + } + SchedulingLevel::Sporadic => {} + } + + let stack_bounds = alloc_stack(32, &mut *crate::TEMP_MAPPER.lock().as_mut().unwrap(), + &mut *crate::FRAME_ALLOCATOR.lock()).unwrap(); + + let terminate_ret_addr = os_terminate as *const () as usize; + stack_bounds.end(); + println!("Function address: {:x}", program_start as *const () as usize); + let fake_int_sp = x86_64::instructions::interrupts::without_interrupts(|| { + unsafe { + asm_fake_register(stack_bounds.end().as_u64() as usize, + terminate_ret_addr, + program_start as *const () as usize) + } + }); + + println!("{:x}", fake_int_sp); + Ok(Process { + pid, + level, + status: ProcessStatus::Scheduled, + stack_bounds, + stack_pointer: VirtAddr::new(fake_int_sp as u64), + name, + arg, + }) + } + + fn get_idx(&self) -> usize { + self.pid as usize - 1 + } + + pub fn get_stack_pos(&self) -> VirtAddr { + self.stack_pointer + } + + pub fn set_regs(&mut self, new_regs: Registers) { + self.regs = Some(new_regs); + } + + pub fn set_process_status(&mut self, new_status: ProcessStatus) { + + } +} \ No newline at end of file diff --git a/src/processes/scheduling.rs b/src/processes/scheduling.rs new file mode 100644 index 0000000..c965728 --- /dev/null +++ b/src/processes/scheduling.rs @@ -0,0 +1,60 @@ +use crate::println; +use crate::kernel::{PROCESSES, CURRENT_PROCESS}; +use core::sync::atomic::Ordering; +use x86_64::instructions::interrupts::without_interrupts; +use alloc::vec::Vec; +use lazy_static::lazy_static; +use spin::Mutex; + +lazy_static! { + static ref SCHEDULER: Mutex = Mutex::new(Scheduler::new()); +} + +pub struct Scheduler { + time: usize, + /// (Index, Time) + periodic_order: Vec<(usize, usize)>, +} + +impl Scheduler { + + pub fn new(periodic_order: Vec<(usize, usize)>) -> Self { + Scheduler { + time: 0, + periodic_order + } + } + + pub fn next_tick(&mut self) { + self.time += 1; + self.schedule_new_process(); + } + + pub fn yielded(&mut self) { + PROCESSES.lock()[CURRENT_PROCESS.load(Ordering::Relaxed)].as_ref().unwrap() + .set_process_status(ProcessStatus::Yielded); + self.schedule_new_process(); + } + + fn schedule_new_process(&mut self) { + + } +} + + +pub fn check_schedule(stack_pointer: usize) -> usize { + println!("{:x}", stack_pointer); + if CURRENT_PROCESS.load(Ordering::Relaxed) == 0 { + let p_lock = PROCESSES.lock(); + for item in &*p_lock { + if let Some(item) = item.as_ref() { + return item.get_stack_pos().as_u64() as usize; + } + } + } else { + + } + // println!("{:x}", stack_pointer); + + stack_pointer +} \ No newline at end of file diff --git a/src/setup_process_stack.s b/src/setup_process_stack.s new file mode 100644 index 0000000..f7c4cfc --- /dev/null +++ b/src/setup_process_stack.s @@ -0,0 +1,43 @@ +.intel_syntax noprefix + +.global asm_fake_register + +//; asm_fake_register(new_stack_pointer: usize, terminate_func_addr: usize, program_start_addr: usize) -> usize +asm_fake_register: + mov r8, rsp // Store stack pointer in a unused scratch register + mov rsp, rdi // Set our stack pointer to the new stack pointer passed in the first argument + + push rsi // Push os_terminate address + mov rcx, rsp // Update rcx to contain the stack pointer before our fake "interrupt" + mov rax, 0 //; Apparently you should use the XOR method + push rax // Push ss (it's just zero) + push rcx // Push the stack pointer just before our fake "interrupt" + pushfq //; push RFLAGS register to stack TODO: (Currently this is "fine" (it really isn't, since all the other flags will be wrong) since everything is in ring 0, but we need to customize this once we have rings) + mov rcx, cs // Move cs to temporary register to be pushed + push rcx // Push code segment + push rdx // Push instruction pointer + + // Use the more efficient XOR method to zero out registers + + // Push a bunch of zeros for all the registers + push rdi //; rbp // Push the input stack start address to the base stack pointer + push rax //; r15 + push rax //; r14 + push rax //; r13 + push rax //; r12 + push rax //; r11 + push rax //; r10 + push rax //; r9 + push rax //; r8 + push rax //; rdi + push rax //; rsi + push rax //; rdx + push rax //; rcx + push rax //; rbx + push rax //; rax + + sub rsp, // Change based on build mode in build.rs (This is so stupid, we need a better way of doing this) + mov rax, rsp // Save new stack pointer in rax, the C return register + mov rsp, r8 // Get back our original stack pointer + + ret \ No newline at end of file