aboutsummaryrefslogtreecommitdiff
path: root/sys/cddl/dev/kinst/kinst.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cddl/dev/kinst/kinst.h')
-rw-r--r--sys/cddl/dev/kinst/kinst.h112
1 files changed, 112 insertions, 0 deletions
diff --git a/sys/cddl/dev/kinst/kinst.h b/sys/cddl/dev/kinst/kinst.h
new file mode 100644
index 000000000000..f0811a4a88d8
--- /dev/null
+++ b/sys/cddl/dev/kinst/kinst.h
@@ -0,0 +1,112 @@
+/*
+ * SPDX-License-Identifier: CDDL 1.0
+ *
+ * Copyright (c) 2022 Christos Margiolis <christos@FreeBSD.org>
+ * Copyright (c) 2023 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Christos Margiolis
+ * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
+ */
+
+#ifndef _KINST_H_
+#define _KINST_H_
+
+#include <sys/dtrace.h>
+
+typedef struct {
+ char kpd_func[DTRACE_FUNCNAMELEN];
+ char kpd_mod[DTRACE_MODNAMELEN];
+ int kpd_off;
+} dtrace_kinst_probedesc_t;
+
+#define KINSTIOC_MAKEPROBE _IOW('k', 1, dtrace_kinst_probedesc_t)
+
+#ifdef _KERNEL
+
+#include <sys/queue.h>
+
+#include "kinst_isa.h"
+
+struct kinst_probe {
+ LIST_ENTRY(kinst_probe) kp_hashnext;
+ const char *kp_func;
+ char kp_name[16];
+ dtrace_id_t kp_id;
+ kinst_patchval_t kp_patchval;
+ kinst_patchval_t kp_savedval;
+ kinst_patchval_t *kp_patchpoint;
+ uint8_t *kp_tramp;
+
+ struct kinst_probe_md kp_md;
+};
+
+struct kinst_cpu_state {
+ /*
+ * kinst uses a breakpoint to return from the trampoline and resume
+ * execution. To do this safely, kinst implements a per-CPU state
+ * machine; the state is set to KINST_PROBE_FIRED for the duration of
+ * the trampoline execution (i.e from the time we transfer execution to
+ * it, until we return). Upon return, the state is set to
+ * KINST_PROBE_ARMED to indicate that a probe is not currently firing.
+ * All CPUs have their state initialized to KINST_PROBE_ARMED when
+ * kinst is loaded.
+ */
+ enum {
+ KINST_PROBE_ARMED,
+ KINST_PROBE_FIRED,
+ } state;
+ /*
+ * Points to the probe whose trampoline we're currently executing.
+ */
+ const struct kinst_probe *kp;
+ /*
+ * Because we execute trampolines with interrupts disabled, we have to
+ * cache the CPU's status in order to restore it when we return from
+ * the trampoline.
+ */
+ uint64_t status;
+};
+
+LIST_HEAD(kinst_probe_list, kinst_probe);
+
+extern struct kinst_probe_list *kinst_probetab;
+
+#define KINST_PROBETAB_MAX 0x8000 /* 32k */
+#define KINST_ADDR2NDX(addr) (((uintptr_t)(addr)) & (KINST_PROBETAB_MAX - 1))
+#define KINST_GETPROBE(i) (&kinst_probetab[KINST_ADDR2NDX(i)])
+
+struct linker_file;
+struct linker_symval;
+
+/* kinst.c */
+volatile void *kinst_memcpy(volatile void *, volatile const void *, size_t);
+bool kinst_excluded(const char *);
+void kinst_probe_create(struct kinst_probe *, struct linker_file *);
+
+/* arch/kinst_isa.c */
+int kinst_invop(uintptr_t, struct trapframe *, uintptr_t);
+void kinst_patch_tracepoint(struct kinst_probe *, kinst_patchval_t);
+int kinst_make_probe(struct linker_file *, int, struct linker_symval *,
+ void *);
+int kinst_md_init(void);
+void kinst_md_deinit(void);
+bool kinst_md_excluded(const char *);
+
+/* trampoline.c */
+int kinst_trampoline_init(void);
+int kinst_trampoline_deinit(void);
+uint8_t *kinst_trampoline_alloc(int);
+void kinst_trampoline_dealloc(uint8_t *);
+
+#ifdef MALLOC_DECLARE
+MALLOC_DECLARE(M_KINST);
+#endif /* MALLOC_DECLARE */
+
+#define KINST_LOG_HELPER(fmt, ...) \
+ printf("%s:%d: " fmt "%s\n", __func__, __LINE__, __VA_ARGS__)
+#define KINST_LOG(...) \
+ KINST_LOG_HELPER(__VA_ARGS__, "")
+
+#endif /* _KERNEL */
+
+#endif /* _KINST_H_ */