1 /* 2 * ARM implementation of KVM and HVF hooks, 64 bit specific code 3 * 4 * Copyright Mian-M. Hamayun 2013, Virtual Open Systems 5 * Copyright Alex Bennée 2014, Linaro 6 * 7 * This work is licensed under the terms of the GNU GPL, version 2 or later. 8 * See the COPYING file in the top-level directory. 9 * 10 */ 11 12 #include "qemu/osdep.h" 13 #include "cpu.h" 14 #include "internals.h" 15 #include "gdbstub/enums.h" 16 17 /* Maximum and current break/watch point counts */ 18 int max_hw_bps, max_hw_wps; 19 GArray *hw_breakpoints, *hw_watchpoints; 20 21 /** 22 * insert_hw_breakpoint() 23 * @addr: address of breakpoint 24 * 25 * See ARM ARM D2.9.1 for details but here we are only going to create 26 * simple un-linked breakpoints (i.e. we don't chain breakpoints 27 * together to match address and context or vmid). The hardware is 28 * capable of fancier matching but that will require exposing that 29 * fanciness to GDB's interface 30 * 31 * DBGBCR<n>_EL1, Debug Breakpoint Control Registers 32 * 33 * 31 24 23 20 19 16 15 14 13 12 9 8 5 4 3 2 1 0 34 * +------+------+-------+-----+----+------+-----+------+-----+---+ 35 * | RES0 | BT | LBN | SSC | HMC| RES0 | BAS | RES0 | PMC | E | 36 * +------+------+-------+-----+----+------+-----+------+-----+---+ 37 * 38 * BT: Breakpoint type (0 = unlinked address match) 39 * LBN: Linked BP number (0 = unused) 40 * SSC/HMC/PMC: Security, Higher and Priv access control (Table D-12) 41 * BAS: Byte Address Select (RES1 for AArch64) 42 * E: Enable bit 43 * 44 * DBGBVR<n>_EL1, Debug Breakpoint Value Registers 45 * 46 * 63 53 52 49 48 2 1 0 47 * +------+-----------+----------+-----+ 48 * | RESS | VA[52:49] | VA[48:2] | 0 0 | 49 * +------+-----------+----------+-----+ 50 * 51 * Depending on the addressing mode bits the top bits of the register 52 * are a sign extension of the highest applicable VA bit. Some 53 * versions of GDB don't do it correctly so we ensure they are correct 54 * here so future PC comparisons will work properly. 55 */ 56 57 int insert_hw_breakpoint(target_ulong addr) 58 { 59 HWBreakpoint brk = { 60 .bcr = 0x1, /* BCR E=1, enable */ 61 .bvr = sextract64(addr, 0, 53) 62 }; 63 64 if (cur_hw_bps >= max_hw_bps) { 65 return -ENOBUFS; 66 } 67 68 brk.bcr = deposit32(brk.bcr, 1, 2, 0x3); /* PMC = 11 */ 69 brk.bcr = deposit32(brk.bcr, 5, 4, 0xf); /* BAS = RES1 */ 70 71 g_array_append_val(hw_breakpoints, brk); 72 73 return 0; 74 } 75 76 /** 77 * delete_hw_breakpoint() 78 * @pc: address of breakpoint 79 * 80 * Delete a breakpoint and shuffle any above down 81 */ 82 83 int delete_hw_breakpoint(target_ulong pc) 84 { 85 int i; 86 for (i = 0; i < hw_breakpoints->len; i++) { 87 HWBreakpoint *brk = get_hw_bp(i); 88 if (brk->bvr == pc) { 89 g_array_remove_index(hw_breakpoints, i); 90 return 0; 91 } 92 } 93 return -ENOENT; 94 } 95 96 /** 97 * insert_hw_watchpoint() 98 * @addr: address of watch point 99 * @len: size of area 100 * @type: type of watch point 101 * 102 * See ARM ARM D2.10. As with the breakpoints we can do some advanced 103 * stuff if we want to. The watch points can be linked with the break 104 * points above to make them context aware. However for simplicity 105 * currently we only deal with simple read/write watch points. 106 * 107 * D7.3.11 DBGWCR<n>_EL1, Debug Watchpoint Control Registers 108 * 109 * 31 29 28 24 23 21 20 19 16 15 14 13 12 5 4 3 2 1 0 110 * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+ 111 * | RES0 | MASK | RES0 | WT | LBN | SSC | HMC | BAS | LSC | PAC | E | 112 * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+ 113 * 114 * MASK: num bits addr mask (0=none,01/10=res,11=3 bits (8 bytes)) 115 * WT: 0 - unlinked, 1 - linked (not currently used) 116 * LBN: Linked BP number (not currently used) 117 * SSC/HMC/PAC: Security, Higher and Priv access control (Table D2-11) 118 * BAS: Byte Address Select 119 * LSC: Load/Store control (01: load, 10: store, 11: both) 120 * E: Enable 121 * 122 * The bottom 2 bits of the value register are masked. Therefore to 123 * break on any sizes smaller than an unaligned word you need to set 124 * MASK=0, BAS=bit per byte in question. For larger regions (^2) you 125 * need to ensure you mask the address as required and set BAS=0xff 126 */ 127 128 int insert_hw_watchpoint(target_ulong addr, target_ulong len, int type) 129 { 130 HWWatchpoint wp = { 131 .wcr = R_DBGWCR_E_MASK, /* E=1, enable */ 132 .wvr = addr & (~0x7ULL), 133 .details = { .vaddr = addr, .len = len } 134 }; 135 136 if (cur_hw_wps >= max_hw_wps) { 137 return -ENOBUFS; 138 } 139 140 /* 141 * HMC=0 SSC=0 PAC=3 will hit EL0 or EL1, any security state, 142 * valid whether EL3 is implemented or not 143 */ 144 wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, PAC, 3); 145 146 switch (type) { 147 case GDB_WATCHPOINT_READ: 148 wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 1); 149 wp.details.flags = BP_MEM_READ; 150 break; 151 case GDB_WATCHPOINT_WRITE: 152 wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 2); 153 wp.details.flags = BP_MEM_WRITE; 154 break; 155 case GDB_WATCHPOINT_ACCESS: 156 wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 3); 157 wp.details.flags = BP_MEM_ACCESS; 158 break; 159 default: 160 g_assert_not_reached(); 161 } 162 if (len <= 8) { 163 /* we align the address and set the bits in BAS */ 164 int off = addr & 0x7; 165 int bas = (1 << len) - 1; 166 167 wp.wcr = deposit32(wp.wcr, 5 + off, 8 - off, bas); 168 } else { 169 /* For ranges above 8 bytes we need to be a power of 2 */ 170 if (is_power_of_2(len)) { 171 int bits = ctz64(len); 172 173 wp.wvr &= ~((1 << bits) - 1); 174 wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, MASK, bits); 175 wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, BAS, 0xff); 176 } else { 177 return -ENOBUFS; 178 } 179 } 180 181 g_array_append_val(hw_watchpoints, wp); 182 return 0; 183 } 184 185 bool check_watchpoint_in_range(int i, target_ulong addr) 186 { 187 HWWatchpoint *wp = get_hw_wp(i); 188 uint64_t addr_top, addr_bottom = wp->wvr; 189 int bas = extract32(wp->wcr, 5, 8); 190 int mask = extract32(wp->wcr, 24, 4); 191 192 if (mask) { 193 addr_top = addr_bottom + (1 << mask); 194 } else { 195 /* 196 * BAS must be contiguous but can offset against the base 197 * address in DBGWVR 198 */ 199 addr_bottom = addr_bottom + ctz32(bas); 200 addr_top = addr_bottom + clo32(bas); 201 } 202 203 if (addr >= addr_bottom && addr <= addr_top) { 204 return true; 205 } 206 207 return false; 208 } 209 210 /** 211 * delete_hw_watchpoint() 212 * @addr: address of breakpoint 213 * 214 * Delete a breakpoint and shuffle any above down 215 */ 216 217 int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type) 218 { 219 int i; 220 for (i = 0; i < cur_hw_wps; i++) { 221 if (check_watchpoint_in_range(i, addr)) { 222 g_array_remove_index(hw_watchpoints, i); 223 return 0; 224 } 225 } 226 return -ENOENT; 227 } 228 229 bool find_hw_breakpoint(CPUState *cpu, target_ulong pc) 230 { 231 int i; 232 233 for (i = 0; i < cur_hw_bps; i++) { 234 HWBreakpoint *bp = get_hw_bp(i); 235 if (bp->bvr == pc) { 236 return true; 237 } 238 } 239 return false; 240 } 241 242 CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr) 243 { 244 int i; 245 246 for (i = 0; i < cur_hw_wps; i++) { 247 if (check_watchpoint_in_range(i, addr)) { 248 return &get_hw_wp(i)->details; 249 } 250 } 251 return NULL; 252 } 253