tests/docker: Add flex/bison to `debian-all-test`
[qemu/ar7.git] / target / riscv / arch_dump.c
blob736a232956e16e0b0becf100af5f81ae4764f7ff
1 /* Support for writing ELF notes for RISC-V architectures
3 * Copyright (C) 2021 Huawei Technologies Co., Ltd
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.
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.
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/>.
18 #include "qemu/osdep.h"
19 #include "cpu.h"
20 #include "elf.h"
21 #include "sysemu/dump.h"
23 /* struct user_regs_struct from arch/riscv/include/uapi/asm/ptrace.h */
24 struct riscv64_user_regs {
25 uint64_t pc;
26 uint64_t regs[31];
27 } QEMU_PACKED;
29 QEMU_BUILD_BUG_ON(sizeof(struct riscv64_user_regs) != 256);
31 /* struct elf_prstatus from include/linux/elfcore.h */
32 struct 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;
41 QEMU_BUILD_BUG_ON(sizeof(struct riscv64_elf_prstatus) != 376);
43 struct riscv64_note {
44 Elf64_Nhdr hdr;
45 char name[8]; /* align_up(sizeof("CORE"), 4) */
46 struct riscv64_elf_prstatus prstatus;
47 } QEMU_PACKED;
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))
53 static void riscv64_note_init(struct riscv64_note *note, DumpState *s,
54 const char *name, Elf64_Word namesz,
55 Elf64_Word type, Elf64_Word descsz)
57 memset(note, 0, sizeof(*note));
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);
63 memcpy(note->name, name, namesz);
66 int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
67 int cpuid, DumpState *s)
69 struct riscv64_note note;
70 RISCVCPU *cpu = RISCV_CPU(cs);
71 CPURISCVState *env = &cpu->env;
72 int ret, i = 0;
73 const char name[] = "CORE";
75 riscv64_note_init(&note, s, name, sizeof(name),
76 NT_PRSTATUS, sizeof(note.prstatus));
78 note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
80 note.prstatus.pr_reg.pc = cpu_to_dump64(s, env->pc);
82 for (i = 0; i < 31; i++) {
83 note.prstatus.pr_reg.regs[i] = cpu_to_dump64(s, env->gpr[i + 1]);
86 ret = f(&note, RISCV64_PRSTATUS_NOTE_SIZE, s);
87 if (ret < 0) {
88 return -1;
91 return ret;
94 struct riscv32_user_regs {
95 uint32_t pc;
96 uint32_t regs[31];
97 } QEMU_PACKED;
99 QEMU_BUILD_BUG_ON(sizeof(struct riscv32_user_regs) != 128);
101 struct riscv32_elf_prstatus {
102 char pad1[24]; /* 24 == offsetof(struct elf_prstatus, pr_pid) */
103 uint32_t pr_pid;
104 char pad2[44]; /* 44 == offsetof(struct elf_prstatus, pr_reg) -
105 offsetof(struct elf_prstatus, pr_ppid) */
106 struct riscv32_user_regs pr_reg;
107 char pad3[4];
108 } QEMU_PACKED;
110 QEMU_BUILD_BUG_ON(sizeof(struct riscv32_elf_prstatus) != 204);
112 struct riscv32_note {
113 Elf32_Nhdr hdr;
114 char name[8]; /* align_up(sizeof("CORE"), 4) */
115 struct riscv32_elf_prstatus prstatus;
116 } QEMU_PACKED;
118 #define RISCV32_NOTE_HEADER_SIZE offsetof(struct riscv32_note, prstatus)
119 #define RISCV32_PRSTATUS_NOTE_SIZE \
120 (RISCV32_NOTE_HEADER_SIZE + sizeof(struct riscv32_elf_prstatus))
122 static void riscv32_note_init(struct riscv32_note *note, DumpState *s,
123 const char *name, Elf32_Word namesz,
124 Elf32_Word type, Elf32_Word descsz)
126 memset(note, 0, sizeof(*note));
128 note->hdr.n_namesz = cpu_to_dump32(s, namesz);
129 note->hdr.n_descsz = cpu_to_dump32(s, descsz);
130 note->hdr.n_type = cpu_to_dump32(s, type);
132 memcpy(note->name, name, namesz);
135 int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
136 int cpuid, DumpState *s)
138 struct riscv32_note note;
139 RISCVCPU *cpu = RISCV_CPU(cs);
140 CPURISCVState *env = &cpu->env;
141 int ret, i;
142 const char name[] = "CORE";
144 riscv32_note_init(&note, s, name, sizeof(name),
145 NT_PRSTATUS, sizeof(note.prstatus));
147 note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
149 note.prstatus.pr_reg.pc = cpu_to_dump32(s, env->pc);
151 for (i = 0; i < 31; i++) {
152 note.prstatus.pr_reg.regs[i] = cpu_to_dump32(s, env->gpr[i + 1]);
155 ret = f(&note, RISCV32_PRSTATUS_NOTE_SIZE, s);
156 if (ret < 0) {
157 return -1;
160 return ret;
163 int cpu_get_dump_info(ArchDumpInfo *info,
164 const GuestPhysBlockList *guest_phys_blocks)
166 RISCVCPU *cpu;
167 CPURISCVState *env;
169 if (first_cpu == NULL) {
170 return -1;
172 cpu = RISCV_CPU(first_cpu);
173 env = &cpu->env;
175 info->d_machine = EM_RISCV;
177 #if defined(TARGET_RISCV64)
178 info->d_class = ELFCLASS64;
179 #else
180 info->d_class = ELFCLASS32;
181 #endif
183 info->d_endian = (env->mstatus & MSTATUS_UBE) != 0
184 ? ELFDATA2MSB : ELFDATA2LSB;
186 return 0;
189 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
191 size_t note_size;
193 if (class == ELFCLASS64) {
194 note_size = RISCV64_PRSTATUS_NOTE_SIZE;
195 } else {
196 note_size = RISCV32_PRSTATUS_NOTE_SIZE;
199 return note_size * nr_cpus;