]> git.proxmox.com Git - mirror_qemu.git/blame - target/riscv/cpu.c
target: Simplify how the TARGET_cpu_list() print
[mirror_qemu.git] / target / riscv / cpu.c
CommitLineData
dc5bd18f
MC
1/*
2 * QEMU RISC-V CPU
3 *
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5 * Copyright (c) 2017-2018 SiFive, Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2 or later, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "qemu/osdep.h"
0442428a 21#include "qemu/qemu-print.h"
dc5bd18f
MC
22#include "qemu/log.h"
23#include "cpu.h"
24#include "exec/exec-all.h"
25#include "qapi/error.h"
26#include "migration/vmstate.h"
27
28/* RISC-V CPU definitions */
29
79f86934 30static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
dc5bd18f
MC
31
32const char * const riscv_int_regnames[] = {
33 "zero", "ra ", "sp ", "gp ", "tp ", "t0 ", "t1 ", "t2 ",
34 "s0 ", "s1 ", "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ",
35 "a6 ", "a7 ", "s2 ", "s3 ", "s4 ", "s5 ", "s6 ", "s7 ",
36 "s8 ", "s9 ", "s10 ", "s11 ", "t3 ", "t4 ", "t5 ", "t6 "
37};
38
39const char * const riscv_fpr_regnames[] = {
40 "ft0 ", "ft1 ", "ft2 ", "ft3 ", "ft4 ", "ft5 ", "ft6 ", "ft7 ",
41 "fs0 ", "fs1 ", "fa0 ", "fa1 ", "fa2 ", "fa3 ", "fa4 ", "fa5 ",
42 "fa6 ", "fa7 ", "fs2 ", "fs3 ", "fs4 ", "fs5 ", "fs6 ", "fs7 ",
43 "fs8 ", "fs9 ", "fs10", "fs11", "ft8 ", "ft9 ", "ft10", "ft11"
44};
45
46const char * const riscv_excp_names[] = {
47 "misaligned_fetch",
48 "fault_fetch",
49 "illegal_instruction",
50 "breakpoint",
51 "misaligned_load",
52 "fault_load",
53 "misaligned_store",
54 "fault_store",
55 "user_ecall",
56 "supervisor_ecall",
57 "hypervisor_ecall",
58 "machine_ecall",
59 "exec_page_fault",
60 "load_page_fault",
61 "reserved",
62 "store_page_fault"
63};
64
65const char * const riscv_intr_names[] = {
66 "u_software",
67 "s_software",
68 "h_software",
69 "m_software",
70 "u_timer",
71 "s_timer",
72 "h_timer",
73 "m_timer",
74 "u_external",
75 "s_external",
76 "h_external",
77 "m_external",
426f0348
MC
78 "reserved",
79 "reserved",
80 "reserved",
81 "reserved"
dc5bd18f
MC
82};
83
dc5bd18f
MC
84static void set_misa(CPURISCVState *env, target_ulong misa)
85{
f18637cd 86 env->misa_mask = env->misa = misa;
dc5bd18f
MC
87}
88
89static void set_versions(CPURISCVState *env, int user_ver, int priv_ver)
90{
91 env->user_ver = user_ver;
92 env->priv_ver = priv_ver;
93}
94
95static void set_feature(CPURISCVState *env, int feature)
96{
97 env->features |= (1ULL << feature);
98}
99
100static void set_resetvec(CPURISCVState *env, int resetvec)
101{
102#ifndef CONFIG_USER_ONLY
103 env->resetvec = resetvec;
104#endif
105}
106
107static void riscv_any_cpu_init(Object *obj)
108{
109 CPURISCVState *env = &RISCV_CPU(obj)->env;
110 set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
111 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
112 set_resetvec(env, DEFAULT_RSTVEC);
113}
114
eab15862
MC
115#if defined(TARGET_RISCV32)
116
dc5bd18f
MC
117static void rv32gcsu_priv1_09_1_cpu_init(Object *obj)
118{
119 CPURISCVState *env = &RISCV_CPU(obj)->env;
120 set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
121 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1);
122 set_resetvec(env, DEFAULT_RSTVEC);
123 set_feature(env, RISCV_FEATURE_MMU);
a88365c1 124 set_feature(env, RISCV_FEATURE_PMP);
dc5bd18f
MC
125}
126
127static void rv32gcsu_priv1_10_0_cpu_init(Object *obj)
128{
129 CPURISCVState *env = &RISCV_CPU(obj)->env;
130 set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
131 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
132 set_resetvec(env, DEFAULT_RSTVEC);
133 set_feature(env, RISCV_FEATURE_MMU);
a88365c1 134 set_feature(env, RISCV_FEATURE_PMP);
dc5bd18f
MC
135}
136
137static void rv32imacu_nommu_cpu_init(Object *obj)
138{
139 CPURISCVState *env = &RISCV_CPU(obj)->env;
140 set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU);
141 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
142 set_resetvec(env, DEFAULT_RSTVEC);
a88365c1 143 set_feature(env, RISCV_FEATURE_PMP);
dc5bd18f
MC
144}
145
eab15862
MC
146#elif defined(TARGET_RISCV64)
147
dc5bd18f
MC
148static void rv64gcsu_priv1_09_1_cpu_init(Object *obj)
149{
150 CPURISCVState *env = &RISCV_CPU(obj)->env;
151 set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
152 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1);
153 set_resetvec(env, DEFAULT_RSTVEC);
154 set_feature(env, RISCV_FEATURE_MMU);
a88365c1 155 set_feature(env, RISCV_FEATURE_PMP);
dc5bd18f
MC
156}
157
158static void rv64gcsu_priv1_10_0_cpu_init(Object *obj)
159{
160 CPURISCVState *env = &RISCV_CPU(obj)->env;
161 set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
162 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
163 set_resetvec(env, DEFAULT_RSTVEC);
164 set_feature(env, RISCV_FEATURE_MMU);
a88365c1 165 set_feature(env, RISCV_FEATURE_PMP);
dc5bd18f
MC
166}
167
168static void rv64imacu_nommu_cpu_init(Object *obj)
169{
170 CPURISCVState *env = &RISCV_CPU(obj)->env;
171 set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU);
172 set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
173 set_resetvec(env, DEFAULT_RSTVEC);
a88365c1 174 set_feature(env, RISCV_FEATURE_PMP);
dc5bd18f
MC
175}
176
eab15862 177#endif
dc5bd18f
MC
178
179static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
180{
181 ObjectClass *oc;
182 char *typename;
183 char **cpuname;
184
185 cpuname = g_strsplit(cpu_model, ",", 1);
186 typename = g_strdup_printf(RISCV_CPU_TYPE_NAME("%s"), cpuname[0]);
187 oc = object_class_by_name(typename);
188 g_strfreev(cpuname);
189 g_free(typename);
190 if (!oc || !object_class_dynamic_cast(oc, TYPE_RISCV_CPU) ||
191 object_class_is_abstract(oc)) {
192 return NULL;
193 }
194 return oc;
195}
196
197static void riscv_cpu_dump_state(CPUState *cs, FILE *f,
198 fprintf_function cpu_fprintf, int flags)
199{
200 RISCVCPU *cpu = RISCV_CPU(cs);
201 CPURISCVState *env = &cpu->env;
202 int i;
203
204 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", env->pc);
205#ifndef CONFIG_USER_ONLY
206 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
207 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
208 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ",
209 (target_ulong)atomic_read(&env->mip));
210 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
211 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
212 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
213 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec ", env->mtvec);
214 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc ", env->mepc);
215 cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause ", env->mcause);
216#endif
217
218 for (i = 0; i < 32; i++) {
219 cpu_fprintf(f, " %s " TARGET_FMT_lx,
220 riscv_int_regnames[i], env->gpr[i]);
221 if ((i & 3) == 3) {
222 cpu_fprintf(f, "\n");
223 }
224 }
86ea1880
RH
225 if (flags & CPU_DUMP_FPU) {
226 for (i = 0; i < 32; i++) {
227 cpu_fprintf(f, " %s %016" PRIx64,
228 riscv_fpr_regnames[i], env->fpr[i]);
229 if ((i & 3) == 3) {
230 cpu_fprintf(f, "\n");
231 }
dc5bd18f
MC
232 }
233 }
234}
235
236static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
237{
238 RISCVCPU *cpu = RISCV_CPU(cs);
239 CPURISCVState *env = &cpu->env;
240 env->pc = value;
241}
242
243static void riscv_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
244{
245 RISCVCPU *cpu = RISCV_CPU(cs);
246 CPURISCVState *env = &cpu->env;
247 env->pc = tb->pc;
248}
249
250static bool riscv_cpu_has_work(CPUState *cs)
251{
252#ifndef CONFIG_USER_ONLY
253 RISCVCPU *cpu = RISCV_CPU(cs);
254 CPURISCVState *env = &cpu->env;
255 /*
256 * Definition of the WFI instruction requires it to ignore the privilege
257 * mode and delegation registers, but respect individual enables
258 */
259 return (atomic_read(&env->mip) & env->mie) != 0;
260#else
261 return true;
262#endif
263}
264
265void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
266 target_ulong *data)
267{
268 env->pc = data[0];
269}
270
271static void riscv_cpu_reset(CPUState *cs)
272{
273 RISCVCPU *cpu = RISCV_CPU(cs);
274 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
275 CPURISCVState *env = &cpu->env;
276
277 mcc->parent_reset(cs);
278#ifndef CONFIG_USER_ONLY
279 env->priv = PRV_M;
280 env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
281 env->mcause = 0;
282 env->pc = env->resetvec;
283#endif
284 cs->exception_index = EXCP_NONE;
285 set_default_nan_mode(1, &env->fp_status);
286}
287
288static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
289{
290#if defined(TARGET_RISCV32)
291 info->print_insn = print_insn_riscv32;
292#elif defined(TARGET_RISCV64)
293 info->print_insn = print_insn_riscv64;
294#endif
295}
296
297static void riscv_cpu_realize(DeviceState *dev, Error **errp)
298{
299 CPUState *cs = CPU(dev);
300 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
301 Error *local_err = NULL;
302
303 cpu_exec_realizefn(cs, &local_err);
304 if (local_err != NULL) {
305 error_propagate(errp, local_err);
306 return;
307 }
308
5371f5cd
JW
309 riscv_cpu_register_gdb_regs_for_features(cs);
310
dc5bd18f
MC
311 qemu_init_vcpu(cs);
312 cpu_reset(cs);
313
314 mcc->parent_realize(dev, errp);
315}
316
317static void riscv_cpu_init(Object *obj)
318{
319 CPUState *cs = CPU(obj);
320 RISCVCPU *cpu = RISCV_CPU(obj);
321
322 cs->env_ptr = &cpu->env;
323}
324
325static const VMStateDescription vmstate_riscv_cpu = {
326 .name = "cpu",
327 .unmigratable = 1,
328};
329
330static void riscv_cpu_class_init(ObjectClass *c, void *data)
331{
332 RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
333 CPUClass *cc = CPU_CLASS(c);
334 DeviceClass *dc = DEVICE_CLASS(c);
335
41fbbba7
MZ
336 device_class_set_parent_realize(dc, riscv_cpu_realize,
337 &mcc->parent_realize);
dc5bd18f
MC
338
339 mcc->parent_reset = cc->reset;
340 cc->reset = riscv_cpu_reset;
341
342 cc->class_by_name = riscv_cpu_class_by_name;
343 cc->has_work = riscv_cpu_has_work;
344 cc->do_interrupt = riscv_cpu_do_interrupt;
345 cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt;
346 cc->dump_state = riscv_cpu_dump_state;
347 cc->set_pc = riscv_cpu_set_pc;
348 cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb;
349 cc->gdb_read_register = riscv_cpu_gdb_read_register;
350 cc->gdb_write_register = riscv_cpu_gdb_write_register;
5371f5cd
JW
351 cc->gdb_num_core_regs = 33;
352#if defined(TARGET_RISCV32)
353 cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
354#elif defined(TARGET_RISCV64)
355 cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
356#endif
dc5bd18f
MC
357 cc->gdb_stop_before_watchpoint = true;
358 cc->disas_set_info = riscv_cpu_disas_set_info;
359#ifdef CONFIG_USER_ONLY
360 cc->handle_mmu_fault = riscv_cpu_handle_mmu_fault;
361#else
362 cc->do_unaligned_access = riscv_cpu_do_unaligned_access;
363 cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug;
364#endif
365#ifdef CONFIG_TCG
366 cc->tcg_initialize = riscv_translate_init;
367#endif
368 /* For now, mark unmigratable: */
369 cc->vmsd = &vmstate_riscv_cpu;
370}
371
dc5bd18f
MC
372char *riscv_isa_string(RISCVCPU *cpu)
373{
374 int i;
d1fd31f8
MC
375 const size_t maxlen = sizeof("rv128") + sizeof(riscv_exts) + 1;
376 char *isa_str = g_new(char, maxlen);
377 char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);
dc5bd18f
MC
378 for (i = 0; i < sizeof(riscv_exts); i++) {
379 if (cpu->env.misa & RV(riscv_exts[i])) {
d1fd31f8 380 *p++ = qemu_tolower(riscv_exts[i]);
dc5bd18f
MC
381 }
382 }
d1fd31f8
MC
383 *p = '\0';
384 return isa_str;
dc5bd18f
MC
385}
386
eab15862 387static gint riscv_cpu_list_compare(gconstpointer a, gconstpointer b)
dc5bd18f 388{
eab15862
MC
389 ObjectClass *class_a = (ObjectClass *)a;
390 ObjectClass *class_b = (ObjectClass *)b;
391 const char *name_a, *name_b;
dc5bd18f 392
eab15862
MC
393 name_a = object_class_get_name(class_a);
394 name_b = object_class_get_name(class_b);
395 return strcmp(name_a, name_b);
dc5bd18f
MC
396}
397
eab15862 398static void riscv_cpu_list_entry(gpointer data, gpointer user_data)
dc5bd18f 399{
eab15862
MC
400 const char *typename = object_class_get_name(OBJECT_CLASS(data));
401 int len = strlen(typename) - strlen(RISCV_CPU_TYPE_SUFFIX);
dc5bd18f 402
0442428a 403 qemu_printf("%.*s\n", len, typename);
eab15862 404}
dc5bd18f 405
0442428a 406void riscv_cpu_list(void)
eab15862 407{
eab15862
MC
408 GSList *list;
409
410 list = object_class_get_list(TYPE_RISCV_CPU, false);
411 list = g_slist_sort(list, riscv_cpu_list_compare);
0442428a 412 g_slist_foreach(list, riscv_cpu_list_entry, NULL);
eab15862 413 g_slist_free(list);
dc5bd18f
MC
414}
415
eab15862
MC
416#define DEFINE_CPU(type_name, initfn) \
417 { \
418 .name = type_name, \
419 .parent = TYPE_RISCV_CPU, \
420 .instance_init = initfn \
421 }
422
423static const TypeInfo riscv_cpu_type_infos[] = {
424 {
425 .name = TYPE_RISCV_CPU,
426 .parent = TYPE_CPU,
427 .instance_size = sizeof(RISCVCPU),
428 .instance_init = riscv_cpu_init,
429 .abstract = true,
430 .class_size = sizeof(RISCVCPUClass),
431 .class_init = riscv_cpu_class_init,
432 },
433 DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
434#if defined(TARGET_RISCV32)
435 DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init),
436 DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init),
437 DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init),
438 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init),
439 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init)
440#elif defined(TARGET_RISCV64)
441 DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init),
442 DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init),
443 DEFINE_CPU(TYPE_RISCV_CPU_RV64IMACU_NOMMU, rv64imacu_nommu_cpu_init),
444 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64imacu_nommu_cpu_init),
445 DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64gcsu_priv1_10_0_cpu_init)
446#endif
447};
448
449DEFINE_TYPES(riscv_cpu_type_infos)