target/arm: Implement new do_transaction_failed hook

Implement the new do_transaction_failed hook for ARM, which should
cause the CPU to take a prefetch abort or data abort.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1504626814-23124-4-git-send-email-peter.maydell@linaro.org
stable-2.11
Peter Maydell 2017-09-07 13:54:55 +01:00
parent 4672cbd7be
commit c79c0a314c
3 changed files with 54 additions and 0 deletions

View File

@ -1707,6 +1707,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
#else
cc->do_interrupt = arm_cpu_do_interrupt;
cc->do_unaligned_access = arm_cpu_do_unaligned_access;
cc->do_transaction_failed = arm_cpu_do_transaction_failed;
cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
cc->asidx_from_attrs = arm_asidx_from_attrs;
cc->vmsd = &vmstate_arm_cpu;

View File

@ -472,6 +472,16 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr);
/* arm_cpu_do_transaction_failed: handle a memory system error response
* (eg "no device/memory present at address") by raising an external abort
* exception
*/
void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response, uintptr_t retaddr);
/* Call the EL change hook if one has been registered */
static inline void arm_call_el_change_hook(ARMCPU *cpu)
{

View File

@ -229,6 +229,49 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
deliver_fault(cpu, vaddr, access_type, fsr, fsc, &fi);
}
/* arm_cpu_do_transaction_failed: handle a memory system error response
* (eg "no device/memory present at address") by raising an external abort
* exception
*/
void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response, uintptr_t retaddr)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
uint32_t fsr, fsc;
ARMMMUFaultInfo fi = {};
ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
if (retaddr) {
/* now we have a real cpu fault */
cpu_restore_state(cs, retaddr);
}
/* The EA bit in syndromes and fault status registers is an
* IMPDEF classification of external aborts. ARM implementations
* usually use this to indicate AXI bus Decode error (0) or
* Slave error (1); in QEMU we follow that.
*/
fi.ea = (response != MEMTX_DECODE_ERROR);
/* The fault status register format depends on whether we're using
* the LPAE long descriptor format, or the short descriptor format.
*/
if (arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
/* long descriptor form, STATUS 0b010000: synchronous ext abort */
fsr = (fi.ea << 12) | (1 << 9) | 0x10;
} else {
/* short descriptor form, FSR 0b01000 : synchronous ext abort */
fsr = (fi.ea << 12) | 0x8;
}
fsc = 0x10;
deliver_fault(cpu, addr, access_type, fsr, fsc, &fi);
}
#endif /* !defined(CONFIG_USER_ONLY) */
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)