diff mbox

[v2,2/2] hw/arm/virt: tcg: adjust MPIDR like KVM

Message ID 1467378129-23302-3-git-send-email-drjones@redhat.com
State New
Headers show

Commit Message

Andrew Jones July 1, 2016, 1:02 p.m. UTC
KVM adjusts the MPIDR of guest vcpus based on the architecture of
the host, 32-bit vs. 64-bit, and, for 64-bit, also on the type of
GIC the guest is using. To be consistent and improve SGI efficiency
we make the same adjustments for TCG as 64-bit KVM hosts. We neglect
to add consistency with 32-bit KVM hosts, as that would reduce SGI
efficiency and KVM is expected to change.

As MPIDR is a system register, and thus guest visible, we only make
adjustments for current and later versioned machines.

Signed-off-by: Andrew Jones <drjones@redhat.com>

---
 hw/arm/virt.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

-- 
2.7.4
diff mbox

Patch

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c5c125e9204a0..fb0265e31703a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -52,7 +52,8 @@ 
 #include "hw/arm/sysbus-fdt.h"
 #include "hw/platform-bus.h"
 #include "hw/arm/fdt.h"
-#include "hw/intc/arm_gic_common.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/intc/arm_gicv3_common.h"
 #include "kvm_arm.h"
 #include "hw/smbios/smbios.h"
 #include "qapi/visitor.h"
@@ -82,6 +83,7 @@  typedef struct VirtBoardInfo {
 typedef struct {
     MachineClass parent;
     VirtBoardInfo *daughterboard;
+    bool disallow_affinity_adjustment;
 } VirtMachineClass;
 
 typedef struct {
@@ -1164,6 +1166,7 @@  void virt_guest_info_machine_done(Notifier *notifier, void *data)
 static void machvirt_init(MachineState *machine)
 {
     VirtMachineState *vms = VIRT_MACHINE(machine);
+    VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
     qemu_irq pic[NUM_IRQS];
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *secure_sysmem = NULL;
@@ -1176,6 +1179,7 @@  static void machvirt_init(MachineState *machine)
     VirtGuestInfo *guest_info = &guest_info_state->info;
     char **cpustr;
     bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
+    uint8_t clustersz;
 
     if (!cpu_model) {
         cpu_model = "cortex-a15";
@@ -1221,8 +1225,10 @@  static void machvirt_init(MachineState *machine)
      */
     if (gic_version == 3) {
         virt_max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000;
+        clustersz = GICV3_TARGETLIST_BITS;
     } else {
         virt_max_cpus = GIC_NCPU;
+        clustersz = GIC_TARGETLIST_BITS;
     }
 
     if (max_cpus > virt_max_cpus) {
@@ -1271,6 +1277,21 @@  static void machvirt_init(MachineState *machine)
         }
         cpuobj = object_new(object_class_get_name(oc));
 
+        if (!vmc->disallow_affinity_adjustment) {
+            /* Adjust MPIDR like 64-bit KVM hosts, which incorporate the
+             * GIC's target-list limitations. 32-bit KVM hosts currently
+             * always create clusters of 4 CPUs, but that is expected to
+             * change when they gain support for gicv3. When KVM is enabled
+             * it will override the changes we make here, therefore our
+             * purposes are to make TCG consistent (with 64-bit KVM hosts)
+             * and to improve SGI efficiency.
+             */
+            uint8_t aff1 = n / clustersz;
+            uint8_t aff0 = n % clustersz;
+            object_property_set_int(cpuobj, (aff1 << ARM_AFF1_SHIFT) | aff0,
+                                    "mp-affinity", NULL);
+        }
+
         /* Handle any CPU options specified by the user */
         cc->parse_features(CPU(cpuobj), cpuopts, &err);
         g_free(cpuopts);
@@ -1505,7 +1526,10 @@  static void virt_2_6_instance_init(Object *obj)
 
 static void virt_machine_2_6_options(MachineClass *mc)
 {
+    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
     virt_machine_2_7_options(mc);
     SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_6);
+    vmc->disallow_affinity_adjustment = true;
 }
 DEFINE_VIRT_MACHINE(2, 6)