aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2013-03-12 00:31:42 +0000
committerAlexander Graf <agraf@suse.de>2013-03-22 15:28:52 +0100
commitb344074642e58fc83635c38105f38b85fc086666 (patch)
treeb337d95844b19839e37d7dba706657e92731b2e3
parent57d0a39d98b0d0e4712e736084667bcb5aed3474 (diff)
mmu-hash*: Clean up PTE flags update
Currently the ppc_hash{32,64}_pte_update_flags() helper functions update a PTE's referenced and changed bits as necessary to reflect the access. It is somewhat long winded, though. This patch open codes them in their (single) callers, in a simpler way. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--target-ppc/mmu-hash32.c39
-rw-r--r--target-ppc/mmu-hash64.c39
2 files changed, 24 insertions, 54 deletions
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 6581d0f425..314b7d1634 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -274,31 +274,6 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
}
}
-static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, uint32_t *pte1p,
- int ret, int rwx)
-{
- int store = 0;
-
- /* Update page flags */
- if (!(*pte1p & HPTE32_R_R)) {
- /* Update accessed flag */
- *pte1p |= HPTE32_R_R;
- store = 1;
- }
- if (!(*pte1p & HPTE32_R_C)) {
- if (rwx == 1 && ret == 0) {
- /* Update changed flag */
- *pte1p |= HPTE32_R_C;
- store = 1;
- } else {
- /* Force page fault for first write access */
- ctx->prot &= ~PAGE_WRITE;
- }
- }
-
- return store;
-}
-
hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
{
return (hash * HASH_PTEG_SIZE_32) & env->htab_mask;
@@ -374,6 +349,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
target_ulong sr;
hwaddr pte_offset;
ppc_hash_pte32_t pte;
+ uint32_t new_pte1;
const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
assert((rwx == 0) || (rwx == 1) || (rwx == 2));
@@ -432,8 +408,17 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
/* 8. Update PTE referenced and changed bits if necessary */
- if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, 0, rwx) == 1) {
- ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
+ new_pte1 = pte.pte1 | HPTE32_R_R; /* set referenced bit */
+ if (rwx == 1) {
+ new_pte1 |= HPTE32_R_C; /* set changed (dirty) bit */
+ } 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;
+ }
+
+ if (new_pte1 != pte.pte1) {
+ ppc_hash32_store_hpte1(env, pte_offset, new_pte1);
}
/* Keep the matching PTE informations */
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 5607ce8dec..c76abb7d22 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -280,31 +280,6 @@ static int ppc_hash64_pte_prot(CPUPPCState *env,
return prot;
}
-static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
- uint64_t *pte1p, int ret, int rw)
-{
- int store = 0;
-
- /* Update page flags */
- if (!(*pte1p & HPTE64_R_R)) {
- /* Update accessed flag */
- *pte1p |= HPTE64_R_R;
- store = 1;
- }
- if (!(*pte1p & HPTE64_R_C)) {
- if (rw == 1 && ret == 0) {
- /* Update changed flag */
- *pte1p |= HPTE64_R_C;
- store = 1;
- } else {
- /* Force page fault for first write access */
- ctx->prot &= ~PAGE_WRITE;
- }
- }
-
- return store;
-}
-
static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off,
bool secondary, target_ulong ptem,
ppc_hash_pte64_t *pte)
@@ -393,6 +368,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
ppc_slb_t *slb;
hwaddr pte_offset;
ppc_hash_pte64_t pte;
+ uint64_t new_pte1;
int target_page_bits;
const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
@@ -440,8 +416,17 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
/* 6. Update PTE referenced and changed bits if necessary */
- if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, 0, rwx) == 1) {
- ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
+ new_pte1 = pte.pte1 | HPTE64_R_R; /* set referenced bit */
+ if (rwx == 1) {
+ new_pte1 |= HPTE64_R_C; /* set changed (dirty) bit */
+ } 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;
+ }
+
+ if (new_pte1 != pte.pte1) {
+ ppc_hash64_store_hpte1(env, pte_offset, new_pte1);
}
/* Keep the matching PTE informations */