From 31b2b0f8463533c32b5ad76e73668e2e9fca8ae2 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Thu, 13 Apr 2017 16:02:36 +1000 Subject: [PATCH] target/ppc: Flush TLB on write to PIDR The PIDR (process id register) is used to store the id of the currently running process, which is used to select the process table entry used to perform address translation. This means that when we write to this register all the translations in the TLB become outdated as they are for a previously running process. Thus when this register is written to we need to invalidate the TLB entries to ensure stale entries aren't used to to perform translation for the new process, which would result in at best segfaults or alternatively just random memory being accessed. Signed-off-by: Suraj Jitindar Singh Reviewed-by: David Gibson [dwg: Fixed compile error for 32-bit targets] Signed-off-by: David Gibson --- target/ppc/helper.h | 1 + target/ppc/misc_helper.c | 8 ++++++++ target/ppc/translate_init.c | 10 ++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 6d77661f7c..bb6a94a8b3 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -709,6 +709,7 @@ DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env) DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env) #endif DEF_HELPER_2(store_sdr1, void, env, tl) +DEF_HELPER_2(store_pidr, void, env, tl) DEF_HELPER_FLAGS_2(store_tbl, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(store_tbu, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(store_atbl, TCG_CALL_NO_RWG, void, env, tl) diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index fa573dd7d2..0e4217821b 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -88,6 +88,14 @@ void helper_store_sdr1(CPUPPCState *env, target_ulong val) } } +void helper_store_pidr(CPUPPCState *env, target_ulong val) +{ + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + env->spr[SPR_BOOKS_PID] = val; + tlb_flush(CPU(cpu)); +} + void helper_store_hid0_601(CPUPPCState *env, target_ulong val) { target_ulong hid0; diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index aa0c44dac1..77e5463a92 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -394,8 +394,14 @@ static void spr_write_sdr1 (DisasContext *ctx, int sprn, int gprn) gen_helper_store_sdr1(cpu_env, cpu_gpr[gprn]); } -/* 64 bits PowerPC specific SPRs */ #if defined(TARGET_PPC64) +/* 64 bits PowerPC specific SPRs */ +/* PIDR */ +static void spr_write_pidr(DisasContext *ctx, int sprn, int gprn) +{ + gen_helper_store_pidr(cpu_env, cpu_gpr[gprn]); +} + static void spr_read_hior (DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, excp_prefix)); @@ -8200,7 +8206,7 @@ static void gen_spr_power8_book4(CPUPPCState *env) KVM_REG_PPC_ACOP, 0); spr_register_kvm(env, SPR_BOOKS_PID, "PID", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_pidr, KVM_REG_PPC_PID, 0); spr_register_kvm(env, SPR_WORT, "WORT", SPR_NOACCESS, SPR_NOACCESS,