mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 12:31:09 +00:00
cpu: Add callback to check architectural watchpoint match
When QEMU watchpoint matches, that is not definitely an architectural watchpoint match yet. If it is a stop-before-access watchpoint then that is hardly possible to ignore it after throwing a TCG exception. A special callback is introduced to check for architectural watchpoint match before raising a TCG exception. Backports commit 568496c0c0f1863a4bc18539962cd8d81baa4e30 from qemu
This commit is contained in:
parent
3d5b54cf4b
commit
6a3038db7c
|
@ -63,6 +63,7 @@ typedef uint64_t vaddr;
|
||||||
#define CPU_GET_CLASS(uc, obj) OBJECT_GET_CLASS(uc, CPUClass, (obj), TYPE_CPU)
|
#define CPU_GET_CLASS(uc, obj) OBJECT_GET_CLASS(uc, CPUClass, (obj), TYPE_CPU)
|
||||||
|
|
||||||
typedef struct CPUState CPUState;
|
typedef struct CPUState CPUState;
|
||||||
|
typedef struct CPUWatchpoint CPUWatchpoint;
|
||||||
|
|
||||||
typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
|
typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
|
||||||
bool is_write, bool is_exec, int opaque,
|
bool is_write, bool is_exec, int opaque,
|
||||||
|
@ -100,6 +101,8 @@ struct TranslationBlock;
|
||||||
* @asidx_from_attrs: Callback to return the CPU AddressSpace to use for
|
* @asidx_from_attrs: Callback to return the CPU AddressSpace to use for
|
||||||
* a memory access with the specified memory transaction attributes.
|
* a memory access with the specified memory transaction attributes.
|
||||||
* @debug_excp_handler: Callback for handling debug exceptions.
|
* @debug_excp_handler: Callback for handling debug exceptions.
|
||||||
|
* @debug_check_watchpoint: Callback: return true if the architectural
|
||||||
|
* watchpoint whose address has matched should really fire.
|
||||||
* @vmsd: State description for migration.
|
* @vmsd: State description for migration.
|
||||||
* @cpu_exec_enter: Callback for cpu_exec preparation.
|
* @cpu_exec_enter: Callback for cpu_exec preparation.
|
||||||
* @cpu_exec_exit: Callback for cpu_exec cleanup.
|
* @cpu_exec_exit: Callback for cpu_exec cleanup.
|
||||||
|
@ -140,6 +143,7 @@ typedef struct CPUClass {
|
||||||
hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
|
hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
|
||||||
MemTxAttrs *attrs);
|
MemTxAttrs *attrs);
|
||||||
int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
|
int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
|
||||||
|
bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
|
||||||
void (*debug_excp_handler)(CPUState *cpu);
|
void (*debug_excp_handler)(CPUState *cpu);
|
||||||
|
|
||||||
const struct VMStateDescription *vmsd;
|
const struct VMStateDescription *vmsd;
|
||||||
|
@ -167,13 +171,13 @@ typedef struct CPUBreakpoint {
|
||||||
QTAILQ_ENTRY(CPUBreakpoint) entry;
|
QTAILQ_ENTRY(CPUBreakpoint) entry;
|
||||||
} CPUBreakpoint;
|
} CPUBreakpoint;
|
||||||
|
|
||||||
typedef struct CPUWatchpoint {
|
struct CPUWatchpoint {
|
||||||
vaddr vaddr;
|
vaddr vaddr;
|
||||||
vaddr len;
|
vaddr len;
|
||||||
vaddr hitaddr;
|
vaddr hitaddr;
|
||||||
int flags; /* BP_* */
|
int flags; /* BP_* */
|
||||||
QTAILQ_ENTRY(CPUWatchpoint) entry;
|
QTAILQ_ENTRY(CPUWatchpoint) entry;
|
||||||
} CPUWatchpoint;
|
};
|
||||||
|
|
||||||
struct KVMState;
|
struct KVMState;
|
||||||
struct kvm_run;
|
struct kvm_run;
|
||||||
|
|
|
@ -178,6 +178,14 @@ static bool cpu_common_has_work(CPUState *cs)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool cpu_common_debug_check_watchpoint(CPUState *cpu, CPUWatchpoint *wp)
|
||||||
|
{
|
||||||
|
/* If no extra check is required, QEMU watchpoint match can be considered
|
||||||
|
* as an architectural match.
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ObjectClass *cpu_class_by_name(struct uc_struct *uc, const char *typename, const char *cpu_model)
|
ObjectClass *cpu_class_by_name(struct uc_struct *uc, const char *typename, const char *cpu_model)
|
||||||
{
|
{
|
||||||
CPUClass *cc = CPU_CLASS(uc, object_class_by_name(uc, typename));
|
CPUClass *cc = CPU_CLASS(uc, object_class_by_name(uc, typename));
|
||||||
|
@ -255,6 +263,7 @@ static void cpu_class_init(struct uc_struct *uc, ObjectClass *klass, void *data)
|
||||||
k->get_paging_enabled = cpu_common_get_paging_enabled;
|
k->get_paging_enabled = cpu_common_get_paging_enabled;
|
||||||
k->get_memory_mapping = cpu_common_get_memory_mapping;
|
k->get_memory_mapping = cpu_common_get_memory_mapping;
|
||||||
k->debug_excp_handler = cpu_common_noop;
|
k->debug_excp_handler = cpu_common_noop;
|
||||||
|
k->debug_check_watchpoint = cpu_common_debug_check_watchpoint;
|
||||||
k->cpu_exec_enter = cpu_common_noop;
|
k->cpu_exec_enter = cpu_common_noop;
|
||||||
k->cpu_exec_exit = cpu_common_noop;
|
k->cpu_exec_exit = cpu_common_noop;
|
||||||
k->cpu_exec_interrupt = cpu_common_exec_interrupt;
|
k->cpu_exec_interrupt = cpu_common_exec_interrupt;
|
||||||
|
|
Loading…
Reference in a new issue