diff options
Diffstat (limited to 'target/hppa')
| -rw-r--r-- | target/hppa/cpu.c | 2 | ||||
| -rw-r--r-- | target/hppa/cpu.h | 8 | ||||
| -rw-r--r-- | target/hppa/int_helper.c | 2 | ||||
| -rw-r--r-- | target/hppa/mem_helper.c | 55 | ||||
| -rw-r--r-- | target/hppa/op_helper.c | 2 |
5 files changed, 40 insertions, 29 deletions
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 7cf2e2f266..c38439c180 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -226,7 +226,7 @@ static const TCGCPUOps hppa_tcg_ops = { .restore_state_to_opc = hppa_restore_state_to_opc, #ifndef CONFIG_USER_ONLY - .tlb_fill = hppa_cpu_tlb_fill, + .tlb_fill_align = hppa_cpu_tlb_fill_align, .cpu_exec_interrupt = hppa_cpu_exec_interrupt, .cpu_exec_halt = hppa_cpu_has_work, .do_interrupt = hppa_cpu_do_interrupt, diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index f4e051f176..e45ba50a59 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -363,13 +363,13 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int); void hppa_ptlbe(CPUHPPAState *env); hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr); void hppa_set_ior_and_isr(CPUHPPAState *env, vaddr addr, bool mmu_disabled); -bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr); +bool hppa_cpu_tlb_fill_align(CPUState *cs, CPUTLBEntryFull *out, vaddr addr, + MMUAccessType access_type, int mmu_idx, + MemOp memop, int size, bool probe, uintptr_t ra); void hppa_cpu_do_interrupt(CPUState *cpu); bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req); int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, - int type, hwaddr *pphys, int *pprot); + int type, MemOp mop, hwaddr *pphys, int *pprot); void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, unsigned size, MMUAccessType access_type, diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index 391f32f27d..58695def82 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -167,7 +167,7 @@ void hppa_cpu_do_interrupt(CPUState *cs) vaddr = hppa_form_gva_psw(old_psw, env->iasq_f, vaddr); t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX, - 0, &paddr, &prot); + 0, 0, &paddr, &prot); if (t >= 0) { /* We can't re-load the instruction. */ env->cr[CR_IIR] = 0; diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index b984f730aa..b8c3e55170 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -197,7 +197,7 @@ static int match_prot_id64(CPUHPPAState *env, uint32_t access_id) } int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, - int type, hwaddr *pphys, int *pprot) + int type, MemOp mop, hwaddr *pphys, int *pprot) { hwaddr phys; int prot, r_prot, w_prot, x_prot, priv; @@ -221,7 +221,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, g_assert_not_reached(); } prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - goto egress; + goto egress_align; } /* Find a valid tlb entry that matches the virtual address. */ @@ -267,6 +267,12 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, goto egress; } + if (unlikely(!(prot & type))) { + /* Not allowed -- Inst/Data Memory Access Rights Fault. */ + ret = (type & PAGE_EXEC) ? EXCP_IMP : EXCP_DMAR; + goto egress; + } + /* access_id == 0 means public page and no check is performed */ if (ent->access_id && MMU_IDX_TO_P(mmu_idx)) { int access_prot = (hppa_is_pa20(env) @@ -281,14 +287,8 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, prot &= access_prot; } - if (unlikely(!(prot & type))) { - /* Not allowed -- Inst/Data Memory Access Rights Fault. */ - ret = (type & PAGE_EXEC) ? EXCP_IMP : EXCP_DMAR; - goto egress; - } - /* - * In priority order, check for conditions which raise faults. + * In reverse priority order, check for conditions which raise faults. * Remove PROT bits that cover the condition we want to check, * so that the resulting PROT will force a re-check of the * architectural TLB entry for the next access. @@ -299,13 +299,15 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, /* The T bit is set -- Page Reference Fault. */ ret = EXCP_PAGE_REF; } - } else if (!ent->d) { + } + if (unlikely(!ent->d)) { prot &= PAGE_READ | PAGE_EXEC; if (type & PAGE_WRITE) { /* The D bit is not set -- TLB Dirty Bit Fault. */ ret = EXCP_TLB_DIRTY; } - } else if (unlikely(ent->b)) { + } + if (unlikely(ent->b)) { prot &= PAGE_READ | PAGE_EXEC; if (type & PAGE_WRITE) { /* @@ -321,6 +323,11 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, } } + egress_align: + if (addr & ((1u << memop_alignment_bits(mop)) - 1)) { + ret = EXCP_UNALIGN; + } + egress: *pphys = phys; *pprot = prot; @@ -340,7 +347,7 @@ hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) mmu_idx = (cpu->env.psw & PSW_D ? MMU_KERNEL_IDX : cpu->env.psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX); - excp = hppa_get_physical_address(&cpu->env, addr, mmu_idx, 0, + excp = hppa_get_physical_address(&cpu->env, addr, mmu_idx, 0, 0, &phys, &prot); /* Since we're translating for debugging, the only error that is a @@ -417,12 +424,11 @@ void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, } } -bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, - MMUAccessType type, int mmu_idx, - bool probe, uintptr_t retaddr) +bool hppa_cpu_tlb_fill_align(CPUState *cs, CPUTLBEntryFull *out, vaddr addr, + MMUAccessType type, int mmu_idx, + MemOp memop, int size, bool probe, uintptr_t ra) { - HPPACPU *cpu = HPPA_CPU(cs); - CPUHPPAState *env = &cpu->env; + CPUHPPAState *env = cpu_env(cs); int prot, excp, a_prot; hwaddr phys; @@ -438,7 +444,8 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, break; } - excp = hppa_get_physical_address(env, addr, mmu_idx, a_prot, &phys, &prot); + excp = hppa_get_physical_address(env, addr, mmu_idx, a_prot, memop, + &phys, &prot); if (unlikely(excp >= 0)) { if (probe) { return false; @@ -446,7 +453,7 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, trace_hppa_tlb_fill_excp(env, addr, size, type, mmu_idx); /* Failure. Raise the indicated exception. */ - raise_exception_with_ior(env, excp, retaddr, addr, + raise_exception_with_ior(env, excp, ra, addr, MMU_IDX_MMU_DISABLED(mmu_idx)); } @@ -460,8 +467,12 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, * the large page protection mask. We do not require this, * because we record the large page here in the hppa tlb. */ - tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, - prot, mmu_idx, TARGET_PAGE_SIZE); + memset(out, 0, sizeof(*out)); + out->phys_addr = phys; + out->prot = prot; + out->attrs = MEMTXATTRS_UNSPECIFIED; + out->lg_page_size = TARGET_PAGE_BITS; + return true; } @@ -678,7 +689,7 @@ target_ulong HELPER(lpa)(CPUHPPAState *env, target_ulong addr) hwaddr phys; int prot, excp; - excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0, + excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0, 0, &phys, &prot); if (excp >= 0) { if (excp == EXCP_DTLB_MISS) { diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 7f79196fff..744325969f 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -334,7 +334,7 @@ target_ulong HELPER(probe)(CPUHPPAState *env, target_ulong addr, } mmu_idx = PRIV_P_TO_MMU_IDX(level, env->psw & PSW_P); - excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys, &prot); + excp = hppa_get_physical_address(env, addr, mmu_idx, 0, 0, &phys, &prot); if (excp >= 0) { cpu_restore_state(env_cpu(env), GETPC()); hppa_set_ior_and_isr(env, addr, MMU_IDX_MMU_DISABLED(mmu_idx)); |