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:
Sergey Fedorov 2018-02-20 11:43:47 -05:00 committed by Lioncash
parent 3d5b54cf4b
commit 6a3038db7c
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 15 additions and 2 deletions

View file

@ -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;

View file

@ -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;