[PATCH v3 31/33] target/ppc/mmu-hash32.c: Drop a local variable

2024-05-07 Thread BALATON Zoltan
In ppc_hash32_xlate() the value of need_prop is checked in two places
but precalculating it does not help because when we reach the first
check we always return and not reach the second place so the value
will only be used once. We can drop the local variable and calculate
it when needed, which makes these checks using it similar to other
places with such checks.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-hash32.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 960751a50e..b5d7aeed4e 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -347,7 +347,6 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 hwaddr pte_offset;
 ppc_hash_pte32_t pte;
 int prot;
-int need_prot;
 hwaddr raddr;
 
 /* There are no hash32 large pages. */
@@ -361,13 +360,11 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 return true;
 }
 
-need_prot = prot_for_access_type(access_type);
-
 /* 2. Check Block Address Translation entries (BATs) */
 if (env->nb_BATs != 0) {
 raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx);
 if (raddr != -1) {
-if (need_prot & ~*protp) {
+if (prot_for_access_type(access_type) & ~*protp) {
 if (guest_visible) {
 if (access_type == MMU_INST_FETCH) {
 cs->exception_index = POWERPC_EXCP_ISI;
@@ -435,7 +432,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 
 prot = ppc_hash32_pte_prot(mmu_idx, sr, pte);
 
-if (need_prot & ~prot) {
+if (prot_for_access_type(access_type) & ~prot) {
 /* Access right violation */
 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
 if (guest_visible) {
-- 
2.30.9




[PATCH v3 29/33] target/ppc: Remove id_tlbs flag from CPU env

2024-05-07 Thread BALATON Zoltan
This flag for split instruction/data TLBs is only set for 6xx soft TLB
MMU model and not used otherwise so no need to have a separate flag
for that.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 hw/ppc/pegasos2.c|  2 +-
 target/ppc/cpu.h |  1 -
 target/ppc/cpu_init.c| 19 +--
 target/ppc/helper_regs.c |  1 -
 target/ppc/mmu_common.c  | 10 ++
 target/ppc/mmu_helper.c  | 12 ++--
 6 files changed, 10 insertions(+), 35 deletions(-)

diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 04d6decb2b..dfc6fab180 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -984,7 +984,7 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
   cpu->env.icache_line_size);
 qemu_fdt_setprop_cell(fdt, cp, "i-cache-line-size",
   cpu->env.icache_line_size);
-if (cpu->env.id_tlbs) {
+if (cpu->env.tlb_type == TLB_6XX) {
 qemu_fdt_setprop_cell(fdt, cp, "i-tlb-sets", cpu->env.nb_ways);
 qemu_fdt_setprop_cell(fdt, cp, "i-tlb-size", cpu->env.tlb_per_way);
 qemu_fdt_setprop_cell(fdt, cp, "d-tlb-sets", cpu->env.nb_ways);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 0ac55d6b25..21e12a4f0d 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1260,7 +1260,6 @@ struct CPUArchState {
 int tlb_per_way; /* Speed-up helper: used to avoid divisions at run time */
 int nb_ways; /* Number of ways in the TLB set */
 int last_way;/* Last used way used to allocate TLB in a LRU way */
-int id_tlbs; /* If 1, MMU has separated TLBs for instructions & data */
 int nb_pids; /* Number of available PID registers */
 int tlb_type;/* Type of TLB we're dealing with */
 ppc_tlb_t tlb;   /* TLB is optional. Allocate them only if needed */
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index c11a69fd90..07ad788e54 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -2117,7 +2117,6 @@ static void init_proc_405(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_4xx(env);
@@ -2190,7 +2189,6 @@ static void init_proc_440EP(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2288,7 +2286,6 @@ static void init_proc_440GP(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2362,7 +2359,6 @@ static void init_proc_440x5(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2724,7 +2720,6 @@ static void init_proc_e200(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_e200(env, 0xUL);
@@ -2843,7 +2838,6 @@ static void init_proc_e500(CPUPPCState *env, int version)
 /* Memory management */
 env->nb_pids = 3;
 env->nb_ways = 2;
-env->id_tlbs = 0;
 switch (version) {
 case fsl_e500v1:
 tlbncfg[0] = register_tlbncfg(2, 1, 1, 0, 256);
@@ -6800,20 +6794,17 @@ static void init_ppc_proc(PowerPCCPU *cpu)
 }
 /* Allocate TLBs buffer when needed */
 #if !defined(CONFIG_USER_ONLY)
-if (env->nb_tlb != 0) {
-int nb_tlb = env->nb_tlb;
-if (env->id_tlbs != 0) {
-nb_tlb *= 2;
-}
+if (env->nb_tlb) {
 switch (env->tlb_type) {
 case TLB_6XX:
-env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, nb_tlb);
+/* 6xx has separate TLBs for instructions and data hence times 2 */
+env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, 2 * env->nb_tlb);
 break;
 case TLB_EMB:
-env->tlb.tlbe = g_new0(ppcemb_tlb_t, nb_tlb);
+env->tlb.tlbe = g_new0(ppcemb_tlb_t, env->nb_tlb);
 break;
 case TLB_MAS:
-env->tlb.tlbm = g_new0(ppcmas_tlb_t, nb_tlb);
+env->tlb.tlbm = g_new0(ppcmas_tlb_t, env->nb_tlb);
 break;
 }
 /* Pre-compute some useful values */
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 25258986e3..ed583fe9b3 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -693,7 +693,6 @@ void register_6xx_7xx_soft_tlb(CPUPPCState *env, int 
nb_tlbs, int nb_ways)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = nb_tlbs;
 env->nb_ways = nb_ways;
-env->id_tlbs = 1;
  

[PATCH v3 25/33] target/ppc/mmu_common.c: Remove BookE handling from get_physical_address_wtlb()

2024-05-07 Thread BALATON Zoltan
This function is no longer called for BookE MMU model so remove parts
related to it. This has uncovered a few may be used uninitialised
warnings that are also fixed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 25 +
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 83dc041a77..788e2bebd5 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -629,12 +629,10 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 break;
 }
 }
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU,
   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
@@ -841,9 +839,6 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 goto found_tlb;
 }
 }
@@ -851,6 +846,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 
 found_tlb:
 
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
   HWADDR_FMT_plx " %d %d\n", __func__,
   ret < 0 ? "refused" : "granted", address, raddr,
@@ -1107,20 +1103,9 @@ static int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-bool real_mode;
-
-if (env->mmu_model == POWERPC_MMU_BOOKE) {
-return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
-} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
-return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-mmu_idx);
-}
-
-real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
-  : !FIELD_EX64(env->msr, MSR, DR);
-if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
-  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
-  env->mmu_model == POWERPC_MMU_REAL)) {
+bool real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode) {
 memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_RWX;
-- 
2.30.9




[PATCH v3 13/33] target/ppc/mmu_common.c: Split out BookE cases before checking real mode

2024-05-07 Thread BALATON Zoltan
BookE does not have real mode so split off and handle it first in
get_physical_address_wtlb() before checking for real mode for other
MMU models.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 2b6252f3f9..5a0df60ebc 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1178,6 +1178,13 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 int ret = -1;
 bool real_mode;
 
+if (env->mmu_model == POWERPC_MMU_BOOKE) {
+return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
+} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
+mmu_idx);
+}
+
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
   : !FIELD_EX64(env->msr, MSR, DR);
 
@@ -1198,13 +1205,6 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
 }
 break;
-case POWERPC_MMU_BOOKE:
-ret = mmubooke_get_physical_address(env, ctx, eaddr, access_type);
-break;
-case POWERPC_MMU_BOOKE206:
-ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-   mmu_idx);
-break;
 case POWERPC_MMU_REAL:
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
-- 
2.30.9




[PATCH v3 33/33] target/ppc: Add a macro to check for page protection bit

2024-05-07 Thread BALATON Zoltan
Checking if a page protection bit is set for a given access type is a
common operation. Add a macro to avoid repeating the same check at
multiple places and also avoid a function call. As this relies on
access type and page protection bit values having certain relation
also add an assert to ensure that this assumption holds.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/cpu_init.c|  4 
 target/ppc/internal.h| 20 ++--
 target/ppc/mmu-hash32.c  |  6 +++---
 target/ppc/mmu-hash64.c  |  2 +-
 target/ppc/mmu-radix64.c |  2 +-
 target/ppc/mmu_common.c  | 26 +-
 6 files changed, 24 insertions(+), 36 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 92c71b2a09..6639235544 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7377,6 +7377,10 @@ static void ppc_cpu_class_init(ObjectClass *oc, void 
*data)
 resettable_class_set_parent_phases(rc, NULL, ppc_cpu_reset_hold, NULL,
>parent_phases);
 
+/* CHECK_PROT_ACCESS relies on this MMU access and PAGE bits relation */
+assert(MMU_DATA_LOAD == 0 && MMU_DATA_STORE == 1 && MMU_INST_FETCH == 2 &&
+   PAGE_READ == 1 && PAGE_WRITE == 2 && PAGE_EXEC == 4);
+
 cc->class_by_name = ppc_cpu_class_by_name;
 cc->has_work = ppc_cpu_has_work;
 cc->mmu_index = ppc_cpu_mmu_index;
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 46176c4711..9880422ce3 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -234,24 +234,8 @@ void destroy_ppc_opcodes(PowerPCCPU *cpu);
 void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
 const gchar *ppc_gdb_arch_name(CPUState *cs);
 
-/**
- * prot_for_access_type:
- * @access_type: Access type
- *
- * Return the protection bit required for the given access type.
- */
-static inline int prot_for_access_type(MMUAccessType access_type)
-{
-switch (access_type) {
-case MMU_INST_FETCH:
-return PAGE_EXEC;
-case MMU_DATA_LOAD:
-return PAGE_READ;
-case MMU_DATA_STORE:
-return PAGE_WRITE;
-}
-g_assert_not_reached();
-}
+/* Check if permission bit required for the access_type is set in prot */
+#define CHECK_PROT_ACCESS(prot, access_type) ((prot) & (1 << (access_type)))
 
 #ifndef CONFIG_USER_ONLY
 
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index b5d7aeed4e..fa4a4ced6d 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -213,7 +213,7 @@ static bool ppc_hash32_direct_store(PowerPCCPU *cpu, 
target_ulong sr,
 }
 
 *prot = key ? PAGE_READ | PAGE_WRITE : PAGE_READ;
-if (*prot & prot_for_access_type(access_type)) {
+if (CHECK_PROT_ACCESS(*prot, access_type)) {
 *raddr = eaddr;
 return true;
 }
@@ -364,7 +364,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 if (env->nb_BATs != 0) {
 raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx);
 if (raddr != -1) {
-if (prot_for_access_type(access_type) & ~*protp) {
+if (!CHECK_PROT_ACCESS(*protp, access_type)) {
 if (guest_visible) {
 if (access_type == MMU_INST_FETCH) {
 cs->exception_index = POWERPC_EXCP_ISI;
@@ -432,7 +432,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 
 prot = ppc_hash32_pte_prot(mmu_idx, sr, pte);
 
-if (prot_for_access_type(access_type) & ~prot) {
+if (!CHECK_PROT_ACCESS(prot, access_type)) {
 /* Access right violation */
 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
 if (guest_visible) {
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 5a0d80feda..14c2116ae7 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -1097,7 +1097,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, 
MMUAccessType access_type,
 amr_prot = ppc_hash64_amr_prot(cpu, pte);
 prot = exec_prot & pp_prot & amr_prot;
 
-need_prot = prot_for_access_type(access_type);
+need_prot = CHECK_PROT_ACCESS(PAGE_RWX, access_type);
 if (need_prot & ~prot) {
 /* Access right violation */
 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 395ce3b782..a72cd927c4 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -209,7 +209,7 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, 
MMUAccessType access_type,
 }
 
 /* Check if requested access type is allowed */
-if (prot_for_access_type(access_type) & ~*prot) {
+if (!CHECK_PROT_ACCESS(*prot, access_type)) {
 /* Page Protected for that Access */
 *fault_cause |= access_type == MMU_INST_FETCH ? SRR1_NOEXEC_GUARD :

[PATCH v3 17/33] target/ppc/mmu_common.c: Simplify mmubooke206_get_physical_address()

2024-05-07 Thread BALATON Zoltan
This function is similar to mmubooke_get_physical_address() and can be
simplified the same way.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 26 +-
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 9793e6d282..a5bc747f40 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -859,15 +859,11 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 int mmu_idx)
 {
 ppcmas_tlb_t *tlb;
-hwaddr raddr;
-int i, j, ret;
-
-ret = -1;
-raddr = (hwaddr)-1ULL;
+hwaddr raddr = (hwaddr)-1ULL;
+int i, j, ret = -1;
 
 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
 int ways = booke206_tlb_ways(env, i);
-
 for (j = 0; j < ways; j++) {
 tlb = booke206_get_tlbm(env, i, address, j);
 if (!tlb) {
@@ -876,6 +872,9 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
+if (ret >= 0) {
+ctx->raddr = raddr;
+}
 goto found_tlb;
 }
 }
@@ -883,17 +882,10 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 
 found_tlb:
 
-if (ret >= 0) {
-ctx->raddr = raddr;
- qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
-   ctx->raddr, ctx->prot, ret);
-} else {
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
-   raddr, ctx->prot, ret);
-}
-
+qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
+  HWADDR_FMT_plx " %d %d\n", __func__,
+  ret < 0 ? "refused" : "granted", address, raddr,
+  ctx->prot, ret);
 return ret;
 }
 
-- 
2.30.9




[PATCH v3 10/33] target/ppc/mmu_common.c: Move else branch to avoid large if block

2024-05-07 Thread BALATON Zoltan
In mmu6xx_get_physical_address() we have a large if block with a two
line else branch that effectively returns. Invert the condition and
move the else there to allow deindenting the large if block to make
the flow easier to follow.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 71 -
 1 file changed, 34 insertions(+), 37 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 181273579b..9d337a73ba 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -405,47 +405,44 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = -1;
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
-if (type != ACCESS_CODE || ctx->nx == 0) {
-/* Page address translation */
-qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx
-" htab_mask " HWADDR_FMT_plx
-" hash " HWADDR_FMT_plx "\n",
-ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
-ctx->hash[0] = hash;
-ctx->hash[1] = ~hash;
-
-/* Initialize real address with an invalid value */
-ctx->raddr = (hwaddr)-1ULL;
-/* Software TLB search */
-ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
+if (type == ACCESS_CODE && ctx->nx) {
+qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
+return -3;
+}
+/* Page address translation */
+qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
+  HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
+  ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), 
hash);
+ctx->hash[0] = hash;
+ctx->hash[1] = ~hash;
+
+/* Initialize real address with an invalid value */
+ctx->raddr = (hwaddr)-1ULL;
+/* Software TLB search */
+ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
 #if defined(DUMP_PAGE_TABLES)
-if (qemu_loglevel_mask(CPU_LOG_MMU)) {
-CPUState *cs = env_cpu(env);
-hwaddr curaddr;
-uint32_t a0, a1, a2, a3;
-
-qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx
- "\n", ppc_hash32_hpt_base(cpu),
- ppc_hash32_hpt_mask(cpu) + 0x80);
-for (curaddr = ppc_hash32_hpt_base(cpu);
- curaddr < (ppc_hash32_hpt_base(cpu)
-+ ppc_hash32_hpt_mask(cpu) + 0x80);
- curaddr += 16) {
-a0 = ldl_phys(cs->as, curaddr);
-a1 = ldl_phys(cs->as, curaddr + 4);
-a2 = ldl_phys(cs->as, curaddr + 8);
-a3 = ldl_phys(cs->as, curaddr + 12);
-if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
-qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
- curaddr, a0, a1, a2, a3);
-}
+if (qemu_loglevel_mask(CPU_LOG_MMU)) {
+CPUState *cs = env_cpu(env);
+hwaddr curaddr;
+uint32_t a0, a1, a2, a3;
+
+qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
+ ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu) + 
0x80);
+for (curaddr = ppc_hash32_hpt_base(cpu);
+ curaddr < (ppc_hash32_hpt_base(cpu)
++ ppc_hash32_hpt_mask(cpu) + 0x80);
+ curaddr += 16) {
+a0 = ldl_phys(cs->as, curaddr);
+a1 = ldl_phys(cs->as, curaddr + 4);
+a2 = ldl_phys(cs->as, curaddr + 8);
+a3 = ldl_phys(cs->as, curaddr + 12);
+if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
+qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
+ curaddr, a0, a1, a2, a3);
 }
 }
-#endif
-} else {
-qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
-ret = -3;
 }
+#endif
 } else {
 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
 /* Direct-store segment : absolutely *BUGGY* for now */
-- 
2.30.9




[PATCH v3 30/33] target/ppc: Split off common embedded TLB init

2024-05-07 Thread BALATON Zoltan
Several 4xx CPUs and e200 share the same TLB settings enclosed in an
ifdef. Split it off in a common function to reduce code duplication
and the number of ifdefs.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/cpu_init.c | 46 ---
 1 file changed, 17 insertions(+), 29 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 07ad788e54..92c71b2a09 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -2107,18 +2107,22 @@ static int check_pow_hid0_74xx(CPUPPCState *env)
 return 0;
 }
 
+static void init_tlbs_emb(CPUPPCState *env)
+{
+#ifndef CONFIG_USER_ONLY
+env->nb_tlb = 64;
+env->nb_ways = 1;
+env->tlb_type = TLB_EMB;
+#endif
+}
+
 static void init_proc_405(CPUPPCState *env)
 {
 register_40x_sprs(env);
 register_405_sprs(env);
 register_usprgh_sprs(env);
 
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+init_tlbs_emb(env);
 init_excp_4xx(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2185,12 +2189,8 @@ static void init_proc_440EP(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_emb(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2282,12 +2282,7 @@ static void init_proc_440GP(CPUPPCState *env)
 register_440_sprs(env);
 register_usprgh_sprs(env);
 
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+init_tlbs_emb(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2355,12 +2350,8 @@ static void init_proc_440x5(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_emb(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2717,11 +2708,8 @@ static void init_proc_e200(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_emb(env);
 init_excp_e200(env, 0xUL);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
-- 
2.30.9




[PATCH v3 27/33] target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 2

2024-05-07 Thread BALATON Zoltan
Merge the code fetch and data access cases in a common switch.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 50 +
 1 file changed, 20 insertions(+), 30 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index c725a7932f..04e5ad661d 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1206,45 +1206,35 @@ static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 
 log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
 env->error_code = 0;
-if (ret == -1) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
 if (env->mmu_model == POWERPC_MMU_BOOKE206) {
 booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
 }
-}
-if (access_type == MMU_INST_FETCH) {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-cs->exception_index = POWERPC_EXCP_ITLB;
+cs->exception_index = (access_type == MMU_INST_FETCH) ?
+  POWERPC_EXCP_ITLB : POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = (access_type == MMU_INST_FETCH) ?
+  POWERPC_EXCP_ISI : POWERPC_EXCP_DSI;
+if (access_type != MMU_INST_FETCH) {
 env->spr[SPR_BOOKE_DEAR] = eaddr;
 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
-break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-break;
-case -3:
-/* No execute protection violation */
+}
+break;
+case -3:
+/* No execute protection violation */
+if (access_type == MMU_INST_FETCH) {
 cs->exception_index = POWERPC_EXCP_ISI;
 env->spr[SPR_BOOKE_ESR] = 0;
-break;
-}
-} else {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-cs->exception_index = POWERPC_EXCP_DTLB;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
-break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_DSI;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
-break;
 }
+break;
 }
+
 return false;
 }
 
-- 
2.30.9




[PATCH v3 12/33] target/ppc/mmu_common.c: Eliminate ret from mmu6xx_get_physical_address()

2024-05-07 Thread BALATON Zoltan
Return directly, which is simpler than dragging a return value through
multpile if and else blocks.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 84 +++--
 1 file changed, 39 insertions(+), 45 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b2f2cee1a8..2b6252f3f9 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -389,7 +389,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 target_ulong vsid, sr, pgidx;
 int ds, target_page_bits;
 bool pr;
-int ret;
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
@@ -422,7 +421,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 qemu_log_mask(CPU_LOG_MMU,
 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
 ctx->key, ds, ctx->nx, vsid);
-ret = -1;
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
 if (type == ACCESS_CODE && ctx->nx) {
@@ -439,51 +437,47 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 /* Initialize real address with an invalid value */
 ctx->raddr = (hwaddr)-1ULL;
 /* Software TLB search */
-ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
-} else {
-qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
-/* Direct-store segment : absolutely *BUGGY* for now */
-
-switch (type) {
-case ACCESS_INT:
-/* Integer load/store : only access allowed */
-break;
-case ACCESS_CODE:
-/* No code fetch is allowed in direct-store areas */
-return -4;
-case ACCESS_FLOAT:
-/* Floating point load/store */
-return -4;
-case ACCESS_RES:
-/* lwarx, ldarx or srwcx. */
-return -4;
-case ACCESS_CACHE:
-/*
- * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
- *
- * Should make the instruction do no-op.  As it already do
- * no-op, it's quite easy :-)
- */
-ctx->raddr = eaddr;
-return 0;
-case ACCESS_EXT:
-/* eciwx or ecowx */
-return -4;
-default:
-qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
-  "address translation\n");
-return -4;
-}
-if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
-(access_type == MMU_DATA_LOAD || ctx->key != 0)) {
-ctx->raddr = eaddr;
-ret = 2;
-} else {
-ret = -2;
-}
+return ppc6xx_tlb_check(env, ctx, eaddr, access_type);
 }
 
-return ret;
+/* Direct-store segment : absolutely *BUGGY* for now */
+qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
+switch (type) {
+case ACCESS_INT:
+/* Integer load/store : only access allowed */
+break;
+case ACCESS_CODE:
+/* No code fetch is allowed in direct-store areas */
+return -4;
+case ACCESS_FLOAT:
+/* Floating point load/store */
+return -4;
+case ACCESS_RES:
+/* lwarx, ldarx or srwcx. */
+return -4;
+case ACCESS_CACHE:
+/*
+ * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
+ *
+ * Should make the instruction do no-op.  As it already do
+ * no-op, it's quite easy :-)
+ */
+ctx->raddr = eaddr;
+return 0;
+case ACCESS_EXT:
+/* eciwx or ecowx */
+return -4;
+default:
+qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need address"
+   " translation\n");
+return -4;
+}
+if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
+(access_type == MMU_DATA_LOAD || ctx->key != 0)) {
+ctx->raddr = eaddr;
+return 2;
+}
+return -2;
 }
 
 /* Generic TLB check function for embedded PowerPC implementations */
-- 
2.30.9




[PATCH v3 21/33] target/ppc/mmu_common.c: Make get_physical_address_wtlb() static

2024-05-07 Thread BALATON Zoltan
This function is not used from any other files so make it static and
fix the maybe used uninitialised warnings this has uncovered. Also
remove mmu_ctx_t definition from internal.h as this type is only used
within this file.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 17 +
 target/ppc/mmu_common.c | 18 +++---
 2 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 98b41a970c..4a90dd2584 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -257,28 +257,13 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 
 /* PowerPC MMU emulation */
 
-typedef struct mmu_ctx_t mmu_ctx_t;
-
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
- target_ulong eaddr,
- MMUAccessType access_type, int type,
- int mmu_idx);
+
 /* Software driven TLB helpers */
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
-/* Context used internally during MMU translations */
-struct mmu_ctx_t {
-hwaddr raddr;  /* Real address  */
-hwaddr eaddr;  /* Effective address */
-int prot;  /* Protection bits   */
-hwaddr hash[2];/* Pagetable hash values */
-target_ulong ptem; /* Virtual segment ID | API  */
-int key;   /* Access key*/
-int nx;/* Non-execute area  */
-};
 
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 63b5fb98d1..d92c9607b8 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -36,6 +36,17 @@
 
 /* #define DUMP_PAGE_TABLES */
 
+/* Context used internally during MMU translations */
+typedef struct {
+hwaddr raddr;  /* Real address */
+hwaddr eaddr;  /* Effective address*/
+int prot;  /* Protection bits  */
+hwaddr hash[2];/* Pagetable hash values*/
+target_ulong ptem; /* Virtual segment ID | API */
+int key;   /* Access key   */
+int nx;/* Non-execute area */
+} mmu_ctx_t;
+
 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 {
 PowerPCCPU *cpu = env_archcpu(env);
@@ -667,7 +678,7 @@ static int mmubooke_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 qemu_log_mask(CPU_LOG_MMU,
   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
-  address, raddr, ctx->prot, ret);
+  address, raddr, ret == -1 ? 0 : ctx->prot, ret);
 return ret;
 }
 
@@ -883,7 +894,7 @@ found_tlb:
 qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
   HWADDR_FMT_plx " %d %d\n", __func__,
   ret < 0 ? "refused" : "granted", address, raddr,
-  ctx->prot, ret);
+  ret == -1 ? 0 : ctx->prot, ret);
 return ret;
 }
 
