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