Merge PowerPC 405 MMU model.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2554 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									1d0a48fb92
								
							
						
					
					
						commit
						a8dea12f45
					
				@ -549,8 +549,6 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
 | 
				
			|||||||
            if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
 | 
					            if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
 | 
				
			||||||
                /* Software TLB search */
 | 
					                /* Software TLB search */
 | 
				
			||||||
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
 | 
					                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
 | 
				
			||||||
            } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
 | 
					 | 
				
			||||||
                /* XXX: TODO */
 | 
					 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
#if defined (DEBUG_MMU)
 | 
					#if defined (DEBUG_MMU)
 | 
				
			||||||
                if (loglevel > 0) {
 | 
					                if (loglevel > 0) {
 | 
				
			||||||
@ -632,6 +630,115 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
 | 
				
			||||||
 | 
					                                 uint32_t address, int rw, int access_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ppcemb_tlb_t *tlb;
 | 
				
			||||||
 | 
					    target_phys_addr_t raddr;
 | 
				
			||||||
 | 
					    target_ulong mask;
 | 
				
			||||||
 | 
					    int i, ret, zsel, zpr;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    ret = -6;
 | 
				
			||||||
 | 
					    for (i = 0; i < env->nb_tlb; i++) {
 | 
				
			||||||
 | 
					        tlb = &env->tlb[i].tlbe;
 | 
				
			||||||
 | 
					        /* Check valid flag */
 | 
				
			||||||
 | 
					        if (!(tlb->prot & PAGE_VALID)) {
 | 
				
			||||||
 | 
					            if (loglevel)
 | 
				
			||||||
 | 
					                fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        mask = ~(tlb->size - 1);
 | 
				
			||||||
 | 
					        if (loglevel) {
 | 
				
			||||||
 | 
					            fprintf(logfile, "%s: TLB %d address %08x PID %04x <=> "
 | 
				
			||||||
 | 
					                    "%08x %08x %04x\n",
 | 
				
			||||||
 | 
					                    __func__, i, address, env->spr[SPR_40x_PID],
 | 
				
			||||||
 | 
					                    tlb->EPN, mask, tlb->PID);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        /* Check PID */
 | 
				
			||||||
 | 
					        if (tlb->PID != 0 && tlb->PID != env->spr[SPR_40x_PID])
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        /* Check effective address */
 | 
				
			||||||
 | 
					        if ((address & mask) != tlb->EPN)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        raddr = (tlb->RPN & mask) | (address & ~mask);
 | 
				
			||||||
 | 
					        zsel = (tlb->attr >> 4) & 0xF;
 | 
				
			||||||
 | 
					        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
 | 
				
			||||||
 | 
					        if (loglevel) {
 | 
				
			||||||
 | 
					            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
 | 
				
			||||||
 | 
					                    __func__, i, zsel, zpr, rw, tlb->attr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (access_type == ACCESS_CODE) {
 | 
				
			||||||
 | 
					            /* Check execute enable bit */
 | 
				
			||||||
 | 
					            switch (zpr) {
 | 
				
			||||||
 | 
					            case 0x0:
 | 
				
			||||||
 | 
					                if (msr_pr) {
 | 
				
			||||||
 | 
					                    ret = -3;
 | 
				
			||||||
 | 
					                    ctx->prot = 0;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                /* No break here */
 | 
				
			||||||
 | 
					            case 0x1:
 | 
				
			||||||
 | 
					            case 0x2:
 | 
				
			||||||
 | 
					                /* Check from TLB entry */
 | 
				
			||||||
 | 
					                if (!(tlb->prot & PAGE_EXEC)) {
 | 
				
			||||||
 | 
					                    ret = -3;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    if (tlb->prot & PAGE_WRITE)
 | 
				
			||||||
 | 
					                        ctx->prot = PAGE_READ | PAGE_WRITE;
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                        ctx->prot = PAGE_READ;
 | 
				
			||||||
 | 
					                    ret = 0;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0x3:
 | 
				
			||||||
 | 
					                /* All accesses granted */
 | 
				
			||||||
 | 
					                ret = 0;
 | 
				
			||||||
 | 
					                ctx->prot = PAGE_READ | PAGE_WRITE;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            switch (zpr) {
 | 
				
			||||||
 | 
					            case 0x0:
 | 
				
			||||||
 | 
					                if (msr_pr) {
 | 
				
			||||||
 | 
					                    ret = -2;
 | 
				
			||||||
 | 
					                    ctx->prot = 0;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                /* No break here */
 | 
				
			||||||
 | 
					            case 0x1:
 | 
				
			||||||
 | 
					            case 0x2:
 | 
				
			||||||
 | 
					                /* Check from TLB entry */
 | 
				
			||||||
 | 
					                /* Check write protection bit */
 | 
				
			||||||
 | 
					                if (rw && !(tlb->prot & PAGE_WRITE)) {
 | 
				
			||||||
 | 
					                    ret = -2;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    ret = 2;
 | 
				
			||||||
 | 
					                    if (tlb->prot & PAGE_WRITE)
 | 
				
			||||||
 | 
					                        ctx->prot = PAGE_READ | PAGE_WRITE;
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                        ctx->prot = PAGE_READ;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 0x3:
 | 
				
			||||||
 | 
					                /* All accesses granted */
 | 
				
			||||||
 | 
					                ret = 2;
 | 
				
			||||||
 | 
					                ctx->prot = PAGE_READ | PAGE_WRITE;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (ret >= 0) {
 | 
				
			||||||
 | 
					            ctx->raddr = raddr;
 | 
				
			||||||
 | 
					            if (loglevel) {
 | 
				
			||||||
 | 
					                fprintf(logfile, "%s: access granted " ADDRX " => " REGX
 | 
				
			||||||
 | 
					                        " %d\n", __func__, address, ctx->raddr, ctx->prot);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int check_physical (CPUState *env, mmu_ctx_t *ctx,
 | 
					static int check_physical (CPUState *env, mmu_ctx_t *ctx,
 | 
				
			||||||
                           target_ulong eaddr, int rw)
 | 
					                           target_ulong eaddr, int rw)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -682,6 +789,9 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
 | 
				
			|||||||
        /* No address translation */
 | 
					        /* No address translation */
 | 
				
			||||||
        ret = check_physical(env, ctx, eaddr, rw);
 | 
					        ret = check_physical(env, ctx, eaddr, rw);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
					        switch (PPC_MMU(env)) {
 | 
				
			||||||
 | 
					        case PPC_FLAGS_MMU_32B:
 | 
				
			||||||
 | 
					        case PPC_FLAGS_MMU_SOFT_6xx:
 | 
				
			||||||
            /* Try to find a BAT */
 | 
					            /* Try to find a BAT */
 | 
				
			||||||
            ret = -1;
 | 
					            ret = -1;
 | 
				
			||||||
            if (check_BATs)
 | 
					            if (check_BATs)
 | 
				
			||||||
@ -690,6 +800,16 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
 | 
				
			|||||||
                /* We didn't match any BAT entry */
 | 
					                /* We didn't match any BAT entry */
 | 
				
			||||||
                ret = get_segment(env, ctx, eaddr, rw, access_type);
 | 
					                ret = get_segment(env, ctx, eaddr, rw, access_type);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case PPC_FLAGS_MMU_SOFT_4xx:
 | 
				
			||||||
 | 
					            ret = mmu4xx_get_physical_address(env, ctx, eaddr,
 | 
				
			||||||
 | 
					                                              rw, access_type);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            /* XXX: TODO */
 | 
				
			||||||
 | 
					            cpu_abort(env, "MMU model not implemented\n");
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
    if (loglevel > 0) {
 | 
					    if (loglevel > 0) {
 | 
				
			||||||
@ -753,7 +873,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
 | 
				
			|||||||
                    error_code = 1 << 18;
 | 
					                    error_code = 1 << 18;
 | 
				
			||||||
                    goto tlb_miss;
 | 
					                    goto tlb_miss;
 | 
				
			||||||
                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
 | 
					                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
 | 
				
			||||||
                    /* XXX: TODO */
 | 
					                    exception = EXCP_40x_ITLBMISS;
 | 
				
			||||||
 | 
					                    error_code = 0;
 | 
				
			||||||
 | 
					                    env->spr[SPR_40x_DEAR] = address;
 | 
				
			||||||
 | 
					                    env->spr[SPR_40x_ESR] = 0x00000000;
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    error_code = 0x40000000;
 | 
					                    error_code = 0x40000000;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -799,7 +922,13 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
 | 
				
			|||||||
                    /* Do not alter DAR nor DSISR */
 | 
					                    /* Do not alter DAR nor DSISR */
 | 
				
			||||||
                    goto out;
 | 
					                    goto out;
 | 
				
			||||||
                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
 | 
					                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
 | 
				
			||||||
                    /* XXX: TODO */
 | 
					                    exception = EXCP_40x_DTLBMISS;
 | 
				
			||||||
 | 
					                    error_code = 0;
 | 
				
			||||||
 | 
					                    env->spr[SPR_40x_DEAR] = address;
 | 
				
			||||||
 | 
					                    if (rw)
 | 
				
			||||||
 | 
					                        env->spr[SPR_40x_ESR] = 0x00800000;
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                        env->spr[SPR_40x_ESR] = 0x00000000;
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    error_code = 0x40000000;
 | 
					                    error_code = 0x40000000;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -1518,9 +1647,7 @@ void do_interrupt (CPUState *env)
 | 
				
			|||||||
        switch (PPC_EXCP(env)) {
 | 
					        switch (PPC_EXCP(env)) {
 | 
				
			||||||
        case PPC_FLAGS_EXCP_40x:
 | 
					        case PPC_FLAGS_EXCP_40x:
 | 
				
			||||||
            /* DTLBMISS on 4xx */
 | 
					            /* DTLBMISS on 4xx */
 | 
				
			||||||
            /* XXX: TODO */
 | 
					            msr &= ~0xFFFF0000;
 | 
				
			||||||
            cpu_abort(env,
 | 
					 | 
				
			||||||
                      "40x DTLBMISS exception is not implemented yet !\n");
 | 
					 | 
				
			||||||
            goto store_next;
 | 
					            goto store_next;
 | 
				
			||||||
        case PPC_FLAGS_EXCP_602:
 | 
					        case PPC_FLAGS_EXCP_602:
 | 
				
			||||||
        case PPC_FLAGS_EXCP_603:
 | 
					        case PPC_FLAGS_EXCP_603:
 | 
				
			||||||
@ -1538,9 +1665,7 @@ void do_interrupt (CPUState *env)
 | 
				
			|||||||
        switch (PPC_EXCP(env)) {
 | 
					        switch (PPC_EXCP(env)) {
 | 
				
			||||||
        case PPC_FLAGS_EXCP_40x:
 | 
					        case PPC_FLAGS_EXCP_40x:
 | 
				
			||||||
            /* ITLBMISS on 4xx */
 | 
					            /* ITLBMISS on 4xx */
 | 
				
			||||||
            /* XXX: TODO */
 | 
					            msr &= ~0xFFFF0000;
 | 
				
			||||||
            cpu_abort(env,
 | 
					 | 
				
			||||||
                      "40x ITLBMISS exception is not implemented yet !\n");
 | 
					 | 
				
			||||||
            goto store_next;
 | 
					            goto store_next;
 | 
				
			||||||
        case PPC_FLAGS_EXCP_602:
 | 
					        case PPC_FLAGS_EXCP_602:
 | 
				
			||||||
        case PPC_FLAGS_EXCP_603:
 | 
					        case PPC_FLAGS_EXCP_603:
 | 
				
			||||||
 | 
				
			|||||||
@ -2365,65 +2365,139 @@ void do_load_6xx_tlb (int is_code)
 | 
				
			|||||||
                     way, is_code, CMP, RPN);
 | 
					                     way, is_code, CMP, RPN);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static target_ulong booke_tlb_to_page_size (int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return 1024 << (2 * size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int booke_page_size_to_tlb (target_ulong page_size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (page_size) {
 | 
				
			||||||
 | 
					    case 0x00000400UL:
 | 
				
			||||||
 | 
					        size = 0x0;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x00001000UL:
 | 
				
			||||||
 | 
					        size = 0x1;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x00004000UL:
 | 
				
			||||||
 | 
					        size = 0x2;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x00010000UL:
 | 
				
			||||||
 | 
					        size = 0x3;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x00040000UL:
 | 
				
			||||||
 | 
					        size = 0x4;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x00100000UL:
 | 
				
			||||||
 | 
					        size = 0x5;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x00400000UL:
 | 
				
			||||||
 | 
					        size = 0x6;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x01000000UL:
 | 
				
			||||||
 | 
					        size = 0x7;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x04000000UL:
 | 
				
			||||||
 | 
					        size = 0x8;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x10000000UL:
 | 
				
			||||||
 | 
					        size = 0x9;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x40000000UL:
 | 
				
			||||||
 | 
					        size = 0xA;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					#if defined (TARGET_PPC64)
 | 
				
			||||||
 | 
					    case 0x000100000000ULL:
 | 
				
			||||||
 | 
					        size = 0xB;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x000400000000ULL:
 | 
				
			||||||
 | 
					        size = 0xC;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x001000000000ULL:
 | 
				
			||||||
 | 
					        size = 0xD;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x004000000000ULL:
 | 
				
			||||||
 | 
					        size = 0xE;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x010000000000ULL:
 | 
				
			||||||
 | 
					        size = 0xF;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        size = -1;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Helpers for 4xx TLB management */
 | 
					/* Helpers for 4xx TLB management */
 | 
				
			||||||
void do_4xx_tlbia (void)
 | 
					void do_4xx_tlbia (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if 0
 | 
					    ppcemb_tlb_t *tlb;
 | 
				
			||||||
    ppc_tlb_t *tlb;
 | 
					 | 
				
			||||||
    target_ulong page, end;
 | 
					 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < 64; i++) {
 | 
					    for (i = 0; i < 64; i++) {
 | 
				
			||||||
        tlb = &env->tlb[i];
 | 
					        tlb = &env->tlb[i].tlbe;
 | 
				
			||||||
        if (tlb->prot & PAGE_VALID) {
 | 
					        if (tlb->prot & PAGE_VALID) {
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
            end = tlb->EPN + tlb->size;
 | 
					            end = tlb->EPN + tlb->size;
 | 
				
			||||||
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
 | 
					            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
 | 
				
			||||||
                tlb_flush_page(env, page);
 | 
					                tlb_flush_page(env, page);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
            tlb->prot &= ~PAGE_VALID;
 | 
					            tlb->prot &= ~PAGE_VALID;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					    tlb_flush(env, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void do_4xx_tlbre_lo (void)
 | 
					void do_4xx_tlbre_lo (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if 0
 | 
					    ppcemb_tlb_t *tlb;
 | 
				
			||||||
    ppc_tlb_t *tlb;
 | 
					    int size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    T0 &= 0x3F;
 | 
					    T0 &= 0x3F;
 | 
				
			||||||
    tlb = &env->tlb[T0];
 | 
					    tlb = &env->tlb[T0].tlbe;
 | 
				
			||||||
    T0 = tlb->stor[0];
 | 
					    T0 = tlb->EPN;
 | 
				
			||||||
    env->spr[SPR_40x_PID] = tlb->pid;
 | 
					    if (tlb->prot & PAGE_VALID)
 | 
				
			||||||
#endif
 | 
					        T0 |= 0x400;
 | 
				
			||||||
 | 
					    size = booke_page_size_to_tlb(tlb->size);
 | 
				
			||||||
 | 
					    if (size < 0 || size > 0x7)
 | 
				
			||||||
 | 
					        size = 1;
 | 
				
			||||||
 | 
					    T0 |= size << 7;
 | 
				
			||||||
 | 
					    env->spr[SPR_40x_PID] = tlb->PID;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void do_4xx_tlbre_hi (void)
 | 
					void do_4xx_tlbre_hi (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if 0
 | 
					    ppcemb_tlb_t *tlb;
 | 
				
			||||||
    ppc_tlb_t *tlb;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    T0 &= 0x3F;
 | 
					    T0 &= 0x3F;
 | 
				
			||||||
    tlb = &env->tlb[T0];
 | 
					    tlb = &env->tlb[T0].tlbe;
 | 
				
			||||||
    T0 = tlb->stor[1];
 | 
					    T0 = tlb->RPN;
 | 
				
			||||||
#endif
 | 
					    if (tlb->prot & PAGE_EXEC)
 | 
				
			||||||
 | 
					        T0 |= 0x200;
 | 
				
			||||||
 | 
					    if (tlb->prot & PAGE_WRITE)
 | 
				
			||||||
 | 
					        T0 |= 0x100;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int tlb_4xx_search (target_ulong virtual)
 | 
					static int tlb_4xx_search (target_ulong virtual)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if 0
 | 
					    ppcemb_tlb_t *tlb;
 | 
				
			||||||
    ppc_tlb_t *tlb;
 | 
					 | 
				
			||||||
    target_ulong base, mask;
 | 
					    target_ulong base, mask;
 | 
				
			||||||
    int i, ret;
 | 
					    int i, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Default return value is no match */
 | 
					    /* Default return value is no match */
 | 
				
			||||||
    ret = -1;
 | 
					    ret = -1;
 | 
				
			||||||
    for (i = 0; i < 64; i++) {
 | 
					    for (i = 0; i < 64; i++) {
 | 
				
			||||||
        tlb = &env->tlb[i];
 | 
					        tlb = &env->tlb[i].tlbe;
 | 
				
			||||||
        /* Check TLB validity */
 | 
					        /* Check TLB validity */
 | 
				
			||||||
        if (!(tlb->prot & PAGE_VALID))
 | 
					        if (!(tlb->prot & PAGE_VALID))
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        /* Check TLB PID vs current PID */
 | 
					        /* Check TLB PID vs current PID */
 | 
				
			||||||
        if (tlb->pid != 0 && tlb->pid != env->spr[SPR_40x_PID])
 | 
					        if (tlb->PID != 0 && tlb->PID != env->spr[SPR_40x_PID])
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        /* Check TLB address vs virtual address */
 | 
					        /* Check TLB address vs virtual address */
 | 
				
			||||||
        base = tlb->EPN;
 | 
					        base = tlb->EPN;
 | 
				
			||||||
@ -2435,9 +2509,6 @@ static int tlb_4xx_search (target_ulong virtual)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
    return -1;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void do_4xx_tlbsx (void)
 | 
					void do_4xx_tlbsx (void)
 | 
				
			||||||
@ -2457,47 +2528,44 @@ void do_4xx_tlbsx_ (void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void do_4xx_tlbwe_lo (void)
 | 
					void do_4xx_tlbwe_lo (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if 0
 | 
					    ppcemb_tlb_t *tlb;
 | 
				
			||||||
    ppc_tlb_t *tlb;
 | 
					 | 
				
			||||||
    target_ulong page, end;
 | 
					    target_ulong page, end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    T0 &= 0x3F;
 | 
					    T0 &= 0x3F;
 | 
				
			||||||
    tlb = &env->tlb[T0];
 | 
					    tlb = &env->tlb[T0].tlbe;
 | 
				
			||||||
    /* Invalidate previous TLB (if it's valid) */
 | 
					    /* Invalidate previous TLB (if it's valid) */
 | 
				
			||||||
    if (tlb->prot & PAGE_VALID) {
 | 
					    if (tlb->prot & PAGE_VALID) {
 | 
				
			||||||
        end = tlb->EPN + tlb->size;
 | 
					        end = tlb->EPN + tlb->size;
 | 
				
			||||||
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
 | 
					        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
 | 
				
			||||||
            tlb_flush_page(env, page);
 | 
					            tlb_flush_page(env, page);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    tlb->size = 1024 << (2 * ((T1 >> 7) & 0x7));
 | 
					    tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
 | 
				
			||||||
    tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
 | 
					    tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
 | 
				
			||||||
    if (T1 & 0x400)
 | 
					    if (T1 & 0x400)
 | 
				
			||||||
        tlb->prot |= PAGE_VALID;
 | 
					        tlb->prot |= PAGE_VALID;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        tlb->prot &= ~PAGE_VALID;
 | 
					        tlb->prot &= ~PAGE_VALID;
 | 
				
			||||||
    tlb->pid = env->spr[SPR_BOOKE_PID]; /* PID */
 | 
					    tlb->PID = env->spr[SPR_BOOKE_PID]; /* PID */
 | 
				
			||||||
 | 
					    tlb->attr = T1 & 0xFF;
 | 
				
			||||||
    /* Invalidate new TLB (if valid) */
 | 
					    /* Invalidate new TLB (if valid) */
 | 
				
			||||||
    if (tlb->prot & PAGE_VALID) {
 | 
					    if (tlb->prot & PAGE_VALID) {
 | 
				
			||||||
        end = tlb->EPN + tlb->size;
 | 
					        end = tlb->EPN + tlb->size;
 | 
				
			||||||
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
 | 
					        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
 | 
				
			||||||
            tlb_flush_page(env, page);
 | 
					            tlb_flush_page(env, page);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void do_4xx_tlbwe_hi (void)
 | 
					void do_4xx_tlbwe_hi (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if 0
 | 
					    ppcemb_tlb_t *tlb;
 | 
				
			||||||
    ppc_tlb_t *tlb;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    T0 &= 0x3F;
 | 
					    T0 &= 0x3F;
 | 
				
			||||||
    tlb = &env->tlb[T0];
 | 
					    tlb = &env->tlb[T0].tlbe;
 | 
				
			||||||
    tlb->RPN = T1 & 0xFFFFFC00;
 | 
					    tlb->RPN = T1 & 0xFFFFFC00;
 | 
				
			||||||
    tlb->prot = PAGE_READ;
 | 
					    tlb->prot = PAGE_READ;
 | 
				
			||||||
    if (T1 & 0x200)
 | 
					    if (T1 & 0x200)
 | 
				
			||||||
        tlb->prot |= PAGE_EXEC;
 | 
					        tlb->prot |= PAGE_EXEC;
 | 
				
			||||||
    if (T1 & 0x100)
 | 
					    if (T1 & 0x100)
 | 
				
			||||||
        tlb->prot |= PAGE_WRITE;
 | 
					        tlb->prot |= PAGE_WRITE;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* !CONFIG_USER_ONLY */
 | 
					#endif /* !CONFIG_USER_ONLY */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user