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.

Backports commit c79c0a314c43b78f6326d5f137bdbafdbf8e9766 from qemu
This commit is contained in:
Peter Maydell 2018-03-04 21:28:01 -05:00 committed by Lioncash
parent 2070ef1c37
commit 8d02ee3b51
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 44 additions and 0 deletions

View file

@ -1472,6 +1472,7 @@ static void arm_cpu_class_init(struct uc_struct *uc, 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;
// UNICORN: Commented out

View file

@ -228,6 +228,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->uc, 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)