1cd71c089SLaurent Vivier /* 2cd71c089SLaurent Vivier * qemu user cpu loop 3cd71c089SLaurent Vivier * 4cd71c089SLaurent Vivier * Copyright (c) 2003-2008 Fabrice Bellard 5cd71c089SLaurent Vivier * 6cd71c089SLaurent Vivier * This program is free software; you can redistribute it and/or modify 7cd71c089SLaurent Vivier * it under the terms of the GNU General Public License as published by 8cd71c089SLaurent Vivier * the Free Software Foundation; either version 2 of the License, or 9cd71c089SLaurent Vivier * (at your option) any later version. 10cd71c089SLaurent Vivier * 11cd71c089SLaurent Vivier * This program is distributed in the hope that it will be useful, 12cd71c089SLaurent Vivier * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cd71c089SLaurent Vivier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14cd71c089SLaurent Vivier * GNU General Public License for more details. 15cd71c089SLaurent Vivier * 16cd71c089SLaurent Vivier * You should have received a copy of the GNU General Public License 17cd71c089SLaurent Vivier * along with this program; if not, see <http://www.gnu.org/licenses/>. 18cd71c089SLaurent Vivier */ 19cd71c089SLaurent Vivier 20cd71c089SLaurent Vivier #include "qemu/osdep.h" 21a8d25326SMarkus Armbruster #include "qemu-common.h" 225836c3ecSKito Cheng #include "qemu/error-report.h" 23cd71c089SLaurent Vivier #include "qemu.h" 243b249d26SPeter Maydell #include "user-internals.h" 25cd71c089SLaurent Vivier #include "cpu_loop-common.h" 262113aed6SPeter Maydell #include "signal-common.h" 275836c3ecSKito Cheng #include "elf.h" 286b5fe137SPhilippe Mathieu-Daudé #include "semihosting/common-semi.h" 29cd71c089SLaurent Vivier 305a0b6d22SLaurent Vivier void cpu_loop(CPURISCVState *env) 315a0b6d22SLaurent Vivier { 323109cd98SRichard Henderson CPUState *cs = env_cpu(env); 33*8521cc21SRichard Henderson int trapnr; 345a0b6d22SLaurent Vivier target_ulong ret; 355a0b6d22SLaurent Vivier 365a0b6d22SLaurent Vivier for (;;) { 375a0b6d22SLaurent Vivier cpu_exec_start(cs); 385a0b6d22SLaurent Vivier trapnr = cpu_exec(cs); 395a0b6d22SLaurent Vivier cpu_exec_end(cs); 405a0b6d22SLaurent Vivier process_queued_cpu_work(cs); 415a0b6d22SLaurent Vivier 425a0b6d22SLaurent Vivier switch (trapnr) { 435a0b6d22SLaurent Vivier case EXCP_INTERRUPT: 445a0b6d22SLaurent Vivier /* just indicate that signals should be handled asap */ 455a0b6d22SLaurent Vivier break; 465a0b6d22SLaurent Vivier case EXCP_ATOMIC: 475a0b6d22SLaurent Vivier cpu_exec_step_atomic(cs); 485a0b6d22SLaurent Vivier break; 495a0b6d22SLaurent Vivier case RISCV_EXCP_U_ECALL: 505a0b6d22SLaurent Vivier env->pc += 4; 515a0b6d22SLaurent Vivier if (env->gpr[xA7] == TARGET_NR_arch_specific_syscall + 15) { 525a0b6d22SLaurent Vivier /* riscv_flush_icache_syscall is a no-op in QEMU as 535a0b6d22SLaurent Vivier self-modifying code is automatically detected */ 545a0b6d22SLaurent Vivier ret = 0; 555a0b6d22SLaurent Vivier } else { 565a0b6d22SLaurent Vivier ret = do_syscall(env, 575836c3ecSKito Cheng env->gpr[(env->elf_flags & EF_RISCV_RVE) 585836c3ecSKito Cheng ? xT0 : xA7], 595a0b6d22SLaurent Vivier env->gpr[xA0], 605a0b6d22SLaurent Vivier env->gpr[xA1], 615a0b6d22SLaurent Vivier env->gpr[xA2], 625a0b6d22SLaurent Vivier env->gpr[xA3], 635a0b6d22SLaurent Vivier env->gpr[xA4], 645a0b6d22SLaurent Vivier env->gpr[xA5], 655a0b6d22SLaurent Vivier 0, 0); 665a0b6d22SLaurent Vivier } 67af254a27SRichard Henderson if (ret == -QEMU_ERESTARTSYS) { 685a0b6d22SLaurent Vivier env->pc -= 4; 6957a0c938SRichard Henderson } else if (ret != -QEMU_ESIGRETURN) { 705a0b6d22SLaurent Vivier env->gpr[xA0] = ret; 715a0b6d22SLaurent Vivier } 725a0b6d22SLaurent Vivier if (cs->singlestep_enabled) { 735a0b6d22SLaurent Vivier goto gdbstep; 745a0b6d22SLaurent Vivier } 755a0b6d22SLaurent Vivier break; 765a0b6d22SLaurent Vivier case RISCV_EXCP_ILLEGAL_INST: 77*8521cc21SRichard Henderson force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); 785a0b6d22SLaurent Vivier break; 795a0b6d22SLaurent Vivier case RISCV_EXCP_BREAKPOINT: 80*8521cc21SRichard Henderson case EXCP_DEBUG: 81*8521cc21SRichard Henderson gdbstep: 82*8521cc21SRichard Henderson force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); 835a0b6d22SLaurent Vivier break; 846b80cb25SKito Cheng case RISCV_EXCP_SEMIHOST: 856b80cb25SKito Cheng env->gpr[xA0] = do_common_semihosting(cs); 866b80cb25SKito Cheng env->pc += 4; 876b80cb25SKito Cheng break; 885a0b6d22SLaurent Vivier default: 895a0b6d22SLaurent Vivier EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n", 905a0b6d22SLaurent Vivier trapnr); 915a0b6d22SLaurent Vivier exit(EXIT_FAILURE); 925a0b6d22SLaurent Vivier } 935a0b6d22SLaurent Vivier 945a0b6d22SLaurent Vivier process_pending_signals(env); 955a0b6d22SLaurent Vivier } 965a0b6d22SLaurent Vivier } 975a0b6d22SLaurent Vivier 98cd71c089SLaurent Vivier void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 99cd71c089SLaurent Vivier { 10029a0af61SRichard Henderson CPUState *cpu = env_cpu(env); 1015836c3ecSKito Cheng TaskState *ts = cpu->opaque; 1025836c3ecSKito Cheng struct image_info *info = ts->info; 1035836c3ecSKito Cheng 1045a0b6d22SLaurent Vivier env->pc = regs->sepc; 1055a0b6d22SLaurent Vivier env->gpr[xSP] = regs->sp; 1065836c3ecSKito Cheng env->elf_flags = info->elf_flags; 1075836c3ecSKito Cheng 108e91a7227SRichard Henderson if ((env->misa_ext & RVE) && !(env->elf_flags & EF_RISCV_RVE)) { 1095836c3ecSKito Cheng error_report("Incompatible ELF: RVE cpu requires RVE ABI binary"); 1105836c3ecSKito Cheng exit(EXIT_FAILURE); 1115836c3ecSKito Cheng } 1127967d1daSAlex Bennée 1137967d1daSAlex Bennée ts->stack_base = info->start_stack; 1147967d1daSAlex Bennée ts->heap_base = info->brk; 1157967d1daSAlex Bennée /* This will be filled in on the first SYS_HEAPINFO call. */ 1167967d1daSAlex Bennée ts->heap_limit = 0; 117cd71c089SLaurent Vivier } 118