ppc: Improve PCR bit selection in ppc_set_compat()
authorThomas Huth <thuth@redhat.com>
Tue, 7 Jun 2016 15:39:39 +0000 (17:39 +0200)
committerDavid Gibson <david@gibson.dropbear.id.au>
Tue, 14 Jun 2016 00:41:38 +0000 (10:41 +1000)
When using an olderr PowerISA level, all the upper compatibility
bits have to be enabled, too. For example when we want to run
something in PowerISA 2.05 compatibility mode on POWER8, the bit
for 2.06 has to be set beside the bit for 2.05.
Additionally, to make sure that we do not set bits that are not
supported by the host, we apply a mask with the known-to-be-good
bits here, too.

Signed-off-by: Thomas Huth <thuth@redhat.com>
[dwg: Added some #ifs to fix compile on 32-bit targets]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
target-ppc/cpu.h
target-ppc/translate_init.c

index 9087a0800275e46ad88d8f1e5cdc60201fe21f3d..93c2dd5a65a124064ed08acba4845f9c8d0de337 100644 (file)
@@ -1187,7 +1187,9 @@ void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
 void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 int ppc_get_compat_smt_threads(PowerPCCPU *cpu);
+#if defined(TARGET_PPC64)
 void ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version, Error **errp);
+#endif
 
 /* Time-base and decrementer management */
 #ifndef NO_CPU_IO_DEFS
index fa09183f2f6a908611a7e820d6e0d73f811ebbd1..274009a888e7f1527791b59f021e88f1ef36f83f 100644 (file)
@@ -9515,28 +9515,34 @@ int ppc_get_compat_smt_threads(PowerPCCPU *cpu)
     return ret;
 }
 
+#ifdef TARGET_PPC64
 void ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version, Error **errp)
 {
     int ret = 0;
     CPUPPCState *env = &cpu->env;
+    PowerPCCPUClass *host_pcc;
 
     cpu->cpu_version = cpu_version;
 
     switch (cpu_version) {
     case CPU_POWERPC_LOGICAL_2_05:
-        env->spr[SPR_PCR] = PCR_COMPAT_2_05;
+        env->spr[SPR_PCR] = PCR_TM_DIS | PCR_VSX_DIS | PCR_COMPAT_2_07 |
+                            PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
         break;
     case CPU_POWERPC_LOGICAL_2_06:
-        env->spr[SPR_PCR] = PCR_COMPAT_2_06;
-        break;
     case CPU_POWERPC_LOGICAL_2_06_PLUS:
-        env->spr[SPR_PCR] = PCR_COMPAT_2_06;
+        env->spr[SPR_PCR] = PCR_TM_DIS | PCR_COMPAT_2_07 | PCR_COMPAT_2_06;
         break;
     default:
         env->spr[SPR_PCR] = 0;
         break;
     }
 
+    host_pcc = kvm_ppc_get_host_cpu_class();
+    if (host_pcc) {
+        env->spr[SPR_PCR] &= host_pcc->pcr_mask;
+    }
+
     if (kvm_enabled()) {
         ret = kvmppc_set_compat(cpu, cpu->cpu_version);
         if (ret < 0) {
@@ -9545,6 +9551,7 @@ void ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version, Error **errp)
         }
     }
 }
+#endif
 
 static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
 {