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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,14 @@ uefi-raw = "=0.9.0"
############# general ##############
iommu = [] # supported by: aarch64, riscv64
pci = [] # supported by: aarch64, riscv64,loongarch64
share_s2pt = ["iommu"]
print_timestamp = [] # print timestamp when logging

############# IOMMU ##############
riscv_iommu = ["iommu"]
arm_smmu = ["iommu"]
intel_vtd = ["iommu"]
share_s2pt = ["iommu"]
viommu = ["iommu"] # supported by: riscv64

############# PCIe access mechanism ##############
ecam_pcie = [] # Standard ECAM mechanism (default for most platforms)
Expand Down
1 change: 1 addition & 0 deletions platform/riscv64/qemu-aia/cargo/features
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pci
ecam_pcie
riscv_iommu
share_s2pt
viommu
11 changes: 11 additions & 0 deletions platform/riscv64/qemu-aia/image/dts/virt.dts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,16 @@
compatible = "sifive,test1\0sifive,test0\0syscon";
};

iommu@3010000 {
msi-parent = <0x0a>;
interrupts = <0x24 0x01 0x25 0x01 0x26 0x01 0x27 0x01>;
interrupt-parent = <0x0c>;
reg = <0x00 0x3010000 0x00 0x1000>;
phandle = <0x8000>;
#iommu-cells = <0x01>;
compatible = "riscv,iommu";
};

virtio_mmio@10008000 {
interrupts = <0x08 0x04>;
interrupt-parent = <0x0c>;
Expand Down Expand Up @@ -315,6 +325,7 @@
pci@30000000 {
interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
interrupt-map = <0x00 0x00 0x00 0x01 0x0c 0x20 0x04 0x00 0x00 0x00 0x02 0x0c 0x21 0x04 0x00 0x00 0x00 0x03 0x0c 0x22 0x04 0x00 0x00 0x00 0x04 0x0c 0x23 0x04 0x800 0x00 0x00 0x01 0x0c 0x21 0x04 0x800 0x00 0x00 0x02 0x0c 0x22 0x04 0x800 0x00 0x00 0x03 0x0c 0x23 0x04 0x800 0x00 0x00 0x04 0x0c 0x20 0x04 0x1000 0x00 0x00 0x01 0x0c 0x22 0x04 0x1000 0x00 0x00 0x02 0x0c 0x23 0x04 0x1000 0x00 0x00 0x03 0x0c 0x20 0x04 0x1000 0x00 0x00 0x04 0x0c 0x21 0x04 0x1800 0x00 0x00 0x01 0x0c 0x23 0x04 0x1800 0x00 0x00 0x02 0x0c 0x20 0x04 0x1800 0x00 0x00 0x03 0x0c 0x21 0x04 0x1800 0x00 0x00 0x04 0x0c 0x22 0x04>;
iommu-map = <0x00 0x8000 0x00 0x00 0x00 0x8000 0x00 0xffff>;
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>;
msi-parent = <0x0a>;
Expand Down
29 changes: 11 additions & 18 deletions platform/riscv64/qemu-aia/image/dts/zone0.dts
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,6 @@
phandle = <0x04>;
};
};

cpu-map {

cluster0 {

core0 {
cpu = <0x07>;
};

core1 {
cpu = <0x05>;
};

core2 {
cpu = <0x03>;
};
};
};
};

soc {
Expand Down Expand Up @@ -159,9 +141,20 @@
compatible = "qemu,imsics\0riscv,imsics";
};

iommu@3010000 {
msi-parent = <0x0a>;
interrupts = <0x24 0x01 0x25 0x01 0x26 0x01 0x27 0x01>;
interrupt-parent = <0x0c>;
reg = <0x00 0x3010000 0x00 0x1000>;
phandle = <0x8000>;
#iommu-cells = <0x01>;
compatible = "riscv,iommu";
};

pci@30000000 {
interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
interrupt-map = <0x00 0x00 0x00 0x01 0x0c 0x20 0x04 0x00 0x00 0x00 0x02 0x0c 0x21 0x04 0x00 0x00 0x00 0x03 0x0c 0x22 0x04 0x00 0x00 0x00 0x04 0x0c 0x23 0x04 0x800 0x00 0x00 0x01 0x0c 0x21 0x04 0x800 0x00 0x00 0x02 0x0c 0x22 0x04 0x800 0x00 0x00 0x03 0x0c 0x23 0x04 0x800 0x00 0x00 0x04 0x0c 0x20 0x04 0x1000 0x00 0x00 0x01 0x0c 0x22 0x04 0x1000 0x00 0x00 0x02 0x0c 0x23 0x04 0x1000 0x00 0x00 0x03 0x0c 0x20 0x04 0x1000 0x00 0x00 0x04 0x0c 0x21 0x04 0x1800 0x00 0x00 0x01 0x0c 0x23 0x04 0x1800 0x00 0x00 0x02 0x0c 0x20 0x04 0x1800 0x00 0x00 0x03 0x0c 0x21 0x04 0x1800 0x00 0x00 0x04 0x0c 0x22 0x04>;
iommu-map = <0x00 0x8000 0x00 0x00 0x00 0x8000 0x00 0xffff>;
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>;
msi-parent = <0x0a>;
Expand Down
11 changes: 11 additions & 0 deletions platform/riscv64/qemu-aia/image/dts/zone1-linux.dts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,20 @@
compatible = "virtio,mmio";
};

