From 19244695d828287071e2d38afce23b402ace5aae Mon Sep 17 00:00:00 2001 From: Masato Imai Date: Fri, 2 May 2025 12:17:36 +0000 Subject: [PATCH] ram test --- Cargo.lock | 131 ++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/vmm/ept.rs | 20 ++++++-- src/vmm/linux.rs | 63 ++++++++++++++++++----- src/vmm/vcpu.rs | 37 ++++++++++++- 5 files changed, 232 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e61eb4..09e7d7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.4.0", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -61,6 +70,12 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + [[package]] name = "linked_list_allocator" version = "0.9.1" @@ -76,7 +91,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "autocfg", + "autocfg 1.4.0", "scopeguard", ] @@ -91,6 +106,7 @@ dependencies = [ "numeric-enum-macro", "pc-keyboard", "pic8259", + "rand", "spin 0.5.2", "uart_16550", "volatile 0.2.7", @@ -137,6 +153,97 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha", + "rand_core 0.4.2", + "rand_hc", + "rand_isaac", + "rand_jitter", + "rand_pcg", + "rand_xorshift", + "winapi", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "raw-cpuid" version = "10.7.0" @@ -219,6 +326,28 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "x86" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index b0e2064..1f1f9eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ linked_list_allocator = "0.9.0" x86 = "0.52.0" bitfield = "0.19.0" numeric-enum-macro = "0.2.0" +rand = { version = "0.6.5", default-features = false } [dependencies.lazy_static] version = "1.0" diff --git a/src/vmm/ept.rs b/src/vmm/ept.rs index 8296a94..4291a81 100644 --- a/src/vmm/ept.rs +++ b/src/vmm/ept.rs @@ -111,6 +111,7 @@ impl EPT { let lv4_index = (gpa >> 39) & 0x1FF; let lv3_index = (gpa >> 30) & 0x1FF; let lv2_index = (gpa >> 21) & 0x1FF; + let page_offset = gpa & 0x1FFFFF; let lv4_table = Self::frame_to_table_ptr(&self.root_table); let lv4_entry = &lv4_table[lv4_index as usize]; @@ -130,7 +131,19 @@ impl EPT { return None; } - Some(lv2_entry.address().as_u64()) + let phys_addr_base = lv2_entry.address().as_u64(); + Some(phys_addr_base | page_offset) + } + + pub fn get(&mut self, gpa: u64) -> Result { + let hpa = self + .get_phys_addr(gpa) + .ok_or("Failed to get physical address")?; + let phys_addr_offset = memory::PHYSICAL_MEMORY_OFFSET.load(Ordering::Relaxed); + let hpa = hpa + phys_addr_offset; + + let guest_memory = unsafe { &*(hpa as *const u8) }; + Ok(*guest_memory) } pub fn set(&mut self, gpa: u64, value: u8) -> Result<(), &'static str> { @@ -140,9 +153,8 @@ impl EPT { let phys_addr_offset = memory::PHYSICAL_MEMORY_OFFSET.load(Ordering::Relaxed); let hpa = hpa + phys_addr_offset; - let guest_memory = unsafe { &mut *(hpa as *mut [u8; 0x100000]) }; - let offset = (gpa & 0xFFFFF) as usize; - guest_memory[offset] = value; + let guest_memory = unsafe { &mut *(hpa as *mut u8) }; + *guest_memory = value; Ok(()) } diff --git a/src/vmm/linux.rs b/src/vmm/linux.rs index 09193f9..58f1319 100644 --- a/src/vmm/linux.rs +++ b/src/vmm/linux.rs @@ -1,5 +1,7 @@ use core::ptr::read_unaligned; +use crate::info; + pub const BZIMAGE: &'static [u8] = include_bytes!("../../bzImage"); pub const LAYOUT_BOOTPARAM: u64 = 0x0001_0000; @@ -40,15 +42,48 @@ pub struct BootParams { impl BootParams { pub const E820MAX: usize = 128; - pub fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() < size_of::() { - return Err("バイト配列が小さすぎます"); - } + pub fn new() -> Self { + let params = Self { + _screen_info: [0; 0x40], + _apm_bios_info: [0; 0x14], + _pad2: [0; 4], + tboot_addr: 0, + ist_info: [0; 0x10], + _pad3: [0; 0x10], + hd0_info: [0; 0x10], + hd1_info: [0; 0x10], + _sys_desc_table: [0; 0x10], + _olpc_ofw_header: [0; 0x10], + _pad4: [0; 0x80], + _edid_info: [0; 0x80], + _efi_info: [0; 0x20], + alt_mem_k: 0, + scratch: 0, + e820_entries: 0, + eddbuf_entries: 0, + edd_mbr_sig_buf_entries: 0, + kbd_status: 0, + _pad6: [0; 5], + hdr: SetupHeader::default(), + _pad7: [0; 0x290 - SetupHeader::HEADER_OFFSET - size_of::()], + _edd_mbr_sig_buffer: [0; 0x10], + e820_map: [E820Entry { + addr: 0, + size: 0, + type_: E820Type::Ram as u32, + }; Self::E820MAX], + _unimplemented: [0; 0x330], + }; - unsafe { - let boot_params_ptr = bytes.as_ptr() as *const Self; - Ok(read_unaligned(boot_params_ptr)) - } + params + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + let hdr = SetupHeader::from_bytes(bytes)?; + info!("hdr: {:?}", hdr); + let mut bp = BootParams::new(); + bp.hdr = hdr; + Ok(bp) } pub fn add_e820_entry(&mut self, addr: u64, size: u64, type_: E820Type) { @@ -60,7 +95,7 @@ impl BootParams { } #[repr(C, packed)] -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct SetupHeader { pub setup_sects: u8, pub root_flags: u16, @@ -111,16 +146,16 @@ impl SetupHeader { return Err("バイト配列が小さすぎます"); } - let mut header = unsafe { + let mut hdr = unsafe { let header_ptr = bytes.as_ptr().add(Self::HEADER_OFFSET) as *const Self; read_unaligned(header_ptr) }; - if header.setup_sects == 0 { - header.setup_sects = 4; + if hdr.setup_sects == 0 { + hdr.setup_sects = 4; } - Ok(header) + Ok(hdr) } pub fn get_protected_code_offset(&self) -> usize { @@ -129,7 +164,7 @@ impl SetupHeader { } #[repr(C, packed)] -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct LoadflagBitfield { raw: u8, } diff --git a/src/vmm/vcpu.rs b/src/vmm/vcpu.rs index af59600..f22334b 100644 --- a/src/vmm/vcpu.rs +++ b/src/vmm/vcpu.rs @@ -1,3 +1,4 @@ +use rand::{Rng, SeedableRng}; use x86::{ bits64::vmx::{vmread, vmwrite}, controlregs::{cr0, cr3, cr4, Cr0}, @@ -12,7 +13,6 @@ use core::sync::atomic::Ordering; use crate::{ info, memory::{self, BootInfoFrameAllocator}, - serial_print, vmm::vmcs::{ DescriptorType, EntryControls, Granularity, PrimaryExitControls, PrimaryProcessorBasedVmExecutionControls, SecondaryProcessorBasedVmExecutionControls, @@ -118,6 +118,7 @@ impl VCpu { core::mem::size_of::(), ) }; + info!("BootParams: {:?}", bp); self.load_image(bp_bytes, linux::LAYOUT_BOOTPARAM as usize); let code_offset = bp.hdr.get_protected_code_offset(); @@ -137,6 +138,38 @@ impl VCpu { } } + pub fn test_guest_memory(&mut self) { + for x in 1..=1024 { + let mut gpa = 0; + let start = 100 * 1024 * (x - 1); + let end = 100 * 1024 * x; + + let mut random_data = [0u8; 100 * 1024]; + let mut rng = rand::rngs::SmallRng::from_seed([0u8; 16]); + for byte in random_data.iter_mut() { + *byte = rng.gen(); + } + + self.load_image(&random_data, start); + + while gpa < 100 * 1024 { + let value = self.ept.get((gpa + start) as u64).unwrap(); + if value != random_data[gpa] { + panic!("Guest memory test failed at {:#x}", gpa); + } + gpa += 1; + } + info!( + "Guest memory test passed for range {:#x} - {:#x}", + start, end + ); + } + + let start = 100 * 1024 * 0; + let end = 100 * 1024 * 1024; + self.ept.set_range(start as u64, end as u64, 0).unwrap(); + } + pub fn setup_guest_memory(&mut self, frame_allocator: &mut BootInfoFrameAllocator) { let mut pages = 100; let mut gpa = 0; @@ -154,6 +187,8 @@ impl VCpu { } info!("Guest memory setup complete"); + self.test_guest_memory(); + self.load_kernel(linux::BZIMAGE); unsafe { let phys_mem_offset = memory::PHYSICAL_MEMORY_OFFSET.load(Ordering::Relaxed);