| 1 |
|
| 2 | #ifndef _UAPI_ASM_X86_DEBUGREG_H
|
| 3 | #define _UAPI_ASM_X86_DEBUGREG_H
|
| 4 |
|
| 5 |
|
| 6 | |
| 7 | debug registers. Registers 0-3 contain the addresses we wish to trap on
|
| 8 | #define DR_FIRSTADDR 0
|
| 9 | #define DR_LASTADDR 3
|
| 10 |
|
| 11 | #define DR_STATUS 6
|
| 12 | #define DR_CONTROL 7
|
| 13 |
|
| 14 | |
| 15 | which debugging register was responsible for the trap. The other bits
|
| 16 | are either reserved or not of interest to us.
|
| 17 |
|
| 18 | |
| 19 | * Define bits in DR6 which are set to 1 by default.
|
| 20 | *
|
| 21 | * This is also the DR6 architectural value following Power-up, Reset or INIT.
|
| 22 | *
|
| 23 | * Note, with the introduction of Bus Lock Detection (BLD) and Restricted
|
| 24 | * Transactional Memory (RTM), the DR6 register has been modified:
|
| 25 | *
|
| 26 | * 1) BLD flag (bit 11) is no longer reserved to 1 if the CPU supports
|
| 27 | * Bus Lock Detection. The assertion of a bus lock could clear it.
|
| 28 | *
|
| 29 | * 2) RTM flag (bit 16) is no longer reserved to 1 if the CPU supports
|
| 30 | * restricted transactional memory. #DB occurred inside an RTM region
|
| 31 | * could clear it.
|
| 32 | *
|
| 33 | * Apparently, DR6.BLD and DR6.RTM are active low bits.
|
| 34 | *
|
| 35 | * As a result, DR6_RESERVED is an incorrect name now, but it is kept for
|
| 36 | * compatibility.
|
| 37 |
|
| 38 | #define DR6_RESERVED (0xFFFF0FF0)
|
| 39 |
|
| 40 | #define DR_TRAP0 (0x1)
|
| 41 | #define DR_TRAP1 (0x2)
|
| 42 | #define DR_TRAP2 (0x4)
|
| 43 | #define DR_TRAP3 (0x8)
|
| 44 | #define DR_TRAP_BITS (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)
|
| 45 |
|
| 46 | #define DR_BUS_LOCK (0x800)
|
| 47 | #define DR_STEP (0x4000)
|
| 48 | #define DR_SWITCH (0x8000)
|
| 49 |
|
| 50 | |
| 51 | The top two bytes of the control register consist of 4 fields of 4
|
| 52 | bits - each field corresponds to one of the four debug registers,
|
| 53 | and indicates what types of access we trap on, and how large the data
|
| 54 | field is that we are looking at
|
| 55 |
|
| 56 | #define DR_CONTROL_SHIFT 16
|
| 57 | #define DR_CONTROL_SIZE 4
|
| 58 |
|
| 59 | #define DR_RW_EXECUTE (0x0)
|
| 60 | #define DR_RW_WRITE (0x1)
|
| 61 | #define DR_RW_READ (0x3)
|
| 62 |
|
| 63 | #define DR_LEN_1 (0x0)
|
| 64 | #define DR_LEN_2 (0x4)
|
| 65 | #define DR_LEN_4 (0xC)
|
| 66 | #define DR_LEN_8 (0x8)
|
| 67 |
|
| 68 | |
| 69 | enabled. There are 4 fields of two bits. One bit is "local", meaning
|
| 70 | that the processor will reset the bit after a task switch and the other
|
| 71 | is global meaning that we have to explicitly reset the bit. With linux,
|
| 72 | you can use either one, since we explicitly zero the register when we enter
|
| 73 | kernel mode.
|
| 74 |
|
| 75 | #define DR_LOCAL_ENABLE_SHIFT 0
|
| 76 | #define DR_GLOBAL_ENABLE_SHIFT 1
|
| 77 | #define DR_LOCAL_ENABLE (0x1)
|
| 78 | #define DR_GLOBAL_ENABLE (0x2)
|
| 79 | #define DR_ENABLE_SIZE 2
|
| 80 |
|
| 81 | #define DR_LOCAL_ENABLE_MASK (0x55)
|
| 82 | #define DR_GLOBAL_ENABLE_MASK (0xAA)
|
| 83 |
|
| 84 | |
| 85 | We can slow the instruction pipeline for instructions coming via the
|
| 86 | gdt or the ldt if we want to. I am not sure why this is an advantage
|
| 87 |
|
| 88 | #ifdef __i386__
|
| 89 | #define DR_CONTROL_RESERVED (0xFC00)
|
| 90 | #else
|
| 91 | #define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL)
|
| 92 | #endif
|
| 93 |
|
| 94 | #define DR_LOCAL_SLOWDOWN (0x100)
|
| 95 | #define DR_GLOBAL_SLOWDOWN (0x200)
|
| 96 |
|
| 97 | |
| 98 | * HW breakpoint additions
|
| 99 |
|
| 100 |
|
| 101 | #endif
|