aboutsummaryrefslogtreecommitdiff
path: root/target-sparc/helper.c
diff options
context:
space:
mode:
authorIgor V. Kovalenko <igor.v.kovalenko@gmail.com>2010-05-03 11:29:44 +0400
committerBlue Swirl <blauwirbel@gmail.com>2010-05-06 23:14:26 +0300
commit2065061ede22d401aae2ce995c3af54db9d28639 (patch)
tree14413bbc4636f37834e8570928f94220d4d853a4 /target-sparc/helper.c
parent299b520cd4092be3c53f8380b81315c33927d9d3 (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.c42
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)