@@ -1131,7 +1142,7 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
+static int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
  int mmu_idx)
@@ -1150,6 +1161,7 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
   env->mmu_model == POWERPC_MMU_SOFT_4xx ||
   env->mmu_model == POWERPC_MMU_REAL)) {
+memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_RWX;
 return 0;
-- 
2.30.9




[PATCH v3 23/33] target/ppc/mmu_common.c: Remove BookE from direct store handling

2024-05-07 Thread BALATON Zoltan
As BookE never returns -4 we can drop BookE from the direct store case
in ppc_jumbo_xlate().

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 87cac12d68..03b834eb77 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1287,12 +1287,7 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 /* Direct store exception */
 /* No code fetch is allowed in direct-store areas */
 cs->exception_index = POWERPC_EXCP_ISI;
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->error_code = 0;
-} else {
-env->error_code = 0x1000;
-}
+env->error_code = 0x1000;
 break;
 }
 } else {
-- 
2.30.9




[PATCH v3 16/33] target/ppc/mmu_common.c: Simplify mmubooke_get_physical_address()

2024-05-07 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 25 +
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 7283eafe27..9793e6d282 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -652,31 +652,24 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
  MMUAccessType access_type)
 {
 ppcemb_tlb_t *tlb;
-hwaddr raddr;
-int i, ret;
+hwaddr raddr = (hwaddr)-1ULL;
+int i, ret = -1;
 
-ret = -1;
-raddr = (hwaddr)-1ULL;
 for (i = 0; i < env->nb_tlb; i++) {
 tlb = >tlb.tlbe[i];
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
+if (ret >= 0) {
+ctx->raddr = raddr;
+}
 break;
 }
 }
-
-if (ret >= 0) {
-ctx->raddr = raddr;
-qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-  " => " HWADDR_FMT_plx " %d %d\n", __func__,
-  address, ctx->raddr, ctx->prot, ret);
-} else {
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__,
-   address, raddr, ctx->prot, ret);
-}
-
+qemu_log_mask(CPU_LOG_MMU,
+  "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
+  " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
+  address, raddr, ctx->prot, ret);
 return ret;
 }
 
-- 
2.30.9




[PATCH v3 15/33] target/ppc/mmu_common.c: Inline and remove check_physical()

2024-05-07 Thread BALATON Zoltan
This function just does two assignments and and unnecessary check that
is always true so inline it in the only caller left and remove it.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 26 +++---
 1 file changed, 3 insertions(+), 23 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index e03a433f02..7283eafe27 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1148,28 +1148,6 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-static int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
-  MMUAccessType access_type)
-{
-ctx->raddr = eaddr;
-ctx->prot = PAGE_READ | PAGE_EXEC;
-
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-case POWERPC_MMU_SOFT_4xx:
-case POWERPC_MMU_REAL:
-case POWERPC_MMU_BOOKE:
-ctx->prot |= PAGE_WRITE;
-break;
-
-default:
-/* Caller's checks mean we should never get here for other models */
-g_assert_not_reached();
-}
-
-return 0;
-}
-
 int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
@@ -1189,7 +1167,9 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
   env->mmu_model == POWERPC_MMU_SOFT_4xx ||
   env->mmu_model == POWERPC_MMU_REAL)) {
-return check_physical(env, ctx, eaddr, access_type);
+ctx->raddr = eaddr;
+ctx->prot = PAGE_RWX;
+return 0;
 }
 
 switch (env->mmu_model) {
-- 
2.30.9




[PATCH v3 06/33] target/ppc/mmu_common.c: Remove unneeded local variable

2024-05-07 Thread BALATON Zoltan
In mmubooke_check_tlb() and mmubooke206_check_tlb() we can assign the
value directly the the destination, no need to have a separate local
variable for it.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 30 +-
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index f79e390306..09cbeb0052 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -628,8 +628,6 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
   hwaddr *raddr, int *prot, target_ulong address,
   MMUAccessType access_type, int i)
 {
-int prot2;
-
 if (!mmubooke_check_pid(env, tlb, raddr, address, i)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__);
 return -1;
@@ -644,17 +642,16 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 }
 
 if (FIELD_EX64(env->msr, MSR, PR)) {
-prot2 = tlb->prot & 0xF;
+*prot = tlb->prot & 0xF;
 } else {
-prot2 = (tlb->prot >> 4) & 0xF;
+*prot = (tlb->prot >> 4) & 0xF;
 }
-*prot = prot2;
-if (prot2 & prot_for_access_type(access_type)) {
+if (*prot & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
 return 0;
 }
 
-qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2);
+qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, *prot);
 return access_type == MMU_INST_FETCH ? -3 : -2;
 }
 
@@ -795,7 +792,6 @@ static int mmubooke206_check_tlb(CPUPPCState *env, 
ppcmas_tlb_t *tlb,
  target_ulong address,
  MMUAccessType access_type, int mmu_idx)
 {
-int prot2 = 0;
 uint32_t epid;
 bool as, pr;
 bool use_epid = mmubooke206_get_as(env, mmu_idx, , , );
@@ -841,34 +837,34 @@ found_tlb:
 return -1;
 }
 
+*prot = 0;
 if (pr) {
 if (tlb->mas7_3 & MAS3_UR) {
-prot2 |= PAGE_READ;
+*prot |= PAGE_READ;
 }
 if (tlb->mas7_3 & MAS3_UW) {
-prot2 |= PAGE_WRITE;
+*prot |= PAGE_WRITE;
 }
 if (tlb->mas7_3 & MAS3_UX) {
-prot2 |= PAGE_EXEC;
+*prot |= PAGE_EXEC;
 }
 } else {
 if (tlb->mas7_3 & MAS3_SR) {
-prot2 |= PAGE_READ;
+*prot |= PAGE_READ;
 }
 if (tlb->mas7_3 & MAS3_SW) {
-prot2 |= PAGE_WRITE;
+*prot |= PAGE_WRITE;
 }
 if (tlb->mas7_3 & MAS3_SX) {
-prot2 |= PAGE_EXEC;
+*prot |= PAGE_EXEC;
 }
 }
-*prot = prot2;
-if (prot2 & prot_for_access_type(access_type)) {
+if (*prot & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
 return 0;
 }
 
-qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2);
+qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, *prot);
 return access_type == MMU_INST_FETCH ? -3 : -2;
 }
 
-- 
2.30.9




[PATCH v3 19/33] target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()

2024-05-07 Thread BALATON Zoltan
Instead of putting a large block of code in an if, invert the
condition and return early to be able to deindent the code block.

Signed-off-by: BALATON Zoltan 
Acked-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 319 
 1 file changed, 159 insertions(+), 160 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 3f584f2655..b1b2d64b90 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1252,187 +1252,186 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 *protp = ctx.prot;
 *psizep = TARGET_PAGE_BITS;
 return true;
+} else if (!guest_visible) {
+return false;
 }
 
-if (guest_visible) {
-log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
-if (type == ACCESS_CODE) {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-cs->exception_index = POWERPC_EXCP_IFTLB;
-env->error_code = 1 << 18;
-env->spr[SPR_IMISS] = eaddr;
-env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
-goto tlb_miss;
-case POWERPC_MMU_SOFT_4xx:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_40x_DEAR] = eaddr;
-env->spr[SPR_40x_ESR] = 0x;
-break;
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
-break;
-case POWERPC_MMU_REAL:
-cpu_abort(cs, "PowerPC in real mode should never raise "
-  "any MMU exceptions\n");
-default:
-cpu_abort(cs, "Unknown or invalid MMU model\n");
-}
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (type == ACCESS_CODE) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_SOFT_6xx:
+cs->exception_index = POWERPC_EXCP_IFTLB;
+env->error_code = 1 << 18;
+env->spr[SPR_IMISS] = eaddr;
+env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
+goto tlb_miss;
+case POWERPC_MMU_SOFT_4xx:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_40x_DEAR] = eaddr;
+env->spr[SPR_40x_ESR] = 0x;
 break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->error_code = 0;
-} else {
-env->error_code = 0x0800;
-}
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
 break;
-case -3:
-/* No execute protection violation */
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->spr[SPR_BOOKE_ESR] = 0x;
-env->error_code = 0;
+case POWERPC_MMU_REAL:
+cpu_abort(cs, "PowerPC in real mode should never raise "
+  "any MMU exceptions\n");
+default:
+cpu_abort(cs, "Unknown or invalid MMU model\n");
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
+(env->mmu_model == POWERPC_MMU_BOOKE206)) {
+env->error_code = 0;
+} e

[PATCH v3 18/33] target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls

2024-05-07 Thread BALATON Zoltan
Fix several qemu_log_mask() calls that are misindented.

Signed-off-by: BALATON Zoltan 
Acked-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 42 -
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index a5bc747f40..3f584f2655 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -318,8 +318,8 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 int ret = -1;
 bool ifetch = access_type == MMU_INST_FETCH;
 
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
- ifetch ? 'I' : 'D', virtual);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
+  ifetch ? 'I' : 'D', virtual);
 if (ifetch) {
 BATlt = env->IBAT[1];
 BATut = env->IBAT[0];
@@ -333,9 +333,9 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
 BEPIu = *BATu & 0xF000;
 BEPIl = *BATu & 0x0FFE;
 bat_size_prot(env, , , , BATu, BATl);
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
-   TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
-   ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
+  TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
+  ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
 if ((virtual & 0xF000) == BEPIu &&
 ((virtual & 0x0FFE) & ~bl) == BEPIl) {
 /* BAT matches */
@@ -367,12 +367,11 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 BEPIu = *BATu & 0xF000;
 BEPIl = *BATu & 0x0FFE;
 bl = (*BATu & 0x1FFC) << 15;
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v "
-   TARGET_FMT_lx " BATu " TARGET_FMT_lx
-   " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
-   TARGET_FMT_lx " " TARGET_FMT_lx "\n",
-   __func__, ifetch ? 'I' : 'D', i, virtual,
-   *BATu, *BATl, BEPIu, BEPIl, bl);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
+  " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
+  "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
+  TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
+  i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl);
 }
 }
 }
@@ -418,9 +417,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 hash = vsid ^ pgidx;
 ctx->ptem = (vsid << 7) | (pgidx >> 10);
 
-qemu_log_mask(CPU_LOG_MMU,
-"pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
-ctx->key, ds, ctx->nx, vsid);
+qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
+  TARGET_FMT_lx "\n", ctx->key, ds, ctx->nx, vsid);
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
 if (type == ACCESS_CODE && ctx->nx) {
@@ -586,9 +584,9 @@ static int mmu40x_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 return 0;
 }
 }
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx
-   " %d %d\n", __func__, address, raddr, ctx->prot, ret);
+qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
+  " => " HWADDR_FMT_plx " %d %d\n",
+  __func__, address, raddr, ctx->prot, ret);
 
 return ret;
 }
@@ -700,11 +698,11 @@ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, 
hwaddr *raddrp,
 }
 
 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
- qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
-   " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
-   HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
-   __func__, address, pid, tlb->mas1, tlb->mas2, mask,
-   tlb->mas7_3, tlb->mas8);
+qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
+  " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
+  HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
+  __func__, address, pid, tlb->mas1, tlb->mas2, mask,
+  tlb->mas7_3, tlb->mas8);
 
 /* Check PID */
 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
-- 
2.30.9




[PATCH v3 09/33] target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()

2024-05-07 Thread BALATON Zoltan
Repurpose get_segment_6xx_tlb() to do the whole address translation
for POWERPC_MMU_SOFT_6xx MMU model by moving the BAT check there and
renaming it to match other similar functions. These are only called
once together so no need to keep these separate functions and
combining them simplifies the caller allowing further restructuring.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 26 --
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index aa137123a4..181273579b 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -360,19 +360,23 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 return ret;
 }
 
-/* Perform segment based translation */
-static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong eaddr, MMUAccessType access_type,
-   int type)
+static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+   target_ulong eaddr,
+   MMUAccessType access_type, int type)
 {
 PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
-target_ulong vsid;
+target_ulong vsid, sr, pgidx;
 int ds, target_page_bits;
 bool pr;
 int ret;
-target_ulong sr, pgidx;
 
+/* First try to find a BAT entry if there are any */
+if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
+return 0;
+}
+
+/* Perform segment based translation when no BATs matched */
 pr = FIELD_EX64(env->msr, MSR, PR);
 ctx->eaddr = eaddr;
 
@@ -1194,14 +1198,8 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
 } else {
-/* Try to find a BAT */
-if (env->nb_BATs != 0) {
-ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
-}
-if (ret < 0) {
-/* We didn't match any BAT entry or don't have BATs */
-ret = get_segment_6xx_tlb(env, ctx, eaddr, access_type, type);
-}
+ret = mmu6xx_get_physical_address(env, ctx, eaddr, access_type,
+  type);
 }
 break;
 
-- 
2.30.9




[PATCH v3 28/33] target/ppc/mmu_common.c: Move BookE MMU functions together

2024-05-07 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 226 
 1 file changed, 113 insertions(+), 113 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 04e5ad661d..a6e7b64049 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -854,6 +854,119 @@ found_tlb:
 return ret;
 }
 
+static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
+ MMUAccessType access_type, int 
mmu_idx)
+{
+uint32_t epid;
+bool as, pr;
+uint32_t missed_tid = 0;
+bool use_epid = mmubooke206_get_as(env, mmu_idx, , , );
+
+if (access_type == MMU_INST_FETCH) {
+as = FIELD_EX64(env->msr, MSR, IR);
+}
+env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
+env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
+env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
+env->spr[SPR_BOOKE_MAS3] = 0;
+env->spr[SPR_BOOKE_MAS6] = 0;
+env->spr[SPR_BOOKE_MAS7] = 0;
+
+/* AS */
+if (as) {
+env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
+env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
+}
+
+env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
+env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
+
+if (!use_epid) {
+switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
+case MAS4_TIDSELD_PID0:
+missed_tid = env->spr[SPR_BOOKE_PID];
+break;
+case MAS4_TIDSELD_PID1:
+missed_tid = env->spr[SPR_BOOKE_PID1];
+break;
+case MAS4_TIDSELD_PID2:
+missed_tid = env->spr[SPR_BOOKE_PID2];
+break;
+}
+env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
+} else {
+missed_tid = epid;
+env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
+}
+env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
+
+
+/* next victim logic */
+env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
+env->last_way++;
+env->last_way &= booke206_tlb_ways(env, 0) - 1;
+env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
+}
+
+static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
+MMUAccessType access_type,
+hwaddr *raddrp, int *psizep, int *protp,
+int mmu_idx, bool guest_visible)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+mmu_ctx_t ctx;
+int ret;
+
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+ret = mmubooke206_get_physical_address(env, , eaddr, access_type,
+   mmu_idx);
+} else {
+ret = mmubooke_get_physical_address(env, , eaddr, access_type);
+}
+if (ret == 0) {
+*raddrp = ctx.raddr;
+*protp = ctx.prot;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+env->error_code = 0;
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+}
+cs->exception_index = (access_type == MMU_INST_FETCH) ?
+  POWERPC_EXCP_ITLB : POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = (access_type == MMU_INST_FETCH) ?
+  POWERPC_EXCP_ISI : POWERPC_EXCP_DSI;
+if (access_type != MMU_INST_FETCH) {
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+}
+break;
+case -3:
+/* No execute protection violation */
+if (access_type == MMU_INST_FETCH) {
+cs->exception_index = POWERPC_EXCP_ISI;
+env->spr[SPR_BOOKE_ESR] = 0;
+}
+break;
+}
+
+return false;
+}
+
 static const char *book3e_tsize_to_str[32] = {
 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
@@ -1125,119 +1238,6 @@ static int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 }
 }
 
-static void booke206_update_mas_

[PATCH v3 14/33] target/ppc/mmu_common.c: Split off real mode cases in get_physical_address_wtlb()

2024-05-07 Thread BALATON Zoltan
The real mode handling is identical in the remaining switch cases.
Split off these common real mode cases into a separate conditional to
leave only the else branches in the switch that are different.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 34 +-
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 5a0df60ebc..e03a433f02 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1175,7 +1175,6 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-int ret = -1;
 bool real_mode;
 
 if (env->mmu_model == POWERPC_MMU_BOOKE) {
@@ -1187,38 +1186,23 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
+  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
+  env->mmu_model == POWERPC_MMU_REAL)) {
+return check_physical(env, ctx, eaddr, access_type);
+}
 
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-ret = mmu6xx_get_physical_address(env, ctx, eaddr, access_type,
-  type);
-}
-break;
-
+return mmu6xx_get_physical_address(env, ctx, eaddr, access_type, type);
 case POWERPC_MMU_SOFT_4xx:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
-}
-break;
+return mmu40x_get_physical_address(env, ctx, eaddr, access_type);
 case POWERPC_MMU_REAL:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-cpu_abort(env_cpu(env),
-  "PowerPC in real mode do not do any translation\n");
-}
-return -1;
+cpu_abort(env_cpu(env),
+  "PowerPC in real mode do not do any translation\n");
 default:
 cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
-return -1;
 }
-
-return ret;
 }
 
 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
-- 
2.30.9




[PATCH v3 22/33] target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot()

2024-05-07 Thread BALATON Zoltan
The ppc_hash32_pp_prot() function in mmu-hash32.c is the same as
pp_check() in mmu_common.c, merge these to remove duplicated code.
Define the common function in internal.h as static lnline otherwise
exporting the function from mmu-hash32.c would stop the compiler
inlining it which results in slightly lower performance.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 35 
 target/ppc/mmu-hash32.c | 45 -
 target/ppc/mmu_common.c | 44 ++--
 3 files changed, 37 insertions(+), 87 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 4a90dd2584..46176c4711 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -256,6 +256,41 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 #ifndef CONFIG_USER_ONLY
 
 /* PowerPC MMU emulation */
+static inline int ppc_hash32_pp_prot(int key, int pp, int nx)
+{
+int prot;
+
+if (key == 0) {
+switch (pp) {
+case 0x0:
+case 0x1:
+case 0x2:
+prot = PAGE_READ | PAGE_WRITE;
+break;
+case 0x3:
+prot = PAGE_READ;
+break;
+default:
+g_assert_not_reached();
+}
+} else {
+switch (pp) {
+case 0x0:
+prot = 0;
+break;
+case 0x1:
+case 0x3:
+prot = PAGE_READ;
+break;
+case 0x2:
+prot = PAGE_READ | PAGE_WRITE;
+break;
+default:
+g_assert_not_reached();
+}
+}
+return nx ? prot : prot | PAGE_EXEC;
+}
 
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 6dfedab11d..960751a50e 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -43,51 +43,6 @@ struct mmu_ctx_hash32 {
 int key;   /* Access key*/
 };
 
-static int ppc_hash32_pp_prot(int key, int pp, int nx)
-{
-int prot;
-
-if (key == 0) {
-switch (pp) {
-case 0x0:
-case 0x1:
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-case 0x3:
-prot = PAGE_READ;
-break;
-
-default:
-abort();
-}
-} else {
-switch (pp) {
-case 0x0:
-prot = 0;
-break;
-
-case 0x1:
-case 0x3:
-prot = PAGE_READ;
-break;
-
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-default:
-abort();
-}
-}
-if (nx == 0) {
-prot |= PAGE_EXEC;
-}
-
-return prot;
-}
-
 static int ppc_hash32_pte_prot(int mmu_idx,
target_ulong sr, ppc_hash_pte32_t pte)
 {
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index d92c9607b8..87cac12d68 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -76,44 +76,6 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 /*/
 /* PowerPC MMU emulation */
 
-static int pp_check(int key, int pp, int nx)
-{
-int access;
-
-/* Compute access rights */
-access = 0;
-if (key == 0) {
-switch (pp) {
-case 0x0:
-case 0x1:
-case 0x2:
-access |= PAGE_WRITE;
-/* fall through */
-case 0x3:
-access |= PAGE_READ;
-break;
-}
-} else {
-switch (pp) {
-case 0x0:
-access = 0;
-break;
-case 0x1:
-case 0x3:
-access = PAGE_READ;
-break;
-case 0x2:
-access = PAGE_READ | PAGE_WRITE;
-break;
-}
-}
-if (nx == 0) {
-access |= PAGE_EXEC;
-}
-
-return access;
-}
-
 static int check_prot(int prot, MMUAccessType access_type)
 {
 return prot & prot_for_access_type(access_type) ? 0 : -2;
@@ -141,7 +103,7 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 MMUAccessType access_type)
 {
 target_ulong ptem, mmask;
-int access, ret, pteh, ptev, pp;
+int ret, pteh, ptev, pp;
 
 ret = -1;
 /* Check validity and table match */
@@ -160,11 +122,9 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 return -3;
 }
 }
-/* Compute access rights */
-access = pp_check(ctx->key, pp, ctx->nx);
 /* Keep the matching PTE information */
 ctx->raddr = pte1;
-ctx->prot = access;
+ctx->prot = ppc_hash32_pp_prot(ctx->key, pp, ctx-

[PATCH v3 32/33] target/ppc/mmu-radix64.c: Drop a local variable

2024-05-07 Thread BALATON Zoltan
The value is only used once so no need to introduce a local variable
for it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu-radix64.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 8daf71d2db..395ce3b782 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -185,7 +185,6 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, 
MMUAccessType access_type,
int mmu_idx, bool partition_scoped)
 {
 CPUPPCState *env = >env;
-int need_prot;
 
 /* Check Page Attributes (pte58:59) */
 if ((pte & R_PTE_ATT) == R_PTE_ATT_NI_IO && access_type == MMU_INST_FETCH) 
{
@@ -210,8 +209,8 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, 
MMUAccessType access_type,
 }
 
 /* Check if requested access type is allowed */
-need_prot = prot_for_access_type(access_type);
-if (need_prot & ~*prot) { /* Page Protected for that Access */
+if (prot_for_access_type(access_type) & ~*prot) {
+/* Page Protected for that Access */
 *fault_cause |= access_type == MMU_INST_FETCH ? SRR1_NOEXEC_GUARD :
 DSISR_PROTFAULT;
 return true;
-- 
2.30.9




[PATCH v3 20/33] target/ppc/mmu_common.c: Replace hard coded constants in ppc_jumbo_xlate()

2024-05-07 Thread BALATON Zoltan
The "2" in booke206_update_mas_tlb_miss() call corresponds to
MMU_INST_FETCH which is the value of access_type in this branch;
mmubooke206_esr() only checks for MMU_DATA_STORE and it's called from
code access so using MMU_DATA_LOAD here seems wrong so replace it with
access_type here as well that yields the same result. This also makes
these calls the same as the data access branch further down.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b1b2d64b90..63b5fb98d1 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1275,13 +1275,13 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 break;
 case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
 /* fall through */
 case POWERPC_MMU_BOOKE:
 cs->exception_index = POWERPC_EXCP_ITLB;
 env->error_code = 0;
 env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
 break;
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
-- 
2.30.9




[PATCH v3 24/33] target/ppc/mmu_common.c: Split off BookE handling from ppc_jumbo_xlate()

2024-05-07 Thread BALATON Zoltan
Introduce ppc_booke_xlate() to handle BookE and BookE 2.06 cases to
reduce ppc_jumbo_xlate() further.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 128 +---
 1 file changed, 92 insertions(+), 36 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 03b834eb77..83dc041a77 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1194,6 +1194,92 @@ static void booke206_update_mas_tlb_miss(CPUPPCState 
*env, target_ulong address,
 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
 }
 
+static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
+MMUAccessType access_type,
+hwaddr *raddrp, int *psizep, int *protp,
+int mmu_idx, bool guest_visible)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+mmu_ctx_t ctx;
+int ret;
+
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+ret = mmubooke206_get_physical_address(env, , eaddr, access_type,
+   mmu_idx);
+} else {
+ret = mmubooke_get_physical_address(env, , eaddr, access_type);
+}
+if (ret == 0) {
+*raddrp = ctx.raddr;
+*protp = ctx.prot;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (access_type == MMU_INST_FETCH) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->error_code = 0;
+break;
+case -3:
+/* No execute protection violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->spr[SPR_BOOKE_ESR] = 0;
+env->error_code = 0;
+break;
+}
+} else {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+}
+}
+return false;
+}
+
 /* Perform address translation */
 /* TODO: Split this by mmu_model. */
 static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
@@ -1246,15 +1332,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_40x_DEAR] = eaddr;
 env->spr[SPR_40x_ESR] = 0x;
 break;
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
   "any MMU exceptions\n");
