xref: /openbmc/qemu/target/riscv/cpu.c (revision b15c0f7d)
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"
21 #include "qemu/qemu-print.h"
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 
30 static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
31 
32 const 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 
39 const 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 
46 const 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 
65 const 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",
78     "reserved",
79     "reserved",
80     "reserved",
81     "reserved"
82 };
83 
84 static void set_misa(CPURISCVState *env, target_ulong misa)
85 {
86     env->misa_mask = env->misa = misa;
87 }
88 
89 static 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 
95 static void set_feature(CPURISCVState *env, int feature)
96 {
97     env->features |= (1ULL << feature);
98 }
99 
100 static void set_resetvec(CPURISCVState *env, int resetvec)
101 {
102 #ifndef CONFIG_USER_ONLY
103     env->resetvec = resetvec;
104 #endif
105 }
106 
107 static 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 
115 #if defined(TARGET_RISCV32)
116 
117 static 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);
124     set_feature(env, RISCV_FEATURE_PMP);
125 }
126 
127 static 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);
134     set_feature(env, RISCV_FEATURE_PMP);
135 }
136 
137 static 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);
143     set_feature(env, RISCV_FEATURE_PMP);
144 }
145 
146 #elif defined(TARGET_RISCV64)
147 
148 static 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);
155     set_feature(env, RISCV_FEATURE_PMP);
156 }
157 
158 static 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);
165     set_feature(env, RISCV_FEATURE_PMP);
166 }
167 
168 static 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);
174     set_feature(env, RISCV_FEATURE_PMP);
175 }
176 
177 #endif
178 
179 static 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 
197 static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
198 {
199     RISCVCPU *cpu = RISCV_CPU(cs);
200     CPURISCVState *env = &cpu->env;
201     int i;
202 
203     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
204 #ifndef CONFIG_USER_ONLY
205     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
206     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
207     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip     ",
208                  (target_ulong)atomic_read(&env->mip));
209     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie     ", env->mie);
210     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
211     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
212     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec   ", env->mtvec);
213     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc    ", env->mepc);
214     qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause  ", env->mcause);
215 #endif
216 
217     for (i = 0; i < 32; i++) {
218         qemu_fprintf(f, " %s " TARGET_FMT_lx,
219                      riscv_int_regnames[i], env->gpr[i]);
220         if ((i & 3) == 3) {
221             qemu_fprintf(f, "\n");
222         }
223     }
224     if (flags & CPU_DUMP_FPU) {
225         for (i = 0; i < 32; i++) {
226             qemu_fprintf(f, " %s %016" PRIx64,
227                          riscv_fpr_regnames[i], env->fpr[i]);
228             if ((i & 3) == 3) {
229                 qemu_fprintf(f, "\n");
230             }
231         }
232     }
233 }
234 
235 static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
236 {
237     RISCVCPU *cpu = RISCV_CPU(cs);
238     CPURISCVState *env = &cpu->env;
239     env->pc = value;
240 }
241 
242 static void riscv_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
243 {
244     RISCVCPU *cpu = RISCV_CPU(cs);
245     CPURISCVState *env = &cpu->env;
246     env->pc = tb->pc;
247 }
248 
249 static bool riscv_cpu_has_work(CPUState *cs)
250 {
251 #ifndef CONFIG_USER_ONLY
252     RISCVCPU *cpu = RISCV_CPU(cs);
253     CPURISCVState *env = &cpu->env;
254     /*
255      * Definition of the WFI instruction requires it to ignore the privilege
256      * mode and delegation registers, but respect individual enables
257      */
258     return (atomic_read(&env->mip) & env->mie) != 0;
259 #else
260     return true;
261 #endif
262 }
263 
264 void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
265                           target_ulong *data)
266 {
267     env->pc = data[0];
268 }
269 
270 static void riscv_cpu_reset(CPUState *cs)
271 {
272     RISCVCPU *cpu = RISCV_CPU(cs);
273     RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
274     CPURISCVState *env = &cpu->env;
275 
276     mcc->parent_reset(cs);
277 #ifndef CONFIG_USER_ONLY
278     env->priv = PRV_M;
279     env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
280     env->mcause = 0;
281     env->pc = env->resetvec;
282 #endif
283     cs->exception_index = EXCP_NONE;
284     set_default_nan_mode(1, &env->fp_status);
285 }
286 
287 static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
288 {
289 #if defined(TARGET_RISCV32)
290     info->print_insn = print_insn_riscv32;
291 #elif defined(TARGET_RISCV64)
292     info->print_insn = print_insn_riscv64;
293 #endif
294 }
295 
296 static void riscv_cpu_realize(DeviceState *dev, Error **errp)
297 {
298     CPUState *cs = CPU(dev);
299     RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
300     Error *local_err = NULL;
301 
302     cpu_exec_realizefn(cs, &local_err);
303     if (local_err != NULL) {
304         error_propagate(errp, local_err);
305         return;
306     }
307 
308     riscv_cpu_register_gdb_regs_for_features(cs);
309 
310     qemu_init_vcpu(cs);
311     cpu_reset(cs);
312 
313     mcc->parent_realize(dev, errp);
314 }
315 
316 static void riscv_cpu_init(Object *obj)
317 {
318     CPUState *cs = CPU(obj);
319     RISCVCPU *cpu = RISCV_CPU(obj);
320 
321     cs->env_ptr = &cpu->env;
322 }
323 
324 static const VMStateDescription vmstate_riscv_cpu = {
325     .name = "cpu",
326     .unmigratable = 1,
327 };
328 
329 static void riscv_cpu_class_init(ObjectClass *c, void *data)
330 {
331     RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
332     CPUClass *cc = CPU_CLASS(c);
333     DeviceClass *dc = DEVICE_CLASS(c);
334 
335     device_class_set_parent_realize(dc, riscv_cpu_realize,
336                                     &mcc->parent_realize);
337 
338     mcc->parent_reset = cc->reset;
339     cc->reset = riscv_cpu_reset;
340 
341     cc->class_by_name = riscv_cpu_class_by_name;
342     cc->has_work = riscv_cpu_has_work;
343     cc->do_interrupt = riscv_cpu_do_interrupt;
344     cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt;
345     cc->dump_state = riscv_cpu_dump_state;
346     cc->set_pc = riscv_cpu_set_pc;
347     cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb;
348     cc->gdb_read_register = riscv_cpu_gdb_read_register;
349     cc->gdb_write_register = riscv_cpu_gdb_write_register;
350     cc->gdb_num_core_regs = 33;
351 #if defined(TARGET_RISCV32)
352     cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
353 #elif defined(TARGET_RISCV64)
354     cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
355 #endif
356     cc->gdb_stop_before_watchpoint = true;
357     cc->disas_set_info = riscv_cpu_disas_set_info;
358 #ifndef CONFIG_USER_ONLY
359     cc->do_unaligned_access = riscv_cpu_do_unaligned_access;
360     cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug;
361 #endif
362 #ifdef CONFIG_TCG
363     cc->tcg_initialize = riscv_translate_init;
364     cc->tlb_fill = riscv_cpu_tlb_fill;
365 #endif
366     /* For now, mark unmigratable: */
367     cc->vmsd = &vmstate_riscv_cpu;
368 }
369 
370 char *riscv_isa_string(RISCVCPU *cpu)
371 {
372     int i;
373     const size_t maxlen = sizeof("rv128") + sizeof(riscv_exts) + 1;
374     char *isa_str = g_new(char, maxlen);
375     char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);
376     for (i = 0; i < sizeof(riscv_exts); i++) {
377         if (cpu->env.misa & RV(riscv_exts[i])) {
378             *p++ = qemu_tolower(riscv_exts[i]);
379         }
380     }
381     *p = '\0';
382     return isa_str;
383 }
384 
385 static gint riscv_cpu_list_compare(gconstpointer a, gconstpointer b)
386 {
387     ObjectClass *class_a = (ObjectClass *)a;
388     ObjectClass *class_b = (ObjectClass *)b;
389     const char *name_a, *name_b;
390 
391     name_a = object_class_get_name(class_a);
392     name_b = object_class_get_name(class_b);
393     return strcmp(name_a, name_b);
394 }
395 
396 static void riscv_cpu_list_entry(gpointer data, gpointer user_data)
397 {
398     const char *typename = object_class_get_name(OBJECT_CLASS(data));
399     int len = strlen(typename) - strlen(RISCV_CPU_TYPE_SUFFIX);
400 
401     qemu_printf("%.*s\n", len, typename);
402 }
403 
404 void riscv_cpu_list(void)
405 {
406     GSList *list;
407 
408     list = object_class_get_list(TYPE_RISCV_CPU, false);
409     list = g_slist_sort(list, riscv_cpu_list_compare);
410     g_slist_foreach(list, riscv_cpu_list_entry, NULL);
411     g_slist_free(list);
412 }
413 
414 #define DEFINE_CPU(type_name, initfn)      \
415     {                                      \
416         .name = type_name,                 \
417         .parent = TYPE_RISCV_CPU,          \
418         .instance_init = initfn            \
419     }
420 
421 static const TypeInfo riscv_cpu_type_infos[] = {
422     {
423         .name = TYPE_RISCV_CPU,
424         .parent = TYPE_CPU,
425         .instance_size = sizeof(RISCVCPU),
426         .instance_init = riscv_cpu_init,
427         .abstract = true,
428         .class_size = sizeof(RISCVCPUClass),
429         .class_init = riscv_cpu_class_init,
430     },
431     DEFINE_CPU(TYPE_RISCV_CPU_ANY,              riscv_any_cpu_init),
432 #if defined(TARGET_RISCV32)
433     DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init),
434     DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init),
435     DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU,  rv32imacu_nommu_cpu_init),
436     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31,       rv32imacu_nommu_cpu_init),
437     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34,       rv32gcsu_priv1_10_0_cpu_init)
438 #elif defined(TARGET_RISCV64)
439     DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init),
440     DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init),
441     DEFINE_CPU(TYPE_RISCV_CPU_RV64IMACU_NOMMU,  rv64imacu_nommu_cpu_init),
442     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51,       rv64imacu_nommu_cpu_init),
443     DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54,       rv64gcsu_priv1_10_0_cpu_init)
444 #endif
445 };
446 
447 DEFINE_TYPES(riscv_cpu_type_infos)
448