1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <xe_drm.h>
#include <xe_drm_eudebug.h>
#include "igt_list.h"
struct xe_eudebug_event_log {
uint8_t *log;
unsigned int head;
unsigned int max_size;
char name[80];
pthread_mutex_t lock;
};
enum xe_eudebug_debugger_worker_state {
DEBUGGER_WORKER_INACTIVE = 0,
DEBUGGER_WORKER_ACTIVE,
DEBUGGER_WORKER_QUITTING,
};
struct xe_eudebug_debugger {
int fd;
uint64_t flags;
/* Used to smuggle private data */
void *ptr;
struct xe_eudebug_event_log *log;
uint64_t event_count;
uint64_t target_pid;
struct igt_list_head triggers;
int master_fd;
pthread_t worker_thread;
enum xe_eudebug_debugger_worker_state worker_state;
int p_client[2];
};
struct xe_eudebug_client {
int pid;
uint64_t seqno;
uint64_t flags;
/* Used to smuggle private data */
void *ptr;
struct xe_eudebug_event_log *log;
int done;
int p_in[2];
int p_out[2];
/* Used to pickup right device (the one used in debugger) */
int master_fd;
int timeout_ms;
pthread_mutex_t lock;
};
struct xe_eudebug_session {
uint64_t flags;
struct xe_eudebug_client *client;
struct xe_eudebug_debugger *debugger;
};
typedef void (*xe_eudebug_client_work_fn)(struct xe_eudebug_client *);
typedef void (*xe_eudebug_trigger_fn)(struct xe_eudebug_debugger *,
struct drm_xe_eudebug_event *);
#define xe_eudebug_for_each_engine(fd__, hwe__) \
xe_for_each_engine(fd__, hwe__) \
if (hwe__->engine_class == DRM_XE_ENGINE_CLASS_RENDER || \
hwe__->engine_class == DRM_XE_ENGINE_CLASS_COMPUTE)
#define xe_eudebug_for_each_event(_e, _log) \
for ((_e) = (_e) ? (void *)(uint8_t *)(_e) + (_e)->len : \
(void *)(_log)->log; \
(uint8_t *)(_e) < (_log)->log + (_log)->head; \
(_e) = (void *)(uint8_t *)(_e) + (_e)->len)
#define xe_eudebug_assert(d, c) \
do { \
if (!(c)) { \
xe_eudebug_event_log_print((d)->log, true); \
igt_assert(c); \
} \
} while (0)
#define xe_eudebug_assert_f(d, c, f...) \
do { \
if (!(c)) { \
xe_eudebug_event_log_print((d)->log, true); \
igt_assert_f(c, f); \
} \
} while (0)
#define XE_EUDEBUG_EVENT_STRING_MAX_LEN 4096
/*
* Default abort timeout to use across xe_eudebug lib and tests if no specific
* timeout value is required.
*/
#define XE_EUDEBUG_DEFAULT_TIMEOUT_SEC 60ULL
#define XE_EUDEBUG_FILTER_EVENT_NONE BIT(DRM_XE_EUDEBUG_EVENT_NONE)
#define XE_EUDEBUG_FILTER_EVENT_READ BIT(DRM_XE_EUDEBUG_EVENT_READ)
#define XE_EUDEBUG_FILTER_EVENT_OPEN BIT(DRM_XE_EUDEBUG_EVENT_OPEN)
#define XE_EUDEBUG_FILTER_EVENT_VM BIT(DRM_XE_EUDEBUG_EVENT_VM)
#define XE_EUDEBUG_FILTER_EVENT_EXEC_QUEUE BIT(DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE)
#define XE_EUDEBUG_FILTER_EVENT_EXEC_QUEUE_PLACEMENTS BIT(DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE_PLACEMENTS)
#define XE_EUDEBUG_FILTER_EVENT_EU_ATTENTION BIT(DRM_XE_EUDEBUG_EVENT_EU_ATTENTION)
#define XE_EUDEBUG_FILTER_EVENT_VM_BIND BIT(DRM_XE_EUDEBUG_EVENT_VM_BIND)
#define XE_EUDEBUG_FILTER_EVENT_VM_BIND_OP BIT(DRM_XE_EUDEBUG_EVENT_VM_BIND_OP)
#define XE_EUDEBUG_FILTER_EVENT_VM_BIND_UFENCE BIT(DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE)
#define XE_EUDEBUG_FILTER_EVENT_METADATA BIT(DRM_XE_EUDEBUG_EVENT_METADATA)
#define XE_EUDEBUG_FILTER_EVENT_VM_BIND_OP_METADATA BIT(DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA)
#define XE_EUDEBUG_FILTER_EVENT_PAGEFAULT BIT(DRM_XE_EUDEBUG_EVENT_PAGEFAULT)
#define XE_EUDEBUG_FILTER_ALL GENMASK(DRM_XE_EUDEBUG_EVENT_PAGEFAULT, 0)
#define XE_EUDEBUG_EVENT_IS_FILTERED(_e, _f) ((1UL << (_e)) & (_f))
int xe_eudebug_connect(int fd, pid_t pid, uint32_t flags);
const char *xe_eudebug_event_to_str(struct drm_xe_eudebug_event *e, char *buf, size_t len);
struct drm_xe_eudebug_event *
xe_eudebug_event_log_find_seqno(struct xe_eudebug_event_log *l, uint64_t seqno);
struct xe_eudebug_event_log *
xe_eudebug_event_log_create(const char *name, unsigned int max_size);
void xe_eudebug_event_log_destroy(struct xe_eudebug_event_log *l);
void xe_eudebug_event_log_print(struct xe_eudebug_event_log *l, bool debug);
void xe_eudebug_event_log_compare(struct xe_eudebug_event_log *c, struct xe_eudebug_event_log *d,
uint32_t filter);
void xe_eudebug_event_log_write(struct xe_eudebug_event_log *l, struct drm_xe_eudebug_event *e);
void xe_eudebug_event_log_match_opposite(struct xe_eudebug_event_log *l, uint32_t filter);
bool xe_eudebug_debugger_available(int fd);
struct xe_eudebug_debugger *
xe_eudebug_debugger_create(int xe, uint64_t flags, void *data);
void xe_eudebug_debugger_destroy(struct xe_eudebug_debugger *d);
int xe_eudebug_debugger_attach(struct xe_eudebug_debugger *d, struct xe_eudebug_client *c);
void xe_eudebug_debugger_start_worker(struct xe_eudebug_debugger *d);
void xe_eudebug_debugger_stop_worker(struct xe_eudebug_debugger *d, int timeout_s);
void xe_eudebug_debugger_detach(struct xe_eudebug_debugger *d);
void xe_eudebug_debugger_set_data(struct xe_eudebug_debugger *c, void *ptr);
void xe_eudebug_debugger_add_trigger(struct xe_eudebug_debugger *d, int type,
xe_eudebug_trigger_fn fn);
void xe_eudebug_debugger_remove_trigger(struct xe_eudebug_debugger *d, int type,
xe_eudebug_trigger_fn fn);
void xe_eudebug_debugger_signal_stage(struct xe_eudebug_debugger *d, uint64_t stage);
void xe_eudebug_debugger_wait_stage(struct xe_eudebug_session *s, uint64_t stage);
struct xe_eudebug_client *
xe_eudebug_client_create(int xe, xe_eudebug_client_work_fn work, uint64_t flags, void *data);
void xe_eudebug_client_destroy(struct xe_eudebug_client *c);
void xe_eudebug_client_start(struct xe_eudebug_client *c);
void xe_eudebug_client_stop(struct xe_eudebug_client *c);
void xe_eudebug_client_wait_done(struct xe_eudebug_client *c);
void xe_eudebug_client_signal_stage(struct xe_eudebug_client *c, uint64_t stage);
void xe_eudebug_client_wait_stage(struct xe_eudebug_client *c, uint64_t stage);
uint64_t xe_eudebug_client_get_seqno(struct xe_eudebug_client *c);
void xe_eudebug_client_set_data(struct xe_eudebug_client *c, void *ptr);
int __xe_eudebug_enable_getset(int fd, bool *old, bool *new);
bool xe_eudebug_enable(int fd, bool enable);
int xe_eudebug_client_open_driver(struct xe_eudebug_client *c);
void xe_eudebug_client_close_driver(struct xe_eudebug_client *c, int fd);
uint32_t xe_eudebug_client_vm_create(struct xe_eudebug_client *c, int fd,
uint32_t flags, uint64_t ext);
void xe_eudebug_client_vm_destroy(struct xe_eudebug_client *c, int fd, uint32_t vm);
uint32_t xe_eudebug_client_exec_queue_create(struct xe_eudebug_client *c, int fd,
struct drm_xe_exec_queue_create *create);
void xe_eudebug_client_exec_queue_destroy(struct xe_eudebug_client *c, int fd,
struct drm_xe_exec_queue_create *create);
void xe_eudebug_client_vm_bind_event(struct xe_eudebug_client *c, uint32_t event_flags, int fd,
uint32_t vm, uint32_t bind_flags,
uint32_t num_ops, uint64_t *ref_seqno);
void xe_eudebug_client_vm_bind_op_event(struct xe_eudebug_client *c, uint32_t event_flags,
uint64_t ref_seqno, uint64_t *op_ref_seqno,
uint64_t addr, uint64_t range,
uint64_t num_extensions);
void xe_eudebug_client_vm_bind_op_metadata_event(struct xe_eudebug_client *c,
uint32_t event_flags, uint64_t op_ref_seqno,
uint64_t metadata_handle, uint64_t metadata_cookie);
void xe_eudebug_client_vm_bind_ufence_event(struct xe_eudebug_client *c, uint32_t event_flags,
uint64_t ref_seqno);
void xe_eudebug_ack_ufence(int debugfd,
const struct drm_xe_eudebug_event_vm_bind_ufence *f);
void xe_eudebug_client_vm_bind_flags(struct xe_eudebug_client *c, int fd, uint32_t vm,
uint32_t bo, uint64_t offset,
uint64_t addr, uint64_t size, uint32_t flags,
struct drm_xe_sync *sync, uint32_t num_syncs,
uint64_t op_ext);
void xe_eudebug_client_vm_bind(struct xe_eudebug_client *c, int fd, uint32_t vm,
uint32_t bo, uint64_t offset,
uint64_t addr, uint64_t size);
void xe_eudebug_client_vm_unbind_flags(struct xe_eudebug_client *c, int fd,
uint32_t vm, uint64_t offset,
uint64_t addr, uint64_t size, uint32_t flags,
struct drm_xe_sync *sync, uint32_t num_syncs);
void xe_eudebug_client_vm_unbind(struct xe_eudebug_client *c, int fd, uint32_t vm,
uint64_t offset, uint64_t addr, uint64_t size);
uint32_t xe_eudebug_client_metadata_create(struct xe_eudebug_client *c, int fd,
int type, size_t len, void *data);
void xe_eudebug_client_metadata_destroy(struct xe_eudebug_client *c, int fd,
uint32_t id, int type, size_t len);
struct xe_eudebug_session *xe_eudebug_session_create(int fd,
xe_eudebug_client_work_fn work,
unsigned int flags,
void *test_private);
void xe_eudebug_session_destroy(struct xe_eudebug_session *s);
void xe_eudebug_session_run(struct xe_eudebug_session *s);
void xe_eudebug_session_check(struct xe_eudebug_session *s, bool match_opposite, uint32_t filter);
|