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, 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(¬e, 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(¬e, 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];
104 uint32_t pr_pid;
105 char pad2[44];
106
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];
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(¬e, 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(¬e, 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}
203