]> Git Repo - qemu.git/blobdiff - target/ppc/compat.c
target-ppc: optimize cmp translation
[qemu.git] / target / ppc / compat.c
index f1b67faa97e399272f7d0fdfe883f1fd3cd6a330..807c906f68486e4f8c0c012515007fdf4728fa4d 100644 (file)
@@ -32,7 +32,16 @@ typedef struct {
     uint32_t pvr;
     uint64_t pcr;
     uint64_t pcr_level;
-    int max_threads;
+
+    /*
+     * Maximum allowed virtual threads per virtual core
+     *
+     * This is to stop older guests getting confused by seeing more
+     * threads than they think the cpu can support.  Usually it's
+     * equal to the number of threads supported on bare metal
+     * hardware, but not always (see POWER9).
+     */
+    int max_vthreads;
 } CompatInfo;
 
 static const CompatInfo compat_table[] = {
@@ -45,35 +54,42 @@ static const CompatInfo compat_table[] = {
         .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 |
                PCR_COMPAT_2_05 | PCR_TM_DIS | PCR_VSX_DIS,
         .pcr_level = PCR_COMPAT_2_05,
-        .max_threads = 2,
+        .max_vthreads = 2,
     },
     { /* POWER7, ISA2.06 */
         .name = "power7",
         .pvr = CPU_POWERPC_LOGICAL_2_06,
         .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
         .pcr_level = PCR_COMPAT_2_06,
-        .max_threads = 4,
+        .max_vthreads = 4,
     },
     {
         .name = "power7+",
         .pvr = CPU_POWERPC_LOGICAL_2_06_PLUS,
         .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
         .pcr_level = PCR_COMPAT_2_06,
-        .max_threads = 4,
+        .max_vthreads = 4,
     },
     { /* POWER8, ISA2.07 */
         .name = "power8",
         .pvr = CPU_POWERPC_LOGICAL_2_07,
         .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07,
         .pcr_level = PCR_COMPAT_2_07,
-        .max_threads = 8,
+        .max_vthreads = 8,
     },
     { /* POWER9, ISA3.00 */
         .name = "power9",
         .pvr = CPU_POWERPC_LOGICAL_3_00,
         .pcr = PCR_COMPAT_3_00,
         .pcr_level = PCR_COMPAT_3_00,
-        .max_threads = 4,
+        /*
+         * POWER9 hardware only supports 4 threads / core, but this
+         * limit is for guests.  We need to support 8 vthreads/vcore
+         * on POWER9 for POWER8 compatibility guests, and it's very
+         * confusing if half of the threads disappear from the guest
+         * if it announces it's POWER9 aware at CAS time.
+         */
+        .max_vthreads = 8,
     },
 };
 
@@ -140,16 +156,17 @@ void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp)
 
     cpu_synchronize_state(CPU(cpu));
 
-    cpu->compat_pvr = compat_pvr;
-    env->spr[SPR_PCR] = pcr & pcc->pcr_mask;
-
-    if (kvm_enabled()) {
-        int ret = kvmppc_set_compat(cpu, cpu->compat_pvr);
+    if (kvm_enabled() && cpu->compat_pvr != compat_pvr) {
+        int ret = kvmppc_set_compat(cpu, compat_pvr);
         if (ret < 0) {
             error_setg_errno(errp, -ret,
                              "Unable to set CPU compatibility mode in KVM");
+            return;
         }
     }
+
+    cpu->compat_pvr = compat_pvr;
+    env->spr[SPR_PCR] = pcr & pcc->pcr_mask;
 }
 
 typedef struct {
@@ -184,14 +201,14 @@ void ppc_set_compat_all(uint32_t compat_pvr, Error **errp)
     }
 }
 
-int ppc_compat_max_threads(PowerPCCPU *cpu)
+int ppc_compat_max_vthreads(PowerPCCPU *cpu)
 {
     const CompatInfo *compat = compat_by_pvr(cpu->compat_pvr);
     int n_threads = CPU(cpu)->nr_threads;
 
     if (cpu->compat_pvr) {
         g_assert(compat);
-        n_threads = MIN(n_threads, compat->max_threads);
+        n_threads = MIN(n_threads, compat->max_vthreads);
     }
 
     return n_threads;
This page took 0.0261 seconds and 4 git commands to generate.