From 754b90630411dee380de08f0bfd5c111906cdd3b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 25 Nov 2019 23:09:15 -0800 Subject: aarch64: use gicv3 when available BUG=chromium:1028450 TEST=tast run -build=false crostini.LaunchTerminal Change-Id: Ibe3adbe5a86dda42d323632ed14f8dccc283a62e Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1934894 Reviewed-by: Stephen Barber Commit-Queue: Stephen Barber Tested-by: Stephen Barber Tested-by: kokoro --- aarch64/src/fdt.rs | 25 ++++++++++++++++--------- aarch64/src/lib.rs | 46 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 18 deletions(-) (limited to 'aarch64/src') diff --git a/aarch64/src/fdt.rs b/aarch64/src/fdt.rs index 753ca0f..dd15b0a 100644 --- a/aarch64/src/fdt.rs +++ b/aarch64/src/fdt.rs @@ -20,6 +20,7 @@ use crate::AARCH64_GIC_CPUI_BASE; use crate::AARCH64_GIC_CPUI_SIZE; use crate::AARCH64_GIC_DIST_BASE; use crate::AARCH64_GIC_DIST_SIZE; +use crate::AARCH64_GIC_REDIST_SIZE; // These are RTC related constants use crate::AARCH64_RTC_ADDR; @@ -86,16 +87,20 @@ fn create_cpu_nodes(fdt: &mut Vec, num_cpus: u32) -> Result<()> { Ok(()) } -fn create_gic_node(fdt: &mut Vec) -> Result<()> { - let gic_reg_prop = generate_prop64(&[ - AARCH64_GIC_DIST_BASE, - AARCH64_GIC_DIST_SIZE, - AARCH64_GIC_CPUI_BASE, - AARCH64_GIC_CPUI_SIZE, - ]); +fn create_gic_node(fdt: &mut Vec, is_gicv3: bool, num_cpus: u64) -> Result<()> { + let mut gic_reg_prop = [AARCH64_GIC_DIST_BASE, AARCH64_GIC_DIST_SIZE, 0, 0]; begin_node(fdt, "intc")?; - property_string(fdt, "compatible", "arm,cortex-a15-gic")?; + if is_gicv3 { + property_string(fdt, "compatible", "arm,gic-v3")?; + gic_reg_prop[2] = AARCH64_GIC_DIST_BASE - (AARCH64_GIC_REDIST_SIZE * num_cpus); + gic_reg_prop[3] = AARCH64_GIC_REDIST_SIZE * num_cpus; + } else { + property_string(fdt, "compatible", "arm,cortex-a15-gic")?; + gic_reg_prop[2] = AARCH64_GIC_CPUI_BASE; + gic_reg_prop[3] = AARCH64_GIC_CPUI_SIZE; + } + let gic_reg_prop = generate_prop64(&gic_reg_prop); property_u32(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS)?; property_null(fdt, "interrupt-controller")?; property(fdt, "reg", &gic_reg_prop)?; @@ -318,6 +323,7 @@ fn create_rtc_node(fdt: &mut Vec) -> Result<()> { /// * `cmdline` - The kernel commandline /// * `initrd` - An optional tuple of initrd guest physical address and size /// * `android_fstab` - An optional file holding Android fstab entries +/// * `is_gicv3` - True if gicv3, false if v2 pub fn create_fdt( fdt_max_size: usize, guest_mem: &GuestMemory, @@ -329,6 +335,7 @@ pub fn create_fdt( cmdline: &CStr, initrd: Option<(GuestAddress, usize)>, android_fstab: Option, + is_gicv3: bool, ) -> Result<()> { let mut fdt = vec![0; fdt_max_size]; start_fdt(&mut fdt, fdt_max_size)?; @@ -345,7 +352,7 @@ pub fn create_fdt( create_chosen_node(&mut fdt, cmdline, initrd)?; create_memory_node(&mut fdt, guest_mem)?; create_cpu_nodes(&mut fdt, num_cpus)?; - create_gic_node(&mut fdt)?; + create_gic_node(&mut fdt, is_gicv3, num_cpus as u64)?; create_timer_node(&mut fdt, num_cpus)?; create_serial_nodes(&mut fdt)?; create_psci_node(&mut fdt)?; diff --git a/aarch64/src/lib.rs b/aarch64/src/lib.rs index 5beb473..1a3b049 100644 --- a/aarch64/src/lib.rs +++ b/aarch64/src/lib.rs @@ -44,6 +44,7 @@ const AARCH64_AXI_BASE: u64 = 0x40000000; // address space. const AARCH64_GIC_DIST_BASE: u64 = AARCH64_AXI_BASE - AARCH64_GIC_DIST_SIZE; const AARCH64_GIC_CPUI_BASE: u64 = AARCH64_GIC_DIST_BASE - AARCH64_GIC_CPUI_SIZE; +const AARCH64_GIC_REDIST_SIZE: u64 = 0x20000; // This is the minimum number of SPI interrupts aligned to 32 + 32 for the // PPI (16) and GSI (16). @@ -230,7 +231,7 @@ impl arch::LinuxArch for AArch64 { let vcpu_affinity = components.vcpu_affinity; - let irq_chip = Self::create_irq_chip(&vm)?; + let (irq_chip, is_gicv3) = Self::create_irq_chip(&vm, vcpu_count as u64)?; let mut mmio_bus = devices::Bus::new(); @@ -298,6 +299,7 @@ impl arch::LinuxArch for AArch64 { pci_irqs, components.android_fstab, kernel_end, + is_gicv3, )?; Ok(RunnableLinuxVm { @@ -326,6 +328,7 @@ impl AArch64 { pci_irqs: Vec<(u32, PciInterruptPin)>, android_fstab: Option, kernel_end: u64, + is_gicv3: bool, ) -> Result<()> { let initrd = match initrd_file { Some(initrd_file) => { @@ -353,6 +356,7 @@ impl AArch64 { cmdline, initrd, android_fstab, + is_gicv3, ) .map_err(Error::CreateFdt)?; Ok(()) @@ -416,11 +420,14 @@ impl AArch64 { /// # Arguments /// /// * `vm` - the vm object - fn create_irq_chip(vm: &Vm) -> Result> { + /// * `vcpu_count` - the number of vCPUs + fn create_irq_chip(vm: &Vm, vcpu_count: u64) -> Result<(Option, bool)> { let cpu_if_addr: u64 = AARCH64_GIC_CPUI_BASE; let dist_if_addr: u64 = AARCH64_GIC_DIST_BASE; + let redist_addr: u64 = dist_if_addr - (AARCH64_GIC_REDIST_SIZE * vcpu_count); let raw_cpu_if_addr = &cpu_if_addr as *const u64; let raw_dist_if_addr = &dist_if_addr as *const u64; + let raw_redist_addr = &redist_addr as *const u64; let cpu_if_attr = kvm_device_attr { group: kvm_sys::KVM_DEV_ARM_VGIC_GRP_ADDR, @@ -428,19 +435,40 @@ impl AArch64 { addr: raw_cpu_if_addr as u64, flags: 0, }; - let dist_attr = kvm_device_attr { + let redist_attr = kvm_device_attr { + group: kvm_sys::KVM_DEV_ARM_VGIC_GRP_ADDR, + attr: kvm_sys::KVM_VGIC_V3_ADDR_TYPE_REDIST as u64, + addr: raw_redist_addr as u64, + flags: 0, + }; + let mut dist_attr = kvm_device_attr { group: kvm_sys::KVM_DEV_ARM_VGIC_GRP_ADDR, - attr: kvm_sys::KVM_VGIC_V2_ADDR_TYPE_DIST as u64, addr: raw_dist_if_addr as u64, + attr: 0, flags: 0, }; + let mut kcd = kvm_sys::kvm_create_device { - type_: kvm_sys::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2, + type_: kvm_sys::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3, fd: 0, flags: 0, }; - vm.create_device(&mut kcd) - .map_err(|e| Error::CreateGICFailure(e))?; + + let mut cpu_redist_attr = redist_attr; + let mut is_gicv3 = true; + dist_attr.attr = kvm_sys::KVM_VGIC_V3_ADDR_TYPE_DIST as u64; + if vm.create_device(&mut kcd).is_err() { + is_gicv3 = false; + cpu_redist_attr = cpu_if_attr; + kcd.type_ = kvm_sys::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2; + dist_attr.attr = kvm_sys::KVM_VGIC_V2_ADDR_TYPE_DIST as u64; + vm.create_device(&mut kcd) + .map_err(|e| Error::CreateGICFailure(e))?; + } + + let is_gicv3 = is_gicv3; + let cpu_redist_attr = cpu_redist_attr; + let dist_attr = dist_attr; // Safe because the kernel is passing us an FD back inside // the struct after we successfully did the create_device ioctl @@ -448,7 +476,7 @@ impl AArch64 { // Safe because we allocated the struct that's being passed in let ret = unsafe { - sys_util::ioctl_with_ref(&vgic_fd, kvm_sys::KVM_SET_DEVICE_ATTR(), &cpu_if_attr) + sys_util::ioctl_with_ref(&vgic_fd, kvm_sys::KVM_SET_DEVICE_ATTR(), &cpu_redist_attr) }; if ret != 0 { return Err(Error::CreateGICFailure(sys_util::Error::new(ret))); @@ -494,7 +522,7 @@ impl AArch64 { if ret != 0 { return Err(Error::SetDeviceAttr(sys_util::Error::new(ret))); } - Ok(Some(vgic_fd)) + Ok((Some(vgic_fd), is_gicv3)) } fn configure_vcpu( -- cgit 1.4.1