[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 32/32] mmu-hash64: Merge translate and fault handling
From: |
David Gibson |
Subject: |
[Qemu-ppc] [PATCH 32/32] mmu-hash64: Merge translate and fault handling functions |
Date: |
Fri, 15 Feb 2013 19:01:22 +1100 |
ppc_hash64_handle_mmu_fault() is now the only caller of
ppc_hash64_translate(), so this patch combines them together. This means
that instead of one returning a variety of non-obvious error codes which
then get translated into the various mmu exception conditions, we can
just generate the exceptions as we discover problems in the translation
path. This also removes the last usage of mmu_ctx_hash64.
Signed-off-by: David Gibson <address@hidden>
---
target-ppc/mmu-hash64.c | 150 +++++++++++++++++------------------------------
1 file changed, 55 insertions(+), 95 deletions(-)
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 3f68933..c34519e 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -40,11 +40,6 @@
# define LOG_SLB(...) do { } while (0)
#endif
-struct mmu_ctx_hash64 {
- hwaddr raddr; /* Real address */
- int prot; /* Protection bits */
-};
-
/*
* SLB handling
*/
@@ -378,14 +373,16 @@ static hwaddr ppc_hash64_pte_real_address(ppc_slb_t *slb,
return (pte.pte1 & HPTE_R_RPN) | pageoff;
}
-static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
- target_ulong eaddr, int rwx)
+int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr,
+ int rwx, int mmu_idx)
{
ppc_slb_t *slb;
hwaddr pte_offset;
ppc_hash_pte64_t pte;
+ int prot;
uint64_t new_pte1;
const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
+ hwaddr raddr;
assert((rwx == 0) || (rwx == 1) || (rwx == 2));
@@ -393,8 +390,10 @@ static int ppc_hash64_translate(CPUPPCState *env, struct
mmu_ctx_hash64 *ctx,
if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
/* Translation is off */
/* In real mode the top 4 effective address bits are ignored */
- ctx->raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
- ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
+ raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
+ tlb_set_page(env, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
+ PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,
+ TARGET_PAGE_SIZE);
return 0;
}
@@ -402,31 +401,67 @@ static int ppc_hash64_translate(CPUPPCState *env, struct
mmu_ctx_hash64 *ctx,
slb = slb_lookup(env, eaddr);
if (!slb) {
- return -5;
+ if (rwx == 2) {
+ env->exception_index = POWERPC_EXCP_ISEG;
+ env->error_code = 0;
+ } else {
+ env->exception_index = POWERPC_EXCP_DSEG;
+ env->error_code = 0;
+ env->spr[SPR_DAR] = eaddr;
+ }
+ return 1;
}
/* 3. Check for segment level no-execute violation */
if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) {
- return -3;
+ env->exception_index = POWERPC_EXCP_ISI;
+ env->error_code = 0x10000000;
+ return 1;
}
/* 4. Locate the PTE in the hash table */
pte_offset = ppc_hash64_htab_lookup(env, slb, eaddr, &pte);
if (pte_offset == -1) {
- return -1;
+ if (rwx == 2) {
+ env->exception_index = POWERPC_EXCP_ISI;
+ env->error_code = 0x40000000;
+ } else {
+ env->exception_index = POWERPC_EXCP_DSI;
+ env->error_code = 0;
+ env->spr[SPR_DAR] = eaddr;
+ if (rwx == 1) {
+ env->spr[SPR_DSISR] = 0x42000000;
+ } else {
+ env->spr[SPR_DSISR] = 0x40000000;
+ }
+ }
+ return 1;
}
LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
/* 5. Check access permissions */
- ctx->prot = ppc_hash64_pte_prot(env, slb, pte);
+ prot = ppc_hash64_pte_prot(env, slb, pte);
assert((rwx == 0) || (rwx == 1) || (rwx == 2));
- if ((need_prot[rwx] & ~ctx->prot) != 0) {
+ if ((need_prot[rwx] & ~prot) != 0) {
/* Access right violation */
LOG_MMU("PTE access rejected\n");
- return -2;
+ if (rwx == 2) {
+ env->exception_index = POWERPC_EXCP_ISI;
+ env->error_code = 0x08000000;
+ } else {
+ env->exception_index = POWERPC_EXCP_DSI;
+ env->error_code = 0;
+ env->spr[SPR_DAR] = eaddr;
+ if (rwx == 1) {
+ env->spr[SPR_DSISR] = 0x0A000000;
+ } else {
+ env->spr[SPR_DSISR] = 0x08000000;
+ }
+ }
+ return 1;
}
LOG_MMU("PTE access granted !\n");
@@ -439,7 +474,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct
mmu_ctx_hash64 *ctx,
} else {
/* Treat the page as read-only for now, so that a later write
* will pass through this function again to set the C bit */
- ctx->prot &= ~PAGE_WRITE;
+ prot &= ~PAGE_WRITE;
}
if (new_pte1 != pte.pte1) {
@@ -447,7 +482,10 @@ static int ppc_hash64_translate(CPUPPCState *env, struct
mmu_ctx_hash64 *ctx,
}
/* 7. Compute the final address from PTE and offset in page */
- ctx->raddr = ppc_hash64_pte_real_address(slb, pte, eaddr);
+ raddr = ppc_hash64_pte_real_address(slb, pte, eaddr);
+
+ tlb_set_page(env, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
+ prot, mmu_idx, TARGET_PAGE_SIZE);
return 0;
}
@@ -475,81 +513,3 @@ hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env,
target_ulong addr)
return ppc_hash64_pte_real_address(slb, pte, addr) & TARGET_PAGE_MASK;
}
-
-int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int
rwx,
- int mmu_idx)
-{
- struct mmu_ctx_hash64 ctx;
- int ret = 0;
-
- ret = ppc_hash64_translate(env, &ctx, address, rwx);
- if (ret == 0) {
- tlb_set_page(env, address & TARGET_PAGE_MASK,
- ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
- mmu_idx, TARGET_PAGE_SIZE);
- ret = 0;
- } else if (ret < 0) {
- LOG_MMU_STATE(env);
- if (rwx == 2) {
- switch (ret) {
- case -1:
- env->exception_index = POWERPC_EXCP_ISI;
- env->error_code = 0x40000000;
- break;
- case -2:
- /* Access rights violation */
- env->exception_index = POWERPC_EXCP_ISI;
- env->error_code = 0x08000000;
- break;
- case -3:
- /* No execute protection violation */
- env->exception_index = POWERPC_EXCP_ISI;
- env->error_code = 0x10000000;
- break;
- case -5:
- /* No match in segment table */
- env->exception_index = POWERPC_EXCP_ISEG;
- env->error_code = 0;
- break;
- }
- } else {
- switch (ret) {
- case -1:
- /* No matches in page tables or TLB */
- env->exception_index = POWERPC_EXCP_DSI;
- env->error_code = 0;
- env->spr[SPR_DAR] = address;
- if (rwx == 1) {
- env->spr[SPR_DSISR] = 0x42000000;
- } else {
- env->spr[SPR_DSISR] = 0x40000000;
- }
- break;
- case -2:
- /* Access rights violation */
- env->exception_index = POWERPC_EXCP_DSI;
- env->error_code = 0;
- env->spr[SPR_DAR] = address;
- if (rwx == 1) {
- env->spr[SPR_DSISR] = 0x0A000000;
- } else {
- env->spr[SPR_DSISR] = 0x08000000;
- }
- break;
- case -5:
- /* No match in segment table */
- env->exception_index = POWERPC_EXCP_DSEG;
- env->error_code = 0;
- env->spr[SPR_DAR] = address;
- break;
- }
- }
-#if 0
- printf("%s: set exception to %d %02x\n", __func__,
- env->exception, env->error_code);
-#endif
- ret = 1;
- }
-
- return ret;
-}
--
1.7.10.4
- [Qemu-ppc] [PATCH 27/32] mmu-hash64: Don't update PTE flags when permission is denied, (continued)
- [Qemu-ppc] [PATCH 27/32] mmu-hash64: Don't update PTE flags when permission is denied, David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 03/32] target-ppc: Move SLB handling into a mmu-hash64.c, David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 26/32] mmu-hash64: Clean up ppc_hash64_htab_lookup(), David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 23/32] mmu-hash64: Separate PTEG searching from permissions checking, David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 22/32] mmu-hash64: Separate VA matching from permission checking in pte64_check(), David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 30/32] mmu-hash64: Correctly mask RPN from hash PTE, David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 25/32] mmu-hash64: Remove permission checking from find_pte64(), David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 28/32] mmu-hash64: Clean up PTE permission checking, David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 29/32] mmu-hash64: Clean up PTE flags update, David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 31/32] mmu-hash64: Don't use full ppc_hash64_translate() path for get_phys_page_debug(), David Gibson, 2013/02/15
- [Qemu-ppc] [PATCH 32/32] mmu-hash64: Merge translate and fault handling functions,
David Gibson <=
- Re: [Qemu-ppc] [0/32] RFC: 64-bit hash mmu implementation clean up, Alexander Graf, 2013/02/23