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" 215836c3ecSKito Cheng #include "qemu/error-report.h" 22cd71c089SLaurent Vivier #include "qemu.h" 233b249d26SPeter Maydell #include "user-internals.h" 24cd71c089SLaurent Vivier #include "cpu_loop-common.h" 252113aed6SPeter Maydell #include "signal-common.h" 265836c3ecSKito Cheng #include "elf.h" 276b5fe137SPhilippe Mathieu-Daudé #include "semihosting/common-semi.h" 28cd71c089SLaurent Vivier 295a0b6d22SLaurent Vivier void cpu_loop(CPURISCVState *env) 305a0b6d22SLaurent Vivier { 313109cd98SRichard Henderson CPUState *cs = env_cpu(env); 328521cc21SRichard Henderson int trapnr; 335a0b6d22SLaurent Vivier target_ulong ret; 345a0b6d22SLaurent Vivier 355a0b6d22SLaurent Vivier for (;;) { 365a0b6d22SLaurent Vivier cpu_exec_start(cs); 375a0b6d22SLaurent Vivier trapnr = cpu_exec(cs); 385a0b6d22SLaurent Vivier cpu_exec_end(cs); 395a0b6d22SLaurent Vivier process_queued_cpu_work(cs); 405a0b6d22SLaurent Vivier 415a0b6d22SLaurent Vivier switch (trapnr) { 425a0b6d22SLaurent Vivier case EXCP_INTERRUPT: 435a0b6d22SLaurent Vivier /* just indicate that signals should be handled asap */ 445a0b6d22SLaurent Vivier break; 455a0b6d22SLaurent Vivier case EXCP_ATOMIC: 465a0b6d22SLaurent Vivier cpu_exec_step_atomic(cs); 475a0b6d22SLaurent Vivier break; 485a0b6d22SLaurent Vivier case RISCV_EXCP_U_ECALL: 495a0b6d22SLaurent Vivier env->pc += 4; 50*5281a197SLaurent Vivier if (env->gpr[xA7] == TARGET_NR_riscv_flush_icache) { 515a0b6d22SLaurent Vivier /* riscv_flush_icache_syscall is a no-op in QEMU as 525a0b6d22SLaurent Vivier self-modifying code is automatically detected */ 535a0b6d22SLaurent Vivier ret = 0; 545a0b6d22SLaurent Vivier } else { 555a0b6d22SLaurent Vivier ret = do_syscall(env, 565836c3ecSKito Cheng env->gpr[(env->elf_flags & EF_RISCV_RVE) 575836c3ecSKito Cheng ? xT0 : xA7], 585a0b6d22SLaurent Vivier env->gpr[xA0], 595a0b6d22SLaurent Vivier env->gpr[xA1], 605a0b6d22SLaurent Vivier env->gpr[xA2], 615a0b6d22SLaurent Vivier env->gpr[xA3], 625a0b6d22SLaurent Vivier env->gpr[xA4], 635a0b6d22SLaurent Vivier env->gpr[xA5], 645a0b6d22SLaurent Vivier 0, 0); 655a0b6d22SLaurent Vivier } 66af254a27SRichard Henderson if (ret == -QEMU_ERESTARTSYS) { 675a0b6d22SLaurent Vivier env->pc -= 4; 6857a0c938SRichard Henderson } else if (ret != -QEMU_ESIGRETURN) { 695a0b6d22SLaurent Vivier env->gpr[xA0] = ret; 705a0b6d22SLaurent Vivier } 715a0b6d22SLaurent Vivier if (cs->singlestep_enabled) { 725a0b6d22SLaurent Vivier goto gdbstep; 735a0b6d22SLaurent Vivier } 745a0b6d22SLaurent Vivier break; 755a0b6d22SLaurent Vivier case RISCV_EXCP_ILLEGAL_INST: 768521cc21SRichard Henderson force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); 775a0b6d22SLaurent Vivier break; 785a0b6d22SLaurent Vivier case RISCV_EXCP_BREAKPOINT: 798521cc21SRichard Henderson case EXCP_DEBUG: 808521cc21SRichard Henderson gdbstep: 818521cc21SRichard Henderson force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); 825a0b6d22SLaurent Vivier break; 836b80cb25SKito Cheng case RISCV_EXCP_SEMIHOST: 84ed3a06b1SRichard Henderson do_common_semihosting(cs); 856b80cb25SKito Cheng env->pc += 4; 866b80cb25SKito Cheng break; 875a0b6d22SLaurent Vivier default: 885a0b6d22SLaurent Vivier EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n", 895a0b6d22SLaurent Vivier trapnr); 905a0b6d22SLaurent Vivier exit(EXIT_FAILURE); 915a0b6d22SLaurent Vivier } 925a0b6d22SLaurent Vivier 935a0b6d22SLaurent Vivier process_pending_signals(env); 945a0b6d22SLaurent Vivier } 955a0b6d22SLaurent Vivier } 965a0b6d22SLaurent Vivier 97cd71c089SLaurent Vivier void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 98cd71c089SLaurent Vivier { 9929a0af61SRichard Henderson CPUState *cpu = env_cpu(env); 100e4e5cb4aSIlya Leoshkevich TaskState *ts = get_task_state(cpu); 1015836c3ecSKito Cheng struct image_info *info = ts->info; 1025836c3ecSKito Cheng 1035a0b6d22SLaurent Vivier env->pc = regs->sepc; 1045a0b6d22SLaurent Vivier env->gpr[xSP] = regs->sp; 1055836c3ecSKito Cheng env->elf_flags = info->elf_flags; 1065836c3ecSKito Cheng 107e91a7227SRichard Henderson if ((env->misa_ext & RVE) && !(env->elf_flags & EF_RISCV_RVE)) { 1085836c3ecSKito Cheng error_report("Incompatible ELF: RVE cpu requires RVE ABI binary"); 1095836c3ecSKito Cheng exit(EXIT_FAILURE); 1105836c3ecSKito Cheng } 1117967d1daSAlex Bennée 1127967d1daSAlex Bennée ts->stack_base = info->start_stack; 1137967d1daSAlex Bennée ts->heap_base = info->brk; 1147967d1daSAlex Bennée /* This will be filled in on the first SYS_HEAPINFO call. */ 1157967d1daSAlex Bennée ts->heap_limit = 0; 116cd71c089SLaurent Vivier } 117