diff --git a/api/src/info.rs b/api/src/info.rs index cdb48722..965fcf40 100644 --- a/api/src/info.rs +++ b/api/src/info.rs @@ -56,6 +56,12 @@ pub struct BootInfo { pub ramdisk_addr: Optional, /// Ramdisk image size, set to 0 if addr is None pub ramdisk_len: u64, + /// Physical address of the kernel ELF in memory. + pub kernel_addr: u64, + /// Size of the kernel ELF in memory. + pub kernel_len: u64, + /// Virtual address of the loaded kernel image. + pub kernel_image_offset: u64, #[doc(hidden)] pub _test_sentinel: u64, @@ -76,6 +82,9 @@ impl BootInfo { tls_template: Optional::None, ramdisk_addr: Optional::None, ramdisk_len: 0, + kernel_addr: 0, + kernel_len: 0, + kernel_image_offset: 0, _test_sentinel: 0, } } diff --git a/common/src/legacy_memory_region.rs b/common/src/legacy_memory_region.rs index bf804e9c..6f4b1741 100644 --- a/common/src/legacy_memory_region.rs +++ b/common/src/legacy_memory_region.rs @@ -110,10 +110,11 @@ where pub fn construct_memory_map( self, regions: &mut [MaybeUninit], - kernel_slice_start: u64, + kernel_slice_start: PhysAddr, kernel_slice_len: u64, ) -> &mut [MemoryRegion] { let mut next_index = 0; + let kernel_slice_start = kernel_slice_start.as_u64(); for descriptor in self.original { let mut start = descriptor.start(); diff --git a/common/src/lib.rs b/common/src/lib.rs index ecd0d9cc..3c407644 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -39,7 +39,7 @@ pub mod serial; const PAGE_SIZE: u64 = 4096; -/// Initialize a text-based logger using the given pixel-based framebuffer as output. +/// Initialize a text-based logger using the given pixel-based framebuffer as output. pub fn init_logger( framebuffer: &'static mut [u8], info: FrameBufferInfo, @@ -195,10 +195,10 @@ where enable_write_protect_bit(); let config = kernel.config; - let kernel_slice_start = kernel.start_address as u64; + let kernel_slice_start = PhysAddr::new(kernel.start_address as _); let kernel_slice_len = u64::try_from(kernel.len).unwrap(); - let (entry_point, tls_template) = load_kernel::load_kernel( + let (kernel_image_offset, entry_point, tls_template) = load_kernel::load_kernel( kernel, kernel_page_table, frame_allocator, @@ -402,6 +402,8 @@ where kernel_slice_start, kernel_slice_len, + kernel_image_offset, + ramdisk_slice_start, ramdisk_slice_len, } @@ -426,9 +428,11 @@ pub struct Mappings { pub tls_template: Option, /// Start address of the kernel slice allocation in memory. - pub kernel_slice_start: u64, + pub kernel_slice_start: PhysAddr, /// Size of the kernel slice allocation in memory. pub kernel_slice_len: u64, + /// Relocation offset of the kernel image in virtual memory. + pub kernel_image_offset: VirtAddr, pub ramdisk_slice_start: Option, pub ramdisk_slice_len: u64, } @@ -543,6 +547,9 @@ where .map(|addr| addr.as_u64()) .into(); info.ramdisk_len = mappings.ramdisk_slice_len; + info.kernel_addr = mappings.kernel_slice_start.as_u64(); + info.kernel_len = mappings.kernel_slice_len as _; + info.kernel_image_offset = mappings.kernel_image_offset.as_u64(); info._test_sentinel = boot_config._test_sentinel; info }); @@ -587,7 +594,7 @@ pub struct PageTables { /// /// Must be the page table that the `kernel` field of this struct refers to. /// - /// This frame is loaded into the `CR3` register on the final context switch to the kernel. + /// This frame is loaded into the `CR3` register on the final context switch to the kernel. pub kernel_level_4_frame: PhysFrame, } @@ -595,7 +602,13 @@ pub struct PageTables { unsafe fn context_switch(addresses: Addresses) -> ! { unsafe { asm!( - "mov cr3, {}; mov rsp, {}; push 0; jmp {}", + r#" + xor rbp, rbp + mov cr3, {} + mov rsp, {} + push 0 + jmp {} + "#, in(reg) addresses.page_table.start_address().as_u64(), in(reg) addresses.stack_top.as_u64(), in(reg) addresses.entry_point.as_u64(), diff --git a/common/src/load_kernel.rs b/common/src/load_kernel.rs index a79a404a..68ad9778 100644 --- a/common/src/load_kernel.rs +++ b/common/src/load_kernel.rs @@ -721,11 +721,15 @@ pub fn load_kernel( page_table: &mut (impl MapperAllSizes + Translate), frame_allocator: &mut impl FrameAllocator, used_entries: &mut UsedLevel4Entries, -) -> Result<(VirtAddr, Option), &'static str> { +) -> Result<(VirtAddr, VirtAddr, Option), &'static str> { let mut loader = Loader::new(kernel, page_table, frame_allocator, used_entries)?; let tls_template = loader.load_segments()?; - Ok((loader.entry_point(), tls_template)) + Ok(( + VirtAddr::new(loader.inner.virtual_address_offset.virtual_address_offset() as u64), + loader.entry_point(), + tls_template, + )) } /// A helper type used to offset virtual addresses for position independent