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