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