10ca52a5fSFrancesco Cagnin /*
20ca52a5fSFrancesco Cagnin * ARM implementation of KVM and HVF hooks, 64 bit specific code
30ca52a5fSFrancesco Cagnin *
40ca52a5fSFrancesco Cagnin * Copyright Mian-M. Hamayun 2013, Virtual Open Systems
50ca52a5fSFrancesco Cagnin * Copyright Alex Bennée 2014, Linaro
60ca52a5fSFrancesco Cagnin *
70ca52a5fSFrancesco Cagnin * This work is licensed under the terms of the GNU GPL, version 2 or later.
80ca52a5fSFrancesco Cagnin * See the COPYING file in the top-level directory.
90ca52a5fSFrancesco Cagnin *
100ca52a5fSFrancesco Cagnin */
110ca52a5fSFrancesco Cagnin
120ca52a5fSFrancesco Cagnin #include "qemu/osdep.h"
130ca52a5fSFrancesco Cagnin #include "cpu.h"
140ca52a5fSFrancesco Cagnin #include "internals.h"
15*5b7d54d4SAlex Bennée #include "gdbstub/enums.h"
160ca52a5fSFrancesco Cagnin
170ca52a5fSFrancesco Cagnin /* Maximum and current break/watch point counts */
180ca52a5fSFrancesco Cagnin int max_hw_bps, max_hw_wps;
190ca52a5fSFrancesco Cagnin GArray *hw_breakpoints, *hw_watchpoints;
200ca52a5fSFrancesco Cagnin
210ca52a5fSFrancesco Cagnin /**
220ca52a5fSFrancesco Cagnin * insert_hw_breakpoint()
230ca52a5fSFrancesco Cagnin * @addr: address of breakpoint
240ca52a5fSFrancesco Cagnin *
250ca52a5fSFrancesco Cagnin * See ARM ARM D2.9.1 for details but here we are only going to create
260ca52a5fSFrancesco Cagnin * simple un-linked breakpoints (i.e. we don't chain breakpoints
270ca52a5fSFrancesco Cagnin * together to match address and context or vmid). The hardware is
280ca52a5fSFrancesco Cagnin * capable of fancier matching but that will require exposing that
290ca52a5fSFrancesco Cagnin * fanciness to GDB's interface
300ca52a5fSFrancesco Cagnin *
310ca52a5fSFrancesco Cagnin * DBGBCR<n>_EL1, Debug Breakpoint Control Registers
320ca52a5fSFrancesco Cagnin *
330ca52a5fSFrancesco Cagnin * 31 24 23 20 19 16 15 14 13 12 9 8 5 4 3 2 1 0
340ca52a5fSFrancesco Cagnin * +------+------+-------+-----+----+------+-----+------+-----+---+
350ca52a5fSFrancesco Cagnin * | RES0 | BT | LBN | SSC | HMC| RES0 | BAS | RES0 | PMC | E |
360ca52a5fSFrancesco Cagnin * +------+------+-------+-----+----+------+-----+------+-----+---+
370ca52a5fSFrancesco Cagnin *
380ca52a5fSFrancesco Cagnin * BT: Breakpoint type (0 = unlinked address match)
390ca52a5fSFrancesco Cagnin * LBN: Linked BP number (0 = unused)
400ca52a5fSFrancesco Cagnin * SSC/HMC/PMC: Security, Higher and Priv access control (Table D-12)
410ca52a5fSFrancesco Cagnin * BAS: Byte Address Select (RES1 for AArch64)
420ca52a5fSFrancesco Cagnin * E: Enable bit
430ca52a5fSFrancesco Cagnin *
440ca52a5fSFrancesco Cagnin * DBGBVR<n>_EL1, Debug Breakpoint Value Registers
450ca52a5fSFrancesco Cagnin *
460ca52a5fSFrancesco Cagnin * 63 53 52 49 48 2 1 0
470ca52a5fSFrancesco Cagnin * +------+-----------+----------+-----+
480ca52a5fSFrancesco Cagnin * | RESS | VA[52:49] | VA[48:2] | 0 0 |
490ca52a5fSFrancesco Cagnin * +------+-----------+----------+-----+
500ca52a5fSFrancesco Cagnin *
510ca52a5fSFrancesco Cagnin * Depending on the addressing mode bits the top bits of the register
520ca52a5fSFrancesco Cagnin * are a sign extension of the highest applicable VA bit. Some
530ca52a5fSFrancesco Cagnin * versions of GDB don't do it correctly so we ensure they are correct
540ca52a5fSFrancesco Cagnin * here so future PC comparisons will work properly.
550ca52a5fSFrancesco Cagnin */
560ca52a5fSFrancesco Cagnin
insert_hw_breakpoint(target_ulong addr)570ca52a5fSFrancesco Cagnin int insert_hw_breakpoint(target_ulong addr)
580ca52a5fSFrancesco Cagnin {
590ca52a5fSFrancesco Cagnin HWBreakpoint brk = {
600ca52a5fSFrancesco Cagnin .bcr = 0x1, /* BCR E=1, enable */
610ca52a5fSFrancesco Cagnin .bvr = sextract64(addr, 0, 53)
620ca52a5fSFrancesco Cagnin };
630ca52a5fSFrancesco Cagnin
640ca52a5fSFrancesco Cagnin if (cur_hw_bps >= max_hw_bps) {
650ca52a5fSFrancesco Cagnin return -ENOBUFS;
660ca52a5fSFrancesco Cagnin }
670ca52a5fSFrancesco Cagnin
680ca52a5fSFrancesco Cagnin brk.bcr = deposit32(brk.bcr, 1, 2, 0x3); /* PMC = 11 */
690ca52a5fSFrancesco Cagnin brk.bcr = deposit32(brk.bcr, 5, 4, 0xf); /* BAS = RES1 */
700ca52a5fSFrancesco Cagnin
710ca52a5fSFrancesco Cagnin g_array_append_val(hw_breakpoints, brk);
720ca52a5fSFrancesco Cagnin
730ca52a5fSFrancesco Cagnin return 0;
740ca52a5fSFrancesco Cagnin }
750ca52a5fSFrancesco Cagnin
760ca52a5fSFrancesco Cagnin /**
770ca52a5fSFrancesco Cagnin * delete_hw_breakpoint()
780ca52a5fSFrancesco Cagnin * @pc: address of breakpoint
790ca52a5fSFrancesco Cagnin *
800ca52a5fSFrancesco Cagnin * Delete a breakpoint and shuffle any above down
810ca52a5fSFrancesco Cagnin */
820ca52a5fSFrancesco Cagnin
delete_hw_breakpoint(target_ulong pc)830ca52a5fSFrancesco Cagnin int delete_hw_breakpoint(target_ulong pc)
840ca52a5fSFrancesco Cagnin {
850ca52a5fSFrancesco Cagnin int i;
860ca52a5fSFrancesco Cagnin for (i = 0; i < hw_breakpoints->len; i++) {
870ca52a5fSFrancesco Cagnin HWBreakpoint *brk = get_hw_bp(i);
880ca52a5fSFrancesco Cagnin if (brk->bvr == pc) {
890ca52a5fSFrancesco Cagnin g_array_remove_index(hw_breakpoints, i);
900ca52a5fSFrancesco Cagnin return 0;
910ca52a5fSFrancesco Cagnin }
920ca52a5fSFrancesco Cagnin }
930ca52a5fSFrancesco Cagnin return -ENOENT;
940ca52a5fSFrancesco Cagnin }
950ca52a5fSFrancesco Cagnin
960ca52a5fSFrancesco Cagnin /**
970ca52a5fSFrancesco Cagnin * insert_hw_watchpoint()
980ca52a5fSFrancesco Cagnin * @addr: address of watch point
990ca52a5fSFrancesco Cagnin * @len: size of area
1000ca52a5fSFrancesco Cagnin * @type: type of watch point
1010ca52a5fSFrancesco Cagnin *
1020ca52a5fSFrancesco Cagnin * See ARM ARM D2.10. As with the breakpoints we can do some advanced
1030ca52a5fSFrancesco Cagnin * stuff if we want to. The watch points can be linked with the break
1040ca52a5fSFrancesco Cagnin * points above to make them context aware. However for simplicity
1050ca52a5fSFrancesco Cagnin * currently we only deal with simple read/write watch points.
1060ca52a5fSFrancesco Cagnin *
1070ca52a5fSFrancesco Cagnin * D7.3.11 DBGWCR<n>_EL1, Debug Watchpoint Control Registers
1080ca52a5fSFrancesco Cagnin *
1090ca52a5fSFrancesco Cagnin * 31 29 28 24 23 21 20 19 16 15 14 13 12 5 4 3 2 1 0
1100ca52a5fSFrancesco Cagnin * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+
1110ca52a5fSFrancesco Cagnin * | RES0 | MASK | RES0 | WT | LBN | SSC | HMC | BAS | LSC | PAC | E |
1120ca52a5fSFrancesco Cagnin * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+
1130ca52a5fSFrancesco Cagnin *
1140ca52a5fSFrancesco Cagnin * MASK: num bits addr mask (0=none,01/10=res,11=3 bits (8 bytes))
1150ca52a5fSFrancesco Cagnin * WT: 0 - unlinked, 1 - linked (not currently used)
1160ca52a5fSFrancesco Cagnin * LBN: Linked BP number (not currently used)
1170ca52a5fSFrancesco Cagnin * SSC/HMC/PAC: Security, Higher and Priv access control (Table D2-11)
1180ca52a5fSFrancesco Cagnin * BAS: Byte Address Select
1190ca52a5fSFrancesco Cagnin * LSC: Load/Store control (01: load, 10: store, 11: both)
1200ca52a5fSFrancesco Cagnin * E: Enable
1210ca52a5fSFrancesco Cagnin *
1220ca52a5fSFrancesco Cagnin * The bottom 2 bits of the value register are masked. Therefore to
1230ca52a5fSFrancesco Cagnin * break on any sizes smaller than an unaligned word you need to set
1240ca52a5fSFrancesco Cagnin * MASK=0, BAS=bit per byte in question. For larger regions (^2) you
1250ca52a5fSFrancesco Cagnin * need to ensure you mask the address as required and set BAS=0xff
1260ca52a5fSFrancesco Cagnin */
1270ca52a5fSFrancesco Cagnin
insert_hw_watchpoint(target_ulong addr,target_ulong len,int type)1280ca52a5fSFrancesco Cagnin int insert_hw_watchpoint(target_ulong addr, target_ulong len, int type)
1290ca52a5fSFrancesco Cagnin {
1300ca52a5fSFrancesco Cagnin HWWatchpoint wp = {
1310ca52a5fSFrancesco Cagnin .wcr = R_DBGWCR_E_MASK, /* E=1, enable */
1320ca52a5fSFrancesco Cagnin .wvr = addr & (~0x7ULL),
1330ca52a5fSFrancesco Cagnin .details = { .vaddr = addr, .len = len }
1340ca52a5fSFrancesco Cagnin };
1350ca52a5fSFrancesco Cagnin
1360ca52a5fSFrancesco Cagnin if (cur_hw_wps >= max_hw_wps) {
1370ca52a5fSFrancesco Cagnin return -ENOBUFS;
1380ca52a5fSFrancesco Cagnin }
1390ca52a5fSFrancesco Cagnin
1400ca52a5fSFrancesco Cagnin /*
1410ca52a5fSFrancesco Cagnin * HMC=0 SSC=0 PAC=3 will hit EL0 or EL1, any security state,
1420ca52a5fSFrancesco Cagnin * valid whether EL3 is implemented or not
1430ca52a5fSFrancesco Cagnin */
1440ca52a5fSFrancesco Cagnin wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, PAC, 3);
1450ca52a5fSFrancesco Cagnin
1460ca52a5fSFrancesco Cagnin switch (type) {
1470ca52a5fSFrancesco Cagnin case GDB_WATCHPOINT_READ:
1480ca52a5fSFrancesco Cagnin wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 1);
1490ca52a5fSFrancesco Cagnin wp.details.flags = BP_MEM_READ;
1500ca52a5fSFrancesco Cagnin break;
1510ca52a5fSFrancesco Cagnin case GDB_WATCHPOINT_WRITE:
1520ca52a5fSFrancesco Cagnin wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 2);
1530ca52a5fSFrancesco Cagnin wp.details.flags = BP_MEM_WRITE;
1540ca52a5fSFrancesco Cagnin break;
1550ca52a5fSFrancesco Cagnin case GDB_WATCHPOINT_ACCESS:
1560ca52a5fSFrancesco Cagnin wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, LSC, 3);
1570ca52a5fSFrancesco Cagnin wp.details.flags = BP_MEM_ACCESS;
1580ca52a5fSFrancesco Cagnin break;
1590ca52a5fSFrancesco Cagnin default:
1600ca52a5fSFrancesco Cagnin g_assert_not_reached();
1610ca52a5fSFrancesco Cagnin }
1620ca52a5fSFrancesco Cagnin if (len <= 8) {
1630ca52a5fSFrancesco Cagnin /* we align the address and set the bits in BAS */
1640ca52a5fSFrancesco Cagnin int off = addr & 0x7;
1650ca52a5fSFrancesco Cagnin int bas = (1 << len) - 1;
1660ca52a5fSFrancesco Cagnin
1670ca52a5fSFrancesco Cagnin wp.wcr = deposit32(wp.wcr, 5 + off, 8 - off, bas);
1680ca52a5fSFrancesco Cagnin } else {
1690ca52a5fSFrancesco Cagnin /* For ranges above 8 bytes we need to be a power of 2 */
1700ca52a5fSFrancesco Cagnin if (is_power_of_2(len)) {
1710ca52a5fSFrancesco Cagnin int bits = ctz64(len);
1720ca52a5fSFrancesco Cagnin
1730ca52a5fSFrancesco Cagnin wp.wvr &= ~((1 << bits) - 1);
1740ca52a5fSFrancesco Cagnin wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, MASK, bits);
1750ca52a5fSFrancesco Cagnin wp.wcr = FIELD_DP64(wp.wcr, DBGWCR, BAS, 0xff);
1760ca52a5fSFrancesco Cagnin } else {
1770ca52a5fSFrancesco Cagnin return -ENOBUFS;
1780ca52a5fSFrancesco Cagnin }
1790ca52a5fSFrancesco Cagnin }
1800ca52a5fSFrancesco Cagnin
1810ca52a5fSFrancesco Cagnin g_array_append_val(hw_watchpoints, wp);
1820ca52a5fSFrancesco Cagnin return 0;
1830ca52a5fSFrancesco Cagnin }
1840ca52a5fSFrancesco Cagnin
check_watchpoint_in_range(int i,target_ulong addr)1850ca52a5fSFrancesco Cagnin bool check_watchpoint_in_range(int i, target_ulong addr)
1860ca52a5fSFrancesco Cagnin {
1870ca52a5fSFrancesco Cagnin HWWatchpoint *wp = get_hw_wp(i);
1880ca52a5fSFrancesco Cagnin uint64_t addr_top, addr_bottom = wp->wvr;
1890ca52a5fSFrancesco Cagnin int bas = extract32(wp->wcr, 5, 8);
1900ca52a5fSFrancesco Cagnin int mask = extract32(wp->wcr, 24, 4);
1910ca52a5fSFrancesco Cagnin
1920ca52a5fSFrancesco Cagnin if (mask) {
1930ca52a5fSFrancesco Cagnin addr_top = addr_bottom + (1 << mask);
1940ca52a5fSFrancesco Cagnin } else {
1950ca52a5fSFrancesco Cagnin /*
1960ca52a5fSFrancesco Cagnin * BAS must be contiguous but can offset against the base
1970ca52a5fSFrancesco Cagnin * address in DBGWVR
1980ca52a5fSFrancesco Cagnin */
1990ca52a5fSFrancesco Cagnin addr_bottom = addr_bottom + ctz32(bas);
2000ca52a5fSFrancesco Cagnin addr_top = addr_bottom + clo32(bas);
2010ca52a5fSFrancesco Cagnin }
2020ca52a5fSFrancesco Cagnin
2030ca52a5fSFrancesco Cagnin if (addr >= addr_bottom && addr <= addr_top) {
2040ca52a5fSFrancesco Cagnin return true;
2050ca52a5fSFrancesco Cagnin }
2060ca52a5fSFrancesco Cagnin
2070ca52a5fSFrancesco Cagnin return false;
2080ca52a5fSFrancesco Cagnin }
2090ca52a5fSFrancesco Cagnin
2100ca52a5fSFrancesco Cagnin /**
2110ca52a5fSFrancesco Cagnin * delete_hw_watchpoint()
2120ca52a5fSFrancesco Cagnin * @addr: address of breakpoint
2130ca52a5fSFrancesco Cagnin *
2140ca52a5fSFrancesco Cagnin * Delete a breakpoint and shuffle any above down
2150ca52a5fSFrancesco Cagnin */
2160ca52a5fSFrancesco Cagnin
delete_hw_watchpoint(target_ulong addr,target_ulong len,int type)2170ca52a5fSFrancesco Cagnin int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type)
2180ca52a5fSFrancesco Cagnin {
2190ca52a5fSFrancesco Cagnin int i;
2200ca52a5fSFrancesco Cagnin for (i = 0; i < cur_hw_wps; i++) {
2210ca52a5fSFrancesco Cagnin if (check_watchpoint_in_range(i, addr)) {
2220ca52a5fSFrancesco Cagnin g_array_remove_index(hw_watchpoints, i);
2230ca52a5fSFrancesco Cagnin return 0;
2240ca52a5fSFrancesco Cagnin }
2250ca52a5fSFrancesco Cagnin }
2260ca52a5fSFrancesco Cagnin return -ENOENT;
2270ca52a5fSFrancesco Cagnin }
2280ca52a5fSFrancesco Cagnin
find_hw_breakpoint(CPUState * cpu,target_ulong pc)2290ca52a5fSFrancesco Cagnin bool find_hw_breakpoint(CPUState *cpu, target_ulong pc)
2300ca52a5fSFrancesco Cagnin {
2310ca52a5fSFrancesco Cagnin int i;
2320ca52a5fSFrancesco Cagnin
2330ca52a5fSFrancesco Cagnin for (i = 0; i < cur_hw_bps; i++) {
2340ca52a5fSFrancesco Cagnin HWBreakpoint *bp = get_hw_bp(i);
2350ca52a5fSFrancesco Cagnin if (bp->bvr == pc) {
2360ca52a5fSFrancesco Cagnin return true;
2370ca52a5fSFrancesco Cagnin }
2380ca52a5fSFrancesco Cagnin }
2390ca52a5fSFrancesco Cagnin return false;
2400ca52a5fSFrancesco Cagnin }
2410ca52a5fSFrancesco Cagnin
find_hw_watchpoint(CPUState * cpu,target_ulong addr)2420ca52a5fSFrancesco Cagnin CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr)
2430ca52a5fSFrancesco Cagnin {
2440ca52a5fSFrancesco Cagnin int i;
2450ca52a5fSFrancesco Cagnin
2460ca52a5fSFrancesco Cagnin for (i = 0; i < cur_hw_wps; i++) {
2470ca52a5fSFrancesco Cagnin if (check_watchpoint_in_range(i, addr)) {
2480ca52a5fSFrancesco Cagnin return &get_hw_wp(i)->details;
2490ca52a5fSFrancesco Cagnin }
2500ca52a5fSFrancesco Cagnin }
2510ca52a5fSFrancesco Cagnin return NULL;
2520ca52a5fSFrancesco Cagnin }
253