diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2013-03-12 00:31:38 +0000 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2013-03-22 15:28:52 +0100 |
commit | 87dc3fd13e9c573fc435678973d8eb9726d50c3b (patch) | |
tree | ce8cd9f7db1faababf5278f927778a0bc1b3f14f /target-ppc/mmu-hash32.c | |
parent | 59acbe28552eb7bd7be75b22b3f3de93d7d40556 (diff) | |
download | qemu-87dc3fd13e9c573fc435678973d8eb9726d50c3b.zip qemu-87dc3fd13e9c573fc435678973d8eb9726d50c3b.tar.gz qemu-87dc3fd13e9c573fc435678973d8eb9726d50c3b.tar.bz2 |
mmu-hash*: Don't update PTE flags when permission is denied
BEHAVIOUR CHANGE
Currently if ppc_hash{32,64}_translate() finds a PTE matching the given
virtual address, it will always update the PTE's R & C (Referenced and
Changed) bits. This happens even if the PTE's permissions mean we are
about to deny the translation.
This is clearly a bug, although we get away with it because:
a) It will only incorrectly set, never reset the bits, which should not
cause guest correctness problems.
b) Linux guests never use the R & C bits anyway.
This patch fixes the behaviour, only updating R & C when access is granted
by the PTE.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc/mmu-hash32.c')
-rw-r--r-- | target-ppc/mmu-hash32.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c index 3488092..ae606fd 100644 --- a/target-ppc/mmu-hash32.c +++ b/target-ppc/mmu-hash32.c @@ -439,15 +439,17 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, ctx->raddr = pte.pte1; ctx->prot = access; ret = ppc_hash32_check_prot(ctx->prot, rwx); - if (ret == 0) { - /* Access granted */ - LOG_MMU("PTE access granted !\n"); - } else { + + if (ret) { /* Access right violation */ LOG_MMU("PTE access rejected\n"); + return ret; } - /* Update page flags */ + LOG_MMU("PTE access granted !\n"); + + /* 8. Update PTE referenced and changed bits if necessary */ + if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) { ppc_hash32_store_hpte1(env, pte_offset, pte.pte1); } |