summaryrefslogtreecommitdiffstats
path: root/qemu/target-ppc/mmu_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/target-ppc/mmu_helper.c')
-rw-r--r--qemu/target-ppc/mmu_helper.c132
1 files changed, 51 insertions, 81 deletions
diff --git a/qemu/target-ppc/mmu_helper.c b/qemu/target-ppc/mmu_helper.c
index 527c6adca..ff217941b 100644
--- a/qemu/target-ppc/mmu_helper.c
+++ b/qemu/target-ppc/mmu_helper.c
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "cpu.h"
#include "exec/helper-proto.h"
#include "sysemu/kvm.h"
@@ -23,28 +25,28 @@
#include "mmu-hash64.h"
#include "mmu-hash32.h"
#include "exec/cpu_ldst.h"
+#include "exec/log.h"
//#define DEBUG_MMU
//#define DEBUG_BATS
//#define DEBUG_SOFTWARE_TLB
//#define DUMP_PAGE_TABLES
-//#define DEBUG_SOFTWARE_TLB
//#define FLUSH_ALL_TLBS
#ifdef DEBUG_MMU
-# define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0)
+# define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
#else
# define LOG_MMU_STATE(cpu) do { } while (0)
#endif
#ifdef DEBUG_SOFTWARE_TLB
-# define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
+# define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
#else
# define LOG_SWTLB(...) do { } while (0)
#endif
#ifdef DEBUG_BATS
-# define LOG_BATS(...) qemu_log(__VA_ARGS__)
+# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
#else
# define LOG_BATS(...) do { } while (0)
#endif
@@ -162,7 +164,7 @@ static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
if (ctx->raddr != (hwaddr)-1ULL) {
/* all matches should have equal RPN, WIMG & PP */
if ((ctx->raddr & mmask) != (pte1 & mmask)) {
- qemu_log("Bad RPN/WIMG/PP\n");
+ qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
return -3;
}
}
@@ -508,7 +510,7 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
/* Software TLB search */
ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
#if defined(DUMP_PAGE_TABLES)
- if (qemu_log_enabled()) {
+ if (qemu_log_mask(CPU_LOG_MMU)) {
hwaddr curaddr;
uint32_t a0, a1, a2, a3;
@@ -575,8 +577,8 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
/* eciwx or ecowx */
return -4;
default:
- qemu_log("ERROR: instruction should not need "
- "address translation\n");
+ qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
+ "address translation\n");
return -4;
}
if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
@@ -658,32 +660,6 @@ static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
tlb_flush(CPU(cpu), 1);
}
-static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState *env,
- target_ulong eaddr, uint32_t pid)
-{
-#if !defined(FLUSH_ALL_TLBS)
- CPUState *cs = CPU(ppc_env_get_cpu(env));
- ppcemb_tlb_t *tlb;
- hwaddr raddr;
- target_ulong page, end;
- int i;
-
- for (i = 0; i < env->nb_tlb; i++) {
- tlb = &env->tlb.tlbe[i];
- if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
- end = tlb->EPN + tlb->size;
- for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
- tlb_flush_page(cs, page);
- }
- tlb->prot &= ~PAGE_VALID;
- break;
- }
- }
-#else
- ppc4xx_tlb_invalidate_all(env);
-#endif
-}
-
static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
target_ulong address, int rw,
int access_type)
@@ -1293,10 +1269,12 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
break;
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
+ case POWERPC_MMU_2_03:
case POWERPC_MMU_2_06:
case POWERPC_MMU_2_06a:
- case POWERPC_MMU_2_06d:
- dump_slb(f, cpu_fprintf, env);
+ case POWERPC_MMU_2_07:
+ case POWERPC_MMU_2_07a:
+ dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
break;
#endif
default:
@@ -1433,15 +1411,17 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
switch (env->mmu_model) {
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
+ case POWERPC_MMU_2_03:
case POWERPC_MMU_2_06:
case POWERPC_MMU_2_06a:
- case POWERPC_MMU_2_06d:
- return ppc_hash64_get_phys_page_debug(env, addr);
+ case POWERPC_MMU_2_07:
+ case POWERPC_MMU_2_07a:
+ return ppc_hash64_get_phys_page_debug(cpu, addr);
#endif
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
- return ppc_hash32_get_phys_page_debug(env, addr);
+ return ppc_hash32_get_phys_page_debug(cpu, addr);
default:
;
@@ -1507,6 +1487,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
int rw, int mmu_idx)
{
CPUState *cs = CPU(ppc_env_get_cpu(env));
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
mmu_ctx_t ctx;
int access_type;
int ret = 0;
@@ -1608,9 +1589,9 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
tlb_miss:
env->error_code |= ctx.key << 19;
env->spr[SPR_HASH1] = env->htab_base +
- get_pteg_offset32(env, ctx.hash[0]);
+ get_pteg_offset32(cpu, ctx.hash[0]);
env->spr[SPR_HASH2] = env->htab_base +
- get_pteg_offset32(env, ctx.hash[1]);
+ get_pteg_offset32(cpu, ctx.hash[1]);
break;
case POWERPC_MMU_SOFT_74xx:
if (rw == 1) {
@@ -1937,9 +1918,11 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
case POWERPC_MMU_601:
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
+ case POWERPC_MMU_2_03:
case POWERPC_MMU_2_06:
case POWERPC_MMU_2_06a:
- case POWERPC_MMU_2_06d:
+ case POWERPC_MMU_2_07:
+ case POWERPC_MMU_2_07a:
#endif /* defined(TARGET_PPC64) */
tlb_flush(CPU(cpu), 1);
break;
@@ -1965,25 +1948,6 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
ppc6xx_tlb_invalidate_virt(env, addr, 1);
}
break;
- case POWERPC_MMU_SOFT_4xx:
- case POWERPC_MMU_SOFT_4xx_Z:
- ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
- break;
- case POWERPC_MMU_REAL:
- cpu_abort(CPU(cpu), "No TLB for PowerPC 4xx in real mode\n");
- break;
- case POWERPC_MMU_MPC8xx:
- /* XXX: TODO */
- cpu_abort(CPU(cpu), "MPC8xx MMU model is not implemented\n");
- break;
- case POWERPC_MMU_BOOKE:
- /* XXX: TODO */
- cpu_abort(CPU(cpu), "BookE MMU model is not implemented\n");
- break;
- case POWERPC_MMU_BOOKE206:
- /* XXX: TODO */
- cpu_abort(CPU(cpu), "BookE 2.06 MMU model is not implemented\n");
- break;
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
/* tlbie invalidate TLBs for all segments */
@@ -2011,9 +1975,11 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
break;
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
+ case POWERPC_MMU_2_03:
case POWERPC_MMU_2_06:
case POWERPC_MMU_2_06a:
- case POWERPC_MMU_2_06d:
+ case POWERPC_MMU_2_07:
+ case POWERPC_MMU_2_07a:
/* tlbie invalidate TLBs for all segments */
/* XXX: given the fact that there are too many segments to invalidate,
* and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
@@ -2023,9 +1989,8 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
break;
#endif /* defined(TARGET_PPC64) */
default:
- /* XXX: TODO */
- cpu_abort(CPU(cpu), "Unknown MMU model\n");
- break;
+ /* Should never reach here with other MMU models */
+ assert(0);
}
#else
ppc_tlb_invalidate_all(env);
@@ -2041,15 +2006,14 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
env->spr[SPR_SDR1] = value;
#if defined(TARGET_PPC64)
if (env->mmu_model & POWERPC_MMU_64) {
- target_ulong htabsize = value & SDR_64_HTABSIZE;
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+ Error *local_err = NULL;
- if (htabsize > 28) {
- fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
- " stored in SDR1\n", htabsize);
- htabsize = 28;
+ ppc_hash64_set_sdr1(cpu, value, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ error_free(local_err);
}
- env->htab_mask = (1ULL << (htabsize + 18 - 7)) - 1;
- env->htab_base = value & SDR_64_HTABORG;
} else
#endif /* defined(TARGET_PPC64) */
{
@@ -2080,21 +2044,17 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
(int)srnum, value, env->sr[srnum]);
#if defined(TARGET_PPC64)
if (env->mmu_model & POWERPC_MMU_64) {
- uint64_t rb = 0, rs = 0;
+ uint64_t esid, vsid;
/* ESID = srnum */
- rb |= ((uint32_t)srnum & 0xf) << 28;
- /* Set the valid bit */
- rb |= SLB_ESID_V;
- /* Index = ESID */
- rb |= (uint32_t)srnum;
+ esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V;
/* VSID = VSID */
- rs |= (value & 0xfffffff) << 12;
+ vsid = (value & 0xfffffff) << 12;
/* flags = flags */
- rs |= ((value >> 27) & 0xf) << 8;
+ vsid |= ((value >> 27) & 0xf) << 8;
- ppc_store_slb(env, rb, rs);
+ ppc_store_slb(cpu, srnum, esid, vsid);
} else
#endif
if (env->sr[srnum] != value) {
@@ -2128,6 +2088,16 @@ void helper_tlbie(CPUPPCState *env, target_ulong addr)
ppc_tlb_invalidate_one(env, addr);
}
+void helper_tlbiva(CPUPPCState *env, target_ulong addr)
+{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+ /* tlbiva instruction only exists on BookE */
+ assert(env->mmu_model == POWERPC_MMU_BOOKE);
+ /* XXX: TODO */
+ cpu_abort(CPU(cpu), "BookE MMU model is not implemented\n");
+}
+
/* Software driven TLBs management */
/* PowerPC 602/603 software TLB load instructions helpers */
static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)