My Project
Loading...
Searching...
No Matches
debugfunctions.c
Go to the documentation of this file.
1/*
2 * PROJECT: MatanelOS Kernel
3 * LICENSE: GPLv3
4 * PURPOSE: Debugging Functions Implementation.
5 */
6
7#include "../../includes/md.h"
8#include "../../includes/mh.h"
9
10 /* Find a free debug slot (0..3) or -1 if none */
12 for (int i = 0; i < 4; ++i) {
13 if (MeGetCurrentProcessor()->DebugEntry[i].Callback == NULL) return i;
14 }
15 return -1;
16}
17
18static inline void write_dr_idx(int idx, uint64_t value) {
19 __write_dr(idx, value);
20}
21static inline uint64_t read_dr7(void) { return __read_dr(7); }
22static inline void write_dr7(uint64_t v) { __write_dr(7, v); }
23static inline void write_dr6(uint64_t v) { __write_dr(6, v); }
24
25// PUBLIC API
26MTSTATUS MdSetHardwareBreakpoint(DebugCallback CallbackFunction, void* BreakpointAddress, DEBUG_ACCESS_MODE AccessMode, DEBUG_LENGTH Length) {
27 if (!CallbackFunction || !BreakpointAddress) return MT_INVALID_PARAM;
28 if (AccessMode == DEBUG_ACCESS_IO) return MT_NOT_IMPLEMENTED; /* legacy / not handled */
29#ifdef DEBUG
30 /* Validate length */
32 return MT_INVALID_PARAM;
33
34 int idx = find_available_debug_reg();
35 if (idx == -1) return MT_NO_RESOURCES;
36
37 uint64_t addr = (uint64_t)BreakpointAddress;
38
39 /* Write address into DRx */
40 write_dr_idx(idx, addr);
41
42 /* Clear DR6 status before enabling */
43 write_dr6(0);
44
45 /* Modify DR7 safely: only change bits for our breakpoint index and the local-enable bit */
46 uint64_t dr7 = read_dr7();
47
48 /* set local enable bit Lx (bit 0,2,4,6 for idx 0..3) */
49 dr7 |= (1ULL << (idx * 2));
50
51 /* Build the 4-bit RW/LEN field value: low 2 bits = RW, high 2 bits = LEN */
52 uint64_t group_val = ((((uint64_t)Length) & 0x3ULL) << 2) | (((uint64_t)AccessMode) & 0x3ULL);
53
54 /* Clear existing 4-bit group and set new one at bits (16 + 4*idx .. 19 + 4*idx) */
55 uint64_t mask = 0xFULL << (16 + 4 * idx);
56 dr7 &= ~mask;
57 dr7 |= (group_val << (16 + 4 * idx));
58
59 write_dr7(dr7);
60
61 // Save in the DEBUG db so the INT1 will handle it.
62 MeGetCurrentProcessor()->DebugEntry[idx].Address = BreakpointAddress;
63 MeGetCurrentProcessor()->DebugEntry[idx].Callback = CallbackFunction;
64
65 IPI_PARAMS params;
66 kmemset(&params, 0, sizeof(IPI_PARAMS));
67 params.debugRegs.address = addr;
68 params.debugRegs.dr7 = dr7;
69 params.debugRegs.callback = CallbackFunction;
70
72
73 return MT_SUCCESS;
74#else
75 return MT_NOT_IMPLEMENTED; // On release builds, this should be toggled off, as the system is in a controlled environment, plus this would corrupt user debug registers.
76#endif
77}
78
80 if (index < 0 || index > 3) return MT_INVALID_PARAM;
81 if (MeGetCurrentProcessor()->DebugEntry[index].Callback == NULL && MeGetCurrentProcessor()->DebugEntry[index].Address == NULL) return MT_NOT_FOUND;
82
83 /* Clear DRx address */
84 write_dr_idx(index, 0);
85
86 /* Clear DR7 bits for this index (local enable and RW/LEN group) */
87 uint64_t dr7 = read_dr7();
88 /* clear local enable bit */
89 dr7 &= ~(1ULL << (index * 2));
90 /* clear RW/LEN 4-bit group */
91 uint64_t mask = 0xFULL << (16 + 4 * index);
92 dr7 &= ~mask;
93 write_dr7(dr7);
94
95 /* Clear status DR6 too */
96 write_dr6(0);
97
98 IPI_PARAMS params;
99 params.debugRegs.address = (uint64_t)MeGetCurrentProcessor()->DebugEntry[index].Address;
100
101 /* Clear table entry */
104
106
107 return MT_SUCCESS;
108}
109
111 if (!BreakpointAddress) return MT_INVALID_PARAM;
112 for (int i = 0; i < 4; ++i) {
113 if (MeGetCurrentProcessor()->DebugEntry[i].Address == BreakpointAddress) {
115 }
116 }
117 return MT_NOT_FOUND;
118}
int find_available_debug_reg(void)
MTSTATUS MdClearHardwareBreakpointByIndex(int index)
MTSTATUS MdClearHardwareBreakpointByAddress(void *BreakpointAddress)
MTSTATUS MdSetHardwareBreakpoint(DebugCallback CallbackFunction, void *BreakpointAddress, DEBUG_ACCESS_MODE AccessMode, DEBUG_LENGTH Length)
FORCEINLINE uint64_t __read_dr(int reg)
Definition intrin.h:109
FORCEINLINE void __write_dr(int reg, uint64_t val)
Definition intrin.h:124
enum _DEBUG_ACCESS_MODE DEBUG_ACCESS_MODE
void(* DebugCallback)(void *)
Definition me.h:139
@ DEBUG_LEN_QWORD
Definition me.h:174
@ DEBUG_LEN_WORD
Definition me.h:173
@ DEBUG_LEN_BYTE
Definition me.h:172
@ DEBUG_LEN_DWORD
Definition me.h:175
enum _DEBUG_LENGTH DEBUG_LENGTH
FORCEINLINE PPROCESSOR MeGetCurrentProcessor(void)
Definition me.h:356
@ DEBUG_ACCESS_IO
Definition me.h:167
@ CPU_ACTION_WRITE_DEBUG_REGS
Definition mh.h:95
@ CPU_ACTION_CLEAR_DEBUG_REGS
Definition mh.h:96
struct _IPI_PARAMS IPI_PARAMS
uint64_t Address
Definition mh.h:4
uint32_t Length
Definition mh.h:6
FORCEINLINE void * kmemset(void *dest, int64_t val, uint64_t len)
Definition mm.h:540
#define MT_SUCCESS
Definition mtstatus.h:22
#define MT_NOT_IMPLEMENTED
Definition mtstatus.h:23
#define MT_INVALID_PARAM
Definition mtstatus.h:24
int32_t MTSTATUS
Definition mtstatus.h:12
#define MT_NOT_FOUND
Definition mtstatus.h:30
#define MT_NO_RESOURCES
Definition mtstatus.h:32
void MhSendActionToCpusAndWait(CPU_ACTION action, IPI_PARAMS parameter)
Definition smp.c:212
DebugCallback Callback
Definition me.h:143
void * Address
Definition me.h:142
uint64_t address
Definition mh.h:389
uint64_t dr7
Definition mh.h:388
DebugCallback callback
Definition mh.h:390
struct _DEBUG_REGISTERS debugRegs
Definition mh.h:398
struct _DEBUG_ENTRY DebugEntry[4]
Definition me.h:327