@@ -1265,23 +1342,12 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 case -2:
 /* Access rights violation */
 cs->exception_index = POWERPC_EXCP_ISI;
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_

[PATCH v3 26/33] target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 1

2024-05-07 Thread BALATON Zoltan
Move setting error_code that appears in every case out in front and
hoist the common fall through case for BOOKE206 as well which allows
removing the nested switches.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 41 -
 1 file changed, 12 insertions(+), 29 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 788e2bebd5..c725a7932f 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1205,58 +1205,41 @@ static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 }
 
 log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+env->error_code = 0;
+if (ret == -1) {
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+}
+}
 if (access_type == MMU_INST_FETCH) {
 switch (ret) {
 case -1:
 /* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
-default:
-g_assert_not_reached();
-}
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
 break;
 case -2:
 /* Access rights violation */
 cs->exception_index = POWERPC_EXCP_ISI;
-env->error_code = 0;
 break;
 case -3:
 /* No execute protection violation */
 cs->exception_index = POWERPC_EXCP_ISI;
 env->spr[SPR_BOOKE_ESR] = 0;
-env->error_code = 0;
 break;
 }
 } else {
 switch (ret) {
 case -1:
 /* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_DTLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
-default:
-g_assert_not_reached();
-}
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
 break;
 case -2:
 /* Access rights violation */
 cs->exception_index = POWERPC_EXCP_DSI;
-env->error_code = 0;
 env->spr[SPR_BOOKE_DEAR] = eaddr;
 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
 break;
-- 
2.30.9




[PATCH v3 04/33] target/ppc: Remove unused helper

2024-05-07 Thread BALATON Zoltan
The helper_rac function is defined but not used, remove it.

Fixes: 005b69fdcc (target/ppc: Remove PowerPC 601 CPUs)
Signed-off-by: BALATON Zoltan 
Reviwed-by: Nicholas Piggin 
---
 target/ppc/helper.h |  2 --
 target/ppc/mmu_helper.c | 24 
 2 files changed, 26 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 86f97ee1e7..f769e01c3d 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -700,8 +700,6 @@ DEF_HELPER_2(book3s_msgclr, void, env, tl)
 
 DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
 #if !defined(CONFIG_USER_ONLY)
-DEF_HELPER_2(rac, tl, env, tl)
-
 DEF_HELPER_2(load_dcr, tl, env, tl)
 DEF_HELPER_3(store_dcr, void, env, tl, tl)
 #endif
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index b35a93c198..421e777ee6 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -596,30 +596,6 @@ void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
 do_6xx_tlb(env, EPN, 1);
 }
 
-/*/
-/* PowerPC 601 specific instructions (POWER bridge) */
-
-target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
-{
-mmu_ctx_t ctx;
-int nb_BATs;
-target_ulong ret = 0;
-
-/*
- * We don't have to generate many instances of this instruction,
- * as rac is supervisor only.
- *
- * XXX: FIX THIS: Pretend we have no BAT
- */
-nb_BATs = env->nb_BATs;
-env->nb_BATs = 0;
-if (get_physical_address_wtlb(env, , addr, 0, ACCESS_INT, 0) == 0) {
-ret = ctx.raddr;
-}
-env->nb_BATs = nb_BATs;
-return ret;
-}
-
 static inline target_ulong booke_tlb_to_page_size(int size)
 {
 return 1024 << (2 * size);
-- 
2.30.9




[PATCH v3 08/33] target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU

2024-05-07 Thread BALATON Zoltan
The default case will catch this and abort the same way and there is
still a warning about it in ppc_tlb_invalidate_all() so drop these
from mmu_common.c to simplify this code.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 886fb6a657..aa137123a4 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1219,10 +1219,6 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
mmu_idx);
 break;
-case POWERPC_MMU_MPC8xx:
-/* XXX: TODO */
-cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
-break;
 case POWERPC_MMU_REAL:
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
@@ -1353,8 +1349,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_BOOKE_DEAR] = eaddr;
 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
 break;
-case POWERPC_MMU_MPC8xx:
-cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
   "any MMU exceptions\n");
@@ -1427,9 +1421,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 }
 break;
-case POWERPC_MMU_MPC8xx:
-/* XXX: TODO */
-cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
 case POWERPC_MMU_BOOKE206:
 booke206_update_mas_tlb_miss(env, eaddr, access_type, 
mmu_idx);
 /* fall through */
-- 
2.30.9




[PATCH v3 11/33] target/ppc/mmu_common.c: Move some debug logging

2024-05-07 Thread BALATON Zoltan
Move the debug logging within ppc6xx_tlb_check() from after its only
call to simplify the caller.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 55 +++--
 1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 9d337a73ba..b2f2cee1a8 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -225,17 +225,14 @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t 
*ctx,
   access_type == MMU_INST_FETCH ? 'I' : 'D');
 switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
  0, access_type)) {
-case -3:
-/* TLB inconsistency */
-return -1;
 case -2:
 /* Access violation */
 ret = -2;
 best = nr;
 break;
-case -1:
+case -1: /* No match */
+case -3: /* TLB inconsistency */
 default:
-/* No match */
 break;
 case 0:
 /* access granted */
@@ -251,14 +248,37 @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t 
*ctx,
 }
 }
 if (best != -1) {
-done:
+done:
 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
   " prot=%01x ret=%d\n",
   ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
 /* Update page flags */
 pte_update_flags(ctx, >tlb.tlb6[best].pte1, ret, access_type);
 }
+#if defined(DUMP_PAGE_TABLES)
+if (qemu_loglevel_mask(CPU_LOG_MMU)) {
+CPUState *cs = env_cpu(env);
+PowerPCCPU *cpu = env_archcpu(env);
+hwaddr curaddr;
+uint32_t a0, a1, a2, a3;
 
+qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
+ ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu) + 
0x80);
+for (curaddr = ppc_hash32_hpt_base(cpu);
+ curaddr < (ppc_hash32_hpt_base(cpu)
++ ppc_hash32_hpt_mask(cpu) + 0x80);
+ curaddr += 16) {
+a0 = ldl_phys(cs->as, curaddr);
+a1 = ldl_phys(cs->as, curaddr + 4);
+a2 = ldl_phys(cs->as, curaddr + 8);
+a3 = ldl_phys(cs->as, curaddr + 12);
+if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
+qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
+ curaddr, a0, a1, a2, a3);
+}
+}
+}
+#endif
 return ret;
 }
 
@@ -420,29 +440,6 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ctx->raddr = (hwaddr)-1ULL;
 /* Software TLB search */
 ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
-#if defined(DUMP_PAGE_TABLES)
-if (qemu_loglevel_mask(CPU_LOG_MMU)) {
-CPUState *cs = env_cpu(env);
-hwaddr curaddr;
-uint32_t a0, a1, a2, a3;
-
-qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
- ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu) + 
0x80);
-for (curaddr = ppc_hash32_hpt_base(cpu);
- curaddr < (ppc_hash32_hpt_base(cpu)
-+ ppc_hash32_hpt_mask(cpu) + 0x80);
- curaddr += 16) {
-a0 = ldl_phys(cs->as, curaddr);
-a1 = ldl_phys(cs->as, curaddr + 4);
-a2 = ldl_phys(cs->as, curaddr + 8);
-a3 = ldl_phys(cs->as, curaddr + 12);
-if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
-qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
- curaddr, a0, a1, a2, a3);
-}
-}
-}
-#endif
 } else {
 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
 /* Direct-store segment : absolutely *BUGGY* for now */
-- 
2.30.9




[PATCH v3 03/33] target/ppc: Simplify syscall exception handlers

2024-05-07 Thread BALATON Zoltan
After previous changes the hypercall handling in 7xx and 74xx
exception handlers can be folded into one if statement to simplify
this code. Also add "unlikely" to mark the less frequently used branch
for the compiler.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Harsh Prateek Bora 
---
 target/ppc/excp_helper.c | 22 ++
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 5aa84bccd2..d19212f772 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -762,26 +762,21 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 {
 int lev = env->error_code;
-
-if (lev == 1 && cpu->vhyp) {
-dump_hcall(env);
-} else {
-dump_syscall(env);
-}
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
  * uses VOF and the 7xx CPUs, so although the 7xx don't have
  * HV mode, we need to keep hypercall support.
  */
-if (lev == 1 && cpu->vhyp) {
+if (unlikely(lev == 1 && cpu->vhyp)) {
 PPCVirtualHypervisorClass *vhc =
 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+dump_hcall(env);
 vhc->hypercall(cpu->vhyp, cpu);
 powerpc_reset_excp_state(cpu);
 return;
 }
-
+dump_syscall(env);
 break;
 }
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
@@ -907,26 +902,21 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 {
 int lev = env->error_code;
-
-if (lev == 1 && cpu->vhyp) {
-dump_hcall(env);
-} else {
-dump_syscall(env);
-}
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
  * uses VOF and the 74xx CPUs, so although the 74xx don't have
  * HV mode, we need to keep hypercall support.
  */
-if (lev == 1 && cpu->vhyp) {
+if (unlikely(lev == 1 && cpu->vhyp)) {
 PPCVirtualHypervisorClass *vhc =
 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+dump_hcall(env);
 vhc->hypercall(cpu->vhyp, cpu);
 powerpc_reset_excp_state(cpu);
 return;
 }
-
+dump_syscall(env);
 break;
 }
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
-- 
2.30.9




[PATCH v3 02/33] target/ppc: Move patching nip from exception handler to helper_scv

2024-05-07 Thread BALATON Zoltan
From: Nicholas Piggin 

Unlike sc, for scv a facility unavailable interrupt must be generated
if FSCR[SCV]=0 so we can't raise the exception with nip set to next
instruction but we can move advancing nip if the FSCR check passes to
helper_scv so the exception handler does not need to change it.

[balaton: added commit message]
Signed-off-by: BALATON Zoltan 
---
 target/ppc/excp_helper.c | 2 +-
 target/ppc/translate.c   | 6 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 92fe535815..5aa84bccd2 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1415,7 +1415,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
 lev = env->error_code;
 dump_syscall(env);
-env->nip += 4;
 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
 
@@ -2524,6 +2523,7 @@ void helper_ppc_maybe_interrupt(CPUPPCState *env)
 void helper_scv(CPUPPCState *env, uint32_t lev)
 {
 if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
+env->nip += 4;
 raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
 } else {
 raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index e112c44a02..1d4e9f0679 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4493,7 +4493,11 @@ static void gen_scv(DisasContext *ctx)
 {
 uint32_t lev = (ctx->opcode >> 5) & 0x7F;
 
-/* Set the PC back to the faulting instruction. */
+/*
+ * Set the PC back to the scv instruction (unlike sc), because a facility
+ * unavailable interrupt must be generated if FSCR[SCV]=0. The helper
+ * advances nip if the FSCR check passes.
+ */
 gen_update_nip(ctx, ctx->cia);
 gen_helper_scv(tcg_env, tcg_constant_i32(lev));
 
-- 
2.30.9




[PATCH v3 07/33] target/ppc/mmu_common.c: Simplify checking for real mode

2024-05-07 Thread BALATON Zoltan
In get_physical_address_wtlb() the real_mode flag depends on either
the MSR[IR] or MSR[DR] bit depending on access_type. Extract just the
needed bit in a more straight forward way instead of doing unnecessary
computation.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 09cbeb0052..886fb6a657 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1184,8 +1184,10 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  int mmu_idx)
 {
 int ret = -1;
-bool real_mode = (type == ACCESS_CODE && !FIELD_EX64(env->msr, MSR, IR)) ||
- (type != ACCESS_CODE && !FIELD_EX64(env->msr, MSR, DR));
+bool real_mode;
+
+real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+  : !FIELD_EX64(env->msr, MSR, DR);
 
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
-- 
2.30.9




[PATCH v3 01/33] target/ppc: Fix gen_sc to use correct nip

2024-05-07 Thread BALATON Zoltan
Most exceptions are raised with nip pointing to the faulting
instruction but the sc instruction generating a syscall exception
leaves nip pointing to next instruction. Fix gen_sc to not use
gen_exception_err() which sets nip back but correctly set nip to
pc_next so we don't have to patch this in the exception handlers.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/excp_helper.c | 43 ++--
 target/ppc/translate.c   | 15 ++
 2 files changed, 8 insertions(+), 50 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0712098cf7..92fe535815 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -116,7 +116,7 @@ static void dump_syscall(CPUPPCState *env)
   ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
   ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
   ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
-  ppc_dump_gpr(env, 8), env->nip);
+  ppc_dump_gpr(env, 8), env->nip - 4);
 }
 
 static void dump_hcall(CPUPPCState *env)
@@ -131,7 +131,7 @@ static void dump_hcall(CPUPPCState *env)
   ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
   ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
   ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
-  env->nip);
+  env->nip - 4);
 }
 
 #ifdef CONFIG_TCG
@@ -516,12 +516,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FIT:   /* Fixed-interval timer interrupt   */
 trace_ppc_excp_print("FIT");
@@ -632,12 +626,6 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 case POWERPC_EXCP_DECR:  /* Decrementer exception*/
@@ -780,13 +768,6 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
@@ -932,13 +913,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
@@ -1098,12 +1072,6 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 case POWERPC_EXCP_APU:   /* Auxiliary processor unavailable  */
@@ -1428,13 +1396,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /* "PAPR mode" built-in hypercall emulation */
 if (lev == 1 && books_vhyp_handles_hcall(cpu)) {
 PPCVirtualHypervisorClass *vhc =
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 93ffec787c..e112c44a02 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4472,22 +4472,19 @@ static void gen_hrfid(DisasContext *ctx)
 #endif
 
 /* sc */
-#if defined(CONFIG_USER_ONLY)
-#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
-#else
-#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
-#endif
 static void gen_sc(DisasContext *ctx)
 {
-uint32_t lev;
-
 /*
  * LEV is a 7-bit field, but the top 6 bits are treated as 

[PATCH v3 00/33] Misc PPC exception and BookE MMU clean ups

2024-05-07 Thread BALATON Zoltan
This series does some further clean up mostly around BookE MMU to
untangle it from other MMU models. It also contains some other changes
that I've come up with while working on this. The Simplify
ppc_booke_xlate() part 1 and part 2 patches could be squashed together
but left them separate for easier review.

v3:
- Address review comments from Nick
- Rebase on master
- Squashed some patches together
- Add some more patches I've done since last version

v2:
- Fix user mode issue in patch 1 by keeping old behaviour for user mode
- Add some more MMU clean up patches

Regards,
BALATON Zoltan


BALATON Zoltan (33):
  target/ppc: Fix gen_sc to use correct nip
  target/ppc: Move patching nip from exception handler to helper_scv
  target/ppc: Simplify syscall exception handlers
  target/ppc: Remove unused helper
  target/ppc/mmu_common.c: Move calculation of a value closer to its
usage
  target/ppc/mmu_common.c: Remove unneeded local variable
  target/ppc/mmu_common.c: Simplify checking for real mode
  target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU
  target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()
  target/ppc/mmu_common.c: Move else branch to avoid large if block
  target/ppc/mmu_common.c: Move some debug logging
  target/ppc/mmu_common.c: Eliminate ret from
mmu6xx_get_physical_address()
  target/ppc/mmu_common.c: Split out BookE cases before checking real
mode
  target/ppc/mmu_common.c: Split off real mode cases in
get_physical_address_wtlb()
  target/ppc/mmu_common.c: Inline and remove check_physical()
  target/ppc/mmu_common.c: Simplify mmubooke_get_physical_address()
  target/ppc/mmu_common.c: Simplify mmubooke206_get_physical_address()
  target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls
  target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Replace hard coded constants in
ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Make get_physical_address_wtlb() static
  target/ppc: Remove pp_check() and reuse ppc_hash32_pp_prot()
  target/ppc/mmu_common.c: Remove BookE from direct store handling
  target/ppc/mmu_common.c: Split off BookE handling from
ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Remove BookE handling from
get_physical_address_wtlb()
  target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 1
  target/ppc/mmu_common.c: Simplify ppc_booke_xlate() part 2
  target/ppc/mmu_common.c: Move BookE MMU functions together
  target/ppc: Remove id_tlbs flag from CPU env
  target/ppc: Split off common embedded TLB init
  target/ppc/mmu-hash32.c: Drop a local variable
  target/ppc/mmu-radix64.c: Drop a local variable
  target/ppc: Add a macro to check for page protection bit

 hw/ppc/pegasos2.c|   2 +-
 target/ppc/cpu.h |   1 -
 target/ppc/cpu_init.c|  69 ++-
 target/ppc/excp_helper.c |  67 +--
 target/ppc/helper.h  |   2 -
 target/ppc/helper_regs.c |   1 -
 target/ppc/internal.h|  72 +--
 target/ppc/mmu-hash32.c  |  54 +--
 target/ppc/mmu-hash64.c  |   2 +-
 target/ppc/mmu-radix64.c |   5 +-
 target/ppc/mmu_common.c  | 954 +--
 target/ppc/mmu_helper.c  |  36 +-
 target/ppc/translate.c   |  21 +-
 13 files changed, 517 insertions(+), 769 deletions(-)

-- 
2.30.9




[PATCH v3 05/33] target/ppc/mmu_common.c: Move calculation of a value closer to its usage

2024-05-07 Thread BALATON Zoltan
In mmubooke_check_tlb() and mmubooke206_check_tlb() prot2 is
calculated first but only used after an unrelated check that can
return before tha value is used. Move the calculation after the check,
closer to where it is used, to keep them together and avoid computing
it when not needed.

Signed-off-by: BALATON Zoltan 
Reviwed-by: Nicholas Piggin 
---
 target/ppc/mmu_common.c | 36 +---
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 4fde7fd3bf..f79e390306 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -635,12 +635,6 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return -1;
 }
 
-if (FIELD_EX64(env->msr, MSR, PR)) {
-prot2 = tlb->prot & 0xF;
-} else {
-prot2 = (tlb->prot >> 4) & 0xF;
-}
-
 /* Check the address space */
 if ((access_type == MMU_INST_FETCH ?
 FIELD_EX64(env->msr, MSR, IR) :
@@ -649,6 +643,11 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return -1;
 }
 
+if (FIELD_EX64(env->msr, MSR, PR)) {
+prot2 = tlb->prot & 0xF;
+} else {
+prot2 = (tlb->prot >> 4) & 0xF;
+}
 *prot = prot2;
 if (prot2 & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
@@ -830,6 +829,18 @@ static int mmubooke206_check_tlb(CPUPPCState *env, 
ppcmas_tlb_t *tlb,
 
 found_tlb:
 
+/* Check the address space and permissions */
+if (access_type == MMU_INST_FETCH) {
+/* There is no way to fetch code using epid load */
+assert(!use_epid);
+as = FIELD_EX64(env->msr, MSR, IR);
+}
+
+if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
+qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
+return -1;
+}
+
 if (pr) {
 if (tlb->mas7_3 & MAS3_UR) {
 prot2 |= PAGE_READ;
@@ -851,19 +862,6 @@ found_tlb:
 prot2 |= PAGE_EXEC;
 }
 }
-
-/* Check the address space and permissions */
-if (access_type == MMU_INST_FETCH) {
-/* There is no way to fetch code using epid load */
-assert(!use_epid);
-as = FIELD_EX64(env->msr, MSR, IR);
-}
-
-if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
-qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
-return -1;
-}
-
 *prot = prot2;
 if (prot2 & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
-- 
2.30.9




Re: [PATCH v2 24/28] target/ppc/mmu_common.c: Remove BookE handling from get_physical_address_wtlb()

2024-05-07 Thread BALATON Zoltan

On Tue, 7 May 2024, Nicholas Piggin wrote:

On Thu May 2, 2024 at 9:43 AM AEST, BALATON Zoltan wrote:

This function is no longer called for BookE MMU model so remove parts
related to it. This has uncovered a few may be used uninitialised
warnings that are also fixed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 25 +
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index a1f98f8de4..d61c41d8c9 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -684,12 +684,10 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 break;
 }
 }
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU,
   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
@@ -897,9 +895,6 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 goto found_tlb;
 }
 }
@@ -907,6 +902,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,

 found_tlb:

+ctx->raddr = raddr;


Not sure about the uninitialized warnings here either, caller probably
should not be using ctx->raddr unless we returned 0...


 qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
   HWADDR_FMT_plx " %d %d\n", __func__,
   ret < 0 ? "refused" : "granted", address, raddr,
@@ -1163,20 +1159,9 @@ static int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-bool real_mode;
-
-if (env->mmu_model == POWERPC_MMU_BOOKE) {
-return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
-} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
-return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-mmu_idx);
-}


This could just go in the previous patch when you split booke xlate?


Removing this uncovers the warnings so I keep it here to separate it from 
the previous change. I gave up on trying to resolve these warnings and 
untangle the embedded functions from mmu_ctx_t which would be needed to 
move these booke functions out from this file. The other problem is that 
these booke get_physical_address functions and mmu40x_get_physical_address 
all use ppcemb_tlb_check which then needs to be in the same file and 
static to be inlined and not run too slow but 40x is still in jumbo_xlate 
so I just leave it for now and may return to it later or let somebody else 
continue from here. I think this series moves forward enough for now and I 
don't have more time now.



-
-real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
-  : !FIELD_EX64(env->msr, MSR, DR);
-if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
-  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
-  env->mmu_model == POWERPC_MMU_REAL)) {
+bool real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode) {
 memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;


This still changes beahviour of MPC8xx MMU doesn't it? It's supposed
to abort always.


I don't think it can get here because there's still an abort case in 
ppc_tlb_invalidate_all() which is called from ppc_cpu_reset_hold() so it 
will likely crash before it could call anything here. But if you think 
it's necessary I could add a case for it in ppc_xlate() maybe.


Regards,
BALATON Zoltan



Re: [PATCH v2 27/28] target/ppc: Remove id_tlbs flag from CPU env

2024-05-07 Thread BALATON Zoltan

On Tue, 7 May 2024, Nicholas Piggin wrote:

On Thu May 2, 2024 at 9:43 AM AEST, BALATON Zoltan wrote:

This flag for split instruction/data TLBs is only set for 6xx soft TLB
MMU model and not used otherwise so no need to have a separate flag
for that.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/pegasos2.c|  2 +-
 target/ppc/cpu.h |  1 -
 target/ppc/cpu_init.c| 19 +--
 target/ppc/helper_regs.c |  1 -
 target/ppc/mmu_common.c  | 10 ++
 target/ppc/mmu_helper.c  | 12 ++--
 6 files changed, 10 insertions(+), 35 deletions(-)

diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 04d6decb2b..dfc6fab180 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -984,7 +984,7 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
   cpu->env.icache_line_size);
 qemu_fdt_setprop_cell(fdt, cp, "i-cache-line-size",
   cpu->env.icache_line_size);