iommu@3010000 {
msi-parent = <0x0a>;
interrupts = <0x24 0x01 0x25 0x01 0x26 0x01 0x27 0x01>;
interrupt-parent = <0x0c>;
reg = <0x00 0x3010000 0x00 0x1000>;
phandle = <0x8000>;
#iommu-cells = <0x01>;
compatible = "riscv,iommu";
};

pci@30000000 {
interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
interrupt-map = <0x00 0x00 0x00 0x01 0x0c 0x20 0x04 0x00 0x00 0x00 0x02 0x0c 0x21 0x04 0x00 0x00 0x00 0x03 0x0c 0x22 0x04 0x00 0x00 0x00 0x04 0x0c 0x23 0x04 0x800 0x00 0x00 0x01 0x0c 0x21 0x04 0x800 0x00 0x00 0x02 0x0c 0x22 0x04 0x800 0x00 0x00 0x03 0x0c 0x23 0x04 0x800 0x00 0x00 0x04 0x0c 0x20 0x04 0x1000 0x00 0x00 0x01 0x0c 0x22 0x04 0x1000 0x00 0x00 0x02 0x0c 0x23 0x04 0x1000 0x00 0x00 0x03 0x0c 0x20 0x04 0x1000 0x00 0x00 0x04 0x0c 0x21 0x04 0x1800 0x00 0x00 0x01 0x0c 0x23 0x04 0x1800 0x00 0x00 0x02 0x0c 0x20 0x04 0x1800 0x00 0x00 0x03 0x0c 0x21 0x04 0x1800 0x00 0x00 0x04 0x0c 0x22 0x04>;
iommu-map = <0x00 0x8000 0x00 0x00 0x00 0x8000 0x00 0xffff>;
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>;
msi-parent = <0x0a>;
Expand Down
5 changes: 3 additions & 2 deletions platform/riscv64/qemu-aia/platform.mk
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ QEMU_ARGS += -device loader,file="$(zone0_dtb)",addr=0x8f000000,force-raw=on

QEMU_ARGS += -drive if=none,file=$(FSIMG1),id=hd0,format=raw
# QEMU_ARGS += -device virtio-blk-device,drive=hd0,bus=virtio-mmio-bus.7
QEMU_ARGS += -device virtio-blk-pci,drive=hd0,disable-legacy=on,disable-modern=off,addr=01.0
QEMU_ARGS += -device virtio-blk-pci,drive=hd0,disable-legacy=on,disable-modern=off,addr=01.0,iommu_platform=on
QEMU_ARGS += -device virtio-serial-device,bus=virtio-mmio-bus.6 -chardev pty,id=X10007000 -device virtconsole,chardev=X10007000 -S
QEMU_ARGS += -drive if=none,file=$(FSIMG2),id=hd1,format=qcow2
# QEMU_ARGS += -device virtio-blk-device,drive=hd1,bus=virtio-mmio-bus.5
QEMU_ARGS += -device virtio-blk-pci,drive=hd1,disable-legacy=on,disable-modern=off,addr=02.0
QEMU_ARGS += -device virtio-blk-pci,drive=hd1,disable-legacy=on,disable-modern=off,addr=02.0,iommu_platform=on
# QEMU_ARGS += -d trace:riscv_iommu_*
# -------------------------------------------------------------------

# QEMU_ARGS := -machine virt
Expand Down
8 changes: 7 additions & 1 deletion src/device/iommu/arm_smmu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,13 @@ impl Iommu for ArmSmmu {
zone_id
);
}
fn viommu_mmio_handler(&self, zone: &mut Zone, viommu_base: usize, viommu_size: usize) {
fn viommu_remove(&self, zone_id: usize) {
todo!(
"ArmSmmu viommu remove for zone id {} not implemented yet.",
zone_id
);
}
fn viommu_mmio_handler_register(&self, zone: &Zone, _viommu_base: usize, _viommu_size: usize) {
todo!(
"ArmSmmu viommu handler for zone id {} not implemented yet.",
zone.id()
Expand Down
5 changes: 4 additions & 1 deletion src/device/iommu/dummy_iommu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ impl Iommu for DummyIommu {
fn viommu_init(&self, zone_id: usize) {
info!("No IOMMU implementation available, cannot initialize VIOMMU for Zone id {}", zone_id);
}
fn viommu_mmio_handler(&self, zone: &mut Zone, _viommu_base: usize, _viommu_size: usize) {
fn viommu_remove(&self, zone_id: usize) {
info!("No IOMMU implementation available, cannot remove VIOMMU for Zone id {}", zone_id);
}
fn viommu_mmio_handler_register(&self, zone: &Zone, _viommu_base: usize, _viommu_size: usize) {
info!("No IOMMU implementation available, cannot handle VIOMMU MMIO for Zone id {}", zone.id());
}
}
8 changes: 7 additions & 1 deletion src/device/iommu/intel_vtd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,13 @@ impl Iommu for IntelVtd {
zone_id
);
}
fn viommu_mmio_handler(&self, zone: &mut Zone, viommu_base: usize, viommu_size: usize) {
fn viommu_remove(&self, zone_id: usize) {
todo!(
"IntelVtd viommu remove for zone id {} not implemented yet.",
zone_id
);
}
fn viommu_mmio_handler_register(&self, zone: &Zone, _viommu_base: usize, _viommu_size: usize) {
todo!(
"IntelVtd viommu handler for zone id {} not implemented yet.",
zone.id()
Expand Down
6 changes: 4 additions & 2 deletions src/device/iommu/iommu_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub(crate) trait Iommu {
fn interrupt_handler(&self, irq_id: usize);
/// Initialize the Virtual IOMMU for the Zone
fn viommu_init(&self, zone_id: usize);
/// Virtual IOMMU MMIO handler for the Zone
fn viommu_mmio_handler(&self, zone: &mut Zone, viommu_base: usize, viommu_size: usize);
/// Remove the Virtual IOMMU for the Zone
fn viommu_remove(&self, zone_id: usize);
/// Register the Virtual IOMMU MMIO handler for the Zone
fn viommu_mmio_handler_register(&self, zone: &Zone, viommu_base: usize, viommu_size: usize);
}
29 changes: 29 additions & 0 deletions src/device/iommu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mod iommu_impl;
mod iommu_trait;

use crate::consts::MAX_ZONE_NUM;
use crate::zone::Zone;
use iommu_impl::iommu_impl;
use iommu_trait::Iommu;

Expand Down Expand Up @@ -60,6 +61,34 @@ pub fn iommu_add_device_with_root_pt_addr(zone_id: usize, did: usize, root_pt_ad
}
}

/// Public interface for initializing the Virtual IOMMU for the Zone
pub(crate) fn viommu_init(zone_id: usize) {
match check_zone_id(zone_id) {
Ok(()) => {
iommu_impl().viommu_init(zone_id);
}
Err(e) => {
warn!("{}", e);
}
}
}

/// Public interface for removing the Virtual IOMMU for the Zone
pub(crate) fn viommu_remove(zone_id: usize) {
match check_zone_id(zone_id) {
Ok(()) => {
iommu_impl().viommu_remove(zone_id);
}
Err(e) => {
warn!("{}", e);
}
}
}

pub(crate) fn viommu_mmio_handler_register(zone: &Zone, viommu_base: usize, viommu_size: usize) {
iommu_impl().viommu_mmio_handler_register(zone, viommu_base, viommu_size);
}

/////////////////////////////////////////////////////////////////////////
// Below pub apis are used for compatibility for old code(for x86_64) //
// These apis will be replaced by IOMMU trait later. //
Expand Down
12 changes: 6 additions & 6 deletions src/device/iommu/riscv_iommu/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

#![allow(unused)]

const IOTINVAL_OPCODE: u8 = 1;
const IOFENCE_OPCODE: u8 = 2;
const IODIR_OPCODE: u8 = 3;
pub(super) const IOTINVAL_OPCODE: u8 = 1;
pub(super) const IOFENCE_OPCODE: u8 = 2;
pub(super) const IODIR_OPCODE: u8 = 3;

// Dword0 and dword1 are the two 64-bit words that make up the command.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
Expand All @@ -41,7 +41,7 @@ pub(super) enum IotInvalFunc {
}

impl IotInvalFunc {
fn raw(self) -> u8 {
pub(super) fn raw(self) -> u8 {
match self {
Self::Vma => 0,
Self::Gvma => 1,
Expand Down Expand Up @@ -103,7 +103,7 @@ pub(super) enum IoFenceFunc {
}

impl IoFenceFunc {
fn raw(self) -> u8 {
pub(super) fn raw(self) -> u8 {
match self {
Self::C => 0,
}
Expand Down Expand Up @@ -150,7 +150,7 @@ pub(super) enum IoDirFunc {
}

impl IoDirFunc {
fn raw(self) -> u8 {
pub(super) fn raw(self) -> u8 {
match self {
Self::InvalDdt => 0,
Self::InvalPdt => 1,
Expand Down
101 changes: 92 additions & 9 deletions src/device/iommu/riscv_iommu/iommu_hw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,88 @@ pub fn iommu_msi_pt_tlb_invalid(gscid: u16, msi_gpa: usize) {
info!("RISC-V: iommu_msi_pt_tlb_invalid do nothing now");
}

/// IOMMU register enumeration, used to access IOMMU registers for viommu module.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) enum IommuReg {
Caps,
Fctl,
Cqcsr,
Fqcsr,
Ipsr,
Icvec,
}

pub(super) fn iommu_read_reg(reg: IommuReg) -> u64 {
let iommu = get_iommu().lock();
let hw = iommu.iommu();

match reg {
IommuReg::Caps => hw.caps.get(),
IommuReg::Fctl => hw.fctl.get() as u64,
IommuReg::Cqcsr => hw.cqcsr.get() as u64,
IommuReg::Fqcsr => hw.fqcsr.get() as u64,
IommuReg::Ipsr => hw.ipsr.get() as u64,
IommuReg::Icvec => hw.icvec.get(),
}
}

pub(super) fn iommu_write_reg(reg: IommuReg, value: u64) {
let iommu = get_iommu().lock();
let hw = iommu.iommu();

match reg {
IommuReg::Cqcsr => hw.cqcsr.set(value as u32),
IommuReg::Fqcsr => hw.fqcsr.set(value as u32),
IommuReg::Ipsr => hw.ipsr.set(value as u32),
IommuReg::Icvec => hw.icvec.set(value),
IommuReg::Caps | IommuReg::Fctl => {
warn!(
"RV IOMMU: ignore unsupported write to mirrored register {:?}",
reg
);
}
}
}

/// Add a raw command to physical IOMMU command queue.
pub(super) fn iommu_add_raw_command(command: RiscvIommuCommand) {
get_iommu().lock().rv_iommu_add_command(command);
}

/// Device directory table field enumeration, used to access device directory table fields for viommu module.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) enum IommuDdtField {
Iohgatp,
Ta,
Fsc,
}

/// Read a specific device directory table entry field.
pub(super) fn iommu_read_ddt_field(device_id: usize, field: IommuDdtField) -> Option<u64> {
let mut iommu = get_iommu().lock();
let (entry, _) = iommu.ddt.get_or_alloc_leaf_entry(device_id)?;

Some(match field {
IommuDdtField::Iohgatp => entry.iohgatp.get(),
IommuDdtField::Ta => entry.ta.get(),
IommuDdtField::Fsc => entry.fsc.get(),
})
}

/// Write a specific device directory table entry field.
pub(super) fn iommu_write_ddt_field(device_id: usize, field: IommuDdtField, value: u64) -> bool {
let mut iommu = get_iommu().lock();
if let Some((entry, _)) = iommu.ddt.get_or_alloc_leaf_entry(device_id) {
match field {
IommuDdtField::Iohgatp => entry.iohgatp.set(value),
IommuDdtField::Ta => entry.ta.set(value),
IommuDdtField::Fsc => entry.fsc.set(value),
}
return true;
}
false
}

/// Initialize RISC-V IOMMU with hardware DDTP probing.
fn riscv_iommu_init() {
assert!(
Expand Down Expand Up @@ -240,13 +322,17 @@ impl IommuHw {
}

fn rv_iommu_check_features(&self) {
let version = self.caps.read(IOMMU_CAPS::VERSION);
// Stop and report failure if capabilities.version is not supported.
if version != IOMMU_CAPS::VERSION::VERSION_1_0.value {
panic!(
"RISC-V IOMMU unsupported version: {}, Please check the IOMMU version",
version
);
match self.caps.read_as_enum(IOMMU_CAPS::VERSION) {
Some(IOMMU_CAPS::VERSION::Value::VERSION_1_0) => {
info!("RISC-V IOMMU version 1.0 supported");
}
_ => {
panic!(
"RISC-V IOMMU unsupported version: {}, Please check the IOMMU version",
self.caps.read(IOMMU_CAPS::VERSION)
);
}
}
// Note: here RISCV-IOMMU and CPU share the same stage-2 page table.
let cpu_s2pt_lvl = unsafe { crate::arch::s2pt::GSTAGE_PT_LEVEL };
Expand All @@ -264,9 +350,6 @@ impl IommuHw {
// Current DDT Entry only supports Extented-for
todo!("To support Base-format DDT Entry");
}
if self.caps.read(IOMMU_CAPS::IGS) == IOMMU_CAPS::IGS::MSI.value {
warn!("RISC-V IOMMU HW does not support WSI generation");
}
}

fn rv_iommu_init(
Expand Down
Loading
Loading