@@ -723,6 +723,7 @@ DEF_HELPER_FLAGS_1(load_vtb, TCG_CALL_NO_RWG, tl, env)
#if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_purr, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_2(store_hrmor, void, env, tl)
DEF_HELPER_2(store_ptcr, void, env, tl)
DEF_HELPER_FLAGS_1(load_dpdes, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_dpdes, TCG_CALL_NO_RWG, void, env, tl)
@@ -177,6 +177,7 @@ void spr_write_pidr(DisasContext *ctx, int sprn, int gprn);
void spr_write_lpidr(DisasContext *ctx, int sprn, int gprn);
void spr_read_hior(DisasContext *ctx, int gprn, int sprn);
void spr_write_hior(DisasContext *ctx, int sprn, int gprn);
+void spr_write_hrmor(DisasContext *ctx, int sprn, int gprn);
void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn);
void spr_write_pcr(DisasContext *ctx, int sprn, int gprn);
void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn);
@@ -21,6 +21,7 @@
#include "cpu.h"
#include "cpu-models.h"
#include "cpu-qom.h"
+#include "exec/exec-all.h"
#include "exec/log.h"
#include "fpu/softfloat-helpers.h"
#include "mmu-hash64.h"
@@ -101,6 +102,9 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
/* The gtse bit affects hflags */
hreg_compute_hflags(env);
+ /* Various untagged bits affect translation (e.g., TC, HR, etc). */
+ tlb_flush(env_cpu(env));
+
ppc_maybe_interrupt(env);
}
@@ -5496,7 +5496,7 @@ static void register_book3s_ids_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_HRMOR, "HRMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_core_write_generic,
+ &spr_read_generic, &spr_write_hrmor,
0x00000000);
}
@@ -169,6 +169,29 @@ void helper_store_sdr1(CPUPPCState *env, target_ulong val)
}
#if defined(TARGET_PPC64)
+void helper_store_hrmor(CPUPPCState *env, target_ulong val)
+{
+ if (env->spr[SPR_HRMOR] != val) {
+ CPUState *cs = env_cpu(env);
+
+ qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, val);
+
+ if (ppc_cpu_lpar_single_threaded(cs)) {
+ env->spr[SPR_HRMOR] = val;
+ tlb_flush(cs);
+ } else {
+ CPUState *ccs;
+
+ THREAD_SIBLING_FOREACH(cs, ccs) {
+ PowerPCCPU *ccpu = POWERPC_CPU(ccs);
+ CPUPPCState *cenv = &ccpu->env;
+ cenv->spr[SPR_HRMOR] = val;
+ tlb_flush(ccs);
+ }
+ }
+ }
+}
+
void helper_store_ptcr(CPUPPCState *env, target_ulong val)
{
if (env->spr[SPR_PTCR] != val) {
@@ -909,6 +909,16 @@ void spr_write_hior(DisasContext *ctx, int sprn, int gprn)
tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0x3FFFFF00000ULL);
tcg_gen_st_tl(t0, tcg_env, offsetof(CPUPPCState, excp_prefix));
}
+
+void spr_write_hrmor(DisasContext *ctx, int sprn, int gprn)
+{
+ if (!gen_serialize_core(ctx)) {
+ return;
+ }
+
+ gen_helper_store_hrmor(tcg_env, cpu_gpr[gprn]);
+}
+
void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
{
if (!gen_serialize_core(ctx)) {
The HRMOR and LPCR registers are involved with MMU translations that are not tagged in the TLB (i.e., with mmuidx), so the TLB needs to be flushed when these are changed, e.g., as PIDR, LPIDR already do. target/ppc: add missing TLB flushes for MMU SPR updates Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- target/ppc/helper.h | 1 + target/ppc/spr_common.h | 1 + target/ppc/cpu.c | 4 ++++ target/ppc/cpu_init.c | 2 +- target/ppc/misc_helper.c | 23 +++++++++++++++++++++++ target/ppc/translate.c | 10 ++++++++++ 6 files changed, 40 insertions(+), 1 deletion(-)