mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-23 06:25:12 +00:00
target-arm: fix get_phys_addr_v6/SCTLR_AFE access check
Introduce simple_ap_to_rw_prot(), which has the same behavior as ap_to_rw_prot(), but takes the 2-bit simple AP[2:1] instead of the 3-bit AP[2:0]. Use this in get_phys_addr_v6 when SCTLR_AFE is set, as that bit indicates we should be using the simple AP format. It's unlikely this path is getting used. I don't see CR_AFE getting used by Linux, so possibly not. If it had been, then the check would have been wrong for all but AP[2:1] = 0b11. Anyway, this should fix it up, in case it ever does get used. Backports commit d76951b65dfb1be4e41cfae6abebf8db7a1243a3 from qemu
This commit is contained in:
parent
dd8d05620f
commit
ea94701bd0
|
@ -4396,6 +4396,11 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
|
|||
|
||||
/* Translate section/page access permissions to page
|
||||
* R/W protection flags
|
||||
*
|
||||
* @env: CPUARMState
|
||||
* @mmu_idx: MMU index indicating required translation regime
|
||||
* @ap: The 3-bit access permissions (AP[2:0])
|
||||
* @domain_prot: The 2-bit domain access permissions
|
||||
*/
|
||||
static inline int ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx,
|
||||
int ap, int domain_prot)
|
||||
|
@ -4445,6 +4450,33 @@ static inline int ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx,
|
|||
}
|
||||
}
|
||||
|
||||
/* Translate section/page access permissions to page
|
||||
* R/W protection flags.
|
||||
*
|
||||
* @env: CPUARMState
|
||||
* @mmu_idx: MMU index indicating required translation regime
|
||||
* @ap: The 2-bit simple AP (AP[2:1])
|
||||
*/
|
||||
static inline int
|
||||
simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap)
|
||||
{
|
||||
bool is_user = regime_is_user(env, mmu_idx);
|
||||
|
||||
switch (ap) {
|
||||
case 0:
|
||||
return is_user ? 0 : PAGE_READ | PAGE_WRITE;
|
||||
case 1:
|
||||
return PAGE_READ | PAGE_WRITE;
|
||||
case 2:
|
||||
return is_user ? 0 : PAGE_READ;
|
||||
case 3:
|
||||
return PAGE_READ;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
|
||||
uint32_t *table, uint32_t address)
|
||||
{
|
||||
|
@ -4677,14 +4709,18 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
|
|||
if (xn && access_type == 2)
|
||||
goto do_fault;
|
||||
|
||||
/* The simplified model uses AP[0] as an access control bit. */
|
||||
if ((regime_sctlr(env, mmu_idx) & SCTLR_AFE)
|
||||
&& (ap & 1) == 0) {
|
||||
/* Access flag fault. */
|
||||
code = (code == 15) ? 6 : 3;
|
||||
goto do_fault;
|
||||
if (arm_feature(env, ARM_FEATURE_V6K) &&
|
||||
(regime_sctlr(env, mmu_idx) & SCTLR_AFE)) {
|
||||
/* The simplified model uses AP[0] as an access control bit. */
|
||||
if ((ap & 1) == 0) {
|
||||
/* Access flag fault. */
|
||||
code = (code == 15) ? 6 : 3;
|
||||
goto do_fault;
|
||||
}
|
||||
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1);
|
||||
} else {
|
||||
*prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
|
||||
}
|
||||
*prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
|
||||
if (*prot && !xn) {
|
||||
*prot |= PAGE_EXEC;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue