191654e61SYifei Jiang /* 291654e61SYifei Jiang * RISC-V implementation of KVM hooks 391654e61SYifei Jiang * 491654e61SYifei Jiang * Copyright (c) 2020 Huawei Technologies Co., Ltd 591654e61SYifei Jiang * 691654e61SYifei Jiang * This program is free software; you can redistribute it and/or modify it 791654e61SYifei Jiang * under the terms and conditions of the GNU General Public License, 891654e61SYifei Jiang * version 2 or later, as published by the Free Software Foundation. 991654e61SYifei Jiang * 1091654e61SYifei Jiang * This program is distributed in the hope it will be useful, but WITHOUT 1191654e61SYifei Jiang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1291654e61SYifei Jiang * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1391654e61SYifei Jiang * more details. 1491654e61SYifei Jiang * 1591654e61SYifei Jiang * You should have received a copy of the GNU General Public License along with 1691654e61SYifei Jiang * this program. If not, see <http://www.gnu.org/licenses/>. 1791654e61SYifei Jiang */ 1891654e61SYifei Jiang 1991654e61SYifei Jiang #include "qemu/osdep.h" 2091654e61SYifei Jiang #include <sys/ioctl.h> 2191654e61SYifei Jiang 2291654e61SYifei Jiang #include <linux/kvm.h> 2391654e61SYifei Jiang 2491654e61SYifei Jiang #include "qemu-common.h" 2591654e61SYifei Jiang #include "qemu/timer.h" 2691654e61SYifei Jiang #include "qemu/error-report.h" 2791654e61SYifei Jiang #include "qemu/main-loop.h" 2891654e61SYifei Jiang #include "sysemu/sysemu.h" 2991654e61SYifei Jiang #include "sysemu/kvm.h" 3091654e61SYifei Jiang #include "sysemu/kvm_int.h" 3191654e61SYifei Jiang #include "cpu.h" 3291654e61SYifei Jiang #include "trace.h" 3391654e61SYifei Jiang #include "hw/pci/pci.h" 3491654e61SYifei Jiang #include "exec/memattrs.h" 3591654e61SYifei Jiang #include "exec/address-spaces.h" 3691654e61SYifei Jiang #include "hw/boards.h" 3791654e61SYifei Jiang #include "hw/irq.h" 3891654e61SYifei Jiang #include "qemu/log.h" 3991654e61SYifei Jiang #include "hw/loader.h" 40ad40be27SYifei Jiang #include "kvm_riscv.h" 414eb47125SYifei Jiang #include "sbi_ecall_interface.h" 424eb47125SYifei Jiang #include "chardev/char-fe.h" 4327abe66fSYifei Jiang #include "migration/migration.h" 44*9ad3e016SYifei Jiang #include "sysemu/runstate.h" 4591654e61SYifei Jiang 460a312b85SYifei Jiang static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, 470a312b85SYifei Jiang uint64_t idx) 480a312b85SYifei Jiang { 490a312b85SYifei Jiang uint64_t id = KVM_REG_RISCV | type | idx; 500a312b85SYifei Jiang 510a312b85SYifei Jiang switch (riscv_cpu_mxl(env)) { 520a312b85SYifei Jiang case MXL_RV32: 530a312b85SYifei Jiang id |= KVM_REG_SIZE_U32; 540a312b85SYifei Jiang break; 550a312b85SYifei Jiang case MXL_RV64: 560a312b85SYifei Jiang id |= KVM_REG_SIZE_U64; 570a312b85SYifei Jiang break; 580a312b85SYifei Jiang default: 590a312b85SYifei Jiang g_assert_not_reached(); 600a312b85SYifei Jiang } 610a312b85SYifei Jiang return id; 620a312b85SYifei Jiang } 630a312b85SYifei Jiang 64937f0b45SYifei Jiang #define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ 65937f0b45SYifei Jiang KVM_REG_RISCV_CORE_REG(name)) 66937f0b45SYifei Jiang 67937f0b45SYifei Jiang #define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ 68937f0b45SYifei Jiang KVM_REG_RISCV_CSR_REG(name)) 69937f0b45SYifei Jiang 7027abe66fSYifei Jiang #define RISCV_TIMER_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_TIMER, \ 7127abe66fSYifei Jiang KVM_REG_RISCV_TIMER_REG(name)) 7227abe66fSYifei Jiang 73937f0b45SYifei Jiang #define RISCV_FP_F_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx) 74937f0b45SYifei Jiang 75937f0b45SYifei Jiang #define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) 76937f0b45SYifei Jiang 77937f0b45SYifei Jiang #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ 78937f0b45SYifei Jiang do { \ 79937f0b45SYifei Jiang int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ 80937f0b45SYifei Jiang if (ret) { \ 81937f0b45SYifei Jiang return ret; \ 82937f0b45SYifei Jiang } \ 83937f0b45SYifei Jiang } while (0) 84937f0b45SYifei Jiang 859997cc1eSYifei Jiang #define KVM_RISCV_SET_CSR(cs, env, csr, reg) \ 869997cc1eSYifei Jiang do { \ 879997cc1eSYifei Jiang int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ 889997cc1eSYifei Jiang if (ret) { \ 899997cc1eSYifei Jiang return ret; \ 909997cc1eSYifei Jiang } \ 919997cc1eSYifei Jiang } while (0) 929997cc1eSYifei Jiang 9327abe66fSYifei Jiang #define KVM_RISCV_GET_TIMER(cs, env, name, reg) \ 9427abe66fSYifei Jiang do { \ 9527abe66fSYifei Jiang int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(env, name), ®); \ 9627abe66fSYifei Jiang if (ret) { \ 9727abe66fSYifei Jiang abort(); \ 9827abe66fSYifei Jiang } \ 9927abe66fSYifei Jiang } while (0) 10027abe66fSYifei Jiang 10127abe66fSYifei Jiang #define KVM_RISCV_SET_TIMER(cs, env, name, reg) \ 10227abe66fSYifei Jiang do { \ 10327abe66fSYifei Jiang int ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(env, time), ®); \ 10427abe66fSYifei Jiang if (ret) { \ 10527abe66fSYifei Jiang abort(); \ 10627abe66fSYifei Jiang } \ 10727abe66fSYifei Jiang } while (0) 10827abe66fSYifei Jiang 109937f0b45SYifei Jiang static int kvm_riscv_get_regs_core(CPUState *cs) 110937f0b45SYifei Jiang { 111937f0b45SYifei Jiang int ret = 0; 112937f0b45SYifei Jiang int i; 113937f0b45SYifei Jiang target_ulong reg; 114937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 115937f0b45SYifei Jiang 116937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); 117937f0b45SYifei Jiang if (ret) { 118937f0b45SYifei Jiang return ret; 119937f0b45SYifei Jiang } 120937f0b45SYifei Jiang env->pc = reg; 121937f0b45SYifei Jiang 122937f0b45SYifei Jiang for (i = 1; i < 32; i++) { 123937f0b45SYifei Jiang uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); 124937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, id, ®); 125937f0b45SYifei Jiang if (ret) { 126937f0b45SYifei Jiang return ret; 127937f0b45SYifei Jiang } 128937f0b45SYifei Jiang env->gpr[i] = reg; 129937f0b45SYifei Jiang } 130937f0b45SYifei Jiang 131937f0b45SYifei Jiang return ret; 132937f0b45SYifei Jiang } 133937f0b45SYifei Jiang 1349997cc1eSYifei Jiang static int kvm_riscv_put_regs_core(CPUState *cs) 1359997cc1eSYifei Jiang { 1369997cc1eSYifei Jiang int ret = 0; 1379997cc1eSYifei Jiang int i; 1389997cc1eSYifei Jiang target_ulong reg; 1399997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 1409997cc1eSYifei Jiang 1419997cc1eSYifei Jiang reg = env->pc; 1429997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); 1439997cc1eSYifei Jiang if (ret) { 1449997cc1eSYifei Jiang return ret; 1459997cc1eSYifei Jiang } 1469997cc1eSYifei Jiang 1479997cc1eSYifei Jiang for (i = 1; i < 32; i++) { 1489997cc1eSYifei Jiang uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); 1499997cc1eSYifei Jiang reg = env->gpr[i]; 1509997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, id, ®); 1519997cc1eSYifei Jiang if (ret) { 1529997cc1eSYifei Jiang return ret; 1539997cc1eSYifei Jiang } 1549997cc1eSYifei Jiang } 1559997cc1eSYifei Jiang 1569997cc1eSYifei Jiang return ret; 1579997cc1eSYifei Jiang } 1589997cc1eSYifei Jiang 159937f0b45SYifei Jiang static int kvm_riscv_get_regs_csr(CPUState *cs) 160937f0b45SYifei Jiang { 161937f0b45SYifei Jiang int ret = 0; 162937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 163937f0b45SYifei Jiang 164937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus); 165937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sie, env->mie); 166937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec); 167937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch); 168937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc); 169937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, scause, env->scause); 170937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, stval, env->stval); 171937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sip, env->mip); 172937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, satp, env->satp); 173937f0b45SYifei Jiang return ret; 174937f0b45SYifei Jiang } 175937f0b45SYifei Jiang 1769997cc1eSYifei Jiang static int kvm_riscv_put_regs_csr(CPUState *cs) 1779997cc1eSYifei Jiang { 1789997cc1eSYifei Jiang int ret = 0; 1799997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 1809997cc1eSYifei Jiang 1819997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus); 1829997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sie, env->mie); 1839997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec); 1849997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch); 1859997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc); 1869997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, scause, env->scause); 1879997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, stval, env->stval); 1889997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sip, env->mip); 1899997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, satp, env->satp); 1909997cc1eSYifei Jiang 1919997cc1eSYifei Jiang return ret; 1929997cc1eSYifei Jiang } 1939997cc1eSYifei Jiang 194937f0b45SYifei Jiang static int kvm_riscv_get_regs_fp(CPUState *cs) 195937f0b45SYifei Jiang { 196937f0b45SYifei Jiang int ret = 0; 197937f0b45SYifei Jiang int i; 198937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 199937f0b45SYifei Jiang 200937f0b45SYifei Jiang if (riscv_has_ext(env, RVD)) { 201937f0b45SYifei Jiang uint64_t reg; 202937f0b45SYifei Jiang for (i = 0; i < 32; i++) { 203937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), ®); 204937f0b45SYifei Jiang if (ret) { 205937f0b45SYifei Jiang return ret; 206937f0b45SYifei Jiang } 207937f0b45SYifei Jiang env->fpr[i] = reg; 208937f0b45SYifei Jiang } 209937f0b45SYifei Jiang return ret; 210937f0b45SYifei Jiang } 211937f0b45SYifei Jiang 212937f0b45SYifei Jiang if (riscv_has_ext(env, RVF)) { 213937f0b45SYifei Jiang uint32_t reg; 214937f0b45SYifei Jiang for (i = 0; i < 32; i++) { 215937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), ®); 216937f0b45SYifei Jiang if (ret) { 217937f0b45SYifei Jiang return ret; 218937f0b45SYifei Jiang } 219937f0b45SYifei Jiang env->fpr[i] = reg; 220937f0b45SYifei Jiang } 221937f0b45SYifei Jiang return ret; 222937f0b45SYifei Jiang } 223937f0b45SYifei Jiang 224937f0b45SYifei Jiang return ret; 225937f0b45SYifei Jiang } 226937f0b45SYifei Jiang 2279997cc1eSYifei Jiang static int kvm_riscv_put_regs_fp(CPUState *cs) 2289997cc1eSYifei Jiang { 2299997cc1eSYifei Jiang int ret = 0; 2309997cc1eSYifei Jiang int i; 2319997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 2329997cc1eSYifei Jiang 2339997cc1eSYifei Jiang if (riscv_has_ext(env, RVD)) { 2349997cc1eSYifei Jiang uint64_t reg; 2359997cc1eSYifei Jiang for (i = 0; i < 32; i++) { 2369997cc1eSYifei Jiang reg = env->fpr[i]; 2379997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), ®); 2389997cc1eSYifei Jiang if (ret) { 2399997cc1eSYifei Jiang return ret; 2409997cc1eSYifei Jiang } 2419997cc1eSYifei Jiang } 2429997cc1eSYifei Jiang return ret; 2439997cc1eSYifei Jiang } 2449997cc1eSYifei Jiang 2459997cc1eSYifei Jiang if (riscv_has_ext(env, RVF)) { 2469997cc1eSYifei Jiang uint32_t reg; 2479997cc1eSYifei Jiang for (i = 0; i < 32; i++) { 2489997cc1eSYifei Jiang reg = env->fpr[i]; 2499997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), ®); 2509997cc1eSYifei Jiang if (ret) { 2519997cc1eSYifei Jiang return ret; 2529997cc1eSYifei Jiang } 2539997cc1eSYifei Jiang } 2549997cc1eSYifei Jiang return ret; 2559997cc1eSYifei Jiang } 2569997cc1eSYifei Jiang 2579997cc1eSYifei Jiang return ret; 2589997cc1eSYifei Jiang } 2599997cc1eSYifei Jiang 26027abe66fSYifei Jiang static void kvm_riscv_get_regs_timer(CPUState *cs) 26127abe66fSYifei Jiang { 26227abe66fSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 26327abe66fSYifei Jiang 26427abe66fSYifei Jiang if (env->kvm_timer_dirty) { 26527abe66fSYifei Jiang return; 26627abe66fSYifei Jiang } 26727abe66fSYifei Jiang 26827abe66fSYifei Jiang KVM_RISCV_GET_TIMER(cs, env, time, env->kvm_timer_time); 26927abe66fSYifei Jiang KVM_RISCV_GET_TIMER(cs, env, compare, env->kvm_timer_compare); 27027abe66fSYifei Jiang KVM_RISCV_GET_TIMER(cs, env, state, env->kvm_timer_state); 27127abe66fSYifei Jiang KVM_RISCV_GET_TIMER(cs, env, frequency, env->kvm_timer_frequency); 27227abe66fSYifei Jiang 27327abe66fSYifei Jiang env->kvm_timer_dirty = true; 27427abe66fSYifei Jiang } 27527abe66fSYifei Jiang 27627abe66fSYifei Jiang static void kvm_riscv_put_regs_timer(CPUState *cs) 27727abe66fSYifei Jiang { 27827abe66fSYifei Jiang uint64_t reg; 27927abe66fSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 28027abe66fSYifei Jiang 28127abe66fSYifei Jiang if (!env->kvm_timer_dirty) { 28227abe66fSYifei Jiang return; 28327abe66fSYifei Jiang } 28427abe66fSYifei Jiang 28527abe66fSYifei Jiang KVM_RISCV_SET_TIMER(cs, env, time, env->kvm_timer_time); 28627abe66fSYifei Jiang KVM_RISCV_SET_TIMER(cs, env, compare, env->kvm_timer_compare); 28727abe66fSYifei Jiang 28827abe66fSYifei Jiang /* 28927abe66fSYifei Jiang * To set register of RISCV_TIMER_REG(state) will occur a error from KVM 29027abe66fSYifei Jiang * on env->kvm_timer_state == 0, It's better to adapt in KVM, but it 29127abe66fSYifei Jiang * doesn't matter that adaping in QEMU now. 29227abe66fSYifei Jiang * TODO If KVM changes, adapt here. 29327abe66fSYifei Jiang */ 29427abe66fSYifei Jiang if (env->kvm_timer_state) { 29527abe66fSYifei Jiang KVM_RISCV_SET_TIMER(cs, env, state, env->kvm_timer_state); 29627abe66fSYifei Jiang } 29727abe66fSYifei Jiang 29827abe66fSYifei Jiang /* 29927abe66fSYifei Jiang * For now, migration will not work between Hosts with different timer 30027abe66fSYifei Jiang * frequency. Therefore, we should check whether they are the same here 30127abe66fSYifei Jiang * during the migration. 30227abe66fSYifei Jiang */ 30327abe66fSYifei Jiang if (migration_is_running(migrate_get_current()->state)) { 30427abe66fSYifei Jiang KVM_RISCV_GET_TIMER(cs, env, frequency, reg); 30527abe66fSYifei Jiang if (reg != env->kvm_timer_frequency) { 30627abe66fSYifei Jiang error_report("Dst Hosts timer frequency != Src Hosts"); 30727abe66fSYifei Jiang } 30827abe66fSYifei Jiang } 30927abe66fSYifei Jiang 31027abe66fSYifei Jiang env->kvm_timer_dirty = false; 31127abe66fSYifei Jiang } 3129997cc1eSYifei Jiang 31391654e61SYifei Jiang const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 31491654e61SYifei Jiang KVM_CAP_LAST_INFO 31591654e61SYifei Jiang }; 31691654e61SYifei Jiang 31791654e61SYifei Jiang int kvm_arch_get_registers(CPUState *cs) 31891654e61SYifei Jiang { 319937f0b45SYifei Jiang int ret = 0; 320937f0b45SYifei Jiang 321937f0b45SYifei Jiang ret = kvm_riscv_get_regs_core(cs); 322937f0b45SYifei Jiang if (ret) { 323937f0b45SYifei Jiang return ret; 324937f0b45SYifei Jiang } 325937f0b45SYifei Jiang 326937f0b45SYifei Jiang ret = kvm_riscv_get_regs_csr(cs); 327937f0b45SYifei Jiang if (ret) { 328937f0b45SYifei Jiang return ret; 329937f0b45SYifei Jiang } 330937f0b45SYifei Jiang 331937f0b45SYifei Jiang ret = kvm_riscv_get_regs_fp(cs); 332937f0b45SYifei Jiang if (ret) { 333937f0b45SYifei Jiang return ret; 334937f0b45SYifei Jiang } 335937f0b45SYifei Jiang 336937f0b45SYifei Jiang return ret; 33791654e61SYifei Jiang } 33891654e61SYifei Jiang 33991654e61SYifei Jiang int kvm_arch_put_registers(CPUState *cs, int level) 34091654e61SYifei Jiang { 3419997cc1eSYifei Jiang int ret = 0; 3429997cc1eSYifei Jiang 3439997cc1eSYifei Jiang ret = kvm_riscv_put_regs_core(cs); 3449997cc1eSYifei Jiang if (ret) { 3459997cc1eSYifei Jiang return ret; 3469997cc1eSYifei Jiang } 3479997cc1eSYifei Jiang 3489997cc1eSYifei Jiang ret = kvm_riscv_put_regs_csr(cs); 3499997cc1eSYifei Jiang if (ret) { 3509997cc1eSYifei Jiang return ret; 3519997cc1eSYifei Jiang } 3529997cc1eSYifei Jiang 3539997cc1eSYifei Jiang ret = kvm_riscv_put_regs_fp(cs); 3549997cc1eSYifei Jiang if (ret) { 3559997cc1eSYifei Jiang return ret; 3569997cc1eSYifei Jiang } 3579997cc1eSYifei Jiang 3589997cc1eSYifei Jiang return ret; 35991654e61SYifei Jiang } 36091654e61SYifei Jiang 36191654e61SYifei Jiang int kvm_arch_release_virq_post(int virq) 36291654e61SYifei Jiang { 36391654e61SYifei Jiang return 0; 36491654e61SYifei Jiang } 36591654e61SYifei Jiang 36691654e61SYifei Jiang int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 36791654e61SYifei Jiang uint64_t address, uint32_t data, PCIDevice *dev) 36891654e61SYifei Jiang { 36991654e61SYifei Jiang return 0; 37091654e61SYifei Jiang } 37191654e61SYifei Jiang 37291654e61SYifei Jiang int kvm_arch_destroy_vcpu(CPUState *cs) 37391654e61SYifei Jiang { 37491654e61SYifei Jiang return 0; 37591654e61SYifei Jiang } 37691654e61SYifei Jiang 37791654e61SYifei Jiang unsigned long kvm_arch_vcpu_id(CPUState *cpu) 37891654e61SYifei Jiang { 37991654e61SYifei Jiang return cpu->cpu_index; 38091654e61SYifei Jiang } 38191654e61SYifei Jiang 382*9ad3e016SYifei Jiang static void kvm_riscv_vm_state_change(void *opaque, bool running, 383*9ad3e016SYifei Jiang RunState state) 384*9ad3e016SYifei Jiang { 385*9ad3e016SYifei Jiang CPUState *cs = opaque; 386*9ad3e016SYifei Jiang 387*9ad3e016SYifei Jiang if (running) { 388*9ad3e016SYifei Jiang kvm_riscv_put_regs_timer(cs); 389*9ad3e016SYifei Jiang } else { 390*9ad3e016SYifei Jiang kvm_riscv_get_regs_timer(cs); 391*9ad3e016SYifei Jiang } 392*9ad3e016SYifei Jiang } 393*9ad3e016SYifei Jiang 39491654e61SYifei Jiang void kvm_arch_init_irq_routing(KVMState *s) 39591654e61SYifei Jiang { 39691654e61SYifei Jiang } 39791654e61SYifei Jiang 39891654e61SYifei Jiang int kvm_arch_init_vcpu(CPUState *cs) 39991654e61SYifei Jiang { 4000a312b85SYifei Jiang int ret = 0; 4010a312b85SYifei Jiang target_ulong isa; 4020a312b85SYifei Jiang RISCVCPU *cpu = RISCV_CPU(cs); 4030a312b85SYifei Jiang CPURISCVState *env = &cpu->env; 4040a312b85SYifei Jiang uint64_t id; 4050a312b85SYifei Jiang 406*9ad3e016SYifei Jiang qemu_add_vm_change_state_handler(kvm_riscv_vm_state_change, cs); 407*9ad3e016SYifei Jiang 4080a312b85SYifei Jiang id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, 4090a312b85SYifei Jiang KVM_REG_RISCV_CONFIG_REG(isa)); 4100a312b85SYifei Jiang ret = kvm_get_one_reg(cs, id, &isa); 4110a312b85SYifei Jiang if (ret) { 4120a312b85SYifei Jiang return ret; 4130a312b85SYifei Jiang } 4140a312b85SYifei Jiang env->misa_ext = isa; 4150a312b85SYifei Jiang 4160a312b85SYifei Jiang return ret; 41791654e61SYifei Jiang } 41891654e61SYifei Jiang 41991654e61SYifei Jiang int kvm_arch_msi_data_to_gsi(uint32_t data) 42091654e61SYifei Jiang { 42191654e61SYifei Jiang abort(); 42291654e61SYifei Jiang } 42391654e61SYifei Jiang 42491654e61SYifei Jiang int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 42591654e61SYifei Jiang int vector, PCIDevice *dev) 42691654e61SYifei Jiang { 42791654e61SYifei Jiang return 0; 42891654e61SYifei Jiang } 42991654e61SYifei Jiang 43091654e61SYifei Jiang int kvm_arch_init(MachineState *ms, KVMState *s) 43191654e61SYifei Jiang { 43291654e61SYifei Jiang return 0; 43391654e61SYifei Jiang } 43491654e61SYifei Jiang 43591654e61SYifei Jiang int kvm_arch_irqchip_create(KVMState *s) 43691654e61SYifei Jiang { 43791654e61SYifei Jiang return 0; 43891654e61SYifei Jiang } 43991654e61SYifei Jiang 44091654e61SYifei Jiang int kvm_arch_process_async_events(CPUState *cs) 44191654e61SYifei Jiang { 44291654e61SYifei Jiang return 0; 44391654e61SYifei Jiang } 44491654e61SYifei Jiang 44591654e61SYifei Jiang void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 44691654e61SYifei Jiang { 44791654e61SYifei Jiang } 44891654e61SYifei Jiang 44991654e61SYifei Jiang MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 45091654e61SYifei Jiang { 45191654e61SYifei Jiang return MEMTXATTRS_UNSPECIFIED; 45291654e61SYifei Jiang } 45391654e61SYifei Jiang 45491654e61SYifei Jiang bool kvm_arch_stop_on_emulation_error(CPUState *cs) 45591654e61SYifei Jiang { 45691654e61SYifei Jiang return true; 45791654e61SYifei Jiang } 45891654e61SYifei Jiang 4594eb47125SYifei Jiang static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run) 4604eb47125SYifei Jiang { 4614eb47125SYifei Jiang int ret = 0; 4624eb47125SYifei Jiang unsigned char ch; 4634eb47125SYifei Jiang switch (run->riscv_sbi.extension_id) { 4644eb47125SYifei Jiang case SBI_EXT_0_1_CONSOLE_PUTCHAR: 4654eb47125SYifei Jiang ch = run->riscv_sbi.args[0]; 4664eb47125SYifei Jiang qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch)); 4674eb47125SYifei Jiang break; 4684eb47125SYifei Jiang case SBI_EXT_0_1_CONSOLE_GETCHAR: 4694eb47125SYifei Jiang ret = qemu_chr_fe_read_all(serial_hd(0)->be, &ch, sizeof(ch)); 4704eb47125SYifei Jiang if (ret == sizeof(ch)) { 4714eb47125SYifei Jiang run->riscv_sbi.args[0] = ch; 4724eb47125SYifei Jiang } else { 4734eb47125SYifei Jiang run->riscv_sbi.args[0] = -1; 4744eb47125SYifei Jiang } 4754eb47125SYifei Jiang break; 4764eb47125SYifei Jiang default: 4774eb47125SYifei Jiang qemu_log_mask(LOG_UNIMP, 4784eb47125SYifei Jiang "%s: un-handled SBI EXIT, specific reasons is %lu\n", 4794eb47125SYifei Jiang __func__, run->riscv_sbi.extension_id); 4804eb47125SYifei Jiang ret = -1; 4814eb47125SYifei Jiang break; 4824eb47125SYifei Jiang } 4834eb47125SYifei Jiang return ret; 4844eb47125SYifei Jiang } 4854eb47125SYifei Jiang 48691654e61SYifei Jiang int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 48791654e61SYifei Jiang { 4884eb47125SYifei Jiang int ret = 0; 4894eb47125SYifei Jiang switch (run->exit_reason) { 4904eb47125SYifei Jiang case KVM_EXIT_RISCV_SBI: 4914eb47125SYifei Jiang ret = kvm_riscv_handle_sbi(cs, run); 4924eb47125SYifei Jiang break; 4934eb47125SYifei Jiang default: 4944eb47125SYifei Jiang qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", 4954eb47125SYifei Jiang __func__, run->exit_reason); 4964eb47125SYifei Jiang ret = -1; 4974eb47125SYifei Jiang break; 4984eb47125SYifei Jiang } 4994eb47125SYifei Jiang return ret; 50091654e61SYifei Jiang } 50191654e61SYifei Jiang 502ad40be27SYifei Jiang void kvm_riscv_reset_vcpu(RISCVCPU *cpu) 503ad40be27SYifei Jiang { 504ad40be27SYifei Jiang CPURISCVState *env = &cpu->env; 505ad40be27SYifei Jiang 506ad40be27SYifei Jiang if (!kvm_enabled()) { 507ad40be27SYifei Jiang return; 508ad40be27SYifei Jiang } 509ad40be27SYifei Jiang env->pc = cpu->env.kernel_addr; 510ad40be27SYifei Jiang env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ 511ad40be27SYifei Jiang env->gpr[11] = cpu->env.fdt_addr; /* a1 */ 512ad40be27SYifei Jiang env->satp = 0; 513ad40be27SYifei Jiang } 514ad40be27SYifei Jiang 5152b650fbbSYifei Jiang void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level) 5162b650fbbSYifei Jiang { 5172b650fbbSYifei Jiang int ret; 5182b650fbbSYifei Jiang unsigned virq = level ? KVM_INTERRUPT_SET : KVM_INTERRUPT_UNSET; 5192b650fbbSYifei Jiang 5202b650fbbSYifei Jiang if (irq != IRQ_S_EXT) { 5212b650fbbSYifei Jiang perror("kvm riscv set irq != IRQ_S_EXT\n"); 5222b650fbbSYifei Jiang abort(); 5232b650fbbSYifei Jiang } 5242b650fbbSYifei Jiang 5252b650fbbSYifei Jiang ret = kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); 5262b650fbbSYifei Jiang if (ret < 0) { 5272b650fbbSYifei Jiang perror("Set irq failed"); 5282b650fbbSYifei Jiang abort(); 5292b650fbbSYifei Jiang } 5302b650fbbSYifei Jiang } 5312b650fbbSYifei Jiang 53291654e61SYifei Jiang bool kvm_arch_cpu_check_are_resettable(void) 53391654e61SYifei Jiang { 53491654e61SYifei Jiang return true; 53591654e61SYifei Jiang } 536