cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

debug_helper.c (9533B)


      1/*
      2 * ARM debug helpers.
      3 *
      4 * This code is licensed under the GNU GPL v2 or later.
      5 *
      6 * SPDX-License-Identifier: GPL-2.0-or-later
      7 */
      8#include "qemu/osdep.h"
      9#include "cpu.h"
     10#include "internals.h"
     11#include "exec/exec-all.h"
     12#include "exec/helper-proto.h"
     13
     14/* Return true if the linked breakpoint entry lbn passes its checks */
     15static bool linked_bp_matches(ARMCPU *cpu, int lbn)
     16{
     17    CPUARMState *env = &cpu->env;
     18    uint64_t bcr = env->cp15.dbgbcr[lbn];
     19    int brps = arm_num_brps(cpu);
     20    int ctx_cmps = arm_num_ctx_cmps(cpu);
     21    int bt;
     22    uint32_t contextidr;
     23    uint64_t hcr_el2;
     24
     25    /*
     26     * Links to unimplemented or non-context aware breakpoints are
     27     * CONSTRAINED UNPREDICTABLE: either behave as if disabled, or
     28     * as if linked to an UNKNOWN context-aware breakpoint (in which
     29     * case DBGWCR<n>_EL1.LBN must indicate that breakpoint).
     30     * We choose the former.
     31     */
     32    if (lbn >= brps || lbn < (brps - ctx_cmps)) {
     33        return false;
     34    }
     35
     36    bcr = env->cp15.dbgbcr[lbn];
     37
     38    if (extract64(bcr, 0, 1) == 0) {
     39        /* Linked breakpoint disabled : generate no events */
     40        return false;
     41    }
     42
     43    bt = extract64(bcr, 20, 4);
     44    hcr_el2 = arm_hcr_el2_eff(env);
     45
     46    switch (bt) {
     47    case 3: /* linked context ID match */
     48        switch (arm_current_el(env)) {
     49        default:
     50            /* Context matches never fire in AArch64 EL3 */
     51            return false;
     52        case 2:
     53            if (!(hcr_el2 & HCR_E2H)) {
     54                /* Context matches never fire in EL2 without E2H enabled. */
     55                return false;
     56            }
     57            contextidr = env->cp15.contextidr_el[2];
     58            break;
     59        case 1:
     60            contextidr = env->cp15.contextidr_el[1];
     61            break;
     62        case 0:
     63            if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
     64                contextidr = env->cp15.contextidr_el[2];
     65            } else {
     66                contextidr = env->cp15.contextidr_el[1];
     67            }
     68            break;
     69        }
     70        break;
     71
     72    case 7:  /* linked contextidr_el1 match */
     73        contextidr = env->cp15.contextidr_el[1];
     74        break;
     75    case 13: /* linked contextidr_el2 match */
     76        contextidr = env->cp15.contextidr_el[2];
     77        break;
     78
     79    case 9: /* linked VMID match (reserved if no EL2) */
     80    case 11: /* linked context ID and VMID match (reserved if no EL2) */
     81    case 15: /* linked full context ID match */
     82    default:
     83        /*
     84         * Links to Unlinked context breakpoints must generate no
     85         * events; we choose to do the same for reserved values too.
     86         */
     87        return false;
     88    }
     89
     90    /*
     91     * We match the whole register even if this is AArch32 using the
     92     * short descriptor format (in which case it holds both PROCID and ASID),
     93     * since we don't implement the optional v7 context ID masking.
     94     */
     95    return contextidr == (uint32_t)env->cp15.dbgbvr[lbn];
     96}
     97
     98static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
     99{
    100    CPUARMState *env = &cpu->env;
    101    uint64_t cr;
    102    int pac, hmc, ssc, wt, lbn;
    103    /*
    104     * Note that for watchpoints the check is against the CPU security
    105     * state, not the S/NS attribute on the offending data access.
    106     */
    107    bool is_secure = arm_is_secure(env);
    108    int access_el = arm_current_el(env);
    109
    110    if (is_wp) {
    111        CPUWatchpoint *wp = env->cpu_watchpoint[n];
    112
    113        if (!wp || !(wp->flags & BP_WATCHPOINT_HIT)) {
    114            return false;
    115        }
    116        cr = env->cp15.dbgwcr[n];
    117        if (wp->hitattrs.user) {
    118            /*
    119             * The LDRT/STRT/LDT/STT "unprivileged access" instructions should
    120             * match watchpoints as if they were accesses done at EL0, even if
    121             * the CPU is at EL1 or higher.
    122             */
    123            access_el = 0;
    124        }
    125    } else {
    126        uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
    127
    128        if (!env->cpu_breakpoint[n] || env->cpu_breakpoint[n]->pc != pc) {
    129            return false;
    130        }
    131        cr = env->cp15.dbgbcr[n];
    132    }
    133    /*
    134     * The WATCHPOINT_HIT flag guarantees us that the watchpoint is
    135     * enabled and that the address and access type match; for breakpoints
    136     * we know the address matched; check the remaining fields, including
    137     * linked breakpoints. We rely on WCR and BCR having the same layout
    138     * for the LBN, SSC, HMC, PAC/PMC and is-linked fields.
    139     * Note that some combinations of {PAC, HMC, SSC} are reserved and
    140     * must act either like some valid combination or as if the watchpoint
    141     * were disabled. We choose the former, and use this together with
    142     * the fact that EL3 must always be Secure and EL2 must always be
    143     * Non-Secure to simplify the code slightly compared to the full
    144     * table in the ARM ARM.
    145     */
    146    pac = extract64(cr, 1, 2);
    147    hmc = extract64(cr, 13, 1);
    148    ssc = extract64(cr, 14, 2);
    149
    150    switch (ssc) {
    151    case 0:
    152        break;
    153    case 1:
    154    case 3:
    155        if (is_secure) {
    156            return false;
    157        }
    158        break;
    159    case 2:
    160        if (!is_secure) {
    161            return false;
    162        }
    163        break;
    164    }
    165
    166    switch (access_el) {
    167    case 3:
    168    case 2:
    169        if (!hmc) {
    170            return false;
    171        }
    172        break;
    173    case 1:
    174        if (extract32(pac, 0, 1) == 0) {
    175            return false;
    176        }
    177        break;
    178    case 0:
    179        if (extract32(pac, 1, 1) == 0) {
    180            return false;
    181        }
    182        break;
    183    default:
    184        g_assert_not_reached();
    185    }
    186
    187    wt = extract64(cr, 20, 1);
    188    lbn = extract64(cr, 16, 4);
    189
    190    if (wt && !linked_bp_matches(cpu, lbn)) {
    191        return false;
    192    }
    193
    194    return true;
    195}
    196
    197static bool check_watchpoints(ARMCPU *cpu)
    198{
    199    CPUARMState *env = &cpu->env;
    200    int n;
    201
    202    /*
    203     * If watchpoints are disabled globally or we can't take debug
    204     * exceptions here then watchpoint firings are ignored.
    205     */
    206    if (extract32(env->cp15.mdscr_el1, 15, 1) == 0
    207        || !arm_generate_debug_exceptions(env)) {
    208        return false;
    209    }
    210
    211    for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) {
    212        if (bp_wp_matches(cpu, n, true)) {
    213            return true;
    214        }
    215    }
    216    return false;
    217}
    218
    219bool arm_debug_check_breakpoint(CPUState *cs)
    220{
    221    ARMCPU *cpu = ARM_CPU(cs);
    222    CPUARMState *env = &cpu->env;
    223    int n;
    224
    225    /*
    226     * If breakpoints are disabled globally or we can't take debug
    227     * exceptions here then breakpoint firings are ignored.
    228     */
    229    if (extract32(env->cp15.mdscr_el1, 15, 1) == 0
    230        || !arm_generate_debug_exceptions(env)) {
    231        return false;
    232    }
    233
    234    for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) {
    235        if (bp_wp_matches(cpu, n, false)) {
    236            return true;
    237        }
    238    }
    239    return false;
    240}
    241
    242bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
    243{
    244    /*
    245     * Called by core code when a CPU watchpoint fires; need to check if this
    246     * is also an architectural watchpoint match.
    247     */
    248    ARMCPU *cpu = ARM_CPU(cs);
    249
    250    return check_watchpoints(cpu);
    251}
    252
    253void arm_debug_excp_handler(CPUState *cs)
    254{
    255    /*
    256     * Called by core code when a watchpoint or breakpoint fires;
    257     * need to check which one and raise the appropriate exception.
    258     */
    259    ARMCPU *cpu = ARM_CPU(cs);
    260    CPUARMState *env = &cpu->env;
    261    CPUWatchpoint *wp_hit = cs->watchpoint_hit;
    262
    263    if (wp_hit) {
    264        if (wp_hit->flags & BP_CPU) {
    265            bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
    266            bool same_el = arm_debug_target_el(env) == arm_current_el(env);
    267
    268            cs->watchpoint_hit = NULL;
    269
    270            env->exception.fsr = arm_debug_exception_fsr(env);
    271            env->exception.vaddress = wp_hit->hitaddr;
    272            raise_exception(env, EXCP_DATA_ABORT,
    273                    syn_watchpoint(same_el, 0, wnr),
    274                    arm_debug_target_el(env));
    275        }
    276    } else {
    277        uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
    278        bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
    279
    280        /*
    281         * (1) GDB breakpoints should be handled first.
    282         * (2) Do not raise a CPU exception if no CPU breakpoint has fired,
    283         * since singlestep is also done by generating a debug internal
    284         * exception.
    285         */
    286        if (cpu_breakpoint_test(cs, pc, BP_GDB)
    287            || !cpu_breakpoint_test(cs, pc, BP_CPU)) {
    288            return;
    289        }
    290
    291        env->exception.fsr = arm_debug_exception_fsr(env);
    292        /*
    293         * FAR is UNKNOWN: clear vaddress to avoid potentially exposing
    294         * values to the guest that it shouldn't be able to see at its
    295         * exception/security level.
    296         */
    297        env->exception.vaddress = 0;
    298        raise_exception(env, EXCP_PREFETCH_ABORT,
    299                        syn_breakpoint(same_el),
    300                        arm_debug_target_el(env));
    301    }
    302}
    303
    304#if !defined(CONFIG_USER_ONLY)
    305
    306vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
    307{
    308    ARMCPU *cpu = ARM_CPU(cs);
    309    CPUARMState *env = &cpu->env;
    310
    311    /*
    312     * In BE32 system mode, target memory is stored byteswapped (on a
    313     * little-endian host system), and by the time we reach here (via an
    314     * opcode helper) the addresses of subword accesses have been adjusted
    315     * to account for that, which means that watchpoints will not match.
    316     * Undo the adjustment here.
    317     */
    318    if (arm_sctlr_b(env)) {
    319        if (len == 1) {
    320            addr ^= 3;
    321        } else if (len == 2) {
    322            addr ^= 2;
    323        }
    324    }
    325
    326    return addr;
    327}
    328
    329#endif