diff options
-rw-r--r-- | hw/spapr.c | 24 | ||||
-rw-r--r-- | target-ppc/helper.c | 11 | ||||
-rw-r--r-- | target-ppc/kvm.c | 8 | ||||
-rw-r--r-- | target-ppc/kvm_ppc.h | 6 |
4 files changed, 46 insertions, 3 deletions
diff --git a/hw/spapr.c b/hw/spapr.c index 63e5d336ea..c2675e1cc1 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -29,6 +29,9 @@ #include "elf.h" #include "net.h" #include "blockdev.h" +#include "cpus.h" +#include "kvm.h" +#include "kvm_ppc.h" #include "hw/boards.h" #include "hw/ppc.h" @@ -105,6 +108,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; int i; char *modelname; + int smt = kvmppc_smt_threads(); #define _FDT(exp) \ do { \ @@ -164,13 +168,18 @@ static void *spapr_create_fdt_skel(const char *cpu_model, for (env = first_cpu; env != NULL; env = env->next_cpu) { int index = env->cpu_index; - uint32_t gserver_prop[] = {cpu_to_be32(index), 0}; /* HACK! */ + uint32_t servers_prop[smp_threads]; + uint32_t gservers_prop[smp_threads * 2]; char *nodename; uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 0xffffffff, 0xffffffff}; uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ; uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; + if ((index % smt) != 0) { + continue; + } + if (asprintf(&nodename, "%s@%x", modelname, index) < 0) { fprintf(stderr, "Allocation failure\n"); exit(1); @@ -195,9 +204,18 @@ static void *spapr_create_fdt_skel(const char *cpu_model, pft_size_prop, sizeof(pft_size_prop)))); _FDT((fdt_property_string(fdt, "status", "okay"))); _FDT((fdt_property(fdt, "64-bit", NULL, 0))); - _FDT((fdt_property_cell(fdt, "ibm,ppc-interrupt-server#s", index))); + + /* Build interrupt servers and gservers properties */ + for (i = 0; i < smp_threads; i++) { + servers_prop[i] = cpu_to_be32(index + i); + /* Hack, direct the group queues back to cpu 0 */ + gservers_prop[i*2] = cpu_to_be32(index + i); + gservers_prop[i*2 + 1] = 0; + } + _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s", + servers_prop, sizeof(servers_prop)))); _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s", - gserver_prop, sizeof(gserver_prop)))); + gservers_prop, sizeof(gservers_prop)))); if (env->mmu_model & POWERPC_MMU_1TSEG) { _FDT((fdt_property(fdt, "ibm,processor-segment-sizes", diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 6339be3a75..137a494201 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -26,6 +26,8 @@ #include "helper_regs.h" #include "qemu-common.h" #include "kvm.h" +#include "kvm_ppc.h" +#include "cpus.h" //#define DEBUG_MMU //#define DEBUG_BATS @@ -3189,6 +3191,15 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model) if (tcg_enabled()) { ppc_translate_init(); } + /* Adjust cpu index for SMT */ +#if !defined(CONFIG_USER_ONLY) + if (kvm_enabled()) { + int smt = kvmppc_smt_threads(); + + env->cpu_index = (env->cpu_index / smp_threads)*smt + + (env->cpu_index % smp_threads); + } +#endif /* !CONFIG_USER_ONLY */ env->cpu_model_str = cpu_model; cpu_ppc_register_internal(env, def); diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 75832d83b8..6c7ca6fc50 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -28,6 +28,7 @@ #include "kvm_ppc.h" #include "cpu.h" #include "device_tree.h" +#include "hw/spapr.h" #include "hw/sysbus.h" #include "hw/spapr.h" @@ -53,6 +54,7 @@ static int cap_interrupt_unset = false; static int cap_interrupt_level = false; static int cap_segstate; static int cap_booke_sregs; +static int cap_ppc_smt; /* XXX We have a race condition where we actually have a level triggered * interrupt, but the infrastructure can't expose that yet, so the guest @@ -76,6 +78,7 @@ int kvm_arch_init(KVMState *s) cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL); cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE); cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS); + cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT); if (!cap_interrupt_level) { fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the " @@ -750,6 +753,11 @@ fail: cpu_abort(env, "This KVM version does not support PAPR\n"); } +int kvmppc_smt_threads(void) +{ + return cap_ppc_smt ? cap_ppc_smt : 1; +} + 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 c484e60bcb..c298411aa8 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -18,6 +18,7 @@ uint64_t kvmppc_get_clockfreq(void); int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len); int kvmppc_set_interrupt(CPUState *env, int irq, int level); void kvmppc_set_papr(CPUState *env); +int kvmppc_smt_threads(void); #else @@ -45,6 +46,11 @@ static inline void kvmppc_set_papr(CPUState *env) { } +static inline int kvmppc_smt_threads(void) +{ + return 1; +} + #endif #ifndef CONFIG_KVM |