summary refs log tree commit diff
diff options
context:
space:
mode:
authorSonny Rao <sonnyrao@chromium.org>2018-03-27 16:30:51 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-04-03 12:50:39 -0700
commita7fae252b05b617fd27f58b9bba8122d18154ccb (patch)
treedda93c135a6df228f813e02003925b839a0be87c
parent2ffa0cbe5bb41beea81fd2d14a7f781747bb955e (diff)
downloadcrosvm-a7fae252b05b617fd27f58b9bba8122d18154ccb.tar
crosvm-a7fae252b05b617fd27f58b9bba8122d18154ccb.tar.gz
crosvm-a7fae252b05b617fd27f58b9bba8122d18154ccb.tar.bz2
crosvm-a7fae252b05b617fd27f58b9bba8122d18154ccb.tar.lz
crosvm-a7fae252b05b617fd27f58b9bba8122d18154ccb.tar.xz
crosvm-a7fae252b05b617fd27f58b9bba8122d18154ccb.tar.zst
crosvm-a7fae252b05b617fd27f58b9bba8122d18154ccb.zip
crosvm: aarch64: get kernel's preferred target type for vcpus
This fixes an issue on kevin where if we start on a little core, the
kernel doesn't like the generic ARMv8 target cpu type for some reason.  To
fix this we must query the preferred type from the vm device first and
supply that to the vcpu init ioctl.

We need to change the signature of the configure_vcpu method to pass
in the vm object even though we aren't using it on x86.

BUG=chromium:797868
TEST=./build_test passes on all architectures
TEST=crosvm runs on kevin

Change-Id: I460cb9db62a8805bb88f838956aa4f1c69183961
Reviewed-on: https://chromium-review.googlesource.com/982996
Commit-Ready: Sonny Rao <sonnyrao@chromium.org>
Tested-by: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Zach Reizner <zachr@chromium.org>
-rw-r--r--aarch64/src/lib.rs5
-rw-r--r--arch/src/lib.rs2
-rw-r--r--kvm/src/lib.rs15
-rw-r--r--src/linux.rs2
-rw-r--r--x86_64/src/lib.rs2
5 files changed, 24 insertions, 2 deletions
diff --git a/aarch64/src/lib.rs b/aarch64/src/lib.rs
index de1f776..c53d2c2 100644
--- a/aarch64/src/lib.rs
+++ b/aarch64/src/lib.rs
@@ -326,16 +326,19 @@ impl arch::LinuxArch for AArch64 {
 
     fn configure_vcpu(guest_mem: &GuestMemory,
                       _kvm: &Kvm,
+                      vm: &Vm,
                       vcpu: &Vcpu,
                       cpu_id: u64,
                       _num_cpus: u64)
                       -> Result<()> {
         let mut kvi = kvm_sys::kvm_vcpu_init {
-            // TODO(sonnyrao): need to read back target from host kernel
             target: kvm_sys::KVM_ARM_TARGET_GENERIC_V8,
             features: [0; 7],
         };
 
+        // This reads back the kernel's preferred target type.
+        vm.arm_preferred_target(&mut kvi)?;
+
         // TODO(sonnyrao): need to verify this feature is supported by host kernel
         kvi.features[0] |= 1 << kvm_sys::KVM_ARM_VCPU_PSCI_0_2;
 
diff --git a/arch/src/lib.rs b/arch/src/lib.rs
index 1fece03..9b781c5 100644
--- a/arch/src/lib.rs
+++ b/arch/src/lib.rs
@@ -102,11 +102,13 @@ pub trait LinuxArch {
     /// * `kernel_load_offset` - Offset in bytes from `guest_mem` at which the
     ///                          kernel starts.
     /// * `kvm` - The /dev/kvm object that created vcpu.
+    /// * `vm` - The VM object associated with this VCPU.
     /// * `vcpu` - The VCPU object to configure.
     /// * `cpu_id` - The id of the given `vcpu`.
     /// * `num_cpus` - Number of virtual CPUs the guest will have.
     fn configure_vcpu(guest_mem: &GuestMemory,
                       kvm: &Kvm,
+                      vm: &Vm,
                       vcpu: &Vcpu,
                       cpu_id: u64,
                       num_cpus: u64)
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs
index a76c018..5f321f2 100644
--- a/kvm/src/lib.rs
+++ b/kvm/src/lib.rs
@@ -718,6 +718,21 @@ impl Vm {
             errno_result()
         }
     }
+
+    /// This queries the kernel for the preferred target CPU type.
+    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+    pub fn arm_preferred_target(&self, kvi: &mut kvm_vcpu_init) -> Result<()> {
+        // The ioctl is safe because we allocated the struct and we know the
+        // kernel will write exactly the size of the struct.
+        let ret = unsafe {
+            ioctl_with_mut_ref(self, KVM_ARM_PREFERRED_TARGET(), kvi)
+        };
+        if ret < 0 {
+            return errno_result();
+        }
+        Ok(())
+    }
+
 }
 
 impl AsRawFd for Vm {
diff --git a/src/linux.rs b/src/linux.rs
index f4cc5a6..1911899 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -409,7 +409,7 @@ fn setup_vcpu(kvm: &Kvm,
               -> Result<Vcpu> {
     let vcpu = Vcpu::new(cpu_id as libc::c_ulong, &kvm, &vm)
         .map_err(Error::CreateVcpu)?;
-    Arch::configure_vcpu(vm.get_memory(), &kvm, &vcpu, cpu_id as u64, vcpu_count as u64).
+    Arch::configure_vcpu(vm.get_memory(), &kvm, &vm, &vcpu, cpu_id as u64, vcpu_count as u64).
         map_err(Error::ConfigureVcpu)?;
     Ok(vcpu)
 }
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index 9a16776..1fcaed0 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -396,11 +396,13 @@ impl arch::LinuxArch for X8664arch {
     /// * `kernel_load_offset` - Offset in bytes from `guest_mem` at which the
     ///                          kernel starts.
     /// * `kvm` - The /dev/kvm object that created vcpu.
+    /// * `vm` - The VM object associated with this VCPU.
     /// * `vcpu` - The VCPU object to configure.
     /// * `cpu_id` - The id of the given `vcpu`.
     /// * `num_cpus` - Number of virtual CPUs the guest will have.
     fn configure_vcpu(guest_mem: &GuestMemory,
                       kvm: &Kvm,
+                      _vm: &Vm,
                       vcpu: &Vcpu,
                       cpu_id: u64,
                       num_cpus: u64)