]>
Commit | Line | Data |
---|---|---|
cd71c089 LV |
1 | /* |
2 | * qemu user cpu loop | |
3 | * | |
4 | * Copyright (c) 2003-2008 Fabrice Bellard | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include "qemu/osdep.h" | |
a8d25326 | 21 | #include "qemu-common.h" |
5836c3ec | 22 | #include "qemu/error-report.h" |
cd71c089 LV |
23 | #include "qemu.h" |
24 | #include "cpu_loop-common.h" | |
5836c3ec | 25 | #include "elf.h" |
6b5fe137 | 26 | #include "semihosting/common-semi.h" |
cd71c089 | 27 | |
5a0b6d22 LV |
28 | void cpu_loop(CPURISCVState *env) |
29 | { | |
3109cd98 | 30 | CPUState *cs = env_cpu(env); |
5a0b6d22 LV |
31 | int trapnr, signum, sigcode; |
32 | target_ulong sigaddr; | |
33 | target_ulong ret; | |
34 | ||
35 | for (;;) { | |
36 | cpu_exec_start(cs); | |
37 | trapnr = cpu_exec(cs); | |
38 | cpu_exec_end(cs); | |
39 | process_queued_cpu_work(cs); | |
40 | ||
41 | signum = 0; | |
42 | sigcode = 0; | |
43 | sigaddr = 0; | |
44 | ||
45 | switch (trapnr) { | |
46 | case EXCP_INTERRUPT: | |
47 | /* just indicate that signals should be handled asap */ | |
48 | break; | |
49 | case EXCP_ATOMIC: | |
50 | cpu_exec_step_atomic(cs); | |
51 | break; | |
52 | case RISCV_EXCP_U_ECALL: | |
53 | env->pc += 4; | |
54 | if (env->gpr[xA7] == TARGET_NR_arch_specific_syscall + 15) { | |
55 | /* riscv_flush_icache_syscall is a no-op in QEMU as | |
56 | self-modifying code is automatically detected */ | |
57 | ret = 0; | |
58 | } else { | |
59 | ret = do_syscall(env, | |
5836c3ec KC |
60 | env->gpr[(env->elf_flags & EF_RISCV_RVE) |
61 | ? xT0 : xA7], | |
5a0b6d22 LV |
62 | env->gpr[xA0], |
63 | env->gpr[xA1], | |
64 | env->gpr[xA2], | |
65 | env->gpr[xA3], | |
66 | env->gpr[xA4], | |
67 | env->gpr[xA5], | |
68 | 0, 0); | |
69 | } | |
70 | if (ret == -TARGET_ERESTARTSYS) { | |
71 | env->pc -= 4; | |
72 | } else if (ret != -TARGET_QEMU_ESIGRETURN) { | |
73 | env->gpr[xA0] = ret; | |
74 | } | |
75 | if (cs->singlestep_enabled) { | |
76 | goto gdbstep; | |
77 | } | |
78 | break; | |
79 | case RISCV_EXCP_ILLEGAL_INST: | |
80 | signum = TARGET_SIGILL; | |
81 | sigcode = TARGET_ILL_ILLOPC; | |
82 | break; | |
83 | case RISCV_EXCP_BREAKPOINT: | |
84 | signum = TARGET_SIGTRAP; | |
85 | sigcode = TARGET_TRAP_BRKPT; | |
86 | sigaddr = env->pc; | |
87 | break; | |
88 | case RISCV_EXCP_INST_PAGE_FAULT: | |
89 | case RISCV_EXCP_LOAD_PAGE_FAULT: | |
90 | case RISCV_EXCP_STORE_PAGE_FAULT: | |
91 | signum = TARGET_SIGSEGV; | |
92 | sigcode = TARGET_SEGV_MAPERR; | |
2921343b | 93 | sigaddr = env->badaddr; |
5a0b6d22 | 94 | break; |
6b80cb25 KC |
95 | case RISCV_EXCP_SEMIHOST: |
96 | env->gpr[xA0] = do_common_semihosting(cs); | |
97 | env->pc += 4; | |
98 | break; | |
5a0b6d22 LV |
99 | case EXCP_DEBUG: |
100 | gdbstep: | |
b10089a1 | 101 | signum = TARGET_SIGTRAP; |
5a0b6d22 LV |
102 | sigcode = TARGET_TRAP_BRKPT; |
103 | break; | |
104 | default: | |
105 | EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n", | |
106 | trapnr); | |
107 | exit(EXIT_FAILURE); | |
108 | } | |
109 | ||
110 | if (signum) { | |
111 | target_siginfo_t info = { | |
112 | .si_signo = signum, | |
113 | .si_errno = 0, | |
114 | .si_code = sigcode, | |
115 | ._sifields._sigfault._addr = sigaddr | |
116 | }; | |
2921343b | 117 | queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); |
5a0b6d22 LV |
118 | } |
119 | ||
120 | process_pending_signals(env); | |
121 | } | |
122 | } | |
123 | ||
cd71c089 LV |
124 | void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) |
125 | { | |
29a0af61 | 126 | CPUState *cpu = env_cpu(env); |
5836c3ec KC |
127 | TaskState *ts = cpu->opaque; |
128 | struct image_info *info = ts->info; | |
129 | ||
5a0b6d22 LV |
130 | env->pc = regs->sepc; |
131 | env->gpr[xSP] = regs->sp; | |
5836c3ec KC |
132 | env->elf_flags = info->elf_flags; |
133 | ||
134 | if ((env->misa & RVE) && !(env->elf_flags & EF_RISCV_RVE)) { | |
135 | error_report("Incompatible ELF: RVE cpu requires RVE ABI binary"); | |
136 | exit(EXIT_FAILURE); | |
137 | } | |
cd71c089 | 138 | } |