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

arch_dump.c (5863B)


      1/* Support for writing ELF notes for RISC-V architectures
      2 *
      3 * Copyright (C) 2021 Huawei Technologies Co., Ltd
      4 *
      5 * This program is free software; you can redistribute it and/or modify it
      6 * under the terms and conditions of the GNU General Public License,
      7 * version 2 or later, as published by the Free Software Foundation.
      8 *
      9 * This program is distributed in the hope it will be useful, but WITHOUT
     10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     12 * more details.
     13 *
     14 * You should have received a copy of the GNU General Public License along with
     15 * this program.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#include "qemu/osdep.h"
     19#include "cpu.h"
     20#include "elf.h"
     21#include "sysemu/dump.h"
     22
     23/* struct user_regs_struct from arch/riscv/include/uapi/asm/ptrace.h */
     24struct riscv64_user_regs {
     25    uint64_t pc;
     26    uint64_t regs[31];
     27} QEMU_PACKED;
     28
     29QEMU_BUILD_BUG_ON(sizeof(struct riscv64_user_regs) != 256);
     30
     31/* struct elf_prstatus from include/linux/elfcore.h */
     32struct riscv64_elf_prstatus {
     33    char pad1[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */
     34    uint32_t pr_pid;
     35    char pad2[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) -
     36                            offsetof(struct elf_prstatus, pr_ppid) */
     37    struct riscv64_user_regs pr_reg;
     38    char pad3[8];
     39} QEMU_PACKED;
     40
     41QEMU_BUILD_BUG_ON(sizeof(struct riscv64_elf_prstatus) != 376);
     42
     43struct riscv64_note {
     44    Elf64_Nhdr hdr;
     45    char name[8]; /* align_up(sizeof("CORE"), 4) */
     46    struct riscv64_elf_prstatus prstatus;
     47} QEMU_PACKED;
     48
     49#define RISCV64_NOTE_HEADER_SIZE offsetof(struct riscv64_note, prstatus)
     50#define RISCV64_PRSTATUS_NOTE_SIZE \
     51            (RISCV64_NOTE_HEADER_SIZE + sizeof(struct riscv64_elf_prstatus))
     52
     53static void riscv64_note_init(struct riscv64_note *note, DumpState *s,
     54                              const char *name, Elf64_Word namesz,
     55                              Elf64_Word type, Elf64_Word descsz)
     56{
     57    memset(note, 0, sizeof(*note));
     58
     59    note->hdr.n_namesz = cpu_to_dump32(s, namesz);
     60    note->hdr.n_descsz = cpu_to_dump32(s, descsz);
     61    note->hdr.n_type = cpu_to_dump32(s, type);
     62
     63    memcpy(note->name, name, namesz);
     64}
     65
     66int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
     67                               int cpuid, void *opaque)
     68{
     69    struct riscv64_note note;
     70    RISCVCPU *cpu = RISCV_CPU(cs);
     71    CPURISCVState *env = &cpu->env;
     72    DumpState *s = opaque;
     73    int ret, i = 0;
     74    const char name[] = "CORE";
     75
     76    riscv64_note_init(&note, s, name, sizeof(name),
     77                      NT_PRSTATUS, sizeof(note.prstatus));
     78
     79    note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
     80
     81    note.prstatus.pr_reg.pc = cpu_to_dump64(s, env->pc);
     82
     83    for (i = 0; i < 31; i++) {
     84        note.prstatus.pr_reg.regs[i] = cpu_to_dump64(s, env->gpr[i + 1]);
     85    }
     86
     87    ret = f(&note, RISCV64_PRSTATUS_NOTE_SIZE, s);
     88    if (ret < 0) {
     89        return -1;
     90    }
     91
     92    return ret;
     93}
     94
     95struct riscv32_user_regs {
     96    uint32_t pc;
     97    uint32_t regs[31];
     98} QEMU_PACKED;
     99
    100QEMU_BUILD_BUG_ON(sizeof(struct riscv32_user_regs) != 128);
    101
    102struct riscv32_elf_prstatus {
    103    char pad1[24]; /* 24 == offsetof(struct elf_prstatus, pr_pid) */
    104    uint32_t pr_pid;
    105    char pad2[44]; /* 44 == offsetof(struct elf_prstatus, pr_reg) -
    106                            offsetof(struct elf_prstatus, pr_ppid) */
    107    struct riscv32_user_regs pr_reg;
    108    char pad3[4];
    109} QEMU_PACKED;
    110
    111QEMU_BUILD_BUG_ON(sizeof(struct riscv32_elf_prstatus) != 204);
    112
    113struct riscv32_note {
    114    Elf32_Nhdr hdr;
    115    char name[8]; /* align_up(sizeof("CORE"), 4) */
    116    struct riscv32_elf_prstatus prstatus;
    117} QEMU_PACKED;
    118
    119#define RISCV32_NOTE_HEADER_SIZE offsetof(struct riscv32_note, prstatus)
    120#define RISCV32_PRSTATUS_NOTE_SIZE \
    121            (RISCV32_NOTE_HEADER_SIZE + sizeof(struct riscv32_elf_prstatus))
    122
    123static void riscv32_note_init(struct riscv32_note *note, DumpState *s,
    124                              const char *name, Elf32_Word namesz,
    125                              Elf32_Word type, Elf32_Word descsz)
    126{
    127    memset(note, 0, sizeof(*note));
    128
    129    note->hdr.n_namesz = cpu_to_dump32(s, namesz);
    130    note->hdr.n_descsz = cpu_to_dump32(s, descsz);
    131    note->hdr.n_type = cpu_to_dump32(s, type);
    132
    133    memcpy(note->name, name, namesz);
    134}
    135
    136int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
    137                               int cpuid, void *opaque)
    138{
    139    struct riscv32_note note;
    140    RISCVCPU *cpu = RISCV_CPU(cs);
    141    CPURISCVState *env = &cpu->env;
    142    DumpState *s = opaque;
    143    int ret, i;
    144    const char name[] = "CORE";
    145
    146    riscv32_note_init(&note, s, name, sizeof(name),
    147                      NT_PRSTATUS, sizeof(note.prstatus));
    148
    149    note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
    150
    151    note.prstatus.pr_reg.pc = cpu_to_dump32(s, env->pc);
    152
    153    for (i = 0; i < 31; i++) {
    154        note.prstatus.pr_reg.regs[i] = cpu_to_dump32(s, env->gpr[i + 1]);
    155    }
    156
    157    ret = f(&note, RISCV32_PRSTATUS_NOTE_SIZE, s);
    158    if (ret < 0) {
    159        return -1;
    160    }
    161
    162    return ret;
    163}
    164
    165int cpu_get_dump_info(ArchDumpInfo *info,
    166                      const GuestPhysBlockList *guest_phys_blocks)
    167{
    168    RISCVCPU *cpu;
    169    CPURISCVState *env;
    170
    171    if (first_cpu == NULL) {
    172        return -1;
    173    }
    174    cpu = RISCV_CPU(first_cpu);
    175    env = &cpu->env;
    176
    177    info->d_machine = EM_RISCV;
    178
    179#if defined(TARGET_RISCV64)
    180    info->d_class = ELFCLASS64;
    181#else
    182    info->d_class = ELFCLASS32;
    183#endif
    184
    185    info->d_endian = (env->mstatus & MSTATUS_UBE) != 0
    186                     ? ELFDATA2MSB : ELFDATA2LSB;
    187
    188    return 0;
    189}
    190
    191ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
    192{
    193    size_t note_size;
    194
    195    if (class == ELFCLASS64) {
    196        note_size = RISCV64_PRSTATUS_NOTE_SIZE;
    197    } else {
    198        note_size = RISCV32_PRSTATUS_NOTE_SIZE;
    199    }
    200
    201    return note_size * nr_cpus;
    202}