target/arm: Convert get_phys_addr_lpae() to not return FSC values

Make get_phys_addr_v6() return a fault type in the ARMMMUFaultInfo
structure, which we convert to the FSC at the callsite.

Backports commit da909b2c23a68e57bbcb6be98229e40df606f0c8 from qemu
This commit is contained in:
Peter Maydell 2018-03-05 13:52:11 -05:00 committed by Lioncash
parent c6496ec00a
commit 013e7873ee
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -26,7 +26,7 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
MMUAccessType access_type, ARMMMUIdx mmu_idx, MMUAccessType access_type, ARMMMUIdx mmu_idx,
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot, hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
target_ulong *page_size_ptr, uint32_t *fsr, target_ulong *page_size_ptr,
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs); ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs);
/* Security attributes for an address, as returned by v8m_security_lookup. */ /* Security attributes for an address, as returned by v8m_security_lookup. */
@ -7465,10 +7465,9 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
hwaddr s2pa; hwaddr s2pa;
int s2prot; int s2prot;
int ret; int ret;
uint32_t fsr;
ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa, ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
&txattrs, &s2prot, &s2size, &fsr, fi, NULL); &txattrs, &s2prot, &s2size, fi, NULL);
if (ret) { if (ret) {
fi->s2addr = addr; fi->s2addr = addr;
fi->stage2 = true; fi->stage2 = true;
@ -7791,15 +7790,6 @@ do_fault:
return true; return true;
} }
/* Fault type for long-descriptor MMU fault reporting; this corresponds
* to bits [5..2] in the STATUS field in long-format DFSR/IFSR.
*/
typedef enum {
translation_fault = 1,
access_fault = 2,
permission_fault = 3,
} MMUFaultType;
/* /*
* check_s2_mmu_setup * check_s2_mmu_setup
* @cpu: ARMCPU * @cpu: ARMCPU
@ -7901,13 +7891,13 @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs)
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
MMUAccessType access_type, ARMMMUIdx mmu_idx, MMUAccessType access_type, ARMMMUIdx mmu_idx,
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot, hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
target_ulong *page_size_ptr, uint32_t *fsr, target_ulong *page_size_ptr,
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
{ {
ARMCPU *cpu = arm_env_get_cpu(env); ARMCPU *cpu = arm_env_get_cpu(env);
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
/* Read an LPAE long-descriptor translation table. */ /* Read an LPAE long-descriptor translation table. */
MMUFaultType fault_type = translation_fault; ARMFaultType fault_type = ARMFault_Translation;
uint32_t level; uint32_t level;
uint32_t epd = 0; uint32_t epd = 0;
int32_t t0sz, t1sz; int32_t t0sz, t1sz;
@ -8017,7 +8007,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
ttbr_select = 1; ttbr_select = 1;
} else { } else {
/* in the gap between the two regions, this is a Translation fault */ /* in the gap between the two regions, this is a Translation fault */
fault_type = translation_fault; fault_type = ARMFault_Translation;
goto do_fault; goto do_fault;
} }
@ -8103,7 +8093,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
ok = check_s2_mmu_setup(cpu, aarch64, startlevel, ok = check_s2_mmu_setup(cpu, aarch64, startlevel,
inputsize, stride); inputsize, stride);
if (!ok) { if (!ok) {
fault_type = translation_fault; fault_type = ARMFault_Translation;
goto do_fault; goto do_fault;
} }
level = startlevel; level = startlevel;
@ -8188,7 +8178,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
/* Here descaddr is the final physical address, and attributes /* Here descaddr is the final physical address, and attributes
* are all in attrs. * are all in attrs.
*/ */
fault_type = access_fault; fault_type = ARMFault_AccessFlag;
if ((attrs & (1 << 8)) == 0) { if ((attrs & (1 << 8)) == 0) {
/* Access flag */ /* Access flag */
goto do_fault; goto do_fault;
@ -8206,7 +8196,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
*prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn); *prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
} }
fault_type = permission_fault; fault_type = ARMFault_Permission;
if (!(*prot & (1 << access_type))) { if (!(*prot & (1 << access_type))) {
/* Unprivileged access not enabled */ /* Unprivileged access not enabled */
goto do_fault; goto do_fault;
@ -8239,10 +8229,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
return false; return false;
do_fault: do_fault:
/* Long-descriptor format IFSR/DFSR value */ fi->type = fault_type;
*fsr = (1 << 9) | (fault_type << 2) | level; fi->level = 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; return true;
} }
@ -8961,8 +8949,9 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
/* S1 is done. Now do S2 translation. */ /* S1 is done. Now do S2 translation. */
ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_S2NS, ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_S2NS,
phys_ptr, attrs, &s2_prot, phys_ptr, attrs, &s2_prot,
page_size, fsr, fi, page_size, fi,
cacheattrs != NULL ? &cacheattrs2 : NULL); cacheattrs != NULL ? &cacheattrs2 : NULL);
*fsr = arm_fi_to_lfsc(fi);
fi->s2addr = ipa; fi->s2addr = ipa;
/* Combine the S1 and S2 perms. */ /* Combine the S1 and S2 perms. */
*prot &= s2_prot; *prot &= s2_prot;
@ -9040,8 +9029,12 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
} }
if (regime_using_lpae_format(env, mmu_idx)) { if (regime_using_lpae_format(env, mmu_idx)) {
return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr, bool ret = get_phys_addr_lpae(env, address, access_type, mmu_idx,
attrs, prot, page_size, fsr, fi, cacheattrs); phys_ptr, attrs, prot, page_size,
fi, cacheattrs);
*fsr = arm_fi_to_lfsc(fi);
return ret;
} else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
bool ret = get_phys_addr_v6(env, address, access_type, mmu_idx, bool ret = get_phys_addr_v6(env, address, access_type, mmu_idx,
phys_ptr, attrs, prot, page_size, fi); phys_ptr, attrs, prot, page_size, fi);