-if (cpu->env.id_tlbs) {
+if (cpu->env.tlb_type == TLB_6XX) {


Want to just add the standard comment here?

   /* 6xx has separate TLBs for instructions and data */


I think that comment would be redundant here because it's clear from the 
i-tlb, d-tlb this adds so I can do without a comment in this machine if 
you don't mind. (If this was not in my machine I would not mind adding a 
comment but I'd keep this one simple.) I think comments should only be 
added for things that are not clear from code.


Regards,
BALATON Zoltan


Otherwise looks good

Reviewed-by: Nicholas Piggin 


 qemu_fdt_setprop_cell(fdt, cp, "i-tlb-sets", cpu->env.nb_ways);
 qemu_fdt_setprop_cell(fdt, cp, "i-tlb-size", cpu->env.tlb_per_way);
 qemu_fdt_setprop_cell(fdt, cp, "d-tlb-sets", cpu->env.nb_ways);




Re: [PATCH v2 26/28] target/ppc/mmu_common.c: Move BookE MMU functions together

2024-05-07 Thread BALATON Zoltan

On Tue, 7 May 2024, Nicholas Piggin wrote:

What do you think about adding mmu-book3e.c instead?


Now I remember that besides possible performance loss because of loss of 
automatic inline if not all functions are static the other reason was that 
these functions use mmu_ctx_t that I don't want to export. Howerver these 
booke functions only use the raddr and ctx fields so there should be no 
reason to use the ctx and I had a patch to do that but dropped it trying 
to simplify the series and come back to it later. I might try to get that 
back to see if it helps with some used uninit warnings but I'm not sure it 
would.


Regards,
BALATON Zoltan



Re: [PATCH v2 20/28] target/ppc/mmu_common.c: Make get_physical_address_wtlb() static

2024-05-07 Thread BALATON Zoltan

On Tue, 7 May 2024, Nicholas Piggin wrote:

On Thu May 2, 2024 at 9:43 AM AEST, BALATON Zoltan wrote:

This function is not used from any other files so make it static and
fix the maybe used uninitialised warnings this has uncovered.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 5 +
 target/ppc/mmu_common.c | 5 -
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 601c0b533f..7a99f08dc8 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -261,10 +261,7 @@ typedef struct mmu_ctx_t mmu_ctx_t;
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
- target_ulong eaddr,
- MMUAccessType access_type, int type,
- int mmu_idx);
+
 /* Software driven TLB helpers */
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 762b13805b..4852cb5571 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -666,6 +666,7 @@ static int mmubooke_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 hwaddr raddr = (hwaddr)-1ULL;
 int i, ret = -1;

+ctx->prot = 0;
 for (i = 0; i < env->nb_tlb; i++) {
 tlb = >tlb.tlbe[i];
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
@@ -873,6 +874,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 hwaddr raddr = (hwaddr)-1ULL;
 int i, j, ways, ret = -1;

+ctx->prot = 0;
 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
 ways = booke206_tlb_ways(env, i);
 for (j = 0; j < ways; j++) {


The prot warnings are valid AFAIKS, used uninit by qemu_log_mask call.

So, I see what the booke _check_tlb() functions are doing with
*prot now and that is to assign it iff return value is 0 or -2 or
-3, matching TLB address (and possibly mismatch prot).

Would it be better to fix it as:

   qemu_log_mask(CPU_LOG_MMU,
 "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
 " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
 address, raddr, ret == -1 ? 0 : ctx->prot, ret);

This way it's clearer that we're only printing it when a TLB was
found, and it won't silence other possible use-uninitialised?


I can do that.


@@ -1144,7 +1146,7 @@ void dump_mmu(CPUPPCState *env)
 }
 }

-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
+static int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
  int mmu_idx)
@@ -1163,6 +1165,7 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
   env->mmu_model == POWERPC_MMU_SOFT_4xx ||
   env->mmu_model == POWERPC_MMU_REAL)) {
+memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 return 0;


I wonder why the compiler doesn't see these, they are all in the return
not-zero cases that should be quite visible?

What if you leave the static change to the end of your series, do the
simplifications allow the compiler to work it out? I prefer not to
squash such compiler warnings if it can be avoided.


Even removing this memser at the end of the series brings back the 
warnings so this has to stay for now. Maybe this can be cleaned up later 
but I'd like to focus on booke now.


Regards,
BALATON Zoltan



Re: [PATCH v2 00/28] Misc PPC exception and BookE MMU clean ups

2024-05-07 Thread BALATON Zoltan

On Tue, 7 May 2024, Nicholas Piggin wrote:

On Thu May 2, 2024 at 9:43 AM AEST, BALATON Zoltan wrote:

This series does some further clean up mostly around BookE MMU to
untangle it from other MMU models. It also contains some other changes
that I've come up with while working on this. The first 3 patches are
from the last exception handling clean up series that were dropped due
to some error on CI but I'm not sure if that was because of some CI
infrastructure problem or some problem with the patches as the error
did not make much sense. So these patches are only rebased now, I made
no other change to them until the issue is understood better. The rest
are new patches I've added since tha last series. Please review.


Not CI infrastructure as far as I could tell it's upstream gitlab.
But I could not figure out how to reproduce at the time... I ended
up running out of time to look too closely though.


I could reproduce it at the end so it wasn't CI failure but I don't 
completely understand what is it.



I think I won't take the first 2, yes arguably the CPU does execute
the sc instruction, but it's actually a good rule for the exception
handler to be invoked with the nip that caused the exception, and
SRR0/1 to be set by the handler according to semantics.


v2:
- Fix user mode issue in patch 1 by keeping old behaviour for user mode


I forgot to change the blurb above but in this v2 version I think I've 
solved that problem as noted here but I don't know why the user mode SC is 
different and could not find where is it handled. This version seems to 
work though.


Regards,
BALATON Zoltan



Re: [PATCH v2 26/28] target/ppc/mmu_common.c: Move BookE MMU functions together

2024-05-07 Thread BALATON Zoltan

On Tue, 7 May 2024, Nicholas Piggin wrote:

What do you think about adding mmu-book3e.c instead?


I have considered that but found that some functions have to be in the 
same file and declared static for the compiler to inline them otherwise I 
get worse performance. Maybe after these rearrangments it's now possible 
to move these out but as this series got a bit long already I dod not go 
through with that and left it for a follow up but I can give it a try.


Thanks for the review so far, I'll try to make the changes that I 
understood and submit and updated version. I'm not sure I got some of your 
requests so that may need another round.


Regards,
BALATON Zoltan



Re: [PATCH 6/7] target/ppc: Remove unused struct 'mmu_ctx_hash32'

2024-05-05 Thread BALATON Zoltan

On Sun, 5 May 2024, Dr. David Alan Gilbert wrote:

I think it's use was removed by
Commit 5883d8b296 ("mmu-hash*: Don't use full ppc_hash{32,
64}_translate() path for get_phys_page_debug()")

Signed-off-by: Dr. David Alan Gilbert 


Reviewed-by: BALATON Zoltan 


---
target/ppc/mmu-hash32.c | 6 --
1 file changed, 6 deletions(-)

diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 3976416840..746321329c 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -36,12 +36,6 @@
#  define LOG_BATS(...) do { } while (0)
#endif

-struct mmu_ctx_hash32 {
-hwaddr raddr;  /* Real address  */
-int prot;  /* Protection bits   */
-int key;   /* Access key*/
-};
-
static int ppc_hash32_pp_prot(int key, int pp, int nx)
{
int prot;





[PATCH] include/exec/cpu-common.h: Rename PAGE_BITS macro to PAGE_RWX

2024-05-05 Thread BALATON Zoltan
This macro can be used to abbreviate PAGE_READ | PAGE_WRITE | PAGE_EXEC
for which PAGE_RWX is a better name and renaming it also shows it is
not related to TARGET_PAGE_BITS.

Signed-off-by: BALATON Zoltan 
---
 accel/tcg/user-exec.c  | 2 +-
 bsd-user/mmap.c| 6 +++---
 include/exec/cpu-common.h  | 2 +-
 linux-user/elfload.c   | 2 +-
 linux-user/mmap.c  | 2 +-
 target/cris/mmu.c  | 4 ++--
 target/microblaze/helper.c | 2 +-
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 1c621477ad..a81e3cc920 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -765,7 +765,7 @@ int page_unprotect(target_ulong address, uintptr_t pc)
 if (prot & PAGE_EXEC) {
 prot = (prot & ~PAGE_EXEC) | PAGE_READ;
 }
-mprotect((void *)g2h_untagged(start), len, prot & PAGE_BITS);
+mprotect((void *)g2h_untagged(start), len, prot & PAGE_RWX);
 }
 mmap_unlock();
 
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 3ef11b2807..c785615392 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -96,7 +96,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
 end = host_end;
 }
 ret = mprotect(g2h_untagged(host_start),
-   qemu_host_page_size, prot1 & PAGE_BITS);
+   qemu_host_page_size, prot1 & PAGE_RWX);
 if (ret != 0)
 goto error;
 host_start += qemu_host_page_size;
@@ -107,7 +107,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int 
prot)
 prot1 |= page_get_flags(addr);
 }
 ret = mprotect(g2h_untagged(host_end - qemu_host_page_size),
-   qemu_host_page_size, prot1 & PAGE_BITS);
+   qemu_host_page_size, prot1 & PAGE_RWX);
 if (ret != 0)
 goto error;
 host_end -= qemu_host_page_size;
@@ -174,7 +174,7 @@ static int mmap_frag(abi_ulong real_start,
 return -1;
 prot1 = prot;
 }
-prot1 &= PAGE_BITS;
+prot1 &= PAGE_RWX;
 
 prot_new = prot | prot1;
 if (fd != -1) {
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 8812ba744d..a4bb4e6680 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -212,7 +212,7 @@ G_NORETURN void cpu_loop_exit_restore(CPUState *cpu, 
uintptr_t pc);
 #define PAGE_READ  0x0001
 #define PAGE_WRITE 0x0002
 #define PAGE_EXEC  0x0004
-#define PAGE_BITS  (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
+#define PAGE_RWX   (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
 #define PAGE_VALID 0x0008
 /*
  * Original state of the write flag (used when tracking self-modifying code)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f9461d2844..41fae2b520 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2361,7 +2361,7 @@ static bool zero_bss(abi_ulong start_bss, abi_ulong 
end_bss,
 if (start_bss < align_bss) {
 int flags = page_get_flags(start_bss);
 
-if (!(flags & PAGE_BITS)) {
+if (!(flags & PAGE_RWX)) {
 /*
  * The whole address space of the executable was reserved
  * at the start, therefore all pages will be VALID.
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index be3b9a68eb..66a1631094 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -117,7 +117,7 @@ static void shm_region_rm_complete(abi_ptr start, abi_ptr 
last)
 static int validate_prot_to_pageflags(int prot)
 {
 int valid = PROT_READ | PROT_WRITE | PROT_EXEC | TARGET_PROT_SEM;
-int page_flags = (prot & PAGE_BITS) | PAGE_VALID;
+int page_flags = (prot & PAGE_RWX) | PAGE_VALID;
 
 #ifdef TARGET_AARCH64
 {
diff --git a/target/cris/mmu.c b/target/cris/mmu.c
index b574ec6e5b..c25c31c9f8 100644
--- a/target/cris/mmu.c
+++ b/target/cris/mmu.c
@@ -333,7 +333,7 @@ int cris_mmu_translate(struct cris_mmu_result *res,
 
 if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) {
 res->phy = vaddr;
-res->prot = PAGE_BITS;
+res->prot = PAGE_RWX;
 goto done;
 }
 
@@ -344,7 +344,7 @@ int cris_mmu_translate(struct cris_mmu_result *res,
 miss = 0;
 base = cris_mmu_translate_seg(env, seg);
 res->phy = base | (0x0fff & vaddr);
-res->prot = PAGE_BITS;
+res->prot = PAGE_RWX;
 } else {
 miss = cris_mmu_translate_page(res, env, vaddr, access_type,
is_user, debug);
diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c
index d25c9eb4d3..ff5f86ddc2 100644
--- a/target/microblaze/helper.c
+++ b/target/microblaze/helper.c
@@ -51,7 +51,7 @@ bool mb_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 if (mmu_idx == MMU_NOMMU_IDX) {
 /* MMU disabled or not available.  */
 

[PATCH v2 01/28] target/ppc: Fix gen_sc to use correct nip

2024-05-01 Thread BALATON Zoltan
Most exceptions are raised with nip pointing to the faulting
instruction but the sc instruction generating a syscall exception
leaves nip pointing to next instruction. Fix gen_sc to not use
gen_exception_err() which sets nip back but correctly set nip to
pc_next so we don't have to patch this in the exception handlers.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/excp_helper.c | 43 ++--
 target/ppc/translate.c   | 15 ++
 2 files changed, 8 insertions(+), 50 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0712098cf7..92fe535815 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -116,7 +116,7 @@ static void dump_syscall(CPUPPCState *env)
   ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
   ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
   ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
-  ppc_dump_gpr(env, 8), env->nip);
+  ppc_dump_gpr(env, 8), env->nip - 4);
 }
 
 static void dump_hcall(CPUPPCState *env)
@@ -131,7 +131,7 @@ static void dump_hcall(CPUPPCState *env)
   ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
   ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
   ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
-  env->nip);
+  env->nip - 4);
 }
 
 #ifdef CONFIG_TCG
@@ -516,12 +516,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FIT:   /* Fixed-interval timer interrupt   */
 trace_ppc_excp_print("FIT");
@@ -632,12 +626,6 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 case POWERPC_EXCP_DECR:  /* Decrementer exception*/
@@ -780,13 +768,6 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
@@ -932,13 +913,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
@@ -1098,12 +1072,6 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 case POWERPC_EXCP_APU:   /* Auxiliary processor unavailable  */
@@ -1428,13 +1396,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /* "PAPR mode" built-in hypercall emulation */
 if (lev == 1 && books_vhyp_handles_hcall(cpu)) {
 PPCVirtualHypervisorClass *vhc =
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 93ffec787c..e112c44a02 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4472,22 +4472,19 @@ static void gen_hrfid(DisasContext *ctx)
 #endif
 
 /* sc */
-#if defined(CONFIG_USER_ONLY)
-#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
-#else
-#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
-#endif
 static void gen_sc(DisasContext *ctx)
 {
-uint32_t lev;
-
 /*
  * LEV is a 7-bit field, but the top 6 bits are treated as 

[PATCH v2 26/28] target/ppc/mmu_common.c: Move BookE MMU functions together

2024-05-01 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 300 
 1 file changed, 150 insertions(+), 150 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b76611da80..204b8af455 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -910,6 +910,156 @@ found_tlb:
 return ret;
 }
 
+static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
+ MMUAccessType access_type, int 
mmu_idx)
+{
+uint32_t epid;
+bool as, pr;
+uint32_t missed_tid = 0;
+bool use_epid = mmubooke206_get_as(env, mmu_idx, , , );
+
+if (access_type == MMU_INST_FETCH) {
+as = FIELD_EX64(env->msr, MSR, IR);
+}
+env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
+env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
+env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
+env->spr[SPR_BOOKE_MAS3] = 0;
+env->spr[SPR_BOOKE_MAS6] = 0;
+env->spr[SPR_BOOKE_MAS7] = 0;
+
+/* AS */
+if (as) {
+env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
+env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
+}
+
+env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
+env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
+
+if (!use_epid) {
+switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
+case MAS4_TIDSELD_PID0:
+missed_tid = env->spr[SPR_BOOKE_PID];
+break;
+case MAS4_TIDSELD_PID1:
+missed_tid = env->spr[SPR_BOOKE_PID1];
+break;
+case MAS4_TIDSELD_PID2:
+missed_tid = env->spr[SPR_BOOKE_PID2];
+break;
+}
+env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
+} else {
+missed_tid = epid;
+env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
+}
+env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
+
+
+/* next victim logic */
+env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
+env->last_way++;
+env->last_way &= booke206_tlb_ways(env, 0) - 1;
+env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
+}
+
+static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
+MMUAccessType access_type,
+hwaddr *raddrp, int *psizep, int *protp,
+int mmu_idx, bool guest_visible)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+mmu_ctx_t ctx;
+int ret;
+
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+ret = mmubooke206_get_physical_address(env, , eaddr, access_type,
+   mmu_idx);
+} else {
+ret = mmubooke_get_physical_address(env, , eaddr, access_type);
+}
+if (ret == 0) {
+*raddrp = ctx.raddr;
+*protp = ctx.prot;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+env->error_code = 0;
+if (env->mmu_model == POWERPC_MMU_BOOKE206 && ret == -1) {
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+}
+if (access_type == MMU_INST_FETCH) {
+if (ret == -1) {
+/* No matches in page tables or TLB */
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+} else {
+cs->exception_index = POWERPC_EXCP_ISI;
+if (ret == -3) {
+/* No execute protection violation */
+env->spr[SPR_BOOKE_ESR] = 0;
+}
+}
+return false;
+}
+
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -4:
+/* Direct store exception */
+env->spr[SPR_DAR] = eaddr;
+switch (env->access_type) {
+case ACCESS_FLOAT:
+/* Floating point load/store */
+cs->exception_index = POWERPC_EXCP_ALIGN;
+env->error_code = POWERPC_EXCP_ALIGN_FP;
+break;
+case ACCESS_RES:
+/* lwarx, ldarx or stwcx. */
+cs->exception_index = POWERPC_EXCP_DSI;
+

[PATCH v2 18/28] target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()

2024-05-01 Thread BALATON Zoltan
Instead of putting a large block of code in an if, invert the
condition and return early to be able to deindent the code block.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 319 
 1 file changed, 159 insertions(+), 160 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 28847c32f2..2487b4deff 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1265,187 +1265,186 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 *protp = ctx.prot;
 *psizep = TARGET_PAGE_BITS;
 return true;
+} else if (!guest_visible) {
+return false;
 }
 
-if (guest_visible) {
-log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
-if (type == ACCESS_CODE) {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-cs->exception_index = POWERPC_EXCP_IFTLB;
-env->error_code = 1 << 18;
-env->spr[SPR_IMISS] = eaddr;
-env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
-goto tlb_miss;
-case POWERPC_MMU_SOFT_4xx:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_40x_DEAR] = eaddr;
-env->spr[SPR_40x_ESR] = 0x;
-break;
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
-break;
-case POWERPC_MMU_REAL:
-cpu_abort(cs, "PowerPC in real mode should never raise "
-  "any MMU exceptions\n");
-default:
-cpu_abort(cs, "Unknown or invalid MMU model\n");
-}
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (type == ACCESS_CODE) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_SOFT_6xx:
+cs->exception_index = POWERPC_EXCP_IFTLB;
+env->error_code = 1 << 18;
+env->spr[SPR_IMISS] = eaddr;
+env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
+goto tlb_miss;
+case POWERPC_MMU_SOFT_4xx:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_40x_DEAR] = eaddr;
+env->spr[SPR_40x_ESR] = 0x;
 break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->error_code = 0;
-} else {
-env->error_code = 0x0800;
-}
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
 break;
-case -3:
-/* No execute protection violation */
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->spr[SPR_BOOKE_ESR] = 0x;
-env->error_code = 0;
+case POWERPC_MMU_REAL:
+cpu_abort(cs, "PowerPC in real mode should never raise "
+  "any MMU exceptions\n");
+default:
+cpu_abort(cs, "Unknown or invalid MMU model\n");
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
+(env->mmu_model == POWERPC_MMU_BOOKE206)) {
+env->error_code = 0;
+} else {
+  

[PATCH v2 28/28] target/ppc: Split off common 4xx TLB init

2024-05-01 Thread BALATON Zoltan
Several 4xx related CPUs have the same TLB settings. Split it off in a
common function in cpu_init.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/cpu_init.c | 46 ---
 1 file changed, 17 insertions(+), 29 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 07ad788e54..d7e85c1b07 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -2107,18 +2107,22 @@ static int check_pow_hid0_74xx(CPUPPCState *env)
 return 0;
 }
 
+static void init_tlbs_4xx(CPUPPCState *env)
+{
+#ifndef CONFIG_USER_ONLY
+env->nb_tlb = 64;
+env->nb_ways = 1;
+env->tlb_type = TLB_EMB;
+#endif
+}
+
 static void init_proc_405(CPUPPCState *env)
 {
 register_40x_sprs(env);
 register_405_sprs(env);
 register_usprgh_sprs(env);
 
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+init_tlbs_4xx(env);
 init_excp_4xx(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2185,12 +2189,8 @@ static void init_proc_440EP(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_4xx(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2282,12 +2282,7 @@ static void init_proc_440GP(CPUPPCState *env)
 register_440_sprs(env);
 register_usprgh_sprs(env);
 
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+init_tlbs_4xx(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2355,12 +2350,8 @@ static void init_proc_440x5(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_4xx(env);
 init_excp_BookE(env);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
@@ -2717,11 +2708,8 @@ static void init_proc_e200(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, _write_generic,
  0x);
-#if !defined(CONFIG_USER_ONLY)
-env->nb_tlb = 64;
-env->nb_ways = 1;
-env->tlb_type = TLB_EMB;
-#endif
+
+init_tlbs_4xx(env);
 init_excp_e200(env, 0xUL);
 env->dcache_line_size = 32;
 env->icache_line_size = 32;
-- 
2.30.9




[PATCH v2 10/28] target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()

2024-05-01 Thread BALATON Zoltan
Repurpose get_segment_6xx_tlb() to do the whole address translation
for POWERPC_MMU_SOFT_6xx MMU model by moving the BAT check there and
renaming it to match other similar functions. These are only called
once together so no need to keep these separate functions and
combining them simplifies the caller allowing further restructuring.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 98730035b1..ef1669b01d 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -359,19 +359,25 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 return ret;
 }
 
-/* Perform segment based translation */
-static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong eaddr, MMUAccessType access_type,
-   int type)
+static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+   target_ulong eaddr,
+   MMUAccessType access_type, int type)
 {
 PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
-target_ulong vsid;
-int ds, target_page_bits;
+target_ulong vsid, sr, pgidx;
 bool pr;
-int ret;
-target_ulong sr, pgidx;
+int ds, target_page_bits, ret = -1;
 
+/* First try to find a BAT entry if there are any */
+if (env->nb_BATs != 0) {
+ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
+}
+if (ret >= 0) {
+return ret;
+}
+
+/* Perform segment based translation when no BATs matched */
 pr = FIELD_EX64(env->msr, MSR, PR);
 ctx->eaddr = eaddr;
 
@@ -1193,14 +1199,8 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
 } else {
-/* Try to find a BAT */
-if (env->nb_BATs != 0) {
-ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
-}
-if (ret < 0) {
-/* We didn't match any BAT entry or don't have BATs */
-ret = get_segment_6xx_tlb(env, ctx, eaddr, access_type, type);
-}
+ret = mmu6xx_get_physical_address(env, ctx, eaddr, access_type,
+  type);
 }
 break;
 
-- 
2.30.9




[PATCH v2 07/28] target/ppc/mmu_common.c: Remove unneeded local variable

2024-05-01 Thread BALATON Zoltan
In mmubooke_check_tlb() and mmubooke206_check_tlb() we can assign the
value directly the the destination, no need to have a separate local
variable for it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 30 +-
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b0aca8ec02..74c3b814c9 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -627,8 +627,6 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
   hwaddr *raddr, int *prot, target_ulong address,
   MMUAccessType access_type, int i)
 {
-int prot2;
-
 if (!mmubooke_check_pid(env, tlb, raddr, address, i)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__);
 return -1;
@@ -643,17 +641,16 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 }
 
 if (FIELD_EX64(env->msr, MSR, PR)) {
-prot2 = tlb->prot & 0xF;
+*prot = tlb->prot & 0xF;
 } else {
-prot2 = (tlb->prot >> 4) & 0xF;
+*prot = (tlb->prot >> 4) & 0xF;
 }
-*prot = prot2;
-if (prot2 & prot_for_access_type(access_type)) {
+if (*prot & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
 return 0;
 }
 
-qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2);
+qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, *prot);
 return access_type == MMU_INST_FETCH ? -3 : -2;
 }
 
@@ -794,7 +791,6 @@ static int mmubooke206_check_tlb(CPUPPCState *env, 
ppcmas_tlb_t *tlb,
  target_ulong address,
  MMUAccessType access_type, int mmu_idx)
 {
-int prot2 = 0;
 uint32_t epid;
 bool as, pr;
 bool use_epid = mmubooke206_get_as(env, mmu_idx, , , );
@@ -840,34 +836,34 @@ found_tlb:
 return -1;
 }
 
+*prot = 0;
 if (pr) {
 if (tlb->mas7_3 & MAS3_UR) {
-prot2 |= PAGE_READ;
+*prot |= PAGE_READ;
 }
 if (tlb->mas7_3 & MAS3_UW) {
-prot2 |= PAGE_WRITE;
+*prot |= PAGE_WRITE;
 }
 if (tlb->mas7_3 & MAS3_UX) {
-prot2 |= PAGE_EXEC;
+*prot |= PAGE_EXEC;
 }
 } else {
 if (tlb->mas7_3 & MAS3_SR) {
-prot2 |= PAGE_READ;
+*prot |= PAGE_READ;
 }
 if (tlb->mas7_3 & MAS3_SW) {
-prot2 |= PAGE_WRITE;
+*prot |= PAGE_WRITE;
 }
 if (tlb->mas7_3 & MAS3_SX) {
-prot2 |= PAGE_EXEC;
+*prot |= PAGE_EXEC;
 }
 }
