mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 00:05:36 +00:00
boards.h: Define new flag ignore_memory_transaction_failures
Define a new MachineClass field ignore_memory_transaction_failures. If this is flag is true then the CPU will ignore memory transaction failures which should cause the CPU to take an exception due to an access to an unassigned physical address; the transaction will instead return zero (for a read) or be ignored (for a write). This should be set only by legacy board models which rely on the old RAZ/WI behaviour for handling devices that QEMU does not yet model. New board models should instead use "unimplemented-device" for all memory ranges where the guest will attempt to probe for a device that QEMU doesn't implement and a stub device is required. We need this for ARM boards, where we're about to implement support for generating external aborts on memory transaction failures. Too many of our legacy board models rely on the RAZ/WI behaviour and we would break currently working guests when their "probe for device" code provoked an external abort rather than a RAZ. Backports commit ed860129acd3fcd0b1e47884e810212aaca4d21b from qemu
This commit is contained in:
parent
4b816fe0aa
commit
2070ef1c37
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_aarch64
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_aarch64
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_aarch64
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_aarch64
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_aarch64
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_aarch64
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_aarch64
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_aarch64eb
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_aarch64eb
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_aarch64eb
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_aarch64eb
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_aarch64eb
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_aarch64eb
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_aarch64eb
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_arm
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_arm
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_arm
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_arm
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_arm
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_arm
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_arm
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_armeb
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_armeb
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_armeb
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_armeb
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_armeb
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_armeb
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_armeb
|
||||
|
|
|
@ -146,6 +146,7 @@ symbols = (
|
|||
'arm_cp_reset_ignore',
|
||||
'arm_cp_write_ignore',
|
||||
'arm_cpu_do_interrupt',
|
||||
'arm_cpu_do_transaction_failed',
|
||||
'arm_cpu_do_unaligned_access',
|
||||
'arm_cpu_exec_interrupt',
|
||||
'arm_cpu_finalizefn',
|
||||
|
|
|
@ -81,6 +81,16 @@ MachineClass *find_default_machine(struct uc_struct *uc, int arch);
|
|||
* size than the target architecture's minimum. (Attempting to create
|
||||
* such a CPU will fail.) Note that changing this is a migration
|
||||
* compatibility break for the machine.
|
||||
* @ignore_memory_transaction_failures:
|
||||
* If this is flag is true then the CPU will ignore memory transaction
|
||||
* failures which should cause the CPU to take an exception due to an
|
||||
* access to an unassigned physical address; the transaction will instead
|
||||
* return zero (for a read) or be ignored (for a write). This should be
|
||||
* set only by legacy board models which rely on the old RAZ/WI behaviour
|
||||
* for handling devices that QEMU does not yet model. New board models
|
||||
* should instead use "unimplemented-device" for all memory ranges where
|
||||
* the guest will attempt to probe for a device that QEMU doesn't
|
||||
* implement and a stub device is required.
|
||||
*/
|
||||
struct MachineClass {
|
||||
/*< private >*/
|
||||
|
@ -97,6 +107,8 @@ struct MachineClass {
|
|||
int is_default;
|
||||
int arch;
|
||||
int minimum_page_bits;
|
||||
bool has_hotpluggable_cpus;
|
||||
bool ignore_memory_transaction_failures;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -331,6 +331,8 @@ struct CPUState {
|
|||
*/
|
||||
bool throttle_thread_scheduled;
|
||||
|
||||
bool ignore_memory_transaction_failures;
|
||||
|
||||
/* Note that this is accessed at the start of every TB via a negative
|
||||
offset from AREG0. Leave this field at the end so as to make the
|
||||
(absolute value) offset as small as possible. This reduces code
|
||||
|
@ -677,7 +679,7 @@ static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
|
|||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu->uc, cpu);
|
||||
|
||||
if (cc->do_transaction_failed) {
|
||||
if (!cpu->ignore_memory_transaction_failures && cc->do_transaction_failed) {
|
||||
cc->do_transaction_failed(cpu, physaddr, addr, size, access_type,
|
||||
mmu_idx, attrs, response, retaddr);
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_m68k
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_m68k
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_m68k
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_m68k
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_m68k
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_m68k
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_m68k
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_mips
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_mips
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_mips
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_mips
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_mips
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_mips
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_mips
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_mips64
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_mips64
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_mips64
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_mips64
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_mips64
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_mips64
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_mips64
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_mips64el
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_mips64el
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_mips64el
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_mips64el
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_mips64el
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_mips64el
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_mips64el
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_mipsel
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_mipsel
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_mipsel
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_mipsel
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_mipsel
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_mipsel
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_mipsel
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_powerpc
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_powerpc
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_powerpc
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_powerpc
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_powerpc
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_powerpc
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_powerpc
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qemu/log.h"
|
||||
#include "uc_priv.h"
|
||||
|
||||
|
@ -243,6 +244,21 @@ static void cpu_common_parse_features(CPUState *cpu, char *features,
|
|||
static int cpu_common_realizefn(struct uc_struct *uc, DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cpu = CPU(dev);
|
||||
Object *machine = qdev_get_machine(uc);
|
||||
|
||||
/* qdev_get_machine() can return something that's not TYPE_MACHINE
|
||||
* if this is one of the user-only emulators; in that case there's
|
||||
* no need to check the ignore_memory_transaction_failures board flag.
|
||||
*/
|
||||
if (object_dynamic_cast(uc, machine, TYPE_MACHINE)) {
|
||||
ObjectClass *oc = object_get_class(machine);
|
||||
MachineClass *mc = MACHINE_CLASS(uc, oc);
|
||||
|
||||
if (mc) {
|
||||
cpu->ignore_memory_transaction_failures =
|
||||
mc->ignore_memory_transaction_failures;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->hotplugged) {
|
||||
cpu_resume(cpu);
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_sparc
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_sparc
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_sparc
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_sparc
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_sparc
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_sparc
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_sparc
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_sparc64
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_sparc64
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_sparc64
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_sparc64
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_sparc64
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_sparc64
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_sparc64
|
||||
|
|
|
@ -474,6 +474,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)
|
||||
{
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
#define arm_cp_reset_ignore arm_cp_reset_ignore_x86_64
|
||||
#define arm_cp_write_ignore arm_cp_write_ignore_x86_64
|
||||
#define arm_cpu_do_interrupt arm_cpu_do_interrupt_x86_64
|
||||
#define arm_cpu_do_transaction_failed arm_cpu_do_transaction_failed_x86_64
|
||||
#define arm_cpu_do_unaligned_access arm_cpu_do_unaligned_access_x86_64
|
||||
#define arm_cpu_exec_interrupt arm_cpu_exec_interrupt_x86_64
|
||||
#define arm_cpu_finalizefn arm_cpu_finalizefn_x86_64
|
||||
|
|
Loading…
Reference in a new issue