From 9823d1ff3014c0ad68f4d8f2dd835da47b6d6cb8 Mon Sep 17 00:00:00 2001 From: Alignof Date: Fri, 7 Feb 2025 22:18:23 +0900 Subject: [PATCH 01/58] [add] add `identity_may` feature --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 9b733e5..9cc12d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,8 @@ codegen-units = 1 [features] # debug log debug_log = [] +# identity memory map +identity_map = [] [dependencies] elf = { version = "0.7.2", default-features = false } From 95fc335c49615161ef8411a50e21c4959f0c491a Mon Sep 17 00:00:00 2001 From: Alignof Date: Fri, 7 Feb 2025 23:02:01 +0900 Subject: [PATCH 02/58] [add] add `load_guest_elf` in `identity_map` feature --- src/guest.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/src/guest.rs b/src/guest.rs index e562427..315517d 100644 --- a/src/guest.rs +++ b/src/guest.rs @@ -55,7 +55,11 @@ impl Guest { page_table::sv39x4::initialize_page_table(page_table_addr); // load guest dtb to memory - let dtb_addr = Self::map_guest_dtb(hart_id, page_table_addr, guest_dtb); + let dtb_addr = if cfg!(feature = "identity_map") { + GuestPhysicalAddress(guest_dtb.as_ptr() as usize) + } else { + Self::map_guest_dtb(hart_id, page_table_addr, guest_dtb) + }; Guest { hart_id, @@ -139,6 +143,82 @@ impl Guest { self.memory_region.start } + /// Load an elf to guest memory page. + /// + /// It only load `PT_LOAD` type segments. + /// Entry address is base address of the dram. + /// + /// # Return + /// - Entry point address in Guest memory space. + /// - End address of the ELF. (for filling remind memory space) + /// + /// # Arguments + /// * `guest_elf` - Elf loading guest space. + /// * `elf_addr` - Elf address. + #[cfg(feature = "identity_map")] + pub fn load_guest_elf( + &self, + guest_elf: &ElfBytes, + elf_addr: *const u8, + ) -> (GuestPhysicalAddress, GuestPhysicalAddress) { + /// Segment type `PT_LOAD` + /// + /// The array element specifies a loadable segment, described by `p_filesz` and `p_memsz`. + const PT_LOAD: u32 = 1; + + let mut elf_end: GuestPhysicalAddress = GuestPhysicalAddress::default(); + + for prog_header in guest_elf + .segments() + .expect("failed to get segments from elf") + .iter() + { + if prog_header.p_type == PT_LOAD { + let segment_gpa = GuestPhysicalAddress( + guest_memory::DRAM_BASE.raw() + prog_header.p_offset as usize, + ); + elf_end = core::cmp::max( + elf_end, + segment_gpa + prog_header.p_memsz as usize + PAGE_SIZE, + ); + unsafe { + core::ptr::copy( + elf_addr.wrapping_add(prog_header.p_offset as usize) as *const u8, + segment_gpa.raw() as *mut u8, + prog_header.p_memsz as usize, + ); + } + + if prog_header.p_memsz > prog_header.p_filesz { + unsafe { + core::ptr::write_bytes( + elf_addr.wrapping_add( + prog_header.p_offset as usize + prog_header.p_filesz as usize, + ) as *mut u8, + 0, + (prog_header.p_memsz - prog_header.p_filesz) as usize, + ); + } + } + } + } + + if !GUEST_INITRD.is_empty() { + let aligned_initrd_size = GUEST_INITRD.len().div_ceil(PAGE_SIZE) * PAGE_SIZE; + let initrd_start = + guest_memory::DRAM_BASE + guest_memory::DRAM_SIZE_PER_GUEST - aligned_initrd_size; + unsafe { + core::ptr::copy( + GUEST_INITRD.as_ptr(), + initrd_start.raw() as *mut u8, + GUEST_INITRD.len(), + ); + } + } + + (self.dram_base(), elf_end) + } + /// Load an elf to new allocated guest memory page. /// /// It only load `PT_LOAD` type segments. @@ -151,6 +231,7 @@ impl Guest { /// # Arguments /// * `guest_elf` - Elf loading guest space. /// * `elf_addr` - Elf address. + #[cfg(not(feature = "identity_map"))] pub fn load_guest_elf( &self, guest_elf: &ElfBytes, From c5a58f80e51b1bb6e787eb194fe465b9e324b190 Mon Sep 17 00:00:00 2001 From: Alignof Date: Fri, 7 Feb 2025 23:02:52 +0900 Subject: [PATCH 03/58] [update] modify to call only if `identity_map` feature disabled --- src/hypervisor_init.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hypervisor_init.rs b/src/hypervisor_init.rs index 8065f9a..acd1285 100644 --- a/src/hypervisor_init.rs +++ b/src/hypervisor_init.rs @@ -149,9 +149,11 @@ fn vsmode_setup(hart_id: usize, dtb_addr: HostPhysicalAddress) -> ! { let (guest_entry_point, elf_end_addr) = new_guest.load_guest_elf(&guest_elf, GUEST_KERNEL.as_ptr()); - // allocate page tables to all remain guest memory region - let guest_memory_end = new_guest.memory_region().end; - new_guest.allocate_memory_region(elf_end_addr..guest_memory_end); + if !cfg!(feature = "identity_map") { + // allocate page tables to all remain guest memory region + let guest_memory_end = new_guest.memory_region().end; + new_guest.allocate_memory_region(elf_end_addr..guest_memory_end); + } // set device memory map hypervisor_data From 6f1b8a143fc8a28e28f124c04000a886d38a3db4 Mon Sep 17 00:00:00 2001 From: Alignof Date: Fri, 7 Feb 2025 23:25:29 +0900 Subject: [PATCH 04/58] [add] add `PciDevice::memmap` --- src/device/pci.rs | 3 +++ src/device/pci/iommu.rs | 4 ++++ src/device/pci/sata.rs | 8 ++++++++ 3 files changed, 15 insertions(+) diff --git a/src/device/pci.rs b/src/device/pci.rs index 2b23878..e43cd95 100644 --- a/src/device/pci.rs +++ b/src/device/pci.rs @@ -64,6 +64,9 @@ pub trait PciDevice { /// Initialize pci device. /// * `pci`: struct `Pci` fn init(&self, pci_config_space_base_addr: HostPhysicalAddress); + + /// Return memory map between physical to physical (identity map) for crate page table. + fn memmap(&self) -> MemoryMap; } #[derive(Debug)] diff --git a/src/device/pci/iommu.rs b/src/device/pci/iommu.rs index ca36748..c267dcf 100644 --- a/src/device/pci/iommu.rs +++ b/src/device/pci/iommu.rs @@ -221,4 +221,8 @@ impl PciDevice for IoMmu { Self::init_page_table(ddt_addr); registers.ddtp.set(IoMmuMode::Lv1, ddt_addr); } + + fn memmap(&self) -> MemoryMap { + unreachable!(); + } } diff --git a/src/device/pci/sata.rs b/src/device/pci/sata.rs index ff85d66..d920cba 100644 --- a/src/device/pci/sata.rs +++ b/src/device/pci/sata.rs @@ -444,4 +444,12 @@ impl PciDevice for Sata { fn init(&self, _: HostPhysicalAddress) { unreachable!(); } + + fn memmap(&self) -> MemoryMap { + MemoryMap::new( + GuestPhysicalAddress(self.abar.start.raw())..GuestPhysicalAddress(self.abar.end.raw()), + self.abar.clone(), + &super::PTE_FLAGS_FOR_DEVICE, + ) + } } From 57882d2b83d225bc95afdfb7346356b2308738e4 Mon Sep 17 00:00:00 2001 From: Alignof Date: Fri, 7 Feb 2025 23:26:57 +0900 Subject: [PATCH 05/58] [update] map storage devece memory if `identity_map` feature is enabled --- src/device.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/device.rs b/src/device.rs index 2c6fb21..0e2f9d6 100644 --- a/src/device.rs +++ b/src/device.rs @@ -271,6 +271,19 @@ impl Devices { device_mapping.push(initrd.memmap()); } + // disable drive emulation + if cfg!(feature = "identity_map") { + if let Some(mmc) = &self.mmc { + device_mapping.push(mmc.memmap()); + } + if let Some(pci) = &self.pci { + if let Some(sata) = &pci.pci_devices.sata { + use pci::PciDevice; + device_mapping.push(sata.memmap()); + } + } + } + device_mapping } } From b177eaaaef58c24db226762325d636bf8bb9e740 Mon Sep 17 00:00:00 2001 From: Alignof Date: Sat, 8 Feb 2025 00:30:26 +0900 Subject: [PATCH 06/58] [add] add memory mapping for identity map --- src/device.rs | 2 +- src/guest.rs | 32 +++++++++++++++++++++++++++++--- src/hypervisor_init.rs | 11 +++++++++-- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/device.rs b/src/device.rs index 0e2f9d6..1d35a59 100644 --- a/src/device.rs +++ b/src/device.rs @@ -271,7 +271,7 @@ impl Devices { device_mapping.push(initrd.memmap()); } - // disable drive emulation + // disable drive emulation if `identity_map` feature is enabled if cfg!(feature = "identity_map") { if let Some(mmc) = &self.mmc { device_mapping.push(mmc.memmap()); diff --git a/src/guest.rs b/src/guest.rs index 315517d..1b99d73 100644 --- a/src/guest.rs +++ b/src/guest.rs @@ -175,7 +175,9 @@ impl Guest { { if prog_header.p_type == PT_LOAD { let segment_gpa = GuestPhysicalAddress( - guest_memory::DRAM_BASE.raw() + prog_header.p_offset as usize, + guest_memory::DRAM_BASE.raw() + + guest_memory::DRAM_SIZE_PER_GUEST * (self.hart_id + 1) + + prog_header.p_paddr as usize, ); elf_end = core::cmp::max( elf_end, @@ -205,8 +207,9 @@ impl Guest { if !GUEST_INITRD.is_empty() { let aligned_initrd_size = GUEST_INITRD.len().div_ceil(PAGE_SIZE) * PAGE_SIZE; - let initrd_start = - guest_memory::DRAM_BASE + guest_memory::DRAM_SIZE_PER_GUEST - aligned_initrd_size; + let initrd_start = guest_memory::DRAM_BASE + + guest_memory::DRAM_SIZE_PER_GUEST * (self.hart_id + 1) + - aligned_initrd_size; unsafe { core::ptr::copy( GUEST_INITRD.as_ptr(), @@ -324,6 +327,29 @@ impl Guest { } /// Allocate guest memory space from heap and create corresponding page table. + #[cfg(feature = "identity_map")] + pub fn allocate_memory_region(&self, region: Range) { + use PteFlag::{Accessed, Dirty, Exec, Read, User, Valid, Write}; + + let all_pte_flags_are_set = &[Dirty, Accessed, Exec, Write, Read, User, Valid]; + + for guest_physical_addr in (region.start.raw()..region.end.raw()).step_by(PAGE_SIZE) { + let guest_physical_addr = GuestPhysicalAddress(guest_physical_addr); + let host_physical_addr = HostPhysicalAddress(guest_physical_addr.raw()); + // create memory mapping + page_table::sv39x4::generate_page_table( + self.page_table_addr, + &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + host_physical_addr..host_physical_addr + PAGE_SIZE, + all_pte_flags_are_set, + )], + ); + } + } + + /// Allocate guest memory space from heap and create corresponding page table. + #[cfg(not(feature = "identity_map"))] pub fn allocate_memory_region(&self, region: Range) { use PteFlag::{Accessed, Dirty, Exec, Read, User, Valid, Write}; diff --git a/src/hypervisor_init.rs b/src/hypervisor_init.rs index acd1285..7f655a9 100644 --- a/src/hypervisor_init.rs +++ b/src/hypervisor_init.rs @@ -9,7 +9,8 @@ use crate::h_extension::csrs::{ }; use crate::h_extension::instruction::hfence_gvma_all; use crate::memmap::{ - page_table::sv39x4::ROOT_PAGE_TABLE, GuestPhysicalAddress, HostPhysicalAddress, + constant::guest_memory, page_table::sv39x4::ROOT_PAGE_TABLE, GuestPhysicalAddress, + HostPhysicalAddress, }; use crate::trap::hstrap_vector; use crate::ALLOCATOR; @@ -149,7 +150,13 @@ fn vsmode_setup(hart_id: usize, dtb_addr: HostPhysicalAddress) -> ! { let (guest_entry_point, elf_end_addr) = new_guest.load_guest_elf(&guest_elf, GUEST_KERNEL.as_ptr()); - if !cfg!(feature = "identity_map") { + if cfg!(feature = "identity_map") { + let guest_memory_start = + guest_memory::DRAM_BASE + (hart_id + 1) * guest_memory::DRAM_SIZE_PER_GUEST; + new_guest.allocate_memory_region( + guest_memory_start..guest_memory_start + guest_memory::DRAM_SIZE_PER_GUEST, + ); + } else { // allocate page tables to all remain guest memory region let guest_memory_end = new_guest.memory_region().end; new_guest.allocate_memory_region(elf_end_addr..guest_memory_end); From 9cc8d979b05a15eac9089cfc86a834137c17f6c5 Mon Sep 17 00:00:00 2001 From: Alignof Date: Sat, 8 Feb 2025 01:54:39 +0900 Subject: [PATCH 07/58] [add] add `map_guest_dtb` for `identity_map` feature --- src/guest.rs | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/guest.rs b/src/guest.rs index 1b99d73..578a97c 100644 --- a/src/guest.rs +++ b/src/guest.rs @@ -55,11 +55,7 @@ impl Guest { page_table::sv39x4::initialize_page_table(page_table_addr); // load guest dtb to memory - let dtb_addr = if cfg!(feature = "identity_map") { - GuestPhysicalAddress(guest_dtb.as_ptr() as usize) - } else { - Self::map_guest_dtb(hart_id, page_table_addr, guest_dtb) - }; + let dtb_addr = Self::map_guest_dtb(hart_id, page_table_addr, guest_dtb); Guest { hart_id, @@ -74,6 +70,41 @@ impl Guest { /// Load guest device tree and create corresponding page table /// /// Guest device tree will be placed start of guest memory region. + #[cfg(feature = "identity_map")] + fn map_guest_dtb( + _hart_id: usize, + page_table_addr: HostPhysicalAddress, + guest_dtb: &'static [u8; include_bytes!("../guest_image/guest.dtb").len()], + ) -> GuestPhysicalAddress { + use PteFlag::{Accessed, Dirty, Read, User, Valid, Write}; + + assert!(guest_dtb.len() < guest_memory::GUEST_DTB_REGION_SIZE); + + let aligned_dtb_size = guest_dtb.len().div_ceil(PAGE_SIZE) * PAGE_SIZE; + + for offset in (0..aligned_dtb_size).step_by(PAGE_SIZE) { + let guest_physical_addr = GuestPhysicalAddress(guest_dtb.as_ptr() as usize + offset); + let host_physical_addr = HostPhysicalAddress(guest_physical_addr.raw()); + + // create memory mapping + page_table::sv39x4::generate_page_table( + page_table_addr, + &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + host_physical_addr..host_physical_addr + PAGE_SIZE, + // allow writing data to dtb to modify device tree on guest OS. + &[Dirty, Accessed, Write, Read, User, Valid], + )], + ); + } + + GuestPhysicalAddress(guest_dtb.as_ptr() as usize) + } + + /// Load guest device tree and create corresponding page table + /// + /// Guest device tree will be placed start of guest memory region. + #[cfg(not(feature = "identity_map"))] fn map_guest_dtb( hart_id: usize, page_table_addr: HostPhysicalAddress, From da480c606da844d8a30817d710a7b8f6cd325f76 Mon Sep 17 00:00:00 2001 From: Alignof Date: Sat, 8 Feb 2025 02:26:58 +0900 Subject: [PATCH 08/58] [fix] fix loading initrd when `identity_map` feature is enabled --- src/guest.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/guest.rs b/src/guest.rs index 578a97c..a412fb6 100644 --- a/src/guest.rs +++ b/src/guest.rs @@ -238,9 +238,16 @@ impl Guest { if !GUEST_INITRD.is_empty() { let aligned_initrd_size = GUEST_INITRD.len().div_ceil(PAGE_SIZE) * PAGE_SIZE; - let initrd_start = guest_memory::DRAM_BASE - + guest_memory::DRAM_SIZE_PER_GUEST * (self.hart_id + 1) - - aligned_initrd_size; + let guest_base = + guest_memory::DRAM_BASE + guest_memory::DRAM_SIZE_PER_GUEST * (self.hart_id + 1); + let initrd_start = guest_base + guest_memory::DRAM_SIZE_PER_GUEST - aligned_initrd_size; + + crate::println!( + "initrd (GPA): {:#x}..{:#x}", + initrd_start.raw(), + initrd_start.raw() + GUEST_INITRD.len() + ); + unsafe { core::ptr::copy( GUEST_INITRD.as_ptr(), From a80a64496c2d25a1555566a3e23309a92bb754dc Mon Sep 17 00:00:00 2001 From: Alignof Date: Sun, 9 Feb 2025 14:19:22 +0900 Subject: [PATCH 09/58] [update] update memory.x for identity map --- memory.x | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/memory.x b/memory.x index 152cb95..a37739e 100644 --- a/memory.x +++ b/memory.x @@ -2,9 +2,9 @@ MEMORY { FLASH (rx) : ORIGIN = 0x83000000, LENGTH = 2M BOOT_RAM (rw) : ORIGIN = 0x83200000, LENGTH = 6M - RAM_HEAP (rwx) : ORIGIN = 0x84000000, LENGTH = 384M - RAM (rwx) : ORIGIN = 0x9c000000, LENGTH = 32M - L2_LIM (rw) : ORIGIN = 0x9e000000, LENGTH = 8M + RAM_HEAP (rwx) : ORIGIN = 0x84000000, LENGTH = 128M + RAM (rwx) : ORIGIN = 0x8c000000, LENGTH = 32M + L2_LIM (rw) : ORIGIN = 0x8e000000, LENGTH = 8M } /* @@ -23,7 +23,7 @@ REGION_ALIAS("REGION_HEAP", RAM_HEAP); REGION_ALIAS("REGION_STACK", L2_LIM); _stack_start = ORIGIN(L2_LIM) + LENGTH(L2_LIM); -_hv_heap_size = 0x18000000; +_hv_heap_size = 0x8000000; _b_stack_size = 0x200000; /* defined section in hikami */ From 15c4a5c3f0c69d683db969ecfb723712d60f094f Mon Sep 17 00:00:00 2001 From: Alingof Date: Fri, 4 Jul 2025 01:55:16 +0900 Subject: [PATCH 10/58] [refactor] fix cargo clippy warnings --- src/memmap/page_table.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/memmap/page_table.rs b/src/memmap/page_table.rs index 9100a2b..0e989ec 100644 --- a/src/memmap/page_table.rs +++ b/src/memmap/page_table.rs @@ -105,6 +105,7 @@ impl PageTableEntry { } /// Is pte invalid? + #[allow(clippy::no_effect_underscore_binding)] fn is_invalid(self) -> bool { let pte_v = self.0 & 0x1; let _pte_r = (self.0 >> 1) & 0x1; From 993fcaaa1e26a4c93c96edd6d01db31b74769c47 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 12 Feb 2025 18:51:49 +0900 Subject: [PATCH 11/58] [add] add workspace member `extension_manager` --- Cargo.toml | 4 +++ extension_manager/Cargo.toml | 6 ++++ extension_manager/build.rs | 60 ++++++++++++++++++++++++++++++++++++ extension_manager/src/lib.rs | 14 +++++++++ 4 files changed, 84 insertions(+) create mode 100644 extension_manager/Cargo.toml create mode 100644 extension_manager/build.rs create mode 100644 extension_manager/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 9cc12d0..f93a2cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,9 @@ missing_crate_level_docs = "warn" panic = 'abort' codegen-units = 1 +[workspace] +members = [ "extension_manager" ] + [features] # debug log debug_log = [] @@ -24,6 +27,7 @@ debug_log = [] identity_map = [] [dependencies] +extension_manager = { path = "extension_manager" } elf = { version = "0.7.2", default-features = false } fdt = "0.1.5" linked_list_allocator = "0.10.5" diff --git a/extension_manager/Cargo.toml b/extension_manager/Cargo.toml new file mode 100644 index 0000000..3b5f6a3 --- /dev/null +++ b/extension_manager/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "extension_manager" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/extension_manager/build.rs b/extension_manager/build.rs new file mode 100644 index 0000000..321f724 --- /dev/null +++ b/extension_manager/build.rs @@ -0,0 +1,60 @@ +use std::collections::HashSet; +use std::env; +use std::fs; +use std::path::Path; +use std::process::Command; + +fn main() { + // `cargo metadata` を実行して JSON を取得 + let output = Command::new("cargo") + .args(["metadata", "--format-version=1", "--no-deps"]) + .output() + .expect("Failed to execute cargo metadata"); + + let metadata = String::from_utf8(output.stdout).expect("Invalid UTF-8"); + + // JSON をパース + let json: serde_json::Value = serde_json::from_str(&metadata).expect("Failed to parse JSON"); + + // `workspace_root` を取得 + let workspace_root = json.get("workspace_root").and_then(|v| v.as_str()).unwrap(); + let root_package_name = Path::new(workspace_root) + .file_name() + .and_then(|s| s.to_str()) + .unwrap(); + + // `macro_crate` の `features` を取得 + let root_crate = json + .get("packages") + .and_then(|v| v.as_array()) + .and_then(|packages| { + packages + .iter() + .find(|pkg| pkg.get("name").and_then(|n| n.as_str()) == Some(&root_package_name)) + }) + .expect("Failed to find root_crate package"); + + dbg!(&root_crate); + + // `enable_extension` に関連するクレートを取得 + let feature_dependencies: HashSet = root_crate + .get("features") + .and_then(|v| v.as_object()) + .and_then(|features| features.get("enable_extension")) // `enable_extension` に紐づいたクレート + .and_then(|v| v.as_array()) + .map(|deps| { + deps.iter() + .filter_map(|dep| dep.as_str()) + .map(|dep| dep.replace('-', "_")) // `-` → `_` に変換 + .collect() + }) + .unwrap_or_default(); + let crate_names = feature_dependencies.into_iter().collect::>(); + + // 取得したクレート一覧を `OUT_DIR/dependencies.rs` に出力 + let out_dir = env::var("OUT_DIR").unwrap(); + let out_path = format!("{}/dependencies.rs", out_dir); + let content = format!("static CRATES: &[&str] = &{:?};", crate_names); + + fs::write(out_path, content).expect("Failed to write dependencies.rs"); +} diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs new file mode 100644 index 0000000..b93cf3f --- /dev/null +++ b/extension_manager/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} From cd9ae283094ea121912f3fc5c9f215cc18734c84 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 12 Feb 2025 19:09:03 +0900 Subject: [PATCH 12/58] [add] init `extension_manager` --- extension_manager/Cargo.toml | 9 +++++++++ extension_manager/src/lib.rs | 36 +++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/extension_manager/Cargo.toml b/extension_manager/Cargo.toml index 3b5f6a3..6227ad6 100644 --- a/extension_manager/Cargo.toml +++ b/extension_manager/Cargo.toml @@ -3,4 +3,13 @@ name = "extension_manager" version = "0.1.0" edition = "2024" +[lib] +proc-macro = true + +[build-dependencies] +serde_json = "1.0.138" + [dependencies] +quote = "1.0.38" +syn = "2.0.98" +proc-macro2 = "1.0.93" diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index b93cf3f..43e61d4 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -1,14 +1,28 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right -} +//! Hikami extension manager. +//! +//! It load extension emulation module as crate and expand function calls from macro. + +extern crate proc_macro; +extern crate proc_macro2; + +use proc_macro::TokenStream; +use quote::quote; +use syn::Ident; + +include!(concat!(env!("OUT_DIR"), "/dependencies.rs")); + +/// Test: call `func` function in all of modules. +#[proc_macro] +pub fn call_all_funcs(_input: TokenStream) -> TokenStream { + let calls = CRATES.iter().map(|name| { + let name = name.trim().replace('-', "_"); + let ident = Ident::new(&name, proc_macro2::Span::call_site()); + quote! { #ident::func(); } + }); -#[cfg(test)] -mod tests { - use super::*; + let expanded = quote! { + #(#calls)* + }; - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } + TokenStream::from(expanded) } From 3120d208444921acf83f324e37e2449335c350b1 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 26 Feb 2025 01:19:57 +0900 Subject: [PATCH 13/58] [add] add lib.rs and move `EmulateExtension` trait to it --- src/emulate_extension.rs | 39 ------------------ src/emulate_extension/zicfiss.rs | 19 ++++----- src/lib.rs | 48 +++++++++++++++++++++++ src/trap/exception/instruction_handler.rs | 2 +- 4 files changed, 59 insertions(+), 49 deletions(-) create mode 100644 src/lib.rs diff --git a/src/emulate_extension.rs b/src/emulate_extension.rs index be0bba5..107bbb4 100644 --- a/src/emulate_extension.rs +++ b/src/emulate_extension.rs @@ -7,47 +7,8 @@ use crate::trap::hstrap_exit; use crate::HYPERVISOR_DATA; use core::arch::asm; -use raki::Instruction; use riscv::register::sstatus; -/// Trait for extention emulation. -pub trait EmulateExtension { - /// Emulate instruction - fn instruction(&mut self, inst: &Instruction); - /// Emulate CSR - fn csr(&mut self, inst: &Instruction); - /// Emulate CSR field that already exists. - fn csr_field(&mut self, inst: &Instruction, write_to_csr_value: u64, read_csr_value: &mut u64); -} - -/// Holding a CSR value for CSRs emulation. -pub struct EmulatedCsr(u64); - -impl EmulatedCsr { - /// Return raw data. - pub fn bits(&self) -> u64 { - self.0 - } - - /// Write data to CSR. - /// For CSRRW or CSRRWI - pub fn write(&mut self, data: u64) { - self.0 = data; - } - - /// Set bit in CSR. - /// For CSRRS or CSRRSI - pub fn set(&mut self, mask: u64) { - self.0 |= mask; - } - - /// Clear bit in CSR. - /// For CSRRC or CSRRCI - pub fn clear(&mut self, mask: u64) { - self.0 &= !mask; - } -} - /// Initialize singletons for extension emulation. /// TODO: Remove it when `OnceCell` is replaced to `LazyCell`. pub fn initialize() { diff --git a/src/emulate_extension/zicfiss.rs b/src/emulate_extension/zicfiss.rs index 3823437..7cb3a2c 100644 --- a/src/emulate_extension/zicfiss.rs +++ b/src/emulate_extension/zicfiss.rs @@ -1,12 +1,13 @@ //! Emulation Zicfiss (Shadow Stack) //! Ref: [https://github.com/riscv/riscv-cfi/releases/download/v1.0/riscv-cfi.pdf](https://github.com/riscv/riscv-cfi/releases/download/v1.0/riscv-cfi.pdf) -use super::{pseudo_vs_exception, EmulateExtension, EmulatedCsr}; +use super::pseudo_vs_exception; use crate::memmap::{ page_table::{g_stage_trans_addr, vs_stage_trans_addr}, GuestVirtualAddress, }; use crate::HYPERVISOR_DATA; +use hikami::{EmulateExtension, EmulatedCsr}; use core::cell::OnceCell; use raki::{Instruction, OpcodeKind, ZicfissOpcode, ZicsrOpcode}; @@ -37,7 +38,7 @@ impl Zicfiss { /// Constructor for `Zicfiss`. pub fn new() -> Self { Zicfiss { - ssp: EmulatedCsr(0), + ssp: EmulatedCsr::new(0), henv_sse: false, senv_sse: false, } @@ -46,7 +47,7 @@ impl Zicfiss { /// Return host physical shadow stack pointer as `*mut usize`. #[allow(clippy::similar_names, clippy::cast_possible_truncation)] fn ssp_hp_ptr(&self) -> *mut usize { - if let Ok(gpa) = vs_stage_trans_addr(GuestVirtualAddress(self.ssp.0 as usize)) { + if let Ok(gpa) = vs_stage_trans_addr(GuestVirtualAddress(self.ssp.bits() as usize)) { let hpa = g_stage_trans_addr(gpa).unwrap(); hpa.0 as *mut usize } else { @@ -54,15 +55,15 @@ impl Zicfiss { HYPERVISOR_DATA.force_unlock(); ZICFISS_DATA.force_unlock(); } - pseudo_vs_exception(STORE_AMO_PAGE_FAULT, self.ssp.0 as usize); + pseudo_vs_exception(STORE_AMO_PAGE_FAULT, self.ssp.bits() as usize); } } /// Push value to shadow stack pub fn ss_push(&mut self, value: usize) { unsafe { - self.ssp = EmulatedCsr( - (self.ssp.0 as *const usize).byte_sub(core::mem::size_of::()) as u64, + self.ssp = EmulatedCsr::new( + (self.ssp.bits() as *const usize).byte_sub(core::mem::size_of::()) as u64, ); self.ssp_hp_ptr().write_volatile(value); } @@ -72,8 +73,8 @@ impl Zicfiss { pub fn ss_pop(&mut self) -> usize { unsafe { let pop_value = self.ssp_hp_ptr().read_volatile(); - self.ssp = EmulatedCsr( - (self.ssp.0 as *const usize).byte_add(core::mem::size_of::()) as u64, + self.ssp = EmulatedCsr::new( + (self.ssp.bits() as *const usize).byte_add(core::mem::size_of::()) as u64, ); pop_value @@ -145,7 +146,7 @@ impl EmulateExtension for Zicfiss { } OpcodeKind::Zicfiss(ZicfissOpcode::SSRDP) => { if self.is_ss_enable(sstatus) { - context.set_xreg(inst.rd.unwrap(), self.ssp.0); + context.set_xreg(inst.rd.unwrap(), self.ssp.bits()); } else { context.set_xreg(inst.rd.unwrap(), 0); } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..d7e2fae --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,48 @@ +//! hikami library + +#![no_std] + +use raki::Instruction; + +/// Trait for extention emulation. +pub trait EmulateExtension { + /// Emulate instruction + fn instruction(&mut self, inst: &Instruction); + /// Emulate CSR + fn csr(&mut self, inst: &Instruction); + /// Emulate CSR field that already exists. + fn csr_field(&mut self, inst: &Instruction, write_to_csr_value: u64, read_csr_value: &mut u64); +} + +/// Holding a CSR value for CSRs emulation. +pub struct EmulatedCsr(u64); + +impl EmulatedCsr { + /// Create self + pub fn new(value: u64) -> Self { + EmulatedCsr(value) + } + + /// Return raw data. + pub fn bits(&self) -> u64 { + self.0 + } + + /// Write data to CSR. + /// For CSRRW or CSRRWI + pub fn write(&mut self, data: u64) { + self.0 = data; + } + + /// Set bit in CSR. + /// For CSRRS or CSRRSI + pub fn set(&mut self, mask: u64) { + self.0 |= mask; + } + + /// Clear bit in CSR. + /// For CSRRC or CSRRCI + pub fn clear(&mut self, mask: u64) { + self.0 &= !mask; + } +} diff --git a/src/trap/exception/instruction_handler.rs b/src/trap/exception/instruction_handler.rs index 6271409..f097b65 100644 --- a/src/trap/exception/instruction_handler.rs +++ b/src/trap/exception/instruction_handler.rs @@ -5,10 +5,10 @@ use super::hs_forward_exception; use crate::emulate_extension::zicfiss::ZICFISS_DATA; -use crate::emulate_extension::EmulateExtension; use crate::HYPERVISOR_DATA; use core::arch::asm; +use hikami::EmulateExtension; use raki::{Instruction, OpcodeKind}; use riscv::register::{sepc, stval}; From caa0765f7aad10567eac2b446ff448fbbb806dbe Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 4 Jun 2025 16:01:26 +0900 Subject: [PATCH 14/58] [wip] tmp commit --- src/emulate_extension.rs | 44 +++++++ src/emulate_extension/zicfiss.rs | 2 +- src/lib.rs | 149 +++++++++++++++++----- src/main.rs | 127 +----------------- src/trap/exception/instruction_handler.rs | 2 +- 5 files changed, 170 insertions(+), 154 deletions(-) diff --git a/src/emulate_extension.rs b/src/emulate_extension.rs index 107bbb4..8e26640 100644 --- a/src/emulate_extension.rs +++ b/src/emulate_extension.rs @@ -7,6 +7,7 @@ use crate::trap::hstrap_exit; use crate::HYPERVISOR_DATA; use core::arch::asm; +use raki::Instruction; use riscv::register::sstatus; /// Initialize singletons for extension emulation. @@ -16,6 +17,49 @@ pub fn initialize() { unsafe { ZICFISS_DATA.lock() }.get_or_init(Zicfiss::new); } +/// Trait for extention emulation. +pub trait EmulateExtension { + /// Emulate instruction + fn instruction(&mut self, inst: &Instruction); + /// Emulate CSR + fn csr(&mut self, inst: &Instruction); + /// Emulate CSR field that already exists. + fn csr_field(&mut self, inst: &Instruction, write_to_csr_value: u64, read_csr_value: &mut u64); +} + +/// Holding a CSR value for CSRs emulation. +pub struct EmulatedCsr(u64); + +impl EmulatedCsr { + /// Create self + pub fn new(value: u64) -> Self { + EmulatedCsr(value) + } + + /// Return raw data. + pub fn bits(&self) -> u64 { + self.0 + } + + /// Write data to CSR. + /// For CSRRW or CSRRWI + pub fn write(&mut self, data: u64) { + self.0 = data; + } + + /// Set bit in CSR. + /// For CSRRS or CSRRSI + pub fn set(&mut self, mask: u64) { + self.0 |= mask; + } + + /// Clear bit in CSR. + /// For CSRRC or CSRRCI + pub fn clear(&mut self, mask: u64) { + self.0 &= !mask; + } +} + /// Throw an VS-level exception. /// * `exception_num`: Exception number. (stored to vscause) /// * `trap_value`: Trap value. (stored to vstval) diff --git a/src/emulate_extension/zicfiss.rs b/src/emulate_extension/zicfiss.rs index 7cb3a2c..660f708 100644 --- a/src/emulate_extension/zicfiss.rs +++ b/src/emulate_extension/zicfiss.rs @@ -2,12 +2,12 @@ //! Ref: [https://github.com/riscv/riscv-cfi/releases/download/v1.0/riscv-cfi.pdf](https://github.com/riscv/riscv-cfi/releases/download/v1.0/riscv-cfi.pdf) use super::pseudo_vs_exception; +use crate::emulate_extension::{EmulateExtension, EmulatedCsr}; use crate::memmap::{ page_table::{g_stage_trans_addr, vs_stage_trans_addr}, GuestVirtualAddress, }; use crate::HYPERVISOR_DATA; -use hikami::{EmulateExtension, EmulatedCsr}; use core::cell::OnceCell; use raki::{Instruction, OpcodeKind, ZicfissOpcode, ZicsrOpcode}; diff --git a/src/lib.rs b/src/lib.rs index d7e2fae..1955515 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,48 +1,135 @@ //! hikami library #![no_std] +// TODO: FIX AND REMOVE IT!!! +#![allow(static_mut_refs)] -use raki::Instruction; +extern crate alloc; +mod device; +mod emulate_extension; +mod guest; +mod h_extension; +mod log; +mod memmap; +mod trap; -/// Trait for extention emulation. -pub trait EmulateExtension { - /// Emulate instruction - fn instruction(&mut self, inst: &Instruction); - /// Emulate CSR - fn csr(&mut self, inst: &Instruction); - /// Emulate CSR field that already exists. - fn csr_field(&mut self, inst: &Instruction, write_to_csr_value: u64, read_csr_value: &mut u64); -} +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::cell::OnceCell; + +use device::Devices; +use guest::Guest; +use memmap::constant::MAX_HART_NUM; +use memmap::HostPhysicalAddress; -/// Holding a CSR value for CSRs emulation. -pub struct EmulatedCsr(u64); +use fdt::Fdt; +use spin::Mutex; -impl EmulatedCsr { - /// Create self - pub fn new(value: u64) -> Self { - EmulatedCsr(value) +/// Singleton for this hypervisor. +pub static mut HYPERVISOR_DATA: Mutex> = Mutex::new(OnceCell::new()); + +/// Global data for hypervisor. +/// +/// FIXME: Rename me! +#[derive(Debug)] +pub struct HypervisorData { + /// Current hart id (zero indexed). + current_hart: usize, + /// Guests data + guests: [Option; MAX_HART_NUM], + /// Devices data. + devices: device::Devices, +} + +impl HypervisorData { + /// Initialize hypervisor. + /// + /// # Panics + /// It will be panic when parsing device tree failed. + #[must_use] + pub fn new(device_tree: Fdt) -> Self { + HypervisorData { + current_hart: 0, + guests: [const { None }; MAX_HART_NUM], + devices: Devices::new(device_tree), + } } - /// Return raw data. - pub fn bits(&self) -> u64 { - self.0 + /// Return Device objects. + /// + /// # Panics + /// It will be panic if devices are uninitialized. + #[must_use] + pub fn devices(&mut self) -> &mut device::Devices { + &mut self.devices } - /// Write data to CSR. - /// For CSRRW or CSRRWI - pub fn write(&mut self, data: u64) { - self.0 = data; + /// Return current hart's guest. + /// + /// # Panics + /// It will be panic if current HART's guest data is empty. + #[must_use] + pub fn guest(&self) -> &Guest { + self.guests[self.current_hart] + .as_ref() + .expect("guest data not found") } - /// Set bit in CSR. - /// For CSRRS or CSRRSI - pub fn set(&mut self, mask: u64) { - self.0 |= mask; + /// Add new guest data. + /// + /// # Panics + /// It will be panic if `hart_id` is greater than `MAX_HART_NUM`. + pub fn register_guest(&mut self, new_guest: Guest) { + let hart_id = new_guest.hart_id(); + assert!(hart_id < MAX_HART_NUM); + self.guests[hart_id] = Some(new_guest); } +} + +/// Guest kernel image +#[link_section = ".guest_kernel"] +pub static GUEST_KERNEL: [u8; include_bytes!("../guest_image/vmlinux").len()] = + *include_bytes!("../guest_image/vmlinux"); + +/// Device tree blob that is passed to guest +#[link_section = ".guest_dtb"] +pub static GUEST_DTB: [u8; include_bytes!("../guest_image/guest.dtb").len()] = + *include_bytes!("../guest_image/guest.dtb"); + +/// Guest intird +#[link_section = ".guest_initrd"] +pub static GUEST_INITRD: [u8; include_bytes!("../guest_image/initrd").len()] = + *include_bytes!("../guest_image/initrd"); + +extern "C" { + /// stack top (defined in `memory.x`) + pub static _stack_start: u8; + /// start of heap (defined in `memory.x`) + pub static mut _start_heap: u8; + /// heap size (defined in `memory.x`) + pub static _hv_heap_size: u8; + /// boot stack top (defined in `memory.x`) + pub static _top_b_stack: u8; + /// start of bss and sbss section. + pub static _start_bss: u8; + /// end of bss and sbss section. + pub static _end_bss: u8; +} + +/// Aligned page size memory block +#[repr(C, align(0x1000))] +pub struct PageBlock([u8; 0x1000]); + +impl PageBlock { + /// Return aligned address of page size memory block. + pub fn alloc() -> HostPhysicalAddress { + let mut host_physical_block_as_vec: Vec> = + Vec::with_capacity(1); + unsafe { + host_physical_block_as_vec.set_len(1); + } - /// Clear bit in CSR. - /// For CSRRC or CSRRCI - pub fn clear(&mut self, mask: u64) { - self.0 &= !mask; + let host_physical_block_slice = host_physical_block_as_vec.into_boxed_slice(); + HostPhysicalAddress(Box::into_raw(host_physical_block_slice) as *const u8 as usize) } } diff --git a/src/main.rs b/src/main.rs index 3df604b..7e4d6ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,59 +16,15 @@ mod log; mod memmap; mod trap; -use alloc::boxed::Box; -use alloc::vec::Vec; use core::arch::naked_asm; -use core::cell::OnceCell; use core::panic::PanicInfo; -use fdt::Fdt; use linked_list_allocator::LockedHeap; -use spin::Mutex; -use crate::device::Devices; -use crate::guest::Guest; use crate::hypervisor_init::hstart; use crate::memmap::constant::{DRAM_BASE, MAX_HART_NUM, STACK_SIZE_PER_HART}; -use crate::memmap::HostPhysicalAddress; - -#[global_allocator] -/// Global allocator. -static ALLOCATOR: LockedHeap = LockedHeap::empty(); -// static mut ALLOCATOR: WildScreenAlloc = WildScreenAlloc::empty(); - -/// Singleton for this hypervisor. -static mut HYPERVISOR_DATA: Mutex> = Mutex::new(OnceCell::new()); - -/// Guest kernel image -#[link_section = ".guest_kernel"] -static GUEST_KERNEL: [u8; include_bytes!("../guest_image/vmlinux").len()] = - *include_bytes!("../guest_image/vmlinux"); - -/// Device tree blob that is passed to guest -#[link_section = ".guest_dtb"] -static GUEST_DTB: [u8; include_bytes!("../guest_image/guest.dtb").len()] = - *include_bytes!("../guest_image/guest.dtb"); - -/// Guest intird -#[link_section = ".guest_initrd"] -static GUEST_INITRD: [u8; include_bytes!("../guest_image/initrd").len()] = - *include_bytes!("../guest_image/initrd"); - -extern "C" { - /// stack top (defined in `memory.x`) - static _stack_start: u8; - /// start of heap (defined in `memory.x`) - static mut _start_heap: u8; - /// heap size (defined in `memory.x`) - static _hv_heap_size: u8; - /// boot stack top (defined in `memory.x`) - static _top_b_stack: u8; - /// start of bss and sbss section. - static _start_bss: u8; - /// end of bss and sbss section. - static _end_bss: u8; -} +use hikami::{HypervisorData, PageBlock, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL, HYPERVISOR_DATA}; +use hikami::{_end_bss, _hv_heap_size, _stack_start, _start_bss, _start_heap, _top_b_stack}; /// Panic handler #[panic_handler] @@ -79,81 +35,10 @@ pub fn panic(info: &PanicInfo) -> ! { } } -/// Aligned page size memory block -#[repr(C, align(0x1000))] -struct PageBlock([u8; 0x1000]); - -impl PageBlock { - /// Return aligned address of page size memory block. - fn alloc() -> HostPhysicalAddress { - let mut host_physical_block_as_vec: Vec> = - Vec::with_capacity(1); - unsafe { - host_physical_block_as_vec.set_len(1); - } - - let host_physical_block_slice = host_physical_block_as_vec.into_boxed_slice(); - HostPhysicalAddress(Box::into_raw(host_physical_block_slice) as *const u8 as usize) - } -} - -/// Global data for hypervisor. -/// -/// FIXME: Rename me! -#[derive(Debug)] -pub struct HypervisorData { - /// Current hart id (zero indexed). - current_hart: usize, - /// Guests data - guests: [Option; MAX_HART_NUM], - /// Devices data. - devices: device::Devices, -} - -impl HypervisorData { - /// Initialize hypervisor. - /// - /// # Panics - /// It will be panic when parsing device tree failed. - #[must_use] - pub fn new(device_tree: Fdt) -> Self { - HypervisorData { - current_hart: 0, - guests: [const { None }; MAX_HART_NUM], - devices: Devices::new(device_tree), - } - } - - /// Return Device objects. - /// - /// # Panics - /// It will be panic if devices are uninitialized. - #[must_use] - pub fn devices(&mut self) -> &mut device::Devices { - &mut self.devices - } - - /// Return current hart's guest. - /// - /// # Panics - /// It will be panic if current HART's guest data is empty. - #[must_use] - pub fn guest(&self) -> &Guest { - self.guests[self.current_hart] - .as_ref() - .expect("guest data not found") - } - - /// Add new guest data. - /// - /// # Panics - /// It will be panic if `hart_id` is greater than `MAX_HART_NUM`. - pub fn register_guest(&mut self, new_guest: Guest) { - let hart_id = new_guest.hart_id(); - assert!(hart_id < MAX_HART_NUM); - self.guests[hart_id] = Some(new_guest); - } -} +#[global_allocator] +/// Global allocator. +static ALLOCATOR: LockedHeap = LockedHeap::empty(); +// static mut ALLOCATOR: WildScreenAlloc = WildScreenAlloc::empty(); /// Entry function of the hypervisor. /// diff --git a/src/trap/exception/instruction_handler.rs b/src/trap/exception/instruction_handler.rs index f097b65..6271409 100644 --- a/src/trap/exception/instruction_handler.rs +++ b/src/trap/exception/instruction_handler.rs @@ -5,10 +5,10 @@ use super::hs_forward_exception; use crate::emulate_extension::zicfiss::ZICFISS_DATA; +use crate::emulate_extension::EmulateExtension; use crate::HYPERVISOR_DATA; use core::arch::asm; -use hikami::EmulateExtension; use raki::{Instruction, OpcodeKind}; use riscv::register::{sepc, stval}; From 48cc5b8669f084454719d5e43a723ef0929e9264 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 4 Jun 2025 19:05:12 +0900 Subject: [PATCH 15/58] [!][update] move modules root to lib.rs --- src/hypervisor_init.rs | 22 +++++++++++----------- src/lib.rs | 14 +++++++------- src/main.rs | 14 +++----------- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/hypervisor_init.rs b/src/hypervisor_init.rs index 7f655a9..e96fdfb 100644 --- a/src/hypervisor_init.rs +++ b/src/hypervisor_init.rs @@ -1,21 +1,21 @@ //! HS-mode level initialization. -use crate::emulate_extension; -use crate::guest::context::ContextData; -use crate::guest::Guest; -use crate::h_extension::csrs::{ +use crate::ALLOCATOR; +use hikami::emulate_extension; +use hikami::guest::context::ContextData; +use hikami::guest::Guest; +use hikami::h_extension::csrs::{ hcounteren, hedeleg, hedeleg::ExceptionKind, henvcfg, hgatp, hideleg, hie, hstatus, hvip, vsatp, VsInterruptKind, }; -use crate::h_extension::instruction::hfence_gvma_all; -use crate::memmap::{ +use hikami::h_extension::instruction::hfence_gvma_all; +use hikami::memmap::{ constant::guest_memory, page_table::sv39x4::ROOT_PAGE_TABLE, GuestPhysicalAddress, HostPhysicalAddress, }; -use crate::trap::hstrap_vector; -use crate::ALLOCATOR; -use crate::{HypervisorData, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL, HYPERVISOR_DATA}; -use crate::{_hv_heap_size, _start_heap}; +use hikami::trap::hstrap_vector; +use hikami::{HypervisorData, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL, HYPERVISOR_DATA}; +use hikami::{_hv_heap_size, _start_heap}; use core::arch::asm; @@ -180,7 +180,7 @@ fn vsmode_setup(hart_id: usize, dtb_addr: HostPhysicalAddress) -> ! { .devices() .pci .as_ref() - .map(super::device::pci::Pci::init_pci_devices); + .map(hikami::device::pci::Pci::init_pci_devices); // set new guest data hypervisor_data.get_mut().unwrap().register_guest(new_guest); diff --git a/src/lib.rs b/src/lib.rs index 1955515..84636c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,13 +5,13 @@ #![allow(static_mut_refs)] extern crate alloc; -mod device; -mod emulate_extension; -mod guest; -mod h_extension; -mod log; -mod memmap; -mod trap; +pub mod device; +pub mod emulate_extension; +pub mod guest; +pub mod h_extension; +pub mod log; +pub mod memmap; +pub mod trap; use alloc::boxed::Box; use alloc::vec::Vec; diff --git a/src/main.rs b/src/main.rs index 7e4d6ad..bda639e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,15 +6,7 @@ // TODO: FIX AND REMOVE IT!!! #![allow(static_mut_refs)] -extern crate alloc; -mod device; -mod emulate_extension; -mod guest; -mod h_extension; mod hypervisor_init; -mod log; -mod memmap; -mod trap; use core::arch::naked_asm; use core::panic::PanicInfo; @@ -22,9 +14,9 @@ use core::panic::PanicInfo; use linked_list_allocator::LockedHeap; use crate::hypervisor_init::hstart; -use crate::memmap::constant::{DRAM_BASE, MAX_HART_NUM, STACK_SIZE_PER_HART}; -use hikami::{HypervisorData, PageBlock, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL, HYPERVISOR_DATA}; -use hikami::{_end_bss, _hv_heap_size, _stack_start, _start_bss, _start_heap, _top_b_stack}; +use hikami::memmap::constant::{DRAM_BASE, STACK_SIZE_PER_HART}; +use hikami::println; +use hikami::{_end_bss, _start_bss, _top_b_stack}; /// Panic handler #[panic_handler] From 236d5dce11e1383d01bd44774040bd5c3e22df8e Mon Sep 17 00:00:00 2001 From: Alingof Date: Fri, 6 Jun 2025 01:54:08 +0900 Subject: [PATCH 16/58] [refactor] apply `cargo clippy --fix` --- src/device.rs | 2 ++ src/device/pci.rs | 6 ++++++ src/device/pci/config_register.rs | 2 ++ src/device/pci/iommu.rs | 1 + src/device/plic.rs | 2 ++ src/device/uart.rs | 1 + src/emulate_extension.rs | 2 ++ src/emulate_extension/zicfiss.rs | 7 +++++++ src/guest.rs | 6 ++++++ src/guest/context.rs | 4 ++++ src/h_extension/csrs.rs | 7 +++++++ src/lib.rs | 1 + src/memmap.rs | 3 +++ 13 files changed, 44 insertions(+) diff --git a/src/device.rs b/src/device.rs index 1d35a59..324eeb0 100644 --- a/src/device.rs +++ b/src/device.rs @@ -40,6 +40,7 @@ pub enum DeviceEmulateError { /// It recives trapped address (and value) and emulate load/store. pub trait EmulateDevice { /// Pass through loading memory + #[must_use] fn pass_through_loading(dst_addr: HostPhysicalAddress) -> u32 { let dst_ptr = dst_addr.raw() as *const u32; unsafe { dst_ptr.read_volatile() } @@ -223,6 +224,7 @@ pub struct Devices { impl Devices { /// Constructor for `Devices`. + #[must_use] pub fn new(device_tree: Fdt) -> Self { Devices { uart: uart::Uart::try_new(&device_tree, &["ns16550a", "riscv,axi-uart-1.0"]) diff --git a/src/device/pci.rs b/src/device/pci.rs index e43cd95..b9d5ff3 100644 --- a/src/device/pci.rs +++ b/src/device/pci.rs @@ -30,6 +30,7 @@ impl Bdf { /// - `range_phys_hi`: Upper 32-bit data of child addresses. /// /// Ref: [https://elinux.org/Device_Tree_Usage#PCI_Address_Translation](https://elinux.org/Device_Tree_Usage#PCI_Address_Translation) + #[must_use] pub fn new(range_phys_hi: u32) -> Self { Bdf { bus: (range_phys_hi >> 16) & 0b1111_1111, // 8 bit @@ -39,6 +40,7 @@ impl Bdf { } /// Calculate offset of config space header + #[must_use] pub fn calc_config_space_header_offset(&self) -> usize { ((self.bus & 0b1111_1111) << 20) as usize | ((self.device & 0b1_1111) << 15) as usize @@ -178,6 +180,7 @@ pub struct PciAddressSpace { impl PciAddressSpace { /// Constructor of `PciAddressSpace`. + #[must_use] pub fn new(device_tree: &Fdt, compatibles: &[&str]) -> Self { /// Bytes size of u32. const BYTES_U32: usize = 4; @@ -235,11 +238,13 @@ impl PciAddressSpace { } /// Return base address of 32-bit memory space. + #[must_use] pub fn base_addr_32bit_memory_space(&self) -> HostPhysicalAddress { self.bit32_memory_space.start } /// Return base address of 64-bit memory space. + #[must_use] pub fn base_addr_64bit_memory_space(&self) -> HostPhysicalAddress { self.bit64_memory_space.start } @@ -266,6 +271,7 @@ impl Pci { /// Return memory maps of Generic PCI host controller /// /// Ref: [https://www.kernel.org/doc/Documentation/devicetree/bindings/pci/host-generic-pci.txt](https://www.kernel.org/doc/Documentation/devicetree/bindings/pci/host-generic-pci.txt) + #[must_use] pub fn pci_memory_maps(&self) -> &[MemoryMap] { &self.memory_maps } diff --git a/src/device/pci/config_register.rs b/src/device/pci/config_register.rs index fa9e377..579b63d 100644 --- a/src/device/pci/config_register.rs +++ b/src/device/pci/config_register.rs @@ -70,6 +70,7 @@ impl ConfigSpaceHeaderField { /// Get size of BAR. #[allow(clippy::cast_possible_truncation)] +#[must_use] pub fn get_bar_size(config_reg_base_addr: usize, reg: ConfigSpaceHeaderField) -> u32 { let config_reg_addr = config_reg_base_addr + reg as usize; match reg { @@ -93,6 +94,7 @@ pub fn get_bar_size(config_reg_base_addr: usize, reg: ConfigSpaceHeaderField) -> /// Read config data from "PCI Configuration Space". #[allow(clippy::cast_possible_truncation)] +#[must_use] pub fn read_config_register(config_reg_base_addr: usize, reg: ConfigSpaceHeaderField) -> u32 { // the register requires 32 bit size access. let config_reg_32bit_addr = (config_reg_base_addr + (reg as usize)) & !0b11; diff --git a/src/device/pci/iommu.rs b/src/device/pci/iommu.rs index c267dcf..0b608ba 100644 --- a/src/device/pci/iommu.rs +++ b/src/device/pci/iommu.rs @@ -34,6 +34,7 @@ impl IoMmu { /// * `device_tree`: struct Fdt /// * `node_path`: node path in fdt #[allow(clippy::cast_possible_truncation)] + #[must_use] pub fn new_from_dtb( device_tree: &Fdt, compatibles: &[&str], diff --git a/src/device/plic.rs b/src/device/plic.rs index fe7511d..1e96381 100644 --- a/src/device/plic.rs +++ b/src/device/plic.rs @@ -28,11 +28,13 @@ impl ContextId { /// Create new `ContextId` from hart id. /// /// Each hart has two id for machine and supervisor. + #[must_use] pub fn new(hart_id: usize, is_supervisor: bool) -> Self { ContextId(2 * hart_id + usize::from(is_supervisor)) } /// Return raw usize value. + #[must_use] pub fn raw(&self) -> usize { self.0 } diff --git a/src/device/uart.rs b/src/device/uart.rs index eaa7534..83ed176 100644 --- a/src/device/uart.rs +++ b/src/device/uart.rs @@ -28,6 +28,7 @@ pub struct Uart { impl Uart { /// Return address of LSR register. + #[must_use] pub fn lsr_addr(&self) -> HostPhysicalAddress { self.base_addr + register::LSR_OFFSET } diff --git a/src/emulate_extension.rs b/src/emulate_extension.rs index 8e26640..9ba622b 100644 --- a/src/emulate_extension.rs +++ b/src/emulate_extension.rs @@ -32,11 +32,13 @@ pub struct EmulatedCsr(u64); impl EmulatedCsr { /// Create self + #[must_use] pub fn new(value: u64) -> Self { EmulatedCsr(value) } /// Return raw data. + #[must_use] pub fn bits(&self) -> u64 { self.0 } diff --git a/src/emulate_extension/zicfiss.rs b/src/emulate_extension/zicfiss.rs index 660f708..e570dfe 100644 --- a/src/emulate_extension/zicfiss.rs +++ b/src/emulate_extension/zicfiss.rs @@ -34,8 +34,15 @@ pub struct Zicfiss { pub senv_sse: bool, } +impl Default for Zicfiss { + fn default() -> Self { + Self::new() + } +} + impl Zicfiss { /// Constructor for `Zicfiss`. + #[must_use] pub fn new() -> Self { Zicfiss { ssp: EmulatedCsr::new(0), diff --git a/src/guest.rs b/src/guest.rs index a412fb6..60a91a9 100644 --- a/src/guest.rs +++ b/src/guest.rs @@ -37,6 +37,7 @@ impl Guest { /// /// - Zero filling root page table. /// - Map guest dtb to guest memory space. + #[must_use] pub fn new( hart_id: usize, root_page_table: &'static [PageTableEntry; FIRST_LV_PAGE_TABLE_LEN], @@ -150,21 +151,25 @@ impl Guest { } /// Return HART(HARdware Thread) id. + #[must_use] pub fn hart_id(&self) -> usize { self.hart_id } /// Return Stack top (end of memory region) + #[must_use] pub fn stack_top(&self) -> HostPhysicalAddress { self.stack_top_addr } /// Return guest device tree address. (GPA) + #[must_use] pub fn guest_dtb_addr(&self) -> GuestPhysicalAddress { self.dtb_addr } /// Return guest dram space start + #[must_use] pub fn memory_region(&self) -> &Range { &self.memory_region } @@ -273,6 +278,7 @@ impl Guest { /// * `guest_elf` - Elf loading guest space. /// * `elf_addr` - Elf address. #[cfg(not(feature = "identity_map"))] + #[must_use] pub fn load_guest_elf( &self, guest_elf: &ElfBytes, diff --git a/src/guest/context.rs b/src/guest/context.rs index bd1be12..6cc36dc 100644 --- a/src/guest/context.rs +++ b/src/guest/context.rs @@ -28,6 +28,7 @@ pub struct Context { impl Context { /// Constructor for `Context`. + #[must_use] pub fn new(address: HostPhysicalAddress) -> Self { Context { address } } @@ -45,6 +46,7 @@ impl Context { } /// Return regular register value. + #[must_use] pub fn xreg(self, index: usize) -> u64 { if index == 0 { 0 @@ -59,6 +61,7 @@ impl Context { } /// Return sepc value. + #[must_use] pub fn sepc(self) -> usize { self.get_context().sepc } @@ -80,6 +83,7 @@ impl Context { } /// Return sstatus value. + #[must_use] pub fn sstatus(self) -> usize { self.get_context().sstatus } diff --git a/src/h_extension/csrs.rs b/src/h_extension/csrs.rs index a8a7f3a..b5e9753 100644 --- a/src/h_extension/csrs.rs +++ b/src/h_extension/csrs.rs @@ -8,6 +8,7 @@ macro_rules! impl_bits { ($register:ident) => { #[allow(dead_code)] impl $register { + #[must_use] pub fn bits(&self) -> usize { self.0 } @@ -21,6 +22,7 @@ macro_rules! read_csr_as { ($register:ident, $csr_number:literal) => { #[inline] #[allow(dead_code)] + #[must_use] pub fn read() -> $register { let csr_out; unsafe { @@ -152,6 +154,7 @@ pub mod vsatp { impl Vsatp { /// Current address-translation scheme #[inline] + #[must_use] pub fn mode(&self) -> Mode { match self.0 >> 60 { 0 => Mode::Bare, @@ -165,6 +168,7 @@ pub mod vsatp { /// Physical page number #[inline] + #[must_use] pub fn ppn(&self) -> usize { self.0 & 0xFFF_FFFF_FFFF // bits 0-43 } @@ -285,6 +289,7 @@ pub mod hgeie { pub struct Hgeie(usize); /// Get the `GEILEN`. + #[must_use] pub fn get_geilen() -> usize { let original_value = read(); write(0xffff_ffff); @@ -437,11 +442,13 @@ pub mod hgatp { impl Hgatp { /// Return ppn. + #[must_use] pub fn ppn(&self) -> usize { self.0 & 0xfff_ffff_ffff // 44 bit } /// Return translation mode. + #[must_use] pub fn mode(&self) -> Mode { match (self.0 >> 60) & 0b1111 { 0 => Mode::Bare, diff --git a/src/lib.rs b/src/lib.rs index 84636c3..3bf1bea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,6 +122,7 @@ pub struct PageBlock([u8; 0x1000]); impl PageBlock { /// Return aligned address of page size memory block. + #[must_use] pub fn alloc() -> HostPhysicalAddress { let mut host_physical_block_as_vec: Vec> = Vec::with_capacity(1); diff --git a/src/memmap.rs b/src/memmap.rs index 34b6a80..e55ca82 100644 --- a/src/memmap.rs +++ b/src/memmap.rs @@ -22,6 +22,7 @@ pub struct GuestPhysicalAddress(pub usize); impl GuestPhysicalAddress { /// Convert to usize. + #[must_use] pub fn raw(self) -> usize { self.0 } @@ -60,6 +61,7 @@ pub struct HostPhysicalAddress(pub usize); impl HostPhysicalAddress { /// Convert to usize. + #[must_use] pub fn raw(self) -> usize { self.0 } @@ -107,6 +109,7 @@ impl MemoryMap { /// Create new `MemoryMap`. /// /// `flags` is mapped to bitmap. + #[must_use] pub fn new( virt: Range, phys: Range, From 963550618f9b6d601803a9e6cc95dcb8d7431226 Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 8 Jun 2025 00:36:07 +0900 Subject: [PATCH 17/58] [refactor] allow missing docs in h_extension::csrs --- src/h_extension/csrs.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/h_extension/csrs.rs b/src/h_extension/csrs.rs index b5e9753..1ca6519 100644 --- a/src/h_extension/csrs.rs +++ b/src/h_extension/csrs.rs @@ -2,6 +2,8 @@ //! //! The specification referred to "The RISC-V Instruction Set Manual: Volume II Version 20240411". +#![allow(missing_docs)] + /// Implement bits for struct #[macro_export] macro_rules! impl_bits { From 6f83c032116b84f94887d755044e4d991010885d Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 8 Jun 2025 13:32:30 +0900 Subject: [PATCH 18/58] [!][fix] remove unnecessary `unsafe` keyword --- src/h_extension/csrs.rs | 12 +++++++----- src/trap.rs | 7 +++++-- src/trap/exception.rs | 6 ++++-- src/trap/interrupt.rs | 18 ++++++++++-------- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/h_extension/csrs.rs b/src/h_extension/csrs.rs index 1ca6519..3c505a6 100644 --- a/src/h_extension/csrs.rs +++ b/src/h_extension/csrs.rs @@ -202,13 +202,15 @@ pub mod hstatus { write_csr_as!(0x600); /// set spv bit (Supervisor Previous Virtualization mode, 7 bit) - pub unsafe fn set_spv() { - core::arch::asm!( - " + pub fn set_spv() { + unsafe { + core::arch::asm!( + " csrs hstatus, {bits} ", - bits = in(reg) 0b1000_0000 - ); + bits = in(reg) 0b1000_0000 + ); + } } } diff --git a/src/trap.rs b/src/trap.rs index f959969..b33bb3a 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -12,6 +12,9 @@ use core::arch::asm; use riscv::register::scause::{self, Trap}; /// Switch to original mode stack and save contexts. +/// +/// # Safety +/// Drop all global variables. #[inline(always)] #[allow(clippy::inline_always)] pub unsafe fn hstrap_exit() -> ! { @@ -93,7 +96,7 @@ pub unsafe fn hstrap_exit() -> ! { /// ``` #[no_mangle] #[inline(never)] -pub unsafe extern "C" fn hstrap_vector() -> ! { +pub extern "C" fn hstrap_vector() -> ! { unsafe { asm!( ".align 4 @@ -151,7 +154,7 @@ pub unsafe extern "C" fn hstrap_vector() -> ! { } /// Separated from `hsrap_vector` by stack pointer circumstance. -pub unsafe extern "C" fn hstrap_vector2() -> ! { +pub extern "C" fn hstrap_vector2() -> ! { match scause::read().cause() { Trap::Interrupt(interrupt_cause) => trap_interrupt(interrupt_cause), Trap::Exception(exception_cause) => trap_exception(exception_cause), diff --git a/src/trap/exception.rs b/src/trap/exception.rs index 0e3b503..5352fec 100644 --- a/src/trap/exception.rs +++ b/src/trap/exception.rs @@ -84,7 +84,7 @@ fn update_sepc_by_inst_type(is_compressed: bool, context: &mut guest::context::C /// Trap handler for exception #[allow(clippy::cast_possible_truncation, clippy::module_name_repetitions)] -pub unsafe fn trap_exception(exception_cause: Exception) -> ! { +pub fn trap_exception(exception_cause: Exception) -> ! { match exception_cause { Exception::IllegalInstruction => instruction_handler::illegal_instruction(), Exception::SupervisorEnvCall => panic!("SupervisorEnvCall should be handled by M-mode"), @@ -109,5 +109,7 @@ pub unsafe fn trap_exception(exception_cause: Exception) -> ! { _ => hs_forward_exception(), } - hstrap_exit(); + unsafe { + hstrap_exit(); + } } diff --git a/src/trap/interrupt.rs b/src/trap/interrupt.rs index 71bfb67..5f1ccfe 100644 --- a/src/trap/interrupt.rs +++ b/src/trap/interrupt.rs @@ -10,17 +10,17 @@ use riscv::register::sie; /// Trap handler for Interrupt #[allow(clippy::module_name_repetitions)] -pub unsafe fn trap_interrupt(interrupt_cause: Interrupt) -> ! { +pub fn trap_interrupt(interrupt_cause: Interrupt) -> ! { match interrupt_cause { - Interrupt::SupervisorSoft => { + Interrupt::SupervisorSoft => unsafe { hvip::set(VsInterruptKind::Software); sie::clear_ssoft(); - } - Interrupt::SupervisorTimer => { + }, + Interrupt::SupervisorTimer => unsafe { hvip::set(VsInterruptKind::Timer); sie::clear_stimer(); - } - Interrupt::SupervisorExternal => { + }, + Interrupt::SupervisorExternal => unsafe { let mut hypervisor_data = HYPERVISOR_DATA.lock(); let hart_id = hypervisor_data.get().unwrap().guest().hart_id(); let context_id = ContextId::new(hart_id, true); @@ -35,9 +35,11 @@ pub unsafe fn trap_interrupt(interrupt_cause: Interrupt) -> ! { hvip::set(VsInterruptKind::External); sie::clear_sext(); - } + }, Interrupt::Unknown => panic!("unknown interrupt type"), } - hstrap_exit(); + unsafe { + hstrap_exit(); + } } From dc24837ab1d4a3a903a5f8a827715d2e927ce51e Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 8 Jun 2025 16:29:29 +0900 Subject: [PATCH 19/58] [refactor] add missing doc comments --- extension_manager/build.rs | 2 +- src/device.rs | 9 +++++++++ src/device/pci.rs | 3 +++ src/device/pci/iommu.rs | 3 +++ src/device/plic.rs | 9 +++++++++ src/emulate_extension.rs | 3 +++ src/guest.rs | 3 +++ src/h_extension/csrs.rs | 10 ++++++++-- src/log.rs | 3 +++ src/memmap/page_table.rs | 6 ++++++ src/memmap/page_table/sv39.rs | 13 ++++++++++++- src/memmap/page_table/sv39x4.rs | 16 +++++++++++++++- src/memmap/page_table/sv57.rs | 13 ++++++++++++- src/trap.rs | 4 ++++ 14 files changed, 91 insertions(+), 6 deletions(-) diff --git a/extension_manager/build.rs b/extension_manager/build.rs index 321f724..be84c25 100644 --- a/extension_manager/build.rs +++ b/extension_manager/build.rs @@ -30,7 +30,7 @@ fn main() { .and_then(|packages| { packages .iter() - .find(|pkg| pkg.get("name").and_then(|n| n.as_str()) == Some(&root_package_name)) + .find(|pkg| pkg.get("name").and_then(|n| n.as_str()) == Some(root_package_name)) }) .expect("Failed to find root_crate package"); diff --git a/src/device.rs b/src/device.rs index 324eeb0..378ae85 100644 --- a/src/device.rs +++ b/src/device.rs @@ -47,6 +47,9 @@ pub trait EmulateDevice { } /// Emulate loading port registers. + /// + /// # Errors + /// It will return an error if loading failed. #[allow(clippy::cast_possible_truncation)] fn emulate_loading(&self, dst_addr: HostPhysicalAddress) -> Result; @@ -59,6 +62,9 @@ pub trait EmulateDevice { } /// Emulate storing port registers. + /// + /// # Errors + /// It will return an error if storing failed. fn emulate_storing( &mut self, dst_addr: HostPhysicalAddress, @@ -224,6 +230,9 @@ pub struct Devices { impl Devices { /// Constructor for `Devices`. + /// + /// # Panics + /// Panics if UART or PLIC or CLINT are not found in device tree. #[must_use] pub fn new(device_tree: Fdt) -> Self { Devices { diff --git a/src/device/pci.rs b/src/device/pci.rs index b9d5ff3..f8d7e89 100644 --- a/src/device/pci.rs +++ b/src/device/pci.rs @@ -180,6 +180,9 @@ pub struct PciAddressSpace { impl PciAddressSpace { /// Constructor of `PciAddressSpace`. + /// + /// # Panics + /// Panics if `ranges` in device tree does not have seven fields or does not be aliged 4 bytes. #[must_use] pub fn new(device_tree: &Fdt, compatibles: &[&str]) -> Self { /// Bytes size of u32. diff --git a/src/device/pci/iommu.rs b/src/device/pci/iommu.rs index 0b608ba..17e639b 100644 --- a/src/device/pci/iommu.rs +++ b/src/device/pci/iommu.rs @@ -33,6 +33,9 @@ impl IoMmu { /// Create self instance from device tree. /// * `device_tree`: struct Fdt /// * `node_path`: node path in fdt + /// + /// # Panics + /// Panics if a pci device is not found in device tree. #[allow(clippy::cast_possible_truncation)] #[must_use] pub fn new_from_dtb( diff --git a/src/device/plic.rs b/src/device/plic.rs index 1e96381..fa5b523 100644 --- a/src/device/plic.rs +++ b/src/device/plic.rs @@ -83,6 +83,9 @@ impl Plic { } /// Emulate reading plic register. + /// + /// # Errors + /// It will return an error if `dst_addr` is out of range. pub fn emulate_loading( &self, dst_addr: HostPhysicalAddress, @@ -99,6 +102,9 @@ impl Plic { } /// Emulate storing plic context register. + /// + /// # Errors + /// It will return an error if `dst_addr` is out of range. fn context_storing( &mut self, dst_addr: HostPhysicalAddress, @@ -138,6 +144,9 @@ impl Plic { } /// Emulate storing plic register. + /// + /// # Errors + /// It will return an error if `dst_addr` is out of range. pub fn emulate_storing( &mut self, dst_addr: HostPhysicalAddress, diff --git a/src/emulate_extension.rs b/src/emulate_extension.rs index 9ba622b..dff99fe 100644 --- a/src/emulate_extension.rs +++ b/src/emulate_extension.rs @@ -65,6 +65,9 @@ impl EmulatedCsr { /// Throw an VS-level exception. /// * `exception_num`: Exception number. (stored to vscause) /// * `trap_value`: Trap value. (stored to vstval) +/// +/// # Panics +/// Panics if failed to get `hypervisor_data`. pub fn pseudo_vs_exception(exception_num: usize, trap_value: usize) -> ! { unsafe { let hypervisor_data = HYPERVISOR_DATA.lock(); diff --git a/src/guest.rs b/src/guest.rs index 60a91a9..d37aece 100644 --- a/src/guest.rs +++ b/src/guest.rs @@ -277,6 +277,9 @@ impl Guest { /// # Arguments /// * `guest_elf` - Elf loading guest space. /// * `elf_addr` - Elf address. + /// + /// # Panics + /// Panics if it failed to calculate `aligned_segment_size` or failed to convert to usize. #[cfg(not(feature = "identity_map"))] #[must_use] pub fn load_guest_elf( diff --git a/src/h_extension/csrs.rs b/src/h_extension/csrs.rs index 3c505a6..2547074 100644 --- a/src/h_extension/csrs.rs +++ b/src/h_extension/csrs.rs @@ -123,7 +123,10 @@ pub mod vsip { read_csr_as!(Vsip, 0x244); write_csr_as!(0x244); - /// set SSIP bit (`SupervisorSoftwareInterruptPending`, 1 bit) + /// Set SSIP bit (`SupervisorSoftwareInterruptPending`, 1 bit) + /// + /// # Safety + /// make sure S-mode config. pub unsafe fn set_ssoft() { core::arch::asm!( " @@ -133,7 +136,10 @@ pub mod vsip { ); } - /// set STIP bit (`SupervisorTimerInterruptPending`, 5 bit) + /// Set STIP bit (`SupervisorTimerInterruptPending`, 5 bit) + /// + /// # Safety + /// make sure S-mode config. pub unsafe fn set_stimer() { core::arch::asm!( " diff --git a/src/log.rs b/src/log.rs index 75968de..a8e0936 100644 --- a/src/log.rs +++ b/src/log.rs @@ -17,6 +17,9 @@ impl core::fmt::Write for Writer { } /// Print function calling from print macro +/// +/// # Panics +/// It will panic if formatting is failed. pub fn print_for_macro(args: fmt::Arguments) { let mut writer = Writer; writer.write_fmt(args).unwrap(); diff --git a/src/memmap/page_table.rs b/src/memmap/page_table.rs index 0e989ec..4a3788c 100644 --- a/src/memmap/page_table.rs +++ b/src/memmap/page_table.rs @@ -179,6 +179,9 @@ impl HostPhysicalAddress { } /// VS-stage address translation. +/// +/// # Errors +/// Returns an error when call it in Bare mode or unsupported mode. pub fn vs_stage_trans_addr( gva: GuestVirtualAddress, ) -> Result { @@ -194,6 +197,9 @@ pub fn vs_stage_trans_addr( } /// G-stage address translation. +/// +/// # Errors +/// Returns an error when call it in Bare mode or unsupported mode. pub fn g_stage_trans_addr( gpa: GuestPhysicalAddress, ) -> Result { diff --git a/src/memmap/page_table/sv39.rs b/src/memmap/page_table/sv39.rs index a628aed..cf9e228 100644 --- a/src/memmap/page_table/sv39.rs +++ b/src/memmap/page_table/sv39.rs @@ -47,7 +47,18 @@ impl AddressFieldSv39 for GuestVirtualAddress { } } -/// Translate gva to gpa in sv39 +/// Translate gva to gpa in `Sv39`. +/// +/// # Errors +/// This function will return an error if: +/// * An invalid Page Table Entry (PTE) is encountered during the page table walk. +/// * For a PTE that points to a superpage, remain PPN fields +/// that must be zero according to the specification is non-zero. +/// * The walk finishes all three levels of the page table hierarchy without reaching a leaf PTE. +/// +/// # Panics +/// This function will panic if: +/// * The current `vsatp` register's mode is not `Sv39`. #[allow(clippy::cast_possible_truncation)] pub fn trans_addr( gva: GuestVirtualAddress, diff --git a/src/memmap/page_table/sv39x4.rs b/src/memmap/page_table/sv39x4.rs index 36a83c2..183048f 100644 --- a/src/memmap/page_table/sv39x4.rs +++ b/src/memmap/page_table/sv39x4.rs @@ -75,6 +75,9 @@ pub fn initialize_page_table(root_table_start_addr: HostPhysicalAddress) { /// Generate third-level page table. (Sv39x4) /// /// The number of address translation stages is determined by the size of the range. +/// +/// # Panics +/// Panics if `root_table_start_addr` is not aligned 16 Kib. #[allow(clippy::module_name_repetitions)] pub fn generate_page_table(root_table_start_addr: HostPhysicalAddress, memmaps: &[MemoryMap]) { use crate::memmap::AddressRangeUtil; @@ -152,7 +155,18 @@ pub fn generate_page_table(root_table_start_addr: HostPhysicalAddress, memmaps: } } -/// Translate gpa to hpa in sv39x4 +/// Translate gva to gpa in `Sv39x4`. +/// +/// # Errors +/// This function will return an error if: +/// * An invalid Page Table Entry (PTE) is encountered during the page table walk. +/// * For a PTE that points to a superpage, remain PPN fields +/// that must be zero according to the specification is non-zero. +/// * The walk finishes all three levels of the page table hierarchy without reaching a leaf PTE. +/// +/// # Panics +/// This function will panic if: +/// * The current `vsatp` register's mode is not `Sv39x4`. #[allow(clippy::cast_possible_truncation)] pub fn trans_addr( gpa: GuestPhysicalAddress, diff --git a/src/memmap/page_table/sv57.rs b/src/memmap/page_table/sv57.rs index 822a2e6..d48c471 100644 --- a/src/memmap/page_table/sv57.rs +++ b/src/memmap/page_table/sv57.rs @@ -50,7 +50,18 @@ impl AddressFieldSv57 for GuestVirtualAddress { } } -/// Translate gva to gpa in sv57 +/// Translate gva to gpa in `Sv57`. +/// +/// # Errors +/// This function will return an error if: +/// * An invalid Page Table Entry (PTE) is encountered during the page table walk. +/// * For a PTE that points to a superpage, remain PPN fields +/// that must be zero according to the specification is non-zero. +/// * The walk finishes all five levels of the page table hierarchy without reaching a leaf PTE. +/// +/// # Panics +/// This function will panic if: +/// * The current `vsatp` register's mode is not `Sv57`. #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)] pub fn trans_addr( gva: GuestVirtualAddress, diff --git a/src/trap.rs b/src/trap.rs index b33bb3a..f5b35cf 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -13,6 +13,10 @@ use riscv::register::scause::{self, Trap}; /// Switch to original mode stack and save contexts. /// +/// # Panics +/// Panics if `hypervisor_data.get().unwrap()` is called on a `None` value. +/// This typically occurs if the hypervisor data has not been initialized. +/// /// # Safety /// Drop all global variables. #[inline(always)] From 2a6ae41211225e447c98458618bc9fd6b807214f Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 10 Jun 2025 00:01:24 +0900 Subject: [PATCH 20/58] [update] update comments in extension_manager/build.rs --- extension_manager/build.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extension_manager/build.rs b/extension_manager/build.rs index be84c25..08b16df 100644 --- a/extension_manager/build.rs +++ b/extension_manager/build.rs @@ -5,7 +5,7 @@ use std::path::Path; use std::process::Command; fn main() { - // `cargo metadata` を実行して JSON を取得 + // exec `cargo metadata` and get a json. let output = Command::new("cargo") .args(["metadata", "--format-version=1", "--no-deps"]) .output() @@ -13,17 +13,17 @@ fn main() { let metadata = String::from_utf8(output.stdout).expect("Invalid UTF-8"); - // JSON をパース + // parse the json. let json: serde_json::Value = serde_json::from_str(&metadata).expect("Failed to parse JSON"); - // `workspace_root` を取得 + // retrieve `workspace_root`. let workspace_root = json.get("workspace_root").and_then(|v| v.as_str()).unwrap(); let root_package_name = Path::new(workspace_root) .file_name() .and_then(|s| s.to_str()) .unwrap(); - // `macro_crate` の `features` を取得 + // extract `features` in `macro_crate`. let root_crate = json .get("packages") .and_then(|v| v.as_array()) @@ -36,22 +36,22 @@ fn main() { dbg!(&root_crate); - // `enable_extension` に関連するクレートを取得 + // collect crates reguardless of `enable_extension`. let feature_dependencies: HashSet = root_crate .get("features") .and_then(|v| v.as_object()) - .and_then(|features| features.get("enable_extension")) // `enable_extension` に紐づいたクレート + .and_then(|features| features.get("enable_extension")) // crates reguardless of `enable_extension` .and_then(|v| v.as_array()) .map(|deps| { deps.iter() .filter_map(|dep| dep.as_str()) - .map(|dep| dep.replace('-', "_")) // `-` → `_` に変換 + .map(|dep| dep.replace('-', "_")) // replace `-` with `_` .collect() }) .unwrap_or_default(); let crate_names = feature_dependencies.into_iter().collect::>(); - // 取得したクレート一覧を `OUT_DIR/dependencies.rs` に出力 + // output crates list to `OUT_DIR/dependencies.rs` let out_dir = env::var("OUT_DIR").unwrap(); let out_path = format!("{}/dependencies.rs", out_dir); let content = format!("static CRATES: &[&str] = &{:?};", crate_names); From 77b93c99e51bc82d7256e7e2e5d37b652befe4e2 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 10 Jun 2025 00:02:51 +0900 Subject: [PATCH 21/58] [add] add `emulate_extension::initialize` --- Cargo.toml | 3 +++ extension_manager/src/lib.rs | 29 ++++++++++++++++++++++++----- src/emulate_extension.rs | 3 +-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f93a2cd..b927f79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,8 +25,11 @@ members = [ "extension_manager" ] debug_log = [] # identity memory map identity_map = [] +# for `extension_manager` +enable_extension = [ "hikami_zicfiss" ] [dependencies] +hikami_zicfiss = { path = "../hikami_zicfiss", optional = true } extension_manager = { path = "extension_manager" } elf = { version = "0.7.2", default-features = false } fdt = "0.1.5" diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index 43e61d4..919b12e 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -6,18 +6,37 @@ extern crate proc_macro; extern crate proc_macro2; use proc_macro::TokenStream; +use proc_macro2::Span; use quote::quote; use syn::Ident; include!(concat!(env!("OUT_DIR"), "/dependencies.rs")); -/// Test: call `func` function in all of modules. +/// Initialize all global variable. #[proc_macro] -pub fn call_all_funcs(_input: TokenStream) -> TokenStream { +pub fn initialize(_input: TokenStream) -> TokenStream { let calls = CRATES.iter().map(|name| { - let name = name.trim().replace('-', "_"); - let ident = Ident::new(&name, proc_macro2::Span::call_site()); - quote! { #ident::func(); } + // crate name format: hikami_modulename + let module_name = name + .strip_prefix("hikami_") + .expect("Crate name should start with 'hikami_'"); + let mut struct_name_chars = module_name.chars(); + let struct_name = match struct_name_chars.next() { + None => String::new(), + Some(c) => c.to_uppercase().collect::() + struct_name_chars.as_str(), + }; + let global_var_name = format!("{}_DATA", module_name.to_uppercase()); + + let module_ident = Ident::new(module_name, Span::call_site()); + let struct_ident = Ident::new(&struct_name, Span::call_site()); + let global_var_ident = Ident::new(&global_var_name, Span::call_site()); + + quote! { + use #module_ident::{#struct_ident, #global_var_ident}; + unsafe { + #global_var_ident.lock().get_or_init(#struct_ident::new); + } + } }); let expanded = quote! { diff --git a/src/emulate_extension.rs b/src/emulate_extension.rs index dff99fe..39d4bf6 100644 --- a/src/emulate_extension.rs +++ b/src/emulate_extension.rs @@ -13,8 +13,7 @@ use riscv::register::sstatus; /// Initialize singletons for extension emulation. /// TODO: Remove it when `OnceCell` is replaced to `LazyCell`. pub fn initialize() { - use zicfiss::{Zicfiss, ZICFISS_DATA}; - unsafe { ZICFISS_DATA.lock() }.get_or_init(Zicfiss::new); + extension_manager::initialize!(); } /// Trait for extention emulation. From 3bc655e7ee02d3b8832f194a1807627829dfe12f Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 10 Jun 2025 01:01:16 +0900 Subject: [PATCH 22/58] [!][add] add `hikami_core` crate and move modules to it --- Cargo.toml | 29 ++++++++++++------- hikami_core/Cargo.toml | 15 ++++++++++ {src => hikami_core/src}/device.rs | 0 {src => hikami_core/src}/device/axi_sdc.rs | 0 .../src}/device/axi_sdc/register.rs | 0 {src => hikami_core/src}/device/clint.rs | 0 {src => hikami_core/src}/device/initrd.rs | 0 {src => hikami_core/src}/device/pci.rs | 0 .../src}/device/pci/config_register.rs | 0 {src => hikami_core/src}/device/pci/iommu.rs | 0 .../src}/device/pci/iommu/register_map.rs | 0 {src => hikami_core/src}/device/pci/sata.rs | 0 .../src}/device/pci/sata/command.rs | 0 {src => hikami_core/src}/device/plic.rs | 0 {src => hikami_core/src}/device/rtc.rs | 0 {src => hikami_core/src}/device/uart.rs | 0 {src => hikami_core/src}/device/virtio.rs | 0 {src => hikami_core/src}/emulate_extension.rs | 0 .../src}/emulate_extension/zicfiss.rs | 0 {src => hikami_core/src}/guest.rs | 4 +-- {src => hikami_core/src}/guest/context.rs | 0 {src => hikami_core/src}/h_extension.rs | 0 {src => hikami_core/src}/h_extension/csrs.rs | 0 .../src}/h_extension/instruction.rs | 0 {src => hikami_core/src}/lib.rs | 20 ++++++------- {src => hikami_core/src}/log.rs | 0 {src => hikami_core/src}/memmap.rs | 0 {src => hikami_core/src}/memmap/constant.rs | 0 {src => hikami_core/src}/memmap/page_table.rs | 0 .../src}/memmap/page_table/sv39.rs | 0 .../src}/memmap/page_table/sv39x4.rs | 2 +- .../src}/memmap/page_table/sv57.rs | 0 {src => hikami_core/src}/trap.rs | 2 +- {src => hikami_core/src}/trap/exception.rs | 2 +- .../trap/exception/instruction_handler.rs | 0 .../src}/trap/exception/page_fault_handler.rs | 0 .../src}/trap/exception/sbi_handler.rs | 0 {src => hikami_core/src}/trap/interrupt.rs | 0 src/hypervisor_init.rs | 20 ++++++------- src/main.rs | 6 ++-- 40 files changed, 61 insertions(+), 39 deletions(-) create mode 100644 hikami_core/Cargo.toml rename {src => hikami_core/src}/device.rs (100%) rename {src => hikami_core/src}/device/axi_sdc.rs (100%) rename {src => hikami_core/src}/device/axi_sdc/register.rs (100%) rename {src => hikami_core/src}/device/clint.rs (100%) rename {src => hikami_core/src}/device/initrd.rs (100%) rename {src => hikami_core/src}/device/pci.rs (100%) rename {src => hikami_core/src}/device/pci/config_register.rs (100%) rename {src => hikami_core/src}/device/pci/iommu.rs (100%) rename {src => hikami_core/src}/device/pci/iommu/register_map.rs (100%) rename {src => hikami_core/src}/device/pci/sata.rs (100%) rename {src => hikami_core/src}/device/pci/sata/command.rs (100%) rename {src => hikami_core/src}/device/plic.rs (100%) rename {src => hikami_core/src}/device/rtc.rs (100%) rename {src => hikami_core/src}/device/uart.rs (100%) rename {src => hikami_core/src}/device/virtio.rs (100%) rename {src => hikami_core/src}/emulate_extension.rs (100%) rename {src => hikami_core/src}/emulate_extension/zicfiss.rs (100%) rename {src => hikami_core/src}/guest.rs (98%) rename {src => hikami_core/src}/guest/context.rs (100%) rename {src => hikami_core/src}/h_extension.rs (100%) rename {src => hikami_core/src}/h_extension/csrs.rs (100%) rename {src => hikami_core/src}/h_extension/instruction.rs (100%) rename {src => hikami_core/src}/lib.rs (85%) rename {src => hikami_core/src}/log.rs (100%) rename {src => hikami_core/src}/memmap.rs (100%) rename {src => hikami_core/src}/memmap/constant.rs (100%) rename {src => hikami_core/src}/memmap/page_table.rs (100%) rename {src => hikami_core/src}/memmap/page_table/sv39.rs (100%) rename {src => hikami_core/src}/memmap/page_table/sv39x4.rs (99%) rename {src => hikami_core/src}/memmap/page_table/sv57.rs (100%) rename {src => hikami_core/src}/trap.rs (99%) rename {src => hikami_core/src}/trap/exception.rs (99%) rename {src => hikami_core/src}/trap/exception/instruction_handler.rs (100%) rename {src => hikami_core/src}/trap/exception/page_fault_handler.rs (100%) rename {src => hikami_core/src}/trap/exception/sbi_handler.rs (100%) rename {src => hikami_core/src}/trap/interrupt.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index b927f79..d9b4504 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,18 @@ panic = 'abort' codegen-units = 1 [workspace] -members = [ "extension_manager" ] +members = [ "extension_manager" , "hikami_core"] + +[workspace.dependencies] +elf = { version = "0.7.2", default-features = false } +fdt = "0.1.5" +linked_list_allocator = "0.10.5" +raki = "1.3.1" +riscv = "0.11.1" +rustsbi = "0.4.0" +sbi-rt = "0.0.3" +sbi-spec = { version = "0.0.8", features = [ "legacy" ] } +spin = "0.9.8" [features] # debug log @@ -29,14 +40,10 @@ identity_map = [] enable_extension = [ "hikami_zicfiss" ] [dependencies] +hikami_core = { path = "hikami_core" } hikami_zicfiss = { path = "../hikami_zicfiss", optional = true } -extension_manager = { path = "extension_manager" } -elf = { version = "0.7.2", default-features = false } -fdt = "0.1.5" -linked_list_allocator = "0.10.5" -raki = "1.3.1" -riscv = "0.11.1" -rustsbi = "0.4.0" -sbi-rt = "0.0.3" -sbi-spec = { version = "0.0.8", features = [ "legacy" ] } -spin = "0.9.8" + +elf = { workspace = true } +fdt = { workspace = true } +riscv = { workspace = true } +linked_list_allocator = { workspace = true } diff --git a/hikami_core/Cargo.toml b/hikami_core/Cargo.toml new file mode 100644 index 0000000..8015051 --- /dev/null +++ b/hikami_core/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "hikami_core" +version = "0.1.0" +edition = "2024" + +[dependencies] +extension_manager = { path = "../extension_manager" } +elf = { workspace = true } +fdt = { workspace = true } +raki = { workspace = true } +riscv = { workspace = true } +rustsbi = { workspace = true } +sbi-rt = { workspace = true } +sbi-spec = { workspace = true } +spin = { workspace = true } diff --git a/src/device.rs b/hikami_core/src/device.rs similarity index 100% rename from src/device.rs rename to hikami_core/src/device.rs diff --git a/src/device/axi_sdc.rs b/hikami_core/src/device/axi_sdc.rs similarity index 100% rename from src/device/axi_sdc.rs rename to hikami_core/src/device/axi_sdc.rs diff --git a/src/device/axi_sdc/register.rs b/hikami_core/src/device/axi_sdc/register.rs similarity index 100% rename from src/device/axi_sdc/register.rs rename to hikami_core/src/device/axi_sdc/register.rs diff --git a/src/device/clint.rs b/hikami_core/src/device/clint.rs similarity index 100% rename from src/device/clint.rs rename to hikami_core/src/device/clint.rs diff --git a/src/device/initrd.rs b/hikami_core/src/device/initrd.rs similarity index 100% rename from src/device/initrd.rs rename to hikami_core/src/device/initrd.rs diff --git a/src/device/pci.rs b/hikami_core/src/device/pci.rs similarity index 100% rename from src/device/pci.rs rename to hikami_core/src/device/pci.rs diff --git a/src/device/pci/config_register.rs b/hikami_core/src/device/pci/config_register.rs similarity index 100% rename from src/device/pci/config_register.rs rename to hikami_core/src/device/pci/config_register.rs diff --git a/src/device/pci/iommu.rs b/hikami_core/src/device/pci/iommu.rs similarity index 100% rename from src/device/pci/iommu.rs rename to hikami_core/src/device/pci/iommu.rs diff --git a/src/device/pci/iommu/register_map.rs b/hikami_core/src/device/pci/iommu/register_map.rs similarity index 100% rename from src/device/pci/iommu/register_map.rs rename to hikami_core/src/device/pci/iommu/register_map.rs diff --git a/src/device/pci/sata.rs b/hikami_core/src/device/pci/sata.rs similarity index 100% rename from src/device/pci/sata.rs rename to hikami_core/src/device/pci/sata.rs diff --git a/src/device/pci/sata/command.rs b/hikami_core/src/device/pci/sata/command.rs similarity index 100% rename from src/device/pci/sata/command.rs rename to hikami_core/src/device/pci/sata/command.rs diff --git a/src/device/plic.rs b/hikami_core/src/device/plic.rs similarity index 100% rename from src/device/plic.rs rename to hikami_core/src/device/plic.rs diff --git a/src/device/rtc.rs b/hikami_core/src/device/rtc.rs similarity index 100% rename from src/device/rtc.rs rename to hikami_core/src/device/rtc.rs diff --git a/src/device/uart.rs b/hikami_core/src/device/uart.rs similarity index 100% rename from src/device/uart.rs rename to hikami_core/src/device/uart.rs diff --git a/src/device/virtio.rs b/hikami_core/src/device/virtio.rs similarity index 100% rename from src/device/virtio.rs rename to hikami_core/src/device/virtio.rs diff --git a/src/emulate_extension.rs b/hikami_core/src/emulate_extension.rs similarity index 100% rename from src/emulate_extension.rs rename to hikami_core/src/emulate_extension.rs diff --git a/src/emulate_extension/zicfiss.rs b/hikami_core/src/emulate_extension/zicfiss.rs similarity index 100% rename from src/emulate_extension/zicfiss.rs rename to hikami_core/src/emulate_extension/zicfiss.rs diff --git a/src/guest.rs b/hikami_core/src/guest.rs similarity index 98% rename from src/guest.rs rename to hikami_core/src/guest.rs index d37aece..fc43a25 100644 --- a/src/guest.rs +++ b/hikami_core/src/guest.rs @@ -41,7 +41,7 @@ impl Guest { pub fn new( hart_id: usize, root_page_table: &'static [PageTableEntry; FIRST_LV_PAGE_TABLE_LEN], - guest_dtb: &'static [u8; include_bytes!("../guest_image/guest.dtb").len()], + guest_dtb: &'static [u8; include_bytes!("../../guest_image/guest.dtb").len()], ) -> Self { // calculate guest memory region let guest_memory_begin: GuestPhysicalAddress = @@ -109,7 +109,7 @@ impl Guest { fn map_guest_dtb( hart_id: usize, page_table_addr: HostPhysicalAddress, - guest_dtb: &'static [u8; include_bytes!("../guest_image/guest.dtb").len()], + guest_dtb: &'static [u8; include_bytes!("../../guest_image/guest.dtb").len()], ) -> GuestPhysicalAddress { use PteFlag::{Accessed, Dirty, Read, User, Valid, Write}; diff --git a/src/guest/context.rs b/hikami_core/src/guest/context.rs similarity index 100% rename from src/guest/context.rs rename to hikami_core/src/guest/context.rs diff --git a/src/h_extension.rs b/hikami_core/src/h_extension.rs similarity index 100% rename from src/h_extension.rs rename to hikami_core/src/h_extension.rs diff --git a/src/h_extension/csrs.rs b/hikami_core/src/h_extension/csrs.rs similarity index 100% rename from src/h_extension/csrs.rs rename to hikami_core/src/h_extension/csrs.rs diff --git a/src/h_extension/instruction.rs b/hikami_core/src/h_extension/instruction.rs similarity index 100% rename from src/h_extension/instruction.rs rename to hikami_core/src/h_extension/instruction.rs diff --git a/src/lib.rs b/hikami_core/src/lib.rs similarity index 85% rename from src/lib.rs rename to hikami_core/src/lib.rs index 3bf1bea..93ee137 100644 --- a/src/lib.rs +++ b/hikami_core/src/lib.rs @@ -87,21 +87,21 @@ impl HypervisorData { } /// Guest kernel image -#[link_section = ".guest_kernel"] -pub static GUEST_KERNEL: [u8; include_bytes!("../guest_image/vmlinux").len()] = - *include_bytes!("../guest_image/vmlinux"); +#[unsafe(link_section = ".guest_kernel")] +pub static GUEST_KERNEL: [u8; include_bytes!("../../guest_image/vmlinux").len()] = + *include_bytes!("../../guest_image/vmlinux"); /// Device tree blob that is passed to guest -#[link_section = ".guest_dtb"] -pub static GUEST_DTB: [u8; include_bytes!("../guest_image/guest.dtb").len()] = - *include_bytes!("../guest_image/guest.dtb"); +#[unsafe(link_section = ".guest_dtb")] +pub static GUEST_DTB: [u8; include_bytes!("../../guest_image/guest.dtb").len()] = + *include_bytes!("../../guest_image/guest.dtb"); /// Guest intird -#[link_section = ".guest_initrd"] -pub static GUEST_INITRD: [u8; include_bytes!("../guest_image/initrd").len()] = - *include_bytes!("../guest_image/initrd"); +#[unsafe(link_section = ".guest_initrd")] +pub static GUEST_INITRD: [u8; include_bytes!("../../guest_image/initrd").len()] = + *include_bytes!("../../guest_image/initrd"); -extern "C" { +unsafe extern "C" { /// stack top (defined in `memory.x`) pub static _stack_start: u8; /// start of heap (defined in `memory.x`) diff --git a/src/log.rs b/hikami_core/src/log.rs similarity index 100% rename from src/log.rs rename to hikami_core/src/log.rs diff --git a/src/memmap.rs b/hikami_core/src/memmap.rs similarity index 100% rename from src/memmap.rs rename to hikami_core/src/memmap.rs diff --git a/src/memmap/constant.rs b/hikami_core/src/memmap/constant.rs similarity index 100% rename from src/memmap/constant.rs rename to hikami_core/src/memmap/constant.rs diff --git a/src/memmap/page_table.rs b/hikami_core/src/memmap/page_table.rs similarity index 100% rename from src/memmap/page_table.rs rename to hikami_core/src/memmap/page_table.rs diff --git a/src/memmap/page_table/sv39.rs b/hikami_core/src/memmap/page_table/sv39.rs similarity index 100% rename from src/memmap/page_table/sv39.rs rename to hikami_core/src/memmap/page_table/sv39.rs diff --git a/src/memmap/page_table/sv39x4.rs b/hikami_core/src/memmap/page_table/sv39x4.rs similarity index 99% rename from src/memmap/page_table/sv39x4.rs rename to hikami_core/src/memmap/page_table/sv39x4.rs index 183048f..e731763 100644 --- a/src/memmap/page_table/sv39x4.rs +++ b/hikami_core/src/memmap/page_table/sv39x4.rs @@ -17,7 +17,7 @@ use core::slice::from_raw_parts_mut; pub const FIRST_LV_PAGE_TABLE_LEN: usize = 2048; /// Device tree blob that is passed to guest -#[link_section = ".root_page_table"] +#[unsafe(link_section = ".root_page_table")] pub static ROOT_PAGE_TABLE: [PageTableEntry; FIRST_LV_PAGE_TABLE_LEN] = [PageTableEntry(0u64); FIRST_LV_PAGE_TABLE_LEN]; diff --git a/src/memmap/page_table/sv57.rs b/hikami_core/src/memmap/page_table/sv57.rs similarity index 100% rename from src/memmap/page_table/sv57.rs rename to hikami_core/src/memmap/page_table/sv57.rs diff --git a/src/trap.rs b/hikami_core/src/trap.rs similarity index 99% rename from src/trap.rs rename to hikami_core/src/trap.rs index f5b35cf..3a80d33 100644 --- a/src/trap.rs +++ b/hikami_core/src/trap.rs @@ -98,7 +98,7 @@ pub unsafe fn hstrap_exit() -> ! { /// #[repr(align(4))] /// pub unsafe extern "C" fn hstrap_vector() -> ! { } /// ``` -#[no_mangle] +#[unsafe(no_mangle)] #[inline(never)] pub extern "C" fn hstrap_vector() -> ! { unsafe { diff --git a/src/trap/exception.rs b/hikami_core/src/trap/exception.rs similarity index 99% rename from src/trap/exception.rs rename to hikami_core/src/trap/exception.rs index 5352fec..97afba6 100644 --- a/src/trap/exception.rs +++ b/hikami_core/src/trap/exception.rs @@ -23,7 +23,7 @@ use sbi_handler::{ }; /// Delegate exception to supervisor mode from VS-mode. -#[no_mangle] +#[unsafe(no_mangle)] #[inline(always)] #[allow(clippy::inline_always, clippy::module_name_repetitions)] pub extern "C" fn hs_forward_exception() { diff --git a/src/trap/exception/instruction_handler.rs b/hikami_core/src/trap/exception/instruction_handler.rs similarity index 100% rename from src/trap/exception/instruction_handler.rs rename to hikami_core/src/trap/exception/instruction_handler.rs diff --git a/src/trap/exception/page_fault_handler.rs b/hikami_core/src/trap/exception/page_fault_handler.rs similarity index 100% rename from src/trap/exception/page_fault_handler.rs rename to hikami_core/src/trap/exception/page_fault_handler.rs diff --git a/src/trap/exception/sbi_handler.rs b/hikami_core/src/trap/exception/sbi_handler.rs similarity index 100% rename from src/trap/exception/sbi_handler.rs rename to hikami_core/src/trap/exception/sbi_handler.rs diff --git a/src/trap/interrupt.rs b/hikami_core/src/trap/interrupt.rs similarity index 100% rename from src/trap/interrupt.rs rename to hikami_core/src/trap/interrupt.rs diff --git a/src/hypervisor_init.rs b/src/hypervisor_init.rs index e96fdfb..92c1932 100644 --- a/src/hypervisor_init.rs +++ b/src/hypervisor_init.rs @@ -1,21 +1,21 @@ //! HS-mode level initialization. use crate::ALLOCATOR; -use hikami::emulate_extension; -use hikami::guest::context::ContextData; -use hikami::guest::Guest; -use hikami::h_extension::csrs::{ +use hikami_core::emulate_extension; +use hikami_core::guest::context::ContextData; +use hikami_core::guest::Guest; +use hikami_core::h_extension::csrs::{ hcounteren, hedeleg, hedeleg::ExceptionKind, henvcfg, hgatp, hideleg, hie, hstatus, hvip, vsatp, VsInterruptKind, }; -use hikami::h_extension::instruction::hfence_gvma_all; -use hikami::memmap::{ +use hikami_core::h_extension::instruction::hfence_gvma_all; +use hikami_core::memmap::{ constant::guest_memory, page_table::sv39x4::ROOT_PAGE_TABLE, GuestPhysicalAddress, HostPhysicalAddress, }; -use hikami::trap::hstrap_vector; -use hikami::{HypervisorData, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL, HYPERVISOR_DATA}; -use hikami::{_hv_heap_size, _start_heap}; +use hikami_core::trap::hstrap_vector; +use hikami_core::{HypervisorData, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL, HYPERVISOR_DATA}; +use hikami_core::{_hv_heap_size, _start_heap}; use core::arch::asm; @@ -180,7 +180,7 @@ fn vsmode_setup(hart_id: usize, dtb_addr: HostPhysicalAddress) -> ! { .devices() .pci .as_ref() - .map(hikami::device::pci::Pci::init_pci_devices); + .map(hikami_core::device::pci::Pci::init_pci_devices); // set new guest data hypervisor_data.get_mut().unwrap().register_guest(new_guest); diff --git a/src/main.rs b/src/main.rs index bda639e..60396b3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,9 +14,9 @@ use core::panic::PanicInfo; use linked_list_allocator::LockedHeap; use crate::hypervisor_init::hstart; -use hikami::memmap::constant::{DRAM_BASE, STACK_SIZE_PER_HART}; -use hikami::println; -use hikami::{_end_bss, _start_bss, _top_b_stack}; +use hikami_core::memmap::constant::{DRAM_BASE, STACK_SIZE_PER_HART}; +use hikami_core::println; +use hikami_core::{_end_bss, _start_bss, _top_b_stack}; /// Panic handler #[panic_handler] From 7ea65ec0589573bd1cd41f642a05dbdad296ef62 Mon Sep 17 00:00:00 2001 From: Alingof Date: Thu, 12 Jun 2025 22:52:30 +0900 Subject: [PATCH 23/58] [wip][fix] use crate_name instead of module name in `extension_manager::initialize` --- extension_manager/src/lib.rs | 15 ++++++--------- hikami_core/src/emulate_extension.rs | 2 -- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index 919b12e..64a66fd 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -15,24 +15,21 @@ include!(concat!(env!("OUT_DIR"), "/dependencies.rs")); /// Initialize all global variable. #[proc_macro] pub fn initialize(_input: TokenStream) -> TokenStream { - let calls = CRATES.iter().map(|name| { - // crate name format: hikami_modulename - let module_name = name - .strip_prefix("hikami_") - .expect("Crate name should start with 'hikami_'"); - let mut struct_name_chars = module_name.chars(); + let calls = CRATES.iter().map(|crate_name| { + // crate name format: hikami_module-name + let mut struct_name_chars = crate_name.chars(); let struct_name = match struct_name_chars.next() { None => String::new(), Some(c) => c.to_uppercase().collect::() + struct_name_chars.as_str(), }; - let global_var_name = format!("{}_DATA", module_name.to_uppercase()); + let global_var_name = format!("{}_DATA", crate_name.to_uppercase()); - let module_ident = Ident::new(module_name, Span::call_site()); + let crate_ident = Ident::new(crate_name, Span::call_site()); let struct_ident = Ident::new(&struct_name, Span::call_site()); let global_var_ident = Ident::new(&global_var_name, Span::call_site()); quote! { - use #module_ident::{#struct_ident, #global_var_ident}; + use #crate_ident::{#struct_ident, #global_var_ident}; unsafe { #global_var_ident.lock().get_or_init(#struct_ident::new); } diff --git a/hikami_core/src/emulate_extension.rs b/hikami_core/src/emulate_extension.rs index 39d4bf6..aa8b0f3 100644 --- a/hikami_core/src/emulate_extension.rs +++ b/hikami_core/src/emulate_extension.rs @@ -1,7 +1,5 @@ //! Extension emulation -pub mod zicfiss; - use crate::h_extension::csrs::vstvec; use crate::trap::hstrap_exit; use crate::HYPERVISOR_DATA; From 5212f6b24188f659e509e9b57ba07063f6def8a1 Mon Sep 17 00:00:00 2001 From: Alingof Date: Thu, 12 Jun 2025 22:59:50 +0900 Subject: [PATCH 24/58] [update] remove `emulate_extension::initialize` --- hikami_core/src/emulate_extension.rs | 6 ------ src/hypervisor_init.rs | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/hikami_core/src/emulate_extension.rs b/hikami_core/src/emulate_extension.rs index aa8b0f3..c319858 100644 --- a/hikami_core/src/emulate_extension.rs +++ b/hikami_core/src/emulate_extension.rs @@ -8,12 +8,6 @@ use core::arch::asm; use raki::Instruction; use riscv::register::sstatus; -/// Initialize singletons for extension emulation. -/// TODO: Remove it when `OnceCell` is replaced to `LazyCell`. -pub fn initialize() { - extension_manager::initialize!(); -} - /// Trait for extention emulation. pub trait EmulateExtension { /// Emulate instruction diff --git a/src/hypervisor_init.rs b/src/hypervisor_init.rs index 92c1932..690d862 100644 --- a/src/hypervisor_init.rs +++ b/src/hypervisor_init.rs @@ -186,7 +186,7 @@ fn vsmode_setup(hart_id: usize, dtb_addr: HostPhysicalAddress) -> ! { hypervisor_data.get_mut().unwrap().register_guest(new_guest); // initialize emulate_extension data - emulate_extension::initialize(); + extension_manager::initialize!(); unsafe { // sstatus.SUM = 1, sstatus.SPP = 0 From f9e267c1b7ecce41d2ee6e6cf7bdfa56dda7362e Mon Sep 17 00:00:00 2001 From: Alingof Date: Thu, 12 Jun 2025 23:06:25 +0900 Subject: [PATCH 25/58] [add] add `import_global_variables` --- extension_manager/src/lib.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index 64a66fd..e3d55a6 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -12,7 +12,28 @@ use syn::Ident; include!(concat!(env!("OUT_DIR"), "/dependencies.rs")); -/// Initialize all global variable. +/// Import all global varables. +#[proc_macro] +pub fn import_global_variables(_input: TokenStream) -> TokenStream { + let calls = CRATES.iter().map(|crate_name| { + let global_var_name = format!("{}_DATA", crate_name.to_uppercase()); + + let crate_ident = Ident::new(crate_name, Span::call_site()); + let global_var_ident = Ident::new(&global_var_name, Span::call_site()); + + quote! { + use #crate_ident::#global_var_ident; + } + }); + + let expanded = quote! { + #(#calls)* + }; + + TokenStream::from(expanded) +} + +/// Initialize all global variables. #[proc_macro] pub fn initialize(_input: TokenStream) -> TokenStream { let calls = CRATES.iter().map(|crate_name| { From 73ad6895bd3ec6de58969bd6ead5973b13836f72 Mon Sep 17 00:00:00 2001 From: Alingof Date: Thu, 12 Jun 2025 23:16:32 +0900 Subject: [PATCH 26/58] [!][update] move `hikami_core::trap` module to `hikami` --- Cargo.toml | 5 + hikami_core/Cargo.toml | 1 - hikami_core/src/emulate_extension/zicfiss.rs | 243 ------------------ hikami_core/src/trap.rs | 93 +------ src/hypervisor_init.rs | 3 +- src/main.rs | 1 + src/trap.rs | 167 ++++++++++++ {hikami_core/src => src}/trap/exception.rs | 8 +- .../trap/exception/instruction_handler.rs | 2 +- .../trap/exception/page_fault_handler.rs | 10 +- .../src => src}/trap/exception/sbi_handler.rs | 2 +- {hikami_core/src => src}/trap/interrupt.rs | 6 +- 12 files changed, 194 insertions(+), 347 deletions(-) delete mode 100644 hikami_core/src/emulate_extension/zicfiss.rs create mode 100644 src/trap.rs rename {hikami_core/src => src}/trap/exception.rs (97%) rename {hikami_core/src => src}/trap/exception/instruction_handler.rs (98%) rename {hikami_core/src => src}/trap/exception/page_fault_handler.rs (95%) rename {hikami_core/src => src}/trap/exception/sbi_handler.rs (99%) rename {hikami_core/src => src}/trap/interrupt.rs (90%) diff --git a/Cargo.toml b/Cargo.toml index d9b4504..82f5770 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,8 +42,13 @@ enable_extension = [ "hikami_zicfiss" ] [dependencies] hikami_core = { path = "hikami_core" } hikami_zicfiss = { path = "../hikami_zicfiss", optional = true } +extension_manager = { path = "extension_manager" } elf = { workspace = true } fdt = { workspace = true } +raki = { workspace = true } riscv = { workspace = true } +rustsbi = { workspace = true } +sbi-rt = { workspace = true } +sbi-spec = { workspace = true } linked_list_allocator = { workspace = true } diff --git a/hikami_core/Cargo.toml b/hikami_core/Cargo.toml index 8015051..777402d 100644 --- a/hikami_core/Cargo.toml +++ b/hikami_core/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2024" [dependencies] -extension_manager = { path = "../extension_manager" } elf = { workspace = true } fdt = { workspace = true } raki = { workspace = true } diff --git a/hikami_core/src/emulate_extension/zicfiss.rs b/hikami_core/src/emulate_extension/zicfiss.rs deleted file mode 100644 index e570dfe..0000000 --- a/hikami_core/src/emulate_extension/zicfiss.rs +++ /dev/null @@ -1,243 +0,0 @@ -//! Emulation Zicfiss (Shadow Stack) -//! Ref: [https://github.com/riscv/riscv-cfi/releases/download/v1.0/riscv-cfi.pdf](https://github.com/riscv/riscv-cfi/releases/download/v1.0/riscv-cfi.pdf) - -use super::pseudo_vs_exception; -use crate::emulate_extension::{EmulateExtension, EmulatedCsr}; -use crate::memmap::{ - page_table::{g_stage_trans_addr, vs_stage_trans_addr}, - GuestVirtualAddress, -}; -use crate::HYPERVISOR_DATA; - -use core::cell::OnceCell; -use raki::{Instruction, OpcodeKind, ZicfissOpcode, ZicsrOpcode}; -use spin::Mutex; - -/// Singleton for Zicfiss. -/// TODO: change `OnceCell` to `LazyCell` when stable `LazyCell::force_mut`. -pub static mut ZICFISS_DATA: Mutex> = Mutex::new(OnceCell::new()); - -/// Software-check exception. (cause value) -const SOFTWARE_CHECK_EXCEPTION: usize = 18; -/// Store/AMO page fault -const STORE_AMO_PAGE_FAULT: usize = 15; -/// Shadow stack fault. (tval value) -const SHADOW_STACK_FAULT: usize = 3; - -/// Singleton for Zicfiss extension -pub struct Zicfiss { - /// Shadow stack pointer - pub ssp: EmulatedCsr, - /// Shadow Stack Enable in henvcfg (for VS-mode) - pub henv_sse: bool, - /// Shadow Stack Enable in senvcfg (for VU-mode) - pub senv_sse: bool, -} - -impl Default for Zicfiss { - fn default() -> Self { - Self::new() - } -} - -impl Zicfiss { - /// Constructor for `Zicfiss`. - #[must_use] - pub fn new() -> Self { - Zicfiss { - ssp: EmulatedCsr::new(0), - henv_sse: false, - senv_sse: false, - } - } - - /// Return host physical shadow stack pointer as `*mut usize`. - #[allow(clippy::similar_names, clippy::cast_possible_truncation)] - fn ssp_hp_ptr(&self) -> *mut usize { - if let Ok(gpa) = vs_stage_trans_addr(GuestVirtualAddress(self.ssp.bits() as usize)) { - let hpa = g_stage_trans_addr(gpa).unwrap(); - hpa.0 as *mut usize - } else { - unsafe { - HYPERVISOR_DATA.force_unlock(); - ZICFISS_DATA.force_unlock(); - } - pseudo_vs_exception(STORE_AMO_PAGE_FAULT, self.ssp.bits() as usize); - } - } - - /// Push value to shadow stack - pub fn ss_push(&mut self, value: usize) { - unsafe { - self.ssp = EmulatedCsr::new( - (self.ssp.bits() as *const usize).byte_sub(core::mem::size_of::()) as u64, - ); - self.ssp_hp_ptr().write_volatile(value); - } - } - - /// Pop value from shadow stack - pub fn ss_pop(&mut self) -> usize { - unsafe { - let pop_value = self.ssp_hp_ptr().read_volatile(); - self.ssp = EmulatedCsr::new( - (self.ssp.bits() as *const usize).byte_add(core::mem::size_of::()) as u64, - ); - - pop_value - } - } - - /// Is shadow stack enabled? - /// - /// Chack corresponding `SSE` bit of xenvcfg. - fn is_ss_enable(&self, sstatus: usize) -> bool { - let spp = (sstatus >> 8) & 0x1; - if spp == 0 { - self.senv_sse - } else { - self.henv_sse - } - } -} - -impl EmulateExtension for Zicfiss { - /// Emulate Zicfiss instruction. - #[allow(clippy::cast_possible_truncation)] - fn instruction(&mut self, inst: &Instruction) { - let mut context = unsafe { HYPERVISOR_DATA.lock() } - .get() - .unwrap() - .guest() - .context; - let sstatus = context.sstatus(); - - match inst.opc { - OpcodeKind::Zicfiss(ZicfissOpcode::SSPUSH) => { - if self.is_ss_enable(sstatus) { - let push_value = context.xreg(inst.rs2.unwrap()); - self.ss_push(push_value as usize); - } - } - OpcodeKind::Zicfiss(ZicfissOpcode::C_SSPUSH) => { - if self.is_ss_enable(sstatus) { - let push_value = context.xreg(inst.rd.unwrap()); - self.ss_push(push_value as usize); - } - } - OpcodeKind::Zicfiss(ZicfissOpcode::SSPOPCHK) => { - if self.is_ss_enable(sstatus) { - let pop_value = self.ss_pop(); - let expected_value = context.xreg(inst.rs1.unwrap()) as usize; - if pop_value != expected_value { - unsafe { - HYPERVISOR_DATA.force_unlock(); - ZICFISS_DATA.force_unlock(); - } - pseudo_vs_exception(SOFTWARE_CHECK_EXCEPTION, SHADOW_STACK_FAULT) - } - } - } - OpcodeKind::Zicfiss(ZicfissOpcode::C_SSPOPCHK) => { - if self.is_ss_enable(sstatus) { - let pop_value = self.ss_pop(); - let expected_value = context.xreg(inst.rd.unwrap()) as usize; - if pop_value != expected_value { - unsafe { - HYPERVISOR_DATA.force_unlock(); - ZICFISS_DATA.force_unlock(); - } - pseudo_vs_exception(SOFTWARE_CHECK_EXCEPTION, SHADOW_STACK_FAULT) - } - } - } - OpcodeKind::Zicfiss(ZicfissOpcode::SSRDP) => { - if self.is_ss_enable(sstatus) { - context.set_xreg(inst.rd.unwrap(), self.ssp.bits()); - } else { - context.set_xreg(inst.rd.unwrap(), 0); - } - } - OpcodeKind::Zicfiss(ZicfissOpcode::SSAMOSWAP_W | ZicfissOpcode::SSAMOSWAP_D) => todo!(), - _ => todo!(), - } - } - - /// Emulate Zicfiss CSRs access. - fn csr(&mut self, inst: &Instruction) { - /// Register number of `Shadow Stack Pointer`. - const CSR_SSP: usize = 0x11; - - let hypervisor_data = unsafe { HYPERVISOR_DATA.lock() }; - let mut context = hypervisor_data.get().unwrap().guest().context; - - let csr_num = inst.rs2.unwrap(); - match csr_num { - CSR_SSP => match inst.opc { - OpcodeKind::Zicsr(ZicsrOpcode::CSRRW) => { - let rs1 = context.xreg(inst.rs1.unwrap()); - context.set_xreg(inst.rd.unwrap(), self.ssp.bits()); - self.ssp.write(rs1); - } - OpcodeKind::Zicsr(ZicsrOpcode::CSRRS) => { - let rs1 = context.xreg(inst.rs1.unwrap()); - context.set_xreg(inst.rd.unwrap(), self.ssp.bits()); - self.ssp.set(rs1); - } - OpcodeKind::Zicsr(ZicsrOpcode::CSRRC) => { - let rs1 = context.xreg(inst.rs1.unwrap()); - context.set_xreg(inst.rd.unwrap(), self.ssp.bits()); - self.ssp.clear(rs1); - } - OpcodeKind::Zicsr(ZicsrOpcode::CSRRWI) => { - context.set_xreg(inst.rd.unwrap(), self.ssp.bits()); - self.ssp.write(inst.rs1.unwrap() as u64); - } - OpcodeKind::Zicsr(ZicsrOpcode::CSRRSI) => { - context.set_xreg(inst.rd.unwrap(), self.ssp.bits()); - self.ssp.set(inst.rs1.unwrap() as u64); - } - OpcodeKind::Zicsr(ZicsrOpcode::CSRRCI) => { - context.set_xreg(inst.rd.unwrap(), self.ssp.bits()); - self.ssp.clear(inst.rs1.unwrap() as u64); - } - _ => unreachable!(), - }, - unsupported_csr_num => { - unimplemented!("unsupported CSRs: {unsupported_csr_num:#x}") - } - } - } - - /// Emulate CSR field that already exists. - fn csr_field(&mut self, inst: &Instruction, write_to_csr_value: u64, read_csr_value: &mut u64) { - /// Register number of `Supervisor Environment Configuration Register`. - const CSR_SENVCFG: usize = 0x10a; - - let csr_num = inst.rs2.unwrap(); - if csr_num == CSR_SENVCFG { - // overwritten emulated csr field - *read_csr_value |= u64::from(self.senv_sse) << 3; - - // update emulated csr field - match inst.opc { - OpcodeKind::Zicsr( - ZicsrOpcode::CSRRW - | ZicsrOpcode::CSRRS - | ZicsrOpcode::CSRRWI - | ZicsrOpcode::CSRRSI, - ) => { - if (write_to_csr_value >> 3) & 0x1 == 1 { - self.senv_sse = true; - } - } - OpcodeKind::Zicsr(ZicsrOpcode::CSRRC | ZicsrOpcode::CSRRCI) => { - if (write_to_csr_value >> 3) & 0x1 == 1 { - self.senv_sse = false; - } - } - _ => unreachable!(), - } - } - } -} diff --git a/hikami_core/src/trap.rs b/hikami_core/src/trap.rs index 3a80d33..b1fbde9 100644 --- a/hikami_core/src/trap.rs +++ b/hikami_core/src/trap.rs @@ -1,15 +1,9 @@ -//! Trap VS-mode exception / interrupt. - -mod exception; -mod interrupt; +//! Trap VS-mode exception. use crate::guest::context::ContextData; -use exception::trap_exception; -use interrupt::trap_interrupt; use crate::HYPERVISOR_DATA; use core::arch::asm; -use riscv::register::scause::{self, Trap}; /// Switch to original mode stack and save contexts. /// @@ -28,8 +22,9 @@ pub unsafe fn hstrap_exit() -> ! { // release HYPERVISOR_DATA lock drop(hypervisor_data); - asm!( - ".align 4 + unsafe { + asm!( + ".align 4 fence.i // set to stack top @@ -82,85 +77,9 @@ pub unsafe fn hstrap_exit() -> ! { sret ", - HS_CONTEXT_SIZE = const size_of::(), - stack_top = in(reg) stack_top.raw(), - options(noreturn) - ); -} - -/// Trap vector for HS-mode. -/// Switch to hypervisor stack and save contexts. -/// -/// ## `fn_align` -/// function alignment (feature `fn_align`). -/// See: [https://github.com/rust-lang/rust/issues/82232](https://github.com/rust-lang/rust/issues/82232). -/// ```no_run -/// #[repr(align(4))] -/// pub unsafe extern "C" fn hstrap_vector() -> ! { } -/// ``` -#[unsafe(no_mangle)] -#[inline(never)] -pub extern "C" fn hstrap_vector() -> ! { - unsafe { - asm!( - ".align 4 - fence.i - - // swap original mode sp for HS-mode sp - csrrw sp, sscratch, sp - addi sp, sp, -{HS_CONTEXT_SIZE} - - // save registers - sd ra, 1*8(sp) - sd gp, 3*8(sp) - sd tp, 4*8(sp) - sd t0, 5*8(sp) - sd t1, 6*8(sp) - sd t2, 7*8(sp) - sd s0, 8*8(sp) - sd s1, 9*8(sp) - sd a0, 10*8(sp) - sd a1, 11*8(sp) - sd a2, 12*8(sp) - sd a3, 13*8(sp) - sd a4, 14*8(sp) - sd a5, 15*8(sp) - sd a6, 16*8(sp) - sd a7, 17*8(sp) - sd s2, 18*8(sp) - sd s3, 19*8(sp) - sd s4, 20*8(sp) - sd s5, 21*8(sp) - sd s6, 22*8(sp) - sd s7, 23*8(sp) - sd s8, 24*8(sp) - sd s9, 25*8(sp) - sd s10, 26*8(sp) - sd s11, 27*8(sp) - sd t3, 28*8(sp) - sd t4, 29*8(sp) - sd t5, 30*8(sp) - sd t6, 31*8(sp) - - // save sstatus - csrr t0, sstatus - sd t0, 32*8(sp) - - // save pc - csrr t1, sepc - sd t1, 33*8(sp) - ", HS_CONTEXT_SIZE = const size_of::(), + stack_top = in(reg) stack_top.raw(), + options(noreturn) ); } - - hstrap_vector2(); -} - -/// Separated from `hsrap_vector` by stack pointer circumstance. -pub extern "C" fn hstrap_vector2() -> ! { - match scause::read().cause() { - Trap::Interrupt(interrupt_cause) => trap_interrupt(interrupt_cause), - Trap::Exception(exception_cause) => trap_exception(exception_cause), - } } diff --git a/src/hypervisor_init.rs b/src/hypervisor_init.rs index 690d862..9af748e 100644 --- a/src/hypervisor_init.rs +++ b/src/hypervisor_init.rs @@ -1,7 +1,7 @@ //! HS-mode level initialization. +use crate::trap::hstrap_vector; use crate::ALLOCATOR; -use hikami_core::emulate_extension; use hikami_core::guest::context::ContextData; use hikami_core::guest::Guest; use hikami_core::h_extension::csrs::{ @@ -13,7 +13,6 @@ use hikami_core::memmap::{ constant::guest_memory, page_table::sv39x4::ROOT_PAGE_TABLE, GuestPhysicalAddress, HostPhysicalAddress, }; -use hikami_core::trap::hstrap_vector; use hikami_core::{HypervisorData, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL, HYPERVISOR_DATA}; use hikami_core::{_hv_heap_size, _start_heap}; diff --git a/src/main.rs b/src/main.rs index 60396b3..0f4e4e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ #![allow(static_mut_refs)] mod hypervisor_init; +mod trap; use core::arch::naked_asm; use core::panic::PanicInfo; diff --git a/src/trap.rs b/src/trap.rs new file mode 100644 index 0000000..3ad88f6 --- /dev/null +++ b/src/trap.rs @@ -0,0 +1,167 @@ +//! Trap VS-mode exception / interrupt. + +mod exception; +mod interrupt; + +use exception::trap_exception; +use interrupt::trap_interrupt; + +use hikami_core::guest::context::ContextData; +use hikami_core::HYPERVISOR_DATA; + +use core::arch::asm; +use riscv::register::scause::{self, Trap}; + +/// Switch to original mode stack and save contexts. +/// +/// # Panics +/// Panics if `hypervisor_data.get().unwrap()` is called on a `None` value. +/// This typically occurs if the hypervisor data has not been initialized. +/// +/// # Safety +/// Drop all global variables. +#[inline(always)] +#[allow(clippy::inline_always)] +pub unsafe fn hstrap_exit() -> ! { + // aquire hypervisor data + let hypervisor_data = unsafe { HYPERVISOR_DATA.lock() }; + let stack_top = hypervisor_data.get().unwrap().guest().stack_top(); + // release HYPERVISOR_DATA lock + drop(hypervisor_data); + + asm!( + ".align 4 + fence.i + + // set to stack top + mv sp, {stack_top} + addi sp, sp, -{HS_CONTEXT_SIZE} + + // restore sstatus + ld t0, 32*8(sp) + csrw sstatus, t0 + + // restore pc + ld t1, 33*8(sp) + csrw sepc, t1 + + // restore registers + ld ra, 1*8(sp) + ld gp, 3*8(sp) + ld tp, 4*8(sp) + ld t0, 5*8(sp) + ld t1, 6*8(sp) + ld t2, 7*8(sp) + ld s0, 8*8(sp) + ld s1, 9*8(sp) + ld a0, 10*8(sp) + ld a1, 11*8(sp) + ld a2, 12*8(sp) + ld a3, 13*8(sp) + ld a4, 14*8(sp) + ld a5, 15*8(sp) + ld a6, 16*8(sp) + ld a7, 17*8(sp) + ld s2, 18*8(sp) + ld s3, 19*8(sp) + ld s4, 20*8(sp) + ld s5, 21*8(sp) + ld s6, 22*8(sp) + ld s7, 23*8(sp) + ld s8, 24*8(sp) + ld s9, 25*8(sp) + ld s10, 26*8(sp) + ld s11, 27*8(sp) + ld t3, 28*8(sp) + ld t4, 29*8(sp) + ld t5, 30*8(sp) + ld t6, 31*8(sp) + + // swap HS-mode sp for original mode sp. + addi sp, sp, {HS_CONTEXT_SIZE} + csrrw sp, sscratch, sp + + sret + ", + HS_CONTEXT_SIZE = const size_of::(), + stack_top = in(reg) stack_top.raw(), + options(noreturn) + ); +} + +/// Trap vector for HS-mode. +/// Switch to hypervisor stack and save contexts. +/// +/// ## `fn_align` +/// function alignment (feature `fn_align`). +/// See: [https://github.com/rust-lang/rust/issues/82232](https://github.com/rust-lang/rust/issues/82232). +/// ```no_run +/// #[repr(align(4))] +/// pub unsafe extern "C" fn hstrap_vector() -> ! { } +/// ``` +#[unsafe(no_mangle)] +#[inline(never)] +pub extern "C" fn hstrap_vector() -> ! { + unsafe { + asm!( + ".align 4 + fence.i + + // swap original mode sp for HS-mode sp + csrrw sp, sscratch, sp + addi sp, sp, -{HS_CONTEXT_SIZE} + + // save registers + sd ra, 1*8(sp) + sd gp, 3*8(sp) + sd tp, 4*8(sp) + sd t0, 5*8(sp) + sd t1, 6*8(sp) + sd t2, 7*8(sp) + sd s0, 8*8(sp) + sd s1, 9*8(sp) + sd a0, 10*8(sp) + sd a1, 11*8(sp) + sd a2, 12*8(sp) + sd a3, 13*8(sp) + sd a4, 14*8(sp) + sd a5, 15*8(sp) + sd a6, 16*8(sp) + sd a7, 17*8(sp) + sd s2, 18*8(sp) + sd s3, 19*8(sp) + sd s4, 20*8(sp) + sd s5, 21*8(sp) + sd s6, 22*8(sp) + sd s7, 23*8(sp) + sd s8, 24*8(sp) + sd s9, 25*8(sp) + sd s10, 26*8(sp) + sd s11, 27*8(sp) + sd t3, 28*8(sp) + sd t4, 29*8(sp) + sd t5, 30*8(sp) + sd t6, 31*8(sp) + + // save sstatus + csrr t0, sstatus + sd t0, 32*8(sp) + + // save pc + csrr t1, sepc + sd t1, 33*8(sp) + ", + HS_CONTEXT_SIZE = const size_of::(), + ); + } + + hstrap_vector2(); +} + +/// Separated from `hsrap_vector` by stack pointer circumstance. +pub extern "C" fn hstrap_vector2() -> ! { + match scause::read().cause() { + Trap::Interrupt(interrupt_cause) => trap_interrupt(interrupt_cause), + Trap::Exception(exception_cause) => trap_exception(exception_cause), + } +} diff --git a/hikami_core/src/trap/exception.rs b/src/trap/exception.rs similarity index 97% rename from hikami_core/src/trap/exception.rs rename to src/trap/exception.rs index 97afba6..8fcc258 100644 --- a/hikami_core/src/trap/exception.rs +++ b/src/trap/exception.rs @@ -5,19 +5,19 @@ mod page_fault_handler; mod sbi_handler; use super::hstrap_exit; -use crate::guest; -use crate::h_extension::{ +use hikami_core::guest; +use hikami_core::h_extension::{ csrs::{htval, vstvec}, HvException, }; -use crate::HYPERVISOR_DATA; -use sbi_handler::sbi_call; +use hikami_core::HYPERVISOR_DATA; use core::arch::asm; use riscv::register::{ scause::{self, Exception}, stval, }; +use sbi_handler::sbi_call; use sbi_handler::{ sbi_base_handler, sbi_fwft_handler, sbi_pmu_handler, sbi_rfnc_handler, sbi_time_handler, }; diff --git a/hikami_core/src/trap/exception/instruction_handler.rs b/src/trap/exception/instruction_handler.rs similarity index 98% rename from hikami_core/src/trap/exception/instruction_handler.rs rename to src/trap/exception/instruction_handler.rs index 6271409..7ae0014 100644 --- a/hikami_core/src/trap/exception/instruction_handler.rs +++ b/src/trap/exception/instruction_handler.rs @@ -6,7 +6,7 @@ use super::hs_forward_exception; use crate::emulate_extension::zicfiss::ZICFISS_DATA; use crate::emulate_extension::EmulateExtension; -use crate::HYPERVISOR_DATA; +use hikami_core::HYPERVISOR_DATA; use core::arch::asm; use raki::{Instruction, OpcodeKind}; diff --git a/hikami_core/src/trap/exception/page_fault_handler.rs b/src/trap/exception/page_fault_handler.rs similarity index 95% rename from hikami_core/src/trap/exception/page_fault_handler.rs rename to src/trap/exception/page_fault_handler.rs index 361b4d4..795a4aa 100644 --- a/hikami_core/src/trap/exception/page_fault_handler.rs +++ b/src/trap/exception/page_fault_handler.rs @@ -4,11 +4,11 @@ //! - Store AMO guest page fault use super::{hs_forward_exception, update_sepc_by_inst_type}; -use crate::device::EmulateDevice; -use crate::h_extension::csrs::{htinst, htval}; -use crate::memmap::page_table::{g_stage_trans_addr, vs_stage_trans_addr}; -use crate::memmap::{GuestPhysicalAddress, GuestVirtualAddress, HostPhysicalAddress}; -use crate::HYPERVISOR_DATA; +use hikami_core::device::EmulateDevice; +use hikami_core::h_extension::csrs::{htinst, htval}; +use hikami_core::memmap::page_table::{g_stage_trans_addr, vs_stage_trans_addr}; +use hikami_core::memmap::{GuestPhysicalAddress, GuestVirtualAddress, HostPhysicalAddress}; +use hikami_core::HYPERVISOR_DATA; use raki::Instruction; use riscv::register::sepc; diff --git a/hikami_core/src/trap/exception/sbi_handler.rs b/src/trap/exception/sbi_handler.rs similarity index 99% rename from hikami_core/src/trap/exception/sbi_handler.rs rename to src/trap/exception/sbi_handler.rs index 7ef237c..17cc825 100644 --- a/hikami_core/src/trap/exception/sbi_handler.rs +++ b/src/trap/exception/sbi_handler.rs @@ -1,7 +1,7 @@ //! Handle VS-mode Ecall exception //! See [https://github.com/riscv-non-isa/riscv-sbi-doc/releases/download/v2.0/riscv-sbi.pdf](https://github.com/riscv-non-isa/riscv-sbi-doc/releases/download/v2.0/riscv-sbi.pdf) -use crate::h_extension::csrs::{hvip, VsInterruptKind}; +use hikami_core::h_extension::csrs::{hvip, VsInterruptKind}; use riscv::register::sie; use sbi_rt::SbiRet; diff --git a/hikami_core/src/trap/interrupt.rs b/src/trap/interrupt.rs similarity index 90% rename from hikami_core/src/trap/interrupt.rs rename to src/trap/interrupt.rs index 5f1ccfe..8f2955f 100644 --- a/hikami_core/src/trap/interrupt.rs +++ b/src/trap/interrupt.rs @@ -1,9 +1,9 @@ //! Trap VS-mode interrupt. use super::hstrap_exit; -use crate::device::plic::ContextId; -use crate::h_extension::csrs::{hvip, VsInterruptKind}; -use crate::HYPERVISOR_DATA; +use hikami_core::device::plic::ContextId; +use hikami_core::h_extension::csrs::{hvip, VsInterruptKind}; +use hikami_core::HYPERVISOR_DATA; use riscv::register::scause::Interrupt; use riscv::register::sie; From 1f001e60bdbd0310e6dc2ff283abbbb6be0807cd Mon Sep 17 00:00:00 2001 From: Alingof Date: Thu, 12 Jun 2025 23:43:00 +0900 Subject: [PATCH 27/58] [update] make `enable_extension` enable as default --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 82f5770..93ef45a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,8 @@ spin = "0.9.8" debug_log = [] # identity memory map identity_map = [] +# default on +default = [ "enable_extension" ] # for `extension_manager` enable_extension = [ "hikami_zicfiss" ] From 59b8f8e83d7912e8ff650e9d7540845e7369fc1f Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 15 Jun 2025 22:28:36 +0900 Subject: [PATCH 28/58] [fix] fix extension macros --- extension_manager/src/lib.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index e3d55a6..9207c26 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -16,7 +16,10 @@ include!(concat!(env!("OUT_DIR"), "/dependencies.rs")); #[proc_macro] pub fn import_global_variables(_input: TokenStream) -> TokenStream { let calls = CRATES.iter().map(|crate_name| { - let global_var_name = format!("{}_DATA", crate_name.to_uppercase()); + let ext_name = crate_name + .strip_prefix("hikami_") + .expect("Crate name should start with 'hikami_'"); + let global_var_name = format!("{}_DATA", ext_name.to_uppercase()); let crate_ident = Ident::new(crate_name, Span::call_site()); let global_var_ident = Ident::new(&global_var_name, Span::call_site()); @@ -37,13 +40,16 @@ pub fn import_global_variables(_input: TokenStream) -> TokenStream { #[proc_macro] pub fn initialize(_input: TokenStream) -> TokenStream { let calls = CRATES.iter().map(|crate_name| { - // crate name format: hikami_module-name - let mut struct_name_chars = crate_name.chars(); + let ext_name = crate_name + .strip_prefix("hikami_") + .expect("Crate name should start with 'hikami_'"); + // crate name format: hikami_extension-name + let mut struct_name_chars = ext_name.chars(); let struct_name = match struct_name_chars.next() { None => String::new(), Some(c) => c.to_uppercase().collect::() + struct_name_chars.as_str(), }; - let global_var_name = format!("{}_DATA", crate_name.to_uppercase()); + let global_var_name = format!("{}_DATA", ext_name.to_uppercase()); let crate_ident = Ident::new(crate_name, Span::call_site()); let struct_ident = Ident::new(&struct_name, Span::call_site()); From 921ac5139a56f38ebccedd6bb76dbe2b5bbb3142 Mon Sep 17 00:00:00 2001 From: Alingof Date: Fri, 20 Jun 2025 01:07:34 +0900 Subject: [PATCH 29/58] [update] use `extension_manager::import_global_variables` --- src/trap/exception/instruction_handler.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/trap/exception/instruction_handler.rs b/src/trap/exception/instruction_handler.rs index 7ae0014..a595999 100644 --- a/src/trap/exception/instruction_handler.rs +++ b/src/trap/exception/instruction_handler.rs @@ -4,14 +4,15 @@ //! - Virtual Instruction use super::hs_forward_exception; -use crate::emulate_extension::zicfiss::ZICFISS_DATA; -use crate::emulate_extension::EmulateExtension; +use hikami_core::emulate_extension::EmulateExtension; use hikami_core::HYPERVISOR_DATA; use core::arch::asm; use raki::{Instruction, OpcodeKind}; use riscv::register::{sepc, stval}; +extension_manager::import_global_variables!(); + /// Trap `Illegal instruction` exception. #[inline] pub fn illegal_instruction() { From 8712448bb2502f14bba3b01a8dfa18bd07984f19 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 1 Jul 2025 22:53:59 +0900 Subject: [PATCH 30/58] [add] add `handle_illegal_inst` --- extension_manager/src/lib.rs | 21 +++++++++++++++++++++ src/trap/exception/instruction_handler.rs | 21 +-------------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index 9207c26..937765b 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -12,6 +12,27 @@ use syn::Ident; include!(concat!(env!("OUT_DIR"), "/dependencies.rs")); +/// Handle all illegal instruction. +#[proc_macro] +pub fn handle_illegal_inst(_input: TokenStream) -> TokenStream { + let inst_arms = generate_instruction_arms(); + let expanded = quote! { + match fault_inst.opc { + #(#inst_arms)* + OpcodeKind::Zicsr(_) => { + let rs2 = fault_inst.rs2.unwrap(); + unimplemented!("unsupported CSRs: {rs2:#x}"); + } + _ => hs_forward_exception(), + } + + let mut context = unsafe { HYPERVISOR_DATA.lock().get().unwrap().guest().context }; + context.update_sepc_by_inst(&fault_inst); + }; + + TokenStream::from(expanded) +} + /// Import all global varables. #[proc_macro] pub fn import_global_variables(_input: TokenStream) -> TokenStream { diff --git a/src/trap/exception/instruction_handler.rs b/src/trap/exception/instruction_handler.rs index a595999..19db4a6 100644 --- a/src/trap/exception/instruction_handler.rs +++ b/src/trap/exception/instruction_handler.rs @@ -22,26 +22,7 @@ pub fn illegal_instruction() { }); // emulate the instruction - match fault_inst.opc { - OpcodeKind::Zicfiss(_) => unsafe { ZICFISS_DATA.lock() } - .get_mut() - .unwrap() - .instruction(&fault_inst), - OpcodeKind::Zicsr(_) => match fault_inst.rs2.unwrap() { - // ssp - 0x11 => unsafe { ZICFISS_DATA.lock() } - .get_mut() - .unwrap() - .csr(&fault_inst), - unsupported_csr_num => { - unimplemented!("unsupported CSRs: {unsupported_csr_num:#x}") - } - }, - _ => hs_forward_exception(), - } - - let mut context = unsafe { HYPERVISOR_DATA.lock().get().unwrap().guest().context }; - context.update_sepc_by_inst(&fault_inst); + extension_manager::handle_illegal_inst!(); } /// Trap `Virtual instruction` exception. From 38170d64b25a0d85624e53edd5d6f8f4f803531a Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 1 Jul 2025 22:55:27 +0900 Subject: [PATCH 31/58] [add] add `generate_instruction_arms` --- extension_manager/src/lib.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index 937765b..c858da1 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -33,6 +33,31 @@ pub fn handle_illegal_inst(_input: TokenStream) -> TokenStream { TokenStream::from(expanded) } +/// Genrate all `EmulateExtension::instruction` arm from extension crate lists. +fn generate_instruction_arms() -> impl Iterator { + CRATES.iter().map(|crate_name| { + let ext_name = crate_name + .strip_prefix("hikami_") + .expect("Crate name should start with 'hikami_'"); + let global_var_name = format!("{}_DATA", ext_name.to_uppercase()); + + let mut variant_name_chars = ext_name.chars(); + let variant_name = match variant_name_chars.next() { + None => String::new(), + Some(c) => c.to_uppercase().collect::() + variant_name_chars.as_str(), + }; + let variant_ident = Ident::new(&variant_name, Span::call_site()); + let global_var_ident = Ident::new(&global_var_name, Span::call_site()); + + quote! { + OpcodeKind::#variant_ident(_) => unsafe { #global_var_ident.lock() } + .get_mut() + .unwrap() + .instruction(&fault_inst), + } + }) +} + /// Import all global varables. #[proc_macro] pub fn import_global_variables(_input: TokenStream) -> TokenStream { From 0a7e6eb264145b57cc642e2e155c8127db3e0c71 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 2 Jul 2025 00:54:32 +0900 Subject: [PATCH 32/58] [add] add `generate_csr_arms` --- extension_manager/src/lib.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index c858da1..fb25521 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -16,6 +16,7 @@ include!(concat!(env!("OUT_DIR"), "/dependencies.rs")); #[proc_macro] pub fn handle_illegal_inst(_input: TokenStream) -> TokenStream { let inst_arms = generate_instruction_arms(); + let csr_arms = generate_csr_arms(); let expanded = quote! { match fault_inst.opc { #(#inst_arms)* @@ -33,6 +34,31 @@ pub fn handle_illegal_inst(_input: TokenStream) -> TokenStream { TokenStream::from(expanded) } +/// Expand all `EmulateExtension::csr`. +fn generate_csr_arms() -> impl Iterator { + CRATES.iter().map(|crate_name| { + let ext_name = crate_name + .strip_prefix("hikami_") + .expect("Crate name should start with 'hikami_'"); + let global_var_name = format!("{}_DATA", ext_name.to_uppercase()); + let global_var_ident = Ident::new(&global_var_name, Span::call_site()); + + quote! { + if unsafe { #global_var_ident.lock().get().unwrap().is_csr_defined(rs2) } { + unsafe { #global_var_ident.lock() } + .get_mut() + .unwrap() + .csr(&fault_inst); + + let mut context = unsafe { HYPERVISOR_DATA.lock().get().unwrap().guest().context }; + context.update_sepc_by_inst(&fault_inst); + + return; + } + } + }) +} + /// Genrate all `EmulateExtension::instruction` arm from extension crate lists. fn generate_instruction_arms() -> impl Iterator { CRATES.iter().map(|crate_name| { From ca85ea8f662d6cc68b55571bd131ab4bd5c05c2e Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 2 Jul 2025 14:24:48 +0900 Subject: [PATCH 33/58] [add] add `is_csr_defined` to `EmulateExtension` --- extension_manager/src/lib.rs | 3 ++- hikami_core/src/emulate_extension.rs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index fb25521..906f472 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -21,7 +21,8 @@ pub fn handle_illegal_inst(_input: TokenStream) -> TokenStream { match fault_inst.opc { #(#inst_arms)* OpcodeKind::Zicsr(_) => { - let rs2 = fault_inst.rs2.unwrap(); + let rs2 = fault_inst.rs2.unwrap() as u16; + #(#csr_arms)* unimplemented!("unsupported CSRs: {rs2:#x}"); } _ => hs_forward_exception(), diff --git a/hikami_core/src/emulate_extension.rs b/hikami_core/src/emulate_extension.rs index c319858..d146d38 100644 --- a/hikami_core/src/emulate_extension.rs +++ b/hikami_core/src/emulate_extension.rs @@ -16,6 +16,8 @@ pub trait EmulateExtension { fn csr(&mut self, inst: &Instruction); /// Emulate CSR field that already exists. fn csr_field(&mut self, inst: &Instruction, write_to_csr_value: u64, read_csr_value: &mut u64); + /// Return whether given csr value defined in the extension. + fn is_csr_defined(&self, csr_num: u16) -> bool; } /// Holding a CSR value for CSRs emulation. From 26d6106aac24c6ebbff7c8e8057a5275d34f8aee Mon Sep 17 00:00:00 2001 From: Alingof Date: Thu, 3 Jul 2025 00:58:26 +0900 Subject: [PATCH 34/58] [add] add `handle_virtual_inst` and `generate_csr_field_arms` --- extension_manager/src/lib.rs | 50 +++++++++++++++++++++-- src/trap/exception/instruction_handler.rs | 41 +------------------ 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index 906f472..54d0803 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -12,7 +12,49 @@ use syn::Ident; include!(concat!(env!("OUT_DIR"), "/dependencies.rs")); -/// Handle all illegal instruction. +/// Handle all virtual instruction exception. +#[proc_macro] +pub fn handle_virtual_inst(_input: TokenStream) -> TokenStream { + let csr_field_arms = generate_csr_field_arms(); + let expanded = quote! { + match fault_inst.opc { + OpcodeKind::Zicsr(_) => { + let csr_num = fault_inst.rs2.unwrap() as u16; + #(#csr_field_arms)* + } + _ => unreachable!(), + } + }; + + TokenStream::from(expanded) +} + +/// Expand all `EmulateExtension::csr_field`. +fn generate_csr_field_arms() -> impl Iterator { + CRATES.iter().map(|crate_name| { + let ext_name = crate_name + .strip_prefix("hikami_") + .expect("Crate name should start with 'hikami_'"); + let global_var_name = format!("{}_DATA", ext_name.to_uppercase()); + let global_var_ident = Ident::new(&global_var_name, Span::call_site()); + + quote! { + if unsafe { #global_var_ident.lock().get().unwrap().is_csr_field_defined(csr_num) } { + // update emulated CSR field. + unsafe { ZICFISS_DATA.lock() }.get_mut().unwrap().csr_field( + &fault_inst, + ); + + let mut context = unsafe { HYPERVISOR_DATA.lock().get().unwrap().guest().context }; + context.update_sepc_by_inst(&fault_inst); + + return; + } + } + }) +} + +/// Handle all illegal instruction exception. #[proc_macro] pub fn handle_illegal_inst(_input: TokenStream) -> TokenStream { let inst_arms = generate_instruction_arms(); @@ -21,9 +63,9 @@ pub fn handle_illegal_inst(_input: TokenStream) -> TokenStream { match fault_inst.opc { #(#inst_arms)* OpcodeKind::Zicsr(_) => { - let rs2 = fault_inst.rs2.unwrap() as u16; + let csr_num = fault_inst.rs2.unwrap() as u16; #(#csr_arms)* - unimplemented!("unsupported CSRs: {rs2:#x}"); + unimplemented!("unsupported CSRs: {csr_num:#x}"); } _ => hs_forward_exception(), } @@ -45,7 +87,7 @@ fn generate_csr_arms() -> impl Iterator { let global_var_ident = Ident::new(&global_var_name, Span::call_site()); quote! { - if unsafe { #global_var_ident.lock().get().unwrap().is_csr_defined(rs2) } { + if unsafe { #global_var_ident.lock().get().unwrap().is_csr_defined(csr_num) } { unsafe { #global_var_ident.lock() } .get_mut() .unwrap() diff --git a/src/trap/exception/instruction_handler.rs b/src/trap/exception/instruction_handler.rs index 19db4a6..47be0c0 100644 --- a/src/trap/exception/instruction_handler.rs +++ b/src/trap/exception/instruction_handler.rs @@ -7,7 +7,6 @@ use super::hs_forward_exception; use hikami_core::emulate_extension::EmulateExtension; use hikami_core::HYPERVISOR_DATA; -use core::arch::asm; use raki::{Instruction, OpcodeKind}; use riscv::register::{sepc, stval}; @@ -32,45 +31,7 @@ pub fn virtual_instruction() { let fault_inst = Instruction::try_from(fault_inst_value).unwrap_or_else(|_| { panic!("decoding load fault instruction failed: fault inst value: {fault_inst_value:#x} at {:#x}", sepc::read()); }); - let mut context = unsafe { HYPERVISOR_DATA.lock() } - .get() - .unwrap() - .guest() - .context; // emulate CSR set - match fault_inst.opc { - OpcodeKind::Zicsr(_) => { - match fault_inst.rs2.unwrap() { - // senvcfg - 0x10a => { - let mut read_from_csr_value: u64; - unsafe { - asm!("csrr {0}, senvcfg", out(reg) read_from_csr_value); - } - - let write_to_csr_value = context.xreg(fault_inst.rs1.unwrap()); - - // update emulated CSR field. - unsafe { ZICFISS_DATA.lock() }.get_mut().unwrap().csr_field( - &fault_inst, - write_to_csr_value, - &mut read_from_csr_value, - ); - - // commit result - unsafe { - asm!("csrw senvcfg, {0}", in(reg) write_to_csr_value); - } - context.set_xreg(fault_inst.rd.unwrap(), read_from_csr_value); - } - unsupported_csr_num => { - unimplemented!("unsupported CSRs: {unsupported_csr_num:#x}") - } - } - } - _ => unreachable!(), - } - - context.update_sepc_by_inst(&fault_inst); + extension_manager::handle_virtual_inst!(); } From a6a60def7af18278ea08827b205f34dd26572b81 Mon Sep 17 00:00:00 2001 From: Alingof Date: Thu, 3 Jul 2025 01:00:11 +0900 Subject: [PATCH 35/58] [add] add `is_csr_field_defined` to `EmulateExtension` --- hikami_core/src/emulate_extension.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hikami_core/src/emulate_extension.rs b/hikami_core/src/emulate_extension.rs index d146d38..d0b8074 100644 --- a/hikami_core/src/emulate_extension.rs +++ b/hikami_core/src/emulate_extension.rs @@ -18,6 +18,8 @@ pub trait EmulateExtension { fn csr_field(&mut self, inst: &Instruction, write_to_csr_value: u64, read_csr_value: &mut u64); /// Return whether given csr value defined in the extension. fn is_csr_defined(&self, csr_num: u16) -> bool; + /// Return whether given csr value has newly defined field. + fn is_csr_field_defined(&self, csr_num: u16) -> bool; } /// Holding a CSR value for CSRs emulation. From 9de1cbfd0af16daaf5969c2d6d243e640330faa7 Mon Sep 17 00:00:00 2001 From: Alingof Date: Thu, 3 Jul 2025 01:00:46 +0900 Subject: [PATCH 36/58] [update] change arguments of `EmulateExtension::csr_field` --- hikami_core/src/emulate_extension.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hikami_core/src/emulate_extension.rs b/hikami_core/src/emulate_extension.rs index d0b8074..56fc91e 100644 --- a/hikami_core/src/emulate_extension.rs +++ b/hikami_core/src/emulate_extension.rs @@ -15,8 +15,8 @@ pub trait EmulateExtension { /// Emulate CSR fn csr(&mut self, inst: &Instruction); /// Emulate CSR field that already exists. - fn csr_field(&mut self, inst: &Instruction, write_to_csr_value: u64, read_csr_value: &mut u64); - /// Return whether given csr value defined in the extension. + fn csr_field(&mut self, inst: &Instruction); + /// Return whether given csr value is defined in the extension. fn is_csr_defined(&self, csr_num: u16) -> bool; /// Return whether given csr value has newly defined field. fn is_csr_field_defined(&self, csr_num: u16) -> bool; From 972498c505261501c3363d359e954b0109dd500a Mon Sep 17 00:00:00 2001 From: Alingof Date: Fri, 4 Jul 2025 02:25:21 +0900 Subject: [PATCH 37/58] [refactor] apply cargo fix and cargo fmt --- hikami_core/src/device.rs | 4 +- hikami_core/src/device/pci.rs | 2 +- hikami_core/src/device/pci/iommu.rs | 6 +- hikami_core/src/device/pci/sata.rs | 4 +- hikami_core/src/device/pci/sata/command.rs | 2 +- hikami_core/src/device/plic.rs | 2 +- hikami_core/src/emulate_extension.rs | 2 +- hikami_core/src/guest.rs | 73 +++++++++------------ hikami_core/src/h_extension/csrs.rs | 20 +++--- hikami_core/src/lib.rs | 2 +- hikami_core/src/memmap/page_table/sv39.rs | 2 +- hikami_core/src/memmap/page_table/sv39x4.rs | 2 +- hikami_core/src/memmap/page_table/sv57.rs | 2 +- 13 files changed, 57 insertions(+), 66 deletions(-) diff --git a/hikami_core/src/device.rs b/hikami_core/src/device.rs index 378ae85..1a47e59 100644 --- a/hikami_core/src/device.rs +++ b/hikami_core/src/device.rs @@ -9,8 +9,8 @@ mod rtc; pub mod uart; mod virtio; -use crate::memmap::page_table::{constants::PAGE_SIZE, g_stage_trans_addr, PteFlag}; -use crate::memmap::{page_table, GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; +use crate::memmap::page_table::{PteFlag, constants::PAGE_SIZE, g_stage_trans_addr}; +use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap, page_table}; use alloc::vec::Vec; use fdt::Fdt; diff --git a/hikami_core/src/device/pci.rs b/hikami_core/src/device/pci.rs index f8d7e89..7ab144e 100644 --- a/hikami_core/src/device/pci.rs +++ b/hikami_core/src/device/pci.rs @@ -8,7 +8,7 @@ pub mod config_register; use super::{MmioDevice, PTE_FLAGS_FOR_DEVICE}; use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; -use config_register::{read_config_register, ConfigSpaceHeaderField}; +use config_register::{ConfigSpaceHeaderField, read_config_register}; use alloc::vec::Vec; use core::ops::Range; diff --git a/hikami_core/src/device/pci/iommu.rs b/hikami_core/src/device/pci/iommu.rs index 17e639b..9a00f31 100644 --- a/hikami_core/src/device/pci/iommu.rs +++ b/hikami_core/src/device/pci/iommu.rs @@ -4,12 +4,12 @@ mod register_map; use super::config_register::{ - get_bar_size, read_config_register, write_config_register, ConfigSpaceHeaderField, + ConfigSpaceHeaderField, get_bar_size, read_config_register, write_config_register, }; use super::{Bdf, PciAddressSpace, PciDevice}; -use crate::h_extension::csrs::hgatp; -use crate::memmap::{page_table::constants::PAGE_SIZE, HostPhysicalAddress, MemoryMap}; use crate::PageBlock; +use crate::h_extension::csrs::hgatp; +use crate::memmap::{HostPhysicalAddress, MemoryMap, page_table::constants::PAGE_SIZE}; use register_map::{IoMmuMode, IoMmuRegisters}; use alloc::vec::Vec; diff --git a/hikami_core/src/device/pci/sata.rs b/hikami_core/src/device/pci/sata.rs index d920cba..61f5c84 100644 --- a/hikami_core/src/device/pci/sata.rs +++ b/hikami_core/src/device/pci/sata.rs @@ -4,13 +4,13 @@ mod command; -use super::config_register::{get_bar_size, read_config_register, ConfigSpaceHeaderField}; +use super::config_register::{ConfigSpaceHeaderField, get_bar_size, read_config_register}; use super::{Bdf, PciAddressSpace, PciDevice}; use crate::device::DeviceEmulateError; use crate::memmap::page_table::g_stage_trans_addr; use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; use command::{ - CommandHeader, CommandTable, CommandTableGpaStorage, TransferDirection, COMMAND_HEADER_SIZE, + COMMAND_HEADER_SIZE, CommandHeader, CommandTable, CommandTableGpaStorage, TransferDirection, }; use alloc::boxed::Box; diff --git a/hikami_core/src/device/pci/sata/command.rs b/hikami_core/src/device/pci/sata/command.rs index 528df8a..09713ef 100644 --- a/hikami_core/src/device/pci/sata/command.rs +++ b/hikami_core/src/device/pci/sata/command.rs @@ -1,8 +1,8 @@ //! Utility for HBA (= ATA) command. use crate::device::DmaHostBuffer; -use crate::memmap::page_table::{constants::PAGE_SIZE, g_stage_trans_addr}; use crate::memmap::GuestPhysicalAddress; +use crate::memmap::page_table::{constants::PAGE_SIZE, g_stage_trans_addr}; use alloc::vec::Vec; diff --git a/hikami_core/src/device/plic.rs b/hikami_core/src/device/plic.rs index fa5b523..1ee436e 100644 --- a/hikami_core/src/device/plic.rs +++ b/hikami_core/src/device/plic.rs @@ -2,7 +2,7 @@ //! ref: [https://github.com/riscv/riscv-plic-spec/releases/download/1.0.0/riscv-plic-1.0.0.pdf](https://github.com/riscv/riscv-plic-spec/releases/download/1.0.0/riscv-plic-1.0.0.pdf) use super::{DeviceEmulateError, MmioDevice, PTE_FLAGS_FOR_DEVICE}; -use crate::h_extension::csrs::{hvip, VsInterruptKind}; +use crate::h_extension::csrs::{VsInterruptKind, hvip}; use crate::memmap::constant::MAX_HART_NUM; use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; diff --git a/hikami_core/src/emulate_extension.rs b/hikami_core/src/emulate_extension.rs index 56fc91e..5135172 100644 --- a/hikami_core/src/emulate_extension.rs +++ b/hikami_core/src/emulate_extension.rs @@ -1,8 +1,8 @@ //! Extension emulation +use crate::HYPERVISOR_DATA; use crate::h_extension::csrs::vstvec; use crate::trap::hstrap_exit; -use crate::HYPERVISOR_DATA; use core::arch::asm; use raki::Instruction; diff --git a/hikami_core/src/guest.rs b/hikami_core/src/guest.rs index fc43a25..4cb1aec 100644 --- a/hikami_core/src/guest.rs +++ b/hikami_core/src/guest.rs @@ -4,16 +4,16 @@ pub mod context; use crate::memmap::page_table::sv39x4::FIRST_LV_PAGE_TABLE_LEN; use crate::memmap::{ + GuestPhysicalAddress, HostPhysicalAddress, MemoryMap, constant::guest_memory, page_table, - page_table::{constants::PAGE_SIZE, PageTableEntry, PteFlag}, - GuestPhysicalAddress, HostPhysicalAddress, MemoryMap, + page_table::{PageTableEntry, PteFlag, constants::PAGE_SIZE}, }; -use crate::{PageBlock, GUEST_INITRD}; +use crate::{GUEST_INITRD, PageBlock}; use context::{Context, ContextData}; use core::ops::Range; -use elf::{endian::AnyEndian, ElfBytes}; +use elf::{ElfBytes, endian::AnyEndian}; /// Guest Information #[derive(Debug)] @@ -88,15 +88,12 @@ impl Guest { let host_physical_addr = HostPhysicalAddress(guest_physical_addr.raw()); // create memory mapping - page_table::sv39x4::generate_page_table( - page_table_addr, - &[MemoryMap::new( - guest_physical_addr..guest_physical_addr + PAGE_SIZE, - host_physical_addr..host_physical_addr + PAGE_SIZE, - // allow writing data to dtb to modify device tree on guest OS. - &[Dirty, Accessed, Write, Read, User, Valid], - )], - ); + page_table::sv39x4::generate_page_table(page_table_addr, &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + host_physical_addr..host_physical_addr + PAGE_SIZE, + // allow writing data to dtb to modify device tree on guest OS. + &[Dirty, Accessed, Write, Read, User, Valid], + )]); } GuestPhysicalAddress(guest_dtb.as_ptr() as usize) @@ -136,15 +133,12 @@ impl Guest { } // create memory mapping - page_table::sv39x4::generate_page_table( - page_table_addr, - &[MemoryMap::new( - guest_physical_addr..guest_physical_addr + PAGE_SIZE, - aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, - // allow writing data to dtb to modify device tree on guest OS. - &[Dirty, Accessed, Write, Read, User, Valid], - )], - ); + page_table::sv39x4::generate_page_table(page_table_addr, &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, + // allow writing data to dtb to modify device tree on guest OS. + &[Dirty, Accessed, Write, Read, User, Valid], + )]); } guest_dtb_addr @@ -347,9 +341,8 @@ impl Guest { } // create memory mapping - page_table::sv39x4::generate_page_table( - self.page_table_addr, - &[MemoryMap::new( + page_table::sv39x4::generate_page_table(self.page_table_addr, &[ + MemoryMap::new( guest_physical_addr..guest_physical_addr + PAGE_SIZE, aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, match prog_header.p_flags & 0b111 { @@ -364,8 +357,8 @@ impl Guest { 0b111 => &[Dirty, Accessed, Exec, Write, Read, User, Valid], _ => panic!("unsupported flags"), }, - )], - ); + ), + ]); } } } @@ -384,14 +377,11 @@ impl Guest { let guest_physical_addr = GuestPhysicalAddress(guest_physical_addr); let host_physical_addr = HostPhysicalAddress(guest_physical_addr.raw()); // create memory mapping - page_table::sv39x4::generate_page_table( - self.page_table_addr, - &[MemoryMap::new( - guest_physical_addr..guest_physical_addr + PAGE_SIZE, - host_physical_addr..host_physical_addr + PAGE_SIZE, - all_pte_flags_are_set, - )], - ); + page_table::sv39x4::generate_page_table(self.page_table_addr, &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + host_physical_addr..host_physical_addr + PAGE_SIZE, + all_pte_flags_are_set, + )]); } } @@ -431,14 +421,11 @@ impl Guest { } // create memory mapping - page_table::sv39x4::generate_page_table( - self.page_table_addr, - &[MemoryMap::new( - guest_physical_addr..guest_physical_addr + PAGE_SIZE, - aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, - all_pte_flags_are_set, - )], - ); + page_table::sv39x4::generate_page_table(self.page_table_addr, &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, + all_pte_flags_are_set, + )]); } } } diff --git a/hikami_core/src/h_extension/csrs.rs b/hikami_core/src/h_extension/csrs.rs index 2547074..1672efe 100644 --- a/hikami_core/src/h_extension/csrs.rs +++ b/hikami_core/src/h_extension/csrs.rs @@ -128,12 +128,14 @@ pub mod vsip { /// # Safety /// make sure S-mode config. pub unsafe fn set_ssoft() { - core::arch::asm!( - " + unsafe { + core::arch::asm!( + " csrs vsip, {bits} ", - bits = in(reg) 0b0010 - ); + bits = in(reg) 0b0010 + ); + } } /// Set STIP bit (`SupervisorTimerInterruptPending`, 5 bit) @@ -141,12 +143,14 @@ pub mod vsip { /// # Safety /// make sure S-mode config. pub unsafe fn set_stimer() { - core::arch::asm!( - " + unsafe { + core::arch::asm!( + " csrs vsip, {bits} ", - bits = in(reg) 0b0010_0000 - ); + bits = in(reg) 0b0010_0000 + ); + } } } diff --git a/hikami_core/src/lib.rs b/hikami_core/src/lib.rs index 93ee137..f3d48e2 100644 --- a/hikami_core/src/lib.rs +++ b/hikami_core/src/lib.rs @@ -19,8 +19,8 @@ use core::cell::OnceCell; use device::Devices; use guest::Guest; -use memmap::constant::MAX_HART_NUM; use memmap::HostPhysicalAddress; +use memmap::constant::MAX_HART_NUM; use fdt::Fdt; use spin::Mutex; diff --git a/hikami_core/src/memmap/page_table/sv39.rs b/hikami_core/src/memmap/page_table/sv39.rs index cf9e228..0108131 100644 --- a/hikami_core/src/memmap/page_table/sv39.rs +++ b/hikami_core/src/memmap/page_table/sv39.rs @@ -1,8 +1,8 @@ //! Sv39: Page-Based 39-bit Virtual-Memory System use super::{ - constants::{PAGE_SIZE, PAGE_TABLE_LEN}, PageTableAddress, PageTableEntry, PageTableLevel, TransAddrError, + constants::{PAGE_SIZE, PAGE_TABLE_LEN}, }; use crate::h_extension::csrs::vsatp; use crate::memmap::{GuestPhysicalAddress, GuestVirtualAddress}; diff --git a/hikami_core/src/memmap/page_table/sv39x4.rs b/hikami_core/src/memmap/page_table/sv39x4.rs index e731763..d662bfe 100644 --- a/hikami_core/src/memmap/page_table/sv39x4.rs +++ b/hikami_core/src/memmap/page_table/sv39x4.rs @@ -4,8 +4,8 @@ //! [The RISC-V Instruction Set Manual: Volume II Version 20240411](https://github.com/riscv/riscv-isa-manual/releases/download/20240411/priv-isa-asciidoc.pdf) p.151 use super::{ - constants::{PAGE_SIZE, PAGE_TABLE_LEN}, PageTableAddress, PageTableEntry, PageTableLevel, PageTableMemory, PteFlag, TransAddrError, + constants::{PAGE_SIZE, PAGE_TABLE_LEN}, }; use crate::h_extension::csrs::hgatp; use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; diff --git a/hikami_core/src/memmap/page_table/sv57.rs b/hikami_core/src/memmap/page_table/sv57.rs index d48c471..0a734e1 100644 --- a/hikami_core/src/memmap/page_table/sv57.rs +++ b/hikami_core/src/memmap/page_table/sv57.rs @@ -1,8 +1,8 @@ //! Sv57: Page-Based 57-bit Virtual-Memory System use super::{ - constants::{PAGE_SIZE, PAGE_TABLE_LEN}, PageTableAddress, PageTableEntry, PageTableLevel, TransAddrError, + constants::{PAGE_SIZE, PAGE_TABLE_LEN}, }; use crate::h_extension::csrs::vsatp; use crate::memmap::{GuestPhysicalAddress, GuestVirtualAddress}; From 75583dedafdae069b504d8ac760fdca7424fcc9d Mon Sep 17 00:00:00 2001 From: Alingof Date: Fri, 4 Jul 2025 16:19:14 +0900 Subject: [PATCH 38/58] [!][fix] add features to child crate and automatically enable if root featres are enabled --- Cargo.toml | 4 ++-- hikami_core/Cargo.toml | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 93ef45a..cf7254c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,9 +33,9 @@ spin = "0.9.8" [features] # debug log -debug_log = [] +debug_log = [ "hikami_core/debug_log" ] # identity memory map -identity_map = [] +identity_map = [ "hikami_core/identity_map" ] # default on default = [ "enable_extension" ] # for `extension_manager` diff --git a/hikami_core/Cargo.toml b/hikami_core/Cargo.toml index 777402d..5f20079 100644 --- a/hikami_core/Cargo.toml +++ b/hikami_core/Cargo.toml @@ -3,6 +3,12 @@ name = "hikami_core" version = "0.1.0" edition = "2024" +[features] +# debug log +debug_log = [] +# identity memory map +identity_map = [] + [dependencies] elf = { workspace = true } fdt = { workspace = true } From d5ad3d6b1ccfb5b432470893bf9152191f28eb18 Mon Sep 17 00:00:00 2001 From: Alingof Date: Fri, 4 Jul 2025 19:03:16 +0900 Subject: [PATCH 39/58] [!][fix] remove raw variable `ZICFISS_DATA` from code --- extension_manager/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension_manager/src/lib.rs b/extension_manager/src/lib.rs index 54d0803..56b50bb 100644 --- a/extension_manager/src/lib.rs +++ b/extension_manager/src/lib.rs @@ -41,7 +41,7 @@ fn generate_csr_field_arms() -> impl Iterator { quote! { if unsafe { #global_var_ident.lock().get().unwrap().is_csr_field_defined(csr_num) } { // update emulated CSR field. - unsafe { ZICFISS_DATA.lock() }.get_mut().unwrap().csr_field( + unsafe { #global_var_ident.lock() }.get_mut().unwrap().csr_field( &fault_inst, ); From dab0bba4a90d484b65d59847c58ce97cd67cecb7 Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 6 Jul 2025 17:49:54 +0900 Subject: [PATCH 40/58] [update] add example emulation crate `hikami_zbb` --- Cargo.toml | 6 +++--- guest_image/guest.dts | 2 +- memory.x | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cf7254c..0aeb478 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ members = [ "extension_manager" , "hikami_core"] elf = { version = "0.7.2", default-features = false } fdt = "0.1.5" linked_list_allocator = "0.10.5" -raki = "1.3.1" +raki = { git = "https://github.com/Alignof/raki", branch = "feature/Zbb"} riscv = "0.11.1" rustsbi = "0.4.0" sbi-rt = "0.0.3" @@ -39,11 +39,11 @@ identity_map = [ "hikami_core/identity_map" ] # default on default = [ "enable_extension" ] # for `extension_manager` -enable_extension = [ "hikami_zicfiss" ] +enable_extension = [ "hikami_zbb" ] [dependencies] hikami_core = { path = "hikami_core" } -hikami_zicfiss = { path = "../hikami_zicfiss", optional = true } +hikami_zbb = { path = "../hikami_zbb", optional = true } extension_manager = { path = "extension_manager" } elf = { workspace = true } diff --git a/guest_image/guest.dts b/guest_image/guest.dts index 8f46850..cd54fd1 100644 --- a/guest_image/guest.dts +++ b/guest_image/guest.dts @@ -89,7 +89,7 @@ }; chosen { - bootargs = "root=/dev/sda locale.LANG=en_US.UTF-8"; + bootargs = "root=/dev/vda locale.LANG=en_US.UTF-8"; stdout-path = "/soc/serial@10000000"; rng-seed = <0x9775b34d 0xe39158f2 0x3e9d10b1 0x73692dfd 0x13c15814 0xa4ad203f 0x8b0d62f7 0x6bf8a79d>; }; diff --git a/memory.x b/memory.x index a37739e..152cb95 100644 --- a/memory.x +++ b/memory.x @@ -2,9 +2,9 @@ MEMORY { FLASH (rx) : ORIGIN = 0x83000000, LENGTH = 2M BOOT_RAM (rw) : ORIGIN = 0x83200000, LENGTH = 6M - RAM_HEAP (rwx) : ORIGIN = 0x84000000, LENGTH = 128M - RAM (rwx) : ORIGIN = 0x8c000000, LENGTH = 32M - L2_LIM (rw) : ORIGIN = 0x8e000000, LENGTH = 8M + RAM_HEAP (rwx) : ORIGIN = 0x84000000, LENGTH = 384M + RAM (rwx) : ORIGIN = 0x9c000000, LENGTH = 32M + L2_LIM (rw) : ORIGIN = 0x9e000000, LENGTH = 8M } /* @@ -23,7 +23,7 @@ REGION_ALIAS("REGION_HEAP", RAM_HEAP); REGION_ALIAS("REGION_STACK", L2_LIM); _stack_start = ORIGIN(L2_LIM) + LENGTH(L2_LIM); -_hv_heap_size = 0x8000000; +_hv_heap_size = 0x18000000; _b_stack_size = 0x200000; /* defined section in hikami */ From 65fdc0acaf11fcef1ca7baa39f20e60c26eb5a0d Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 6 Jul 2025 18:11:44 +0900 Subject: [PATCH 41/58] [update] add rerun condition to extension_manager/build.rs to watch Cargo.toml --- extension_manager/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extension_manager/build.rs b/extension_manager/build.rs index 08b16df..6ab30c9 100644 --- a/extension_manager/build.rs +++ b/extension_manager/build.rs @@ -5,6 +5,8 @@ use std::path::Path; use std::process::Command; fn main() { + println!("cargo:rerun-if-changed=Cargo.toml"); + // exec `cargo metadata` and get a json. let output = Command::new("cargo") .args(["metadata", "--format-version=1", "--no-deps"]) From 790ae339c728509036eb6899d982f01baa18a0b1 Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 6 Jul 2025 21:36:39 +0900 Subject: [PATCH 42/58] [update] add a description of extension manager --- Cargo.toml | 1 + README.md | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 0aeb478..9bf2300 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ enable_extension = [ "hikami_zbb" ] [dependencies] hikami_core = { path = "hikami_core" } hikami_zbb = { path = "../hikami_zbb", optional = true } +#hikami_zbb = { git = "https://github.com/Alignof/hikami_zbb", branch = "develop", optional = true } extension_manager = { path = "extension_manager" } elf = { workspace = true } diff --git a/README.md b/README.md index 5e3c919..37333a0 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,26 @@ Paper in ComSys2024(ja): [link](https://ipsj.ixsq.nii.ac.jp/records/241051) $ cargo doc --open ``` +## Extension Management +hikami utilizes a procedural macro crate called `extension_manager` to dynamically incorporate RISC-V extension emulations. +This allows for adding or removing extension supports without modifying the core hypervisor code. + +To enable an extension, simply add the extension crate name to the `enable_extension` feature list in the root `Cargo.toml` file. +For example, to enable the `Zbb` extension, you would add `hikami_zbb` as follows: + +```toml +# hikami/Cargo.toml +[dependencies] +hikami_zbb = { git = "https://github.com/Alignof/hikami_zbb", optional = true } +[features] +enable_extension = [ "hikami_zbb" ] +``` + +See also: [https://github.com/Alignof/hikami_zbb](https://github.com/Alignof/hikami_zbb) + +During the build process, extension_manager automatically detects these crates and expands the necessary code to initialize the extension and dispatch instruction handling. +This approach simplifies the management of multiple extensions and enhances the modularity of the hypervisor. + ## Getting Started ### Setup ```sh From 1ac18d28f84576ec9fe1f12b2b8e97b1bd67ff84 Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 6 Jul 2025 21:42:56 +0900 Subject: [PATCH 43/58] [!][update] move `GUEST_KERNEL`, `GUEST_INITRD` and `GUEST_DTB` to hikami/ --- hikami_core/src/guest.rs | 111 ++++++++++++++++++++++++--------------- hikami_core/src/lib.rs | 17 +----- src/hypervisor_init.rs | 9 ++-- src/main.rs | 15 ++++++ 4 files changed, 89 insertions(+), 63 deletions(-) diff --git a/hikami_core/src/guest.rs b/hikami_core/src/guest.rs index 4cb1aec..1bd76a1 100644 --- a/hikami_core/src/guest.rs +++ b/hikami_core/src/guest.rs @@ -4,16 +4,16 @@ pub mod context; use crate::memmap::page_table::sv39x4::FIRST_LV_PAGE_TABLE_LEN; use crate::memmap::{ - GuestPhysicalAddress, HostPhysicalAddress, MemoryMap, constant::guest_memory, page_table, - page_table::{PageTableEntry, PteFlag, constants::PAGE_SIZE}, + page_table::{constants::PAGE_SIZE, PageTableEntry, PteFlag}, + GuestPhysicalAddress, HostPhysicalAddress, MemoryMap, }; -use crate::{GUEST_INITRD, PageBlock}; +use crate::PageBlock; use context::{Context, ContextData}; use core::ops::Range; -use elf::{ElfBytes, endian::AnyEndian}; +use elf::{endian::AnyEndian, ElfBytes}; /// Guest Information #[derive(Debug)] @@ -41,7 +41,7 @@ impl Guest { pub fn new( hart_id: usize, root_page_table: &'static [PageTableEntry; FIRST_LV_PAGE_TABLE_LEN], - guest_dtb: &'static [u8; include_bytes!("../../guest_image/guest.dtb").len()], + guest_dtb: &'static [u8], ) -> Self { // calculate guest memory region let guest_memory_begin: GuestPhysicalAddress = @@ -88,12 +88,15 @@ impl Guest { let host_physical_addr = HostPhysicalAddress(guest_physical_addr.raw()); // create memory mapping - page_table::sv39x4::generate_page_table(page_table_addr, &[MemoryMap::new( - guest_physical_addr..guest_physical_addr + PAGE_SIZE, - host_physical_addr..host_physical_addr + PAGE_SIZE, - // allow writing data to dtb to modify device tree on guest OS. - &[Dirty, Accessed, Write, Read, User, Valid], - )]); + page_table::sv39x4::generate_page_table( + page_table_addr, + &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + host_physical_addr..host_physical_addr + PAGE_SIZE, + // allow writing data to dtb to modify device tree on guest OS. + &[Dirty, Accessed, Write, Read, User, Valid], + )], + ); } GuestPhysicalAddress(guest_dtb.as_ptr() as usize) @@ -106,7 +109,7 @@ impl Guest { fn map_guest_dtb( hart_id: usize, page_table_addr: HostPhysicalAddress, - guest_dtb: &'static [u8; include_bytes!("../../guest_image/guest.dtb").len()], + guest_dtb: &'static [u8], ) -> GuestPhysicalAddress { use PteFlag::{Accessed, Dirty, Read, User, Valid, Write}; @@ -133,12 +136,15 @@ impl Guest { } // create memory mapping - page_table::sv39x4::generate_page_table(page_table_addr, &[MemoryMap::new( - guest_physical_addr..guest_physical_addr + PAGE_SIZE, - aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, - // allow writing data to dtb to modify device tree on guest OS. - &[Dirty, Accessed, Write, Read, User, Valid], - )]); + page_table::sv39x4::generate_page_table( + page_table_addr, + &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, + // allow writing data to dtb to modify device tree on guest OS. + &[Dirty, Accessed, Write, Read, User, Valid], + )], + ); } guest_dtb_addr @@ -185,11 +191,13 @@ impl Guest { /// # Arguments /// * `guest_elf` - Elf loading guest space. /// * `elf_addr` - Elf address. + /// * `guest_initrd` - Initrd raw slice. #[cfg(feature = "identity_map")] pub fn load_guest_elf( &self, guest_elf: &ElfBytes, elf_addr: *const u8, + guest_initrd: &'static [u8], ) -> (GuestPhysicalAddress, GuestPhysicalAddress) { /// Segment type `PT_LOAD` /// @@ -235,8 +243,8 @@ impl Guest { } } - if !GUEST_INITRD.is_empty() { - let aligned_initrd_size = GUEST_INITRD.len().div_ceil(PAGE_SIZE) * PAGE_SIZE; + if !guest_initrd.is_empty() { + let aligned_initrd_size = guest_initrd.len().div_ceil(PAGE_SIZE) * PAGE_SIZE; let guest_base = guest_memory::DRAM_BASE + guest_memory::DRAM_SIZE_PER_GUEST * (self.hart_id + 1); let initrd_start = guest_base + guest_memory::DRAM_SIZE_PER_GUEST - aligned_initrd_size; @@ -244,14 +252,14 @@ impl Guest { crate::println!( "initrd (GPA): {:#x}..{:#x}", initrd_start.raw(), - initrd_start.raw() + GUEST_INITRD.len() + initrd_start.raw() + guest_initrd.len() ); unsafe { core::ptr::copy( - GUEST_INITRD.as_ptr(), + guest_initrd.as_ptr(), initrd_start.raw() as *mut u8, - GUEST_INITRD.len(), + guest_initrd.len(), ); } } @@ -271,6 +279,7 @@ impl Guest { /// # Arguments /// * `guest_elf` - Elf loading guest space. /// * `elf_addr` - Elf address. + /// * `guest_initrd` - Initrd raw slice. /// /// # Panics /// Panics if it failed to calculate `aligned_segment_size` or failed to convert to usize. @@ -280,6 +289,7 @@ impl Guest { &self, guest_elf: &ElfBytes, elf_addr: *const u8, + _guest_initrd: &'static [u8], ) -> (GuestPhysicalAddress, GuestPhysicalAddress) { /// Segment type `PT_LOAD` /// @@ -341,8 +351,9 @@ impl Guest { } // create memory mapping - page_table::sv39x4::generate_page_table(self.page_table_addr, &[ - MemoryMap::new( + page_table::sv39x4::generate_page_table( + self.page_table_addr, + &[MemoryMap::new( guest_physical_addr..guest_physical_addr + PAGE_SIZE, aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, match prog_header.p_flags & 0b111 { @@ -357,8 +368,8 @@ impl Guest { 0b111 => &[Dirty, Accessed, Exec, Write, Read, User, Valid], _ => panic!("unsupported flags"), }, - ), - ]); + )], + ); } } } @@ -368,7 +379,11 @@ impl Guest { /// Allocate guest memory space from heap and create corresponding page table. #[cfg(feature = "identity_map")] - pub fn allocate_memory_region(&self, region: Range) { + pub fn allocate_memory_region( + &self, + region: Range, + _guest_initrd: &'static [u8], + ) { use PteFlag::{Accessed, Dirty, Exec, Read, User, Valid, Write}; let all_pte_flags_are_set = &[Dirty, Accessed, Exec, Write, Read, User, Valid]; @@ -377,28 +392,35 @@ impl Guest { let guest_physical_addr = GuestPhysicalAddress(guest_physical_addr); let host_physical_addr = HostPhysicalAddress(guest_physical_addr.raw()); // create memory mapping - page_table::sv39x4::generate_page_table(self.page_table_addr, &[MemoryMap::new( - guest_physical_addr..guest_physical_addr + PAGE_SIZE, - host_physical_addr..host_physical_addr + PAGE_SIZE, - all_pte_flags_are_set, - )]); + page_table::sv39x4::generate_page_table( + self.page_table_addr, + &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + host_physical_addr..host_physical_addr + PAGE_SIZE, + all_pte_flags_are_set, + )], + ); } } /// Allocate guest memory space from heap and create corresponding page table. #[cfg(not(feature = "identity_map"))] - pub fn allocate_memory_region(&self, region: Range) { + pub fn allocate_memory_region( + &self, + region: Range, + guest_initrd: &'static [u8], + ) { use PteFlag::{Accessed, Dirty, Exec, Read, User, Valid, Write}; let all_pte_flags_are_set = &[Dirty, Accessed, Exec, Write, Read, User, Valid]; - let aligned_initrd_size = GUEST_INITRD.len().div_ceil(PAGE_SIZE) * PAGE_SIZE; + let aligned_initrd_size = guest_initrd.len().div_ceil(PAGE_SIZE) * PAGE_SIZE; let initrd_start = region.end - aligned_initrd_size; - if !GUEST_INITRD.is_empty() { + if !guest_initrd.is_empty() { crate::println!( "initrd (GPA): {:#x}..{:#x}", initrd_start.raw(), - initrd_start.raw() + GUEST_INITRD.len() + initrd_start.raw() + guest_initrd.len() ); } @@ -413,7 +435,7 @@ impl Guest { unsafe { let offset = guest_physical_addr.raw() - initrd_start.raw(); core::ptr::copy( - GUEST_INITRD.as_ptr().byte_add(offset), + guest_initrd.as_ptr().byte_add(offset), aligned_page_size_block_addr.raw() as *mut u8, PAGE_SIZE, ); @@ -421,11 +443,14 @@ impl Guest { } // create memory mapping - page_table::sv39x4::generate_page_table(self.page_table_addr, &[MemoryMap::new( - guest_physical_addr..guest_physical_addr + PAGE_SIZE, - aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, - all_pte_flags_are_set, - )]); + page_table::sv39x4::generate_page_table( + self.page_table_addr, + &[MemoryMap::new( + guest_physical_addr..guest_physical_addr + PAGE_SIZE, + aligned_page_size_block_addr..aligned_page_size_block_addr + PAGE_SIZE, + all_pte_flags_are_set, + )], + ); } } } diff --git a/hikami_core/src/lib.rs b/hikami_core/src/lib.rs index f3d48e2..ebca33a 100644 --- a/hikami_core/src/lib.rs +++ b/hikami_core/src/lib.rs @@ -19,8 +19,8 @@ use core::cell::OnceCell; use device::Devices; use guest::Guest; -use memmap::HostPhysicalAddress; use memmap::constant::MAX_HART_NUM; +use memmap::HostPhysicalAddress; use fdt::Fdt; use spin::Mutex; @@ -86,21 +86,6 @@ impl HypervisorData { } } -/// Guest kernel image -#[unsafe(link_section = ".guest_kernel")] -pub static GUEST_KERNEL: [u8; include_bytes!("../../guest_image/vmlinux").len()] = - *include_bytes!("../../guest_image/vmlinux"); - -/// Device tree blob that is passed to guest -#[unsafe(link_section = ".guest_dtb")] -pub static GUEST_DTB: [u8; include_bytes!("../../guest_image/guest.dtb").len()] = - *include_bytes!("../../guest_image/guest.dtb"); - -/// Guest intird -#[unsafe(link_section = ".guest_initrd")] -pub static GUEST_INITRD: [u8; include_bytes!("../../guest_image/initrd").len()] = - *include_bytes!("../../guest_image/initrd"); - unsafe extern "C" { /// stack top (defined in `memory.x`) pub static _stack_start: u8; diff --git a/src/hypervisor_init.rs b/src/hypervisor_init.rs index 9af748e..b1b0395 100644 --- a/src/hypervisor_init.rs +++ b/src/hypervisor_init.rs @@ -1,7 +1,7 @@ //! HS-mode level initialization. use crate::trap::hstrap_vector; -use crate::ALLOCATOR; +use crate::{ALLOCATOR, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL}; use hikami_core::guest::context::ContextData; use hikami_core::guest::Guest; use hikami_core::h_extension::csrs::{ @@ -13,7 +13,7 @@ use hikami_core::memmap::{ constant::guest_memory, page_table::sv39x4::ROOT_PAGE_TABLE, GuestPhysicalAddress, HostPhysicalAddress, }; -use hikami_core::{HypervisorData, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL, HYPERVISOR_DATA}; +use hikami_core::{HypervisorData, HYPERVISOR_DATA}; use hikami_core::{_hv_heap_size, _start_heap}; use core::arch::asm; @@ -147,18 +147,19 @@ fn vsmode_setup(hart_id: usize, dtb_addr: HostPhysicalAddress) -> ! { // load guest image let (guest_entry_point, elf_end_addr) = - new_guest.load_guest_elf(&guest_elf, GUEST_KERNEL.as_ptr()); + new_guest.load_guest_elf(&guest_elf, GUEST_KERNEL.as_ptr(), &GUEST_INITRD); if cfg!(feature = "identity_map") { let guest_memory_start = guest_memory::DRAM_BASE + (hart_id + 1) * guest_memory::DRAM_SIZE_PER_GUEST; new_guest.allocate_memory_region( guest_memory_start..guest_memory_start + guest_memory::DRAM_SIZE_PER_GUEST, + &GUEST_INITRD, ); } else { // allocate page tables to all remain guest memory region let guest_memory_end = new_guest.memory_region().end; - new_guest.allocate_memory_region(elf_end_addr..guest_memory_end); + new_guest.allocate_memory_region(elf_end_addr..guest_memory_end, &GUEST_INITRD); } // set device memory map diff --git a/src/main.rs b/src/main.rs index 0f4e4e7..dca527d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,21 @@ use hikami_core::memmap::constant::{DRAM_BASE, STACK_SIZE_PER_HART}; use hikami_core::println; use hikami_core::{_end_bss, _start_bss, _top_b_stack}; +/// Guest kernel image +#[unsafe(link_section = ".guest_kernel")] +pub static GUEST_KERNEL: [u8; include_bytes!("../guest_image/vmlinux").len()] = + *include_bytes!("../guest_image/vmlinux"); + +/// Device tree blob that is passed to guest +#[unsafe(link_section = ".guest_dtb")] +pub static GUEST_DTB: [u8; include_bytes!("../guest_image/guest.dtb").len()] = + *include_bytes!("../guest_image/guest.dtb"); + +/// Guest intird +#[unsafe(link_section = ".guest_initrd")] +pub static GUEST_INITRD: [u8; include_bytes!("../guest_image/initrd").len()] = + *include_bytes!("../guest_image/initrd"); + /// Panic handler #[panic_handler] pub fn panic(info: &PanicInfo) -> ! { From 51861888bc49c87a44f07a670f22be01fe161c54 Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 6 Jul 2025 23:11:18 +0900 Subject: [PATCH 44/58] [update] add patch section to Cargo.toml to avoid crate confliction --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 9bf2300..bc2dc6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,3 +55,6 @@ rustsbi = { workspace = true } sbi-rt = { workspace = true } sbi-spec = { workspace = true } linked_list_allocator = { workspace = true } + +[patch.'https://github.com/Alignof/hikami'] +hikami_core = { path = "hikami_core" } From bf034e297643c23d56efb485bcede4e0987475ac Mon Sep 17 00:00:00 2001 From: Alingof Date: Mon, 7 Jul 2025 00:13:06 +0900 Subject: [PATCH 45/58] [fix] fix source of `hikami_zbb` crate --- Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bc2dc6e..19316d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,8 +43,7 @@ enable_extension = [ "hikami_zbb" ] [dependencies] hikami_core = { path = "hikami_core" } -hikami_zbb = { path = "../hikami_zbb", optional = true } -#hikami_zbb = { git = "https://github.com/Alignof/hikami_zbb", branch = "develop", optional = true } +hikami_zbb = { git = "https://github.com/Alignof/hikami_zbb", branch = "develop", optional = true } extension_manager = { path = "extension_manager" } elf = { workspace = true } From 93d1cbec6fa77777cffacb6d649206ede3126556 Mon Sep 17 00:00:00 2001 From: Alingof Date: Mon, 7 Jul 2025 00:40:22 +0900 Subject: [PATCH 46/58] [update] update root crate edition --- Cargo.toml | 2 +- README.md | 2 +- src/main.rs | 4 ++-- src/trap.rs | 14 ++++++++------ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 19316d3..7a45018 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hikami" version = "1.2.0" -edition = "2021" +edition = "2024" [lints.clippy] pedantic = "warn" diff --git a/README.md b/README.md index 37333a0..3cdc200 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ enable_extension = [ "hikami_zbb" ] See also: [https://github.com/Alignof/hikami_zbb](https://github.com/Alignof/hikami_zbb) -During the build process, extension_manager automatically detects these crates and expands the necessary code to initialize the extension and dispatch instruction handling. +During the build process, `extension_manager` automatically detects these crates and expands the necessary code to initialize the extension and dispatch instruction handling. This approach simplifies the management of multiple extensions and enhances the modularity of the hypervisor. ## Getting Started diff --git a/src/main.rs b/src/main.rs index dca527d..6b23f09 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,8 +55,8 @@ static ALLOCATOR: LockedHeap = LockedHeap::empty(); /// - jump to hstart /// /// TODO: Remove the `.attribute arch, "rv64gc"` directive when the LLVM problem is fixed. -#[link_section = ".text.entry"] -#[no_mangle] +#[unsafe(link_section = ".text.entry")] +#[unsafe(no_mangle)] #[naked] extern "C" fn _start() -> ! { unsafe { diff --git a/src/trap.rs b/src/trap.rs index 3ad88f6..697fbd9 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -29,8 +29,9 @@ pub unsafe fn hstrap_exit() -> ! { // release HYPERVISOR_DATA lock drop(hypervisor_data); - asm!( - ".align 4 + unsafe { + asm!( + ".align 4 fence.i // set to stack top @@ -83,10 +84,11 @@ pub unsafe fn hstrap_exit() -> ! { sret ", - HS_CONTEXT_SIZE = const size_of::(), - stack_top = in(reg) stack_top.raw(), - options(noreturn) - ); + HS_CONTEXT_SIZE = const size_of::(), + stack_top = in(reg) stack_top.raw(), + options(noreturn) + ); + } } /// Trap vector for HS-mode. From cf800e8c8196b8ba9fdab32e92eb5f055179cb4d Mon Sep 17 00:00:00 2001 From: Alingof Date: Mon, 7 Jul 2025 00:44:15 +0900 Subject: [PATCH 47/58] [refactor] fix `clippy::uninlined_format_args` in extension_manager/build.rs --- extension_manager/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extension_manager/build.rs b/extension_manager/build.rs index 6ab30c9..ed2dd09 100644 --- a/extension_manager/build.rs +++ b/extension_manager/build.rs @@ -55,8 +55,8 @@ fn main() { // output crates list to `OUT_DIR/dependencies.rs` let out_dir = env::var("OUT_DIR").unwrap(); - let out_path = format!("{}/dependencies.rs", out_dir); - let content = format!("static CRATES: &[&str] = &{:?};", crate_names); + let out_path = format!("{out_dir}/dependencies.rs"); + let content = format!("static CRATES: &[&str] = &{crate_names:?};"); fs::write(out_path, content).expect("Failed to write dependencies.rs"); } From 5058e186b9bda0987f1e9ba1dcd6c75ab04ad9d0 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 8 Jul 2025 20:57:06 +0900 Subject: [PATCH 48/58] [update] update rust channel (nightly -> 1.88.0) --- rust-toolchain.toml | 2 +- src/main.rs | 22 +++++++++------------- src/trap/exception.rs | 1 - 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 11f7a7a..d6bce38 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly" +channel = "1.88.0" components = [ "rustfmt", "clippy" ] targets = [ "riscv64imac-unknown-none-elf" ] diff --git a/src/main.rs b/src/main.rs index 6b23f09..4bca364 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,6 @@ #![doc = include_str!("../README.md")] #![no_main] #![no_std] -// TODO: remove nightly when `naked_functions` become stable. -#![feature(naked_functions)] // TODO: FIX AND REMOVE IT!!! #![allow(static_mut_refs)] @@ -57,12 +55,11 @@ static ALLOCATOR: LockedHeap = LockedHeap::empty(); /// TODO: Remove the `.attribute arch, "rv64gc"` directive when the LLVM problem is fixed. #[unsafe(link_section = ".text.entry")] #[unsafe(no_mangle)] -#[naked] +#[unsafe(naked)] extern "C" fn _start() -> ! { - unsafe { - // set stack pointer - naked_asm!( - r#" + // set stack pointer + naked_asm!( + r#" .attribute arch, "rv64gc" li t0, {stack_size_per_hart} mul t1, a0, t0 @@ -74,10 +71,9 @@ extern "C" fn _start() -> ! { call {hstart} "#, - stack_top = sym _top_b_stack, - stack_size_per_hart = const STACK_SIZE_PER_HART, - DRAM_BASE = const DRAM_BASE, - hstart = sym hstart, - ) - } + stack_top = sym _top_b_stack, + stack_size_per_hart = const STACK_SIZE_PER_HART, + DRAM_BASE = const DRAM_BASE, + hstart = sym hstart, + ) } diff --git a/src/trap/exception.rs b/src/trap/exception.rs index 8fcc258..8f140ea 100644 --- a/src/trap/exception.rs +++ b/src/trap/exception.rs @@ -24,7 +24,6 @@ use sbi_handler::{ /// Delegate exception to supervisor mode from VS-mode. #[unsafe(no_mangle)] -#[inline(always)] #[allow(clippy::inline_always, clippy::module_name_repetitions)] pub extern "C" fn hs_forward_exception() { unsafe { From 6d2f2ce4b4e379edea92863b4471bdc0ce469a8f Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 8 Jul 2025 21:01:14 +0900 Subject: [PATCH 49/58] [refactor] apply `cargo clippy --fix --bin "hikami"` --- README.md | 8 ++++---- src/trap.rs | 2 +- src/trap/exception/sbi_handler.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3cdc200..dcc1855 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # hikami -[![Rust](https://github.com/Alignof/hikami/actions/workflows/rust.yml/badge.svg)](https://github.com/Alignof/hikami/actions/workflows/rust.yml) +[![Rust](https://github.com/Alignof/hikami/actions/workflows/rust.yml/badge.svg)](https://github.com/Alignof/hikami/actions/workflows/rust.yml)\ A lightweight Type-1 hypervisor for RISC-V H-extension, featuring **RISC-V extension emulation**. -This project aims not only to realize a lightweight hypervisor that can be used on RISC-V H extensions, but also to easily reproduce and manage the "extension" on the hypervisor. -Poster in RISC-V Days Tokyo 2024 Summer: [PDF](https://riscv.or.jp/wp-content/uploads/RV-Days_Tokyo_2024_Summer_paper_9.pdf) +This project aims not only to realize a lightweight hypervisor that can be used on RISC-V H extensions, but also to easily reproduce and manage the "extension" on the hypervisor.\ +Poster in RISC-V Days Tokyo 2024 Summer: [PDF](https://riscv.or.jp/wp-content/uploads/RV-Days_Tokyo_2024_Summer_paper_9.pdf)\ Paper in ComSys2024(ja): [link](https://ipsj.ixsq.nii.ac.jp/records/241051) ## Related projects @@ -112,5 +112,5 @@ Coming soon... - [hypocaust-2](https://github.com/KuangjuX/hypocaust-2) ## Acknowledgement -Exploratory IT Human Resources Project (MITOU Program) of Information-technology Promotion Agency, Japan (IPA) in the fiscal year 2024. +Exploratory IT Human Resources Project (MITOU Program) of Information-technology Promotion Agency, Japan (IPA) in the fiscal year 2024.\ [https://www.ipa.go.jp/jinzai/mitou/it/2024/gaiyou-tn-3.html](https://www.ipa.go.jp/jinzai/mitou/it/2024/gaiyou-tn-3.html) diff --git a/src/trap.rs b/src/trap.rs index 697fbd9..a7352a2 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -95,7 +95,7 @@ pub unsafe fn hstrap_exit() -> ! { /// Switch to hypervisor stack and save contexts. /// /// ## `fn_align` -/// function alignment (feature `fn_align`). +/// function alignment (feature `fn_align`).\ /// See: [https://github.com/rust-lang/rust/issues/82232](https://github.com/rust-lang/rust/issues/82232). /// ```no_run /// #[repr(align(4))] diff --git a/src/trap/exception/sbi_handler.rs b/src/trap/exception/sbi_handler.rs index 17cc825..2af43c8 100644 --- a/src/trap/exception/sbi_handler.rs +++ b/src/trap/exception/sbi_handler.rs @@ -1,4 +1,4 @@ -//! Handle VS-mode Ecall exception +//! Handle VS-mode Ecall exception\ //! See [https://github.com/riscv-non-isa/riscv-sbi-doc/releases/download/v2.0/riscv-sbi.pdf](https://github.com/riscv-non-isa/riscv-sbi-doc/releases/download/v2.0/riscv-sbi.pdf) use hikami_core::h_extension::csrs::{hvip, VsInterruptKind}; From e0141a148838de5a12809b524286761ba97cb4b0 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 8 Jul 2025 21:06:37 +0900 Subject: [PATCH 50/58] [refactor] apply cargo fmt --- hikami_core/src/guest.rs | 8 ++++---- hikami_core/src/lib.rs | 2 +- src/hypervisor_init.rs | 14 +++++++------- src/trap.rs | 2 +- src/trap/exception.rs | 4 ++-- src/trap/exception/instruction_handler.rs | 2 +- src/trap/exception/page_fault_handler.rs | 2 +- src/trap/exception/sbi_handler.rs | 2 +- src/trap/interrupt.rs | 4 ++-- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/hikami_core/src/guest.rs b/hikami_core/src/guest.rs index 1bd76a1..f3bd72a 100644 --- a/hikami_core/src/guest.rs +++ b/hikami_core/src/guest.rs @@ -2,18 +2,18 @@ pub mod context; +use crate::PageBlock; use crate::memmap::page_table::sv39x4::FIRST_LV_PAGE_TABLE_LEN; use crate::memmap::{ + GuestPhysicalAddress, HostPhysicalAddress, MemoryMap, constant::guest_memory, page_table, - page_table::{constants::PAGE_SIZE, PageTableEntry, PteFlag}, - GuestPhysicalAddress, HostPhysicalAddress, MemoryMap, + page_table::{PageTableEntry, PteFlag, constants::PAGE_SIZE}, }; -use crate::PageBlock; use context::{Context, ContextData}; use core::ops::Range; -use elf::{endian::AnyEndian, ElfBytes}; +use elf::{ElfBytes, endian::AnyEndian}; /// Guest Information #[derive(Debug)] diff --git a/hikami_core/src/lib.rs b/hikami_core/src/lib.rs index ebca33a..79a517c 100644 --- a/hikami_core/src/lib.rs +++ b/hikami_core/src/lib.rs @@ -19,8 +19,8 @@ use core::cell::OnceCell; use device::Devices; use guest::Guest; -use memmap::constant::MAX_HART_NUM; use memmap::HostPhysicalAddress; +use memmap::constant::MAX_HART_NUM; use fdt::Fdt; use spin::Mutex; diff --git a/src/hypervisor_init.rs b/src/hypervisor_init.rs index b1b0395..3640795 100644 --- a/src/hypervisor_init.rs +++ b/src/hypervisor_init.rs @@ -2,23 +2,23 @@ use crate::trap::hstrap_vector; use crate::{ALLOCATOR, GUEST_DTB, GUEST_INITRD, GUEST_KERNEL}; -use hikami_core::guest::context::ContextData; use hikami_core::guest::Guest; +use hikami_core::guest::context::ContextData; use hikami_core::h_extension::csrs::{ - hcounteren, hedeleg, hedeleg::ExceptionKind, henvcfg, hgatp, hideleg, hie, hstatus, hvip, - vsatp, VsInterruptKind, + VsInterruptKind, hcounteren, hedeleg, hedeleg::ExceptionKind, henvcfg, hgatp, hideleg, hie, + hstatus, hvip, vsatp, }; use hikami_core::h_extension::instruction::hfence_gvma_all; use hikami_core::memmap::{ - constant::guest_memory, page_table::sv39x4::ROOT_PAGE_TABLE, GuestPhysicalAddress, - HostPhysicalAddress, + GuestPhysicalAddress, HostPhysicalAddress, constant::guest_memory, + page_table::sv39x4::ROOT_PAGE_TABLE, }; -use hikami_core::{HypervisorData, HYPERVISOR_DATA}; use hikami_core::{_hv_heap_size, _start_heap}; +use hikami_core::{HYPERVISOR_DATA, HypervisorData}; use core::arch::asm; -use elf::{endian::AnyEndian, ElfBytes}; +use elf::{ElfBytes, endian::AnyEndian}; use riscv::register::{sepc, sie, sscratch, sstatus, sstatus::FS, stvec}; /// Entry point to HS-mode. diff --git a/src/trap.rs b/src/trap.rs index a7352a2..b9ac245 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -6,8 +6,8 @@ mod interrupt; use exception::trap_exception; use interrupt::trap_interrupt; -use hikami_core::guest::context::ContextData; use hikami_core::HYPERVISOR_DATA; +use hikami_core::guest::context::ContextData; use core::arch::asm; use riscv::register::scause::{self, Trap}; diff --git a/src/trap/exception.rs b/src/trap/exception.rs index 8f140ea..751f385 100644 --- a/src/trap/exception.rs +++ b/src/trap/exception.rs @@ -5,12 +5,12 @@ mod page_fault_handler; mod sbi_handler; use super::hstrap_exit; +use hikami_core::HYPERVISOR_DATA; use hikami_core::guest; use hikami_core::h_extension::{ - csrs::{htval, vstvec}, HvException, + csrs::{htval, vstvec}, }; -use hikami_core::HYPERVISOR_DATA; use core::arch::asm; use riscv::register::{ diff --git a/src/trap/exception/instruction_handler.rs b/src/trap/exception/instruction_handler.rs index 47be0c0..a0ac4e4 100644 --- a/src/trap/exception/instruction_handler.rs +++ b/src/trap/exception/instruction_handler.rs @@ -4,8 +4,8 @@ //! - Virtual Instruction use super::hs_forward_exception; -use hikami_core::emulate_extension::EmulateExtension; use hikami_core::HYPERVISOR_DATA; +use hikami_core::emulate_extension::EmulateExtension; use raki::{Instruction, OpcodeKind}; use riscv::register::{sepc, stval}; diff --git a/src/trap/exception/page_fault_handler.rs b/src/trap/exception/page_fault_handler.rs index 795a4aa..ff0848c 100644 --- a/src/trap/exception/page_fault_handler.rs +++ b/src/trap/exception/page_fault_handler.rs @@ -4,11 +4,11 @@ //! - Store AMO guest page fault use super::{hs_forward_exception, update_sepc_by_inst_type}; +use hikami_core::HYPERVISOR_DATA; use hikami_core::device::EmulateDevice; use hikami_core::h_extension::csrs::{htinst, htval}; use hikami_core::memmap::page_table::{g_stage_trans_addr, vs_stage_trans_addr}; use hikami_core::memmap::{GuestPhysicalAddress, GuestVirtualAddress, HostPhysicalAddress}; -use hikami_core::HYPERVISOR_DATA; use raki::Instruction; use riscv::register::sepc; diff --git a/src/trap/exception/sbi_handler.rs b/src/trap/exception/sbi_handler.rs index 2af43c8..b03105c 100644 --- a/src/trap/exception/sbi_handler.rs +++ b/src/trap/exception/sbi_handler.rs @@ -1,7 +1,7 @@ //! Handle VS-mode Ecall exception\ //! See [https://github.com/riscv-non-isa/riscv-sbi-doc/releases/download/v2.0/riscv-sbi.pdf](https://github.com/riscv-non-isa/riscv-sbi-doc/releases/download/v2.0/riscv-sbi.pdf) -use hikami_core::h_extension::csrs::{hvip, VsInterruptKind}; +use hikami_core::h_extension::csrs::{VsInterruptKind, hvip}; use riscv::register::sie; use sbi_rt::SbiRet; diff --git a/src/trap/interrupt.rs b/src/trap/interrupt.rs index 8f2955f..6aa68db 100644 --- a/src/trap/interrupt.rs +++ b/src/trap/interrupt.rs @@ -1,9 +1,9 @@ //! Trap VS-mode interrupt. use super::hstrap_exit; -use hikami_core::device::plic::ContextId; -use hikami_core::h_extension::csrs::{hvip, VsInterruptKind}; use hikami_core::HYPERVISOR_DATA; +use hikami_core::device::plic::ContextId; +use hikami_core::h_extension::csrs::{VsInterruptKind, hvip}; use riscv::register::scause::Interrupt; use riscv::register::sie; From 22424210649625b7565cf916f2c3bb24143f3542 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 9 Jul 2025 15:42:12 +0900 Subject: [PATCH 51/58] [!][fix] fix `Devices::create_device_map` --- hikami_core/src/device.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/hikami_core/src/device.rs b/hikami_core/src/device.rs index 1a47e59..a982f13 100644 --- a/hikami_core/src/device.rs +++ b/hikami_core/src/device.rs @@ -271,10 +271,6 @@ impl Devices { self.clint.memmap(), ]); - if let Some(pci) = &self.pci { - device_mapping.push(pci.memmap()); - device_mapping.extend_from_slice(pci.pci_memory_maps()); - } if let Some(rtc) = &self.rtc { device_mapping.push(rtc.memmap()); } @@ -282,18 +278,25 @@ impl Devices { device_mapping.push(initrd.memmap()); } - // disable drive emulation if `identity_map` feature is enabled - if cfg!(feature = "identity_map") { - if let Some(mmc) = &self.mmc { - device_mapping.push(mmc.memmap()); - } - if let Some(pci) = &self.pci { + if let Some(pci) = &self.pci { + device_mapping.push(pci.memmap()); + + // mapping whole region of block divices + if cfg!(feature = "identity_map") { + device_mapping.extend_from_slice(pci.pci_memory_maps()); + } else { + // mapping pass-through registers' region if let Some(sata) = &pci.pci_devices.sata { use pci::PciDevice; device_mapping.push(sata.memmap()); } } } + if cfg!(feature = "identity_map") { + if let Some(mmc) = &self.mmc { + device_mapping.push(mmc.memmap()); + } + } device_mapping } From fd1881937b9ff3dcb739f4b4b090372afe307f6a Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 9 Jul 2025 15:46:31 +0900 Subject: [PATCH 52/58] [!][update] remove `memory_maps` argument from `PciDevice::new` --- hikami_core/src/device/pci.rs | 8 ++------ hikami_core/src/device/pci/iommu.rs | 8 +++----- hikami_core/src/device/pci/sata.rs | 6 ++---- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/hikami_core/src/device/pci.rs b/hikami_core/src/device/pci.rs index 7ab144e..3f17d55 100644 --- a/hikami_core/src/device/pci.rs +++ b/hikami_core/src/device/pci.rs @@ -8,7 +8,7 @@ pub mod config_register; use super::{MmioDevice, PTE_FLAGS_FOR_DEVICE}; use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; -use config_register::{ConfigSpaceHeaderField, read_config_register}; +use config_register::{read_config_register, ConfigSpaceHeaderField}; use alloc::vec::Vec; use core::ops::Range; @@ -60,7 +60,6 @@ pub trait PciDevice { device_id: u32, pci_config_space_base_addr: HostPhysicalAddress, pci_addr_space: &PciAddressSpace, - memory_maps: &mut Vec, ) -> Self; /// Initialize pci device. @@ -87,7 +86,6 @@ impl PciDevices { device_tree: &Fdt, pci_config_space_base_addr: HostPhysicalAddress, pci_addr_space: &PciAddressSpace, - memory_maps: &mut Vec, ) -> Self { /// Max PCI bus size. const PCI_MAX_BUS: u8 = 255; @@ -143,7 +141,6 @@ impl PciDevices { device_id.into(), pci_config_space_base_addr, pci_addr_space, - memory_maps, )); } @@ -299,8 +296,7 @@ impl MmioDevice for Pci { let mut memory_maps = Vec::new(); let base_address = HostPhysicalAddress(region.starting_address as usize); let pci_addr_space = PciAddressSpace::new(device_tree, compatibles); - let pci_devices = - PciDevices::new(device_tree, base_address, &pci_addr_space, &mut memory_maps); + let pci_devices = PciDevices::new(device_tree, base_address, &pci_addr_space); // 32 bit memory map memory_maps.push(MemoryMap::new( diff --git a/hikami_core/src/device/pci/iommu.rs b/hikami_core/src/device/pci/iommu.rs index 9a00f31..464c80d 100644 --- a/hikami_core/src/device/pci/iommu.rs +++ b/hikami_core/src/device/pci/iommu.rs @@ -4,15 +4,14 @@ mod register_map; use super::config_register::{ - ConfigSpaceHeaderField, get_bar_size, read_config_register, write_config_register, + get_bar_size, read_config_register, write_config_register, ConfigSpaceHeaderField, }; use super::{Bdf, PciAddressSpace, PciDevice}; -use crate::PageBlock; use crate::h_extension::csrs::hgatp; -use crate::memmap::{HostPhysicalAddress, MemoryMap, page_table::constants::PAGE_SIZE}; +use crate::memmap::{page_table::constants::PAGE_SIZE, HostPhysicalAddress, MemoryMap}; +use crate::PageBlock; use register_map::{IoMmuMode, IoMmuRegisters}; -use alloc::vec::Vec; use core::ops::Range; use fdt::Fdt; @@ -137,7 +136,6 @@ impl PciDevice for IoMmu { _device_id: u32, _pci_config_space_base_addr: HostPhysicalAddress, _pci_addr_space: &PciAddressSpace, - _memory_maps: &mut Vec, ) -> Self { unreachable!("use `IoMmu::new_from_dtb` instead."); } diff --git a/hikami_core/src/device/pci/sata.rs b/hikami_core/src/device/pci/sata.rs index 61f5c84..bd11eb2 100644 --- a/hikami_core/src/device/pci/sata.rs +++ b/hikami_core/src/device/pci/sata.rs @@ -4,18 +4,17 @@ mod command; -use super::config_register::{ConfigSpaceHeaderField, get_bar_size, read_config_register}; +use super::config_register::{get_bar_size, read_config_register, ConfigSpaceHeaderField}; use super::{Bdf, PciAddressSpace, PciDevice}; use crate::device::DeviceEmulateError; use crate::memmap::page_table::g_stage_trans_addr; use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; use command::{ - COMMAND_HEADER_SIZE, CommandHeader, CommandTable, CommandTableGpaStorage, TransferDirection, + CommandHeader, CommandTable, CommandTableGpaStorage, TransferDirection, COMMAND_HEADER_SIZE, }; use alloc::boxed::Box; use alloc::vec; -use alloc::vec::Vec; use core::ops::Range; /// Number of SATA port. @@ -406,7 +405,6 @@ impl PciDevice for Sata { device_id: u32, pci_config_space_base_addr: HostPhysicalAddress, pci_addr_space: &PciAddressSpace, - _memory_maps: &mut Vec, ) -> Self { let config_space_header_addr = pci_config_space_base_addr.0 | bdf.calc_config_space_header_offset(); From 21a39dfd10835a3cd727b44e8b2f711b7a338d49 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 9 Jul 2025 16:00:56 +0900 Subject: [PATCH 53/58] [rebase] 1st --- hikami_core/src/device.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/hikami_core/src/device.rs b/hikami_core/src/device.rs index a982f13..8083357 100644 --- a/hikami_core/src/device.rs +++ b/hikami_core/src/device.rs @@ -281,15 +281,9 @@ impl Devices { if let Some(pci) = &self.pci { device_mapping.push(pci.memmap()); - // mapping whole region of block divices if cfg!(feature = "identity_map") { + // mapping whole memory mapped register region of block divices. device_mapping.extend_from_slice(pci.pci_memory_maps()); - } else { - // mapping pass-through registers' region - if let Some(sata) = &pci.pci_devices.sata { - use pci::PciDevice; - device_mapping.push(sata.memmap()); - } } } if cfg!(feature = "identity_map") { From 4b7cd64884c19586b211571fda3c82b95f667768 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 9 Jul 2025 16:27:08 +0900 Subject: [PATCH 54/58] [update] update default drive in device tree --- guest_image/guest.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guest_image/guest.dts b/guest_image/guest.dts index cd54fd1..8f46850 100644 --- a/guest_image/guest.dts +++ b/guest_image/guest.dts @@ -89,7 +89,7 @@ }; chosen { - bootargs = "root=/dev/vda locale.LANG=en_US.UTF-8"; + bootargs = "root=/dev/sda locale.LANG=en_US.UTF-8"; stdout-path = "/soc/serial@10000000"; rng-seed = <0x9775b34d 0xe39158f2 0x3e9d10b1 0x73692dfd 0x13c15814 0xa4ad203f 0x8b0d62f7 0x6bf8a79d>; }; From 40baf07162279732db70e156c092f002b1b67508 Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 9 Jul 2025 16:28:03 +0900 Subject: [PATCH 55/58] [refactor] add comments to `MmioDevice` implementation for `Pci` --- hikami_core/src/device/pci.rs | 7 ++++--- hikami_core/src/device/pci/iommu.rs | 6 +++--- hikami_core/src/device/pci/sata.rs | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/hikami_core/src/device/pci.rs b/hikami_core/src/device/pci.rs index 3f17d55..46ed9a3 100644 --- a/hikami_core/src/device/pci.rs +++ b/hikami_core/src/device/pci.rs @@ -8,7 +8,7 @@ pub mod config_register; use super::{MmioDevice, PTE_FLAGS_FOR_DEVICE}; use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; -use config_register::{read_config_register, ConfigSpaceHeaderField}; +use config_register::{ConfigSpaceHeaderField, read_config_register}; use alloc::vec::Vec; use core::ops::Range; @@ -298,7 +298,7 @@ impl MmioDevice for Pci { let pci_addr_space = PciAddressSpace::new(device_tree, compatibles); let pci_devices = PciDevices::new(device_tree, base_address, &pci_addr_space); - // 32 bit memory map + // 32 bit reserved memory map memory_maps.push(MemoryMap::new( GuestPhysicalAddress(pci_addr_space.bit32_memory_space.start.raw()) ..GuestPhysicalAddress(pci_addr_space.bit32_memory_space.end.raw()), @@ -306,7 +306,7 @@ impl MmioDevice for Pci { &PTE_FLAGS_FOR_DEVICE, )); - // 64 bit memory map + // 64 bit reserved memory map memory_maps.push(MemoryMap::new( GuestPhysicalAddress(pci_addr_space.bit64_memory_space.start.raw()) ..GuestPhysicalAddress(pci_addr_space.bit64_memory_space.end.raw()), @@ -331,6 +331,7 @@ impl MmioDevice for Pci { self.base_addr } + /// mapping sata register region. fn memmap(&self) -> MemoryMap { let vaddr = GuestPhysicalAddress(self.paddr().raw()); MemoryMap::new( diff --git a/hikami_core/src/device/pci/iommu.rs b/hikami_core/src/device/pci/iommu.rs index 464c80d..0ab8d92 100644 --- a/hikami_core/src/device/pci/iommu.rs +++ b/hikami_core/src/device/pci/iommu.rs @@ -4,12 +4,12 @@ mod register_map; use super::config_register::{ - get_bar_size, read_config_register, write_config_register, ConfigSpaceHeaderField, + ConfigSpaceHeaderField, get_bar_size, read_config_register, write_config_register, }; use super::{Bdf, PciAddressSpace, PciDevice}; -use crate::h_extension::csrs::hgatp; -use crate::memmap::{page_table::constants::PAGE_SIZE, HostPhysicalAddress, MemoryMap}; use crate::PageBlock; +use crate::h_extension::csrs::hgatp; +use crate::memmap::{HostPhysicalAddress, MemoryMap, page_table::constants::PAGE_SIZE}; use register_map::{IoMmuMode, IoMmuRegisters}; use core::ops::Range; diff --git a/hikami_core/src/device/pci/sata.rs b/hikami_core/src/device/pci/sata.rs index bd11eb2..e62efc1 100644 --- a/hikami_core/src/device/pci/sata.rs +++ b/hikami_core/src/device/pci/sata.rs @@ -4,13 +4,13 @@ mod command; -use super::config_register::{get_bar_size, read_config_register, ConfigSpaceHeaderField}; +use super::config_register::{ConfigSpaceHeaderField, get_bar_size, read_config_register}; use super::{Bdf, PciAddressSpace, PciDevice}; use crate::device::DeviceEmulateError; use crate::memmap::page_table::g_stage_trans_addr; use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap}; use command::{ - CommandHeader, CommandTable, CommandTableGpaStorage, TransferDirection, COMMAND_HEADER_SIZE, + COMMAND_HEADER_SIZE, CommandHeader, CommandTable, CommandTableGpaStorage, TransferDirection, }; use alloc::boxed::Box; From 169b6c62c74a9785891ab8f3dce9d7d7788d49ed Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 9 Jul 2025 16:33:51 +0900 Subject: [PATCH 56/58] [fix] fix an argument of `Guest::map_guest_dtb` in `identity_map` feature --- hikami_core/src/guest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hikami_core/src/guest.rs b/hikami_core/src/guest.rs index f3bd72a..f4abc44 100644 --- a/hikami_core/src/guest.rs +++ b/hikami_core/src/guest.rs @@ -75,7 +75,7 @@ impl Guest { fn map_guest_dtb( _hart_id: usize, page_table_addr: HostPhysicalAddress, - guest_dtb: &'static [u8; include_bytes!("../guest_image/guest.dtb").len()], + guest_dtb: &'static [u8], ) -> GuestPhysicalAddress { use PteFlag::{Accessed, Dirty, Read, User, Valid, Write}; From 43976fc109a9b7b546e9a32ef42f417d344535be Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 9 Jul 2025 17:07:40 +0900 Subject: [PATCH 57/58] [add] add QEMU option description to disable zbb emulation in QEMU --- .cargo/config.toml | 2 ++ README.md | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 83a16da..46c5aff 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,4 +1,6 @@ [target.riscv64imac-unknown-none-elf] +# if you wanna test zbb emulation, you can: +# -cpu rv64,smstateen=true -> -cpu rv64,smstateen=true,zbb=false runner = """ qemu-system-riscv64 -cpu rv64,smstateen=true diff --git a/README.md b/README.md index dcc1855..3629893 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,22 @@ enable_extension = [ "hikami_zbb" ] See also: [https://github.com/Alignof/hikami_zbb](https://github.com/Alignof/hikami_zbb) +and add `zbb=false` option to qemu args in `.cargo/config.toml`. +```toml +[target.riscv64imac-unknown-none-elf] +runner = """ +qemu-system-riscv64 +-cpu rv64,smstateen=true,zbb=false +-machine virt +-bios default +-nographic +-m 2G +-drive file=rootfs.ext2,format=raw,id=hd0,if=none +-device ich9-ahci,id=ahci -device ide-hd,drive=hd0,bus=ahci.0 +-kernel +""" +``` + During the build process, `extension_manager` automatically detects these crates and expands the necessary code to initialize the extension and dispatch instruction handling. This approach simplifies the management of multiple extensions and enhances the modularity of the hypervisor. From c824f6f1ae89900108cf56a167a0d1ed98ce992e Mon Sep 17 00:00:00 2001 From: Alingof Date: Wed, 9 Jul 2025 17:21:48 +0900 Subject: [PATCH 58/58] [update] hikami's version (1.2.0 -> 2.0.0) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7a45018..6345814 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hikami" -version = "1.2.0" +version = "2.0.0" edition = "2024" [lints.clippy]