1 /*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7 #pragma once
8 #include <assert.h>
9
10 #ifdef CONFIG_HARDWARE_DEBUG_API
11
12 #define X86_DEBUG_BP_N_REGS (4)
13
readDr6Reg(void)14 static inline word_t readDr6Reg(void)
15 {
16 word_t ret;
17
18 asm volatile(
19 "movl %%dr6, %0 \n\t"
20 : "=r"(ret));
21 return ret;
22 }
23
writeDr6Reg(word_t val)24 static inline void writeDr6Reg(word_t val)
25 {
26 asm volatile(
27 "movl %0, %%dr6 \n\t"
28 :
29 : "r"(val));
30 }
31
readDr7Reg(void)32 static inline word_t readDr7Reg(void)
33 {
34 word_t ret;
35
36 asm volatile(
37 "movl %%dr7, %0 \n\t"
38 : "=r"(ret));
39 return ret;
40 }
41
writeDr7Reg(word_t val)42 static inline void writeDr7Reg(word_t val)
43 {
44 asm volatile(
45 "movl %0, %%dr7 \n\t"
46 :
47 : "r"(val));
48 }
49
readDrReg(uint8_t reg)50 static inline word_t readDrReg(uint8_t reg)
51 {
52 word_t ret;
53
54 assert(reg < X86_DEBUG_BP_N_REGS);
55 switch (reg) {
56 case 0:
57 asm volatile("movl %%dr0, %0 \n\t" : "=r"(ret));
58 break;
59 case 1:
60 asm volatile("movl %%dr1, %0 \n\t" : "=r"(ret));
61 break;
62 case 2:
63 asm volatile("movl %%dr2, %0 \n\t" : "=r"(ret));
64 break;
65 default:
66 asm volatile("movl %%dr3, %0 \n\t" : "=r"(ret));
67 break;
68 }
69 return ret;
70 }
71
writeDrReg(uint8_t reg,word_t val)72 static inline void writeDrReg(uint8_t reg, word_t val)
73 {
74 assert(reg < X86_DEBUG_BP_N_REGS);
75 switch (reg) {
76 case 0:
77 asm volatile("movl %0, %%dr0 \n\t" :: "r"(val));
78 break;
79 case 1:
80 asm volatile("movl %0, %%dr1 \n\t" :: "r"(val));
81 break;
82 case 2:
83 asm volatile("movl %0, %%dr2 \n\t" :: "r"(val));
84 break;
85 default:
86 asm volatile("movl %0, %%dr3 \n\t" :: "r"(val));
87 break;
88 }
89 }
90
91 /** Restore debug register context from a block of memory.
92 *@param source The memory block from which to load the register values.
93 */
loadBreakpointState(tcb_t * source)94 static inline void loadBreakpointState(tcb_t *source)
95 {
96 /* Order does matter when restoring the registers: we want to restore the
97 * breakpoint control register (DR7) last since it is what "activates" the
98 * effects of the configuration described by the other registers.
99 */
100 asm volatile(
101 "movl %0, %%edx \n\t"
102 "movl (%%edx), %%ecx \n\t"
103 "movl %%ecx, %%dr0 \n\t"
104 "addl $4, %%edx \n\t"
105 "movl (%%edx), %%ecx \n\t"
106 "movl %%ecx, %%dr1 \n\t"
107 "addl $4, %%edx \n\t"
108 "movl (%%edx), %%ecx \n\t"
109 "movl %%ecx, %%dr2 \n\t"
110 "addl $4, %%edx \n\t"
111 "movl (%%edx), %%ecx \n\t"
112 "movl %%ecx, %%dr3 \n\t"
113 "addl $4, %%edx \n\t"
114 "movl (%%edx), %%ecx \n\t"
115 "movl %%ecx, %%dr6 \n\t"
116 "addl $4, %%edx \n\t"
117 "movl (%%edx), %%ecx \n\t"
118 "movl %%ecx, %%dr7 \n\t"
119 :
120 : "r"(source->tcbArch.tcbContext.breakpointState.dr)
121 : "edx", "ecx");
122 }
123
124 #endif /* CONFIG_HARDWARE_DEBUG_API */
125