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>
This commit is contained in:
Stephen Boyd 2019-11-25 23:09:15 -08:00 committed by Commit Bot
parent cef1079c20
commit 754b906304
2 changed files with 54 additions and 19 deletions

View file

@ -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)?;

View file

@ -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_V2_ADDR_TYPE_DIST as u64,
addr: raw_dist_if_addr as u64,
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,
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(