diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 3f77e308a6..8e5c85c28e 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1107,6 +1107,7 @@ void ppc_store_msr (CPUPPCState *env, target_ulong value); void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf); +const ppc_def_t *ppc_find_by_pvr(uint32_t pvr); const ppc_def_t *cpu_ppc_find_by_name (const char *name); int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def); diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 96139acb23..313c7b2af2 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -879,6 +879,25 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size) return 0; } +static inline uint32_t mfpvr(void) +{ + uint32_t pvr; + + asm ("mfpvr %0" + : "=r"(pvr)); + return pvr; +} + +const ppc_def_t *kvmppc_host_cpu_def(void) +{ + uint32_t host_pvr = mfpvr(); + const ppc_def_t *base_spec; + + base_spec = ppc_find_by_pvr(host_pvr); + + return base_spec; +} + bool kvm_arch_stop_on_emulation_error(CPUState *env) { return true; diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index 955729a1cf..b0d6fb667e 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -26,6 +26,7 @@ int kvmppc_smt_threads(void); off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem); void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd); int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size); +const ppc_def_t *kvmppc_host_cpu_def(void); #else @@ -85,6 +86,11 @@ static inline int kvmppc_remove_spapr_tce(void *table, int pfd, return -1; } +static inline const ppc_def_t *kvmppc_host_cpu_def(void) +{ + return NULL; +} + #endif #ifndef CONFIG_KVM diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 73b49cfd6e..62f0a6b867 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 +#include "kvm_ppc.h" //#define PPC_DUMP_CPU //#define PPC_DEBUG_SPR @@ -10041,7 +10043,7 @@ 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) +const ppc_def_t *ppc_find_by_pvr(uint32_t pvr) { int i; @@ -10063,6 +10065,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') {