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

monitor.c (6822B)


      1/*
      2 * QEMU monitor for RISC-V
      3 *
      4 * Copyright (c) 2019 Bin Meng <bmeng.cn@gmail.com>
      5 *
      6 * RISC-V specific monitor commands implementation
      7 *
      8 * This program is free software; you can redistribute it and/or modify it
      9 * under the terms and conditions of the GNU General Public License,
     10 * version 2 or later, as published by the Free Software Foundation.
     11 *
     12 * This program is distributed in the hope it will be useful, but WITHOUT
     13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     15 * more details.
     16 *
     17 * You should have received a copy of the GNU General Public License along with
     18 * this program.  If not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "cpu.h"
     23#include "cpu_bits.h"
     24#include "monitor/monitor.h"
     25#include "monitor/hmp-target.h"
     26
     27#ifdef TARGET_RISCV64
     28#define PTE_HEADER_FIELDS       "vaddr            paddr            "\
     29                                "size             attr\n"
     30#define PTE_HEADER_DELIMITER    "---------------- ---------------- "\
     31                                "---------------- -------\n"
     32#else
     33#define PTE_HEADER_FIELDS       "vaddr    paddr            size     attr\n"
     34#define PTE_HEADER_DELIMITER    "-------- ---------------- -------- -------\n"
     35#endif
     36
     37/* Perform linear address sign extension */
     38static target_ulong addr_canonical(int va_bits, target_ulong addr)
     39{
     40#ifdef TARGET_RISCV64
     41    if (addr & (1UL << (va_bits - 1))) {
     42        addr |= (hwaddr)-(1L << va_bits);
     43    }
     44#endif
     45
     46    return addr;
     47}
     48
     49static void print_pte_header(Monitor *mon)
     50{
     51    monitor_printf(mon, PTE_HEADER_FIELDS);
     52    monitor_printf(mon, PTE_HEADER_DELIMITER);
     53}
     54
     55static void print_pte(Monitor *mon, int va_bits, target_ulong vaddr,
     56                      hwaddr paddr, target_ulong size, int attr)
     57{
     58    /* santity check on vaddr */
     59    if (vaddr >= (1UL << va_bits)) {
     60        return;
     61    }
     62
     63    if (!size) {
     64        return;
     65    }
     66
     67    monitor_printf(mon, TARGET_FMT_lx " " TARGET_FMT_plx " " TARGET_FMT_lx
     68                   " %c%c%c%c%c%c%c\n",
     69                   addr_canonical(va_bits, vaddr),
     70                   paddr, size,
     71                   attr & PTE_R ? 'r' : '-',
     72                   attr & PTE_W ? 'w' : '-',
     73                   attr & PTE_X ? 'x' : '-',
     74                   attr & PTE_U ? 'u' : '-',
     75                   attr & PTE_G ? 'g' : '-',
     76                   attr & PTE_A ? 'a' : '-',
     77                   attr & PTE_D ? 'd' : '-');
     78}
     79
     80static void walk_pte(Monitor *mon, hwaddr base, target_ulong start,
     81                     int level, int ptidxbits, int ptesize, int va_bits,
     82                     target_ulong *vbase, hwaddr *pbase, hwaddr *last_paddr,
     83                     target_ulong *last_size, int *last_attr)
     84{
     85    hwaddr pte_addr;
     86    hwaddr paddr;
     87    target_ulong pgsize;
     88    target_ulong pte;
     89    int ptshift;
     90    int attr;
     91    int idx;
     92
     93    if (level < 0) {
     94        return;
     95    }
     96
     97    ptshift = level * ptidxbits;
     98    pgsize = 1UL << (PGSHIFT + ptshift);
     99
    100    for (idx = 0; idx < (1UL << ptidxbits); idx++) {
    101        pte_addr = base + idx * ptesize;
    102        cpu_physical_memory_read(pte_addr, &pte, ptesize);
    103
    104        paddr = (hwaddr)(pte >> PTE_PPN_SHIFT) << PGSHIFT;
    105        attr = pte & 0xff;
    106
    107        /* PTE has to be valid */
    108        if (attr & PTE_V) {
    109            if (attr & (PTE_R | PTE_W | PTE_X)) {
    110                /*
    111                 * A leaf PTE has been found
    112                 *
    113                 * If current PTE's permission bits differ from the last one,
    114                 * or current PTE's ppn does not make a contiguous physical
    115                 * address block together with the last one, print out the last
    116                 * contiguous mapped block details.
    117                 */
    118                if ((*last_attr != attr) ||
    119                    (*last_paddr + *last_size != paddr)) {
    120                    print_pte(mon, va_bits, *vbase, *pbase,
    121                              *last_paddr + *last_size - *pbase, *last_attr);
    122
    123                    *vbase = start;
    124                    *pbase = paddr;
    125                    *last_attr = attr;
    126                }
    127
    128                *last_paddr = paddr;
    129                *last_size = pgsize;
    130            } else {
    131                /* pointer to the next level of the page table */
    132                walk_pte(mon, paddr, start, level - 1, ptidxbits, ptesize,
    133                         va_bits, vbase, pbase, last_paddr,
    134                         last_size, last_attr);
    135            }
    136        }
    137
    138        start += pgsize;
    139    }
    140
    141}
    142
    143static void mem_info_svxx(Monitor *mon, CPUArchState *env)
    144{
    145    int levels, ptidxbits, ptesize, vm, va_bits;
    146    hwaddr base;
    147    target_ulong vbase;
    148    hwaddr pbase;
    149    hwaddr last_paddr;
    150    target_ulong last_size;
    151    int last_attr;
    152
    153    if (riscv_cpu_is_32bit(env)) {
    154        base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT;
    155        vm = get_field(env->satp, SATP32_MODE);
    156    } else {
    157        base = (hwaddr)get_field(env->satp, SATP64_PPN) << PGSHIFT;
    158        vm = get_field(env->satp, SATP64_MODE);
    159    }
    160
    161    switch (vm) {
    162    case VM_1_10_SV32:
    163        levels = 2;
    164        ptidxbits = 10;
    165        ptesize = 4;
    166        break;
    167    case VM_1_10_SV39:
    168        levels = 3;
    169        ptidxbits = 9;
    170        ptesize = 8;
    171        break;
    172    case VM_1_10_SV48:
    173        levels = 4;
    174        ptidxbits = 9;
    175        ptesize = 8;
    176        break;
    177    case VM_1_10_SV57:
    178        levels = 5;
    179        ptidxbits = 9;
    180        ptesize = 8;
    181        break;
    182    default:
    183        g_assert_not_reached();
    184        break;
    185    }
    186
    187    /* calculate virtual address bits */
    188    va_bits = PGSHIFT + levels * ptidxbits;
    189
    190    /* print header */
    191    print_pte_header(mon);
    192
    193    vbase = -1;
    194    pbase = -1;
    195    last_paddr = -1;
    196    last_size = 0;
    197    last_attr = 0;
    198
    199    /* walk page tables, starting from address 0 */
    200    walk_pte(mon, base, 0, levels - 1, ptidxbits, ptesize, va_bits,
    201             &vbase, &pbase, &last_paddr, &last_size, &last_attr);
    202
    203    /* don't forget the last one */
    204    print_pte(mon, va_bits, vbase, pbase,
    205              last_paddr + last_size - pbase, last_attr);
    206}
    207
    208void hmp_info_mem(Monitor *mon, const QDict *qdict)
    209{
    210    CPUArchState *env;
    211
    212    env = mon_get_cpu_env(mon);
    213    if (!env) {
    214        monitor_printf(mon, "No CPU available\n");
    215        return;
    216    }
    217
    218    if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
    219        monitor_printf(mon, "S-mode MMU unavailable\n");
    220        return;
    221    }
    222
    223    if (riscv_cpu_is_32bit(env)) {
    224        if (!(env->satp & SATP32_MODE)) {
    225            monitor_printf(mon, "No translation or protection\n");
    226            return;
    227        }
    228    } else {
    229        if (!(env->satp & SATP64_MODE)) {
    230            monitor_printf(mon, "No translation or protection\n");
    231            return;
    232        }
    233    }
    234
    235    mem_info_svxx(mon, env);
    236}