diff --git a/Cargo.lock b/Cargo.lock index 18ad6ea2..a4c7e8d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,6 +97,18 @@ dependencies = [ "tock-registers", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + [[package]] name = "fdt" version = "0.1.5" @@ -120,8 +132,10 @@ dependencies = [ "psci", "qemu-exit", "raw-cpuid", - "riscv", + "riscv 0.6.0", "riscv-decode", + "riscv-pac", + "riscv-peripheral", "sbi-rt", "spin 0.9.8", "tock-registers", @@ -183,6 +197,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + [[package]] name = "psci" version = "0.1.3" @@ -195,6 +218,15 @@ version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bb0fd6580eeed0103c054e3fba2c2618ff476943762f28a645b63b8692b21c9" +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + [[package]] name = "raw-cpuid" version = "10.7.0" @@ -245,12 +277,53 @@ dependencies = [ "riscv-target", ] +[[package]] +name = "riscv" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa3cdbeccae4359f6839a00e8b77e5736caa200ba216caf38d24e4c16e2b586" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + [[package]] name = "riscv-decode" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec7a6dc0b0bb96a4d23271864a45c0d24dcd9dde2a1b630a35f79fa29c588bf" +[[package]] +name = "riscv-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c4aa1ea1af6dcc83a61be12e8189f9b293c3ba5a487778a4cd89fb060fdbbc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "riscv-peripheral" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955a98c085e0657c1735d4baf5450092f03c2484d165c00d0166f3dc48b77651" +dependencies = [ + "embedded-hal", + "riscv 0.13.0", + "riscv-pac", +] + [[package]] name = "riscv-target" version = "0.1.2" @@ -278,21 +351,18 @@ checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "sbi-rt" -version = "0.0.2" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c113c53291db8ac141e01f43224ed488b8d6001ab66737b82e04695a43a42b7" +checksum = "7fbaa69be1eedc61c426e6d489b2260482e928b465360576900d52d496a58bd0" dependencies = [ "sbi-spec", ] [[package]] name = "sbi-spec" -version = "0.0.4" +version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4027cf9bb591a9fd0fc0e283be6165c5abe96cb73e9f0e24738c227f425377" -dependencies = [ - "static_assertions", -] +checksum = "e6e36312fb5ddc10d08ecdc65187402baba4ac34585cb9d1b78522ae2358d890" [[package]] name = "scopeguard" @@ -337,10 +407,15 @@ dependencies = [ ] [[package]] -name = "static_assertions" -version = "1.1.0" +name = "syn" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] name = "tock-registers" @@ -348,6 +423,12 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + [[package]] name = "volatile" version = "0.4.6" diff --git a/Cargo.toml b/Cargo.toml index 57346df2..8717729a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,9 +25,11 @@ aarch64-cpu = "9.4.0" psci = { version = "0.1.0", default-features = false, features = ["smc"]} [target.'cfg(target_arch = "riscv64")'.dependencies] -sbi-rt = { version = "0.0.2", features = ["legacy"] } +sbi-rt = { version = "0.0.3", features = ["legacy"] } riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } riscv-decode = "0.2.1" +riscv-peripheral = "0.2.1" +riscv-pac = "0.2.0" [target.'cfg(target_arch = "loongarch64")'.dependencies] loongArch64 = "0.2.4" @@ -56,6 +58,7 @@ pt_layout_qemu = [] # irqchip driver plic = [] aia = [] +aclint = [] ########### loongarch64 ############ # irqchip driver loongson_7a2000 = [] diff --git a/platform/riscv64/qemu-aia/board.rs b/platform/riscv64/qemu-aia/board.rs index 2d33e8e4..8bc2d0ea 100644 --- a/platform/riscv64/qemu-aia/board.rs +++ b/platform/riscv64/qemu-aia/board.rs @@ -2,6 +2,8 @@ use crate::{arch::zone::HvArchZoneConfig, config::*}; pub const BOARD_NAME: &str = "qemu-aia"; +pub const ACLINT_SSWI_BASE: usize = 0x2F00000; + pub const PLIC_BASE: usize = 0xc000000; pub const APLIC_BASE: usize = 0xc000000; pub const PLIC_MAX_IRQ: usize = 1024; diff --git a/platform/riscv64/qemu-plic/board.rs b/platform/riscv64/qemu-plic/board.rs index 42346ece..5c3e9ed8 100644 --- a/platform/riscv64/qemu-plic/board.rs +++ b/platform/riscv64/qemu-plic/board.rs @@ -2,6 +2,8 @@ use crate::{arch::zone::HvArchZoneConfig, config::*}; pub const BOARD_NAME: &str = "qem-plic"; +pub const ACLINT_SSWI_BASE: usize = 0x2F00000; + pub const PLIC_BASE: usize = 0xc000000; pub const APLIC_BASE: usize = 0xc000000; pub const PLIC_MAX_IRQ: usize = 1024; @@ -24,7 +26,7 @@ pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 9] = [ mem_type: MEM_TYPE_RAM, physical_start: 0x83000000, virtual_start: 0x83000000, - size: 0x1D000000, + size: 0x7D000000, }, // ram HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, diff --git a/platform/riscv64/qemu-plic/cargo/features b/platform/riscv64/qemu-plic/cargo/features index caebca78..45cd16fc 100644 --- a/platform/riscv64/qemu-plic/cargo/features +++ b/platform/riscv64/qemu-plic/cargo/features @@ -1 +1,2 @@ -plic \ No newline at end of file +plic +aclint \ No newline at end of file diff --git a/platform/riscv64/qemu-plic/image/dts/zone0.dts b/platform/riscv64/qemu-plic/image/dts/zone0.dts index d0880d64..6b280391 100644 --- a/platform/riscv64/qemu-plic/image/dts/zone0.dts +++ b/platform/riscv64/qemu-plic/image/dts/zone0.dts @@ -55,9 +55,9 @@ }; - memory@83000000 { + memory@80000000 { device_type = "memory"; - reg = <0x0 0x83000000 0x0 0x1D000000>; + reg = <0x0 0x80000000 0x0 0x80000000>; }; reserved-memory { @@ -65,6 +65,16 @@ #size-cells = <0x02>; ranges; + opensbi@0x80000000 { + no-map; + reg = <0x00 0x80000000 0x00 0x00200000>; + }; + + hvisor@0x80200000 { + no-map; + reg = <0x00 0x80200000 0x00 0x02E00000>; + }; + nonroot@0x83000000 { no-map; reg = <0x00 0x83000000 0x00 0x0C000000>; @@ -81,6 +91,7 @@ #size-cells = <0x02>; compatible = "simple-bus"; ranges; + plic: interrupt-controller@c000000 { phandle = <0x03>; riscv,ndev = <0x5f>; @@ -94,6 +105,7 @@ compatible = "riscv,plic0"; #interrupt-cells = <0x1>; }; + uart@10000000 { interrupts = <0x0a>; interrupt-parent = <&plic>; @@ -101,39 +113,13 @@ reg = <0x00 0x10000000 0x00 0x100>; compatible = "ns16550a"; }; - pci@30000000 { - interrupt-map-mask = <0x1800 0x00 0x00 0x07>; - interrupt-map = <0x00 0x00 0x00 0x01 0x03 0x20 0x00 0x00 0x00 0x02 0x03 0x21 0x00 0x00 0x00 0x03 0x03 0x22 0x00 0x00 0x00 0x04 0x03 0x23 0x800 0x00 0x00 0x01 0x03 0x21 0x800 0x00 0x00 0x02 0x03 0x22 0x800 0x00 0x00 0x03 0x03 0x23 0x800 0x00 0x00 0x04 0x03 0x20 0x1000 0x00 0x00 0x01 0x03 0x22 0x1000 0x00 0x00 0x02 0x03 0x23 0x1000 0x00 0x00 0x03 0x03 0x20 0x1000 0x00 0x00 0x04 0x03 0x21 0x1800 0x00 0x00 0x01 0x03 0x23 0x1800 0x00 0x00 0x02 0x03 0x20 0x1800 0x00 0x00 0x03 0x03 0x21 0x1800 0x00 0x00 0x04 0x03 0x22>; - ranges = <0x1000000 0x00 0x00 0x00 0x3000000 0x00 0x10000 0x2000000 0x00 0x40000000 0x00 0x40000000 0x00 0x40000000 0x3000000 0x04 0x00 0x04 0x00 0x04 0x00>; - reg = <0x00 0x30000000 0x00 0x10000000>; - dma-coherent; - bus-range = <0x00 0xff>; - linux,pci-domain = <0x00>; - device_type = "pci"; - compatible = "pci-host-ecam-generic"; - #size-cells = <0x02>; - #interrupt-cells = <0x01>; - #address-cells = <0x03>; - }; virtio_mmio@10008000 { - interrupts = <0x8>; - interrupt-parent = <&plic>; - reg = <0x0 0x10008000 0x0 0x1000>; - compatible = "virtio,mmio"; + interrupts = <0x8>; + interrupt-parent = <&plic>; + reg = <0x0 0x10008000 0x0 0x1000>; + compatible = "virtio,mmio"; }; - // virtio_mmio@10007000 { - // interrupts = <0x7>; - // interrupt-parent = <&plic>; - // reg = <0x0 0x10007000 0x0 0x1000>; - // compatible = "virtio,mmio"; - // }; - // virtio_mmio@10006000 { - // interrupts = <0x6>; - // interrupt-parent = <&plic>; - // reg = <0x0 0x10006000 0x0 0x1000>; - // compatible = "virtio,mmio"; - // }; virtio_mmio@10005000 { interrupts = <0x5>; @@ -173,5 +159,4 @@ chosen { bootargs = "root=/dev/vda rw earlycon console=ttyS0"; }; - }; diff --git a/platform/riscv64/qemu-plic/platform.mk b/platform/riscv64/qemu-plic/platform.mk index 0ae991bf..6c350ce2 100644 --- a/platform/riscv64/qemu-plic/platform.mk +++ b/platform/riscv64/qemu-plic/platform.mk @@ -10,11 +10,11 @@ zone0_dtb := $(image_dir)/dts/zone0.dtb # zone1_kernel := $(image_dir)/kernel/Image # zone1_dtb := $(image_dir)/devicetree/linux.dtb -QEMU_ARGS := -machine virt +QEMU_ARGS := -machine virt,aclint=on QEMU_ARGS += -bios default QEMU_ARGS += -cpu rv64 QEMU_ARGS += -smp 4 -QEMU_ARGS += -m 2G +QEMU_ARGS += -m 4G QEMU_ARGS += -nographic QEMU_ARGS += -kernel $(hvisor_bin) diff --git a/src/arch/riscv64/ipi.rs b/src/arch/riscv64/ipi.rs index b7c1a544..81abe19b 100644 --- a/src/arch/riscv64/ipi.rs +++ b/src/arch/riscv64/ipi.rs @@ -1,3 +1,10 @@ +use sbi_rt::HartMask; + +// arch_send_event pub fn arch_send_event(cpu_id: u64, _sgi_num: u64) { - sbi_rt::send_ipi(1 << cpu_id, 0); + info!("arch_send_event: cpu_id: {}", cpu_id); + #[cfg(feature = "aclint")] + crate::device::irqchip::aclint::aclint_send_ipi(cpu_id as usize); + #[cfg(not(feature = "aclint"))] + sbi_rt::send_ipi(HartMask::from_mask_base(1 << cpu_id, 0)); } diff --git a/src/device/irqchip/aclint/mod.rs b/src/device/irqchip/aclint/mod.rs new file mode 100644 index 00000000..65cd87f2 --- /dev/null +++ b/src/device/irqchip/aclint/mod.rs @@ -0,0 +1,60 @@ +// This used for transfering the software interrupt to the target hart + +// Offset Width Attr Name Description +// 0x0000_0000 4B RW SETSSIP0 HART index 0 set supervisor-level IPI register +// 0x0000_0004 4B RW SETSSIP1 HART index 1 set supervisor-level IPI register +// ... +// 0x0000_3FFC 4B RESERVED Reserved for future use. + +use crate::consts::MAX_CPU_NUM; +use log::info; +use riscv_pac::result::{Error, Result}; +use riscv_pac::HartIdNumber; +use riscv_peripheral::aclint::sswi::SSWI; +use spin::Once; + +// Only init at boot time. +// Don't spend more time considering the concurrency. +static ACLINT_BASE: Once = Once::new(); + +// HartId is needed for riscv_peripheral::aclint. +#[derive(Debug, Clone, Copy)] +pub struct HartId(usize); + +// sswi.setssip needs a type which implement HartIdNumber. +unsafe impl HartIdNumber for HartId { + const MAX_HART_ID_NUMBER: usize = MAX_CPU_NUM as usize; + #[inline] + fn number(self) -> usize { + self.0 + } + #[inline] + fn from_number(number: usize) -> Result { + if number > Self::MAX_HART_ID_NUMBER { + return Err(Error::InvalidVariant(number)); + } + Ok(unsafe { core::mem::transmute::(number) }) + } +} + +/// Init the aclint's base address. +pub fn aclint_init(base_addr: usize) { + info!("ACLINT: base address is {:#x?}", base_addr); + ACLINT_BASE.call_once(|| base_addr); +} + +/// Send a software interrupt to the target hart. +pub fn aclint_send_ipi(hart_id: usize) { + assert!( + hart_id >= 0 && hart_id < MAX_CPU_NUM, + "hart_id is out of range" + ); + + info!("ACLINT: addr {:#x}", *ACLINT_BASE.get().unwrap()); + + let sswi = unsafe { SSWI::new(*ACLINT_BASE.get().unwrap() as usize) }; + let setssip = sswi.setssip(HartId::from_number(hart_id).unwrap()); + + // Write the software interrupt to the target hart. + setssip.pend(); +} diff --git a/src/device/irqchip/mod.rs b/src/device/irqchip/mod.rs index 7295e110..7d672169 100644 --- a/src/device/irqchip/mod.rs +++ b/src/device/irqchip/mod.rs @@ -16,14 +16,27 @@ pub use gicv3::{ gicd::set_ispender, inject_irq, percpu_init, primary_init_early, primary_init_late, }; -#[cfg(target_arch = "riscv64")] -#[cfg(feature = "plic")] +#[cfg(all(feature = "aclint", target_arch = "riscv64"))] +pub mod aclint; + +#[cfg(all(feature = "plic", target_arch = "riscv64"))] pub mod plic; -#[cfg(target_arch = "riscv64")] -#[cfg(feature = "aia")] +#[cfg(all(feature = "aia", target_arch = "riscv64"))] pub mod aia; +#[cfg(target_arch = "riscv64")] +pub fn primary_init_early() { + // aclint is local interrupt controller + // plic & aia is global interrupt controller + #[cfg(feature = "plic")] + plic::primary_init_early(); + #[cfg(feature = "aia")] + aia::aplic::primary_init_early(); + #[cfg(feature = "aclint")] + aclint::aclint_init(crate::platform::ACLINT_SSWI_BASE); +} + pub fn gic_handle_irq() { #[cfg(all(feature = "gicv2", target_arch = "aarch64"))] gicv2::gic::gicv2_handle_irq(); @@ -45,18 +58,14 @@ impl Zone { } } -#[cfg(target_arch = "riscv64")] -#[cfg(feature = "plic")] +#[cfg(all(feature = "plic", target_arch = "riscv64"))] pub use plic::{ - host_plic, inject_irq, percpu_init, primary_init_early, primary_init_late, - vplic_global_emul_handler, vplic_hart_emul_handler, + host_plic, inject_irq, percpu_init, primary_init_late, vplic_global_emul_handler, + vplic_hart_emul_handler, }; -#[cfg(target_arch = "riscv64")] -#[cfg(feature = "aia")] -pub use aia::aplic::{ - host_aplic, inject_irq, percpu_init, primary_init_early, primary_init_late, vaplic_emul_handler, -}; +#[cfg(all(feature = "aia", target_arch = "riscv64"))] +pub use aia::aplic::{host_aplic, inject_irq, percpu_init, primary_init_late, vaplic_emul_handler}; #[cfg(target_arch = "loongarch64")] pub mod ls7a2000;