This commit is contained in:
Masato Imai
2025-05-02 12:17:36 +00:00
parent 7168cd0826
commit 19244695d8
5 changed files with 232 additions and 20 deletions

131
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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<u8, &'static str> {
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(())
}

View File

@ -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<Self, &'static str> {
if bytes.len() < size_of::<Self>() {
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::<SetupHeader>()],
_edd_mbr_sig_buffer: [0; 0x10],
e820_map: [E820Entry {
addr: 0,
size: 0,
type_: E820Type::Ram as u32,
}; Self::E820MAX],
_unimplemented: [0; 0x330],
};
params
}
unsafe {
let boot_params_ptr = bytes.as_ptr() as *const Self;
Ok(read_unaligned(boot_params_ptr))
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, &'static str> {
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,
}

View File

@ -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::<BootParams>(),
)
};
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);