-*prot = prot2;
-if (prot2 & prot_for_access_type(access_type)) {
+if (*prot & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
 return 0;
 }
 
-qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2);
+qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, *prot);
 return access_type == MMU_INST_FETCH ? -3 : -2;
 }
 
-- 
2.30.9




[PATCH v2 05/28] target/ppc/mmu_common.c: Move calculation of a value closer to its usage

2024-05-01 Thread BALATON Zoltan
In mmubooke_check_tlb() prot2 is calculated first but only used after
an unrelated check that can return before tha value is used. Move the
calculation after the check, closer to where it is used, to keep them
together and avoid computing it when not needed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 751403f1c8..168ff842a5 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -634,12 +634,6 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return -1;
 }
 
-if (FIELD_EX64(env->msr, MSR, PR)) {
-prot2 = tlb->prot & 0xF;
-} else {
-prot2 = (tlb->prot >> 4) & 0xF;
-}
-
 /* Check the address space */
 if ((access_type == MMU_INST_FETCH ?
 FIELD_EX64(env->msr, MSR, IR) :
@@ -648,6 +642,11 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return -1;
 }
 
+if (FIELD_EX64(env->msr, MSR, PR)) {
+prot2 = tlb->prot & 0xF;
+} else {
+prot2 = (tlb->prot >> 4) & 0xF;
+}
 *prot = prot2;
 if (prot2 & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
-- 
2.30.9




[PATCH v2 04/28] target/ppc: Remove unused helper

2024-05-01 Thread BALATON Zoltan
The helper_rac function is defined but not used, remove it.

Fixes: 005b69fdcc (target/ppc: Remove PowerPC 601 CPUs)
Signed-off-by: BALATON Zoltan 
---
 target/ppc/helper.h |  2 --
 target/ppc/mmu_helper.c | 24 
 2 files changed, 26 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 86f97ee1e7..f769e01c3d 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -700,8 +700,6 @@ DEF_HELPER_2(book3s_msgclr, void, env, tl)
 
 DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
 #if !defined(CONFIG_USER_ONLY)
-DEF_HELPER_2(rac, tl, env, tl)
-
 DEF_HELPER_2(load_dcr, tl, env, tl)
 DEF_HELPER_3(store_dcr, void, env, tl, tl)
 #endif
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index c071b4d5e2..817836b731 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -595,30 +595,6 @@ void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
 do_6xx_tlb(env, EPN, 1);
 }
 
-/*/
-/* PowerPC 601 specific instructions (POWER bridge) */
-
-target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
-{
-mmu_ctx_t ctx;
-int nb_BATs;
-target_ulong ret = 0;
-
-/*
- * We don't have to generate many instances of this instruction,
- * as rac is supervisor only.
- *
- * XXX: FIX THIS: Pretend we have no BAT
- */
-nb_BATs = env->nb_BATs;
-env->nb_BATs = 0;
-if (get_physical_address_wtlb(env, , addr, 0, ACCESS_INT, 0) == 0) {
-ret = ctx.raddr;
-}
-env->nb_BATs = nb_BATs;
-return ret;
-}
-
 static inline target_ulong booke_tlb_to_page_size(int size)
 {
 return 1024 << (2 * size);
-- 
2.30.9




[PATCH v2 19/28] target/ppc/mmu_common.c: Replace hard coded constants in ppc_jumbo_xlate()

2024-05-01 Thread BALATON Zoltan
The "2" in booke206_update_mas_tlb_miss() call corresponds to
MMU_INST_FETCH which is the value of access_type in this branch;
mmubooke206_esr() only checks for MMU_DATA_STORE and it's called from
code access so using MMU_DATA_LOAD here seems wrong so replace it with
access_type here as well that yields the same result. This also makes
these calls the same as the data access branch further down.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 2487b4deff..762b13805b 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1288,13 +1288,13 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 break;
 case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
 /* fall through */
 case POWERPC_MMU_BOOKE:
 cs->exception_index = POWERPC_EXCP_ITLB;
 env->error_code = 0;
 env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
 break;
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
-- 
2.30.9




[PATCH v2 11/28] target/ppc/mmu_common.c: Rename get_bat_6xx_tlb()

2024-05-01 Thread BALATON Zoltan
Rename to ppc6xx_tlb_get_bat() to match other similar names in the
same file.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ef1669b01d..a069e4083f 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -288,8 +288,8 @@ static inline void bat_size_prot(CPUPPCState *env, 
target_ulong *blp,
 *protp = prot;
 }
 
-static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong virtual, MMUAccessType access_type)
+static int ppc6xx_tlb_get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
+  target_ulong virtual, MMUAccessType access_type)
 {
 target_ulong *BATlt, *BATut, *BATu, *BATl;
 target_ulong BEPIl, BEPIu, bl;
@@ -371,7 +371,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs != 0) {
-ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
+ret = ppc6xx_tlb_get_bat(env, ctx, eaddr, access_type);
 }
 if (ret >= 0) {
 return ret;
-- 
2.30.9




[PATCH v2 24/28] target/ppc/mmu_common.c: Remove BookE handling from get_physical_address_wtlb()

2024-05-01 Thread BALATON Zoltan
This function is no longer called for BookE MMU model so remove parts
related to it. This has uncovered a few may be used uninitialised
warnings that are also fixed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 25 +
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index a1f98f8de4..d61c41d8c9 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -684,12 +684,10 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 break;
 }
 }
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU,
   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
@@ -897,9 +895,6 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 goto found_tlb;
 }
 }
@@ -907,6 +902,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 
 found_tlb:
 
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
   HWADDR_FMT_plx " %d %d\n", __func__,
   ret < 0 ? "refused" : "granted", address, raddr,
@@ -1163,20 +1159,9 @@ static int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-bool real_mode;
-
-if (env->mmu_model == POWERPC_MMU_BOOKE) {
-return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
-} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
-return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-mmu_idx);
-}
-
-real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
-  : !FIELD_EX64(env->msr, MSR, DR);
-if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
-  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
-  env->mmu_model == POWERPC_MMU_REAL)) {
+bool real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode) {
 memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-- 
2.30.9




[PATCH v2 17/28] target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls

2024-05-01 Thread BALATON Zoltan
Fix several qemu_log_mask() calls that are misindented.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 42 -
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ebf18a751c..28847c32f2 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -297,8 +297,8 @@ static int ppc6xx_tlb_get_bat(CPUPPCState *env, mmu_ctx_t 
*ctx,
 int ret = -1;
 bool ifetch = access_type == MMU_INST_FETCH;
 
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
- ifetch ? 'I' : 'D', virtual);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
+  ifetch ? 'I' : 'D', virtual);
 if (ifetch) {
 BATlt = env->IBAT[1];
 BATut = env->IBAT[0];
@@ -312,9 +312,9 @@ static int ppc6xx_tlb_get_bat(CPUPPCState *env, mmu_ctx_t 
*ctx,
 BEPIu = *BATu & 0xF000;
 BEPIl = *BATu & 0x0FFE;
 bat_size_prot(env, , , , BATu, BATl);
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
-   TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
-   ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
+  TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
+  ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
 if ((virtual & 0xF000) == BEPIu &&
 ((virtual & 0x0FFE) & ~bl) == BEPIl) {
 /* BAT matches */
@@ -346,12 +346,11 @@ static int ppc6xx_tlb_get_bat(CPUPPCState *env, mmu_ctx_t 
*ctx,
 BEPIu = *BATu & 0xF000;
 BEPIl = *BATu & 0x0FFE;
 bl = (*BATu & 0x1FFC) << 15;
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v "
-   TARGET_FMT_lx " BATu " TARGET_FMT_lx
-   " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
-   TARGET_FMT_lx " " TARGET_FMT_lx "\n",
-   __func__, ifetch ? 'I' : 'D', i, virtual,
-   *BATu, *BATl, BEPIu, BEPIl, bl);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
+  " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
+  "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
+  TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
+  i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl);
 }
 }
 }
@@ -400,9 +399,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 hash = vsid ^ pgidx;
 ctx->ptem = (vsid << 7) | (pgidx >> 10);
 
-qemu_log_mask(CPU_LOG_MMU,
-"pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
-ctx->key, ds, ctx->nx, vsid);
+qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
+  TARGET_FMT_lx "\n", ctx->key, ds, ctx->nx, vsid);
 ret = -1;
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
@@ -599,9 +597,9 @@ static int mmu40x_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 return 0;
 }
 }
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx
-   " %d %d\n", __func__, address, raddr, ctx->prot, ret);
+qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
+  " => " HWADDR_FMT_plx " %d %d\n",
+  __func__, address, raddr, ctx->prot, ret);
 
 return ret;
 }
@@ -713,11 +711,11 @@ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, 
hwaddr *raddrp,
 }
 
 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
- qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
-   " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
-   HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
-   __func__, address, pid, tlb->mas1, tlb->mas2, mask,
-   tlb->mas7_3, tlb->mas8);
+qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
+  " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
+  HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
+  __func__, address, pid, tlb->mas1, tlb->mas2, mask,
+  tlb->mas7_3, tlb->mas8);
 
 /* Check PID */
 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
-- 
2.30.9




[PATCH v2 02/28] target/ppc: Move patching nip from exception handler to helper_scv

2024-05-01 Thread BALATON Zoltan
From: Nicholas Piggin 

Unlike sc, for scv a facility unavailable interrupt must be generated
if FSCR[SCV]=0 so we can't raise the exception with nip set to next
instruction but we can move advancing nip if the FSCR check passes to
helper_scv so the exception handler does not need to change it.

[balaton: added commit message]
Signed-off-by: BALATON Zoltan 
---
 target/ppc/excp_helper.c | 2 +-
 target/ppc/translate.c   | 6 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 92fe535815..5aa84bccd2 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1415,7 +1415,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
 lev = env->error_code;
 dump_syscall(env);
-env->nip += 4;
 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
 
@@ -2524,6 +2523,7 @@ void helper_ppc_maybe_interrupt(CPUPPCState *env)
 void helper_scv(CPUPPCState *env, uint32_t lev)
 {
 if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
+env->nip += 4;
 raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
 } else {
 raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index e112c44a02..1d4e9f0679 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4493,7 +4493,11 @@ static void gen_scv(DisasContext *ctx)
 {
 uint32_t lev = (ctx->opcode >> 5) & 0x7F;
 
-/* Set the PC back to the faulting instruction. */
+/*
+ * Set the PC back to the scv instruction (unlike sc), because a facility
+ * unavailable interrupt must be generated if FSCR[SCV]=0. The helper
+ * advances nip if the FSCR check passes.
+ */
 gen_update_nip(ctx, ctx->cia);
 gen_helper_scv(tcg_env, tcg_constant_i32(lev));
 
-- 
2.30.9




[PATCH v2 13/28] target/ppc/mmu_common.c: Split off real mode cases in get_physical_address_wtlb()

2024-05-01 Thread BALATON Zoltan
The real mode handling is identical in the remaining switch cases.
Split off these common real mode cases into a separate conditional to
leave only the else branches in the switch that are different.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 34 +-
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 24a9b9ef19..3132030baa 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1188,7 +1188,6 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-int ret = -1;
 bool real_mode;
 
 if (env->mmu_model == POWERPC_MMU_BOOKE) {
@@ -1200,38 +1199,23 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
+  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
+  env->mmu_model == POWERPC_MMU_REAL)) {
+return check_physical(env, ctx, eaddr, access_type);
+}
 
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-ret = mmu6xx_get_physical_address(env, ctx, eaddr, access_type,
-  type);
-}
-break;
-
+return mmu6xx_get_physical_address(env, ctx, eaddr, access_type, type);
 case POWERPC_MMU_SOFT_4xx:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
-}
-break;
+return mmu40x_get_physical_address(env, ctx, eaddr, access_type);
 case POWERPC_MMU_REAL:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-cpu_abort(env_cpu(env),
-  "PowerPC in real mode do not do any translation\n");
-}
-return -1;
+cpu_abort(env_cpu(env),
+  "PowerPC in real mode do not do any translation\n");
 default:
 cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
-return -1;
 }
-
-return ret;
 }
 
 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
-- 
2.30.9




[PATCH v2 16/28] target/ppc/mmu_common.c: Simplify mmubooke206_get_physical_address()

2024-05-01 Thread BALATON Zoltan
This function is similar to mmubooke_get_physical_address() and can be
simplified the same way.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 28 ++--
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 760e4072b2..ebf18a751c 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -872,15 +872,11 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 int mmu_idx)
 {
 ppcmas_tlb_t *tlb;
-hwaddr raddr;
-int i, j, ret;
-
-ret = -1;
-raddr = (hwaddr)-1ULL;
+hwaddr raddr = (hwaddr)-1ULL;
+int i, j, ways, ret = -1;
 
 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
-int ways = booke206_tlb_ways(env, i);
-
+ways = booke206_tlb_ways(env, i);
 for (j = 0; j < ways; j++) {
 tlb = booke206_get_tlbm(env, i, address, j);
 if (!tlb) {
@@ -889,6 +885,9 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
+if (ret >= 0) {
+ctx->raddr = raddr;
+}
 goto found_tlb;
 }
 }
@@ -896,17 +895,10 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 
 found_tlb:
 
-if (ret >= 0) {
-ctx->raddr = raddr;
- qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
-   ctx->raddr, ctx->prot, ret);
-} else {
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
-   raddr, ctx->prot, ret);
-}
-
+qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
+  HWADDR_FMT_plx " %d %d\n", __func__,
+  ret < 0 ? "refused" : "granted", address, raddr,
+  ctx->prot, ret);
 return ret;
 }
 
-- 
2.30.9




[PATCH v2 27/28] target/ppc: Remove id_tlbs flag from CPU env

2024-05-01 Thread BALATON Zoltan
This flag for split instruction/data TLBs is only set for 6xx soft TLB
MMU model and not used otherwise so no need to have a separate flag
for that.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/pegasos2.c|  2 +-
 target/ppc/cpu.h |  1 -
 target/ppc/cpu_init.c| 19 +--
 target/ppc/helper_regs.c |  1 -
 target/ppc/mmu_common.c  | 10 ++
 target/ppc/mmu_helper.c  | 12 ++--
 6 files changed, 10 insertions(+), 35 deletions(-)

diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 04d6decb2b..dfc6fab180 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -984,7 +984,7 @@ static void *build_fdt(MachineState *machine, int *fdt_size)
   cpu->env.icache_line_size);
 qemu_fdt_setprop_cell(fdt, cp, "i-cache-line-size",
   cpu->env.icache_line_size);
-if (cpu->env.id_tlbs) {
+if (cpu->env.tlb_type == TLB_6XX) {
 qemu_fdt_setprop_cell(fdt, cp, "i-tlb-sets", cpu->env.nb_ways);
 qemu_fdt_setprop_cell(fdt, cp, "i-tlb-size", cpu->env.tlb_per_way);
 qemu_fdt_setprop_cell(fdt, cp, "d-tlb-sets", cpu->env.nb_ways);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 0ac55d6b25..21e12a4f0d 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1260,7 +1260,6 @@ struct CPUArchState {
 int tlb_per_way; /* Speed-up helper: used to avoid divisions at run time */
 int nb_ways; /* Number of ways in the TLB set */
 int last_way;/* Last used way used to allocate TLB in a LRU way */
-int id_tlbs; /* If 1, MMU has separated TLBs for instructions & data */
 int nb_pids; /* Number of available PID registers */
 int tlb_type;/* Type of TLB we're dealing with */
 ppc_tlb_t tlb;   /* TLB is optional. Allocate them only if needed */
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index c11a69fd90..07ad788e54 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -2117,7 +2117,6 @@ static void init_proc_405(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_4xx(env);
@@ -2190,7 +2189,6 @@ static void init_proc_440EP(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2288,7 +2286,6 @@ static void init_proc_440GP(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2362,7 +2359,6 @@ static void init_proc_440x5(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_BookE(env);
@@ -2724,7 +2720,6 @@ static void init_proc_e200(CPUPPCState *env)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = 64;
 env->nb_ways = 1;
-env->id_tlbs = 0;
 env->tlb_type = TLB_EMB;
 #endif
 init_excp_e200(env, 0xUL);
@@ -2843,7 +2838,6 @@ static void init_proc_e500(CPUPPCState *env, int version)
 /* Memory management */
 env->nb_pids = 3;
 env->nb_ways = 2;
-env->id_tlbs = 0;
 switch (version) {
 case fsl_e500v1:
 tlbncfg[0] = register_tlbncfg(2, 1, 1, 0, 256);
@@ -6800,20 +6794,17 @@ static void init_ppc_proc(PowerPCCPU *cpu)
 }
 /* Allocate TLBs buffer when needed */
 #if !defined(CONFIG_USER_ONLY)
-if (env->nb_tlb != 0) {
-int nb_tlb = env->nb_tlb;
-if (env->id_tlbs != 0) {
-nb_tlb *= 2;
-}
+if (env->nb_tlb) {
 switch (env->tlb_type) {
 case TLB_6XX:
-env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, nb_tlb);
+/* 6xx has separate TLBs for instructions and data hence times 2 */
+env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, 2 * env->nb_tlb);
 break;
 case TLB_EMB:
-env->tlb.tlbe = g_new0(ppcemb_tlb_t, nb_tlb);
+env->tlb.tlbe = g_new0(ppcemb_tlb_t, env->nb_tlb);
 break;
 case TLB_MAS:
-env->tlb.tlbm = g_new0(ppcmas_tlb_t, nb_tlb);
+env->tlb.tlbm = g_new0(ppcmas_tlb_t, env->nb_tlb);
 break;
 }
 /* Pre-compute some useful values */
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 25258986e3..ed583fe9b3 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -693,7 +693,6 @@ void register_6xx_7xx_soft_tlb(CPUPPCState *env, int 
nb_tlbs, int nb_ways)
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = nb_tlbs;
 env->nb_ways = nb_ways;
-env->id_tlbs = 1;
 env->tlb_type = TLB_6XX;

[PATCH v2 14/28] target/ppc/mmu_common.c: Inline and remove check_physical()

2024-05-01 Thread BALATON Zoltan
This function just does two assignments and and unnecessary check that
is always true so inline it in the only caller left and remove it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 26 +++---
 1 file changed, 3 insertions(+), 23 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 3132030baa..fab86a8f3e 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1161,28 +1161,6 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-static int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
-  MMUAccessType access_type)
-{
-ctx->raddr = eaddr;
-ctx->prot = PAGE_READ | PAGE_EXEC;
-
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-case POWERPC_MMU_SOFT_4xx:
-case POWERPC_MMU_REAL:
-case POWERPC_MMU_BOOKE:
-ctx->prot |= PAGE_WRITE;
-break;
-
-default:
-/* Caller's checks mean we should never get here for other models */
-g_assert_not_reached();
-}
-
-return 0;
-}
-
 int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
@@ -1202,7 +1180,9 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
   env->mmu_model == POWERPC_MMU_SOFT_4xx ||
   env->mmu_model == POWERPC_MMU_REAL)) {
-return check_physical(env, ctx, eaddr, access_type);
+ctx->raddr = eaddr;
+ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+return 0;
 }
 
 switch (env->mmu_model) {
-- 
2.30.9




[PATCH v2 08/28] target/ppc/mmu_common.c: Simplify checking for real mode

2024-05-01 Thread BALATON Zoltan
In get_physical_address_wtlb() the real_mode flag depends on either
the MSR[IR] or MSR[DR] bit depending on access_type. Extract just the
needed bit in a more straight forward way instead of doing unnecessary
computation.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 74c3b814c9..45b6501ecb 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1183,8 +1183,10 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  int mmu_idx)
 {
 int ret = -1;
-bool real_mode = (type == ACCESS_CODE && !FIELD_EX64(env->msr, MSR, IR)) ||
- (type != ACCESS_CODE && !FIELD_EX64(env->msr, MSR, DR));
+bool real_mode;
+
+real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+  : !FIELD_EX64(env->msr, MSR, DR);
 
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
-- 
2.30.9




[PATCH v2 06/28] target/ppc/mmu_common.c: Move calculation of a value closer to its usage

2024-05-01 Thread BALATON Zoltan
In mmubooke206_check_tlb() prot2 is calculated first but only used
after an unrelated check that can return before tha value is used.
Move the calculation after the check, closer to where it is used, to
keep them together and avoid computing it when not needed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 25 -
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 168ff842a5..b0aca8ec02 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -828,6 +828,18 @@ static int mmubooke206_check_tlb(CPUPPCState *env, 
ppcmas_tlb_t *tlb,
 
 found_tlb:
 
+/* Check the address space and permissions */
+if (access_type == MMU_INST_FETCH) {
+/* There is no way to fetch code using epid load */
+assert(!use_epid);
+as = FIELD_EX64(env->msr, MSR, IR);
+}
+
+if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
+qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
+return -1;
+}
+
 if (pr) {
 if (tlb->mas7_3 & MAS3_UR) {
 prot2 |= PAGE_READ;
@@ -849,19 +861,6 @@ found_tlb:
 prot2 |= PAGE_EXEC;
 }
 }
-
-/* Check the address space and permissions */
-if (access_type == MMU_INST_FETCH) {
-/* There is no way to fetch code using epid load */
-assert(!use_epid);
-as = FIELD_EX64(env->msr, MSR, IR);
-}
-
-if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
-qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__);
-return -1;
-}
-
 *prot = prot2;
 if (prot2 & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
-- 
2.30.9




[PATCH v2 15/28] target/ppc/mmu_common.c: Simplify mmubooke_get_physical_address()

2024-05-01 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 25 +
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index fab86a8f3e..760e4072b2 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -665,31 +665,24 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
  MMUAccessType access_type)
 {
 ppcemb_tlb_t *tlb;
-hwaddr raddr;
-int i, ret;
+hwaddr raddr = (hwaddr)-1ULL;
+int i, ret = -1;
 
-ret = -1;
-raddr = (hwaddr)-1ULL;
 for (i = 0; i < env->nb_tlb; i++) {
 tlb = >tlb.tlbe[i];
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
+if (ret >= 0) {
+ctx->raddr = raddr;
+}
 break;
 }
 }
-
-if (ret >= 0) {
-ctx->raddr = raddr;
-qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-  " => " HWADDR_FMT_plx " %d %d\n", __func__,
-  address, ctx->raddr, ctx->prot, ret);
-} else {
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__,
-   address, raddr, ctx->prot, ret);
-}
-
+qemu_log_mask(CPU_LOG_MMU,
+  "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
+  " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
+  address, raddr, ctx->prot, ret);
 return ret;
 }
 
-- 
2.30.9




[PATCH v2 23/28] target/ppc/mmu_common.c: Split off BookE handling from ppc_jumbo_xlate()

2024-05-01 Thread BALATON Zoltan
Introduce ppc_booke_xlate() to handle BookE and BookE 2.06 cases to
reduce ppc_jumbo_xlate() further.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 180 ++--
 1 file changed, 138 insertions(+), 42 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 0ce5c1e841..a1f98f8de4 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1250,6 +1250,137 @@ static void booke206_update_mas_tlb_miss(CPUPPCState 
*env, target_ulong address,
 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
 }
 
