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