mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
SPARC64: SFSR cleanup and fix
Add macros for SFSR fields and use macros instead of magic numbers. Also fix the update of the register fields on MMU faults. Signed-off-by: Tsuneo Saito <tsnsaito@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
06e12b6503
commit
ccc76c24ef
@ -309,6 +309,28 @@ enum {
|
||||
#define TTE_PGSIZE(tte) (((tte) >> 61) & 3ULL)
|
||||
#define TTE_PA(tte) ((tte) & 0x1ffffffe000ULL)
|
||||
|
||||
#define SFSR_NF_BIT (1ULL << 24) /* JPS1 NoFault */
|
||||
#define SFSR_TM_BIT (1ULL << 15) /* JPS1 TLB Miss */
|
||||
#define SFSR_FT_VA_IMMU_BIT (1ULL << 13) /* USIIi VA out of range (IMMU) */
|
||||
#define SFSR_FT_VA_DMMU_BIT (1ULL << 12) /* USIIi VA out of range (DMMU) */
|
||||
#define SFSR_FT_NFO_BIT (1ULL << 11) /* NFO page access */
|
||||
#define SFSR_FT_ILL_BIT (1ULL << 10) /* illegal LDA/STA ASI */
|
||||
#define SFSR_FT_ATOMIC_BIT (1ULL << 9) /* atomic op on noncacheable area */
|
||||
#define SFSR_FT_NF_E_BIT (1ULL << 8) /* NF access on side effect area */
|
||||
#define SFSR_FT_PRIV_BIT (1ULL << 7) /* privilege violation */
|
||||
#define SFSR_PR_BIT (1ULL << 3) /* privilege mode */
|
||||
#define SFSR_WRITE_BIT (1ULL << 2) /* write access mode */
|
||||
#define SFSR_OW_BIT (1ULL << 1) /* status overwritten */
|
||||
#define SFSR_VALID_BIT (1ULL << 0) /* status valid */
|
||||
|
||||
#define SFSR_ASI_SHIFT 16 /* 23:16 ASI value */
|
||||
#define SFSR_ASI_MASK (0xffULL << SFSR_ASI_SHIFT)
|
||||
#define SFSR_CT_PRIMARY (0ULL << 4) /* 5:4 context type */
|
||||
#define SFSR_CT_SECONDARY (1ULL << 4)
|
||||
#define SFSR_CT_NUCLEUS (2ULL << 4)
|
||||
#define SFSR_CT_NOTRANS (3ULL << 4)
|
||||
#define SFSR_CT_MASK (3ULL << 4)
|
||||
|
||||
typedef struct SparcTLBEntry {
|
||||
uint64_t tag;
|
||||
uint64_t tte;
|
||||
|
@ -413,6 +413,7 @@ static int get_physical_address_data(CPUState *env,
|
||||
{
|
||||
unsigned int i;
|
||||
uint64_t context;
|
||||
uint64_t sfsr = 0;
|
||||
|
||||
int is_user = (mmu_idx == MMU_USER_IDX ||
|
||||
mmu_idx == MMU_USER_SECONDARY_IDX);
|
||||
@ -427,26 +428,32 @@ static int get_physical_address_data(CPUState *env,
|
||||
case MMU_USER_IDX:
|
||||
case MMU_KERNEL_IDX:
|
||||
context = env->dmmu.mmu_primary_context & 0x1fff;
|
||||
sfsr |= SFSR_CT_PRIMARY;
|
||||
break;
|
||||
case MMU_USER_SECONDARY_IDX:
|
||||
case MMU_KERNEL_SECONDARY_IDX:
|
||||
context = env->dmmu.mmu_secondary_context & 0x1fff;
|
||||
sfsr |= SFSR_CT_SECONDARY;
|
||||
break;
|
||||
case MMU_NUCLEUS_IDX:
|
||||
sfsr |= SFSR_CT_NUCLEUS;
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
context = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rw == 1) {
|
||||
sfsr |= SFSR_WRITE_BIT;
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
// ctx match, vaddr match, valid?
|
||||
if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
|
||||
|
||||
uint8_t fault_type = 0;
|
||||
|
||||
// access ok?
|
||||
if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
|
||||
fault_type |= 1; /* privilege violation */
|
||||
sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
|
||||
env->exception_index = TT_DFAULT;
|
||||
|
||||
DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
|
||||
@ -469,13 +476,17 @@ static int get_physical_address_data(CPUState *env,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (env->dmmu.sfsr & 1) /* Fault status register */
|
||||
env->dmmu.sfsr = 2; /* overflow (not read before
|
||||
another fault) */
|
||||
if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
|
||||
sfsr |= SFSR_OW_BIT; /* overflow (not read before
|
||||
another fault) */
|
||||
}
|
||||
|
||||
env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
|
||||
if (env->pstate & PS_PRIV) {
|
||||
sfsr |= SFSR_PR_BIT;
|
||||
}
|
||||
|
||||
env->dmmu.sfsr |= (fault_type << 7);
|
||||
/* FIXME: ASI field in SFSR must be set */
|
||||
env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
|
||||
|
||||
env->dmmu.sfar = address; /* Fault address register */
|
||||
|
||||
@ -488,6 +499,11 @@ static int get_physical_address_data(CPUState *env,
|
||||
DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
|
||||
address, context);
|
||||
|
||||
/*
|
||||
* On MMU misses:
|
||||
* - UltraSPARC IIi: SFSR and SFAR unmodified
|
||||
* - JPS1: SFAR updated and some fields of SFSR updated
|
||||
*/
|
||||
env->dmmu.tag_access = (address & ~0x1fffULL) | context;
|
||||
env->exception_index = TT_DMISS;
|
||||
return 1;
|
||||
@ -524,10 +540,22 @@ static int get_physical_address_code(CPUState *env,
|
||||
address, context, physical)) {
|
||||
// access ok?
|
||||
if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
|
||||
if (env->immu.sfsr) /* Fault status register */
|
||||
env->immu.sfsr = 2; /* overflow (not read before
|
||||
another fault) */
|
||||
env->immu.sfsr |= (is_user << 3) | 1;
|
||||
/* Fault status register */
|
||||
if (env->immu.sfsr & SFSR_VALID_BIT) {
|
||||
env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
|
||||
another fault) */
|
||||
} else {
|
||||
env->immu.sfsr = 0;
|
||||
}
|
||||
if (env->pstate & PS_PRIV) {
|
||||
env->immu.sfsr |= SFSR_PR_BIT;
|
||||
}
|
||||
if (env->tl > 0) {
|
||||
env->immu.sfsr |= SFSR_CT_NUCLEUS;
|
||||
}
|
||||
|
||||
/* FIXME: ASI field in SFSR must be set */
|
||||
env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
|
||||
env->exception_index = TT_TFAULT;
|
||||
|
||||
env->immu.tag_access = (address & ~0x1fffULL) | context;
|
||||
|
Loading…
Reference in New Issue
Block a user