diff --git a/src/arch/aarch64/cpu.rs b/src/arch/aarch64/cpu.rs index 442a2a29..13cbb0de 100644 --- a/src/arch/aarch64/cpu.rs +++ b/src/arch/aarch64/cpu.rs @@ -274,7 +274,7 @@ pub fn get_target_cpu(_irq: usize, zone_id: usize) -> usize { find_zone(zone_id) .unwrap() .read() - .cpu_set + .cpu_set() .first_cpu() .unwrap() } diff --git a/src/arch/aarch64/hypercall.rs b/src/arch/aarch64/hypercall.rs index 5a1ec0da..d06be7a9 100644 --- a/src/arch/aarch64/hypercall.rs +++ b/src/arch/aarch64/hypercall.rs @@ -30,7 +30,7 @@ impl<'a> HyperCall<'a> { // ipa->hpa->hva let hpa = unsafe { zone.read() - .gpm + .gpm() .page_table_query(ivc_info_ipa as _) .unwrap() .0 diff --git a/src/arch/aarch64/ivc.rs b/src/arch/aarch64/ivc.rs index 70a163c6..1de98422 100644 --- a/src/arch/aarch64/ivc.rs +++ b/src/arch/aarch64/ivc.rs @@ -151,16 +151,20 @@ impl From<&HvIvcConfig> for IvcRecord { impl Zone { pub fn ivc_init(&mut self, ivc_configs: &[HvIvcConfig]) { + let mut inner = self.write(); for ivc_config in ivc_configs { // is_new is ok to remove - if let Ok((_, start_paddr)) = insert_ivc_record(ivc_config, self.id as _) { + if let Ok((_, start_paddr)) = insert_ivc_record(ivc_config, self.id() as _) { info!( "ivc init: zone {}'s shared mem begins at {:x}, ipa is {:x}", - self.id, start_paddr, ivc_config.shared_mem_ipa + self.id(), + start_paddr, + ivc_config.shared_mem_ipa ); let rw_sec_size: usize = ivc_config.rw_sec_size as usize; let out_sec_size: usize = ivc_config.out_sec_size as usize; - self.gpm + inner + .gpm_mut() .insert(MemoryRegion::new_with_offset_mapper( ivc_config.shared_mem_ipa as _, start_paddr, @@ -174,7 +178,8 @@ impl Zone { } else { MemFlags::READ }; - self.gpm + inner + .gpm_mut() .insert(MemoryRegion::new_with_offset_mapper( ivc_config.shared_mem_ipa as usize + rw_sec_size + i * out_sec_size, start_paddr + rw_sec_size + i * out_sec_size, @@ -183,7 +188,7 @@ impl Zone { )) .unwrap(); } - self.mmio_region_register( + inner.mmio_region_register( ivc_config.control_table_ipa as _, PAGE_SIZE, mmio_ivc_handler, @@ -193,7 +198,9 @@ impl Zone { return; } } - IVC_INFOS.lock().insert(self.id, IvcInfo::from(ivc_configs)); + IVC_INFOS + .lock() + .insert(self.id(), IvcInfo::from(ivc_configs)); } } diff --git a/src/arch/aarch64/trap.rs b/src/arch/aarch64/trap.rs index acd09f06..066f28b7 100644 --- a/src/arch/aarch64/trap.rs +++ b/src/arch/aarch64/trap.rs @@ -390,10 +390,10 @@ fn handle_psci_smc( PsciFnId::PSCI_CPU_ON_32 | PsciFnId::PSCI_CPU_ON_64 => psci_emulate_cpu_on(regs), PsciFnId::PSCI_SYSTEM_OFF => { let zone = this_zone(); - let zone_id = zone.read().id; + let zone_id = zone.id(); let is_root = is_this_root_zone(); - for cpu_id in zone.read().cpu_set.iter_except(this_cpu_data().id) { + for cpu_id in zone.read().cpu_set().iter_except(this_cpu_data().id) { let target_cpu = get_cpu_data(cpu_id); let _lock = target_cpu.ctrl_lock.lock(); target_cpu.zone = None; diff --git a/src/arch/aarch64/zone.rs b/src/arch/aarch64/zone.rs index c4691135..e347e3a2 100644 --- a/src/arch/aarch64/zone.rs +++ b/src/arch/aarch64/zone.rs @@ -25,6 +25,7 @@ use crate::{ impl Zone { pub fn pt_init(&mut self, mem_regions: &[HvConfigMemoryRegion]) -> HvResult { + let mut inner = self.write(); // The first memory region is used to map the guest physical memory. for mem_region in mem_regions.iter() { @@ -34,15 +35,17 @@ impl Zone { } match mem_region.mem_type { MEM_TYPE_RAM | MEM_TYPE_IO => { - self.gpm.insert(MemoryRegion::new_with_offset_mapper( - mem_region.virtual_start as GuestPhysAddr, - mem_region.physical_start as HostPhysAddr, - mem_region.size as _, - flags, - ))? + inner + .gpm_mut() + .insert(MemoryRegion::new_with_offset_mapper( + mem_region.virtual_start as GuestPhysAddr, + mem_region.physical_start as HostPhysAddr, + mem_region.size as _, + flags, + ))? } MEM_TYPE_VIRTIO => { - self.mmio_region_register( + inner.mmio_region_register( mem_region.physical_start as _, mem_region.size as _, mmio_virtio_handler, @@ -50,13 +53,23 @@ impl Zone { ); } _ => { - // hvisor-tool will check memory type. So only root linux can reach here. - panic!("Unsupported memory type: {}", mem_region.mem_type) + // hvisor-tool should check memory type in advance. + if self.id() == 0 { + panic!("Unsupported memory type: {}", mem_region.mem_type); + } + return hv_result_err!( + EINVAL, + format!( + "zone {} has unsupported memory type: {}", + self.id(), + mem_region.mem_type + ) + ); } } } - info!("VM stage 2 memory set: {:#x?}", self.gpm); + info!("VM stage 2 memory set: {:#x?}", inner.gpm()); Ok(()) } @@ -65,10 +78,11 @@ impl Zone { mem_regions: &[HvConfigMemoryRegion], hv_config: &HvArchZoneConfig, ) -> HvResult { + let mut inner = self.write(); // Create a new stage 2 page table for iommu. // Only map the memory regions that are possible to be accessed by devices as DMA buffer. - let pt = self.iommu_pt.as_mut().unwrap(); + let pt = inner.iommu_pt_mut().unwrap(); let flags = MemFlags::READ | MemFlags::WRITE; for mem_region in mem_regions.iter() { match mem_region.mem_type { diff --git a/src/arch/loongarch64/cpu.rs b/src/arch/loongarch64/cpu.rs index 5b524dd4..9c035d7f 100644 --- a/src/arch/loongarch64/cpu.rs +++ b/src/arch/loongarch64/cpu.rs @@ -169,7 +169,7 @@ pub fn get_target_cpu(irq: usize, zone_id: usize) -> usize { find_zone(zone_id) .unwrap() .read() - .cpu_set + .cpu_set() .first_cpu() .unwrap() } diff --git a/src/arch/loongarch64/trap.rs b/src/arch/loongarch64/trap.rs index 29397185..e6f8b25b 100644 --- a/src/arch/loongarch64/trap.rs +++ b/src/arch/loongarch64/trap.rs @@ -608,14 +608,14 @@ pub fn _vcpu_return(ctx: usize) { } else { // since LVZ use GID=0 for hypervisor TLB, we cannot use zone id 0 here // so we add it by 1 - wheatfox - vm_id = z.unwrap().read().id + 1; + vm_id = z.unwrap().id() + 1; } gstat::set_gid(vm_id); gstat::set_pgm(true); trace!( "loongarch64: _vcpu_return: set hardware Guest ID to {} for zone {}", vm_id, - z.unwrap().read().id + z.unwrap().id() ); // Configure guest TLB control gtlbc::set_use_tgid(true); diff --git a/src/arch/loongarch64/zone.rs b/src/arch/loongarch64/zone.rs index 86dfafbc..b1440d09 100644 --- a/src/arch/loongarch64/zone.rs +++ b/src/arch/loongarch64/zone.rs @@ -40,39 +40,46 @@ use spin::Mutex; impl Zone { pub fn pt_init(&mut self, mem_regions: &[HvConfigMemoryRegion]) -> HvResult { + let mut inner = self.write(); // use the new zone config type of init for region in mem_regions { trace!("loongarch64: pt_init: process region: {:#x?}", region); let mem_type = region.mem_type; match mem_type { MEM_TYPE_RAM => { - self.gpm.insert(MemoryRegion::new_with_offset_mapper( - region.virtual_start as GuestPhysAddr, - region.physical_start as HostPhysAddr, - region.size as _, - MemFlags::READ | MemFlags::WRITE | MemFlags::EXECUTE, - ))?; + inner + .gpm_mut() + .insert(MemoryRegion::new_with_offset_mapper( + region.virtual_start as GuestPhysAddr, + region.physical_start as HostPhysAddr, + region.size as _, + MemFlags::READ | MemFlags::WRITE | MemFlags::EXECUTE, + ))?; } MEM_TYPE_IO => { - self.gpm.insert(MemoryRegion::new_with_offset_mapper( - region.virtual_start as GuestPhysAddr, - region.physical_start as HostPhysAddr, - region.size as _, - MemFlags::READ | MemFlags::WRITE | MemFlags::IO, - ))?; + inner + .gpm_mut() + .insert(MemoryRegion::new_with_offset_mapper( + region.virtual_start as GuestPhysAddr, + region.physical_start as HostPhysAddr, + region.size as _, + MemFlags::READ | MemFlags::WRITE | MemFlags::IO, + ))?; } MEM_TYPE_VIRTIO => { info!( "loongarch64: pt_init: register virtio mmio region: {:#x?}", region ); - self.gpm.insert(MemoryRegion::new_with_offset_mapper( - region.virtual_start as GuestPhysAddr, - region.physical_start as HostPhysAddr, - PAGE_SIZE, // since we only need 0x200 size for virtio mmio, but the minimal size is PAGE_SIZE - MemFlags::USER, // we use the USER as a hint flag for invalidating this stage-2 PTE - ))?; - self.mmio_region_register( + inner + .gpm_mut() + .insert(MemoryRegion::new_with_offset_mapper( + region.virtual_start as GuestPhysAddr, + region.physical_start as HostPhysAddr, + PAGE_SIZE, // since we only need 0x200 size for virtio mmio, but the minimal size is PAGE_SIZE + MemFlags::USER, // we use the USER as a hint flag for invalidating this stage-2 PTE + ))?; + inner.mmio_region_register( region.physical_start as _, region.size as _, mmio_virtio_handler, @@ -92,14 +99,14 @@ impl Zone { // 3. chip configuration info!("loongarch64: pt_init: add mmio handler for 0x1fe0_xxxx mmio region"); - self.mmio_region_register(0x1fe0_0000, 0x3000, loongarch_generic_mmio_handler, 0x1234); + inner.mmio_region_register(0x1fe0_0000, 0x3000, loongarch_generic_mmio_handler, 0x1234); - info!("zone stage-2 memory set: {:#x?}", self.gpm); + info!("zone stage-2 memory set: {:#x?}", inner.gpm()); unsafe { // test the page table by querying the first page if mem_regions.len() > 0 { - let r = self - .gpm + let r = inner + .gpm() .page_table_query(mem_regions[0].virtual_start as GuestPhysAddr); debug!("query 0x{:x}: {:#x?}", mem_regions[0].virtual_start, r); // check whether the first page is mapped @@ -674,13 +681,15 @@ pub fn loongarch_generic_mmio_handler(mmio: &mut MMIOAccess, arg: usize) -> HvRe impl Zone { pub fn page_table_emergency(&mut self, vaddr: usize, size: usize) -> HvResult { - self.gpm.insert(MemoryRegion::new_with_offset_mapper( - vaddr as GuestPhysAddr, - vaddr as HostPhysAddr, - size as _, - MemFlags::READ | MemFlags::WRITE | MemFlags::IO, - ))?; - self.gpm.delete(vaddr as GuestPhysAddr, size) + self.write() + .gpm_mut() + .insert(MemoryRegion::new_with_offset_mapper( + vaddr as GuestPhysAddr, + vaddr as HostPhysAddr, + size as _, + MemFlags::READ | MemFlags::WRITE | MemFlags::IO, + ))?; + self.write().gpm_mut().delete(vaddr as GuestPhysAddr, size) } pub fn arch_zone_pre_configuration(&mut self, config: &HvZoneConfig) -> HvResult { diff --git a/src/arch/riscv64/cpu.rs b/src/arch/riscv64/cpu.rs index 966ab9b6..0dea57d1 100644 --- a/src/arch/riscv64/cpu.rs +++ b/src/arch/riscv64/cpu.rs @@ -247,7 +247,7 @@ pub fn get_target_cpu(_irq: usize, zone_id: usize) -> usize { find_zone(zone_id) .unwrap() .read() - .cpu_set + .cpu_set() .first_cpu() .unwrap() } diff --git a/src/arch/riscv64/zone.rs b/src/arch/riscv64/zone.rs index 1f53e97d..6edc4bfe 100644 --- a/src/arch/riscv64/zone.rs +++ b/src/arch/riscv64/zone.rs @@ -22,6 +22,7 @@ use crate::{ }; impl Zone { pub fn pt_init(&mut self, mem_regions: &[HvConfigMemoryRegion]) -> HvResult { + let mut inner = self.write(); for mem_region in mem_regions.iter() { let mut flags = MemFlags::READ | MemFlags::WRITE; // Note: in riscv, base flags are D/A/G/U/W/X, some mem attributes are embedded in the PMA. @@ -31,15 +32,17 @@ impl Zone { } match mem_region.mem_type { MEM_TYPE_RAM | MEM_TYPE_IO => { - self.gpm.insert(MemoryRegion::new_with_offset_mapper( - mem_region.virtual_start as GuestPhysAddr, - mem_region.physical_start as HostPhysAddr, - mem_region.size as _, - flags, - ))? + inner + .gpm_mut() + .insert(MemoryRegion::new_with_offset_mapper( + mem_region.virtual_start as GuestPhysAddr, + mem_region.physical_start as HostPhysAddr, + mem_region.size as _, + flags, + ))? } MEM_TYPE_VIRTIO => { - self.mmio_region_register( + inner.mmio_region_register( mem_region.physical_start as _, mem_region.size as _, mmio_virtio_handler, @@ -51,7 +54,7 @@ impl Zone { } } } - info!("VM stage 2 memory set: {:#x?}", self.gpm); + info!("VM stage 2 memory set: {:#x?}", inner.gpm()); Ok(()) } diff --git a/src/arch/x86_64/hypercall.rs b/src/arch/x86_64/hypercall.rs index 4a228af7..69304786 100644 --- a/src/arch/x86_64/hypercall.rs +++ b/src/arch/x86_64/hypercall.rs @@ -38,7 +38,7 @@ impl<'a> HyperCall<'a> { unsafe { this_zone() .read() - .gpm + .gpm() .page_table_query(config_addr as _) .unwrap() .0 as _ @@ -49,7 +49,7 @@ impl<'a> HyperCall<'a> { let magic_version = unsafe { this_zone() .read() - .gpm + .gpm() .page_table_query(magic_version as usize) .unwrap() .0 as *mut u64 @@ -73,7 +73,7 @@ impl<'a> HyperCall<'a> { let virtio_irq = unsafe { this_zone() .read() - .gpm + .gpm() .page_table_query(virtio_irq as usize) .unwrap() .0 as *mut u32 diff --git a/src/arch/x86_64/ipi.rs b/src/arch/x86_64/ipi.rs index 4c3b6d46..7de5c2cc 100644 --- a/src/arch/x86_64/ipi.rs +++ b/src/arch/x86_64/ipi.rs @@ -91,7 +91,7 @@ pub fn send_ipi(value: u64) -> HvResult { let dest = get_cpu_id(value.get_bits(32..=39) as usize); let cnt = value.get_bits(40..=63) as u32; - let mut cpu_set = this_zone().read().cpu_set; + let mut cpu_set = this_zone().cpu_set(); let cpu_id = this_cpu_id(); let mut dest_set = CpuSet::new(cpu_set.max_cpu_id, 0); diff --git a/src/arch/x86_64/mmio.rs b/src/arch/x86_64/mmio.rs index 7e7443c5..256dc6fe 100644 --- a/src/arch/x86_64/mmio.rs +++ b/src/arch/x86_64/mmio.rs @@ -258,7 +258,7 @@ impl ModRM { } fn gpa_to_hpa(gpa: GuestPhysAddr) -> HvResult { - let (hpa, _, _) = unsafe { this_zone().read().gpm.page_table_query(gpa)? }; + let (hpa, _, _) = unsafe { this_zone().read().gpm().page_table_query(gpa)? }; Ok(hpa) } diff --git a/src/arch/x86_64/zone.rs b/src/arch/x86_64/zone.rs index 6a3b5f0c..5a59075a 100644 --- a/src/arch/x86_64/zone.rs +++ b/src/arch/x86_64/zone.rs @@ -64,6 +64,7 @@ pub struct HvArchZoneConfig { impl Zone { pub fn pt_init(&mut self, mem_regions: &[HvConfigMemoryRegion]) -> HvResult { + let mut inner = self.write(); for mem_region in mem_regions.iter() { let mut flags = MemFlags::READ | MemFlags::WRITE | MemFlags::EXECUTE; if mem_region.mem_type == MEM_TYPE_IO { @@ -71,7 +72,7 @@ impl Zone { } match mem_region.mem_type { MEM_TYPE_RAM | MEM_TYPE_IO | MEM_TYPE_RESERVED => { - self.gpm.insert(MemoryRegion::new_with_offset_mapper( + inner.gpm_mut().insert(MemoryRegion::new_with_offset_mapper( mem_region.virtual_start as GuestPhysAddr, mem_region.physical_start as HostPhysAddr, mem_region.size as _, @@ -79,7 +80,7 @@ impl Zone { )); } MEM_TYPE_VIRTIO => { - self.mmio_region_register( + inner.mmio_region_register( mem_region.physical_start as _, mem_region.size as _, mmio_virtio_handler, @@ -100,16 +101,18 @@ impl Zone { /// called after cpu_set is initialized pub fn arch_zone_pre_configuration(&mut self, config: &HvZoneConfig) -> HvResult { - self.cpu_set.iter().for_each(|cpuid| { + let inner = self.read(); + inner.cpu_set().iter().for_each(|cpuid| { let cpu_data = get_cpu_data(cpuid); // boot cpu - if cpuid == self.cpu_set.first_cpu().unwrap() { + if cpuid == inner.cpu_set().first_cpu().unwrap() { cpu_data.arch_cpu.set_boot_cpu_vm_launch_regs( config.arch_config.kernel_entry_gpa as _, config.arch_config.setup_load_gpa as _, ); } }); + drop(inner); set_msr_bitmap(config.zone_id as _); set_pio_bitmap(config.zone_id as _); @@ -118,6 +121,7 @@ impl Zone { } pub fn arch_zone_post_configuration(&mut self, config: &HvZoneConfig) -> HvResult { + let mut inner = self.write(); /*let mut msix_bar_regions: Vec = Vec::new(); for region in self.pciroot.bar_regions.iter_mut() { // check whether this bar is msi-x table @@ -140,12 +144,12 @@ impl Zone { ); } - if self.id == 0 { + if self.id() == 0 { self.pci_bars_register(&config.pci_config); }*/ - boot::BootParams::fill(&config, &mut self.gpm); - acpi::copy_to_guest_memory_region(&config, &self.cpu_set); + boot::BootParams::fill(&config, inner.gpm_mut()); + acpi::copy_to_guest_memory_region(&config, &inner.cpu_set()); Ok(()) } diff --git a/src/cpu_data.rs b/src/cpu_data.rs index 5c22d1bc..98b1acec 100644 --- a/src/cpu_data.rs +++ b/src/cpu_data.rs @@ -14,7 +14,7 @@ // Authors: // use alloc::sync::Arc; -use spin::{Mutex, RwLock}; +use spin::Mutex; use crate::arch::cpu::{store_cpu_pointer_to_reg, this_cpu_id, ArchCpu}; use crate::consts::{INVALID_ADDRESS, PER_CPU_ARRAY_PTR, PER_CPU_SIZE}; @@ -32,7 +32,7 @@ pub struct PerCpu { pub cpu_on_entry: usize, pub dtb_ipa: usize, pub arch_cpu: ArchCpu, - pub zone: Option>>, + pub zone: Option>, pub ctrl_lock: Mutex<()>, pub boot_cpu: bool, // percpu stack @@ -84,7 +84,7 @@ impl PerCpu { pub fn activate_gpm(&self) { unsafe { - self.zone.clone().unwrap().read().gpm.activate(); + self.zone.clone().unwrap().read().gpm().activate(); } } } @@ -100,7 +100,7 @@ pub fn this_cpu_data<'a>() -> &'a mut PerCpu { } #[allow(unused)] -pub fn this_zone() -> Arc> { +pub fn this_zone() -> Arc { this_cpu_data().zone.clone().unwrap() } diff --git a/src/device/eic7700_syscrg.rs b/src/device/eic7700_syscrg.rs index d6049309..54a43cf8 100644 --- a/src/device/eic7700_syscrg.rs +++ b/src/device/eic7700_syscrg.rs @@ -97,13 +97,14 @@ pub fn virtual_hsp_sp_top_csr_handler(mmio: &mut MMIOAccess, _arg: usize) -> HvR impl Zone { /// Initialize syscon MMIO region. pub fn virtual_syscon_mmio_init(&mut self) { - self.mmio_region_register( + let mut inner = self.write(); + inner.mmio_region_register( EIC7700_SYSCRG_BASE, EIC7700_SYSCRG_SIZE, virtual_syscrg_handler, 0, ); - self.mmio_region_register( + inner.mmio_region_register( EIC7700_HSP_SP_TOP_CSR_BASE, EIC7700_HSP_SP_TOP_CSR_SIZE, virtual_hsp_sp_top_csr_handler, diff --git a/src/device/irqchip/aia/mod.rs b/src/device/irqchip/aia/mod.rs index 1579ee80..695e2998 100644 --- a/src/device/irqchip/aia/mod.rs +++ b/src/device/irqchip/aia/mod.rs @@ -82,7 +82,6 @@ pub fn vaplic_handler(mmio: &mut MMIOAccess, _arg: usize) -> HvResult { .zone .as_ref() .unwrap() - .read() .get_vaplic() .vaplic_emul_access(mmio.address, mmio.size, mmio.value, mmio.is_write); if !mmio.is_write { @@ -104,7 +103,6 @@ pub fn inject_irq(irq: usize, is_hardware: bool) { .zone .as_ref() .unwrap() - .read() .get_vaplic() .vaplic_get_target(irq); let mut hart = (target >> 18) & 0x3FFF; @@ -117,7 +115,7 @@ pub fn inject_irq(irq: usize, is_hardware: bool) { .as_ref() .unwrap() .read() - .cpu_set + .cpu_set() .first_cpu() .unwrap() as u32; imsic_trigger(hart, IMSIC_GUEST_INDEX as u32, eiid); @@ -141,26 +139,29 @@ impl Zone { // Create a new VirtualAPLIC for this Zone. unsafe { if let Some(map) = &mut VAPLIC_MAP { - if map.contains_key(&self.id) { - panic!("VirtualAPLIC for Zone {} already exists!", self.id); + if map.contains_key(&self.id()) { + panic!("VirtualAPLIC for Zone {} already exists!", self.id()); } let vaplic = vaplic::VirtualAPLIC::new( config.arch_config.aplic_base, BOARD_APLIC_INTERRUPTS_NUM, ); // Insert into Map - let _ = map.insert(self.id, vaplic); + let _ = map.insert(self.id(), vaplic); } else { panic!("VAPLIC_MAP is not initialized!"); } } - info!("VirtualAPLIC for Zone {} initialized successfully", self.id); + info!( + "VirtualAPLIC for Zone {} initialized successfully", + self.id() + ); print_keys(); } /// Initial the virtual IMSIC related to thiz Zone. pub fn vimsic_init(&mut self, config: &HvZoneConfig) { - info!("Zone {} vIMSIC init", self.id); + info!("Zone {} vIMSIC init", self.id()); vimsic::vimsic_init(self, IMSIC_S_BASE, IMSIC_GUEST_NUM); } @@ -169,7 +170,7 @@ impl Zone { VAPLIC_MAP .as_ref() .expect("VAPLIC_MAP is not initialized!") - .get(&self.id) + .get(&self.id()) .expect("VirtualAPLIC for this Zone does not exist!") } } @@ -179,7 +180,8 @@ impl Zone { // This func will only be called by one root zone's cpu. let host_aplic = host_aplic(); let vaplic = self.get_vaplic(); - for (index, &word) in self.irq_bitmap.iter().enumerate() { + let zone_r = self.read(); + for (index, &word) in zone_r.irq_bitmap().iter().enumerate() { for bit_position in 0..32 { if word & (1 << bit_position) != 0 { let irq_id = index * 32 + bit_position; @@ -195,7 +197,7 @@ impl Zone { } } - self.cpu_set.iter().for_each(|cpuid| { + self.cpu_set().iter().for_each(|cpuid| { // Clear the events related to this cpu. info!("Clear events related to cpu {}", cpuid); crate::event::clear_events(cpuid); @@ -203,7 +205,7 @@ impl Zone { unsafe { if let Some(map) = &mut VAPLIC_MAP { - map.remove(&self.id); + map.remove(&self.id()); } else { panic!("VAPLIC_MAP is not initialized!"); } @@ -211,14 +213,9 @@ impl Zone { print_keys(); } - fn insert_irq_to_bitmap(&mut self, irq: u32) { - let irq_index = irq / 32; - let irq_bit = irq % 32; - self.irq_bitmap[irq_index as usize] |= 1 << irq_bit; - } - /// irq_bitmap_init, and set these irqs' hw bit in vplic to true. pub fn irq_bitmap_init(&mut self, irqs_bitmap: &[BitmapWord]) { + let mut zone_w = self.write(); // insert to zone.irq_bitmap for i in 0..irqs_bitmap.len() { let word = irqs_bitmap[i]; @@ -232,18 +229,21 @@ impl Zone { self.get_vaplic().vaplic_set_hw(irq_id as usize, true); info!("Set irq {} to hardware interrupt", irq_id); } - self.insert_irq_to_bitmap(irq_id); + let irq_index = irq_id / 32; + let irq_bit = irq_id % 32; + zone_w.irq_bitmap_mut()[irq_index as usize] |= 1 << irq_bit; } } } // print irq_bitmap - for (index, &word) in self.irq_bitmap.iter().enumerate() { + for (index, &word) in zone_w.irq_bitmap().iter().enumerate() { for bit_position in 0..32 { if word & (1 << bit_position) != 0 { let interrupt_number = index * 32 + bit_position; info!( "Found interrupt in Zone {} irq_bitmap: {}", - self.id, interrupt_number + self.id(), + interrupt_number ); } } @@ -254,6 +254,7 @@ impl Zone { if arch.aplic_base == 0 { panic!("vplic_mmio_init: plic_base is null"); } - self.mmio_region_register(arch.aplic_base, arch.aplic_size, vaplic_handler, 0); + self.write() + .mmio_region_register(arch.aplic_base, arch.aplic_size, vaplic_handler, 0); } } diff --git a/src/device/irqchip/aia/vaplic.rs b/src/device/irqchip/aia/vaplic.rs index 795b72f1..88312326 100644 --- a/src/device/irqchip/aia/vaplic.rs +++ b/src/device/irqchip/aia/vaplic.rs @@ -302,7 +302,7 @@ impl VirtualAPLIC { .as_ref() .unwrap() .read() - .cpu_set + .cpu_set() .first_cpu() .unwrap(); let guest_id = (value >> 12) & 0x3f; diff --git a/src/device/irqchip/aia/vimsic.rs b/src/device/irqchip/aia/vimsic.rs index 0e065f4a..9fbfbd29 100644 --- a/src/device/irqchip/aia/vimsic.rs +++ b/src/device/irqchip/aia/vimsic.rs @@ -14,9 +14,10 @@ // Authors: Jingyu Liu // +use alloc::vec::Vec; + use crate::consts::PAGE_SIZE; use crate::memory::GuestPhysAddr; -use crate::memory::HostPhysAddr; use crate::memory::MemFlags; use crate::memory::MemoryRegion; use crate::platform::__board::{IMSIC_GUEST_INDEX, IMSIC_GUEST_NUM, IMSIC_S_BASE}; @@ -33,18 +34,24 @@ use crate::zone::Zone; */ pub fn vimsic_init(zone: &mut Zone, imsic_base: usize, guest_num: usize) { - let paddr = imsic_base as HostPhysAddr; let size = crate::memory::PAGE_SIZE; - zone.cpu_set.iter().for_each(|cpu_id| { + + let cpu_ids: Vec<_> = zone.cpu_set().iter().collect(); + let mut inner = zone.write(); + + cpu_ids.iter().for_each(|cpu_id| { let vcpu_id = cpu_id; // In hvisor, vcpu_id == cpu_id. let imsic_hpa = imsic_base + PAGE_SIZE * ((1 + guest_num) * cpu_id + IMSIC_GUEST_INDEX); // For VM, it couldn't see VS-files. let imsic_gpa = imsic_base + PAGE_SIZE * vcpu_id; // In hvisor, vcpu_id == cpu_id. info!( "Zone {} vIMSIC map hart {} imsic hpa {:#x} gpa {:#x}", - zone.id, cpu_id, imsic_hpa, imsic_gpa + zone.id(), + cpu_id, + imsic_hpa, + imsic_gpa ); - zone.gpm.insert(MemoryRegion::new_with_offset_mapper( + inner.gpm_mut().insert(MemoryRegion::new_with_offset_mapper( imsic_gpa as GuestPhysAddr, imsic_hpa, size, diff --git a/src/device/irqchip/gicv2/vgic.rs b/src/device/irqchip/gicv2/vgic.rs index 19b18268..5016c330 100644 --- a/src/device/irqchip/gicv2/vgic.rs +++ b/src/device/irqchip/gicv2/vgic.rs @@ -40,6 +40,8 @@ const GICV2_REG_WIDTH: usize = 4; impl Zone { // trap all Guest OS accesses to the GIC Distributor registers. pub fn vgicv2_mmio_init(&mut self, arch: &HvArchZoneConfig) { + let zone_id = self.id(); + let mut inner = self.write(); match arch.gic_config { GicConfig::Gicv3(_) => { panic!("GICv3 is not supported in this version of hvisor"); @@ -48,8 +50,8 @@ impl Zone { if gicv2_config.gicd_base == 0 { panic!("vgicv2_mmio_init: gicd_base is null"); } - info!("Initializing GICv2 MMIO regions for zone {}", self.id); - self.mmio_region_register( + info!("Initializing GICv2 MMIO regions for zone {}", zone_id); + inner.mmio_region_register( gicv2_config.gicd_base, gicv2_config.gicd_size, vgicv2_dist_handler, @@ -61,6 +63,8 @@ impl Zone { // remap the GIC CPU interface register address space to point to the GIC virtual CPU interface registers. pub fn vgicv2_remap_init(&mut self, arch: &HvArchZoneConfig) { + let zone_id = self.id(); + let mut inner = self.write(); match arch.gic_config { GicConfig::Gicv3(_) => { panic!("GICv3 is not supported in this version of hvisor"); @@ -78,10 +82,11 @@ impl Zone { } info!( "Remaping GICv2 GICV MMIO regions to GICC MMIO regions for zone {}", - self.id + zone_id ); // map gicv memory region to gicc memory region. - self.gpm + inner + .gpm_mut() .insert(MemoryRegion::new_with_offset_mapper( gicv2_config.gicc_base, gicv2_config.gicv_base, @@ -95,8 +100,10 @@ impl Zone { // store the interrupt number in the irq_bitmap. pub fn irq_bitmap_init(&mut self, irqs_bitmap: &[BitmapWord]) { + let zone_id = self.id(); + let mut inner = self.write(); // Enable each cpu's sgi and ppi access permission - self.irq_bitmap[0] = 0xffff_ffff; + inner.irq_bitmap_mut()[0] = 0xffff_ffff; for i in 0..irqs_bitmap.len() { let word = irqs_bitmap[i]; @@ -104,31 +111,26 @@ impl Zone { for j in 0..CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD { if ((word >> j) & 1) == 1 { let irq_id = (i * CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD + j) as u32; - self.insert_irq_to_bitmap(irq_id); + assert!(irq_id < get_max_int_num() as u32); + let irq_index = irq_id / 32; + let irq_bit = irq_id % 32; + inner.irq_bitmap_mut()[irq_index as usize] |= 1 << irq_bit; } } } - for (index, &word) in self.irq_bitmap.iter().enumerate() { + for (index, &word) in inner.irq_bitmap().iter().enumerate() { for bit_position in 0..32 { if word & (1 << bit_position) != 0 { let interrupt_number = index * 32 + bit_position; info!( "Found interrupt in Zone {} irq_bitmap: {}", - self.id, interrupt_number + zone_id, interrupt_number ); } } } } - - // insert the interrupt number into the irq_bitmap. - fn insert_irq_to_bitmap(&mut self, irq: u32) { - assert!(irq < get_max_int_num() as u32); - let irq_index = irq / 32; - let irq_bit = irq % 32; - self.irq_bitmap[irq_index as usize] |= 1 << irq_bit; - } } pub fn reg_range(base: usize, n: usize, size: usize) -> core::ops::Range { diff --git a/src/device/irqchip/gicv3/gits.rs b/src/device/irqchip/gicv3/gits.rs index 9a44abe8..2b7c3f43 100644 --- a/src/device/irqchip/gicv3/gits.rs +++ b/src/device/irqchip/gicv3/gits.rs @@ -184,7 +184,7 @@ impl Cmdq { self.cbaser_list[zone_id] = value; let gpa_base = value & 0xffffffffff000; unsafe { - let _phy_base = match this_zone().read().gpm.page_table_query(gpa_base) { + let _phy_base = match this_zone().read().gpm().page_table_query(gpa_base) { Ok(p) => self.phy_base_list[zone_id] = p.0, _ => {} }; @@ -235,8 +235,7 @@ impl Cmdq { let code = (value[0] & 0xff) as usize; let mut new_cmd = value.clone(); let binding = this_zone(); - let zone = binding.read(); - let cpuset_bitmap = zone.cpu_set.bitmap; + let cpuset_bitmap = binding.read().cpu_set().bitmap; match code { 0x0b => { let id = value[0] & 0xffffffff00000000; @@ -266,7 +265,7 @@ impl Cmdq { let phys_itt_base = unsafe { this_zone() .read() - .gpm + .gpm() .page_table_query(itt_base as _) .unwrap() .0 diff --git a/src/device/irqchip/gicv3/mod.rs b/src/device/irqchip/gicv3/mod.rs index 921c52e8..a8d74c50 100644 --- a/src/device/irqchip/gicv3/mod.rs +++ b/src/device/irqchip/gicv3/mod.rs @@ -480,7 +480,8 @@ pub fn percpu_init() { impl Zone { pub fn arch_irqchip_reset(&self) { let gicd_base = host_gicd_base(); - for (idx, &mask) in self.irq_bitmap.iter().enumerate() { + let zone = self.read(); + for (idx, &mask) in zone.irq_bitmap().iter().enumerate() { if idx == 0 { continue; } @@ -490,7 +491,7 @@ impl Zone { } } if host_gits_size() != 0 { - gits_reset(self.id); + gits_reset(self.id()); } } } diff --git a/src/device/irqchip/gicv3/vgic.rs b/src/device/irqchip/gicv3/vgic.rs index 8ac7dd87..8caab289 100644 --- a/src/device/irqchip/gicv3/vgic.rs +++ b/src/device/irqchip/gicv3/vgic.rs @@ -37,24 +37,25 @@ pub fn reg_range(base: usize, n: usize, size: usize) -> core::ops::Range impl Zone { pub fn vgicv3_mmio_init(&mut self, arch: &HvArchZoneConfig) { + let mut inner = self.write(); match arch.gic_config { GicConfig::Gicv2(_) => { panic!("vgicv3_mmio_init: GICv2 is not supported in this function"); } GicConfig::Gicv3(ref gicv3_config) => { // GICv3 specific initialization - info!("Initializing GICv3 MMIO regions for zone {}", self.id); + info!("Initializing GICv3 MMIO regions for zone {}", self.id()); if gicv3_config.gicd_base == 0 || gicv3_config.gicr_base == 0 { panic!("vgicv3_mmio_init: gicd_base or gicr_base is null"); } - self.mmio_region_register( + inner.mmio_region_register( gicv3_config.gicd_base, gicv3_config.gicd_size, vgicv3_dist_handler, 0, ); - self.mmio_region_register( + inner.mmio_region_register( gicv3_config.gits_base, gicv3_config.gits_size, vgicv3_its_handler, @@ -67,44 +68,47 @@ impl Zone { "Registering GIC Redistributor region for CPU {} at {:#x?}", cpu, gicr_base ); - self.mmio_region_register(gicr_base, PER_GICR_SIZE, vgicv3_redist_handler, cpu); + inner.mmio_region_register( + gicr_base, + PER_GICR_SIZE, + vgicv3_redist_handler, + cpu, + ); } } } } pub fn irq_bitmap_init(&mut self, irqs_bitmap: &[BitmapWord]) { + let mut inner = self.write(); for i in 0..irqs_bitmap.len() { let word = irqs_bitmap[i]; for j in 0..CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD { if ((word >> j) & 1) == 1 { let irq_id = (i * CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD + j) as u32; - self.insert_irq_to_bitmap(irq_id); + assert!(irq_id < (CONFIG_MAX_INTERRUPTS as u32)); + let irq_index = irq_id / (CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD as u32); + let irq_bit = irq_id % (CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD as u32); + inner.irq_bitmap_mut()[irq_index as usize] |= 1 << irq_bit; } } } - for (index, &word) in self.irq_bitmap.iter().enumerate() { + for (index, &word) in inner.irq_bitmap().iter().enumerate() { for bit_position in 0..CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD { if word & (1 << bit_position) != 0 { let interrupt_number = index * CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD + bit_position; info!( "Found interrupt in Zone {} irq_bitmap: {}", - self.id, interrupt_number + self.id(), + interrupt_number ); } } } } - - fn insert_irq_to_bitmap(&mut self, irq: u32) { - assert!(irq < (CONFIG_MAX_INTERRUPTS as u32)); // CONFIG_MAX_INTERRUPTS is the maximum number of interrupts supported by GICv3 (GICD_TYPER.ITLinesNumber) - let irq_index = irq / (CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD as u32); - let irq_bit = irq % (CONFIG_INTERRUPTS_BITMAP_BITS_PER_WORD as u32); - self.irq_bitmap[irq_index as usize] |= 1 << irq_bit; - } } fn restrict_bitmask_access( @@ -363,7 +367,7 @@ pub fn vgicv3_its_handler(mmio: &mut MMIOAccess, _arg: usize) -> HvResult { if zone_id == 0 { let v_dt_addr = mmio.value & 0xfff_fff_fff_000usize; let phys_dt_trans = - unsafe { this_zone().read().gpm.page_table_query(v_dt_addr) }; + unsafe { this_zone().read().gpm().page_table_query(v_dt_addr) }; match phys_dt_trans { Ok(p) => { mmio.value &= !0xfff_fff_fff_000usize; @@ -383,7 +387,7 @@ pub fn vgicv3_its_handler(mmio: &mut MMIOAccess, _arg: usize) -> HvResult { if zone_id == 0 { let v_ct_addr = mmio.value & 0xfff_fff_fff_000usize; let phys_ct_trans = - unsafe { this_zone().read().gpm.page_table_query(v_ct_addr) }; + unsafe { this_zone().read().gpm().page_table_query(v_ct_addr) }; match phys_ct_trans { Ok(p) => { mmio.value &= !0xfff_fff_fff_000usize; diff --git a/src/device/irqchip/pic/ioapic.rs b/src/device/irqchip/pic/ioapic.rs index 84b6e5a2..75c7b160 100644 --- a/src/device/irqchip/pic/ioapic.rs +++ b/src/device/irqchip/pic/ioapic.rs @@ -181,7 +181,7 @@ impl Zone { if arch.ioapic_base == 0 || arch.ioapic_size == 0 { return; } - self.mmio_region_register( + self.write().mmio_region_register( arch.ioapic_base, arch.ioapic_size, mmio_ioapic_handler, diff --git a/src/device/irqchip/pic/mod.rs b/src/device/irqchip/pic/mod.rs index a72b4e07..8c439891 100644 --- a/src/device/irqchip/pic/mod.rs +++ b/src/device/irqchip/pic/mod.rs @@ -144,6 +144,6 @@ pub fn primary_init_late() {} impl Zone { pub fn arch_irqchip_reset(&self) { - iommu::clear_dma_translation_tables(self.id); + iommu::clear_dma_translation_tables(self.id()); } } diff --git a/src/device/irqchip/plic/mod.rs b/src/device/irqchip/plic/mod.rs index f2fb304d..b0c95978 100644 --- a/src/device/irqchip/plic/mod.rs +++ b/src/device/irqchip/plic/mod.rs @@ -92,10 +92,8 @@ pub fn inject_irq(irq: usize, is_hardware: bool) { // .read() // .get_vplic() // .inject_irq(vcontext_id, irq, is_hardware); - let vplic = { - let zone = this_cpu_data().zone.as_ref().unwrap().read(); - zone.get_vplic() - }; + let zone = this_cpu_data().zone.as_ref().unwrap().clone(); + let vplic = zone.get_vplic(); // Avoid holding the read lock when calling inject_irq vplic.inject_irq(vcontext_id, irq, is_hardware); } @@ -106,8 +104,7 @@ pub fn vcontext_to_pcontext(vcontext_id: usize) -> usize { .zone .as_ref() .unwrap() - .read() - .cpu_set + .cpu_set() .iter() .collect::>(); let index = vcontext_id / NUM_CONTEXTS_PER_HART; @@ -122,8 +119,7 @@ pub fn pcontext_to_vcontext(_pcontext_id: usize) -> usize { .zone .as_ref() .unwrap() - .read() - .cpu_set + .cpu_set() .iter() .collect::>(); let pcpu_id = this_cpu_id(); @@ -147,10 +143,8 @@ pub fn vplic_handler(mmio: &mut MMIOAccess, _arg: usize) -> HvResult { // .read() // .get_vplic() // .vplic_emul_access(mmio.address, mmio.size, mmio.value, mmio.is_write); - let vplic = { - let zone = this_cpu_data().zone.as_ref().unwrap().read(); - zone.get_vplic() - }; + let zone = this_cpu_data().zone.as_ref().unwrap().clone(); + let vplic = zone.get_vplic(); // Avoid holding the read lock when calling vplic_emul_access let value = vplic.vplic_emul_access(mmio.address, mmio.size, mmio.value, mmio.is_write); if !mmio.is_write { @@ -171,10 +165,8 @@ pub fn update_hart_line() { // .read() // .get_vplic() // .update_hart_line(vcontext_id); - let vplic = { - let zone = this_cpu_data().zone.as_ref().unwrap().read(); - zone.get_vplic() - }; + let zone = this_cpu_data().zone.as_ref().unwrap().clone(); + let vplic = zone.get_vplic(); // Avoid holding the read lock when calling update_hart_line vplic.update_hart_line(vcontext_id); } @@ -201,24 +193,27 @@ impl Zone { pub fn vplic_init(&mut self, config: &HvZoneConfig) { // Create a new VirtualPLIC for this Zone. let mut map = VPLIC_MAP.lock(); - if map.contains_key(&self.id) { - panic!("VirtualPLIC for Zone {} already exists!", self.id); + if map.contains_key(&self.id()) { + panic!("VirtualPLIC for Zone {} already exists!", self.id()); } let vplic = vplic::VirtualPLIC::new( config.arch_config.plic_base, BOARD_PLIC_INTERRUPTS_NUM, - self.cpu_num * NUM_CONTEXTS_PER_HART, + self.read().cpu_num() * NUM_CONTEXTS_PER_HART, ); // Insert into Map - map.insert(self.id, Arc::new(vplic)); - info!("VirtualPLIC for Zone {} initialized successfully", self.id); + map.insert(self.id(), Arc::new(vplic)); + info!( + "VirtualPLIC for Zone {} initialized successfully", + self.id() + ); print_keys_from_map(&map); } pub fn get_vplic(&self) -> Arc { VPLIC_MAP .lock() - .get(&self.id) + .get(&self.id()) .expect("No vplic exists for current zone.") .clone() } @@ -228,7 +223,8 @@ impl Zone { // This func will only be called by one root zone's cpu. let host_plic = host_plic(); let _vplic = self.get_vplic(); - for (index, &word) in self.irq_bitmap.iter().enumerate() { + let zone_r = self.read(); + for (index, &word) in zone_r.irq_bitmap().iter().enumerate() { for bit_position in 0..32 { if word & (1 << bit_position) != 0 { let irq_id = index * 32 + bit_position; @@ -240,7 +236,7 @@ impl Zone { info!("Reset irq_id {} priority to 0", irq_id); host_plic.set_priority(irq_id, 0); // Reset enable - self.cpu_set.iter().for_each(|cpuid| { + self.cpu_set().iter().for_each(|cpuid| { let pcontext_id = cpuid * NUM_CONTEXTS_PER_HART + 1; info!( "Reset pcontext_id {} irq_id {} enable to false", @@ -251,7 +247,7 @@ impl Zone { } } } - self.cpu_set.iter().for_each(|cpuid| { + self.cpu_set().iter().for_each(|cpuid| { // Reset threshold let pcontext_id = cpuid * NUM_CONTEXTS_PER_HART + 1; info!("Reset pcontext_id {} threshold to 0", pcontext_id); @@ -262,18 +258,13 @@ impl Zone { }); let mut map = VPLIC_MAP.lock(); - map.remove(&self.id); + map.remove(&self.id()); print_keys_from_map(&map); } - fn insert_irq_to_bitmap(&mut self, irq: u32) { - let irq_index = irq / 32; - let irq_bit = irq % 32; - self.irq_bitmap[irq_index as usize] |= 1 << irq_bit; - } - /// irq_bitmap_init, and set these irqs' hw bit in vplic to true. pub fn irq_bitmap_init(&mut self, irqs_bitmap: &[BitmapWord]) { + let mut zone_w = self.write(); // insert to zone.irq_bitmap for i in 0..irqs_bitmap.len() { let word = irqs_bitmap[i]; @@ -288,19 +279,22 @@ impl Zone { info!("Set irq {} to hardware interrupt", irq_id); } - self.insert_irq_to_bitmap(irq_id); + let irq_index = irq_id / 32; + let irq_bit = irq_id % 32; + zone_w.irq_bitmap_mut()[irq_index as usize] |= 1 << irq_bit; } } } // print irq_bitmap - for (index, &word) in self.irq_bitmap.iter().enumerate() { + for (index, &word) in zone_w.irq_bitmap().iter().enumerate() { for bit_position in 0..32 { if word & (1 << bit_position) != 0 { let interrupt_number = index * 32 + bit_position; info!( "Found interrupt in Zone {} irq_bitmap: {}", - self.id, interrupt_number + self.id(), + interrupt_number ); } } @@ -311,6 +305,7 @@ impl Zone { if arch.plic_base == 0 { panic!("vplic_mmio_init: plic_base is null"); } - self.mmio_region_register(arch.plic_base, arch.plic_size, vplic_handler, 0); + self.write() + .mmio_region_register(arch.plic_base, arch.plic_size, vplic_handler, 0); } } diff --git a/src/device/sifive_ccache/mod.rs b/src/device/sifive_ccache/mod.rs index a4d2a604..d32432cc 100644 --- a/src/device/sifive_ccache/mod.rs +++ b/src/device/sifive_ccache/mod.rs @@ -86,7 +86,7 @@ pub fn virtual_sifive_ccache_handler(mmio: &mut MMIOAccess, _arg: usize) -> HvRe impl Zone { /// Initialize cache controller MMIO region. pub fn virtual_sifive_ccache_mmio_init(&mut self) { - self.mmio_region_register( + self.write().mmio_region_register( SIFIVE_CCACHE_BASE, SIFIVE_CCACHE_SIZE, virtual_sifive_ccache_handler, diff --git a/src/hypercall/mod.rs b/src/hypercall/mod.rs index 55a3b8e1..0e22a4cf 100644 --- a/src/hypercall/mod.rs +++ b/src/hypercall/mod.rs @@ -195,7 +195,7 @@ impl<'a> HyperCall<'a> { ); } let zone = zone_create(config)?; - let boot_cpu = zone.read().cpu_set.first_cpu().unwrap(); + let boot_cpu = zone.read().cpu_set().first_cpu().unwrap(); let target_data = get_cpu_data(boot_cpu as _); let _lock = target_data.ctrl_lock.lock(); @@ -238,7 +238,7 @@ impl<'a> HyperCall<'a> { }; let zone_w = zone.write(); - zone_w.cpu_set.iter().for_each(|cpu_id| { + zone_w.cpu_set().iter().for_each(|cpu_id| { let _lock = get_cpu_data(cpu_id).ctrl_lock.lock(); get_cpu_data(cpu_id).cpu_on_entry = INVALID_ADDRESS; send_event(cpu_id, SGI_IPI_ID as _, IPI_EVENT_SHUTDOWN); @@ -251,7 +251,7 @@ impl<'a> HyperCall<'a> { let mut count: usize = 0; // wait all zone's cpus shutdown - while zone_w.cpu_set.iter().any(|cpu_id| { + while zone_w.cpu_set().iter().any(|cpu_id| { let _lock = get_cpu_data(cpu_id).ctrl_lock.lock(); let power_on = get_cpu_data(cpu_id).arch_cpu.power_on; count += 1; @@ -264,13 +264,13 @@ impl<'a> HyperCall<'a> { power_on }) {} - zone_w.cpu_set.iter().for_each(|cpu_id| { + zone_w.cpu_set().iter().for_each(|cpu_id| { let _lock = get_cpu_data(cpu_id).ctrl_lock.lock(); get_cpu_data(cpu_id).zone = None; }); - zone_w.arch_irqchip_reset(); drop(zone_w); + zone.arch_irqchip_reset(); drop(zone); remove_zone(zone_id as _); info!("zone {} has been shutdown", zone_id); diff --git a/src/memory/mmio.rs b/src/memory/mmio.rs index e96641c1..1d477189 100644 --- a/src/memory/mmio.rs +++ b/src/memory/mmio.rs @@ -85,7 +85,7 @@ pub fn mmio_perform_access(base: usize, mmio: &mut MMIOAccess) { pub fn mmio_handle_access(mmio: &mut MMIOAccess) -> HvResult { let zone = this_zone(); let res = zone.read().find_mmio_region(mmio.address, mmio.size); - let zone_id = zone.read().id; + let zone_id = zone.id(); drop(zone); match res { Some((region, handler, arg)) => { diff --git a/src/pci/pci_config.rs b/src/pci/pci_config.rs index 34f881fc..b126567d 100644 --- a/src/pci/pci_config.rs +++ b/src/pci/pci_config.rs @@ -24,6 +24,9 @@ use crate::{ zone::Zone, }; +#[cfg(feature = "loongarch64_pcie")] +use alloc::vec::Vec; + #[cfg(any( all(feature = "iommu", target_arch = "aarch64"), target_arch = "x86_64" @@ -172,6 +175,7 @@ impl Zone { pci_config: &[HvPciConfig], _num_pci_config: usize, ) -> HvResult { + let mut inner = self.write(); let mut guard = GLOBAL_PCIE_LIST.lock(); for target_pci_config in pci_config { // Skip empty config @@ -258,8 +262,8 @@ impl Zone { target_arch = "x86_64" ))] { - let iommu_pt_addr = if self.iommu_pt.is_some() { - self.iommu_pt.as_ref().unwrap().root_paddr() + let iommu_pt_addr = if inner.iommu_pt().is_some() { + inner.iommu_pt().unwrap().root_paddr() } else { 0 }; @@ -278,12 +282,12 @@ impl Zone { { let mut vdev = dev.read().clone(); vdev.set_vbdf(vbdf); - self.vpci_bus.insert(vbdf, vdev); + inner.vpci_bus_mut().insert(vbdf, vdev); } else { let vdev = guard.remove(&bdf).unwrap(); let mut vdev_inner = vdev.read().clone(); vdev_inner.set_vbdf(vbdf); - self.vpci_bus.insert(vbdf, vdev_inner); + inner.vpci_bus_mut().insert(vbdf, vdev_inner); } } else { // warn!("can not find dev {:#?}", bdf); @@ -301,7 +305,7 @@ impl Zone { + ((bdf.device() as u64) << 15) + ((bdf.function() as u64) << 12); let dev = VirtualPciConfigSpace::virt_dev(bdf, base, dev_type); - self.vpci_bus.insert(vbdf, dev); + inner.vpci_bus_mut().insert(vbdf, dev); } else { warn!("can not find dev {:#?}, unknown device type", bdf); } @@ -311,7 +315,7 @@ impl Zone { } } } - info!("vpci bus init done\n {:#x?}", self.vpci_bus); + info!("vpci bus init done\n {:#x?}", inner.vpci_bus()); Ok(()) } @@ -320,6 +324,10 @@ impl Zone { pci_rootcomplex_config: &[HvPciConfig; CONFIG_PCI_BUS_MAXNUM], _num_pci_config: usize, ) { + #[cfg(feature = "loongarch64_pcie")] + let mut emergency_map_regions: Vec<(usize, usize)> = Vec::new(); + + let mut inner = self.write(); for rootcomplex_config in pci_rootcomplex_config { /* empty config */ if rootcomplex_config.ecam_base == 0 { @@ -328,7 +336,7 @@ impl Zone { #[cfg(feature = "ecam_pcie")] { // use crate::pci::pci_handler::mmio_vpci_direct_handler; - self.mmio_region_register( + inner.mmio_region_register( rootcomplex_config.ecam_base as usize, rootcomplex_config.ecam_size as usize, mmio_vpci_handler, @@ -338,7 +346,7 @@ impl Zone { } #[cfg(feature = "dwc_pcie")] { - self.mmio_region_register( + inner.mmio_region_register( rootcomplex_config.ecam_base as usize, rootcomplex_config.ecam_size as usize, mmio_vpci_handler_dbi, @@ -351,7 +359,7 @@ impl Zone { if let Some(extend_config) = extend_config { if extend_config.apb_base != 0 && extend_config.apb_size != 0 { - self.mmio_region_register( + inner.mmio_region_register( extend_config.apb_base as usize, extend_config.apb_size as usize, mmio_generic_handler, @@ -362,7 +370,7 @@ impl Zone { let cfg_size_half = extend_config.cfg_size / 2; let cfg0_base = extend_config.cfg_base; if cfg0_base != 0 && cfg_size_half != 0 { - self.mmio_region_register( + inner.mmio_region_register( cfg0_base as usize, cfg_size_half as usize, mmio_dwc_cfg_handler, @@ -372,7 +380,7 @@ impl Zone { let cfg1_base = extend_config.cfg_base + cfg_size_half; if cfg1_base != 0 && cfg_size_half != 0 { - self.mmio_region_register( + inner.mmio_region_register( cfg1_base as usize, cfg_size_half as usize, mmio_dwc_cfg_handler, @@ -381,7 +389,7 @@ impl Zone { } if extend_config.io_cfg_atu_shared != 0 { - self.mmio_region_register( + inner.mmio_region_register( rootcomplex_config.io_base as usize, rootcomplex_config.io_size as usize, mmio_dwc_io_handler, @@ -399,13 +407,14 @@ impl Zone { warn!("Failed to initialize ATU0 limit defaults: {:?}", e); } - self.atu_configs + inner + .atu_configs_mut() .insert_atu(rootcomplex_config.ecam_base as usize, atu); - self.atu_configs.insert_cfg_base_mapping( + inner.atu_configs_mut().insert_cfg_base_mapping( extend_config.cfg_base as PciConfigAddress, rootcomplex_config.ecam_base as usize, ); - self.atu_configs.insert_io_base_mapping( + inner.atu_configs_mut().insert_io_base_mapping( rootcomplex_config.io_base as PciConfigAddress, rootcomplex_config.ecam_base as usize, ); @@ -413,16 +422,16 @@ impl Zone { } #[cfg(feature = "loongarch64_pcie")] { - self.mmio_region_register( + inner.mmio_region_register( rootcomplex_config.ecam_base as usize, rootcomplex_config.ecam_size as usize, mmio_vpci_direct_handler, rootcomplex_config.ecam_base as usize, ); - let _ = self.page_table_emergency( + emergency_map_regions.push(( rootcomplex_config.ecam_base as usize, rootcomplex_config.ecam_size as usize, - ); + )); } #[cfg(not(any( feature = "ecam_pcie", @@ -436,5 +445,13 @@ impl Zone { ); } } + + #[cfg(feature = "loongarch64_pcie")] + { + drop(inner); + for (base, size) in emergency_map_regions { + let _ = self.page_table_emergency(base, size); + } + } } } diff --git a/src/pci/pci_handler.rs b/src/pci/pci_handler.rs index 48882762..f08bfb20 100644 --- a/src/pci/pci_handler.rs +++ b/src/pci/pci_handler.rs @@ -312,7 +312,7 @@ fn handle_endpoint_access( let zone = this_zone(); let mut guard = zone.write(); - let gpm = &mut guard.gpm; + let gpm = guard.gpm_mut(); if !gpm .try_delete(old_vaddr.try_into().unwrap(), bar_size as usize) @@ -437,7 +437,7 @@ fn handle_endpoint_access( let zone = this_zone(); let mut guard = zone.write(); - let gpm = &mut guard.gpm; + let gpm = guard.gpm_mut(); if !gpm .try_delete(old_vaddr.try_into().unwrap(), rom_size as usize) @@ -658,8 +658,8 @@ pub fn mmio_vpci_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { let base = mmio.address as PciConfigAddress - offset + _base as PciConfigAddress; let dev: Option = { - let mut guard = zone.write(); - let vbus = &mut guard.vpci_bus; + let guard = zone.read(); + let vbus = guard.vpci_bus(); vbus.get_device_by_base(base) }; @@ -681,11 +681,11 @@ pub fn mmio_dwc_io_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { let guard = zone.read(); let atu_config = guard - .atu_configs + .atu_configs() .get_atu_by_io_base(_base as PciConfigAddress) .and_then(|atu| { guard - .atu_configs + .atu_configs() .get_ecam_by_io_base(_base as PciConfigAddress) .map(|ecam| (*atu, ecam)) }); @@ -722,11 +722,11 @@ pub fn mmio_dwc_cfg_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { let guard = zone.read(); let atu_config = guard - .atu_configs + .atu_configs() .get_atu_by_cfg_base(_base as PciConfigAddress) .and_then(|atu| { guard - .atu_configs + .atu_configs() .get_ecam_by_cfg_base(_base as PciConfigAddress) .map(|ecam| (*atu, ecam)) }); @@ -760,7 +760,7 @@ pub fn mmio_dwc_cfg_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { let dev: Option = { let mut guard = zone.write(); - let vbus = &mut guard.vpci_bus; + let vbus = guard.vpci_bus_mut(); if let Some(dev) = vbus.get_device_by_base(base) { is_dev_belong_to_zone = true; Some(dev) @@ -816,7 +816,10 @@ pub fn mmio_vpci_handler_dbi(mmio: &mut MMIOAccess, _base: usize) -> HvResult { // warn!("set atu0 register {:#X} value {:#X}", atu_offset, mmio.value); - let atu = guard.atu_configs.get_atu_by_ecam_mut(ecam_base).unwrap(); + let atu = guard + .atu_configs_mut() + .get_atu_by_ecam_mut(ecam_base) + .unwrap(); // info!("atu config write {:#?}", atu); @@ -936,7 +939,7 @@ pub fn mmio_vpci_handler_dbi(mmio: &mut MMIOAccess, _base: usize) -> HvResult { let dev: Option = { let mut guard = zone.write(); - let vbus = &mut guard.vpci_bus; + let vbus = guard.vpci_bus_mut(); if let Some(dev) = vbus.get_device_by_base(base) { is_dev_belong_to_zone = true; Some(dev) @@ -983,7 +986,7 @@ pub fn mmio_vpci_direct_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult let dev: Option = { let mut guard = zone.write(); - let vbus = &mut guard.vpci_bus; + let vbus = guard.vpci_bus_mut(); if let Some(dev) = vbus.get_device_by_base(base) { is_dev_belong_to_zone = true; Some(dev) diff --git a/src/pci/pci_struct.rs b/src/pci/pci_struct.rs index 13140269..7232c4f9 100644 --- a/src/pci/pci_struct.rs +++ b/src/pci/pci_struct.rs @@ -1470,7 +1470,7 @@ impl VirtualRootComplex { /* because the base of device may discontinuous,get device by base is simpler */ pub fn get_device_by_base( - &mut self, + &self, base: PciConfigAddress, ) -> Option { let bdf = self.base_to_bdf.get(&base).copied()?; diff --git a/src/pci/pci_test.rs b/src/pci/pci_test.rs index 021ccf3b..182a614d 100644 --- a/src/pci/pci_test.rs +++ b/src/pci/pci_test.rs @@ -57,7 +57,8 @@ pub fn pcie_test() { pub fn pcie_guest_init() { let zone = this_zone(); - let vbus = &mut zone.write().vpci_bus; + let mut zone_w = zone.write(); + let vbus = zone_w.vpci_bus_mut(); let mut guard = GLOBAL_PCIE_LIST_TEST.lock(); @@ -111,7 +112,8 @@ pub fn ecam_pcie_guest_test() { // Get base from VirtualPciConfigSpace and add offset // Use a block scope to ensure the read lock is released before calling mmio_vpci_direct_handler let address = { - let vbus = &zone.read().vpci_bus; + let zone_r = zone.read(); + let vbus = zone_r.vpci_bus(); if let Some(vdev) = vbus.get(&bdf) { vdev.read().get_base() } else { @@ -240,7 +242,8 @@ pub fn ecam_pcie_guest_test64() { // Get base from VirtualPciConfigSpace and add offset // Use a block scope to ensure the read lock is released before calling mmio_vpci_direct_handler let address = { - let vbus = &zone.read().vpci_bus; + let zone_r = zone.read(); + let vbus = zone_r.vpci_bus(); if let Some(vdev) = vbus.get(&bdf) { vdev.read().get_base() } else { diff --git a/src/zone.rs b/src/zone.rs index 6297d1f6..b81ca718 100644 --- a/src/zone.rs +++ b/src/zone.rs @@ -18,7 +18,7 @@ use alloc::vec::Vec; // use psci::error::INVALID_ADDRESS; use crate::consts::{INVALID_ADDRESS, MAX_CPU_NUM}; use crate::pci::pci_struct::VirtualRootComplex; -use spin::RwLock; +use spin::{RwLock, RwLockReadGuard, RwLockWriteGuard}; #[cfg(feature = "dwc_pcie")] use crate::pci::{config_accessors::dwc_atu::AtuConfig, PciConfigAddress}; @@ -34,6 +34,7 @@ use crate::error::HvResult; use crate::memory::addr::GuestPhysAddr; use crate::memory::{MMIOConfig, MMIOHandler, MMIORegion, MemorySet}; use core::panic; +use core::sync::atomic::{AtomicBool, Ordering}; #[cfg(feature = "dwc_pcie")] #[derive(Debug)] @@ -108,36 +109,77 @@ impl VirtualAtuConfigs { } pub struct Zone { - pub name: [u8; CONFIG_NAME_MAXLEN], - pub id: usize, - pub mmio: Vec, - pub cpu_num: usize, - pub cpu_set: CpuSet, - pub irq_bitmap: [u32; 1024 / 32], - pub gpm: MemorySet, - pub iommu_pt: Option>, - pub is_err: bool, - pub vpci_bus: VirtualRootComplex, + name: [u8; CONFIG_NAME_MAXLEN], + id: usize, + is_err: AtomicBool, + inner: RwLock, +} + +pub struct ZoneInner { + mmio: Vec, + cpu_num: usize, + cpu_set: CpuSet, + irq_bitmap: [u32; 1024 / 32], + gpm: MemorySet, + iommu_pt: Option>, + vpci_bus: VirtualRootComplex, #[cfg(feature = "dwc_pcie")] - pub atu_configs: VirtualAtuConfigs, + atu_configs: VirtualAtuConfigs, } impl Zone { + #[allow(dead_code)] pub fn new(zoneid: usize, name: &[u8]) -> Self { Self { name: name.try_into().unwrap(), id: zoneid, + is_err: AtomicBool::new(false), + inner: RwLock::new(ZoneInner::new()), + } + } + + pub fn read(&self) -> RwLockReadGuard<'_, ZoneInner> { + self.inner.read() + } + + pub fn write(&self) -> RwLockWriteGuard<'_, ZoneInner> { + self.inner.write() + } + + pub fn id(&self) -> usize { + self.id + } + + pub fn name(&self) -> [u8; CONFIG_NAME_MAXLEN] { + self.name + } + + pub fn is_err(&self) -> bool { + self.is_err.load(Ordering::Acquire) + } + + pub fn set_err(&self) { + self.is_err.store(true, Ordering::Release); + } + + pub fn cpu_set(&self) -> CpuSet { + self.read().cpu_set() + } +} + +impl ZoneInner { + pub fn new() -> Self { + Self { gpm: new_s2_memory_set(), + mmio: Vec::new(), cpu_num: 0, cpu_set: CpuSet::new(MAX_CPU_NUM as usize, 0), - mmio: Vec::new(), irq_bitmap: [0; 1024 / 32], iommu_pt: if cfg!(feature = "iommu") { Some(new_s2_memory_set()) } else { None }, - is_err: false, vpci_bus: VirtualRootComplex::new(), #[cfg(feature = "dwc_pcie")] atu_configs: VirtualAtuConfigs::new(), @@ -217,11 +259,69 @@ impl Zone { let bit_pos = (irq_id % 32) as usize; (self.irq_bitmap[idx] & (1 << bit_pos)) != 0 } + + pub fn cpu_set(&self) -> CpuSet { + self.cpu_set + } + + pub fn cpu_num(&self) -> usize { + self.cpu_num + } + + pub fn set_cpu_num(&mut self, cpu_num: usize) { + self.cpu_num = cpu_num; + } + + pub fn cpu_set_mut(&mut self) -> &mut CpuSet { + &mut self.cpu_set + } + + pub fn irq_bitmap(&self) -> &[u32; 1024 / 32] { + &self.irq_bitmap + } + + pub fn irq_bitmap_mut(&mut self) -> &mut [u32; 1024 / 32] { + &mut self.irq_bitmap + } + + pub fn gpm(&self) -> &MemorySet { + &self.gpm + } + + pub fn gpm_mut(&mut self) -> &mut MemorySet { + &mut self.gpm + } + + pub fn iommu_pt(&self) -> Option<&MemorySet> { + self.iommu_pt.as_ref() + } + + pub fn iommu_pt_mut(&mut self) -> Option<&mut MemorySet> { + self.iommu_pt.as_mut() + } + + pub fn vpci_bus(&self) -> &VirtualRootComplex { + &self.vpci_bus + } + + pub fn vpci_bus_mut(&mut self) -> &mut VirtualRootComplex { + &mut self.vpci_bus + } + + #[cfg(feature = "dwc_pcie")] + pub fn atu_configs(&self) -> &VirtualAtuConfigs { + &self.atu_configs + } + + #[cfg(feature = "dwc_pcie")] + pub fn atu_configs_mut(&mut self) -> &mut VirtualAtuConfigs { + &mut self.atu_configs + } } -static ZONE_LIST: RwLock>>> = RwLock::new(vec![]); +static ZONE_LIST: RwLock>> = RwLock::new(vec![]); -pub fn root_zone() -> Arc> { +pub fn root_zone() -> Arc { ZONE_LIST.read().get(0).cloned().unwrap() } @@ -230,7 +330,7 @@ pub fn is_this_root_zone() -> bool { } /// Add zone to CELL_LIST -pub fn add_zone(zone: Arc>) { +pub fn add_zone(zone: Arc) { ZONE_LIST.write().push(zone); } @@ -240,17 +340,17 @@ pub fn remove_zone(zone_id: usize) { let (idx, _) = zone_list .iter() .enumerate() - .find(|(_, zone)| zone.read().id == zone_id) + .find(|(_, zone)| zone.id() == zone_id) .unwrap(); let removed_zone = zone_list.remove(idx); assert_eq!(Arc::strong_count(&removed_zone), 1); } -pub fn find_zone(zone_id: usize) -> Option>> { +pub fn find_zone(zone_id: usize) -> Option> { ZONE_LIST .read() .iter() - .find(|zone| zone.read().id == zone_id) + .find(|zone| zone.id() == zone_id) .cloned() } @@ -259,23 +359,20 @@ pub fn all_zones_info() -> Vec { zone_list .iter() - .map(|zone| { - let zone_lock = zone.read(); - ZoneInfo { - zone_id: zone_lock.id as u32, - cpus: zone_lock.cpu_set.bitmap, - name: zone_lock.name.clone(), - is_err: zone_lock.is_err as u8, - } + .map(|zone| ZoneInfo { + zone_id: zone.id() as u32, + cpus: zone.read().cpu_set().bitmap, + name: zone.name(), + is_err: zone.is_err() as u8, }) .collect() } pub fn this_zone_id() -> usize { - this_zone().read().id + this_zone().id() } -pub fn zone_create(config: &HvZoneConfig) -> HvResult>> { +pub fn zone_create(config: &HvZoneConfig) -> HvResult> { // we create the new zone here // TODO: create Zone with cpu_set let zone_id = config.zone_id as usize; @@ -288,7 +385,7 @@ pub fn zone_create(config: &HvZoneConfig) -> HvResult>> { } let mut zone = Zone::new(zone_id, &config.name); - zone.pt_init(config.memory_regions()).unwrap(); + zone.pt_init(config.memory_regions())?; zone.mmio_init(&config.arch_config); #[cfg(feature = "pci")] @@ -316,30 +413,29 @@ pub fn zone_create(config: &HvZoneConfig) -> HvResult>> { let mut cpu_num = 0; for cpu_id in config.cpus().iter() { - if let Some(zone) = get_cpu_data(*cpu_id as _).zone.clone() { + if let Some(existing_zone) = get_cpu_data(*cpu_id as _).zone.clone() { return hv_result_err!( EBUSY, format!( "Failed to create zone: cpu {} already belongs to zone {}", cpu_id, - zone.read().id + existing_zone.id() ) ); } - zone.cpu_set.set_bit(*cpu_id as _); + zone.write().cpu_set_mut().set_bit(*cpu_id as _); cpu_num += 1; } - zone.cpu_num = cpu_num; - info!("zone cpu_set: {:#b}", zone.cpu_set.bitmap); - let cpu_set = zone.cpu_set; + zone.write().set_cpu_num(cpu_num); + let cpu_set = zone.read().cpu_set(); + info!("zone cpu_set: {:#b}", cpu_set.bitmap); zone.arch_zone_pre_configuration(config)?; // #[cfg(target_arch = "aarch64")] // zone.ivc_init(config.ivc_config()); #[cfg(all(feature = "iommu", target_arch = "aarch64"))] - zone.iommu_pt_init(config.memory_regions(), &config.arch_config) - .unwrap(); + zone.iommu_pt_init(config.memory_regions(), &config.arch_config)?; /* loongarch page table emergency */ /* Kai: Maybe unnecessary but i can't boot vms on my 3A6000 PC without this function. */ @@ -372,7 +468,7 @@ pub fn zone_create(config: &HvZoneConfig) -> HvResult>> { } } - let new_zone_pointer = Arc::new(RwLock::new(zone)); + let new_zone_pointer = Arc::new(zone); { cpu_set.iter().for_each(|cpuid| { let cpu_data = get_cpu_data(cpuid); @@ -407,13 +503,10 @@ pub fn zone_error() { panic!("root zone has some error"); } let zone = this_zone(); - let zone_id = zone.read().id; + let zone_id = zone.id(); error!("zone {} has some error, please shut down it", zone_id); - let mut zone_w = zone.write(); - zone_w.is_err = true; - - drop(zone_w); + zone.set_err(); drop(zone); } @@ -424,7 +517,7 @@ fn test_add_and_remove_zone() { for i in 0..zone_count { let u8name_array = [i as u8; CONFIG_NAME_MAXLEN]; let zone = Zone::new(i, &u8name_array); - ZONE_LIST.write().push(Arc::new(RwLock::new(zone))); + ZONE_LIST.write().push(Arc::new(zone)); } for i in 0..zone_count { remove_zone(i);