linux load kernel

This commit is contained in:
Masato Imai
2025-08-10 10:47:21 +00:00
parent 78973adc59
commit c1e555304c
4 changed files with 122 additions and 2 deletions

View File

@ -23,7 +23,15 @@ pub trait VCpu {
) -> Result<(), &'static str>; ) -> Result<(), &'static str>;
fn write_memory(&mut self, addr: u64, data: u8) -> 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<u8, &'static str>; fn read_memory(&mut self, addr: u64) -> Result<u8, &'static str>;
fn get_guest_memory_size(&self) -> u64;
} }
pub fn get_vcpu( pub fn get_vcpu(

View File

@ -18,6 +18,27 @@ impl VCpu for AMDVCpu {
Ok(()) 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<u8, &'static str> {
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<Size4KiB>) -> Result<Self, &'static str> fn new(_frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str>
where where
Self: Sized, Self: Sized,

View File

@ -1,7 +1,75 @@
use core::ptr::read_unaligned; use core::ptr::read_unaligned;
pub const BZIMAGE: &'static [u8] = include_bytes!("../../../../bzImage"); use crate::vmm::VCpu;
pub const INITRD: &'static [u8] = include_bytes!("../../../../rootfs-n.cpio.gz");
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::<BootParams>(),
)
};
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_BOOTPARAM: u64 = 0x0001_0000;
pub const LAYOUT_CMDLINE: u64 = 0x0002_0000; pub const LAYOUT_CMDLINE: u64 = 0x0002_0000;

View File

@ -39,6 +39,7 @@ pub struct IntelVCpu {
vmcs: vmcs::Vmcs, vmcs: vmcs::Vmcs,
ept: ept::EPT, ept: ept::EPT,
eptp: ept::EPTP, eptp: ept::EPTP,
guest_memory_size: u64,
} }
impl IntelVCpu { impl IntelVCpu {
@ -564,6 +565,27 @@ impl VCpu for IntelVCpu {
Ok(()) 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<u8, &'static str> {
self.ept.get(addr)
}
fn get_guest_memory_size(&self) -> u64 {
self.guest_memory_size
}
fn new(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str> fn new(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str>
where where
Self: Sized, Self: Sized,
@ -597,6 +619,7 @@ impl VCpu for IntelVCpu {
vmcs, vmcs,
ept, ept,
eptp, eptp,
guest_memory_size: 1024 * 1024 * 1024, // 1 GiB
}) })
} }