diff options
author | Igor V. Kovalenko <igor.v.kovalenko@gmail.com> | 2010-05-03 11:29:44 +0400 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2010-05-06 23:14:26 +0300 |
commit | 2065061ede22d401aae2ce995c3af54db9d28639 (patch) | |
tree | 14413bbc4636f37834e8570928f94220d4d853a4 /target-sparc/helper.c | |
parent | 299b520cd4092be3c53f8380b81315c33927d9d3 (diff) |
sparc64: handle asi referencing nucleus and secondary MMU contexts
- increase max supported MMU modes to 6
- handle nucleus context asi
- handle secondary context asi
- handle non-faulting loads from secondary context
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-sparc/helper.c')
-rw-r--r-- | target-sparc/helper.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 4ece01b844..cac6cadcd0 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -420,21 +420,32 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb, static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot, - target_ulong address, int rw, int is_user) + target_ulong address, int rw, int mmu_idx) { unsigned int i; uint64_t context; + int is_user = (mmu_idx == MMU_USER_IDX || + mmu_idx == MMU_USER_SECONDARY_IDX); + if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */ *physical = ultrasparc_truncate_physical(address); *prot = PAGE_READ | PAGE_WRITE; return 0; } - if (env->tl == 0) { + switch(mmu_idx) { + case MMU_USER_IDX: + case MMU_KERNEL_IDX: context = env->dmmu.mmu_primary_context & 0x1fff; - } else { + break; + case MMU_USER_SECONDARY_IDX: + case MMU_KERNEL_SECONDARY_IDX: + context = env->dmmu.mmu_secondary_context & 0x1fff; + break; + case MMU_NUCLEUS_IDX: context = 0; + break; } for (i = 0; i < 64; i++) { @@ -482,11 +493,14 @@ static int get_physical_address_data(CPUState *env, static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot, - target_ulong address, int is_user) + target_ulong address, int mmu_idx) { unsigned int i; uint64_t context; + int is_user = (mmu_idx == MMU_USER_IDX || + mmu_idx == MMU_USER_SECONDARY_IDX); + if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) { /* IMMU disabled */ *physical = ultrasparc_truncate_physical(address); @@ -495,8 +509,10 @@ static int get_physical_address_code(CPUState *env, } if (env->tl == 0) { + /* PRIMARY context */ context = env->dmmu.mmu_primary_context & 0x1fff; } else { + /* NUCLEUS context */ context = 0; } @@ -535,17 +551,15 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical, target_ulong address, int rw, int mmu_idx, target_ulong *page_size) { - int is_user = mmu_idx == MMU_USER_IDX; - /* ??? We treat everything as a small page, then explicitly flush everything when an entry is evicted. */ *page_size = TARGET_PAGE_SIZE; if (rw == 2) return get_physical_address_code(env, physical, prot, address, - is_user); + mmu_idx); else return get_physical_address_data(env, physical, prot, address, rw, - is_user); + mmu_idx); } /* Perform address translation */ @@ -659,21 +673,27 @@ void dump_mmu(CPUState *env) #if !defined(CONFIG_USER_ONLY) -target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) +target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr, + int mmu_idx) { target_phys_addr_t phys_addr; target_ulong page_size; int prot, access_index; if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, - MMU_KERNEL_IDX, &page_size) != 0) + mmu_idx, &page_size) != 0) if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, - 0, MMU_KERNEL_IDX, &page_size) != 0) + 0, mmu_idx, &page_size) != 0) return -1; if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) return -1; return phys_addr; } + +target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) +{ + return cpu_get_phys_page_nofault(env, addr, MMU_KERNEL_IDX); +} #endif void cpu_reset(CPUSPARCState *env) |