xref: /openbmc/qemu/target/riscv/cpu.c (revision dc5bd18f)
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] = "IMAFDQECLBJTPVNSUHKORWXYZG";
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     "coprocessor",
78     "host"
79 };
80 
81 typedef struct RISCVCPUInfo {
82     const int bit_widths;
83     const char *name;
84     void (*initfn)(Object *obj);
85 } RISCVCPUInfo;
86 
87 static void set_misa(CPURISCVState *env, target_ulong misa)
88 {
89     env->misa = misa;
90 }
91 
92 static void set_versions(CPURISCVState *env, int user_ver, int priv_ver)
93 {
94     env->user_ver = user_ver;
95     env->priv_ver = priv_ver;
96 }
97 
98 static void set_feature(CPURISCVState *env, int feature)
99 {
100     env->features |= (1ULL << feature);
101 }
102 
103 static void set_resetvec(CPURISCVState *env, int resetvec)
104 {
105 #ifndef CONFIG_USER_ONLY
106     env->resetvec = resetvec;
107 #endif
108 }
109 
110 static void riscv_any_cpu_init(Object *obj)
111 {
112     CPURISCVState *env = &RISCV_CPU(obj)->env;
113     set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
114     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
115     set_resetvec(env, DEFAULT_RSTVEC);
116 }
117 
118 static void rv32gcsu_priv1_09_1_cpu_init(Object *obj)
119 {
120     CPURISCVState *env = &RISCV_CPU(obj)->env;
121     set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
122     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1);
123     set_resetvec(env, DEFAULT_RSTVEC);
124     set_feature(env, RISCV_FEATURE_MMU);
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 }
135 
136 static void rv32imacu_nommu_cpu_init(Object *obj)
137 {
138     CPURISCVState *env = &RISCV_CPU(obj)->env;
139     set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU);
140     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
141     set_resetvec(env, DEFAULT_RSTVEC);
142 }
143 
144 static void rv64gcsu_priv1_09_1_cpu_init(Object *obj)
145 {
146     CPURISCVState *env = &RISCV_CPU(obj)->env;
147     set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
148     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_09_1);
149     set_resetvec(env, DEFAULT_RSTVEC);
150     set_feature(env, RISCV_FEATURE_MMU);
151 }
152 
153 static void rv64gcsu_priv1_10_0_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_10_0);
158     set_resetvec(env, DEFAULT_RSTVEC);
159     set_feature(env, RISCV_FEATURE_MMU);
160 }
161 
162 static void rv64imacu_nommu_cpu_init(Object *obj)
163 {
164     CPURISCVState *env = &RISCV_CPU(obj)->env;
165     set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU);
166     set_versions(env, USER_VERSION_2_02_0, PRIV_VERSION_1_10_0);
167     set_resetvec(env, DEFAULT_RSTVEC);
168 }
169 
170 static const RISCVCPUInfo riscv_cpus[] = {
171     { 96, TYPE_RISCV_CPU_ANY,              riscv_any_cpu_init },
172     { 32, TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init },
173     { 32, TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init },
174     { 32, TYPE_RISCV_CPU_RV32IMACU_NOMMU,  rv32imacu_nommu_cpu_init },
175     { 32, TYPE_RISCV_CPU_SIFIVE_E31,       rv32imacu_nommu_cpu_init },
176     { 32, TYPE_RISCV_CPU_SIFIVE_U34,       rv32gcsu_priv1_10_0_cpu_init },
177     { 64, TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init },
178     { 64, TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init },
179     { 64, TYPE_RISCV_CPU_RV64IMACU_NOMMU,  rv64imacu_nommu_cpu_init },
180     { 64, TYPE_RISCV_CPU_SIFIVE_E51,       rv64imacu_nommu_cpu_init },
181     { 64, TYPE_RISCV_CPU_SIFIVE_U54,       rv64gcsu_priv1_10_0_cpu_init },
182     { 0, NULL, NULL }
183 };
184 
185 static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
186 {
187     ObjectClass *oc;
188     char *typename;
189     char **cpuname;
190 
191     cpuname = g_strsplit(cpu_model, ",", 1);
192     typename = g_strdup_printf(RISCV_CPU_TYPE_NAME("%s"), cpuname[0]);
193     oc = object_class_by_name(typename);
194     g_strfreev(cpuname);
195     g_free(typename);
196     if (!oc || !object_class_dynamic_cast(oc, TYPE_RISCV_CPU) ||
197         object_class_is_abstract(oc)) {
198         return NULL;
199     }
200     return oc;
201 }
202 
203 static void riscv_cpu_dump_state(CPUState *cs, FILE *f,
204     fprintf_function cpu_fprintf, int flags)
205 {
206     RISCVCPU *cpu = RISCV_CPU(cs);
207     CPURISCVState *env = &cpu->env;
208     int i;
209 
210     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc      ", env->pc);
211 #ifndef CONFIG_USER_ONLY
212     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
213     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
214     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip     ",
215         (target_ulong)atomic_read(&env->mip));
216     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie     ", env->mie);
217     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
218     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
219     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec   ", env->mtvec);
220     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc    ", env->mepc);
221     cpu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause  ", env->mcause);
222 #endif
223 
224     for (i = 0; i < 32; i++) {
225         cpu_fprintf(f, " %s " TARGET_FMT_lx,
226             riscv_int_regnames[i], env->gpr[i]);
227         if ((i & 3) == 3) {
228             cpu_fprintf(f, "\n");
229         }
230     }
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 static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
241 {
242     RISCVCPU *cpu = RISCV_CPU(cs);
243     CPURISCVState *env = &cpu->env;
244     env->pc = value;
245 }
246 
247 static void riscv_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
248 {
249     RISCVCPU *cpu = RISCV_CPU(cs);
250     CPURISCVState *env = &cpu->env;
251     env->pc = tb->pc;
252 }
253 
254 static bool riscv_cpu_has_work(CPUState *cs)
255 {
256 #ifndef CONFIG_USER_ONLY
257     RISCVCPU *cpu = RISCV_CPU(cs);
258     CPURISCVState *env = &cpu->env;
259     /*
260      * Definition of the WFI instruction requires it to ignore the privilege
261      * mode and delegation registers, but respect individual enables
262      */
263     return (atomic_read(&env->mip) & env->mie) != 0;
264 #else
265     return true;
266 #endif
267 }
268 
269 void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
270                           target_ulong *data)
271 {
272     env->pc = data[0];
273 }
274 
275 static void riscv_cpu_reset(CPUState *cs)
276 {
277     RISCVCPU *cpu = RISCV_CPU(cs);
278     RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
279     CPURISCVState *env = &cpu->env;
280 
281     mcc->parent_reset(cs);
282 #ifndef CONFIG_USER_ONLY
283     env->priv = PRV_M;
284     env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
285     env->mcause = 0;
286     env->pc = env->resetvec;
287 #endif
288     cs->exception_index = EXCP_NONE;
289     set_default_nan_mode(1, &env->fp_status);
290 }
291 
292 static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
293 {
294 #if defined(TARGET_RISCV32)
295     info->print_insn = print_insn_riscv32;
296 #elif defined(TARGET_RISCV64)
297     info->print_insn = print_insn_riscv64;
298 #endif
299 }
300 
301 static void riscv_cpu_realize(DeviceState *dev, Error **errp)
302 {
303     CPUState *cs = CPU(dev);
304     RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
305     Error *local_err = NULL;
306 
307     cpu_exec_realizefn(cs, &local_err);
308     if (local_err != NULL) {
309         error_propagate(errp, local_err);
310         return;
311     }
312 
313     qemu_init_vcpu(cs);
314     cpu_reset(cs);
315 
316     mcc->parent_realize(dev, errp);
317 }
318 
319 static void riscv_cpu_init(Object *obj)
320 {
321     CPUState *cs = CPU(obj);
322     RISCVCPU *cpu = RISCV_CPU(obj);
323 
324     cs->env_ptr = &cpu->env;
325 }
326 
327 static const VMStateDescription vmstate_riscv_cpu = {
328     .name = "cpu",
329     .unmigratable = 1,
330 };
331 
332 static void riscv_cpu_class_init(ObjectClass *c, void *data)
333 {
334     RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
335     CPUClass *cc = CPU_CLASS(c);
336     DeviceClass *dc = DEVICE_CLASS(c);
337 
338     mcc->parent_realize = dc->realize;
339     dc->realize = riscv_cpu_realize;
340 
341     mcc->parent_reset = cc->reset;
342     cc->reset = riscv_cpu_reset;
343 
344     cc->class_by_name = riscv_cpu_class_by_name;
345     cc->has_work = riscv_cpu_has_work;
346     cc->do_interrupt = riscv_cpu_do_interrupt;
347     cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt;
348     cc->dump_state = riscv_cpu_dump_state;
349     cc->set_pc = riscv_cpu_set_pc;
350     cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb;
351     cc->gdb_read_register = riscv_cpu_gdb_read_register;
352     cc->gdb_write_register = riscv_cpu_gdb_write_register;
353     cc->gdb_num_core_regs = 65;
354     cc->gdb_stop_before_watchpoint = true;
355     cc->disas_set_info = riscv_cpu_disas_set_info;
356 #ifdef CONFIG_USER_ONLY
357     cc->handle_mmu_fault = riscv_cpu_handle_mmu_fault;
358 #else
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 #endif
365     /* For now, mark unmigratable: */
366     cc->vmsd = &vmstate_riscv_cpu;
367 }
368 
369 static void cpu_register(const RISCVCPUInfo *info)
370 {
371     TypeInfo type_info = {
372         .name = info->name,
373         .parent = TYPE_RISCV_CPU,
374         .instance_size = sizeof(RISCVCPU),
375         .instance_init = info->initfn,
376     };
377 
378     type_register(&type_info);
379 }
380 
381 static const TypeInfo riscv_cpu_type_info = {
382     .name = TYPE_RISCV_CPU,
383     .parent = TYPE_CPU,
384     .instance_size = sizeof(RISCVCPU),
385     .instance_init = riscv_cpu_init,
386     .abstract = false,
387     .class_size = sizeof(RISCVCPUClass),
388     .class_init = riscv_cpu_class_init,
389 };
390 
391 char *riscv_isa_string(RISCVCPU *cpu)
392 {
393     int i;
394     size_t maxlen = 5 + ctz32(cpu->env.misa);
395     char *isa_string = g_new0(char, maxlen);
396     snprintf(isa_string, maxlen, "rv%d", TARGET_LONG_BITS);
397     for (i = 0; i < sizeof(riscv_exts); i++) {
398         if (cpu->env.misa & RV(riscv_exts[i])) {
399             isa_string[strlen(isa_string)] = riscv_exts[i] - 'A' + 'a';
400 
401         }
402     }
403     return isa_string;
404 }
405 
406 void riscv_cpu_list(FILE *f, fprintf_function cpu_fprintf)
407 {
408     const RISCVCPUInfo *info = riscv_cpus;
409 
410     while (info->name) {
411         if (info->bit_widths & TARGET_LONG_BITS) {
412             (*cpu_fprintf)(f, "%s\n", info->name);
413         }
414         info++;
415     }
416 }
417 
418 static void riscv_cpu_register_types(void)
419 {
420     const RISCVCPUInfo *info = riscv_cpus;
421 
422     type_register_static(&riscv_cpu_type_info);
423 
424     while (info->name) {
425         if (info->bit_widths & TARGET_LONG_BITS) {
426             cpu_register(info);
427         }
428         info++;
429     }
430 }
431 
432 type_init(riscv_cpu_register_types)
433