aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/translate_init.c
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2011-11-01 20:57:01 +0000
committerBlue Swirl <blauwirbel@gmail.com>2011-11-01 20:57:01 +0000
commite927dab1fda0eee41fa5fe51ae98293f66a86db1 (patch)
treef4e2c0f47ef3f0e4821d019bb796a1a1c0c225a8 /target-ppc/translate_init.c
parent2ff6458116546ced7ce00cc39423ee30b1477e67 (diff)
parent3384f95c59e5db381cf3e605c8acec71baf0e6b8 (diff)
Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf
* 'ppc-next' of git://repo.or.cz/qemu/agraf: (24 commits) pseries: Add partial support for PCI ppc: Alter CPU state to mask out TCG unimplemented instructions as appropriate pseries: Allow writes to KVM accelerated TCE table KVM: PPC: Override host vmx/vsx/dfp only when information known ppc: Fix up usermode only builds pseries: Correct vmx/dfp handling in both KVM and TCG cases PPC: Fail configure when libfdt is not available ppc: Avoid decrementer related kvm exits PPC: Disable non-440 CPUs for ppcemb target PPC: Bump qemu-system-ppc to 64-bit physical address space pseries: Under kvm use guest cpu = host cpu by default ppc: Add cpu defs for POWER7 revisions 2.1 and 2.3 ppc: First cut implementation of -cpu host ppc: Remove broken partial PVR matching pseries: Update SLOF firmware image pseries: Add device tree properties for VMX/VSX and DFP under kvm ppc: Generalize the kvmppc_get_clockfreq() function Set an invalid-bits mask for each SPE instructions pseries: Update SLOF firmware image pseries: Use Book3S-HV TCE acceleration capabilities ...
Diffstat (limited to 'target-ppc/translate_init.c')
-rw-r--r--target-ppc/translate_init.c106
1 files changed, 58 insertions, 48 deletions
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index ca0d8525c8..8a7233fc82 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -24,6 +24,8 @@
#include "dis-asm.h"
#include "gdbstub.h"
+#include <kvm.h>
+#include "kvm_ppc.h"
//#define PPC_DUMP_CPU
//#define PPC_DEBUG_SPR
@@ -32,22 +34,6 @@
#define TODO_USER_ONLY 1
#endif
-struct ppc_def_t {
- const char *name;
- uint32_t pvr;
- uint32_t svr;
- uint64_t insns_flags;
- uint64_t insns_flags2;
- uint64_t msr_mask;
- powerpc_mmu_t mmu_model;
- powerpc_excp_t excp_model;
- powerpc_input_t bus_model;
- uint32_t flags;
- int bfd_mach;
- void (*init_proc)(CPUPPCState *env);
- int (*check_pow)(CPUPPCState *env);
-};
-
/* For user-mode emulation, we don't emulate any IRQ controller */
#if defined(CONFIG_USER_ONLY)
#define PPC_IRQ_INIT_FN(name) \
@@ -6533,7 +6519,7 @@ static void init_proc_970MP (CPUPPCState *env)
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI | \
PPC_POPCNTB | PPC_POPCNTWD)
-#define POWERPC_INSNS2_POWER7 (PPC_NONE)
+#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP)
#define POWERPC_MSRM_POWER7 (0x800000000204FF36ULL)
#define POWERPC_MMU_POWER7 (POWERPC_MMU_2_06)
#define POWERPC_EXCP_POWER7 (POWERPC_EXCP_POWER7)
@@ -7331,6 +7317,8 @@ enum {
CPU_POWERPC_POWER6A = 0x0F000002,
#define CPU_POWERPC_POWER7 CPU_POWERPC_POWER7_v20
CPU_POWERPC_POWER7_v20 = 0x003F0200,
+ CPU_POWERPC_POWER7_v21 = 0x003F0201,
+ CPU_POWERPC_POWER7_v23 = 0x003F0203,
CPU_POWERPC_970 = 0x00390202,
#define CPU_POWERPC_970FX CPU_POWERPC_970FX_v31
CPU_POWERPC_970FX_v10 = 0x00391100,
@@ -9137,6 +9125,8 @@ static const ppc_def_t ppc_defs[] = {
/* POWER7 */
POWERPC_DEF("POWER7", CPU_POWERPC_POWER7, POWER7),
POWERPC_DEF("POWER7_v2.0", CPU_POWERPC_POWER7_v20, POWER7),
+ POWERPC_DEF("POWER7_v2.1", CPU_POWERPC_POWER7_v21, POWER7),
+ POWERPC_DEF("POWER7_v2.3", CPU_POWERPC_POWER7_v23, POWER7),
/* PowerPC 970 */
POWERPC_DEF("970", CPU_POWERPC_970, 970),
/* PowerPC 970FX (G5) */
@@ -9856,6 +9846,22 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
env->bus_model = def->bus_model;
env->insns_flags = def->insns_flags;
env->insns_flags2 = def->insns_flags2;
+ if (!kvm_enabled()) {
+ /* TCG doesn't (yet) emulate some groups of instructions that
+ * are implemented on some otherwise supported CPUs (e.g. VSX
+ * and decimal floating point instructions on POWER7). We
+ * remove unsupported instruction groups from the cpu state's
+ * instruction masks and hope the guest can cope. For at
+ * least the pseries machine, the unavailability of these
+ * instructions can be advertise to the guest via the device
+ * tree.
+ *
+ * FIXME: we should have a similar masking for CPU features
+ * not accessible under KVM, but so far, there aren't any of
+ * those. */
+ env->insns_flags &= PPC_TCG_INSNS;
+ env->insns_flags2 &= PPC_TCG_INSNS2;
+ }
env->flags = def->flags;
env->bfd_mach = def->bfd_mach;
env->check_pow = def->check_pow;
@@ -10041,42 +10047,34 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
return 0;
}
-static const ppc_def_t *ppc_find_by_pvr (uint32_t pvr)
+static bool ppc_cpu_usable(const ppc_def_t *def)
{
- const ppc_def_t *ret;
- uint32_t pvr_rev;
- int i, best, match, best_match, max;
+#if defined(TARGET_PPCEMB)
+ /* When using the ppcemb target, we only support 440 style cores */
+ if (def->mmu_model != POWERPC_MMU_BOOKE) {
+ return false;
+ }
+#endif
- ret = NULL;
- max = ARRAY_SIZE(ppc_defs);
- best = -1;
- pvr_rev = pvr & 0xFFFF;
- /* We want all specified bits to match */
- best_match = 32 - ctz32(pvr_rev);
- for (i = 0; i < max; i++) {
- /* We check that the 16 higher bits are the same to ensure the CPU
- * model will be the choosen one.
- */
- if (((pvr ^ ppc_defs[i].pvr) >> 16) == 0) {
- /* We want as much as possible of the low-level 16 bits
- * to be the same but we allow inexact matches.
- */
- match = clz32(pvr_rev ^ (ppc_defs[i].pvr & 0xFFFF));
- /* We check '>=' instead of '>' because the PPC_defs table
- * is ordered by increasing revision.
- * Then, we will match the higher revision compatible
- * with the requested PVR
- */
- if (match >= best_match) {
- best = i;
- best_match = match;
- }
+ return true;
+}
+
+const ppc_def_t *ppc_find_by_pvr(uint32_t pvr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
+ if (!ppc_cpu_usable(&ppc_defs[i])) {
+ continue;
+ }
+
+ /* If we have an exact match, we're done */
+ if (pvr == ppc_defs[i].pvr) {
+ return &ppc_defs[i];
}
}
- if (best != -1)
- ret = &ppc_defs[best];
- return ret;
+ return NULL;
}
#include <ctype.h>
@@ -10087,6 +10085,10 @@ const ppc_def_t *cpu_ppc_find_by_name (const char *name)
const char *p;
int i, max, len;
+ if (kvm_enabled() && (strcasecmp(name, "host") == 0)) {
+ return kvmppc_host_cpu_def();
+ }
+
/* Check if the given name is a PVR */
len = strlen(name);
if (len == 10 && name[0] == '0' && name[1] == 'x') {
@@ -10105,6 +10107,10 @@ const ppc_def_t *cpu_ppc_find_by_name (const char *name)
ret = NULL;
max = ARRAY_SIZE(ppc_defs);
for (i = 0; i < max; i++) {
+ if (!ppc_cpu_usable(&ppc_defs[i])) {
+ continue;
+ }
+
if (strcasecmp(name, ppc_defs[i].name) == 0) {
ret = &ppc_defs[i];
break;
@@ -10120,6 +10126,10 @@ void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf)
max = ARRAY_SIZE(ppc_defs);
for (i = 0; i < max; i++) {
+ if (!ppc_cpu_usable(&ppc_defs[i])) {
+ continue;
+ }
+
(*cpu_fprintf)(f, "PowerPC %-16s PVR %08x\n",
ppc_defs[i].name, ppc_defs[i].pvr);
}