1*69de9b31SRicardo Koller #include <libcflat.h> 2*69de9b31SRicardo Koller #include <errata.h> 3*69de9b31SRicardo Koller #include <asm/setup.h> 4*69de9b31SRicardo Koller #include <asm/processor.h> 5*69de9b31SRicardo Koller #include <asm/delay.h> 6*69de9b31SRicardo Koller #include <asm/smp.h> 7*69de9b31SRicardo Koller #include <asm/barrier.h> 8*69de9b31SRicardo Koller #include <asm/io.h> 9*69de9b31SRicardo Koller 10*69de9b31SRicardo Koller #define MDSCR_KDE (1 << 13) 11*69de9b31SRicardo Koller #define MDSCR_MDE (1 << 15) 12*69de9b31SRicardo Koller 13*69de9b31SRicardo Koller #define DBGBCR_LEN8 (0xff << 5) 14*69de9b31SRicardo Koller #define DBGBCR_EXEC (0x0 << 3) 15*69de9b31SRicardo Koller #define DBGBCR_EL1 (0x1 << 1) 16*69de9b31SRicardo Koller #define DBGBCR_E (0x1 << 0) 17*69de9b31SRicardo Koller 18*69de9b31SRicardo Koller #define SPSR_D (1 << 9) 19*69de9b31SRicardo Koller 20*69de9b31SRicardo Koller #define ESR_EC_HW_BP_CURRENT 0x31 21*69de9b31SRicardo Koller 22*69de9b31SRicardo Koller #define ID_AA64DFR0_BRPS_SHIFT 12 23*69de9b31SRicardo Koller #define ID_AA64DFR0_BRPS_MASK 0xf 24*69de9b31SRicardo Koller 25*69de9b31SRicardo Koller static volatile uint64_t hw_bp_idx, hw_bp_addr[16]; 26*69de9b31SRicardo Koller 27*69de9b31SRicardo Koller static void hw_bp_handler(struct pt_regs *regs, unsigned int esr) 28*69de9b31SRicardo Koller { 29*69de9b31SRicardo Koller hw_bp_addr[hw_bp_idx++] = regs->pc; 30*69de9b31SRicardo Koller regs->pstate |= SPSR_D; 31*69de9b31SRicardo Koller } 32*69de9b31SRicardo Koller 33*69de9b31SRicardo Koller static int get_num_hw_bp(void) 34*69de9b31SRicardo Koller { 35*69de9b31SRicardo Koller uint64_t reg = read_sysreg(id_aa64dfr0_el1); 36*69de9b31SRicardo Koller /* Number of breakpoints, minus 1 */ 37*69de9b31SRicardo Koller uint8_t brps = (reg >> ID_AA64DFR0_BRPS_SHIFT) & ID_AA64DFR0_BRPS_MASK; 38*69de9b31SRicardo Koller 39*69de9b31SRicardo Koller return brps + 1; 40*69de9b31SRicardo Koller } 41*69de9b31SRicardo Koller 42*69de9b31SRicardo Koller static void write_dbgbcr(int n, uint32_t bcr) 43*69de9b31SRicardo Koller { 44*69de9b31SRicardo Koller switch (n) { 45*69de9b31SRicardo Koller case 0: 46*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr0_el1); break; 47*69de9b31SRicardo Koller case 1: 48*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr1_el1); break; 49*69de9b31SRicardo Koller case 2: 50*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr2_el1); break; 51*69de9b31SRicardo Koller case 3: 52*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr3_el1); break; 53*69de9b31SRicardo Koller case 4: 54*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr4_el1); break; 55*69de9b31SRicardo Koller case 5: 56*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr5_el1); break; 57*69de9b31SRicardo Koller case 6: 58*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr6_el1); break; 59*69de9b31SRicardo Koller case 7: 60*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr7_el1); break; 61*69de9b31SRicardo Koller case 8: 62*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr8_el1); break; 63*69de9b31SRicardo Koller case 9: 64*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr9_el1); break; 65*69de9b31SRicardo Koller case 10: 66*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr10_el1); break; 67*69de9b31SRicardo Koller case 11: 68*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr11_el1); break; 69*69de9b31SRicardo Koller case 12: 70*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr12_el1); break; 71*69de9b31SRicardo Koller case 13: 72*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr13_el1); break; 73*69de9b31SRicardo Koller case 14: 74*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr14_el1); break; 75*69de9b31SRicardo Koller case 15: 76*69de9b31SRicardo Koller write_sysreg(bcr, dbgbcr15_el1); break; 77*69de9b31SRicardo Koller default: 78*69de9b31SRicardo Koller report_abort("Invalid bcr"); 79*69de9b31SRicardo Koller } 80*69de9b31SRicardo Koller } 81*69de9b31SRicardo Koller 82*69de9b31SRicardo Koller static void write_dbgbvr(int n, uint64_t bvr) 83*69de9b31SRicardo Koller { 84*69de9b31SRicardo Koller switch (n) { 85*69de9b31SRicardo Koller case 0: 86*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr0_el1); break; 87*69de9b31SRicardo Koller case 1: 88*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr1_el1); break; 89*69de9b31SRicardo Koller case 2: 90*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr2_el1); break; 91*69de9b31SRicardo Koller case 3: 92*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr3_el1); break; 93*69de9b31SRicardo Koller case 4: 94*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr4_el1); break; 95*69de9b31SRicardo Koller case 5: 96*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr5_el1); break; 97*69de9b31SRicardo Koller case 6: 98*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr6_el1); break; 99*69de9b31SRicardo Koller case 7: 100*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr7_el1); break; 101*69de9b31SRicardo Koller case 8: 102*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr8_el1); break; 103*69de9b31SRicardo Koller case 9: 104*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr9_el1); break; 105*69de9b31SRicardo Koller case 10: 106*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr10_el1); break; 107*69de9b31SRicardo Koller case 11: 108*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr11_el1); break; 109*69de9b31SRicardo Koller case 12: 110*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr12_el1); break; 111*69de9b31SRicardo Koller case 13: 112*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr13_el1); break; 113*69de9b31SRicardo Koller case 14: 114*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr14_el1); break; 115*69de9b31SRicardo Koller case 15: 116*69de9b31SRicardo Koller write_sysreg(bvr, dbgbvr15_el1); break; 117*69de9b31SRicardo Koller default: 118*69de9b31SRicardo Koller report_abort("invalid bvr"); 119*69de9b31SRicardo Koller } 120*69de9b31SRicardo Koller } 121*69de9b31SRicardo Koller 122*69de9b31SRicardo Koller static void reset_debug_state(void) 123*69de9b31SRicardo Koller { 124*69de9b31SRicardo Koller int i, num_bp = get_num_hw_bp(); 125*69de9b31SRicardo Koller 126*69de9b31SRicardo Koller asm volatile("msr daifset, #8"); 127*69de9b31SRicardo Koller 128*69de9b31SRicardo Koller write_sysreg(0, osdlr_el1); 129*69de9b31SRicardo Koller write_sysreg(0, oslar_el1); 130*69de9b31SRicardo Koller isb(); 131*69de9b31SRicardo Koller 132*69de9b31SRicardo Koller write_sysreg(0, mdscr_el1); 133*69de9b31SRicardo Koller for (i = 0; i < num_bp; i++) { 134*69de9b31SRicardo Koller write_dbgbvr(i, 0); 135*69de9b31SRicardo Koller write_dbgbcr(i, 0); 136*69de9b31SRicardo Koller } 137*69de9b31SRicardo Koller isb(); 138*69de9b31SRicardo Koller } 139*69de9b31SRicardo Koller 140*69de9b31SRicardo Koller static void do_migrate(void) 141*69de9b31SRicardo Koller { 142*69de9b31SRicardo Koller puts("Now migrate the VM, then press a key to continue...\n"); 143*69de9b31SRicardo Koller (void)getchar(); 144*69de9b31SRicardo Koller report_info("Migration complete"); 145*69de9b31SRicardo Koller } 146*69de9b31SRicardo Koller 147*69de9b31SRicardo Koller static void test_hw_bp(bool migrate) 148*69de9b31SRicardo Koller { 149*69de9b31SRicardo Koller extern unsigned char hw_bp0; 150*69de9b31SRicardo Koller uint32_t bcr; 151*69de9b31SRicardo Koller uint32_t mdscr; 152*69de9b31SRicardo Koller uint64_t addr; 153*69de9b31SRicardo Koller int num_bp = get_num_hw_bp(); 154*69de9b31SRicardo Koller int i; 155*69de9b31SRicardo Koller 156*69de9b31SRicardo Koller install_exception_handler(EL1H_SYNC, ESR_EC_HW_BP_CURRENT, hw_bp_handler); 157*69de9b31SRicardo Koller 158*69de9b31SRicardo Koller reset_debug_state(); 159*69de9b31SRicardo Koller 160*69de9b31SRicardo Koller bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E; 161*69de9b31SRicardo Koller for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4) { 162*69de9b31SRicardo Koller write_dbgbcr(i, bcr); 163*69de9b31SRicardo Koller write_dbgbvr(i, addr); 164*69de9b31SRicardo Koller } 165*69de9b31SRicardo Koller isb(); 166*69de9b31SRicardo Koller 167*69de9b31SRicardo Koller asm volatile("msr daifclr, #8"); 168*69de9b31SRicardo Koller 169*69de9b31SRicardo Koller mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE; 170*69de9b31SRicardo Koller write_sysreg(mdscr, mdscr_el1); 171*69de9b31SRicardo Koller isb(); 172*69de9b31SRicardo Koller 173*69de9b31SRicardo Koller if (migrate) { 174*69de9b31SRicardo Koller do_migrate(); 175*69de9b31SRicardo Koller report(num_bp == get_num_hw_bp(), "brps match after migrate"); 176*69de9b31SRicardo Koller } 177*69de9b31SRicardo Koller 178*69de9b31SRicardo Koller hw_bp_idx = 0; 179*69de9b31SRicardo Koller 180*69de9b31SRicardo Koller /* Trap on up to 16 debug exception unmask instructions. */ 181*69de9b31SRicardo Koller asm volatile("hw_bp0:\n" 182*69de9b31SRicardo Koller "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n" 183*69de9b31SRicardo Koller "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n" 184*69de9b31SRicardo Koller "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n" 185*69de9b31SRicardo Koller "msr daifclr, #8; msr daifclr, #8; msr daifclr, #8; msr daifclr, #8\n"); 186*69de9b31SRicardo Koller 187*69de9b31SRicardo Koller for (i = 0, addr = (uint64_t)&hw_bp0; i < num_bp; i++, addr += 4) 188*69de9b31SRicardo Koller report(hw_bp_addr[i] == addr, "hw breakpoint: %d", i); 189*69de9b31SRicardo Koller } 190*69de9b31SRicardo Koller 191*69de9b31SRicardo Koller int main(int argc, char **argv) 192*69de9b31SRicardo Koller { 193*69de9b31SRicardo Koller if (argc < 2) 194*69de9b31SRicardo Koller report_abort("no test specified"); 195*69de9b31SRicardo Koller 196*69de9b31SRicardo Koller if (strcmp(argv[1], "bp") == 0) { 197*69de9b31SRicardo Koller report_prefix_push(argv[1]); 198*69de9b31SRicardo Koller test_hw_bp(false); 199*69de9b31SRicardo Koller report_prefix_pop(); 200*69de9b31SRicardo Koller } else if (strcmp(argv[1], "bp-migration") == 0) { 201*69de9b31SRicardo Koller report_prefix_push(argv[1]); 202*69de9b31SRicardo Koller test_hw_bp(true); 203*69de9b31SRicardo Koller report_prefix_pop(); 204*69de9b31SRicardo Koller } else { 205*69de9b31SRicardo Koller report_abort("Unknown subtest '%s'", argv[1]); 206*69de9b31SRicardo Koller } 207*69de9b31SRicardo Koller 208*69de9b31SRicardo Koller return report_summary(); 209*69de9b31SRicardo Koller } 210