xref: /kvm-unit-tests/x86/debug.c (revision 9e486280a0173c61eb3426956aac15f48ed89e3e)
1478027f5SJan Kiszka /*
2478027f5SJan Kiszka  * Test for x86 debugging facilities
3478027f5SJan Kiszka  *
4478027f5SJan Kiszka  * Copyright (c) Siemens AG, 2014
5478027f5SJan Kiszka  *
6478027f5SJan Kiszka  * Authors:
7478027f5SJan Kiszka  *  Jan Kiszka <jan.kiszka@siemens.com>
8478027f5SJan Kiszka  *
9478027f5SJan Kiszka  * This work is licensed under the terms of the GNU GPL, version 2.
10478027f5SJan Kiszka  */
11478027f5SJan Kiszka 
12478027f5SJan Kiszka #include "libcflat.h"
13478027f5SJan Kiszka #include "desc.h"
14478027f5SJan Kiszka 
15478027f5SJan Kiszka static volatile unsigned long bp_addr[10], dr6[10];
16478027f5SJan Kiszka static volatile unsigned int n;
17478027f5SJan Kiszka static volatile unsigned long value;
18478027f5SJan Kiszka 
19478027f5SJan Kiszka static unsigned long get_dr6(void)
20478027f5SJan Kiszka {
21478027f5SJan Kiszka 	unsigned long value;
22478027f5SJan Kiszka 
23478027f5SJan Kiszka 	asm volatile("mov %%dr6,%0" : "=r" (value));
24478027f5SJan Kiszka 	return value;
25478027f5SJan Kiszka }
26478027f5SJan Kiszka 
27478027f5SJan Kiszka static void set_dr0(void *value)
28478027f5SJan Kiszka {
29478027f5SJan Kiszka 	asm volatile("mov %0,%%dr0" : : "r" (value));
30478027f5SJan Kiszka }
31478027f5SJan Kiszka 
32478027f5SJan Kiszka static void set_dr1(void *value)
33478027f5SJan Kiszka {
34478027f5SJan Kiszka 	asm volatile("mov %0,%%dr1" : : "r" (value));
35478027f5SJan Kiszka }
36478027f5SJan Kiszka 
37*9e486280SPaolo Bonzini static void set_dr6(unsigned long value)
38*9e486280SPaolo Bonzini {
39*9e486280SPaolo Bonzini 	asm volatile("mov %0,%%dr6" : : "r" (value));
40*9e486280SPaolo Bonzini }
41*9e486280SPaolo Bonzini 
42478027f5SJan Kiszka static void set_dr7(unsigned long value)
43478027f5SJan Kiszka {
44478027f5SJan Kiszka 	asm volatile("mov %0,%%dr7" : : "r" (value));
45478027f5SJan Kiszka }
46478027f5SJan Kiszka 
47478027f5SJan Kiszka static void handle_db(struct ex_regs *regs)
48478027f5SJan Kiszka {
49478027f5SJan Kiszka 	bp_addr[n] = regs->rip;
50478027f5SJan Kiszka 	dr6[n] = get_dr6();
51478027f5SJan Kiszka 
52478027f5SJan Kiszka 	if (dr6[n] & 0x1)
53478027f5SJan Kiszka 		regs->rflags |= (1 << 16);
54478027f5SJan Kiszka 
55478027f5SJan Kiszka 	if (++n >= 10) {
56478027f5SJan Kiszka 		regs->rflags &= ~(1 << 8);
57478027f5SJan Kiszka 		set_dr7(0x00000400);
58478027f5SJan Kiszka 	}
59478027f5SJan Kiszka }
60478027f5SJan Kiszka 
61478027f5SJan Kiszka static void handle_bp(struct ex_regs *regs)
62478027f5SJan Kiszka {
63478027f5SJan Kiszka 	bp_addr[0] = regs->rip;
64478027f5SJan Kiszka }
65478027f5SJan Kiszka 
66478027f5SJan Kiszka int main(int ac, char **av)
67478027f5SJan Kiszka {
68478027f5SJan Kiszka 	unsigned long start;
69478027f5SJan Kiszka 
70478027f5SJan Kiszka 	setup_idt();
71478027f5SJan Kiszka 	handle_exception(DB_VECTOR, handle_db);
72478027f5SJan Kiszka 	handle_exception(BP_VECTOR, handle_bp);
73478027f5SJan Kiszka 
74478027f5SJan Kiszka sw_bp:
75478027f5SJan Kiszka 	asm volatile("int3");
76478027f5SJan Kiszka 	report("#BP", bp_addr[0] == (unsigned long)&&sw_bp + 1);
77478027f5SJan Kiszka 
78*9e486280SPaolo Bonzini 	n = 0;
79*9e486280SPaolo Bonzini 	set_dr0(&&hw_bp1);
80478027f5SJan Kiszka 	set_dr7(0x00000402);
81*9e486280SPaolo Bonzini hw_bp1:
82478027f5SJan Kiszka 	asm volatile("nop");
83*9e486280SPaolo Bonzini 	report("hw breakpoint (test that dr6.BS is not set)",
84478027f5SJan Kiszka 	       n == 1 &&
85*9e486280SPaolo Bonzini 	       bp_addr[0] == ((unsigned long)&&hw_bp1) && dr6[0] == 0xffff0ff1);
86478027f5SJan Kiszka 
87478027f5SJan Kiszka 	n = 0;
88*9e486280SPaolo Bonzini 	set_dr0(&&hw_bp2);
89*9e486280SPaolo Bonzini 	set_dr6(0x00004002);
90*9e486280SPaolo Bonzini hw_bp2:
91*9e486280SPaolo Bonzini 	asm volatile("nop");
92*9e486280SPaolo Bonzini 	report("hw breakpoint (test that dr6.BS is not cleared)",
93*9e486280SPaolo Bonzini 	       n == 1 &&
94*9e486280SPaolo Bonzini 	       bp_addr[0] == ((unsigned long)&&hw_bp2) && dr6[0] == 0xffff4ff1);
95*9e486280SPaolo Bonzini 
96*9e486280SPaolo Bonzini 	n = 0;
97*9e486280SPaolo Bonzini 	set_dr6(0);
98478027f5SJan Kiszka 	asm volatile(
99478027f5SJan Kiszka 		"pushf\n\t"
100478027f5SJan Kiszka 		"pop %%rax\n\t"
101478027f5SJan Kiszka 		"or $(1<<8),%%rax\n\t"
102478027f5SJan Kiszka 		"push %%rax\n\t"
103478027f5SJan Kiszka 		"lea (%%rip),%0\n\t"
104478027f5SJan Kiszka 		"popf\n\t"
105478027f5SJan Kiszka 		"and $~(1<<8),%%rax\n\t"
106478027f5SJan Kiszka 		"push %%rax\n\t"
107478027f5SJan Kiszka 		"popf\n\t"
108478027f5SJan Kiszka 		: "=g" (start) : : "rax");
109478027f5SJan Kiszka 	report("single step",
110478027f5SJan Kiszka 	       n == 3 &&
111478027f5SJan Kiszka 	       bp_addr[0] == start+1+6 && dr6[0] == 0xffff4ff0 &&
112478027f5SJan Kiszka 	       bp_addr[1] == start+1+6+1 && dr6[1] == 0xffff4ff0 &&
113478027f5SJan Kiszka 	       bp_addr[2] == start+1+6+1+1 && dr6[2] == 0xffff4ff0);
114478027f5SJan Kiszka 
115478027f5SJan Kiszka 	n = 0;
116478027f5SJan Kiszka 	set_dr1((void *)&value);
117478027f5SJan Kiszka 	set_dr7(0x00d0040a);
118478027f5SJan Kiszka 
119478027f5SJan Kiszka 	asm volatile(
120478027f5SJan Kiszka 		"mov $42,%%rax\n\t"
121478027f5SJan Kiszka 		"mov %%rax,%0\n\t"
122478027f5SJan Kiszka 		: "=m" (value) : : "rax");
123*9e486280SPaolo Bonzini hw_wp1:
124*9e486280SPaolo Bonzini 	report("hw watchpoint (test that dr6.BS is not cleared)",
125478027f5SJan Kiszka 	       n == 1 &&
126*9e486280SPaolo Bonzini 	       bp_addr[0] == ((unsigned long)&&hw_wp1) && dr6[0] == 0xffff4ff2);
127*9e486280SPaolo Bonzini 
128*9e486280SPaolo Bonzini 	n = 0;
129*9e486280SPaolo Bonzini 	set_dr6(0);
130*9e486280SPaolo Bonzini 
131*9e486280SPaolo Bonzini 	asm volatile(
132*9e486280SPaolo Bonzini 		"mov $42,%%rax\n\t"
133*9e486280SPaolo Bonzini 		"mov %%rax,%0\n\t"
134*9e486280SPaolo Bonzini 		: "=m" (value) : : "rax");
135*9e486280SPaolo Bonzini hw_wp2:
136*9e486280SPaolo Bonzini 	report("hw watchpoint (test that dr6.BS is not set)",
137*9e486280SPaolo Bonzini 	       n == 1 &&
138*9e486280SPaolo Bonzini 	       bp_addr[0] == ((unsigned long)&&hw_wp2) && dr6[0] == 0xffff0ff2);
139*9e486280SPaolo Bonzini 
140*9e486280SPaolo Bonzini 	n = 0;
141*9e486280SPaolo Bonzini 	set_dr6(0);
142*9e486280SPaolo Bonzini sw_icebp:
143*9e486280SPaolo Bonzini 	asm volatile(".byte 0xf1");
144*9e486280SPaolo Bonzini 	report("icebp",
145*9e486280SPaolo Bonzini 	       n == 1 &&
146*9e486280SPaolo Bonzini 	       bp_addr[0] == (unsigned long)&&sw_icebp + 1 &&
147*9e486280SPaolo Bonzini 	       dr6[0] == 0xffff0ff0);
148478027f5SJan Kiszka 
14986065ca2SAndrew Jones 	return report_summary();
150478027f5SJan Kiszka }
151