mirror of https://gitee.com/openkylin/qemu.git
target-arm: Add S2 translation to 64bit S1 PTWs
Add support for applying S2 translation to 64bit S1 page-table walks. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Message-id: 1445864527-14520-12-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
e14b5a23d8
commit
3778597762
|
@ -21,6 +21,12 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
|
|||
target_ulong *page_size, uint32_t *fsr,
|
||||
ARMMMUFaultInfo *fi);
|
||||
|
||||
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
|
||||
int access_type, ARMMMUIdx mmu_idx,
|
||||
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
|
||||
target_ulong *page_size_ptr, uint32_t *fsr,
|
||||
ARMMMUFaultInfo *fi);
|
||||
|
||||
/* Definitions for the PMCCNTR and PMCR registers */
|
||||
#define PMCRD 0x8
|
||||
#define PMCRC 0x4
|
||||
|
@ -6207,6 +6213,32 @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Translate a S1 pagetable walk through S2 if needed. */
|
||||
static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
|
||||
hwaddr addr, MemTxAttrs txattrs,
|
||||
uint32_t *fsr,
|
||||
ARMMMUFaultInfo *fi)
|
||||
{
|
||||
if ((mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1) &&
|
||||
!regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
|
||||
target_ulong s2size;
|
||||
hwaddr s2pa;
|
||||
int s2prot;
|
||||
int ret;
|
||||
|
||||
ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
|
||||
&txattrs, &s2prot, &s2size, fsr, fi);
|
||||
if (ret) {
|
||||
fi->s2addr = addr;
|
||||
fi->stage2 = true;
|
||||
fi->s1ptw = true;
|
||||
return ~0;
|
||||
}
|
||||
addr = s2pa;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* All loads done in the course of a page table walk go through here.
|
||||
* TODO: rather than ignoring errors from physical memory reads (which
|
||||
* are external aborts in ARM terminology) we should propagate this
|
||||
|
@ -6222,11 +6254,19 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure)
|
|||
return address_space_ldl(cs->as, addr, attrs, NULL);
|
||||
}
|
||||
|
||||
static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure)
|
||||
static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
|
||||
ARMMMUIdx mmu_idx, uint32_t *fsr,
|
||||
ARMMMUFaultInfo *fi)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
MemTxAttrs attrs = {};
|
||||
|
||||
attrs.secure = is_secure;
|
||||
addr = S1_ptw_translate(env, mmu_idx, addr, attrs, fsr, fi);
|
||||
if (fi->s1ptw) {
|
||||
return 0;
|
||||
}
|
||||
return address_space_ldq(cs->as, addr, attrs, NULL);
|
||||
}
|
||||
|
||||
|
@ -6785,7 +6825,11 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
|
|||
descaddr |= (address >> (stride * (4 - level))) & descmask;
|
||||
descaddr &= ~7ULL;
|
||||
nstable = extract32(tableattrs, 4, 1);
|
||||
descriptor = arm_ldq_ptw(cs, descaddr, !nstable);
|
||||
descriptor = arm_ldq_ptw(cs, descaddr, !nstable, mmu_idx, fsr, fi);
|
||||
if (fi->s1ptw) {
|
||||
goto do_fault;
|
||||
}
|
||||
|
||||
if (!(descriptor & 1) ||
|
||||
(!(descriptor & 2) && (level == 3))) {
|
||||
/* Invalid, or the Reserved level 3 encoding */
|
||||
|
@ -6869,6 +6913,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
|
|||
do_fault:
|
||||
/* Long-descriptor format IFSR/DFSR value */
|
||||
*fsr = (1 << 9) | (fault_type << 2) | level;
|
||||
/* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */
|
||||
fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_S2NS);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,10 +104,10 @@ void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
|
|||
* information; this is always true for exceptions reported to EL1.
|
||||
*/
|
||||
if (is_write == 2) {
|
||||
syn = syn_insn_abort(same_el, 0, 0, syn);
|
||||
syn = syn_insn_abort(same_el, 0, fi.s1ptw, syn);
|
||||
exc = EXCP_PREFETCH_ABORT;
|
||||
} else {
|
||||
syn = syn_data_abort(same_el, 0, 0, 0, is_write == 1, syn);
|
||||
syn = syn_data_abort(same_el, 0, 0, fi.s1ptw, is_write == 1, syn);
|
||||
if (is_write == 1 && arm_feature(env, ARM_FEATURE_V6)) {
|
||||
fsr |= (1 << 11);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue