diff --git a/platform/aarch64/imx8mp/board.rs b/platform/aarch64/imx8mp/board.rs index 555001f0..4e094ca2 100644 --- a/platform/aarch64/imx8mp/board.rs +++ b/platform/aarch64/imx8mp/board.rs @@ -13,7 +13,7 @@ // // Authors: // -use crate::{arch::zone::HvArchZoneConfig, config::*}; +use crate::{arch::zone::{HvArchZoneConfig,GicConfig,Gicv3Config}, config::*}; pub const BOARD_NAME: &str = "imx8mp"; @@ -75,13 +75,13 @@ pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 8] = [ virtual_start: 0x32c00000, size: 0x400000, }, // hdmi - // bus@30800000 - // HvConfigMemoryRegion { - // mem_type: MEM_TYPE_IO, - // physical_start: 0x30890000, - // virtual_start: 0x30890000, - // size: 0x1000, - // }, // serial + // bus@30800000 + // HvConfigMemoryRegion { + // mem_type: MEM_TYPE_IO, + // physical_start: 0x30890000, + // virtual_start: 0x30890000, + // size: 0x1000, + // }, // serial ]; pub const ROOT_ZONE_IRQS: [u32; 28] = [ @@ -90,19 +90,15 @@ pub const ROOT_ZONE_IRQS: [u32; 28] = [ ]; pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { - gicd_base: 0x38800000, - gicd_size: 0x10000, - gicr_base: 0x38880000, - gicr_size: 0xc0000, - gicc_base: 0, - gicc_size: 0, - gicc_offset: 0x0, - gich_base: 0, - gich_size: 0, - gicv_base: 0, - gicv_size: 0, - gits_base: 0, - gits_size: 0, + gic_version: 3, + gic_config: GicConfig::Gicv3(Gicv3Config { + gicd_base: 0x38800000, + gicd_size: 0x10000, + gicr_base: 0x38880000, + gicr_size: 0xc0000, + gits_base: 0x0, + gits_size: 0x0, + }), }; -pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; +pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; \ No newline at end of file diff --git a/platform/aarch64/ok6254-c/board.rs b/platform/aarch64/ok6254-c/board.rs index 862f0292..68697405 100644 --- a/platform/aarch64/ok6254-c/board.rs +++ b/platform/aarch64/ok6254-c/board.rs @@ -14,7 +14,7 @@ // Authors: // -use crate::{arch::zone::HvArchZoneConfig, config::*}; +use crate::{arch::zone::{HvArchZoneConfig,GicConfig,Gicv3Config}, config::*}; pub const BOARD_NAME: &str = "ok6254"; pub const BOARD_NCPUS: usize = 4; @@ -106,19 +106,15 @@ pub const ROOT_ZONE_IRQS: [u32; 13] = [ ]; pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { - gicd_base: 0x1800000, - gicd_size: 0x10000, - gicr_base: 0x1880000, - gicr_size: 0xc0000, - gicc_base: 0x0, - gicc_size: 0x0, - gicc_offset: 0x0, - gich_base: 0x0, - gich_size: 0x0, - gicv_base: 0x0, - gicv_size: 0x00000, - gits_base: 0x1820000, - gits_size: 0x10000, + gic_version: 3, + gic_config: GicConfig::Gicv3(Gicv3Config { + gicd_base: 0x1800000, + gicd_size: 0x10000, + gicr_base: 0x1880000, + gicr_size: 0xc0000, + gits_base: 0x1820000, + gits_size: 0x10000, + }), }; -pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; +pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; \ No newline at end of file diff --git a/platform/aarch64/qemu-gicv2/board.rs b/platform/aarch64/qemu-gicv2/board.rs index c9d6f8f8..5bf74cdc 100644 --- a/platform/aarch64/qemu-gicv2/board.rs +++ b/platform/aarch64/qemu-gicv2/board.rs @@ -12,8 +12,8 @@ // https://www.syswonder.org // // Authors: -// -use crate::{arch::zone::HvArchZoneConfig, config::*}; +// Hangqi Ren <2572131118@qq.com> +use crate::{arch::zone::{HvArchZoneConfig,GicConfig,Gicv2Config}, config::*}; pub const BOARD_NAME: &str = "qemu-gicv2"; @@ -52,21 +52,21 @@ pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 3] = [ pub const ROOT_ZONE_IRQS: [u32; 9] = [33, 64, 77, 79, 35, 36, 37, 38, 65]; pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { - gicd_base: 0x8000000, - gicd_size: 0x10000, - gicr_base: 0x80a0000, - gicr_size: 0xf60000, - gicc_base: 0x8010000, - gicc_size: 0x10000, - gicc_offset: 0x0, - gich_base: 0x8030000, - gich_size: 0x10000, - gicv_base: 0x8040000, - gicv_size: 0x10000, - gits_base: 0x8080000, - gits_size: 0x20000, + gic_version: 2, + gic_config: GicConfig::Gicv2(Gicv2Config { + gicd_base: 0x8000000, + gicd_size: 0x10000, + gicc_base: 0x8010000, + gicc_size: 0x10000, + gicc_offset: 0x0, + gich_base: 0x8030000, + gich_size: 0x10000, + gicv_base: 0x8040000, + gicv_size: 0x10000, + }), }; + pub const ROOT_PCI_CONFIG: HvPciConfig = HvPciConfig { ecam_base: 0x4010000000, ecam_size: 0x10000000, @@ -83,4 +83,4 @@ pub const ROOT_PCI_CONFIG: HvPciConfig = HvPciConfig { pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; -pub const ROOT_PCI_DEVS: [u64; 2] = [0, 1 << 3]; +pub const ROOT_PCI_DEVS: [u64; 2] = [0, 1 << 3]; \ No newline at end of file diff --git a/platform/aarch64/qemu-gicv3/board.rs b/platform/aarch64/qemu-gicv3/board.rs index 9ff4be52..c8ea830a 100644 --- a/platform/aarch64/qemu-gicv3/board.rs +++ b/platform/aarch64/qemu-gicv3/board.rs @@ -13,7 +13,10 @@ // // Authors: // -use crate::{arch::zone::HvArchZoneConfig, config::*}; +use crate::{ + arch::zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + config::*, +}; pub const BOARD_NAME: &str = "qemu-gicv3"; @@ -52,19 +55,15 @@ pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 3] = [ pub const ROOT_ZONE_IRQS: [u32; 9] = [33, 64, 77, 79, 35, 36, 37, 38, 65]; pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { - gicd_base: 0x8000000, - gicd_size: 0x10000, - gicr_base: 0x80a0000, - gicr_size: 0xf60000, - gicc_base: 0x8010000, - gicc_size: 0x10000, - gicc_offset: 0x0, - gich_base: 0x8030000, - gich_size: 0x10000, - gicv_base: 0x8040000, - gicv_size: 0x10000, - gits_base: 0x8080000, - gits_size: 0x20000, + gic_version: 3, + gic_config: GicConfig::Gicv3(Gicv3Config { + gicd_base: 0x8000000, + gicd_size: 0x10000, + gicr_base: 0x80a0000, + gicr_size: 0xf60000, + gits_base: 0x8080000, + gits_size: 0x20000, + }), }; pub const ROOT_PCI_CONFIG: HvPciConfig = HvPciConfig { diff --git a/platform/aarch64/rk3568/board.rs b/platform/aarch64/rk3568/board.rs index 12845b62..f0989bbe 100644 --- a/platform/aarch64/rk3568/board.rs +++ b/platform/aarch64/rk3568/board.rs @@ -14,7 +14,7 @@ // Authors: // -use crate::{arch::zone::HvArchZoneConfig, config::*}; +use crate::{arch::zone::{HvArchZoneConfig,GicConfig,Gicv3Config}, config::*}; pub const BOARD_NAME: &str = "rk3568"; @@ -163,23 +163,20 @@ pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 19] = [ ]; pub const ROOT_ZONE_IRQS: [u32; 20] = [ - 0x84, 0x98, 0x40, 0x104, 0x105, 0x106, 0x107, 0x2d, 0x2e, 0x2b, 0x2a, 0x29, 0x33, 0x96, 0x11c, 0x44, 0x43, 0x42, 0x41, 0x8d]; + 0x84, 0x98, 0x40, 0x104, 0x105, 0x106, 0x107, 0x2d, 0x2e, 0x2b, 0x2a, 0x29, 0x33, 0x96, 0x11c, 0x44, 0x43, 0x42, 0x41, 0x8d]; pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { - gicd_base: 0xfd400000, - gicd_size: 0x10000, - gicr_base: 0xfd460000, - gicr_size: 0xc0000, - gicc_base: 0, - gicc_size: 0, - gicc_offset: 0x0, - gich_base: 0, - gich_size: 0, - gicv_base: 0, - gicv_size: 0, - gits_base: 0, - gits_size: 0, + gic_version: 3, + gic_config: GicConfig::Gicv3(Gicv3Config { + gicd_base: 0xfd400000, + gicd_size: 0x10000, + gicr_base: 0xfd460000, + gicr_size: 0xc0000, + gits_base: 0x0, + gits_size: 0x0, + }), }; + pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; -pub const ROOT_PCI_DEVS: [u64; 0] = []; +pub const ROOT_PCI_DEVS: [u64; 0] = []; \ No newline at end of file diff --git a/platform/aarch64/rk3588/board.rs b/platform/aarch64/rk3588/board.rs index 95680030..bbedd76c 100644 --- a/platform/aarch64/rk3588/board.rs +++ b/platform/aarch64/rk3588/board.rs @@ -13,7 +13,7 @@ // // Authors: // -use crate::{arch::zone::HvArchZoneConfig, config::*}; +use crate::{arch::zone::{HvArchZoneConfig,GicConfig,Gicv3Config}, config::*}; // [ 17.796762] node 0: [mem 0x0000000000200000-0x000000000047ffff] // [ 17.797335] node 0: [mem 0x0000000000480000-0x000000000087ffff] @@ -146,19 +146,15 @@ pub const ROOT_ZONE_IRQS: [u32; 29] = [ ]; pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { - gicd_base: 0xfe600000, - gicd_size: 0x10000, - gicr_base: 0xfe680000, - gicr_size: 0x100000, - gicc_base: 0x8010000, - gicc_size: 0x10000, - gicc_offset: 0x0, - gich_base: 0x8030000, - gich_size: 0x10000, - gicv_base: 0x8040000, - gicv_size: 0x10000, - gits_base: 0x8080000, - gits_size: 0x20000, + gic_version: 3, + gic_config: GicConfig::Gicv3(Gicv3Config { + gicd_base: 0xfe600000, + gicd_size: 0x10000, + gicr_base: 0xfe680000, + gicr_size: 0x100000, + gits_base: 0x8080000, + gits_size: 0x20000, + }), }; pub const ROOT_PCI_CONFIG: HvPciConfig = HvPciConfig { @@ -177,4 +173,4 @@ pub const ROOT_PCI_CONFIG: HvPciConfig = HvPciConfig { pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; -pub const ROOT_PCI_DEVS: [u64; 2] = [0, 1 << 3]; +pub const ROOT_PCI_DEVS: [u64; 2] = [0, 1 << 3]; \ No newline at end of file diff --git a/platform/aarch64/zcu102/board.rs b/platform/aarch64/zcu102/board.rs index 54049234..e331365e 100644 --- a/platform/aarch64/zcu102/board.rs +++ b/platform/aarch64/zcu102/board.rs @@ -12,9 +12,9 @@ // https://www.syswonder.org // // Authors: -// +// Hangqi Ren <2572131118@qq.com> use crate::config::HvConfigMemoryRegion; -use crate::{arch::zone::HvArchZoneConfig, config::*}; +use crate::{arch::zone::{HvArchZoneConfig,GicConfig,Gicv2Config}, config::*}; pub const BOARD_NAME: &str = "zcu102"; @@ -69,19 +69,18 @@ pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 5] = [ pub const ROOT_ZONE_IRQS: [u32; 8] = [53, 81, 67, 175, 176, 177, 178, 64]; pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { - gicd_base: 0xf9010000, - gicd_size: 0x10000, - gicr_base: 0x80a0000, - gicr_size: 0xf60000, - gits_base: 0x20000, - gits_size: 0x20000, - gicc_base: 0xf9020000, - gicc_size: 0x20000, - gicc_offset: 0xf000, - gich_base: 0xf9040000, - gich_size: 0x20000, - gicv_base: 0xf9060000, - gicv_size: 0x20000, + gic_version: 2, + gic_config: GicConfig::Gicv2(Gicv2Config { + gicd_base: 0xf9010000, + gicd_size: 0x10000, + gicc_base: 0xf9020000, + gicc_size: 0x20000, + gicc_offset: 0xf000, + gich_base: 0xf9040000, + gich_size: 0x20000, + gicv_base: 0xf9060000, + gicv_size: 0x20000, + }), }; -pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; +pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; \ No newline at end of file diff --git a/src/arch/aarch64/zone.rs b/src/arch/aarch64/zone.rs index 037750e4..a404126e 100644 --- a/src/arch/aarch64/zone.rs +++ b/src/arch/aarch64/zone.rs @@ -64,17 +64,38 @@ impl Zone { #[repr(C)] #[derive(Debug, Clone)] pub struct HvArchZoneConfig { + pub gic_version: usize, + pub gic_config: GicConfig, +} + +#[repr(C, usize)] +#[derive(Debug, Clone)] +pub enum GicConfig { + Gicv2(Gicv2Config), + Gicv3(Gicv3Config), +} + +#[repr(C)] +#[derive(Debug, Clone)] +pub struct Gicv2Config { pub gicd_base: usize, pub gicd_size: usize, - pub gicr_base: usize, - pub gicr_size: usize, - pub gits_base: usize, - pub gits_size: usize, pub gicc_base: usize, - pub gicc_offset: usize, pub gicc_size: usize, + pub gicc_offset: usize, pub gich_base: usize, pub gich_size: usize, pub gicv_base: usize, pub gicv_size: usize, } + +#[repr(C)] +#[derive(Debug, Clone)] +pub struct Gicv3Config { + pub gicd_base: usize, + pub gicd_size: usize, + pub gicr_base: usize, + pub gicr_size: usize, + pub gits_base: usize, + pub gits_size: usize, +} diff --git a/src/device/irqchip/gicv2/gic.rs b/src/device/irqchip/gicv2/gic.rs index 50356341..ffe491e2 100644 --- a/src/device/irqchip/gicv2/gic.rs +++ b/src/device/irqchip/gicv2/gic.rs @@ -12,9 +12,8 @@ // https://www.syswonder.org // // Authors: -// +// Hangqi Ren <2572131118@qq.com> use crate::arch::cpu::this_cpu_id; -use crate::consts; use crate::device::irqchip::gicv2::gicc::GICC; use crate::device::irqchip::gicv2::gicd::GICV2_SGIS_NUM; use crate::device::irqchip::gicv2::gich::{ @@ -31,7 +30,7 @@ use alloc::collections::VecDeque; use alloc::vec::Vec; use spin::{Mutex, Once}; -pub const MAX_CPU_NUM: usize = consts::MAX_CPU_NUM; +pub const MAX_CPU_NUM: usize = 8; pub const MAINTENACE_INTERRUPT: u64 = 25; pub fn gicv2_handle_irq() { @@ -57,7 +56,7 @@ pub fn gicv2_handle_irq() { } pub fn get_pending_irq() -> Option { - let iar = GICC.get_iar() as usize; + let iar = GICC.get().unwrap().get_iar() as usize; let irq = iar & 0x3ff; if irq >= 1023 { None @@ -68,22 +67,22 @@ pub fn get_pending_irq() -> Option { // deactivate irq: GIC doesn't care CPU ID. pub fn deactivate_irq(irq_id: usize) { - GICC.set_eoir(irq_id as u32); + GICC.get().unwrap().set_eoir(irq_id as u32); if irq_id < GICV2_SGIS_NUM { - GICC.set_dir(irq_id as u32); + GICC.get().unwrap().set_dir(irq_id as u32); } } pub fn change_underflow_maintenance(is_enable: bool) { trace!("enable_maintenace_interrupt, is_enable is {}", is_enable); - let mut hcr = GICH.get_hcr(); + let mut hcr = GICH.get().unwrap().get_hcr(); trace!("hcr is {}", hcr); if is_enable { hcr |= GICV2_GICH_HCR_UIE; } else { hcr &= !GICV2_GICH_HCR_UIE; } - GICH.set_hcr(hcr); + GICH.get().unwrap().set_hcr(hcr); } fn handle_maintenace_interrupt() { @@ -103,8 +102,9 @@ fn handle_maintenace_interrupt() { } pub fn inject_irq(irq_id: usize, is_sgi: bool) -> bool { - let elrsr: u64 = (GICH.get_elrsr(1) as u64) << 32 | GICH.get_elrsr(0) as u64; - let lr_num: isize = GICH.get_lr_num() as isize; + let elrsr: u64 = + (GICH.get().unwrap().get_elrsr(1) as u64) << 32 | GICH.get().unwrap().get_elrsr(0) as u64; + let lr_num: isize = GICH.get().unwrap().get_lr_num() as isize; let lr_pint_mask: usize = 0x3ff << 10; let mut free_lr: isize = -1; for i in 0..lr_num { @@ -112,7 +112,7 @@ pub fn inject_irq(irq_id: usize, is_sgi: bool) -> bool { free_lr = i; continue; } - let lr = GICH.get_lr(i as usize) as usize; + let lr = GICH.get().unwrap().get_lr(i as usize) as usize; let pint = (lr & lr_pint_mask) >> 10; if pint == irq_id { trace!("virtual irq {} enables again", irq_id); @@ -122,7 +122,7 @@ pub fn inject_irq(irq_id: usize, is_sgi: bool) -> bool { if free_lr == -1 { warn!("no free lr"); for i in 0..lr_num { - let lr = GICH.get_lr(i as usize) as usize; + let lr = GICH.get().unwrap().get_lr(i as usize) as usize; warn!("lr[{}]: {:#x}", i, lr); } PENDING_VIRQS @@ -147,7 +147,7 @@ pub fn inject_irq(irq_id: usize, is_sgi: bool) -> bool { // config hw bit 31 val = val | GICV2_GICH_LR_HW; } - GICH.set_lr(free_lr as usize, val as u32); + GICH.get().unwrap().set_lr(free_lr as usize, val as u32); true } } diff --git a/src/device/irqchip/gicv2/gic_ref.rs b/src/device/irqchip/gicv2/gic_ref.rs index b86f2f92..833d7e48 100644 --- a/src/device/irqchip/gicv2/gic_ref.rs +++ b/src/device/irqchip/gicv2/gic_ref.rs @@ -12,12 +12,8 @@ // https://www.syswonder.org // // Authors: -// +// Hangqi Ren <2572131118@qq.com> use core::marker::PhantomData; -/// A struct definition that wraps around a bare pointer -/// author: ForeverYolo -/// references: -/// rust_shyper: https://gitee.com/openeuler/rust_shyper use core::ops::Deref; use core::ptr::NonNull; diff --git a/src/device/irqchip/gicv2/gicc.rs b/src/device/irqchip/gicv2/gicc.rs index 41a9f0c7..a5f14df3 100644 --- a/src/device/irqchip/gicv2/gicc.rs +++ b/src/device/irqchip/gicv2/gicc.rs @@ -12,9 +12,10 @@ // https://www.syswonder.org // // Authors: -// +// Hangqi Ren <2572131118@qq.com> #![allow(unused_variables)] #![allow(dead_code)] + use crate::device::irqchip::gicv2::gic_ref::GicRef; use crate::device::irqchip::gicv2::gicd::GICD; use crate::device::irqchip::gicv2::gich::{ @@ -22,6 +23,7 @@ use crate::device::irqchip::gicv2::gich::{ GICV2_GICH_VMCR_VMGRP0EN, }; use crate::device::irqchip::gicv2::GICV2; +use spin::Once; /// gicc layout definition and functions for gicc operations. /// author : ForeverYolo /// reference: @@ -83,14 +85,19 @@ register_structs! { unsafe impl Sync for GicCpuInterface {} // Each CPU holds one GICC. -pub static GICC: GicRef = - unsafe { GicRef::new(GICV2.gicc_base as *const GicCpuInterface) }; +pub static GICC: Once> = Once::new(); + +pub fn gicc_init(gicc_base: usize) { + unsafe { + GICC.call_once(|| GicRef::new(gicc_base as *const GicCpuInterface)); + } +} impl GicCpuInterface { // init GICC for each CPU. pub fn init(&self) { // Ensure all SGIs disabled. - GICD.set_icenabler(0, 0x0000FFFF); + GICD.get().unwrap().set_icenabler(0, 0x0000FFFF); // get ctrl and pmr value let gicc_ctrl = self.CTLR.get(); let gicc_pmr = self.PMR.get(); @@ -108,18 +115,18 @@ impl GicCpuInterface { if gicc_ctrl & GICV2_GICC_CTRL_EOIMODES != 0 { vmcr |= GICV2_GICH_VMCR_VEM; } - GICH.set_vmcr(vmcr); + GICH.get().unwrap().set_vmcr(vmcr); // Enable virtual CPU interface operation. - GICH.set_hcr(GICV2_GICH_HCR_EN); + GICH.get().unwrap().set_hcr(GICV2_GICH_HCR_EN); // Clear all lr registers in GICH. - GICH.clear_all_lr(); + GICH.get().unwrap().clear_all_lr(); // Deactivate all active and pending SGIS - let gicd_isactive = GICD.get_isactiver(0); - let gicd_ispend = GICD.get_spendsgir(0); - GICD.set_icactiver(0, gicd_isactive & 0xffff); - GICD.set_cpendsgir(0, gicd_ispend & 0xffff); + let gicd_isactive = GICD.get().unwrap().get_isactiver(0); + let gicd_ispend = GICD.get().unwrap().get_spendsgir(0); + GICD.get().unwrap().set_icactiver(0, gicd_isactive & 0xffff); + GICD.get().unwrap().set_cpendsgir(0, gicd_ispend & 0xffff); // re-enable all SGIs - GICD.set_isenabler(0, 0x0000FFFF); + GICD.get().unwrap().set_isenabler(0, 0x0000FFFF); info!("GICV2: GICC init done."); } diff --git a/src/device/irqchip/gicv2/gicd.rs b/src/device/irqchip/gicv2/gicd.rs index bc8fab22..dd9f3283 100644 --- a/src/device/irqchip/gicv2/gicd.rs +++ b/src/device/irqchip/gicv2/gicd.rs @@ -12,7 +12,7 @@ // https://www.syswonder.org // // Authors: -// +// Hangqi Ren <2572131118@qq.com> #![allow(unused_variables)] #![allow(dead_code)] use crate::device::irqchip::gicv2::gic_ref::GicRef; @@ -21,7 +21,7 @@ use crate::device::irqchip::gicv2::GICV2; /// author : ForeverYolo /// reference: /// 1. gicv2 spec : https://www.cl.cam.ac.uk/research/srg/han/ACS-P35/zynq/arm_gic_architecture_specification.pdf -use spin::Mutex; +use spin::{Mutex, Once}; use tock_registers::interfaces::{Readable, Writeable}; use tock_registers::register_structs; use tock_registers::registers::{ReadOnly, ReadWrite}; @@ -100,10 +100,13 @@ register_structs! { unsafe impl Sync for GicDistributer {} // GICD is globally unique. -pub static GICD: GicRef = - unsafe { GicRef::new(GICV2.gicd_base as *const GicDistributer) }; +pub static GICD: Once> = Once::new(); pub static GICD_LOCK: Mutex<()> = Mutex::new(()); +pub fn gicd_init(gicd_base: usize) { + GICD.call_once(|| unsafe { GicRef::new(gicd_base as *const GicDistributer) }); +} + impl GicDistributer { // init GICD globally and enable it. pub fn global_init(&self) { @@ -187,7 +190,7 @@ impl GicDistributer { // Get the maximum number of interrupt IDs that the GIC supports. pub fn get_max_int_num() -> usize { - let value = (GICD.TYPER.get() & 0b11111) as usize; + let value = (GICD.get().unwrap().TYPER.get() & 0b11111) as usize; (value + 1) * 32 } @@ -198,9 +201,9 @@ pub fn is_spi(irqn: usize) -> bool { // Get the base address of GICD. pub fn host_gicd_base() -> usize { - GICV2.gicd_base + GICV2.get().unwrap().gicd_base } pub fn set_ispender(index: usize, value: u32) { - GICD.set_ispender(index, value); + GICD.get().unwrap().set_ispender(index, value); } diff --git a/src/device/irqchip/gicv2/gich.rs b/src/device/irqchip/gicv2/gich.rs index e1dc2bae..982ff7ad 100644 --- a/src/device/irqchip/gicv2/gich.rs +++ b/src/device/irqchip/gicv2/gich.rs @@ -12,11 +12,12 @@ // https://www.syswonder.org // // Authors: -// +// Hangqi Ren <2572131118@qq.com> #![allow(unused_variables)] #![allow(dead_code)] use crate::device::irqchip::gicv2::gic_ref::GicRef; use crate::device::irqchip::gicv2::GICV2; +use spin::Once; /// gich layout definition and functions for gich operations. /// author : ForeverYolo use tock_registers::interfaces::{Readable, Writeable}; @@ -67,8 +68,13 @@ register_structs! { } unsafe impl Sync for GicHypervisorInterface {} // Each CPU holds one GICH. -pub static GICH: GicRef = - unsafe { GicRef::new(GICV2.gich_base as *const GicHypervisorInterface) }; +pub static GICH: Once> = Once::new(); + +pub fn gich_init(gich_base: usize) { + unsafe { + GICH.call_once(|| GicRef::new(gich_base as *const GicHypervisorInterface)); + } +} impl GicHypervisorInterface { // init GICH for each CPU. diff --git a/src/device/irqchip/gicv2/gicv.rs b/src/device/irqchip/gicv2/gicv.rs index 6f408f5e..6309364a 100644 --- a/src/device/irqchip/gicv2/gicv.rs +++ b/src/device/irqchip/gicv2/gicv.rs @@ -12,7 +12,7 @@ // https://www.syswonder.org // // Authors: -// +// Hangqi Ren <2572131118@qq.com> #![allow(unused_variables)] #![allow(dead_code)] /// gicv layout definition and functions for gicv operations. @@ -23,7 +23,12 @@ use crate::device::irqchip::gicv2::gic_ref::GicRef; use crate::device::irqchip::gicv2::gicc::GicCpuInterface; use crate::device::irqchip::gicv2::GICV2; - +use spin::Once; // Each CPU holds one GICV, and it has the same register layout as GICC. -pub static GICV: GicRef = - unsafe { GicRef::new(GICV2.gicv_base as *const GicCpuInterface) }; +pub static GICV: Once> = Once::new(); + +pub fn gicv_init(gicv_base: usize) { + unsafe { + GICV.call_once(|| GicRef::new(gicv_base as *const GicCpuInterface)); + } +} diff --git a/src/device/irqchip/gicv2/mod.rs b/src/device/irqchip/gicv2/mod.rs index ea1760f8..516df11e 100644 --- a/src/device/irqchip/gicv2/mod.rs +++ b/src/device/irqchip/gicv2/mod.rs @@ -12,17 +12,22 @@ // https://www.syswonder.org // // Authors: -// +// Hangqi Ren <2572131118@qq.com> +use crate::arch::zone::{GicConfig, Gicv2Config, HvArchZoneConfig}; use crate::device::irqchip::gicv2::gic::MAX_CPU_NUM; +use crate::device::irqchip::gicv2::gicc::gicc_init; /// The outer layer is defined using gicv2. /// author: ForeverYolo /// reference: /// 1. gicv2 spec : https://www.cl.cam.ac.uk/research/srg/han/ACS-P35/zynq/arm_gic_architecture_specification.pdf use crate::device::irqchip::gicv2::gicc::GICC; +use crate::device::irqchip::gicv2::gicd::gicd_init; use crate::device::irqchip::gicv2::gicd::GICD; +use crate::device::irqchip::gicv2::gich::gich_init; +use crate::device::irqchip::gicv2::gicv::gicv_init; use crate::platform::ROOT_ARCH_ZONE_CONFIG; use crate::zone::Zone; - +use spin::Once; // GIC Distributor Definition. pub mod gicd; @@ -51,33 +56,70 @@ pub struct Gicv2 { gicv_base: usize, } -pub static GICV2: Gicv2 = Gicv2 { - gicd_base: ROOT_ARCH_ZONE_CONFIG.gicd_base, - /* - * Some boards have the GIC CPU interface registers alias, which will overlap DIR register, so we need to add an offset to - * find the last gic cpu alias region. - * ref: https://github.com/Xilinx/qemu-devicetrees/commit/09d4c3200538dc90082fbda9289e2af9794b9a28 - */ - gicc_base: ROOT_ARCH_ZONE_CONFIG.gicc_base + ROOT_ARCH_ZONE_CONFIG.gicc_offset, - gich_base: ROOT_ARCH_ZONE_CONFIG.gich_base, - gicv_base: ROOT_ARCH_ZONE_CONFIG.gicv_base, -}; - +pub static GICV2: Once = Once::new(); // get base address of GIC and initialize GIC Structs. pub fn primary_init_early() { - info!("GicDistributer = {:#x?}", GICV2.gicd_base); - info!("GicCpuInterface = {:#x?}", GICV2.gicc_base); - info!("GicHypervisorInterface = {:#x?}", GICV2.gich_base); - info!("GicVCpuInterface = {:#x?}", GICV2.gicv_base); + match ROOT_ARCH_ZONE_CONFIG.gic_config { + GicConfig::Gicv3(_) => { + panic!("GICv3 is not supported in this version of hvisor"); + } + GicConfig::Gicv2(ref gicv2_config) => { + if ROOT_ARCH_ZONE_CONFIG.gic_version != 2 { + panic!( + "GIC version mismatch, expected 2, got {}", + ROOT_ARCH_ZONE_CONFIG.gic_version + ); + } + info!("GICv2 detected"); + GICV2.call_once(|| { + Gicv2 { + gicd_base: gicv2_config.gicd_base, + /* + * Some boards have the GIC CPU interface registers alias, which will overlap DIR register, so we need to add an offset to + * find the last gic cpu alias region. + * ref: https://github.com/Xilinx/qemu-devicetrees/commit/09d4c3200538dc90082fbda9289e2af9794b9a28 + */ + gicc_base: gicv2_config.gicc_base + gicv2_config.gicc_offset, + gich_base: gicv2_config.gich_base, + gicv_base: gicv2_config.gicv_base, + } + }); + gicd_init(gicv2_config.gicd_base); + gicc_init(gicv2_config.gicc_base + gicv2_config.gicc_offset); + gich_init(gicv2_config.gich_base); + gicv_init(gicv2_config.gicv_base); + info!( + "GIC Distributor base: {:#x}, size: {:#x}", + GICV2.get().unwrap().gicd_base, + gicv2_config.gicd_size + ); + info!( + "GIC CPU Interface base: {:#x}, size: {:#x}", + GICV2.get().unwrap().gicc_base, + gicv2_config.gicc_size + ); + info!("GIC CPU Interface offset: {:#x}", gicv2_config.gicc_offset); + info!( + "GIC Hypervisor Interface base: {:#x}, size: {:#x}", + GICV2.get().unwrap().gich_base, + gicv2_config.gich_size + ); + info!( + "GIC Virtual CPU Interface base: {:#x}, size: {:#x}", + GICV2.get().unwrap().gicv_base, + gicv2_config.gicv_size + ); + } + }; gic::PENDING_VIRQS.call_once(|| gic::PendingIrqs::new(MAX_CPU_NUM)); } pub fn percpu_init() { - GICC.init(); + GICC.get().unwrap().init(); } pub fn primary_init_late() { - GICD.global_init(); + GICD.get().unwrap().global_init(); } impl Zone { diff --git a/src/device/irqchip/gicv2/vgic.rs b/src/device/irqchip/gicv2/vgic.rs index eddfcb90..2b4a4158 100644 --- a/src/device/irqchip/gicv2/vgic.rs +++ b/src/device/irqchip/gicv2/vgic.rs @@ -12,8 +12,8 @@ // https://www.syswonder.org // // Authors: -// -use crate::arch::zone::HvArchZoneConfig; +// Hangqi Ren <2572131118@qq.com> +use crate::arch::zone::{GicConfig, Gicv2Config, HvArchZoneConfig}; use crate::device::irqchip::gicv2::gicd::{ get_max_int_num, GICD, GICD_CTRL_REG_OFFSET, GICD_ICACTIVER_REG_OFFSET, GICD_ICENABLER_REG_OFFSET, GICD_ICFGR_REG_OFFSET, GICD_ICPENDR_REG_OFFSET, @@ -33,36 +33,62 @@ use crate::percpu::this_zone; /// reference: /// 1. gicv2 spec : https://www.cl.cam.ac.uk/research/srg/han/ACS-P35/zynq/arm_gic_architecture_specification.pdf use crate::zone::Zone; - 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) { - if arch.gicd_base == 0 { - panic!("vgicv2_mmio_init: gicd_base is null"); + match arch.gic_config { + GicConfig::Gicv3(_) => { + panic!("GICv3 is not supported in this version of hvisor"); + } + GicConfig::Gicv2(ref gicv2_config) => { + 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( + gicv2_config.gicd_base, + gicv2_config.gicd_size, + vgicv2_dist_handler, + 0, + ); + } } - self.mmio_region_register(arch.gicd_base, arch.gicd_size, vgicv2_dist_handler, 0); } // 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) { - if arch.gicc_base == 0 || arch.gicv_base == 0 || arch.gicc_size == 0 || arch.gicv_size == 0 - { - panic!("vgicv2_remap_init: gic related address is null"); - } - if arch.gicv_size != arch.gicc_size { - panic!("vgicv2_remap_init: gicv_size not equal to gicc_size"); + match arch.gic_config { + GicConfig::Gicv3(_) => { + panic!("GICv3 is not supported in this version of hvisor"); + } + GicConfig::Gicv2(ref gicv2_config) => { + if gicv2_config.gicc_base == 0 + || gicv2_config.gicv_base == 0 + || gicv2_config.gicc_size == 0 + || gicv2_config.gicv_size == 0 + { + panic!("vgicv2_remap_init: gic related address is null"); + } + if gicv2_config.gicv_size != gicv2_config.gicc_size { + panic!("vgicv2_remap_init: gicv_size not equal to gicc_size"); + } + info!( + "Remaping GICv2 GICV MMIO regions to GICC MMIO regions for zone {}", + self.id + ); + // map gicv memory region to gicc memory region. + self.gpm + .insert(MemoryRegion::new_with_offset_mapper( + gicv2_config.gicc_base, + gicv2_config.gicv_base, + gicv2_config.gicc_size, + MemFlags::READ | MemFlags::WRITE, + )) + .unwrap(); + } } - // map gicv memory region to gicc memory region. - self.gpm - .insert(MemoryRegion::new_with_offset_mapper( - arch.gicc_base, - arch.gicv_base, - arch.gicc_size, - MemFlags::READ | MemFlags::WRITE, - )) - .unwrap(); } // store the interrupt number in the irq_bitmap. @@ -229,13 +255,13 @@ pub fn set_sgi_irq(irq_id: usize, target_list: usize, routing_mode: usize) { target_list, routing_mode ); - trace!("ISENABLER: {:#x}", GICD.get_isenabler(0)); - GICD.set_sgir(val as u32); + trace!("ISENABLER: {:#x}", GICD.get().unwrap().get_isenabler(0)); + GICD.get().unwrap().set_sgir(val as u32); } // Handle GIC Distributor register accesses. pub fn vgicv2_dist_handler(mmio: &mut MMIOAccess, _arg: usize) -> HvResult { - let gicd_base = GICV2.gicd_base; + let gicd_base = GICV2.get().unwrap().gicd_base; let reg = mmio.address; match reg { diff --git a/src/device/irqchip/gicv3/mod.rs b/src/device/irqchip/gicv3/mod.rs index 3d0969a4..590b1f17 100644 --- a/src/device/irqchip/gicv3/mod.rs +++ b/src/device/irqchip/gicv3/mod.rs @@ -34,9 +34,9 @@ use self::gicd::{enable_gic_are_ns, GICD_ICACTIVER, GICD_ICENABLER}; use self::gicr::enable_ipi; use crate::arch::aarch64::sysreg::{read_sysreg, smc_arg1, write_sysreg}; use crate::arch::cpu::this_cpu_id; +use crate::arch::zone::{GicConfig, Gicv2Config, HvArchZoneConfig}; use crate::config::root_zone_config; -use crate::consts::{self, MAX_CPU_NUM}; - +use crate::consts::MAX_CPU_NUM; use crate::event::check_events; use crate::hypercall::SGI_IPI_ID; use crate::zone::Zone; @@ -346,7 +346,7 @@ pub fn host_gicd_base() -> usize { } pub fn host_gicr_base(id: usize) -> usize { - assert!(id < consts::MAX_CPU_NUM); + assert!(id < MAX_CPU_NUM); GIC.get().unwrap().gicr_base + id * PER_GICR_SIZE } @@ -384,16 +384,43 @@ pub fn disable_irqs() { pub fn primary_init_early() { let root_config = root_zone_config(); - - GIC.call_once(|| Gic { - gicd_base: root_config.arch_config.gicd_base, - gicr_base: root_config.arch_config.gicr_base, - gicd_size: root_config.arch_config.gicd_size, - gicr_size: root_config.arch_config.gicr_size, - gits_base: root_config.arch_config.gits_base, - gits_size: root_config.arch_config.gits_size, - }); - + match root_config.arch_config.gic_config { + GicConfig::Gicv2(_) => { + panic!("GICv2 is not supported in this version of hvisor"); + } + GicConfig::Gicv3(ref gicv3_config) => { + if root_config.arch_config.gic_version != 3 { + panic!( + "GIC version mismatch, expected 3, got {}", + root_config.arch_config.gic_version + ); + } + info!("GICv3 detected"); + GIC.call_once(|| Gic { + gicd_base: gicv3_config.gicd_base, + gicr_base: gicv3_config.gicr_base, + gicd_size: gicv3_config.gicd_size, + gicr_size: gicv3_config.gicr_size, + gits_base: gicv3_config.gits_base, + gits_size: gicv3_config.gits_size, + }); + info!( + "GIC Distributor base: {:#x}, size: {:#x}", + GIC.get().unwrap().gicd_base, + GIC.get().unwrap().gicd_size + ); + info!( + "GIC Redistributor base: {:#x}, size: {:#x}", + GIC.get().unwrap().gicr_base, + GIC.get().unwrap().gicr_size + ); + info!( + "GIC ITS base: {:#x}, size: {:#x}", + GIC.get().unwrap().gits_base, + GIC.get().unwrap().gits_size + ); + } + } init_lpi_prop(); if host_gits_base() != 0 && host_gits_size() != 0 { diff --git a/src/device/irqchip/gicv3/vgic.rs b/src/device/irqchip/gicv3/vgic.rs index c4924e1c..c5734382 100644 --- a/src/device/irqchip/gicv3/vgic.rs +++ b/src/device/irqchip/gicv3/vgic.rs @@ -17,7 +17,7 @@ use alloc::sync::Arc; use super::{gicd::GICD_LOCK, is_spi}; use crate::{ - arch::zone::HvArchZoneConfig, + arch::zone::{GicConfig, Gicv2Config, Gicv3Config, HvArchZoneConfig}, consts::MAX_CPU_NUM, device::irqchip::gicv3::{ gicd::*, gicr::*, gits::*, host_gicd_base, host_gicr_base, host_gits_base, @@ -36,17 +36,36 @@ pub fn reg_range(base: usize, n: usize, size: usize) -> core::ops::Range impl Zone { pub fn vgicv3_mmio_init(&mut self, arch: &HvArchZoneConfig) { - if arch.gicd_base == 0 || arch.gicr_base == 0 { - panic!("vgicv3_mmio_init: gicd_base or gicr_base is null"); - } + 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); + 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(arch.gicd_base, arch.gicd_size, vgicv3_dist_handler, 0); - self.mmio_region_register(arch.gits_base, arch.gits_size, vgicv3_its_handler, 0); + self.mmio_region_register( + gicv3_config.gicd_base, + gicv3_config.gicd_size, + vgicv3_dist_handler, + 0, + ); + self.mmio_region_register( + gicv3_config.gits_base, + gicv3_config.gits_size, + vgicv3_its_handler, + 0, + ); - for cpu in 0..MAX_CPU_NUM { - let gicr_base = arch.gicr_base + cpu * PER_GICR_SIZE; - debug!("registering gicr {} at {:#x?}", cpu, gicr_base); - self.mmio_region_register(gicr_base, PER_GICR_SIZE, vgicv3_redist_handler, cpu); + for cpu in 0..MAX_CPU_NUM { + let gicr_base = gicv3_config.gicr_base + cpu * PER_GICR_SIZE; + debug!("registering gicr {} at {:#x?}", cpu, gicr_base); + self.mmio_region_register(gicr_base, PER_GICR_SIZE, vgicv3_redist_handler, cpu); + } + } } }