diff --git a/nel_os_kernel/src/vmm/mod.rs b/nel_os_kernel/src/vmm/mod.rs index d1dcd6b..9ee8c83 100644 --- a/nel_os_kernel/src/vmm/mod.rs +++ b/nel_os_kernel/src/vmm/mod.rs @@ -23,7 +23,15 @@ pub trait VCpu { ) -> Result<(), &'static str>; fn write_memory(&mut self, addr: u64, data: u8) -> Result<(), &'static str>; + fn write_memory_ranged( + &mut self, + addr_start: u64, + addr_end: u64, + data: u8, + ) -> Result<(), &'static str>; fn read_memory(&mut self, addr: u64) -> Result; + + fn get_guest_memory_size(&self) -> u64; } pub fn get_vcpu( diff --git a/nel_os_kernel/src/vmm/x86_64/amd/vcpu.rs b/nel_os_kernel/src/vmm/x86_64/amd/vcpu.rs index cd3753d..1667493 100644 --- a/nel_os_kernel/src/vmm/x86_64/amd/vcpu.rs +++ b/nel_os_kernel/src/vmm/x86_64/amd/vcpu.rs @@ -18,6 +18,27 @@ impl VCpu for AMDVCpu { Ok(()) } + fn write_memory(&mut self, addr: u64, data: u8) -> Result<(), &'static str> { + unimplemented!("AMDVCpu::write_memory is not implemented yet"); + } + + fn write_memory_ranged( + &mut self, + addr_start: u64, + addr_end: u64, + data: u8, + ) -> Result<(), &'static str> { + unimplemented!("AMDVCpu::write_memory_ranged is not implemented yet"); + } + + fn read_memory(&mut self, addr: u64) -> Result { + unimplemented!("AMDVCpu::read_memory is not implemented yet"); + } + + fn get_guest_memory_size(&self) -> u64 { + unimplemented!("AMDVCpu::get_guest_memory_size is not implemented yet") + } + fn new(_frame_allocator: &mut impl FrameAllocator) -> Result where Self: Sized, diff --git a/nel_os_kernel/src/vmm/x86_64/common/linux.rs b/nel_os_kernel/src/vmm/x86_64/common/linux.rs index 085397f..52daf1c 100644 --- a/nel_os_kernel/src/vmm/x86_64/common/linux.rs +++ b/nel_os_kernel/src/vmm/x86_64/common/linux.rs @@ -1,7 +1,75 @@ use core::ptr::read_unaligned; -pub const BZIMAGE: &'static [u8] = include_bytes!("../../../../bzImage"); -pub const INITRD: &'static [u8] = include_bytes!("../../../../rootfs-n.cpio.gz"); +use crate::vmm::VCpu; + +pub fn load_kernel(vcpu: &mut dyn VCpu) -> Result<(), &'static str> { + let kernel = BZIMAGE; + + let guest_mem_size = vcpu.get_guest_memory_size(); + let mut bp = BootParams::from_bytes(kernel).unwrap(); + bp.e820_entries = 0; + + bp.hdr.type_of_loader = 0xFF; + bp.hdr.ext_loader_ver = 0; + bp.hdr.loadflags.set_loaded_high(true); + bp.hdr.loadflags.set_can_use_heap(true); + bp.hdr.heap_end_ptr = (LAYOUT_BOOTPARAM - 0x200) as u16; + bp.hdr.loadflags.set_keep_segments(true); + bp.hdr.cmd_line_ptr = LAYOUT_CMDLINE as u32; + bp.hdr.vid_mode = 0xFFFF; + + bp.add_e820_entry(0, LAYOUT_KERNEL_BASE, E820Type::Ram); + bp.add_e820_entry( + LAYOUT_KERNEL_BASE, + guest_mem_size - LAYOUT_KERNEL_BASE, + E820Type::Ram, + ); + + let cmdline_max_size = if bp.hdr.cmdline_size < 256 { + bp.hdr.cmdline_size + } else { + 256 + }; + + let cmdline_start = LAYOUT_CMDLINE as u64; + let cmdline_end = cmdline_start + cmdline_max_size as u64; + vcpu.write_memory_ranged(cmdline_start, cmdline_end, 0)?; + let cmdline_val = "console=ttyS0 earlyprintk=serial nokaslr"; + let cmdline_bytes = cmdline_val.as_bytes(); + for (i, &byte) in cmdline_bytes.iter().enumerate() { + vcpu.write_memory(cmdline_start + i as u64, byte)?; + } + + let bp_bytes = unsafe { + core::slice::from_raw_parts( + &bp as *const BootParams as *const u8, + core::mem::size_of::(), + ) + }; + load_image(vcpu, bp_bytes, LAYOUT_BOOTPARAM as usize)?; + + let code_offset = bp.hdr.get_protected_code_offset(); + let code_size = kernel.len() - code_offset; + load_image( + vcpu, + &kernel[code_offset..code_offset + code_size], + LAYOUT_KERNEL_BASE as usize, + )?; + + Ok(()) +} + +fn load_image(vcpu: &mut dyn VCpu, image: &[u8], addr: usize) -> Result<(), &'static str> { + for (i, &byte) in image.iter().enumerate() { + let gpa = addr + i; + vcpu.write_memory(gpa as u64, byte)?; + } + + Ok(()) +} + +pub const BZIMAGE: &[u8] = include_bytes!("../../../../bzImage"); +pub const INITRD: &[u8] = include_bytes!("../../../../rootfs-n.cpio.gz"); pub const LAYOUT_BOOTPARAM: u64 = 0x0001_0000; pub const LAYOUT_CMDLINE: u64 = 0x0002_0000; diff --git a/nel_os_kernel/src/vmm/x86_64/intel/vcpu.rs b/nel_os_kernel/src/vmm/x86_64/intel/vcpu.rs index 816c636..bb2b7b4 100644 --- a/nel_os_kernel/src/vmm/x86_64/intel/vcpu.rs +++ b/nel_os_kernel/src/vmm/x86_64/intel/vcpu.rs @@ -39,6 +39,7 @@ pub struct IntelVCpu { vmcs: vmcs::Vmcs, ept: ept::EPT, eptp: ept::EPTP, + guest_memory_size: u64, } impl IntelVCpu { @@ -564,6 +565,27 @@ impl VCpu for IntelVCpu { Ok(()) } + fn write_memory(&mut self, addr: u64, data: u8) -> Result<(), &'static str> { + self.ept.set(addr, data) + } + + fn write_memory_ranged( + &mut self, + addr_start: u64, + addr_end: u64, + data: u8, + ) -> Result<(), &'static str> { + self.ept.set_range(addr_start, addr_end, data) + } + + fn read_memory(&mut self, addr: u64) -> Result { + self.ept.get(addr) + } + + fn get_guest_memory_size(&self) -> u64 { + self.guest_memory_size + } + fn new(frame_allocator: &mut impl FrameAllocator) -> Result where Self: Sized, @@ -597,6 +619,7 @@ impl VCpu for IntelVCpu { vmcs, ept, eptp, + guest_memory_size: 1024 * 1024 * 1024, // 1 GiB }) }