summary refs log tree commit diff
path: root/aarch64/src
diff options
context:
space:
mode:
authorStephen Boyd <swboyd@chromium.org>2019-11-25 23:09:15 -0800
committerCommit Bot <commit-bot@chromium.org>2019-12-06 23:59:23 +0000
commit754b90630411dee380de08f0bfd5c111906cdd3b (patch)
tree37810f60ce00e5e4fb9ffa10085e749ca8265414 /aarch64/src
parentcef1079c2058457bc9485fc0f41f5fe1d592e715 (diff)
downloadcrosvm-754b90630411dee380de08f0bfd5c111906cdd3b.tar
crosvm-754b90630411dee380de08f0bfd5c111906cdd3b.tar.gz
crosvm-754b90630411dee380de08f0bfd5c111906cdd3b.tar.bz2
crosvm-754b90630411dee380de08f0bfd5c111906cdd3b.tar.lz
crosvm-754b90630411dee380de08f0bfd5c111906cdd3b.tar.xz
crosvm-754b90630411dee380de08f0bfd5c111906cdd3b.tar.zst
crosvm-754b90630411dee380de08f0bfd5c111906cdd3b.zip
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 <smbarber@chromium.org>
Commit-Queue: Stephen Barber <smbarber@chromium.org>
Tested-by: Stephen Barber <smbarber@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'aarch64/src')
-rw-r--r--aarch64/src/fdt.rs25
-rw-r--r--aarch64/src/lib.rs46
2 files changed, 53 insertions, 18 deletions
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<u8>, num_cpus: u32) -> Result<()> {
     Ok(())
 }
 
-fn create_gic_node(fdt: &mut Vec<u8>) -> 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<u8>, 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<u8>) -> 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<File>,
+    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<File>,
         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<Option<File>> {
+    /// * `vcpu_count` - the number of vCPUs
+    fn create_irq_chip(vm: &Vm, vcpu_count: u64) -> Result<(Option<File>, 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(