target/arm: Implement arm_cpu_record_sigsegv

Because of the complexity of setting ESR, continue to use
arm_deliver_fault.  This means we cannot remove the code
within cpu_loop that decodes EXCP_DATA_ABORT and
EXCP_PREFETCH_ABORT.

But using the new hook means that we don't have to do the
page_get_flags check manually, and we'll be able to restrict
the tlb_fill hook to sysemu later.

Reviewed-by: Warner Losh <imp@bsdimp.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-09-17 18:23:07 -07:00
parent 5e98763c0e
commit 9b12b6b442
4 changed files with 33 additions and 21 deletions

View file

@ -147,28 +147,12 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
arm_deliver_fault(cpu, addr, access_type, mmu_idx, &fi);
}
#endif /* !defined(CONFIG_USER_ONLY) */
bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr)
{
ARMCPU *cpu = ARM_CPU(cs);
ARMMMUFaultInfo fi = {};
#ifdef CONFIG_USER_ONLY
int flags = page_get_flags(useronly_clean_ptr(address));
if (flags & PAGE_VALID) {
fi.type = ARMFault_Permission;
} else {
fi.type = ARMFault_Translation;
}
fi.level = 3;
/* now we have a real cpu fault */
cpu_restore_state(cs, retaddr, true);
arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi);
#else
hwaddr phys_addr;
target_ulong page_size;
int prot, ret;
@ -210,5 +194,23 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_restore_state(cs, retaddr, true);
arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi);
}
#endif
}
#else
void arm_cpu_record_sigsegv(CPUState *cs, vaddr addr,
MMUAccessType access_type,
bool maperr, uintptr_t ra)
{
ARMMMUFaultInfo fi = {
.type = maperr ? ARMFault_Translation : ARMFault_Permission,
.level = 3,
};
ARMCPU *cpu = ARM_CPU(cs);
/*
* We report both ESR and FAR to signal handlers.
* For now, it's easiest to deliver the fault normally.
*/
cpu_restore_state(cs, ra, true);
arm_deliver_fault(cpu, addr, access_type, MMU_USER_IDX, &fi);
}
#endif /* !defined(CONFIG_USER_ONLY) */