]> git.proxmox.com Git - mirror_qemu.git/blame - target/riscv/arch_dump.c
target/riscv: add support for Zca extension
[mirror_qemu.git] / target / riscv / arch_dump.c
CommitLineData
43a96588
YJ
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,
1af0006a 67 int cpuid, DumpState *s)
43a96588
YJ
68{
69 struct riscv64_note note;
70 RISCVCPU *cpu = RISCV_CPU(cs);
71 CPURISCVState *env = &cpu->env;
43a96588
YJ
72 int ret, i = 0;
73 const char name[] = "CORE";
74
75 riscv64_note_init(&note, s, name, sizeof(name),
76 NT_PRSTATUS, sizeof(note.prstatus));
77
78 note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
79
80 note.prstatus.pr_reg.pc = cpu_to_dump64(s, env->pc);
81
82 for (i = 0; i < 31; i++) {
83 note.prstatus.pr_reg.regs[i] = cpu_to_dump64(s, env->gpr[i + 1]);
84 }
85
86 ret = f(&note, RISCV64_PRSTATUS_NOTE_SIZE, s);
87 if (ret < 0) {
88 return -1;
89 }
90
91 return ret;
92}
93
94struct riscv32_user_regs {
95 uint32_t pc;
96 uint32_t regs[31];
97} QEMU_PACKED;
98
99QEMU_BUILD_BUG_ON(sizeof(struct riscv32_user_regs) != 128);
100
101struct 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;
109
110QEMU_BUILD_BUG_ON(sizeof(struct riscv32_elf_prstatus) != 204);
111
112struct riscv32_note {
113 Elf32_Nhdr hdr;
114 char name[8]; /* align_up(sizeof("CORE"), 4) */
115 struct riscv32_elf_prstatus prstatus;
116} QEMU_PACKED;
117
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))
121
122static void riscv32_note_init(struct riscv32_note *note, DumpState *s,
123 const char *name, Elf32_Word namesz,
124 Elf32_Word type, Elf32_Word descsz)
125{
126 memset(note, 0, sizeof(*note));
127
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);
131
132 memcpy(note->name, name, namesz);
133}
134
135int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
1af0006a 136 int cpuid, DumpState *s)
43a96588
YJ
137{
138 struct riscv32_note note;
139 RISCVCPU *cpu = RISCV_CPU(cs);
140 CPURISCVState *env = &cpu->env;
43a96588
YJ
141 int ret, i;
142 const char name[] = "CORE";
143
144 riscv32_note_init(&note, s, name, sizeof(name),
145 NT_PRSTATUS, sizeof(note.prstatus));
146
147 note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
148
149 note.prstatus.pr_reg.pc = cpu_to_dump32(s, env->pc);
150
151 for (i = 0; i < 31; i++) {
152 note.prstatus.pr_reg.regs[i] = cpu_to_dump32(s, env->gpr[i + 1]);
153 }
154
155 ret = f(&note, RISCV32_PRSTATUS_NOTE_SIZE, s);
156 if (ret < 0) {
157 return -1;
158 }
159
160 return ret;
161}
162
163int cpu_get_dump_info(ArchDumpInfo *info,
164 const GuestPhysBlockList *guest_phys_blocks)
165{
166 RISCVCPU *cpu;
167 CPURISCVState *env;
168
169 if (first_cpu == NULL) {
170 return -1;
171 }
172 cpu = RISCV_CPU(first_cpu);
173 env = &cpu->env;
174
175 info->d_machine = EM_RISCV;
176
177#if defined(TARGET_RISCV64)
178 info->d_class = ELFCLASS64;
179#else
180 info->d_class = ELFCLASS32;
181#endif
182
183 info->d_endian = (env->mstatus & MSTATUS_UBE) != 0
184 ? ELFDATA2MSB : ELFDATA2LSB;
185
186 return 0;
187}
188
189ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
190{
191 size_t note_size;
192
193 if (class == ELFCLASS64) {
194 note_size = RISCV64_PRSTATUS_NOTE_SIZE;
195 } else {
196 note_size = RISCV32_PRSTATUS_NOTE_SIZE;
197 }
198
199 return note_size * nr_cpus;
200}