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