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 15*230db53fSPaolo Bonzini static volatile unsigned long bp_addr; 16*230db53fSPaolo Bonzini static volatile unsigned long db_addr[10], dr6[10]; 17478027f5SJan Kiszka static volatile unsigned int n; 18478027f5SJan Kiszka static volatile unsigned long value; 19478027f5SJan Kiszka 20478027f5SJan Kiszka static unsigned long get_dr6(void) 21478027f5SJan Kiszka { 22478027f5SJan Kiszka unsigned long value; 23478027f5SJan Kiszka 24478027f5SJan Kiszka asm volatile("mov %%dr6,%0" : "=r" (value)); 25478027f5SJan Kiszka return value; 26478027f5SJan Kiszka } 27478027f5SJan Kiszka 28478027f5SJan Kiszka static void set_dr0(void *value) 29478027f5SJan Kiszka { 30478027f5SJan Kiszka asm volatile("mov %0,%%dr0" : : "r" (value)); 31478027f5SJan Kiszka } 32478027f5SJan Kiszka 33478027f5SJan Kiszka static void set_dr1(void *value) 34478027f5SJan Kiszka { 35478027f5SJan Kiszka asm volatile("mov %0,%%dr1" : : "r" (value)); 36478027f5SJan Kiszka } 37478027f5SJan Kiszka 389e486280SPaolo Bonzini static void set_dr6(unsigned long value) 399e486280SPaolo Bonzini { 409e486280SPaolo Bonzini asm volatile("mov %0,%%dr6" : : "r" (value)); 419e486280SPaolo Bonzini } 429e486280SPaolo Bonzini 43478027f5SJan Kiszka static void set_dr7(unsigned long value) 44478027f5SJan Kiszka { 45478027f5SJan Kiszka asm volatile("mov %0,%%dr7" : : "r" (value)); 46478027f5SJan Kiszka } 47478027f5SJan Kiszka 48478027f5SJan Kiszka static void handle_db(struct ex_regs *regs) 49478027f5SJan Kiszka { 50*230db53fSPaolo Bonzini db_addr[n] = regs->rip; 51478027f5SJan Kiszka dr6[n] = get_dr6(); 52478027f5SJan Kiszka 53478027f5SJan Kiszka if (dr6[n] & 0x1) 54478027f5SJan Kiszka regs->rflags |= (1 << 16); 55478027f5SJan Kiszka 56478027f5SJan Kiszka if (++n >= 10) { 57478027f5SJan Kiszka regs->rflags &= ~(1 << 8); 58478027f5SJan Kiszka set_dr7(0x00000400); 59478027f5SJan Kiszka } 60478027f5SJan Kiszka } 61478027f5SJan Kiszka 62478027f5SJan Kiszka static void handle_bp(struct ex_regs *regs) 63478027f5SJan Kiszka { 64*230db53fSPaolo Bonzini bp_addr = regs->rip; 65478027f5SJan Kiszka } 66478027f5SJan Kiszka 67478027f5SJan Kiszka int main(int ac, char **av) 68478027f5SJan Kiszka { 69478027f5SJan Kiszka unsigned long start; 70478027f5SJan Kiszka 71478027f5SJan Kiszka setup_idt(); 72478027f5SJan Kiszka handle_exception(DB_VECTOR, handle_db); 73478027f5SJan Kiszka handle_exception(BP_VECTOR, handle_bp); 74478027f5SJan Kiszka 75c68a7ff0SPaolo Bonzini extern unsigned char sw_bp; 76c68a7ff0SPaolo Bonzini asm volatile("int3; sw_bp:"); 77*230db53fSPaolo Bonzini report("#BP", bp_addr == (unsigned long)&sw_bp); 78478027f5SJan Kiszka 799e486280SPaolo Bonzini n = 0; 80c68a7ff0SPaolo Bonzini extern unsigned char hw_bp1; 81c68a7ff0SPaolo Bonzini set_dr0(&hw_bp1); 82478027f5SJan Kiszka set_dr7(0x00000402); 83c68a7ff0SPaolo Bonzini asm volatile("hw_bp1: nop"); 849e486280SPaolo Bonzini report("hw breakpoint (test that dr6.BS is not set)", 85478027f5SJan Kiszka n == 1 && 86*230db53fSPaolo Bonzini db_addr[0] == ((unsigned long)&hw_bp1) && dr6[0] == 0xffff0ff1); 87478027f5SJan Kiszka 88478027f5SJan Kiszka n = 0; 89c68a7ff0SPaolo Bonzini extern unsigned char hw_bp2; 90c68a7ff0SPaolo Bonzini set_dr0(&hw_bp2); 919e486280SPaolo Bonzini set_dr6(0x00004002); 92c68a7ff0SPaolo Bonzini asm volatile("hw_bp2: nop"); 939e486280SPaolo Bonzini report("hw breakpoint (test that dr6.BS is not cleared)", 949e486280SPaolo Bonzini n == 1 && 95*230db53fSPaolo Bonzini db_addr[0] == ((unsigned long)&hw_bp2) && dr6[0] == 0xffff4ff1); 969e486280SPaolo Bonzini 979e486280SPaolo Bonzini n = 0; 989e486280SPaolo Bonzini set_dr6(0); 99478027f5SJan Kiszka asm volatile( 100478027f5SJan Kiszka "pushf\n\t" 101478027f5SJan Kiszka "pop %%rax\n\t" 102478027f5SJan Kiszka "or $(1<<8),%%rax\n\t" 103478027f5SJan Kiszka "push %%rax\n\t" 104478027f5SJan Kiszka "lea (%%rip),%0\n\t" 105478027f5SJan Kiszka "popf\n\t" 106478027f5SJan Kiszka "and $~(1<<8),%%rax\n\t" 107478027f5SJan Kiszka "push %%rax\n\t" 108478027f5SJan Kiszka "popf\n\t" 109478027f5SJan Kiszka : "=g" (start) : : "rax"); 110478027f5SJan Kiszka report("single step", 111478027f5SJan Kiszka n == 3 && 112*230db53fSPaolo Bonzini db_addr[0] == start+1+6 && dr6[0] == 0xffff4ff0 && 113*230db53fSPaolo Bonzini db_addr[1] == start+1+6+1 && dr6[1] == 0xffff4ff0 && 114*230db53fSPaolo Bonzini db_addr[2] == start+1+6+1+1 && dr6[2] == 0xffff4ff0); 115478027f5SJan Kiszka 1160a982d78SKyle Huey /* 1170a982d78SKyle Huey * cpuid and rdmsr (among others) trigger VM exits and are then 1180a982d78SKyle Huey * emulated. Test that single stepping works on emulated instructions. 1190a982d78SKyle Huey */ 1200a982d78SKyle Huey n = 0; 1210a982d78SKyle Huey set_dr6(0); 1220a982d78SKyle Huey asm volatile( 1230a982d78SKyle Huey "pushf\n\t" 1240a982d78SKyle Huey "pop %%rax\n\t" 1250a982d78SKyle Huey "or $(1<<8),%%rax\n\t" 1260a982d78SKyle Huey "push %%rax\n\t" 1270a982d78SKyle Huey "lea (%%rip),%0\n\t" 1280a982d78SKyle Huey "popf\n\t" 1290a982d78SKyle Huey "and $~(1<<8),%%rax\n\t" 1300a982d78SKyle Huey "push %%rax\n\t" 1310a982d78SKyle Huey "xor %%rax,%%rax\n\t" 1320a982d78SKyle Huey "cpuid\n\t" 1330a982d78SKyle Huey "movl $0x1a0,%%ecx\n\t" 1340a982d78SKyle Huey "rdmsr\n\t" 1350a982d78SKyle Huey "popf\n\t" 1360a982d78SKyle Huey : "=g" (start) : : "rax", "ebx", "ecx", "edx"); 1370a982d78SKyle Huey report("single step emulated instructions", 1380a982d78SKyle Huey n == 7 && 139*230db53fSPaolo Bonzini db_addr[0] == start+1+6 && dr6[0] == 0xffff4ff0 && 140*230db53fSPaolo Bonzini db_addr[1] == start+1+6+1 && dr6[1] == 0xffff4ff0 && 141*230db53fSPaolo Bonzini db_addr[2] == start+1+6+1+3 && dr6[2] == 0xffff4ff0 && 142*230db53fSPaolo Bonzini db_addr[3] == start+1+6+1+3+2 && dr6[3] == 0xffff4ff0 && 143*230db53fSPaolo Bonzini db_addr[4] == start+1+6+1+3+2+5 && dr6[4] == 0xffff4ff0 && 144*230db53fSPaolo Bonzini db_addr[5] == start+1+6+1+3+2+5+2 && dr6[5] == 0xffff4ff0 && 145*230db53fSPaolo Bonzini db_addr[6] == start+1+6+1+3+2+5+2+1 && dr6[6] == 0xffff4ff0); 1460a982d78SKyle Huey 147478027f5SJan Kiszka n = 0; 148478027f5SJan Kiszka set_dr1((void *)&value); 149*230db53fSPaolo Bonzini set_dr7(0x00d0040a); // 4-byte write 150478027f5SJan Kiszka 151c68a7ff0SPaolo Bonzini extern unsigned char hw_wp1; 152478027f5SJan Kiszka asm volatile( 153478027f5SJan Kiszka "mov $42,%%rax\n\t" 154c68a7ff0SPaolo Bonzini "mov %%rax,%0\n\t; hw_wp1:" 155478027f5SJan Kiszka : "=m" (value) : : "rax"); 1569e486280SPaolo Bonzini report("hw watchpoint (test that dr6.BS is not cleared)", 157478027f5SJan Kiszka n == 1 && 158*230db53fSPaolo Bonzini db_addr[0] == ((unsigned long)&hw_wp1) && dr6[0] == 0xffff4ff2); 1599e486280SPaolo Bonzini 1609e486280SPaolo Bonzini n = 0; 1619e486280SPaolo Bonzini set_dr6(0); 1629e486280SPaolo Bonzini 163c68a7ff0SPaolo Bonzini extern unsigned char hw_wp2; 1649e486280SPaolo Bonzini asm volatile( 1659e486280SPaolo Bonzini "mov $42,%%rax\n\t" 166c68a7ff0SPaolo Bonzini "mov %%rax,%0\n\t; hw_wp2:" 1679e486280SPaolo Bonzini : "=m" (value) : : "rax"); 1689e486280SPaolo Bonzini report("hw watchpoint (test that dr6.BS is not set)", 1699e486280SPaolo Bonzini n == 1 && 170*230db53fSPaolo Bonzini db_addr[0] == ((unsigned long)&hw_wp2) && dr6[0] == 0xffff0ff2); 1719e486280SPaolo Bonzini 1729e486280SPaolo Bonzini n = 0; 1739e486280SPaolo Bonzini set_dr6(0); 174c68a7ff0SPaolo Bonzini extern unsigned char sw_icebp; 175c68a7ff0SPaolo Bonzini asm volatile(".byte 0xf1; sw_icebp:"); 1769e486280SPaolo Bonzini report("icebp", 1779e486280SPaolo Bonzini n == 1 && 178*230db53fSPaolo Bonzini db_addr[0] == (unsigned long)&sw_icebp && 1799e486280SPaolo Bonzini dr6[0] == 0xffff0ff0); 180478027f5SJan Kiszka 18186065ca2SAndrew Jones return report_summary(); 182478027f5SJan Kiszka } 183