+static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
+MMUAccessType access_type,
+hwaddr *raddrp, int *psizep, int *protp,
+int mmu_idx, bool guest_visible)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+mmu_ctx_t ctx;
+int ret;
+
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+ret = mmubooke206_get_physical_address(env, , eaddr, access_type,
+   mmu_idx);
+} else {
+ret = mmubooke_get_physical_address(env, , eaddr, access_type);
+}
+if (ret == 0) {
+*raddrp = ctx.raddr;
+*protp = ctx.prot;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (access_type == MMU_INST_FETCH) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->error_code = 0;
+break;
+case -3:
+/* No execute protection violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->spr[SPR_BOOKE_ESR] = 0;
+env->error_code = 0;
+break;
+case -4:
+/* Direct store exception */
+/* No code fetch is allowed in direct-store areas */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->error_code = 0;
+break;
+}
+} else {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -4:
+/* Direct store exception */
+switch (env->access_type) {
+case ACCESS_FLOAT:
+/* Floating point load/store */
+cs->exception_index = POWERPC_EXCP_ALIGN;
+env->error_code = POWERPC_EXCP_ALIGN_FP;
+env->spr[SPR_DAR] = eaddr;
+break;
+case ACCESS_RES:
+/* lwarx, ldarx or stwcx. */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_DAR] = eaddr;
+if (access_type == MMU_DATA_STORE) {
+env->spr[SPR_DSISR] = 0x0600;
+} else {
+env->spr[SPR_DSISR] = 0x0400;
+}
+break;
+case ACCESS_EXT:
+/* eciwx or ecowx */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_DAR] = eaddr;
+if (access_type == MMU_DATA_ST

[PATCH v2 00/28] Misc PPC exception and BookE MMU clean ups

2024-05-01 Thread BALATON Zoltan
This series does some further clean up mostly around BookE MMU to
untangle it from other MMU models. It also contains some other changes
that I've come up with while working on this. The first 3 patches are
from the last exception handling clean up series that were dropped due
to some error on CI but I'm not sure if that was because of some CI
infrastructure problem or some problem with the patches as the error
did not make much sense. So these patches are only rebased now, I made
no other change to them until the issue is understood better. The rest
are new patches I've added since tha last series. Please review.

v2:
- Fix user mode issue in patch 1 by keeping old behaviour for user mode
- Add some more MMU clean up patches

Regards,
BALATON Zoltan

BALATON Zoltan (28):
  target/ppc: Fix gen_sc to use correct nip
  target/ppc: Move patching nip from exception handler to helper_scv
  target/ppc: Simplify syscall exception handlers
  target/ppc: Remove unused helper
  target/ppc/mmu_common.c: Move calculation of a value closer to its
usage
  target/ppc/mmu_common.c: Move calculation of a value closer to its
usage
  target/ppc/mmu_common.c: Remove unneeded local variable
  target/ppc/mmu_common.c: Simplify checking for real mode
  target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU
  target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()
  target/ppc/mmu_common.c: Rename get_bat_6xx_tlb()
  target/ppc/mmu_common.c: Split out BookE cases before checking real
mode
  target/ppc/mmu_common.c: Split off real mode cases in
get_physical_address_wtlb()
  target/ppc/mmu_common.c: Inline and remove check_physical()
  target/ppc/mmu_common.c: Simplify mmubooke_get_physical_address()
  target/ppc/mmu_common.c: Simplify mmubooke206_get_physical_address()
  target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls
  target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Replace hard coded constants in
ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Make get_physical_address_wtlb() static
  target/ppc: Move mmu_ctx_t definition to mmu_common.c
  target/ppc: Remove ppc_hash32_pp_prot() and reuse common function
  target/ppc/mmu_common.c: Split off BookE handling from
ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Remove BookE handling from
get_physical_address_wtlb()
  target/ppc/mmu_common.c: Simplify ppc_booke_xlate()
  target/ppc/mmu_common.c: Move BookE MMU functions together
  target/ppc: Remove id_tlbs flag from CPU env
  target/ppc: Split off common 4xx TLB init

 hw/ppc/pegasos2.c|   2 +-
 target/ppc/cpu.h |   1 -
 target/ppc/cpu_init.c|  65 ++--
 target/ppc/excp_helper.c |  67 +---
 target/ppc/helper.h  |   2 -
 target/ppc/helper_regs.c |   1 -
 target/ppc/internal.h|  19 +-
 target/ppc/mmu-hash32.c  |  47 +--
 target/ppc/mmu_common.c  | 792 +++
 target/ppc/mmu_helper.c  |  36 +-
 target/ppc/translate.c   |  21 +-
 11 files changed, 438 insertions(+), 615 deletions(-)

-- 
2.30.9




[PATCH v2 09/28] target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU

2024-05-01 Thread BALATON Zoltan
The default case will catch this and abort the same way and there is
still a warning about it in ppc_tlb_invalidate_all() so drop these
from mmu_common.c to simplify this code.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 45b6501ecb..98730035b1 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1218,10 +1218,6 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
mmu_idx);
 break;
-case POWERPC_MMU_MPC8xx:
-/* XXX: TODO */
-cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
-break;
 case POWERPC_MMU_REAL:
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
@@ -1352,8 +1348,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_BOOKE_DEAR] = eaddr;
 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
 break;
-case POWERPC_MMU_MPC8xx:
-cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
   "any MMU exceptions\n");
@@ -1426,9 +1420,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 }
 break;
-case POWERPC_MMU_MPC8xx:
-/* XXX: TODO */
-cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
 case POWERPC_MMU_BOOKE206:
 booke206_update_mas_tlb_miss(env, eaddr, access_type, 
mmu_idx);
 /* fall through */
-- 
2.30.9




[PATCH v2 25/28] target/ppc/mmu_common.c: Simplify ppc_booke_xlate()

2024-05-01 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 147 +++-
 1 file changed, 56 insertions(+), 91 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index d61c41d8c9..b76611da80 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1261,106 +1261,71 @@ static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 }
 
 log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+env->error_code = 0;
+if (env->mmu_model == POWERPC_MMU_BOOKE206 && ret == -1) {
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+}
 if (access_type == MMU_INST_FETCH) {
-switch (ret) {
-case -1:
+if (ret == -1) {
 /* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
-default:
-g_assert_not_reached();
-}
-break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-env->error_code = 0;
-break;
-case -3:
-/* No execute protection violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-env->spr[SPR_BOOKE_ESR] = 0;
-env->error_code = 0;
-break;
-case -4:
-/* Direct store exception */
-/* No code fetch is allowed in direct-store areas */
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+} else {
 cs->exception_index = POWERPC_EXCP_ISI;
-env->error_code = 0;
-break;
-}
-} else {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_DTLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
-default:
-g_assert_not_reached();
+if (ret == -3) {
+/* No execute protection violation */
+env->spr[SPR_BOOKE_ESR] = 0;
 }
+}
+return false;
+}
+
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -4:
+/* Direct store exception */
+env->spr[SPR_DAR] = eaddr;
+switch (env->access_type) {
+case ACCESS_FLOAT:
+/* Floating point load/store */
+cs->exception_index = POWERPC_EXCP_ALIGN;
+env->error_code = POWERPC_EXCP_ALIGN_FP;
 break;
-case -2:
-/* Access rights violation */
+case ACCESS_RES:
+/* lwarx, ldarx or stwcx. */
 cs->exception_index = POWERPC_EXCP_DSI;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+if (access_type == MMU_DATA_STORE) {
+env->spr[SPR_DSISR] = 0x0600;
+} else {
+env->spr[SPR_DSISR] = 0x0400;
+}
 break;
-case -4:
-/* Direct store exception */
-switch (env->access_type) {
-case ACCESS_FLOAT:
-/* Floating point load/store */
-cs->exception_index = POWERPC_EXCP_ALIGN;
-env->error_code = POWERPC_EXCP_ALIGN_FP;
-env->spr[SPR_DAR] = eaddr;
-break;
-case ACCESS_RES:
-/* lwarx, ldarx or s

[PATCH v2 20/28] target/ppc/mmu_common.c: Make get_physical_address_wtlb() static

2024-05-01 Thread BALATON Zoltan
This function is not used from any other files so make it static and
fix the maybe used uninitialised warnings this has uncovered.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 5 +
 target/ppc/mmu_common.c | 5 -
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 601c0b533f..7a99f08dc8 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -261,10 +261,7 @@ typedef struct mmu_ctx_t mmu_ctx_t;
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
- target_ulong eaddr,
- MMUAccessType access_type, int type,
- int mmu_idx);
+
 /* Software driven TLB helpers */
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 762b13805b..4852cb5571 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -666,6 +666,7 @@ static int mmubooke_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 hwaddr raddr = (hwaddr)-1ULL;
 int i, ret = -1;
 
+ctx->prot = 0;
 for (i = 0; i < env->nb_tlb; i++) {
 tlb = >tlb.tlbe[i];
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
@@ -873,6 +874,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 hwaddr raddr = (hwaddr)-1ULL;
 int i, j, ways, ret = -1;
 
+ctx->prot = 0;
 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
 ways = booke206_tlb_ways(env, i);
 for (j = 0; j < ways; j++) {
@@ -1144,7 +1146,7 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
+static int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
  int mmu_idx)
@@ -1163,6 +1165,7 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
   env->mmu_model == POWERPC_MMU_SOFT_4xx ||
   env->mmu_model == POWERPC_MMU_REAL)) {
+memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 return 0;
-- 
2.30.9




[PATCH v2 22/28] target/ppc: Remove ppc_hash32_pp_prot() and reuse common function

2024-05-01 Thread BALATON Zoltan
The ppc_hash32_pp_prot() function in mmu-hash32.c is the same as
pp_check() in mmu_common.c. Rename the latter to ppc_pte_prot() and
merge with ppc_hash32_pp_prot() to remove duplicated code.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   |  2 +-
 target/ppc/mmu-hash32.c | 47 +
 target/ppc/mmu_common.c | 19 +
 3 files changed, 12 insertions(+), 56 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 61c2aadd0d..d7c923b017 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -255,7 +255,7 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 #ifndef CONFIG_USER_ONLY
 
 /* PowerPC MMU emulation */
-
+int ppc_pte_prot(int key, int pp, int nx);
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 3976416840..ee9df351ae 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -42,51 +42,6 @@ struct mmu_ctx_hash32 {
 int key;   /* Access key*/
 };
 
-static int ppc_hash32_pp_prot(int key, int pp, int nx)
-{
-int prot;
-
-if (key == 0) {
-switch (pp) {
-case 0x0:
-case 0x1:
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-case 0x3:
-prot = PAGE_READ;
-break;
-
-default:
-abort();
-}
-} else {
-switch (pp) {
-case 0x0:
-prot = 0;
-break;
-
-case 0x1:
-case 0x3:
-prot = PAGE_READ;
-break;
-
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-default:
-abort();
-}
-}
-if (nx == 0) {
-prot |= PAGE_EXEC;
-}
-
-return prot;
-}
-
 static int ppc_hash32_pte_prot(int mmu_idx,
target_ulong sr, ppc_hash_pte32_t pte)
 {
@@ -95,7 +50,7 @@ static int ppc_hash32_pte_prot(int mmu_idx,
 key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS));
 pp = pte.pte1 & HPTE32_R_PP;
 
-return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
+return ppc_pte_prot(key, pp, !!(sr & SR32_NX));
 }
 
 static target_ulong hash32_bat_size(int mmu_idx,
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 41ef174ab4..0ce5c1e841 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -75,22 +75,23 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 /*/
 /* PowerPC MMU emulation */
 
-static int pp_check(int key, int pp, int nx)
+int ppc_pte_prot(int key, int pp, int nx)
 {
 int access;
 
 /* Compute access rights */
-access = 0;
 if (key == 0) {
 switch (pp) {
 case 0x0:
 case 0x1:
 case 0x2:
-access |= PAGE_WRITE;
-/* fall through */
+access = PAGE_READ | PAGE_WRITE;
+break;
 case 0x3:
-access |= PAGE_READ;
+access = PAGE_READ;
 break;
+default:
+g_assert_not_reached();
 }
 } else {
 switch (pp) {
@@ -104,6 +105,8 @@ static int pp_check(int key, int pp, int nx)
 case 0x2:
 access = PAGE_READ | PAGE_WRITE;
 break;
+default:
+g_assert_not_reached();
 }
 }
 if (nx == 0) {
@@ -140,7 +143,7 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 MMUAccessType access_type)
 {
 target_ulong ptem, mmask;
-int access, ret, pteh, ptev, pp;
+int ret, pteh, ptev, pp;
 
 ret = -1;
 /* Check validity and table match */
@@ -159,11 +162,9 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 return -3;
 }
 }
-/* Compute access rights */
-access = pp_check(ctx->key, pp, ctx->nx);
 /* Keep the matching PTE information */
 ctx->raddr = pte1;
-ctx->prot = access;
+ctx->prot = ppc_pte_prot(ctx->key, pp, ctx->nx);
 ret = check_prot(ctx->prot, access_type);
 if (ret == 0) {
 /* Access granted */
-- 
2.30.9




[PATCH v2 21/28] target/ppc: Move mmu_ctx_t definition to mmu_common.c

2024-05-01 Thread BALATON Zoltan
This type is only used within mmu_common.c. Move its definition from
internal.h to there.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 12 
 target/ppc/mmu_common.c | 11 +++
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 7a99f08dc8..61c2aadd0d 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -256,8 +256,6 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 
 /* PowerPC MMU emulation */
 
-typedef struct mmu_ctx_t mmu_ctx_t;
-
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
@@ -265,16 +263,6 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType 
access_type,
 /* Software driven TLB helpers */
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
-/* Context used internally during MMU translations */
-struct mmu_ctx_t {
-hwaddr raddr;  /* Real address  */
-hwaddr eaddr;  /* Effective address */
-int prot;  /* Protection bits   */
-hwaddr hash[2];/* Pagetable hash values */
-target_ulong ptem; /* Virtual segment ID | API  */
-int key;   /* Access key*/
-int nx;/* Non-execute area  */
-};
 
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 4852cb5571..41ef174ab4 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -35,6 +35,17 @@
 
 /* #define DUMP_PAGE_TABLES */
 
+/* Context used internally during MMU translations */
+typedef struct {
+hwaddr raddr;  /* Real address */
+hwaddr eaddr;  /* Effective address*/
+int prot;  /* Protection bits  */
+hwaddr hash[2];/* Pagetable hash values*/
+target_ulong ptem; /* Virtual segment ID | API */
+int key;   /* Access key   */
+int nx;/* Non-execute area */
+} mmu_ctx_t;
+
 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 {
 PowerPCCPU *cpu = env_archcpu(env);
-- 
2.30.9




[PATCH v2 12/28] target/ppc/mmu_common.c: Split out BookE cases before checking real mode

2024-05-01 Thread BALATON Zoltan
BookE does not have real mode so split off and handle it first in
get_physical_address_wtlb() before checking for real mode for other
MMU models.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index a069e4083f..24a9b9ef19 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1191,6 +1191,13 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 int ret = -1;
 bool real_mode;
 
+if (env->mmu_model == POWERPC_MMU_BOOKE) {
+return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
+} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
+mmu_idx);
+}
+
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
   : !FIELD_EX64(env->msr, MSR, DR);
 
@@ -1211,13 +1218,6 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
 }
 break;
-case POWERPC_MMU_BOOKE:
-ret = mmubooke_get_physical_address(env, ctx, eaddr, access_type);
-break;
-case POWERPC_MMU_BOOKE206:
-ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-   mmu_idx);
-break;
 case POWERPC_MMU_REAL:
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
-- 
2.30.9




[PATCH v2 03/28] target/ppc: Simplify syscall exception handlers

2024-05-01 Thread BALATON Zoltan
After previous changes the hypercall handling in 7xx and 74xx
exception handlers can be folded into one if statement to simplify
this code. Also add "unlikely" to mark the less frequently used branch
for the compiler.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Harsh Prateek Bora 
---
 target/ppc/excp_helper.c | 22 ++
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 5aa84bccd2..d19212f772 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -762,26 +762,21 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 {
 int lev = env->error_code;
-
-if (lev == 1 && cpu->vhyp) {
-dump_hcall(env);
-} else {
-dump_syscall(env);
-}
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
  * uses VOF and the 7xx CPUs, so although the 7xx don't have
  * HV mode, we need to keep hypercall support.
  */
-if (lev == 1 && cpu->vhyp) {
+if (unlikely(lev == 1 && cpu->vhyp)) {
 PPCVirtualHypervisorClass *vhc =
 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+dump_hcall(env);
 vhc->hypercall(cpu->vhyp, cpu);
 powerpc_reset_excp_state(cpu);
 return;
 }
-
+dump_syscall(env);
 break;
 }
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
@@ -907,26 +902,21 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 {
 int lev = env->error_code;
-
-if (lev == 1 && cpu->vhyp) {
-dump_hcall(env);
-} else {
-dump_syscall(env);
-}
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
  * uses VOF and the 74xx CPUs, so although the 74xx don't have
  * HV mode, we need to keep hypercall support.
  */
-if (lev == 1 && cpu->vhyp) {
+if (unlikely(lev == 1 && cpu->vhyp)) {
 PPCVirtualHypervisorClass *vhc =
 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+dump_hcall(env);
 vhc->hypercall(cpu->vhyp, cpu);
 powerpc_reset_excp_state(cpu);
 return;
 }
-
+dump_syscall(env);
 break;
 }
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
-- 
2.30.9




Re: [PATCH v2 1/2] net: Provide MemReentrancyGuard * to qemu_new_nic()

2024-04-26 Thread BALATON Zoltan

On Fri, 26 Apr 2024, Philippe Mathieu-Daudé wrote:

On 26/4/24 14:37, Akihiko Odaki wrote:

On 2024/04/24 21:32, Thomas Huth wrote:

On 24/04/2024 12.41, Prasad Pandit wrote:
On Wednesday, 24 April, 2024 at 03:36:01 pm IST, Philippe Mathieu-Daudé 
wrote:

On 1/6/23 05:18, Akihiko Odaki wrote:

Recently MemReentrancyGuard was added to DeviceState to record that the
device is engaging in I/O. The network device backend needs to update 
it

when delivering a packet to a device.
In preparation for such a change, add MemReentrancyGuard * as a
parameter of qemu_new_nic().


An user on IRC asked if this patch is related/fixing CVE-2021-20255,
any clue?


* CVE-2021-20255 bug: infinite recursion is pointing at a different fix 
patch.

   -> https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2021-20255

* And the this patch below has different issue tagged
-> https://lists.nongnu.org/archive/html/qemu-devel/2023-05/msg08312.html
   Fixes: CVE-2023-3019


* They look different, former is an infinite recursion issue and the 
latter is a use-after-free one.


I assume the eepro reentrancy issue has been fixed with:

  https://gitlab.com/qemu-project/qemu/-/issues/556
  i.e.:
  https://gitlab.com/qemu-project/qemu/-/commit/c40ca2301c7603524eaddb5308a3


I agree. Commit c40ca2301c7603524eaddb5308a3 should be what fixed 
CVE-2021-20255, not this patch.


Thank you all for clarifying!


$ git log -p c40ca2301c7603524eaddb5308a3 --
fatal: bad revision 'c40ca2301c7603524eaddb5308a3'

It seems to actually be commit a2e1753b8054344f32cf94f31c6399a58794a380

Regards,
BALATON Zoltan

Re: [PATCH-for-9.1 05/21] target/m68k: Replace qemu_printf() by monitor_printf() in monitor

2024-04-24 Thread BALATON Zoltan

On Wed, 24 Apr 2024, BALATON Zoltan wrote:

On Wed, 24 Apr 2024, Markus Armbruster wrote:

Philippe Mathieu-Daudé  writes:


Replace qemu_printf() by monitor_printf() / monitor_puts() in monitor.


Why?  Here's my attempt at an answer: because this runs only within HMP
command "info tlb".  Using qemu_printf() there isn't wrong, but with
monitor_printf(), it's obvious that we print to the monitor.

On monitor_printf() vs. monitor_puts().

qemu_printf() behaves like monitor_printf() when monitor_cur() returns
non-null, which it certainly does within a monitor command.

monitor_printf() prints like monitor_puts() when monitor_is_qmp()
returns false, which it certainly does within an HMP command.

Note: despite their names, monitor_printf() and monitor_puts() are at
different interface layers!

We need a low-level function to send to a monitor, be it HMP or QMP:
monitor_puts().

We need a high-level function to format JSON and send it to QMP:
qmp_send_response().

We need a high-level functions to format text and send it to HMP:
monitor_printf(), ...

Naming the functions that expect an HMP monitor hmp_FOO() would make
more sense.  Renaming them now would be quite some churn, though.
Discussed at
<https://lore.kernel.org/qemu-devel/87y1adm0os@pond.sub.org/>.


The hmp_ prefix is more cryptic than monitor_. Without knowing QEMU too much 
I can guess what monitor_ does but would have to look up what hmp_means so 
keeping monitor_ is better IMO. The solution to the naming issue mentioned 
above may be renaming monitor_puts to something that tells it's a low level 
function (and add a momitor_puts that behaves as expected) but I can't come 
up with a name either. Maybe the low level function could be called hmp_putt?


Meant hmp_puts.


Or add a comment near monitor_puts to explain this for now.
Regards,
BALATON Zoltan

Re: [PATCH-for-9.1 05/21] target/m68k: Replace qemu_printf() by monitor_printf() in monitor

2024-04-24 Thread BALATON Zoltan

On Wed, 24 Apr 2024, Markus Armbruster wrote:

Philippe Mathieu-Daudé  writes:


Replace qemu_printf() by monitor_printf() / monitor_puts() in monitor.


Why?  Here's my attempt at an answer: because this runs only within HMP
command "info tlb".  Using qemu_printf() there isn't wrong, but with
monitor_printf(), it's obvious that we print to the monitor.

On monitor_printf() vs. monitor_puts().

qemu_printf() behaves like monitor_printf() when monitor_cur() returns
non-null, which it certainly does within a monitor command.

monitor_printf() prints like monitor_puts() when monitor_is_qmp()
returns false, which it certainly does within an HMP command.

Note: despite their names, monitor_printf() and monitor_puts() are at
different interface layers!

We need a low-level function to send to a monitor, be it HMP or QMP:
monitor_puts().

We need a high-level function to format JSON and send it to QMP:
qmp_send_response().

We need a high-level functions to format text and send it to HMP:
monitor_printf(), ...

Naming the functions that expect an HMP monitor hmp_FOO() would make
more sense.  Renaming them now would be quite some churn, though.
Discussed at
<https://lore.kernel.org/qemu-devel/87y1adm0os@pond.sub.org/>.


The hmp_ prefix is more cryptic than monitor_. Without knowing QEMU too 
much I can guess what monitor_ does but would have to look up what 
hmp_means so keeping monitor_ is better IMO. The solution to the naming 
issue mentioned above may be renaming monitor_puts to something that tells 
it's a low level function (and add a momitor_puts that behaves as 
expected) but I can't come up with a name either. Maybe the low level 
function could be called hmp_putt? Or add a comment near monitor_puts to 
explain this for now.


Regards,
BALATON Zoltan

[PATCH 01/24] target/ppc: Fix gen_sc to use correct nip

2024-04-23 Thread BALATON Zoltan
Most exceptions are raised with nip pointing to the faulting
instruction but the sc instruction generating a syscall exception
leaves nip pointing to next instruction. Fix gen_sc to not use
gen_exception_err() which sets nip back but correctly set nip to
pc_next so we don't have to patch this in the exception handlers.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Nicholas Piggin 
---
 target/ppc/excp_helper.c | 43 ++--
 target/ppc/translate.c   |  6 ++
 2 files changed, 4 insertions(+), 45 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 674c05a2ce..b6a5241a4d 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -116,7 +116,7 @@ static void dump_syscall(CPUPPCState *env)
   ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
   ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
   ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
-  ppc_dump_gpr(env, 8), env->nip);
+  ppc_dump_gpr(env, 8), env->nip - 4);
 }
 
 static void dump_hcall(CPUPPCState *env)
@@ -131,7 +131,7 @@ static void dump_hcall(CPUPPCState *env)
   ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
   ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
   ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
-  env->nip);
+  env->nip - 4);
 }
 
 #ifdef CONFIG_TCG
@@ -516,12 +516,6 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FIT:   /* Fixed-interval timer interrupt   */
 trace_ppc_excp_print("FIT");
@@ -632,12 +626,6 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 case POWERPC_EXCP_DECR:  /* Decrementer exception*/
@@ -780,13 +768,6 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
@@ -932,13 +913,6 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
@@ -1098,12 +1072,6 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
 break;
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 dump_syscall(env);
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
 break;
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
 case POWERPC_EXCP_APU:   /* Auxiliary processor unavailable  */
@@ -1428,13 +1396,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
 } else {
 dump_syscall(env);
 }
