diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-12-05 20:29:47 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-12-05 20:29:47 +0000 |
commit | 227671c93ba454a4687ba0ddc5c7f3c55a166900 (patch) | |
tree | db7812c8473ee2f89699ab5f8c6899c80b1e04c2 /target-sparc/helper.c | |
parent | f881a0d4f6eed97eba4b9c32628f566d830ad65e (diff) |
PAGE_EXEC support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1692 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sparc/helper.c')
-rw-r--r-- | target-sparc/helper.c | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 7436e4ff40..d011de7fb7 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -75,10 +75,27 @@ static const int access_table[8][8] = { { 2, 2, 2, 0, 2, 2, 2, 0 } }; -/* 1 = write OK */ -static const int rw_table[2][8] = { - { 0, 1, 0, 1, 0, 1, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 } +static const int perm_table[2][8] = { + { + PAGE_READ, + PAGE_READ | PAGE_WRITE, + PAGE_READ | PAGE_EXEC, + PAGE_READ | PAGE_WRITE | PAGE_EXEC, + PAGE_EXEC, + PAGE_READ | PAGE_WRITE, + PAGE_READ | PAGE_EXEC, + PAGE_READ | PAGE_WRITE | PAGE_EXEC + }, + { + PAGE_READ, + PAGE_READ | PAGE_WRITE, + PAGE_READ | PAGE_EXEC, + PAGE_READ | PAGE_WRITE | PAGE_EXEC, + PAGE_EXEC, + PAGE_READ, + 0, + 0, + } }; int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot, @@ -95,7 +112,7 @@ int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot virt_addr = address & TARGET_PAGE_MASK; if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */ *physical = address; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return 0; } @@ -177,12 +194,11 @@ int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot return error_code; /* the page can be put in the TLB */ - *prot = PAGE_READ; - if (pde & PG_MODIFIED_MASK) { + *prot = perm_table[is_user][access_perms]; + if (!(pde & PG_MODIFIED_MASK)) { /* only set write access if already dirty... otherwise wait for dirty access */ - if (rw_table[is_user][access_perms]) - *prot |= PAGE_WRITE; + *prot &= ~PAGE_WRITE; } /* Even if large ptes, we map only one 4KB page in the cache to @@ -206,7 +222,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, #ifdef DEBUG_MMU printf("Translate at 0x%lx -> 0x%lx, vaddr 0x%lx\n", (long)address, (long)paddr, (long)vaddr); #endif - ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); + ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); return ret; } @@ -221,8 +237,8 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, // neverland. Fake/overridden mappings will be flushed when // switching to normal mode. vaddr = address & TARGET_PAGE_MASK; - prot = PAGE_READ | PAGE_WRITE; - ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); + prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); return ret; } else { if (rw & 2) @@ -405,7 +421,7 @@ static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */ *physical = address; - *prot = PAGE_READ; + *prot = PAGE_EXEC; return 0; } @@ -441,7 +457,7 @@ static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical return 1; } *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL); - *prot = PAGE_READ; + *prot = PAGE_EXEC; return 0; } } @@ -477,7 +493,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, #ifdef DEBUG_MMU printf("Translate at 0x%llx -> 0x%llx, vaddr 0x%llx\n", address, paddr, vaddr); #endif - ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); + ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); return ret; } // XXX |