summaryrefslogtreecommitdiff
path: root/target-ppc/mmu-hash64.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2013-03-12 00:31:47 +0000
committerAlexander Graf <agraf@suse.de>2013-03-22 15:28:53 +0100
commitf80872e21c07edd06eb343eeeefc8af404b518a6 (patch)
tree9334b1d60ca24bfed9d73b0f4b8f072cb20ec25e /target-ppc/mmu-hash64.c
parentcaa597bd9f5439cb16653119f362ad85a9f02b55 (diff)
downloadqemu-f80872e21c07edd06eb343eeeefc8af404b518a6.tar.gz
mmu-hash64: Implement Virtual Page Class Key Protection
Version 2.06 of the Power architecture describes an additional page protection mechanism. Each virtual page has a "class" (0-31) recorded in the PTE. The AMR register contains bits which can prohibit reads and/or writes on a class by class basis. Interestingly, the AMR is userspace readable and writable, however user mode writes are masked by the contents of the UAMOR which is privileged. This patch implements this protection mechanism, along with the AMR and UAMOR SPRs. The architecture also specifies a hypervisor-privileged AMOR register which masks user and supervisor writes to the AMR and UAMOR. We leave this out for now, since we don't at present model hypervisor mode correctly in any case. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> [agraf: fix 32-bit hosts] Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc/mmu-hash64.c')
-rw-r--r--target-ppc/mmu-hash64.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index f18c98f021..43ccf456e3 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -275,6 +275,33 @@ static int ppc_hash64_pte_prot(CPUPPCState *env,
return prot;
}
+static int ppc_hash64_amr_prot(CPUPPCState *env, ppc_hash_pte64_t pte)
+{
+ int key, amrbits;
+ int prot = PAGE_EXEC;
+
+
+ /* Only recent MMUs implement Virtual Page Class Key Protection */
+ if (!(env->mmu_model & POWERPC_MMU_AMR)) {
+ return PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ }
+
+ key = HPTE64_R_KEY(pte.pte1);
+ amrbits = (env->spr[SPR_AMR] >> 2*(31 - key)) & 0x3;
+
+ /* fprintf(stderr, "AMR protection: key=%d AMR=0x%" PRIx64 "\n", key, */
+ /* env->spr[SPR_AMR]); */
+
+ if (amrbits & 0x2) {
+ prot |= PAGE_WRITE;
+ }
+ if (amrbits & 0x1) {
+ prot |= PAGE_READ;
+ }
+
+ return prot;
+}
+
static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off,
bool secondary, target_ulong ptem,
ppc_hash_pte64_t *pte)
@@ -375,7 +402,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr,
ppc_slb_t *slb;
hwaddr pte_offset;
ppc_hash_pte64_t pte;
- int prot;
+ int pp_prot, amr_prot, prot;
uint64_t new_pte1;
const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
hwaddr raddr;
@@ -437,7 +464,9 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr,
/* 5. Check access permissions */
- prot = ppc_hash64_pte_prot(env, slb, pte);
+ pp_prot = ppc_hash64_pte_prot(env, slb, pte);
+ amr_prot = ppc_hash64_amr_prot(env, pte);
+ prot = pp_prot & amr_prot;
if ((need_prot[rwx] & ~prot) != 0) {
/* Access right violation */
@@ -446,14 +475,21 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr,
env->exception_index = POWERPC_EXCP_ISI;
env->error_code = 0x08000000;
} else {
+ target_ulong dsisr = 0;
+
env->exception_index = POWERPC_EXCP_DSI;
env->error_code = 0;
env->spr[SPR_DAR] = eaddr;
+ if (need_prot[rwx] & ~pp_prot) {
+ dsisr |= 0x08000000;
+ }
if (rwx == 1) {
- env->spr[SPR_DSISR] = 0x0A000000;
- } else {
- env->spr[SPR_DSISR] = 0x08000000;
+ dsisr |= 0x02000000;
+ }
+ if (need_prot[rwx] & ~amr_prot) {
+ dsisr |= 0x00200000;
}
+ env->spr[SPR_DSISR] = dsisr;
}
return 1;
}