-
-/*
- * We need to correct the NIP which in this case is supposed
- * to point to the next instruction
- */
-env->nip += 4;
-
 /* "PAPR mode" built-in hypercall emulation */
 if (lev == 1 && books_vhyp_handles_hcall(cpu)) {
 PPCVirtualHypervisorClass *vhc =
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 93ffec787c..fa72f17c3e 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4479,15 +4479,13 @@ static void gen_hrfid(DisasContext *ctx)
 #endif
 static void gen_sc(DisasContext *ctx)
 {
-uint32_t lev;
-
 /*
  * LEV is a 7-bit field, but the top 6 bits are treated as a reserved
  * field (i.e., ignored). ISA v3.1 changes that to 5 bits, but that is
  * for Ultravisor which TCG does not support, 

[PATCH 06/24] target/ppc/mmu_common.c: Simplify checking for real mode

2024-04-23 Thread BALATON Zoltan
In get_physical_address_wtlb() the real_mode flag depends on either
the MSR[IR] or MSR[DR] bit depending on access_type. Extract just the
needed bit in a more straight forward way instead of doing unnecessary
computation.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 168ff842a5..aa01469604 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1188,8 +1188,10 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  int mmu_idx)
 {
 int ret = -1;
-bool real_mode = (type == ACCESS_CODE && !FIELD_EX64(env->msr, MSR, IR)) ||
- (type != ACCESS_CODE && !FIELD_EX64(env->msr, MSR, DR));
+bool real_mode;
+
+real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+  : !FIELD_EX64(env->msr, MSR, DR);
 
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
-- 
2.30.9




[PATCH 15/24] target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls

2024-04-23 Thread BALATON Zoltan
Fix several qemu_log_mask() calls that are misindented.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 42 -
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 5cb550da7e..80c8fb0bf5 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -297,8 +297,8 @@ static int ppc6xx_tlb_get_bat(CPUPPCState *env, mmu_ctx_t 
*ctx,
 int ret = -1;
 bool ifetch = access_type == MMU_INST_FETCH;
 
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
- ifetch ? 'I' : 'D', virtual);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
+  ifetch ? 'I' : 'D', virtual);
 if (ifetch) {
 BATlt = env->IBAT[1];
 BATut = env->IBAT[0];
@@ -312,9 +312,9 @@ static int ppc6xx_tlb_get_bat(CPUPPCState *env, mmu_ctx_t 
*ctx,
 BEPIu = *BATu & 0xF000;
 BEPIl = *BATu & 0x0FFE;
 bat_size_prot(env, , , , BATu, BATl);
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
-   TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
-   ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
+  TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
+  ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
 if ((virtual & 0xF000) == BEPIu &&
 ((virtual & 0x0FFE) & ~bl) == BEPIl) {
 /* BAT matches */
@@ -346,12 +346,11 @@ static int ppc6xx_tlb_get_bat(CPUPPCState *env, mmu_ctx_t 
*ctx,
 BEPIu = *BATu & 0xF000;
 BEPIl = *BATu & 0x0FFE;
 bl = (*BATu & 0x1FFC) << 15;
- qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v "
-   TARGET_FMT_lx " BATu " TARGET_FMT_lx
-   " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
-   TARGET_FMT_lx " " TARGET_FMT_lx "\n",
-   __func__, ifetch ? 'I' : 'D', i, virtual,
-   *BATu, *BATl, BEPIu, BEPIl, bl);
+qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
+  " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
+  "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
+  TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
+  i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl);
 }
 }
 }
@@ -400,9 +399,8 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 hash = vsid ^ pgidx;
 ctx->ptem = (vsid << 7) | (pgidx >> 10);
 
-qemu_log_mask(CPU_LOG_MMU,
-"pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
-ctx->key, ds, ctx->nx, vsid);
+qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
+  TARGET_FMT_lx "\n", ctx->key, ds, ctx->nx, vsid);
 ret = -1;
 if (!ds) {
 /* Check if instruction fetch is allowed, if needed */
@@ -599,9 +597,9 @@ static int mmu40x_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 return 0;
 }
 }
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx
-   " %d %d\n", __func__, address, raddr, ctx->prot, ret);
+qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
+  " => " HWADDR_FMT_plx " %d %d\n",
+  __func__, address, raddr, ctx->prot, ret);
 
 return ret;
 }
@@ -716,11 +714,11 @@ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, 
hwaddr *raddrp,
 }
 
 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
- qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
-   " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
-   HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
-   __func__, address, pid, tlb->mas1, tlb->mas2, mask,
-   tlb->mas7_3, tlb->mas8);
+qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx
+  " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%"
+  HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n",
+  __func__, address, pid, tlb->mas1, tlb->mas2, mask,
+  tlb->mas7_3, tlb->mas8);
 
 /* Check PID */
 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
-- 
2.30.9




[PATCH 07/24] target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU

2024-04-23 Thread BALATON Zoltan
The default case will catch this and abort the same way and there is
still a warning about it in ppc_tlb_invalidate_all() so drop these
from mmu_common.c to simplify this code.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index aa01469604..c4fafebbe3 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1223,10 +1223,6 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
mmu_idx);
 break;
-case POWERPC_MMU_MPC8xx:
-/* XXX: TODO */
-cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
-break;
 case POWERPC_MMU_REAL:
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
@@ -1357,8 +1353,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_BOOKE_DEAR] = eaddr;
 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
 break;
-case POWERPC_MMU_MPC8xx:
-cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
   "any MMU exceptions\n");
@@ -1431,9 +1425,6 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 }
 break;
-case POWERPC_MMU_MPC8xx:
-/* XXX: TODO */
-cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
 case POWERPC_MMU_BOOKE206:
 booke206_update_mas_tlb_miss(env, eaddr, access_type, 
mmu_idx);
 /* fall through */
-- 
2.30.9




[PATCH 10/24] target/ppc/mmu_common.c: Split out BookE cases before checking real mode

2024-04-23 Thread BALATON Zoltan
BookE does not have real mode so split off and handle it first in
get_physical_address_wtlb() before checking for real mode for other
MMU models.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 1fbf5a1bb0..68c367e6ad 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1196,6 +1196,13 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 int ret = -1;
 bool real_mode;
 
+if (env->mmu_model == POWERPC_MMU_BOOKE) {
+return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
+} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
+mmu_idx);
+}
+
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
   : !FIELD_EX64(env->msr, MSR, DR);
 
@@ -1216,13 +1223,6 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
 }
 break;
-case POWERPC_MMU_BOOKE:
-ret = mmubooke_get_physical_address(env, ctx, eaddr, access_type);
-break;
-case POWERPC_MMU_BOOKE206:
-ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-   mmu_idx);
-break;
 case POWERPC_MMU_REAL:
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
-- 
2.30.9




[PATCH 19/24] target/ppc: Move mmu_ctx_t definition to mmu_common.c

2024-04-23 Thread BALATON Zoltan
This type is only used within mmu_common.c. Move its definition from
internal.h to there.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 12 
 target/ppc/mmu_common.c | 11 +++
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 3e4423ce0d..b835b2cba0 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -255,8 +255,6 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 
 /* PowerPC MMU emulation */
 
-typedef struct mmu_ctx_t mmu_ctx_t;
-
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
@@ -264,16 +262,6 @@ bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType 
access_type,
 /* Software driven TLB helpers */
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
-/* Context used internally during MMU translations */
-struct mmu_ctx_t {
-hwaddr raddr;  /* Real address  */
-hwaddr eaddr;  /* Effective address */
-int prot;  /* Protection bits   */
-hwaddr hash[2];/* Pagetable hash values */
-target_ulong ptem; /* Virtual segment ID | API  */
-int key;   /* Access key*/
-int nx;/* Non-execute area  */
-};
 
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 5ba8d2460d..244830c196 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -35,6 +35,17 @@
 
 /* #define DUMP_PAGE_TABLES */
 
+/* Context used internally during MMU translations */
+typedef struct {
+hwaddr raddr;  /* Real address */
+hwaddr eaddr;  /* Effective address*/
+int prot;  /* Protection bits  */
+hwaddr hash[2];/* Pagetable hash values*/
+target_ulong ptem; /* Virtual segment ID | API */
+int key;   /* Access key   */
+int nx;/* Non-execute area */
+} mmu_ctx_t;
+
 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 {
 PowerPCCPU *cpu = env_archcpu(env);
-- 
2.30.9




[PATCH 03/24] target/ppc: Simplify syscall exception handlers

2024-04-23 Thread BALATON Zoltan
After previous changes the hypercall handling in 7xx and 74xx
exception handlers can be folded into one if statement to simplify
this code. Also add "unlikely" to mark the less frequently used branch
for the compiler.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Harsh Prateek Bora 
---
 target/ppc/excp_helper.c | 22 ++
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index fd145200dd..4c1375381d 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -762,26 +762,21 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 {
 int lev = env->error_code;
-
-if (lev == 1 && cpu->vhyp) {
-dump_hcall(env);
-} else {
-dump_syscall(env);
-}
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
  * uses VOF and the 7xx CPUs, so although the 7xx don't have
  * HV mode, we need to keep hypercall support.
  */
-if (lev == 1 && cpu->vhyp) {
+if (unlikely(lev == 1 && cpu->vhyp)) {
 PPCVirtualHypervisorClass *vhc =
 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+dump_hcall(env);
 vhc->hypercall(cpu->vhyp, cpu);
 powerpc_reset_excp_state(cpu);
 return;
 }
-
+dump_syscall(env);
 break;
 }
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
@@ -907,26 +902,21 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL:   /* System call exception*/
 {
 int lev = env->error_code;
-
-if (lev == 1 && cpu->vhyp) {
-dump_hcall(env);
-} else {
-dump_syscall(env);
-}
 /*
  * The Virtual Open Firmware (VOF) relies on the 'sc 1'
  * instruction to communicate with QEMU. The pegasos2 machine
  * uses VOF and the 74xx CPUs, so although the 74xx don't have
  * HV mode, we need to keep hypercall support.
  */
-if (lev == 1 && cpu->vhyp) {
+if (unlikely(lev == 1 && cpu->vhyp)) {
 PPCVirtualHypervisorClass *vhc =
 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+dump_hcall(env);
 vhc->hypercall(cpu->vhyp, cpu);
 powerpc_reset_excp_state(cpu);
 return;
 }
-
+dump_syscall(env);
 break;
 }
 case POWERPC_EXCP_FPU:   /* Floating-point unavailable exception */
-- 
2.30.9




[PATCH 17/24] target/ppc/mmu_common.c: Replace hard coded constants in ppc_jumbo_xlate()

2024-04-23 Thread BALATON Zoltan
The "2" in booke206_update_mas_tlb_miss() call corresponds to
MMU_INST_FETCH which is the value of access_type in this branch;
mmubooke206_esr() only checks for MMU_DATA_STORE and it's called from
code access so using MMU_DATA_LOAD here seems wrong so replace it with
access_type here as well that yields the same result. This also makes
these calls the same as the data access branch further down.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 34d8576905..b64f8f79c3 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1293,13 +1293,13 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 env->spr[SPR_40x_ESR] = 0x;
 break;
 case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
 /* fall through */
 case POWERPC_MMU_BOOKE:
 cs->exception_index = POWERPC_EXCP_ITLB;
 env->error_code = 0;
 env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
 break;
 case POWERPC_MMU_REAL:
 cpu_abort(cs, "PowerPC in real mode should never raise "
-- 
2.30.9




[PATCH 09/24] target/ppc/mmu_common.c: Rename get_bat_6xx_tlb()

2024-04-23 Thread BALATON Zoltan
Rename to ppc6xx_tlb_get_bat() to match other similar names in the
same file.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 47346adb88..1fbf5a1bb0 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -288,8 +288,8 @@ static inline void bat_size_prot(CPUPPCState *env, 
target_ulong *blp,
 *protp = prot;
 }
 
-static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong virtual, MMUAccessType access_type)
+static int ppc6xx_tlb_get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
+  target_ulong virtual, MMUAccessType access_type)
 {
 target_ulong *BATlt, *BATut, *BATu, *BATl;
 target_ulong BEPIl, BEPIu, bl;
@@ -371,7 +371,7 @@ static int mmu6xx_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 /* First try to find a BAT entry if there are any */
 if (env->nb_BATs != 0) {
-ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
+ret = ppc6xx_tlb_get_bat(env, ctx, eaddr, access_type);
 }
 if (ret >= 0) {
 return ret;
-- 
2.30.9




[PATCH 12/24] target/ppc/mmu_common.c: Inline and remove check_physical()

2024-04-23 Thread BALATON Zoltan
This function just does two assignments and and unnecessary check that
is always true so inline it in the only caller left and remove it.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 26 +++---
 1 file changed, 3 insertions(+), 23 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index fb66468d34..843f909619 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1166,28 +1166,6 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-static int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
-  MMUAccessType access_type)
-{
-ctx->raddr = eaddr;
-ctx->prot = PAGE_READ | PAGE_EXEC;
-
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-case POWERPC_MMU_SOFT_4xx:
-case POWERPC_MMU_REAL:
-case POWERPC_MMU_BOOKE:
-ctx->prot |= PAGE_WRITE;
-break;
-
-default:
-/* Caller's checks mean we should never get here for other models */
-g_assert_not_reached();
-}
-
-return 0;
-}
-
 int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
@@ -1207,7 +1185,9 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
   env->mmu_model == POWERPC_MMU_SOFT_4xx ||
   env->mmu_model == POWERPC_MMU_REAL)) {
-return check_physical(env, ctx, eaddr, access_type);
+ctx->raddr = eaddr;
+ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+return 0;
 }
 
 switch (env->mmu_model) {
-- 
2.30.9




[PATCH 21/24] target/ppc/mmu_common.c: Split off BookE handling from ppc_jumbo_xlate()

2024-04-23 Thread BALATON Zoltan
Introduce ppc_booke_xlate() to handle BookE and BookE 2.06 cases to
reduce ppc_jumbo_xlate() further.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 180 ++--
 1 file changed, 138 insertions(+), 42 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ca1cbba0f0..b7803c1c26 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1255,6 +1255,137 @@ static void booke206_update_mas_tlb_miss(CPUPPCState 
*env, target_ulong address,
 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
 }
 
+static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
+MMUAccessType access_type,
+hwaddr *raddrp, int *psizep, int *protp,
+int mmu_idx, bool guest_visible)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+mmu_ctx_t ctx;
+int ret;
+
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+ret = mmubooke206_get_physical_address(env, , eaddr, access_type,
+   mmu_idx);
+} else {
+ret = mmubooke_get_physical_address(env, , eaddr, access_type);
+}
+if (ret == 0) {
+*raddrp = ctx.raddr;
+*protp = ctx.prot;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (access_type == MMU_INST_FETCH) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->error_code = 0;
+break;
+case -3:
+/* No execute protection violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->spr[SPR_BOOKE_ESR] = 0;
+env->error_code = 0;
+break;
+case -4:
+/* Direct store exception */
+/* No code fetch is allowed in direct-store areas */
+cs->exception_index = POWERPC_EXCP_ISI;
+env->error_code = 0;
+break;
+}
+} else {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
+break;
+default:
+g_assert_not_reached();
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -4:
+/* Direct store exception */
+switch (env->access_type) {
+case ACCESS_FLOAT:
+/* Floating point load/store */
+cs->exception_index = POWERPC_EXCP_ALIGN;
+env->error_code = POWERPC_EXCP_ALIGN_FP;
+env->spr[SPR_DAR] = eaddr;
+break;
+case ACCESS_RES:
+/* lwarx, ldarx or stwcx. */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_DAR] = eaddr;
+if (access_type == MMU_DATA_STORE) {
+env->spr[SPR_DSISR] = 0x0600;
+} else {
+env->spr[SPR_DSISR] = 0x0400;
+}
+break;
+case ACCESS_EXT:
+/* eciwx or ecowx */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->error_code = 0;
+env->spr[SPR_DAR] = eaddr;
+if (access_type == MMU_DATA_ST

[PATCH 14/24] target/ppc/mmu_common.c: Simplify mmubooke206_get_physical_address()

2024-04-23 Thread BALATON Zoltan
This function is similar to mmubooke_get_physical_address() and can be
simplified the same way.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 28 ++--
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index d40ddb6fc3..5cb550da7e 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -877,15 +877,11 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 int mmu_idx)
 {
 ppcmas_tlb_t *tlb;
-hwaddr raddr;
-int i, j, ret;
-
-ret = -1;
-raddr = (hwaddr)-1ULL;
+hwaddr raddr = (hwaddr)-1ULL;
+int i, j, ways, ret = -1;
 
 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
-int ways = booke206_tlb_ways(env, i);
-
+ways = booke206_tlb_ways(env, i);
 for (j = 0; j < ways; j++) {
 tlb = booke206_get_tlbm(env, i, address, j);
 if (!tlb) {
@@ -894,6 +890,9 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
+if (ret >= 0) {
+ctx->raddr = raddr;
+}
 goto found_tlb;
 }
 }
@@ -901,17 +900,10 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 
 found_tlb:
 
-if (ret >= 0) {
-ctx->raddr = raddr;
- qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
-   ctx->raddr, ctx->prot, ret);
-} else {
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__, address,
-   raddr, ctx->prot, ret);
-}
-
+qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
+  HWADDR_FMT_plx " %d %d\n", __func__,
+  ret < 0 ? "refused" : "granted", address, raddr,
+  ctx->prot, ret);
 return ret;
 }
 
-- 
2.30.9




[PATCH 16/24] target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()

2024-04-23 Thread BALATON Zoltan
Instead of putting a large block of code in an if, invert the
condition and return early to be able to deindent the code block.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 319 
 1 file changed, 159 insertions(+), 160 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 80c8fb0bf5..34d8576905 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1270,187 +1270,186 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 *protp = ctx.prot;
 *psizep = TARGET_PAGE_BITS;
 return true;
+} else if (!guest_visible) {
+return false;
 }
 
-if (guest_visible) {
-log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
-if (type == ACCESS_CODE) {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_SOFT_6xx:
-cs->exception_index = POWERPC_EXCP_IFTLB;
-env->error_code = 1 << 18;
-env->spr[SPR_IMISS] = eaddr;
-env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
-goto tlb_miss;
-case POWERPC_MMU_SOFT_4xx:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_40x_DEAR] = eaddr;
-env->spr[SPR_40x_ESR] = 0x;
-break;
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
-break;
-case POWERPC_MMU_REAL:
-cpu_abort(cs, "PowerPC in real mode should never raise "
-  "any MMU exceptions\n");
-default:
-cpu_abort(cs, "Unknown or invalid MMU model\n");
-}
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+if (type == ACCESS_CODE) {
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+switch (env->mmu_model) {
+case POWERPC_MMU_SOFT_6xx:
+cs->exception_index = POWERPC_EXCP_IFTLB;
+env->error_code = 1 << 18;
+env->spr[SPR_IMISS] = eaddr;
+env->spr[SPR_ICMP] = 0x8000 | ctx.ptem;
+goto tlb_miss;
+case POWERPC_MMU_SOFT_4xx:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_40x_DEAR] = eaddr;
+env->spr[SPR_40x_ESR] = 0x;
 break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->error_code = 0;
-} else {
-env->error_code = 0x0800;
-}
+case POWERPC_MMU_BOOKE206:
+booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
+/* fall through */
+case POWERPC_MMU_BOOKE:
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->error_code = 0;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
MMU_DATA_LOAD);
 break;
-case -3:
-/* No execute protection violation */
-if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
-(env->mmu_model == POWERPC_MMU_BOOKE206)) {
-env->spr[SPR_BOOKE_ESR] = 0x;
-env->error_code = 0;
+case POWERPC_MMU_REAL:
+cpu_abort(cs, "PowerPC in real mode should never raise "
+  "any MMU exceptions\n");
+default:
+cpu_abort(cs, "Unknown or invalid MMU model\n");
+}
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_ISI;
+if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
+(env->mmu_model == POWERPC_MMU_BOOKE206)) {
+env->error_code = 0;
+} else {
+  

[PATCH 23/24] target/ppc/mmu_common.c: Simplify ppc_booke_xlate()

2024-04-23 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 147 +++-
 1 file changed, 56 insertions(+), 91 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ce1cf5cb77..ad64ec1647 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1266,106 +1266,71 @@ static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr 
eaddr,
 }
 
 log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+env->error_code = 0;
+if (env->mmu_model == POWERPC_MMU_BOOKE206 && ret == -1) {
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+}
 if (access_type == MMU_INST_FETCH) {
-switch (ret) {
-case -1:
+if (ret == -1) {
 /* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_ITLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
-default:
-g_assert_not_reached();
-}
-break;
-case -2:
-/* Access rights violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-env->error_code = 0;
-break;
-case -3:
-/* No execute protection violation */
-cs->exception_index = POWERPC_EXCP_ISI;
-env->spr[SPR_BOOKE_ESR] = 0;
-env->error_code = 0;
-break;
-case -4:
-/* Direct store exception */
-/* No code fetch is allowed in direct-store areas */
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+} else {
 cs->exception_index = POWERPC_EXCP_ISI;
-env->error_code = 0;
-break;
-}
-} else {
-switch (ret) {
-case -1:
-/* No matches in page tables or TLB */
-switch (env->mmu_model) {
-case POWERPC_MMU_BOOKE206:
-booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
-/* fall through */
-case POWERPC_MMU_BOOKE:
-cs->exception_index = POWERPC_EXCP_DTLB;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, 
access_type);
-break;
-default:
-g_assert_not_reached();
+if (ret == -3) {
+/* No execute protection violation */
+env->spr[SPR_BOOKE_ESR] = 0;
 }
+}
+return false;
+}
+
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -4:
+/* Direct store exception */
+env->spr[SPR_DAR] = eaddr;
+switch (env->access_type) {
+case ACCESS_FLOAT:
+/* Floating point load/store */
+cs->exception_index = POWERPC_EXCP_ALIGN;
+env->error_code = POWERPC_EXCP_ALIGN_FP;
 break;
-case -2:
-/* Access rights violation */
+case ACCESS_RES:
+/* lwarx, ldarx or stwcx. */
 cs->exception_index = POWERPC_EXCP_DSI;
-env->error_code = 0;
-env->spr[SPR_BOOKE_DEAR] = eaddr;
-env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+if (access_type == MMU_DATA_STORE) {
+env->spr[SPR_DSISR] = 0x0600;
+} else {
+env->spr[SPR_DSISR] = 0x0400;
+}
 break;
-case -4:
-/* Direct store exception */
-switch (env->access_type) {
-case ACCESS_FLOAT:
-/* Floating point load/store */
-cs->exception_index = POWERPC_EXCP_ALIGN;
-env->error_code = POWERPC_EXCP_ALIGN_FP;
-env->spr[SPR_DAR] = eaddr;
-break;
-case ACCESS_RES:
-/* lwarx, ldarx or s

[PATCH 20/24] target/ppc: Remove ppc_hash32_pp_prot() and reuse common function

2024-04-23 Thread BALATON Zoltan
The ppc_hash32_pp_prot() function in mmu-hash32.c is the same as
pp_check() in mmu_common.c. Rename the latter to ppc_pte_prot() and
merge with ppc_hash32_pp_prot() to remove duplicated code.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   |  2 +-
 target/ppc/mmu-hash32.c | 47 +
 target/ppc/mmu_common.c | 19 +
 3 files changed, 12 insertions(+), 56 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index b835b2cba0..2d95d406f6 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -254,7 +254,7 @@ static inline int prot_for_access_type(MMUAccessType 
access_type)
 #ifndef CONFIG_USER_ONLY
 
 /* PowerPC MMU emulation */
-
+int ppc_pte_prot(int key, int pp, int nx);
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 3976416840..ee9df351ae 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -42,51 +42,6 @@ struct mmu_ctx_hash32 {
 int key;   /* Access key*/
 };
 
-static int ppc_hash32_pp_prot(int key, int pp, int nx)
-{
-int prot;
-
-if (key == 0) {
-switch (pp) {
-case 0x0:
-case 0x1:
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-case 0x3:
-prot = PAGE_READ;
-break;
-
-default:
-abort();
-}
-} else {
-switch (pp) {
-case 0x0:
-prot = 0;
-break;
-
-case 0x1:
-case 0x3:
-prot = PAGE_READ;
-break;
-
-case 0x2:
-prot = PAGE_READ | PAGE_WRITE;
-break;
-
-default:
-abort();
-}
-}
-if (nx == 0) {
-prot |= PAGE_EXEC;
-}
-
-return prot;
-}
-
 static int ppc_hash32_pte_prot(int mmu_idx,
target_ulong sr, ppc_hash_pte32_t pte)
 {
@@ -95,7 +50,7 @@ static int ppc_hash32_pte_prot(int mmu_idx,
 key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS));
 pp = pte.pte1 & HPTE32_R_PP;
 
-return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
+return ppc_pte_prot(key, pp, !!(sr & SR32_NX));
 }
 
 static target_ulong hash32_bat_size(int mmu_idx,
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 244830c196..ca1cbba0f0 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -75,22 +75,23 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 /*/
 /* PowerPC MMU emulation */
 
-static int pp_check(int key, int pp, int nx)
+int ppc_pte_prot(int key, int pp, int nx)
 {
 int access;
 
 /* Compute access rights */
-access = 0;
 if (key == 0) {
 switch (pp) {
 case 0x0:
 case 0x1:
 case 0x2:
-access |= PAGE_WRITE;
-/* fall through */
+access = PAGE_READ | PAGE_WRITE;
+break;
 case 0x3:
-access |= PAGE_READ;
+access = PAGE_READ;
 break;
+default:
+g_assert_not_reached();
 }
 } else {
 switch (pp) {
@@ -104,6 +105,8 @@ static int pp_check(int key, int pp, int nx)
 case 0x2:
 access = PAGE_READ | PAGE_WRITE;
 break;
+default:
+g_assert_not_reached();
 }
 }
 if (nx == 0) {
@@ -140,7 +143,7 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 MMUAccessType access_type)
 {
 target_ulong ptem, mmask;
-int access, ret, pteh, ptev, pp;
+int ret, pteh, ptev, pp;
 
 ret = -1;
 /* Check validity and table match */
@@ -159,11 +162,9 @@ static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, 
target_ulong pte0,
 return -3;
 }
 }
-/* Compute access rights */
-access = pp_check(ctx->key, pp, ctx->nx);
 /* Keep the matching PTE information */
 ctx->raddr = pte1;
-ctx->prot = access;
+ctx->prot = ppc_pte_prot(ctx->key, pp, ctx->nx);
 ret = check_prot(ctx->prot, access_type);
 if (ret == 0) {
 /* Access granted */
-- 
2.30.9




[PATCH 18/24] target/ppc/mmu_common.c: Make get_physical_address_wtlb() static

2024-04-23 Thread BALATON Zoltan
This function is not used from any other files so make it static and
fix the maybe used uninitialised warnings this has uncovered.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/internal.h   | 5 +
 target/ppc/mmu_common.c | 5 -
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 5b20ecbd33..3e4423ce0d 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -260,10 +260,7 @@ typedef struct mmu_ctx_t mmu_ctx_t;
 bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
   hwaddr *raddrp, int *psizep, int *protp,
   int mmu_idx, bool guest_visible);
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
- target_ulong eaddr,
- MMUAccessType access_type, int type,
- int mmu_idx);
+
 /* Software driven TLB helpers */
 int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
 int way, int is_code);
diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b64f8f79c3..5ba8d2460d 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -669,6 +669,7 @@ static int mmubooke_get_physical_address(CPUPPCState *env, 
mmu_ctx_t *ctx,
 hwaddr raddr = (hwaddr)-1ULL;
 int i, ret = -1;
 
+ctx->prot = 0;
 for (i = 0; i < env->nb_tlb; i++) {
 tlb = >tlb.tlbe[i];
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
@@ -878,6 +879,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 hwaddr raddr = (hwaddr)-1ULL;
 int i, j, ways, ret = -1;
 
+ctx->prot = 0;
 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
 ways = booke206_tlb_ways(env, i);
 for (j = 0; j < ways; j++) {
@@ -1149,7 +1151,7 @@ void dump_mmu(CPUPPCState *env)
 }
 }
 
-int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
+static int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
  target_ulong eaddr,
  MMUAccessType access_type, int type,
  int mmu_idx)
@@ -1168,6 +1170,7 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
   env->mmu_model == POWERPC_MMU_SOFT_4xx ||
   env->mmu_model == POWERPC_MMU_REAL)) {
+memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 return 0;
-- 
2.30.9




[PATCH 08/24] target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()

2024-04-23 Thread BALATON Zoltan
Repurpose get_segment_6xx_tlb() to do the whole address translation
for POWERPC_MMU_SOFT_6xx MMU model by moving the BAT check there and
renaming it to match other similar functions. These are only called
once together so no need to keep these separate functions and
combining them simplifies the caller allowing further restructuring.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index c4fafebbe3..47346adb88 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -359,19 +359,25 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
 return ret;
 }
 
