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" 40*ad40be27SYifei Jiang #include "kvm_riscv.h" 4191654e61SYifei Jiang 420a312b85SYifei Jiang static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, 430a312b85SYifei Jiang uint64_t idx) 440a312b85SYifei Jiang { 450a312b85SYifei Jiang uint64_t id = KVM_REG_RISCV | type | idx; 460a312b85SYifei Jiang 470a312b85SYifei Jiang switch (riscv_cpu_mxl(env)) { 480a312b85SYifei Jiang case MXL_RV32: 490a312b85SYifei Jiang id |= KVM_REG_SIZE_U32; 500a312b85SYifei Jiang break; 510a312b85SYifei Jiang case MXL_RV64: 520a312b85SYifei Jiang id |= KVM_REG_SIZE_U64; 530a312b85SYifei Jiang break; 540a312b85SYifei Jiang default: 550a312b85SYifei Jiang g_assert_not_reached(); 560a312b85SYifei Jiang } 570a312b85SYifei Jiang return id; 580a312b85SYifei Jiang } 590a312b85SYifei Jiang 60937f0b45SYifei Jiang #define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ 61937f0b45SYifei Jiang KVM_REG_RISCV_CORE_REG(name)) 62937f0b45SYifei Jiang 63937f0b45SYifei Jiang #define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ 64937f0b45SYifei Jiang KVM_REG_RISCV_CSR_REG(name)) 65937f0b45SYifei Jiang 66937f0b45SYifei Jiang #define RISCV_FP_F_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx) 67937f0b45SYifei Jiang 68937f0b45SYifei Jiang #define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) 69937f0b45SYifei Jiang 70937f0b45SYifei Jiang #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ 71937f0b45SYifei Jiang do { \ 72937f0b45SYifei Jiang int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ 73937f0b45SYifei Jiang if (ret) { \ 74937f0b45SYifei Jiang return ret; \ 75937f0b45SYifei Jiang } \ 76937f0b45SYifei Jiang } while (0) 77937f0b45SYifei Jiang 789997cc1eSYifei Jiang #define KVM_RISCV_SET_CSR(cs, env, csr, reg) \ 799997cc1eSYifei Jiang do { \ 809997cc1eSYifei Jiang int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ 819997cc1eSYifei Jiang if (ret) { \ 829997cc1eSYifei Jiang return ret; \ 839997cc1eSYifei Jiang } \ 849997cc1eSYifei Jiang } while (0) 859997cc1eSYifei Jiang 86937f0b45SYifei Jiang static int kvm_riscv_get_regs_core(CPUState *cs) 87937f0b45SYifei Jiang { 88937f0b45SYifei Jiang int ret = 0; 89937f0b45SYifei Jiang int i; 90937f0b45SYifei Jiang target_ulong reg; 91937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 92937f0b45SYifei Jiang 93937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); 94937f0b45SYifei Jiang if (ret) { 95937f0b45SYifei Jiang return ret; 96937f0b45SYifei Jiang } 97937f0b45SYifei Jiang env->pc = reg; 98937f0b45SYifei Jiang 99937f0b45SYifei Jiang for (i = 1; i < 32; i++) { 100937f0b45SYifei Jiang uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); 101937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, id, ®); 102937f0b45SYifei Jiang if (ret) { 103937f0b45SYifei Jiang return ret; 104937f0b45SYifei Jiang } 105937f0b45SYifei Jiang env->gpr[i] = reg; 106937f0b45SYifei Jiang } 107937f0b45SYifei Jiang 108937f0b45SYifei Jiang return ret; 109937f0b45SYifei Jiang } 110937f0b45SYifei Jiang 1119997cc1eSYifei Jiang static int kvm_riscv_put_regs_core(CPUState *cs) 1129997cc1eSYifei Jiang { 1139997cc1eSYifei Jiang int ret = 0; 1149997cc1eSYifei Jiang int i; 1159997cc1eSYifei Jiang target_ulong reg; 1169997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 1179997cc1eSYifei Jiang 1189997cc1eSYifei Jiang reg = env->pc; 1199997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); 1209997cc1eSYifei Jiang if (ret) { 1219997cc1eSYifei Jiang return ret; 1229997cc1eSYifei Jiang } 1239997cc1eSYifei Jiang 1249997cc1eSYifei Jiang for (i = 1; i < 32; i++) { 1259997cc1eSYifei Jiang uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); 1269997cc1eSYifei Jiang reg = env->gpr[i]; 1279997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, id, ®); 1289997cc1eSYifei Jiang if (ret) { 1299997cc1eSYifei Jiang return ret; 1309997cc1eSYifei Jiang } 1319997cc1eSYifei Jiang } 1329997cc1eSYifei Jiang 1339997cc1eSYifei Jiang return ret; 1349997cc1eSYifei Jiang } 1359997cc1eSYifei Jiang 136937f0b45SYifei Jiang static int kvm_riscv_get_regs_csr(CPUState *cs) 137937f0b45SYifei Jiang { 138937f0b45SYifei Jiang int ret = 0; 139937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 140937f0b45SYifei Jiang 141937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus); 142937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sie, env->mie); 143937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec); 144937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch); 145937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc); 146937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, scause, env->scause); 147937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, stval, env->stval); 148937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sip, env->mip); 149937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, satp, env->satp); 150937f0b45SYifei Jiang return ret; 151937f0b45SYifei Jiang } 152937f0b45SYifei Jiang 1539997cc1eSYifei Jiang static int kvm_riscv_put_regs_csr(CPUState *cs) 1549997cc1eSYifei Jiang { 1559997cc1eSYifei Jiang int ret = 0; 1569997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 1579997cc1eSYifei Jiang 1589997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus); 1599997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sie, env->mie); 1609997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec); 1619997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch); 1629997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc); 1639997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, scause, env->scause); 1649997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, stval, env->stval); 1659997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sip, env->mip); 1669997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, satp, env->satp); 1679997cc1eSYifei Jiang 1689997cc1eSYifei Jiang return ret; 1699997cc1eSYifei Jiang } 1709997cc1eSYifei Jiang 171937f0b45SYifei Jiang static int kvm_riscv_get_regs_fp(CPUState *cs) 172937f0b45SYifei Jiang { 173937f0b45SYifei Jiang int ret = 0; 174937f0b45SYifei Jiang int i; 175937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 176937f0b45SYifei Jiang 177937f0b45SYifei Jiang if (riscv_has_ext(env, RVD)) { 178937f0b45SYifei Jiang uint64_t reg; 179937f0b45SYifei Jiang for (i = 0; i < 32; i++) { 180937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), ®); 181937f0b45SYifei Jiang if (ret) { 182937f0b45SYifei Jiang return ret; 183937f0b45SYifei Jiang } 184937f0b45SYifei Jiang env->fpr[i] = reg; 185937f0b45SYifei Jiang } 186937f0b45SYifei Jiang return ret; 187937f0b45SYifei Jiang } 188937f0b45SYifei Jiang 189937f0b45SYifei Jiang if (riscv_has_ext(env, RVF)) { 190937f0b45SYifei Jiang uint32_t reg; 191937f0b45SYifei Jiang for (i = 0; i < 32; i++) { 192937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), ®); 193937f0b45SYifei Jiang if (ret) { 194937f0b45SYifei Jiang return ret; 195937f0b45SYifei Jiang } 196937f0b45SYifei Jiang env->fpr[i] = reg; 197937f0b45SYifei Jiang } 198937f0b45SYifei Jiang return ret; 199937f0b45SYifei Jiang } 200937f0b45SYifei Jiang 201937f0b45SYifei Jiang return ret; 202937f0b45SYifei Jiang } 203937f0b45SYifei Jiang 2049997cc1eSYifei Jiang static int kvm_riscv_put_regs_fp(CPUState *cs) 2059997cc1eSYifei Jiang { 2069997cc1eSYifei Jiang int ret = 0; 2079997cc1eSYifei Jiang int i; 2089997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 2099997cc1eSYifei Jiang 2109997cc1eSYifei Jiang if (riscv_has_ext(env, RVD)) { 2119997cc1eSYifei Jiang uint64_t reg; 2129997cc1eSYifei Jiang for (i = 0; i < 32; i++) { 2139997cc1eSYifei Jiang reg = env->fpr[i]; 2149997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), ®); 2159997cc1eSYifei Jiang if (ret) { 2169997cc1eSYifei Jiang return ret; 2179997cc1eSYifei Jiang } 2189997cc1eSYifei Jiang } 2199997cc1eSYifei Jiang return ret; 2209997cc1eSYifei Jiang } 2219997cc1eSYifei Jiang 2229997cc1eSYifei Jiang if (riscv_has_ext(env, RVF)) { 2239997cc1eSYifei Jiang uint32_t reg; 2249997cc1eSYifei Jiang for (i = 0; i < 32; i++) { 2259997cc1eSYifei Jiang reg = env->fpr[i]; 2269997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), ®); 2279997cc1eSYifei Jiang if (ret) { 2289997cc1eSYifei Jiang return ret; 2299997cc1eSYifei Jiang } 2309997cc1eSYifei Jiang } 2319997cc1eSYifei Jiang return ret; 2329997cc1eSYifei Jiang } 2339997cc1eSYifei Jiang 2349997cc1eSYifei Jiang return ret; 2359997cc1eSYifei Jiang } 2369997cc1eSYifei Jiang 2379997cc1eSYifei Jiang 23891654e61SYifei Jiang const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 23991654e61SYifei Jiang KVM_CAP_LAST_INFO 24091654e61SYifei Jiang }; 24191654e61SYifei Jiang 24291654e61SYifei Jiang int kvm_arch_get_registers(CPUState *cs) 24391654e61SYifei Jiang { 244937f0b45SYifei Jiang int ret = 0; 245937f0b45SYifei Jiang 246937f0b45SYifei Jiang ret = kvm_riscv_get_regs_core(cs); 247937f0b45SYifei Jiang if (ret) { 248937f0b45SYifei Jiang return ret; 249937f0b45SYifei Jiang } 250937f0b45SYifei Jiang 251937f0b45SYifei Jiang ret = kvm_riscv_get_regs_csr(cs); 252937f0b45SYifei Jiang if (ret) { 253937f0b45SYifei Jiang return ret; 254937f0b45SYifei Jiang } 255937f0b45SYifei Jiang 256937f0b45SYifei Jiang ret = kvm_riscv_get_regs_fp(cs); 257937f0b45SYifei Jiang if (ret) { 258937f0b45SYifei Jiang return ret; 259937f0b45SYifei Jiang } 260937f0b45SYifei Jiang 261937f0b45SYifei Jiang return ret; 26291654e61SYifei Jiang } 26391654e61SYifei Jiang 26491654e61SYifei Jiang int kvm_arch_put_registers(CPUState *cs, int level) 26591654e61SYifei Jiang { 2669997cc1eSYifei Jiang int ret = 0; 2679997cc1eSYifei Jiang 2689997cc1eSYifei Jiang ret = kvm_riscv_put_regs_core(cs); 2699997cc1eSYifei Jiang if (ret) { 2709997cc1eSYifei Jiang return ret; 2719997cc1eSYifei Jiang } 2729997cc1eSYifei Jiang 2739997cc1eSYifei Jiang ret = kvm_riscv_put_regs_csr(cs); 2749997cc1eSYifei Jiang if (ret) { 2759997cc1eSYifei Jiang return ret; 2769997cc1eSYifei Jiang } 2779997cc1eSYifei Jiang 2789997cc1eSYifei Jiang ret = kvm_riscv_put_regs_fp(cs); 2799997cc1eSYifei Jiang if (ret) { 2809997cc1eSYifei Jiang return ret; 2819997cc1eSYifei Jiang } 2829997cc1eSYifei Jiang 2839997cc1eSYifei Jiang return ret; 28491654e61SYifei Jiang } 28591654e61SYifei Jiang 28691654e61SYifei Jiang int kvm_arch_release_virq_post(int virq) 28791654e61SYifei Jiang { 28891654e61SYifei Jiang return 0; 28991654e61SYifei Jiang } 29091654e61SYifei Jiang 29191654e61SYifei Jiang int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 29291654e61SYifei Jiang uint64_t address, uint32_t data, PCIDevice *dev) 29391654e61SYifei Jiang { 29491654e61SYifei Jiang return 0; 29591654e61SYifei Jiang } 29691654e61SYifei Jiang 29791654e61SYifei Jiang int kvm_arch_destroy_vcpu(CPUState *cs) 29891654e61SYifei Jiang { 29991654e61SYifei Jiang return 0; 30091654e61SYifei Jiang } 30191654e61SYifei Jiang 30291654e61SYifei Jiang unsigned long kvm_arch_vcpu_id(CPUState *cpu) 30391654e61SYifei Jiang { 30491654e61SYifei Jiang return cpu->cpu_index; 30591654e61SYifei Jiang } 30691654e61SYifei Jiang 30791654e61SYifei Jiang void kvm_arch_init_irq_routing(KVMState *s) 30891654e61SYifei Jiang { 30991654e61SYifei Jiang } 31091654e61SYifei Jiang 31191654e61SYifei Jiang int kvm_arch_init_vcpu(CPUState *cs) 31291654e61SYifei Jiang { 3130a312b85SYifei Jiang int ret = 0; 3140a312b85SYifei Jiang target_ulong isa; 3150a312b85SYifei Jiang RISCVCPU *cpu = RISCV_CPU(cs); 3160a312b85SYifei Jiang CPURISCVState *env = &cpu->env; 3170a312b85SYifei Jiang uint64_t id; 3180a312b85SYifei Jiang 3190a312b85SYifei Jiang id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, 3200a312b85SYifei Jiang KVM_REG_RISCV_CONFIG_REG(isa)); 3210a312b85SYifei Jiang ret = kvm_get_one_reg(cs, id, &isa); 3220a312b85SYifei Jiang if (ret) { 3230a312b85SYifei Jiang return ret; 3240a312b85SYifei Jiang } 3250a312b85SYifei Jiang env->misa_ext = isa; 3260a312b85SYifei Jiang 3270a312b85SYifei Jiang return ret; 32891654e61SYifei Jiang } 32991654e61SYifei Jiang 33091654e61SYifei Jiang int kvm_arch_msi_data_to_gsi(uint32_t data) 33191654e61SYifei Jiang { 33291654e61SYifei Jiang abort(); 33391654e61SYifei Jiang } 33491654e61SYifei Jiang 33591654e61SYifei Jiang int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 33691654e61SYifei Jiang int vector, PCIDevice *dev) 33791654e61SYifei Jiang { 33891654e61SYifei Jiang return 0; 33991654e61SYifei Jiang } 34091654e61SYifei Jiang 34191654e61SYifei Jiang int kvm_arch_init(MachineState *ms, KVMState *s) 34291654e61SYifei Jiang { 34391654e61SYifei Jiang return 0; 34491654e61SYifei Jiang } 34591654e61SYifei Jiang 34691654e61SYifei Jiang int kvm_arch_irqchip_create(KVMState *s) 34791654e61SYifei Jiang { 34891654e61SYifei Jiang return 0; 34991654e61SYifei Jiang } 35091654e61SYifei Jiang 35191654e61SYifei Jiang int kvm_arch_process_async_events(CPUState *cs) 35291654e61SYifei Jiang { 35391654e61SYifei Jiang return 0; 35491654e61SYifei Jiang } 35591654e61SYifei Jiang 35691654e61SYifei Jiang void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 35791654e61SYifei Jiang { 35891654e61SYifei Jiang } 35991654e61SYifei Jiang 36091654e61SYifei Jiang MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 36191654e61SYifei Jiang { 36291654e61SYifei Jiang return MEMTXATTRS_UNSPECIFIED; 36391654e61SYifei Jiang } 36491654e61SYifei Jiang 36591654e61SYifei Jiang bool kvm_arch_stop_on_emulation_error(CPUState *cs) 36691654e61SYifei Jiang { 36791654e61SYifei Jiang return true; 36891654e61SYifei Jiang } 36991654e61SYifei Jiang 37091654e61SYifei Jiang int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 37191654e61SYifei Jiang { 37291654e61SYifei Jiang return 0; 37391654e61SYifei Jiang } 37491654e61SYifei Jiang 375*ad40be27SYifei Jiang void kvm_riscv_reset_vcpu(RISCVCPU *cpu) 376*ad40be27SYifei Jiang { 377*ad40be27SYifei Jiang CPURISCVState *env = &cpu->env; 378*ad40be27SYifei Jiang 379*ad40be27SYifei Jiang if (!kvm_enabled()) { 380*ad40be27SYifei Jiang return; 381*ad40be27SYifei Jiang } 382*ad40be27SYifei Jiang env->pc = cpu->env.kernel_addr; 383*ad40be27SYifei Jiang env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ 384*ad40be27SYifei Jiang env->gpr[11] = cpu->env.fdt_addr; /* a1 */ 385*ad40be27SYifei Jiang env->satp = 0; 386*ad40be27SYifei Jiang } 387*ad40be27SYifei Jiang 38891654e61SYifei Jiang bool kvm_arch_cpu_check_are_resettable(void) 38991654e61SYifei Jiang { 39091654e61SYifei Jiang return true; 39191654e61SYifei Jiang } 392