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_PGSIZE(tte)     (((tte) >> 61) & 3ULL)
 | 
				
			||||||
#define TTE_PA(tte)         ((tte) & 0x1ffffffe000ULL)
 | 
					#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 {
 | 
					typedef struct SparcTLBEntry {
 | 
				
			||||||
    uint64_t tag;
 | 
					    uint64_t tag;
 | 
				
			||||||
    uint64_t tte;
 | 
					    uint64_t tte;
 | 
				
			||||||
 | 
				
			|||||||
@ -413,6 +413,7 @@ static int get_physical_address_data(CPUState *env,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    unsigned int i;
 | 
					    unsigned int i;
 | 
				
			||||||
    uint64_t context;
 | 
					    uint64_t context;
 | 
				
			||||||
 | 
					    uint64_t sfsr = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int is_user = (mmu_idx == MMU_USER_IDX ||
 | 
					    int is_user = (mmu_idx == MMU_USER_IDX ||
 | 
				
			||||||
                   mmu_idx == MMU_USER_SECONDARY_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_USER_IDX:
 | 
				
			||||||
    case MMU_KERNEL_IDX:
 | 
					    case MMU_KERNEL_IDX:
 | 
				
			||||||
        context = env->dmmu.mmu_primary_context & 0x1fff;
 | 
					        context = env->dmmu.mmu_primary_context & 0x1fff;
 | 
				
			||||||
 | 
					        sfsr |= SFSR_CT_PRIMARY;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case MMU_USER_SECONDARY_IDX:
 | 
					    case MMU_USER_SECONDARY_IDX:
 | 
				
			||||||
    case MMU_KERNEL_SECONDARY_IDX:
 | 
					    case MMU_KERNEL_SECONDARY_IDX:
 | 
				
			||||||
        context = env->dmmu.mmu_secondary_context & 0x1fff;
 | 
					        context = env->dmmu.mmu_secondary_context & 0x1fff;
 | 
				
			||||||
 | 
					        sfsr |= SFSR_CT_SECONDARY;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case MMU_NUCLEUS_IDX:
 | 
					    case MMU_NUCLEUS_IDX:
 | 
				
			||||||
 | 
					        sfsr |= SFSR_CT_NUCLEUS;
 | 
				
			||||||
 | 
					        /* FALLTHRU */
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        context = 0;
 | 
					        context = 0;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rw == 1) {
 | 
				
			||||||
 | 
					        sfsr |= SFSR_WRITE_BIT;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < 64; i++) {
 | 
					    for (i = 0; i < 64; i++) {
 | 
				
			||||||
        // ctx match, vaddr match, valid?
 | 
					        // ctx match, vaddr match, valid?
 | 
				
			||||||
        if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
 | 
					        if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            uint8_t fault_type = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // access ok?
 | 
					            // access ok?
 | 
				
			||||||
            if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
 | 
					            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;
 | 
					                env->exception_index = TT_DFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
 | 
					                DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
 | 
				
			||||||
@ -469,13 +476,17 @@ static int get_physical_address_data(CPUState *env,
 | 
				
			|||||||
                return 0;
 | 
					                return 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (env->dmmu.sfsr & 1) /* Fault status register */
 | 
					            if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
 | 
				
			||||||
                env->dmmu.sfsr = 2; /* overflow (not read before
 | 
					                sfsr |= SFSR_OW_BIT; /* overflow (not read before
 | 
				
			||||||
                                        another fault) */
 | 
					                                        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 */
 | 
					            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",
 | 
					    DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
 | 
				
			||||||
                address, context);
 | 
					                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->dmmu.tag_access = (address & ~0x1fffULL) | context;
 | 
				
			||||||
    env->exception_index = TT_DMISS;
 | 
					    env->exception_index = TT_DMISS;
 | 
				
			||||||
    return 1;
 | 
					    return 1;
 | 
				
			||||||
@ -524,10 +540,22 @@ static int get_physical_address_code(CPUState *env,
 | 
				
			|||||||
                                 address, context, physical)) {
 | 
					                                 address, context, physical)) {
 | 
				
			||||||
            // access ok?
 | 
					            // access ok?
 | 
				
			||||||
            if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
 | 
					            if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
 | 
				
			||||||
                if (env->immu.sfsr) /* Fault status register */
 | 
					                /* Fault status register */
 | 
				
			||||||
                    env->immu.sfsr = 2; /* overflow (not read before
 | 
					                if (env->immu.sfsr & SFSR_VALID_BIT) {
 | 
				
			||||||
 | 
					                    env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
 | 
				
			||||||
                                                     another fault) */
 | 
					                                                     another fault) */
 | 
				
			||||||
                env->immu.sfsr |= (is_user << 3) | 1;
 | 
					                } 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->exception_index = TT_TFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                env->immu.tag_access = (address & ~0x1fffULL) | context;
 | 
					                env->immu.tag_access = (address & ~0x1fffULL) | context;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user