1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2*4882a593Smuzhiyun #ifndef _UAPI_ASM_X86_DEBUGREG_H 3*4882a593Smuzhiyun #define _UAPI_ASM_X86_DEBUGREG_H 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun /* Indicate the register numbers for a number of the specific 7*4882a593Smuzhiyun debug registers. Registers 0-3 contain the addresses we wish to trap on */ 8*4882a593Smuzhiyun #define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */ 9*4882a593Smuzhiyun #define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */ 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #define DR_STATUS 6 /* u_debugreg[DR_STATUS] */ 12*4882a593Smuzhiyun #define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */ 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun /* Define a few things for the status register. We can use this to determine 15*4882a593Smuzhiyun which debugging register was responsible for the trap. The other bits 16*4882a593Smuzhiyun are either reserved or not of interest to us. */ 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun /* Define reserved bits in DR6 which are always set to 1 */ 19*4882a593Smuzhiyun #define DR6_RESERVED (0xFFFF0FF0) 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun #define DR_TRAP0 (0x1) /* db0 */ 22*4882a593Smuzhiyun #define DR_TRAP1 (0x2) /* db1 */ 23*4882a593Smuzhiyun #define DR_TRAP2 (0x4) /* db2 */ 24*4882a593Smuzhiyun #define DR_TRAP3 (0x8) /* db3 */ 25*4882a593Smuzhiyun #define DR_TRAP_BITS (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3) 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun #define DR_STEP (0x4000) /* single-step */ 28*4882a593Smuzhiyun #define DR_SWITCH (0x8000) /* task switch */ 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun /* Now define a bunch of things for manipulating the control register. 31*4882a593Smuzhiyun The top two bytes of the control register consist of 4 fields of 4 32*4882a593Smuzhiyun bits - each field corresponds to one of the four debug registers, 33*4882a593Smuzhiyun and indicates what types of access we trap on, and how large the data 34*4882a593Smuzhiyun field is that we are looking at */ 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun #define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */ 37*4882a593Smuzhiyun #define DR_CONTROL_SIZE 4 /* 4 control bits per register */ 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun #define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */ 40*4882a593Smuzhiyun #define DR_RW_WRITE (0x1) 41*4882a593Smuzhiyun #define DR_RW_READ (0x3) 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun #define DR_LEN_1 (0x0) /* Settings for data length to trap on */ 44*4882a593Smuzhiyun #define DR_LEN_2 (0x4) 45*4882a593Smuzhiyun #define DR_LEN_4 (0xC) 46*4882a593Smuzhiyun #define DR_LEN_8 (0x8) 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun /* The low byte to the control register determine which registers are 49*4882a593Smuzhiyun enabled. There are 4 fields of two bits. One bit is "local", meaning 50*4882a593Smuzhiyun that the processor will reset the bit after a task switch and the other 51*4882a593Smuzhiyun is global meaning that we have to explicitly reset the bit. With linux, 52*4882a593Smuzhiyun you can use either one, since we explicitly zero the register when we enter 53*4882a593Smuzhiyun kernel mode. */ 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun #define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ 56*4882a593Smuzhiyun #define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ 57*4882a593Smuzhiyun #define DR_LOCAL_ENABLE (0x1) /* Local enable for reg 0 */ 58*4882a593Smuzhiyun #define DR_GLOBAL_ENABLE (0x2) /* Global enable for reg 0 */ 59*4882a593Smuzhiyun #define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun #define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ 62*4882a593Smuzhiyun #define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */ 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun /* The second byte to the control register has a few special things. 65*4882a593Smuzhiyun We can slow the instruction pipeline for instructions coming via the 66*4882a593Smuzhiyun gdt or the ldt if we want to. I am not sure why this is an advantage */ 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun #ifdef __i386__ 69*4882a593Smuzhiyun #define DR_CONTROL_RESERVED (0xFC00) /* Reserved by Intel */ 70*4882a593Smuzhiyun #else 71*4882a593Smuzhiyun #define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL) /* Reserved */ 72*4882a593Smuzhiyun #endif 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun #define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ 75*4882a593Smuzhiyun #define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun /* 78*4882a593Smuzhiyun * HW breakpoint additions 79*4882a593Smuzhiyun */ 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun #endif /* _UAPI_ASM_X86_DEBUGREG_H */ 82