1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "qemu/osdep.h"
19#include "cpu.h"
20#include "elf.h"
21#include "sysemu/dump.h"
22
23
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
32struct riscv64_elf_prstatus {
33 char pad1[32];
34 uint32_t pr_pid;
35 char pad2[76];
36
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];
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, DumpState *s)
68{
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";
74
75 riscv64_note_init(¬e, 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(¬e, 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];
103 uint32_t pr_pid;
104 char pad2[44];
105
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];
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,
136 int cpuid, DumpState *s)
137{
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";
143
144 riscv32_note_init(¬e, 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(¬e, 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}
201