From 89fca22f212bd9000e9b481bd70dceb8df2a17a0 Mon Sep 17 00:00:00 2001 From: KONRAD Frederic Date: Tue, 1 Aug 2017 10:44:57 +0200 Subject: [PATCH 1/6] booke206: fix MAS update on tlb miss When a tlb instruction miss happen, rw is set to 0 at the bottom of cpu_ppc_handle_mmu_fault which cause the MAS update function to miss the SAS and TS bit in MAS6, MAS1 in booke206_update_mas_tlb_miss. Just calling booke206_update_mas_tlb_miss with rw = 2 solve the issue. Signed-off-by: KONRAD Frederic Signed-off-by: David Gibson --- target/ppc/mmu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index b7b9088842..f06b9382b4 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -1551,7 +1551,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, env->spr[SPR_40x_ESR] = 0x00000000; break; case POWERPC_MMU_BOOKE206: - booke206_update_mas_tlb_miss(env, address, rw); + booke206_update_mas_tlb_miss(env, address, 2); /* fall through */ case POWERPC_MMU_BOOKE: cs->exception_index = POWERPC_EXCP_ITLB; From e7bab9a256d653948760ef9f3d04f14eb2a81731 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Wed, 2 Aug 2017 19:34:16 +0200 Subject: [PATCH 2/6] ppc: fix double-free in cpu_post_load() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When running nested with KVM PR, ppc_set_compat() fails and QEMU crashes because of "double free or corruption (!prev)". The crash happens because error_report_err() has already called error_free(). Signed-off-by: Greg Kurz Reviewed-by: Eric Blake Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- target/ppc/machine.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/ppc/machine.c b/target/ppc/machine.c index f578156dd4..abe0a1cdf0 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -239,7 +239,6 @@ static int cpu_post_load(void *opaque, int version_id) ppc_set_compat(cpu, cpu->compat_pvr, &local_err); if (local_err) { error_report_err(local_err); - error_free(local_err); return -1; } } else From 650f3287abb7c6124b7fb0f4a2330246fe2d4da2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Aug 2017 13:42:53 +1000 Subject: [PATCH 3/6] target/ppc: Implement TIDR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a trivial implementation of the TIDR register added in POWER9. This isn't particularly important to qemu directly - it's used by accelerator modules that we don't emulate. However, since qemu isn't aware of it, its state is not synchronized with KVM and therefore not migrated, which can be a problem. Signed-off-by: David Gibson Reviewed-by: Cédric Le Goater Reviewed-by: Greg Kurz Reviewed-by: Thomas Huth --- target/ppc/cpu.h | 1 + target/ppc/translate_init.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 6ee2a26a96..f6e5413fad 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1451,6 +1451,7 @@ void ppc_compat_add_property(Object *obj, const char *name, #define SPR_TEXASR (0x082) #define SPR_TEXASRU (0x083) #define SPR_UCTRL (0x088) +#define SPR_TIDR (0x090) #define SPR_MPC_CMPA (0x090) #define SPR_MPC_CMPB (0x091) #define SPR_MPC_CMPC (0x092) diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index 01723bdfec..94800cd29d 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -8841,6 +8841,11 @@ static void init_proc_POWER9(CPUPPCState *env) gen_spr_power8_book4(env); gen_spr_power8_rpr(env); + /* POWER9 Specific registers */ + spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, + spr_read_generic, spr_write_generic, + KVM_REG_PPC_TIDR, 0); + /* env variables */ #if !defined(CONFIG_USER_ONLY) env->slb_nr = 32; From b8af5b2d5f67b0e1b274f8532f42a47bfe46ea3b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Aug 2017 15:09:35 +1000 Subject: [PATCH 4/6] target/ppc: Add stub implementation of the PSSCR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PSSCR register added in POWER9 controls certain power saving mode behaviours. Mostly, it's not relevant to TCG, however because qemu doesn't know about it yet, it doesn't synchronize the state with KVM, and thus it doesn't get migrated. To fix that, this adds a minimal stub implementation of the register. This isn't complete, even to the extent that an implementation is possible in TCG, just enough to get migration working. We need to come back later and at least properly filter the various fields in the register based on privilege level. Signed-off-by: David Gibson Reviewed-by: Cédric Le Goater Reviewed-by: Greg Kurz Reviewed-by: Thomas Huth --- target/ppc/cpu.h | 1 + target/ppc/translate_init.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index f6e5413fad..46d3dd88f6 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1771,6 +1771,7 @@ void ppc_compat_add_property(Object *obj, const char *name, #define SPR_IC (0x350) #define SPR_VTB (0x351) #define SPR_MMCRC (0x353) +#define SPR_PSSCR (0x357) #define SPR_440_INV0 (0x370) #define SPR_440_INV1 (0x371) #define SPR_440_INV2 (0x372) diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index 94800cd29d..8fb407ed73 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -8846,6 +8846,11 @@ static void init_proc_POWER9(CPUPPCState *env) spr_read_generic, spr_write_generic, KVM_REG_PPC_TIDR, 0); + /* FIXME: Filter fields properly based on privilege level */ + spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, + spr_read_generic, spr_write_generic, + KVM_REG_PPC_PSSCR, 0); + /* env variables */ #if !defined(CONFIG_USER_ONLY) env->slb_nr = 32; From 325837ca3851d7e6761649a44ea3c111e2e1757f Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Mon, 7 Aug 2017 19:24:39 +0200 Subject: [PATCH 5/6] spapr_drc: abort if object_property_add_child() fails object_property_add_child() can only fail in two cases: - the child already has a parent, which shouldn't happen since the DRC was allocated a few lines above - the parent already has a child with the same name, which would mean the caller tries to create a DRC that already exists In both case, this is a QEMU bug and we should abort. Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr_drc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 47d94e782a..5260b5d363 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -541,7 +541,7 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type, drc->owner = owner; prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", spapr_drc_index(drc)); - object_property_add_child(owner, prop_name, OBJECT(drc), NULL); + object_property_add_child(owner, prop_name, OBJECT(drc), &error_abort); object_property_set_bool(OBJECT(drc), true, "realized", NULL); g_free(prop_name); From f57467e3b326c7736f8e481fd6b680f30e575c87 Mon Sep 17 00:00:00 2001 From: Sam Bobroff Date: Thu, 3 Aug 2017 16:28:27 +1000 Subject: [PATCH 6/6] spapr: Fix bug in h_signal_sys_reset() The unicast case in h_signal_sys_reset() seems to be broken: rather than selecting the target CPU, it looks like it will pick either the first CPU or fail to find one at all. Fix it by using the search function rather than open coding the search. This was found by inspection; the code appears to be unused because the Linux kernel only uses the broadcast target. Signed-off-by: Sam Bobroff Reviewed-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr_hcall.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 72ea5a8247..07b3da8dc4 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1431,11 +1431,10 @@ static target_ulong h_signal_sys_reset(PowerPCCPU *cpu, } else { /* Unicast */ - CPU_FOREACH(cs) { - if (cpu->cpu_dt_id == target) { - run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); - return H_SUCCESS; - } + cs = CPU(ppc_get_vcpu_by_dt_id(target)); + if (cs) { + run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); + return H_SUCCESS; } return H_PARAMETER; }