xref: /kvm-unit-tests/lib/x86/asm/debugreg.h (revision c865f654ffe4c5955038aaf74f702ba62f3eb014)
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