-/* Perform segment based translation */
-static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
-   target_ulong eaddr, MMUAccessType access_type,
-   int type)
+static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+   target_ulong eaddr,
+   MMUAccessType access_type, int type)
 {
 PowerPCCPU *cpu = env_archcpu(env);
 hwaddr hash;
-target_ulong vsid;
-int ds, target_page_bits;
+target_ulong vsid, sr, pgidx;
 bool pr;
-int ret;
-target_ulong sr, pgidx;
+int ds, target_page_bits, ret = -1;
 
+/* First try to find a BAT entry if there are any */
+if (env->nb_BATs != 0) {
+ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
+}
+if (ret >= 0) {
+return ret;
+}
+
+/* Perform segment based translation when no BATs matched */
 pr = FIELD_EX64(env->msr, MSR, PR);
 ctx->eaddr = eaddr;
 
@@ -1198,14 +1204,8 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 if (real_mode) {
 ret = check_physical(env, ctx, eaddr, access_type);
 } else {
-/* Try to find a BAT */
-if (env->nb_BATs != 0) {
-ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
-}
-if (ret < 0) {
-/* We didn't match any BAT entry or don't have BATs */
-ret = get_segment_6xx_tlb(env, ctx, eaddr, access_type, type);
-}
+ret = mmu6xx_get_physical_address(env, ctx, eaddr, access_type,
+  type);
 }
 break;
 
-- 
2.30.9




[PATCH 04/24] target/ppc: Remove unused helper

2024-04-23 Thread BALATON Zoltan
The helper_rac function is defined but not used, remove it.

Fixes: 005b69fdcc (target/ppc: Remove PowerPC 601 CPUs)
Signed-off-by: BALATON Zoltan 
---
 target/ppc/helper.h |  2 --
 target/ppc/mmu_helper.c | 24 
 2 files changed, 26 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 86f97ee1e7..f769e01c3d 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -700,8 +700,6 @@ DEF_HELPER_2(book3s_msgclr, void, env, tl)
 
 DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
 #if !defined(CONFIG_USER_ONLY)
-DEF_HELPER_2(rac, tl, env, tl)
-
 DEF_HELPER_2(load_dcr, tl, env, tl)
 DEF_HELPER_3(store_dcr, void, env, tl, tl)
 #endif
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index c071b4d5e2..817836b731 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -595,30 +595,6 @@ void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
 do_6xx_tlb(env, EPN, 1);
 }
 
-/*/
-/* PowerPC 601 specific instructions (POWER bridge) */
-
-target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
-{
-mmu_ctx_t ctx;
-int nb_BATs;
-target_ulong ret = 0;
-
-/*
- * We don't have to generate many instances of this instruction,
- * as rac is supervisor only.
- *
- * XXX: FIX THIS: Pretend we have no BAT
- */
-nb_BATs = env->nb_BATs;
-env->nb_BATs = 0;
-if (get_physical_address_wtlb(env, , addr, 0, ACCESS_INT, 0) == 0) {
-ret = ctx.raddr;
-}
-env->nb_BATs = nb_BATs;
-return ret;
-}
-
 static inline target_ulong booke_tlb_to_page_size(int size)
 {
 return 1024 << (2 * size);
-- 
2.30.9




[PATCH 05/24] target/ppc/mmu_common.c: Move calculation of a value closer to its usage

2024-04-23 Thread BALATON Zoltan
In mmubooke_check_tlb() prot2 is calculated first but only used after
an unrelated check that can return before tha value is used. Move the
calculation after the check, closer to where it is used, to keep them
together and avoid computing it when not needed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 751403f1c8..168ff842a5 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -634,12 +634,6 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return -1;
 }
 
-if (FIELD_EX64(env->msr, MSR, PR)) {
-prot2 = tlb->prot & 0xF;
-} else {
-prot2 = (tlb->prot >> 4) & 0xF;
-}
-
 /* Check the address space */
 if ((access_type == MMU_INST_FETCH ?
 FIELD_EX64(env->msr, MSR, IR) :
@@ -648,6 +642,11 @@ static int mmubooke_check_tlb(CPUPPCState *env, 
ppcemb_tlb_t *tlb,
 return -1;
 }
 
+if (FIELD_EX64(env->msr, MSR, PR)) {
+prot2 = tlb->prot & 0xF;
+} else {
+prot2 = (tlb->prot >> 4) & 0xF;
+}
 *prot = prot2;
 if (prot2 & prot_for_access_type(access_type)) {
 qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__);
-- 
2.30.9




[PATCH 13/24] target/ppc/mmu_common.c: Simplify mmubooke_get_physical_address()

2024-04-23 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 25 +
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 843f909619..d40ddb6fc3 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -668,31 +668,24 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
  MMUAccessType access_type)
 {
 ppcemb_tlb_t *tlb;
-hwaddr raddr;
-int i, ret;
+hwaddr raddr = (hwaddr)-1ULL;
+int i, ret = -1;
 
-ret = -1;
-raddr = (hwaddr)-1ULL;
 for (i = 0; i < env->nb_tlb; i++) {
 tlb = >tlb.tlbe[i];
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
+if (ret >= 0) {
+ctx->raddr = raddr;
+}
 break;
 }
 }
-
-if (ret >= 0) {
-ctx->raddr = raddr;
-qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx
-  " => " HWADDR_FMT_plx " %d %d\n", __func__,
-  address, ctx->raddr, ctx->prot, ret);
-} else {
- qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx
-   " => " HWADDR_FMT_plx " %d %d\n", __func__,
-   address, raddr, ctx->prot, ret);
-}
-
+qemu_log_mask(CPU_LOG_MMU,
+  "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
+  " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
+  address, raddr, ctx->prot, ret);
 return ret;
 }
 
-- 
2.30.9




[PATCH 24/24] target/ppc/mmu_common.c: Move BookE MMU functions together

2024-04-23 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 300 
 1 file changed, 150 insertions(+), 150 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index ad64ec1647..18e49aa2f1 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -915,6 +915,156 @@ found_tlb:
 return ret;
 }
 
+static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
+ MMUAccessType access_type, int 
mmu_idx)
+{
+uint32_t epid;
+bool as, pr;
+uint32_t missed_tid = 0;
+bool use_epid = mmubooke206_get_as(env, mmu_idx, , , );
+
+if (access_type == MMU_INST_FETCH) {
+as = FIELD_EX64(env->msr, MSR, IR);
+}
+env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
+env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
+env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
+env->spr[SPR_BOOKE_MAS3] = 0;
+env->spr[SPR_BOOKE_MAS6] = 0;
+env->spr[SPR_BOOKE_MAS7] = 0;
+
+/* AS */
+if (as) {
+env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
+env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
+}
+
+env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
+env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
+
+if (!use_epid) {
+switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
+case MAS4_TIDSELD_PID0:
+missed_tid = env->spr[SPR_BOOKE_PID];
+break;
+case MAS4_TIDSELD_PID1:
+missed_tid = env->spr[SPR_BOOKE_PID1];
+break;
+case MAS4_TIDSELD_PID2:
+missed_tid = env->spr[SPR_BOOKE_PID2];
+break;
+}
+env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
+} else {
+missed_tid = epid;
+env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
+}
+env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
+
+
+/* next victim logic */
+env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
+env->last_way++;
+env->last_way &= booke206_tlb_ways(env, 0) - 1;
+env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
+}
+
+static bool ppc_booke_xlate(PowerPCCPU *cpu, vaddr eaddr,
+MMUAccessType access_type,
+hwaddr *raddrp, int *psizep, int *protp,
+int mmu_idx, bool guest_visible)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+mmu_ctx_t ctx;
+int ret;
+
+if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+ret = mmubooke206_get_physical_address(env, , eaddr, access_type,
+   mmu_idx);
+} else {
+ret = mmubooke_get_physical_address(env, , eaddr, access_type);
+}
+if (ret == 0) {
+*raddrp = ctx.raddr;
+*protp = ctx.prot;
+*psizep = TARGET_PAGE_BITS;
+return true;
+} else if (!guest_visible) {
+return false;
+}
+
+log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
+env->error_code = 0;
+if (env->mmu_model == POWERPC_MMU_BOOKE206 && ret == -1) {
+booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
+}
+if (access_type == MMU_INST_FETCH) {
+if (ret == -1) {
+/* No matches in page tables or TLB */
+cs->exception_index = POWERPC_EXCP_ITLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+} else {
+cs->exception_index = POWERPC_EXCP_ISI;
+if (ret == -3) {
+/* No execute protection violation */
+env->spr[SPR_BOOKE_ESR] = 0;
+}
+}
+return false;
+}
+
+switch (ret) {
+case -1:
+/* No matches in page tables or TLB */
+cs->exception_index = POWERPC_EXCP_DTLB;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -2:
+/* Access rights violation */
+cs->exception_index = POWERPC_EXCP_DSI;
+env->spr[SPR_BOOKE_DEAR] = eaddr;
+env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
+break;
+case -4:
+/* Direct store exception */
+env->spr[SPR_DAR] = eaddr;
+switch (env->access_type) {
+case ACCESS_FLOAT:
+/* Floating point load/store */
+cs->exception_index = POWERPC_EXCP_ALIGN;
+env->error_code = POWERPC_EXCP_ALIGN_FP;
+break;
+case ACCESS_RES:
+/* lwarx, ldarx or stwcx. */
+cs->exception_index = POWERPC_EXCP_DSI;
+

[PATCH 02/24] target/ppc: Move patching nip from exception handler to helper_scv

2024-04-23 Thread BALATON Zoltan
From: Nicholas Piggin 

Unlike sc, for scv a facility unavailable interrupt must be generated
if FSCR[SCV]=0 so we can't raise the exception with nip set to next
instruction but we can move advancing nip if the FSCR check passes to
helper_scv so the exception handler does not need to change it.

[balaton: added commit message]
Signed-off-by: BALATON Zoltan 
---
 target/ppc/excp_helper.c | 2 +-
 target/ppc/translate.c   | 6 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index b6a5241a4d..fd145200dd 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1415,7 +1415,6 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
 case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
 lev = env->error_code;
 dump_syscall(env);
-env->nip += 4;
 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
 
@@ -2524,6 +2523,7 @@ void helper_ppc_maybe_interrupt(CPUPPCState *env)
 void helper_scv(CPUPPCState *env, uint32_t lev)
 {
 if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
+env->nip += 4;
 raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
 } else {
 raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index fa72f17c3e..0dbcf4b26f 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4494,7 +4494,11 @@ static void gen_scv(DisasContext *ctx)
 {
 uint32_t lev = (ctx->opcode >> 5) & 0x7F;
 
-/* Set the PC back to the faulting instruction. */
+/*
+ * Set the PC back to the scv instruction (unlike sc), because a facility
+ * unavailable interrupt must be generated if FSCR[SCV]=0. The helper
+ * advances nip if the FSCR check passes.
+ */
 gen_update_nip(ctx, ctx->cia);
 gen_helper_scv(tcg_env, tcg_constant_i32(lev));
 
-- 
2.30.9




[PATCH 22/24] target/ppc/mmu_common.c: Remove BookE handling from get_physical_address_wtlb()

2024-04-23 Thread BALATON Zoltan
This function is no longer called for BookE MMU model so remove parts
related to it. This has uncovered a few may be used uninitialised
warnings that are also fixed.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 25 +
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index b7803c1c26..ce1cf5cb77 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -687,12 +687,10 @@ static int mmubooke_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke_check_tlb(env, tlb, , >prot, address,
  access_type, i);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 break;
 }
 }
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU,
   "%s: access %s " TARGET_FMT_lx " => " HWADDR_FMT_plx
   " %d %d\n", __func__, ret < 0 ? "refused" : "granted",
@@ -902,9 +900,6 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 ret = mmubooke206_check_tlb(env, tlb, , >prot, address,
 access_type, mmu_idx);
 if (ret != -1) {
-if (ret >= 0) {
-ctx->raddr = raddr;
-}
 goto found_tlb;
 }
 }
@@ -912,6 +907,7 @@ static int mmubooke206_get_physical_address(CPUPPCState 
*env, mmu_ctx_t *ctx,
 
 found_tlb:
 
+ctx->raddr = raddr;
 qemu_log_mask(CPU_LOG_MMU, "%s: access %s " TARGET_FMT_lx " => "
   HWADDR_FMT_plx " %d %d\n", __func__,
   ret < 0 ? "refused" : "granted", address, raddr,
@@ -1168,20 +1164,9 @@ static int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-bool real_mode;
-
-if (env->mmu_model == POWERPC_MMU_BOOKE) {
-return mmubooke_get_physical_address(env, ctx, eaddr, access_type);
-} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
-return mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
-mmu_idx);
-}
-
-real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
-  : !FIELD_EX64(env->msr, MSR, DR);
-if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
-  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
-  env->mmu_model == POWERPC_MMU_REAL)) {
+bool real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
+   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode) {
 memset(ctx, 0, sizeof(*ctx));
 ctx->raddr = eaddr;
 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-- 
2.30.9




[PATCH 11/24] target/ppc/mmu_common.c: Split off real mode cases in get_physical_address_wtlb()

2024-04-23 Thread BALATON Zoltan
The real mode handling is identical in the remaining switch cases.
Split off these common real mode cases into a separate conditional to
leave only the else branches in the switch that are different.

Signed-off-by: BALATON Zoltan 
---
 target/ppc/mmu_common.c | 34 +-
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c
index 68c367e6ad..fb66468d34 100644
--- a/target/ppc/mmu_common.c
+++ b/target/ppc/mmu_common.c
@@ -1193,7 +1193,6 @@ int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t 
*ctx,
  MMUAccessType access_type, int type,
  int mmu_idx)
 {
-int ret = -1;
 bool real_mode;
 
 if (env->mmu_model == POWERPC_MMU_BOOKE) {
@@ -1205,38 +1204,23 @@ int get_physical_address_wtlb(CPUPPCState *env, 
mmu_ctx_t *ctx,
 
 real_mode = (type == ACCESS_CODE) ? !FIELD_EX64(env->msr, MSR, IR)
   : !FIELD_EX64(env->msr, MSR, DR);
+if (real_mode && (env->mmu_model == POWERPC_MMU_SOFT_6xx ||
+  env->mmu_model == POWERPC_MMU_SOFT_4xx ||
+  env->mmu_model == POWERPC_MMU_REAL)) {
+return check_physical(env, ctx, eaddr, access_type);
+}
 
 switch (env->mmu_model) {
 case POWERPC_MMU_SOFT_6xx:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-ret = mmu6xx_get_physical_address(env, ctx, eaddr, access_type,
-  type);
-}
-break;
-
+return mmu6xx_get_physical_address(env, ctx, eaddr, access_type, type);
 case POWERPC_MMU_SOFT_4xx:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
-}
-break;
+return mmu40x_get_physical_address(env, ctx, eaddr, access_type);
 case POWERPC_MMU_REAL:
-if (real_mode) {
-ret = check_physical(env, ctx, eaddr, access_type);
-} else {
-cpu_abort(env_cpu(env),
-  "PowerPC in real mode do not do any translation\n");
-}
-return -1;
+cpu_abort(env_cpu(env),
+  "PowerPC in real mode do not do any translation\n");
 default:
 cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
-return -1;
 }
-
-return ret;
 }
 
 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong 
address,
-- 
2.30.9




[PATCH 00/24] Misc PPC exception and BookE MMU clean ups

2024-04-23 Thread BALATON Zoltan
This series does some further clean up mostly around BookE MMU to
untangle it from other MMU models. It also contains some other changes
that I've come up with while working on this. The first 3 patches are
from the last exception handling clean up series that were dropped due
to some error on CI but I'm not sure if that was because of some CI
infrastructure problem or some problem with the patches as the error
did not make much sense. So these patches are only rebased now, I made
no other change to them until the issue is understood better. The rest
are new patches I've added since tha last series. Please review.

Regards,
BALATON Zoltan


BALATON Zoltan (24):
  target/ppc: Fix gen_sc to use correct nip
  target/ppc: Move patching nip from exception handler to helper_scv
  target/ppc: Simplify syscall exception handlers
  target/ppc: Remove unused helper
  target/ppc/mmu_common.c: Move calculation of a value closer to its
usage
  target/ppc/mmu_common.c: Simplify checking for real mode
  target/ppc/mmu_common.c: Drop cases for unimplemented MPC8xx MMU
  target/ppc/mmu_common.c: Introduce mmu6xx_get_physical_address()
  target/ppc/mmu_common.c: Rename get_bat_6xx_tlb()
  target/ppc/mmu_common.c: Split out BookE cases before checking real
mode
  target/ppc/mmu_common.c: Split off real mode cases in
get_physical_address_wtlb()
  target/ppc/mmu_common.c: Inline and remove check_physical()
  target/ppc/mmu_common.c: Simplify mmubooke_get_physical_address()
  target/ppc/mmu_common.c: Simplify mmubooke206_get_physical_address()
  target/ppc/mmu_common.c: Fix misindented qemu_log_mask() calls
  target/ppc/mmu_common.c: Deindent ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Replace hard coded constants in
ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Make get_physical_address_wtlb() static
  target/ppc: Move mmu_ctx_t definition to mmu_common.c
  target/ppc: Remove ppc_hash32_pp_prot() and reuse common function
  target/ppc/mmu_common.c: Split off BookE handling from
ppc_jumbo_xlate()
  target/ppc/mmu_common.c: Remove BookE handling from
get_physical_address_wtlb()
  target/ppc/mmu_common.c: Simplify ppc_booke_xlate()
  target/ppc/mmu_common.c: Move BookE MMU functions together

 target/ppc/excp_helper.c |  67 +---
 target/ppc/helper.h  |   2 -
 target/ppc/internal.h|  19 +-
 target/ppc/mmu-hash32.c  |  47 +--
 target/ppc/mmu_common.c  | 731 +++
 target/ppc/mmu_helper.c  |  24 --
 target/ppc/translate.c   |  12 +-
 7 files changed, 384 insertions(+), 518 deletions(-)

-- 
2.30.9




Re: [PATCH for-9.0] ppc440_pcix: Do not expose a bridge device on PCI bus

2024-04-16 Thread BALATON Zoltan

On Tue, 16 Apr 2024, Nicholas Piggin wrote:

On Wed Apr 10, 2024 at 9:03 PM AEST, BALATON Zoltan wrote:

On Wed, 10 Apr 2024, Nicholas Piggin wrote:

On Wed Apr 10, 2024 at 9:55 AM AEST, BALATON Zoltan wrote:

Real 460EX SoC apparently does not expose a bridge device and having
it appear on PCI bus confuses an AmigaOS file system driver that uses
this to detect which machine it is running on. Since values written
here by firmware are never read, just ignore these writes and drop the
bridge device.

Signed-off-by: BALATON Zoltan 
---
This is only used by sam460ex and this fixes an issue with AmigaOS on
this machine so I'd like this to be merged for 9.0 please.


Is it a regression? Does it have a fixes: or resolves: tag?

Unless we broke it in this cycle, I would be inclined to wait,
and we can ask to put it in stable.


It's not something that broke in this cycle but since this does not affect
anything else than sam460ex I think it's OK to change this for 9.0. The
changes to 440 tlb in this cycle made sam460ex more useful to run AmigaOS
and this fixes the file system driver on it so it would make 9.0 really
usable. Otherwise people would have to wait longer until August or install
a stable update. Since this has low chance to break anything (tested with
AmogaOS and Linux and MorphOS does not boot due to do_io changes anyway) I
don't think we have to wait with this.


Hey, travelling / at a conference / on vacation for the next couple of
weeks.

It's just a bit late for hard freeze IMO, since we didn't break it
before the prior release or a bad security / crash bug. Will put it in
9.1.


Philippe already queued this (and another) patch. This fixes AmigaOS on 
sam460ex which became usable with the tlbwe changes in this cycle but it's 
not really usable without a file system driver that this patch fixes. 
Please allow this in 9.0 so users who want to try it don't have to wait a 
few months more. Sorry for sending it this late but it was reported late 
and took time to debug it.


Regards,
BALATON Zoltan



  1   2   3   4   5   6   7   8   9   10   >