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 14static 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 24static inline void writeDr6Reg(word_t val) 25{ 26 asm volatile( 27 "movl %0, %%dr6 \n\t" 28 : 29 : "r"(val)); 30} 31 32static 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 42static inline void writeDr7Reg(word_t val) 43{ 44 asm volatile( 45 "movl %0, %%dr7 \n\t" 46 : 47 : "r"(val)); 48} 49 50static 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 72static 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 */ 94static 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