Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/arch/aarch64/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2025 Syswonder
// hvisor is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR
// FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Syswonder Website:
// https://www.syswonder.org
//
// Authors:
// Jingyu Liu <[email protected]>
//

pub unsafe fn invalidate_dcache_range(start: usize, size: usize, line_size: usize) {
let mut addr = start & !(line_size - 1);
let end = start + size;
while addr < end {
core::arch::asm!("dc ivac, {0}", in(reg) addr, options(nostack, preserves_flags));
addr += line_size;
}
core::arch::asm!("dsb sy", options(nostack, preserves_flags));
}
1 change: 1 addition & 0 deletions src/arch/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//
// Authors:
//
mod cache;
pub mod consts;
pub mod cpu;
pub mod entry;
Expand Down
30 changes: 29 additions & 1 deletion src/arch/aarch64/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
//
use core::panic;

use super::cache::invalidate_dcache_range;
use crate::{
config::*,
device::virtio_trampoline::mmio_virtio_handler,
error::HvResult,
memory::{GuestPhysAddr, HostPhysAddr, MemFlags, MemoryRegion},
memory::{addr::phys_to_virt, GuestPhysAddr, HostPhysAddr, MemFlags, MemoryRegion},
zone::Zone,
};

Expand Down Expand Up @@ -120,6 +121,33 @@ impl Zone {
pub fn arch_zone_post_configuration(&mut self, _config: &HvZoneConfig) -> HvResult {
Ok(())
}

pub fn arch_zone_reset(&mut self, _config: &HvZoneConfig) -> HvResult {
// This operation serves as an insurance to ensure that
// there is no relevant d-cache line in the cache;
// since the VA has the inner-shareable attribute,
// the cores within the inner-shareable domain will
// be affected by the broadcast invalidation.
unsafe {
// Get cache line size from CTR_EL0[16:19] (min line size, in words of 4 bytes)
let ctr_el0: u64;
core::arch::asm!("mrs {0}, ctr_el0", out(reg) ctr_el0, options(nostack, preserves_flags));
let dcache_line_size = (1 << ((ctr_el0 >> 16 & 0xF) as usize)) * 4;
self.gpm.for_each_region(|region| {
// Invalidate all RAM regions of the guest
if !region.flags.contains(MemFlags::IO) { // TODO: need to enrich the types and exercise more precise control
// Calculate the physical start address of the region
let phys_start = region.mapper.map_fn(region.start);
// Map phys_start to hvisor virtual address
let hva_start = phys_to_virt(phys_start);
info!("Invalidate Guest related cache, region.start: {:#x}, region.size: {:#x}, phys_start: {:#x}, hva_start: {:#x}", region.start, region.size, phys_start, hva_start);
// D-cache invalid operation will broadcast to all cores, just do it once. There is no need to do it on each core.
invalidate_dcache_range(hva_start, region.size, dcache_line_size);
}
});
}
Ok(())
}
}

#[repr(C)]
Expand Down
4 changes: 4 additions & 0 deletions src/arch/loongarch64/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,4 +690,8 @@ impl Zone {
pub fn arch_zone_post_configuration(&mut self, config: &HvZoneConfig) -> HvResult {
Ok(())
}

pub fn arch_zone_reset(&mut self, _config: &HvZoneConfig) -> HvResult {
Ok(())
}
}
4 changes: 4 additions & 0 deletions src/arch/riscv64/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ impl Zone {
pub fn arch_zone_post_configuration(&mut self, _config: &HvZoneConfig) -> HvResult {
Ok(())
}

pub fn arch_zone_reset(&mut self, _config: &HvZoneConfig) -> HvResult {
Ok(())
}
}

#[repr(C)]
Expand Down
4 changes: 4 additions & 0 deletions src/arch/x86_64/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ impl Zone {

Ok(())
}

pub fn arch_zone_reset(&mut self, _config: &HvZoneConfig) -> HvResult {
Ok(())
}
}

/*impl BarRegion {
Expand Down
10 changes: 10 additions & 0 deletions src/memory/mm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ where
true
}

/// Iterate over all memory regions in the MemorySet.
pub fn for_each_region<F>(&self, mut f: F)
where
F: FnMut(&MemoryRegion<PT::VA>),
{
for region in self.regions.values() {
f(region);
}
}

/// Add a memory region to this set.
pub fn insert(&mut self, region: MemoryRegion<PT::VA>) -> HvResult {
info!(
Expand Down
3 changes: 3 additions & 0 deletions src/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,9 @@ pub fn zone_create(config: &HvZoneConfig) -> HvResult<Arc<RwLock<Zone>>> {

zone.arch_zone_post_configuration(config)?;

// Reset the zone arch-related resources, e.g. invalid data cache
zone.arch_zone_reset(config)?;

// Initialize the virtual interrupt controller, it needs zone.cpu_num
zone.virqc_init(config);

Expand Down
Loading