1*3b57254dSWeiwei Li /* 2*3b57254dSWeiwei Li * Support for writing ELF notes for RISC-V architectures 343a96588SYifei Jiang * 443a96588SYifei Jiang * Copyright (C) 2021 Huawei Technologies Co., Ltd 543a96588SYifei Jiang * 643a96588SYifei Jiang * This program is free software; you can redistribute it and/or modify it 743a96588SYifei Jiang * under the terms and conditions of the GNU General Public License, 843a96588SYifei Jiang * version 2 or later, as published by the Free Software Foundation. 943a96588SYifei Jiang * 1043a96588SYifei Jiang * This program is distributed in the hope it will be useful, but WITHOUT 1143a96588SYifei Jiang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1243a96588SYifei Jiang * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1343a96588SYifei Jiang * more details. 1443a96588SYifei Jiang * 1543a96588SYifei Jiang * You should have received a copy of the GNU General Public License along with 1643a96588SYifei Jiang * this program. If not, see <http://www.gnu.org/licenses/>. 1743a96588SYifei Jiang */ 1843a96588SYifei Jiang 1943a96588SYifei Jiang #include "qemu/osdep.h" 2043a96588SYifei Jiang #include "cpu.h" 2143a96588SYifei Jiang #include "elf.h" 2243a96588SYifei Jiang #include "sysemu/dump.h" 2343a96588SYifei Jiang 2443a96588SYifei Jiang /* struct user_regs_struct from arch/riscv/include/uapi/asm/ptrace.h */ 2543a96588SYifei Jiang struct riscv64_user_regs { 2643a96588SYifei Jiang uint64_t pc; 2743a96588SYifei Jiang uint64_t regs[31]; 2843a96588SYifei Jiang } QEMU_PACKED; 2943a96588SYifei Jiang 3043a96588SYifei Jiang QEMU_BUILD_BUG_ON(sizeof(struct riscv64_user_regs) != 256); 3143a96588SYifei Jiang 3243a96588SYifei Jiang /* struct elf_prstatus from include/linux/elfcore.h */ 3343a96588SYifei Jiang struct riscv64_elf_prstatus { 3443a96588SYifei Jiang char pad1[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */ 3543a96588SYifei Jiang uint32_t pr_pid; 3643a96588SYifei Jiang char pad2[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) - 3743a96588SYifei Jiang offsetof(struct elf_prstatus, pr_ppid) */ 3843a96588SYifei Jiang struct riscv64_user_regs pr_reg; 3943a96588SYifei Jiang char pad3[8]; 4043a96588SYifei Jiang } QEMU_PACKED; 4143a96588SYifei Jiang 4243a96588SYifei Jiang QEMU_BUILD_BUG_ON(sizeof(struct riscv64_elf_prstatus) != 376); 4343a96588SYifei Jiang 4443a96588SYifei Jiang struct riscv64_note { 4543a96588SYifei Jiang Elf64_Nhdr hdr; 4643a96588SYifei Jiang char name[8]; /* align_up(sizeof("CORE"), 4) */ 4743a96588SYifei Jiang struct riscv64_elf_prstatus prstatus; 4843a96588SYifei Jiang } QEMU_PACKED; 4943a96588SYifei Jiang 5043a96588SYifei Jiang #define RISCV64_NOTE_HEADER_SIZE offsetof(struct riscv64_note, prstatus) 5143a96588SYifei Jiang #define RISCV64_PRSTATUS_NOTE_SIZE \ 5243a96588SYifei Jiang (RISCV64_NOTE_HEADER_SIZE + sizeof(struct riscv64_elf_prstatus)) 5343a96588SYifei Jiang 5443a96588SYifei Jiang static void riscv64_note_init(struct riscv64_note *note, DumpState *s, 5543a96588SYifei Jiang const char *name, Elf64_Word namesz, 5643a96588SYifei Jiang Elf64_Word type, Elf64_Word descsz) 5743a96588SYifei Jiang { 5843a96588SYifei Jiang memset(note, 0, sizeof(*note)); 5943a96588SYifei Jiang 6043a96588SYifei Jiang note->hdr.n_namesz = cpu_to_dump32(s, namesz); 6143a96588SYifei Jiang note->hdr.n_descsz = cpu_to_dump32(s, descsz); 6243a96588SYifei Jiang note->hdr.n_type = cpu_to_dump32(s, type); 6343a96588SYifei Jiang 6443a96588SYifei Jiang memcpy(note->name, name, namesz); 6543a96588SYifei Jiang } 6643a96588SYifei Jiang 6743a96588SYifei Jiang int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, 681af0006aSJanosch Frank int cpuid, DumpState *s) 6943a96588SYifei Jiang { 7043a96588SYifei Jiang struct riscv64_note note; 7143a96588SYifei Jiang RISCVCPU *cpu = RISCV_CPU(cs); 7243a96588SYifei Jiang CPURISCVState *env = &cpu->env; 7343a96588SYifei Jiang int ret, i = 0; 7443a96588SYifei Jiang const char name[] = "CORE"; 7543a96588SYifei Jiang 7643a96588SYifei Jiang riscv64_note_init(¬e, s, name, sizeof(name), 7743a96588SYifei Jiang NT_PRSTATUS, sizeof(note.prstatus)); 7843a96588SYifei Jiang 7943a96588SYifei Jiang note.prstatus.pr_pid = cpu_to_dump32(s, cpuid); 8043a96588SYifei Jiang 8143a96588SYifei Jiang note.prstatus.pr_reg.pc = cpu_to_dump64(s, env->pc); 8243a96588SYifei Jiang 8343a96588SYifei Jiang for (i = 0; i < 31; i++) { 8443a96588SYifei Jiang note.prstatus.pr_reg.regs[i] = cpu_to_dump64(s, env->gpr[i + 1]); 8543a96588SYifei Jiang } 8643a96588SYifei Jiang 8743a96588SYifei Jiang ret = f(¬e, RISCV64_PRSTATUS_NOTE_SIZE, s); 8843a96588SYifei Jiang if (ret < 0) { 8943a96588SYifei Jiang return -1; 9043a96588SYifei Jiang } 9143a96588SYifei Jiang 9243a96588SYifei Jiang return ret; 9343a96588SYifei Jiang } 9443a96588SYifei Jiang 9543a96588SYifei Jiang struct riscv32_user_regs { 9643a96588SYifei Jiang uint32_t pc; 9743a96588SYifei Jiang uint32_t regs[31]; 9843a96588SYifei Jiang } QEMU_PACKED; 9943a96588SYifei Jiang 10043a96588SYifei Jiang QEMU_BUILD_BUG_ON(sizeof(struct riscv32_user_regs) != 128); 10143a96588SYifei Jiang 10243a96588SYifei Jiang struct riscv32_elf_prstatus { 10343a96588SYifei Jiang char pad1[24]; /* 24 == offsetof(struct elf_prstatus, pr_pid) */ 10443a96588SYifei Jiang uint32_t pr_pid; 10543a96588SYifei Jiang char pad2[44]; /* 44 == offsetof(struct elf_prstatus, pr_reg) - 10643a96588SYifei Jiang offsetof(struct elf_prstatus, pr_ppid) */ 10743a96588SYifei Jiang struct riscv32_user_regs pr_reg; 10843a96588SYifei Jiang char pad3[4]; 10943a96588SYifei Jiang } QEMU_PACKED; 11043a96588SYifei Jiang 11143a96588SYifei Jiang QEMU_BUILD_BUG_ON(sizeof(struct riscv32_elf_prstatus) != 204); 11243a96588SYifei Jiang 11343a96588SYifei Jiang struct riscv32_note { 11443a96588SYifei Jiang Elf32_Nhdr hdr; 11543a96588SYifei Jiang char name[8]; /* align_up(sizeof("CORE"), 4) */ 11643a96588SYifei Jiang struct riscv32_elf_prstatus prstatus; 11743a96588SYifei Jiang } QEMU_PACKED; 11843a96588SYifei Jiang 11943a96588SYifei Jiang #define RISCV32_NOTE_HEADER_SIZE offsetof(struct riscv32_note, prstatus) 12043a96588SYifei Jiang #define RISCV32_PRSTATUS_NOTE_SIZE \ 12143a96588SYifei Jiang (RISCV32_NOTE_HEADER_SIZE + sizeof(struct riscv32_elf_prstatus)) 12243a96588SYifei Jiang 12343a96588SYifei Jiang static void riscv32_note_init(struct riscv32_note *note, DumpState *s, 12443a96588SYifei Jiang const char *name, Elf32_Word namesz, 12543a96588SYifei Jiang Elf32_Word type, Elf32_Word descsz) 12643a96588SYifei Jiang { 12743a96588SYifei Jiang memset(note, 0, sizeof(*note)); 12843a96588SYifei Jiang 12943a96588SYifei Jiang note->hdr.n_namesz = cpu_to_dump32(s, namesz); 13043a96588SYifei Jiang note->hdr.n_descsz = cpu_to_dump32(s, descsz); 13143a96588SYifei Jiang note->hdr.n_type = cpu_to_dump32(s, type); 13243a96588SYifei Jiang 13343a96588SYifei Jiang memcpy(note->name, name, namesz); 13443a96588SYifei Jiang } 13543a96588SYifei Jiang 13643a96588SYifei Jiang int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, 1371af0006aSJanosch Frank int cpuid, DumpState *s) 13843a96588SYifei Jiang { 13943a96588SYifei Jiang struct riscv32_note note; 14043a96588SYifei Jiang RISCVCPU *cpu = RISCV_CPU(cs); 14143a96588SYifei Jiang CPURISCVState *env = &cpu->env; 14243a96588SYifei Jiang int ret, i; 14343a96588SYifei Jiang const char name[] = "CORE"; 14443a96588SYifei Jiang 14543a96588SYifei Jiang riscv32_note_init(¬e, s, name, sizeof(name), 14643a96588SYifei Jiang NT_PRSTATUS, sizeof(note.prstatus)); 14743a96588SYifei Jiang 14843a96588SYifei Jiang note.prstatus.pr_pid = cpu_to_dump32(s, cpuid); 14943a96588SYifei Jiang 15043a96588SYifei Jiang note.prstatus.pr_reg.pc = cpu_to_dump32(s, env->pc); 15143a96588SYifei Jiang 15243a96588SYifei Jiang for (i = 0; i < 31; i++) { 15343a96588SYifei Jiang note.prstatus.pr_reg.regs[i] = cpu_to_dump32(s, env->gpr[i + 1]); 15443a96588SYifei Jiang } 15543a96588SYifei Jiang 15643a96588SYifei Jiang ret = f(¬e, RISCV32_PRSTATUS_NOTE_SIZE, s); 15743a96588SYifei Jiang if (ret < 0) { 15843a96588SYifei Jiang return -1; 15943a96588SYifei Jiang } 16043a96588SYifei Jiang 16143a96588SYifei Jiang return ret; 16243a96588SYifei Jiang } 16343a96588SYifei Jiang 16443a96588SYifei Jiang int cpu_get_dump_info(ArchDumpInfo *info, 16543a96588SYifei Jiang const GuestPhysBlockList *guest_phys_blocks) 16643a96588SYifei Jiang { 16743a96588SYifei Jiang RISCVCPU *cpu; 16843a96588SYifei Jiang CPURISCVState *env; 16943a96588SYifei Jiang 17043a96588SYifei Jiang if (first_cpu == NULL) { 17143a96588SYifei Jiang return -1; 17243a96588SYifei Jiang } 17343a96588SYifei Jiang cpu = RISCV_CPU(first_cpu); 17443a96588SYifei Jiang env = &cpu->env; 17543a96588SYifei Jiang 17643a96588SYifei Jiang info->d_machine = EM_RISCV; 17743a96588SYifei Jiang 17843a96588SYifei Jiang #if defined(TARGET_RISCV64) 17943a96588SYifei Jiang info->d_class = ELFCLASS64; 18043a96588SYifei Jiang #else 18143a96588SYifei Jiang info->d_class = ELFCLASS32; 18243a96588SYifei Jiang #endif 18343a96588SYifei Jiang 184c45eff30SWeiwei Li info->d_endian = (env->mstatus & MSTATUS_UBE) != 0 ? 185c45eff30SWeiwei Li ELFDATA2MSB : ELFDATA2LSB; 18643a96588SYifei Jiang 18743a96588SYifei Jiang return 0; 18843a96588SYifei Jiang } 18943a96588SYifei Jiang 19043a96588SYifei Jiang ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) 19143a96588SYifei Jiang { 19243a96588SYifei Jiang size_t note_size; 19343a96588SYifei Jiang 19443a96588SYifei Jiang if (class == ELFCLASS64) { 19543a96588SYifei Jiang note_size = RISCV64_PRSTATUS_NOTE_SIZE; 19643a96588SYifei Jiang } else { 19743a96588SYifei Jiang note_size = RISCV32_PRSTATUS_NOTE_SIZE; 19843a96588SYifei Jiang } 19943a96588SYifei Jiang 20043a96588SYifei Jiang return note_size * nr_cpus; 20143a96588SYifei Jiang } 202