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" 4091654e61SYifei Jiang 410a312b85SYifei Jiang static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, 420a312b85SYifei Jiang uint64_t idx) 430a312b85SYifei Jiang { 440a312b85SYifei Jiang uint64_t id = KVM_REG_RISCV | type | idx; 450a312b85SYifei Jiang 460a312b85SYifei Jiang switch (riscv_cpu_mxl(env)) { 470a312b85SYifei Jiang case MXL_RV32: 480a312b85SYifei Jiang id |= KVM_REG_SIZE_U32; 490a312b85SYifei Jiang break; 500a312b85SYifei Jiang case MXL_RV64: 510a312b85SYifei Jiang id |= KVM_REG_SIZE_U64; 520a312b85SYifei Jiang break; 530a312b85SYifei Jiang default: 540a312b85SYifei Jiang g_assert_not_reached(); 550a312b85SYifei Jiang } 560a312b85SYifei Jiang return id; 570a312b85SYifei Jiang } 580a312b85SYifei Jiang 59937f0b45SYifei Jiang #define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ 60937f0b45SYifei Jiang KVM_REG_RISCV_CORE_REG(name)) 61937f0b45SYifei Jiang 62937f0b45SYifei Jiang #define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ 63937f0b45SYifei Jiang KVM_REG_RISCV_CSR_REG(name)) 64937f0b45SYifei Jiang 65937f0b45SYifei Jiang #define RISCV_FP_F_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx) 66937f0b45SYifei Jiang 67937f0b45SYifei Jiang #define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) 68937f0b45SYifei Jiang 69937f0b45SYifei Jiang #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ 70937f0b45SYifei Jiang do { \ 71937f0b45SYifei Jiang int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ 72937f0b45SYifei Jiang if (ret) { \ 73937f0b45SYifei Jiang return ret; \ 74937f0b45SYifei Jiang } \ 75937f0b45SYifei Jiang } while (0) 76937f0b45SYifei Jiang 77*9997cc1eSYifei Jiang #define KVM_RISCV_SET_CSR(cs, env, csr, reg) \ 78*9997cc1eSYifei Jiang do { \ 79*9997cc1eSYifei Jiang int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ 80*9997cc1eSYifei Jiang if (ret) { \ 81*9997cc1eSYifei Jiang return ret; \ 82*9997cc1eSYifei Jiang } \ 83*9997cc1eSYifei Jiang } while (0) 84*9997cc1eSYifei Jiang 85937f0b45SYifei Jiang static int kvm_riscv_get_regs_core(CPUState *cs) 86937f0b45SYifei Jiang { 87937f0b45SYifei Jiang int ret = 0; 88937f0b45SYifei Jiang int i; 89937f0b45SYifei Jiang target_ulong reg; 90937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 91937f0b45SYifei Jiang 92937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); 93937f0b45SYifei Jiang if (ret) { 94937f0b45SYifei Jiang return ret; 95937f0b45SYifei Jiang } 96937f0b45SYifei Jiang env->pc = reg; 97937f0b45SYifei Jiang 98937f0b45SYifei Jiang for (i = 1; i < 32; i++) { 99937f0b45SYifei Jiang uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); 100937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, id, ®); 101937f0b45SYifei Jiang if (ret) { 102937f0b45SYifei Jiang return ret; 103937f0b45SYifei Jiang } 104937f0b45SYifei Jiang env->gpr[i] = reg; 105937f0b45SYifei Jiang } 106937f0b45SYifei Jiang 107937f0b45SYifei Jiang return ret; 108937f0b45SYifei Jiang } 109937f0b45SYifei Jiang 110*9997cc1eSYifei Jiang static int kvm_riscv_put_regs_core(CPUState *cs) 111*9997cc1eSYifei Jiang { 112*9997cc1eSYifei Jiang int ret = 0; 113*9997cc1eSYifei Jiang int i; 114*9997cc1eSYifei Jiang target_ulong reg; 115*9997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 116*9997cc1eSYifei Jiang 117*9997cc1eSYifei Jiang reg = env->pc; 118*9997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); 119*9997cc1eSYifei Jiang if (ret) { 120*9997cc1eSYifei Jiang return ret; 121*9997cc1eSYifei Jiang } 122*9997cc1eSYifei Jiang 123*9997cc1eSYifei Jiang for (i = 1; i < 32; i++) { 124*9997cc1eSYifei Jiang uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); 125*9997cc1eSYifei Jiang reg = env->gpr[i]; 126*9997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, id, ®); 127*9997cc1eSYifei Jiang if (ret) { 128*9997cc1eSYifei Jiang return ret; 129*9997cc1eSYifei Jiang } 130*9997cc1eSYifei Jiang } 131*9997cc1eSYifei Jiang 132*9997cc1eSYifei Jiang return ret; 133*9997cc1eSYifei Jiang } 134*9997cc1eSYifei Jiang 135937f0b45SYifei Jiang static int kvm_riscv_get_regs_csr(CPUState *cs) 136937f0b45SYifei Jiang { 137937f0b45SYifei Jiang int ret = 0; 138937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 139937f0b45SYifei Jiang 140937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus); 141937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sie, env->mie); 142937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec); 143937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch); 144937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc); 145937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, scause, env->scause); 146937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, stval, env->stval); 147937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sip, env->mip); 148937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, satp, env->satp); 149937f0b45SYifei Jiang return ret; 150937f0b45SYifei Jiang } 151937f0b45SYifei Jiang 152*9997cc1eSYifei Jiang static int kvm_riscv_put_regs_csr(CPUState *cs) 153*9997cc1eSYifei Jiang { 154*9997cc1eSYifei Jiang int ret = 0; 155*9997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 156*9997cc1eSYifei Jiang 157*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus); 158*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sie, env->mie); 159*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec); 160*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch); 161*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc); 162*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, scause, env->scause); 163*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, stval, env->stval); 164*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sip, env->mip); 165*9997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, satp, env->satp); 166*9997cc1eSYifei Jiang 167*9997cc1eSYifei Jiang return ret; 168*9997cc1eSYifei Jiang } 169*9997cc1eSYifei Jiang 170937f0b45SYifei Jiang static int kvm_riscv_get_regs_fp(CPUState *cs) 171937f0b45SYifei Jiang { 172937f0b45SYifei Jiang int ret = 0; 173937f0b45SYifei Jiang int i; 174937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 175937f0b45SYifei Jiang 176937f0b45SYifei Jiang if (riscv_has_ext(env, RVD)) { 177937f0b45SYifei Jiang uint64_t reg; 178937f0b45SYifei Jiang for (i = 0; i < 32; i++) { 179937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), ®); 180937f0b45SYifei Jiang if (ret) { 181937f0b45SYifei Jiang return ret; 182937f0b45SYifei Jiang } 183937f0b45SYifei Jiang env->fpr[i] = reg; 184937f0b45SYifei Jiang } 185937f0b45SYifei Jiang return ret; 186937f0b45SYifei Jiang } 187937f0b45SYifei Jiang 188937f0b45SYifei Jiang if (riscv_has_ext(env, RVF)) { 189937f0b45SYifei Jiang uint32_t reg; 190937f0b45SYifei Jiang for (i = 0; i < 32; i++) { 191937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), ®); 192937f0b45SYifei Jiang if (ret) { 193937f0b45SYifei Jiang return ret; 194937f0b45SYifei Jiang } 195937f0b45SYifei Jiang env->fpr[i] = reg; 196937f0b45SYifei Jiang } 197937f0b45SYifei Jiang return ret; 198937f0b45SYifei Jiang } 199937f0b45SYifei Jiang 200937f0b45SYifei Jiang return ret; 201937f0b45SYifei Jiang } 202937f0b45SYifei Jiang 203*9997cc1eSYifei Jiang static int kvm_riscv_put_regs_fp(CPUState *cs) 204*9997cc1eSYifei Jiang { 205*9997cc1eSYifei Jiang int ret = 0; 206*9997cc1eSYifei Jiang int i; 207*9997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 208*9997cc1eSYifei Jiang 209*9997cc1eSYifei Jiang if (riscv_has_ext(env, RVD)) { 210*9997cc1eSYifei Jiang uint64_t reg; 211*9997cc1eSYifei Jiang for (i = 0; i < 32; i++) { 212*9997cc1eSYifei Jiang reg = env->fpr[i]; 213*9997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), ®); 214*9997cc1eSYifei Jiang if (ret) { 215*9997cc1eSYifei Jiang return ret; 216*9997cc1eSYifei Jiang } 217*9997cc1eSYifei Jiang } 218*9997cc1eSYifei Jiang return ret; 219*9997cc1eSYifei Jiang } 220*9997cc1eSYifei Jiang 221*9997cc1eSYifei Jiang if (riscv_has_ext(env, RVF)) { 222*9997cc1eSYifei Jiang uint32_t reg; 223*9997cc1eSYifei Jiang for (i = 0; i < 32; i++) { 224*9997cc1eSYifei Jiang reg = env->fpr[i]; 225*9997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), ®); 226*9997cc1eSYifei Jiang if (ret) { 227*9997cc1eSYifei Jiang return ret; 228*9997cc1eSYifei Jiang } 229*9997cc1eSYifei Jiang } 230*9997cc1eSYifei Jiang return ret; 231*9997cc1eSYifei Jiang } 232*9997cc1eSYifei Jiang 233*9997cc1eSYifei Jiang return ret; 234*9997cc1eSYifei Jiang } 235*9997cc1eSYifei Jiang 236*9997cc1eSYifei Jiang 23791654e61SYifei Jiang const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 23891654e61SYifei Jiang KVM_CAP_LAST_INFO 23991654e61SYifei Jiang }; 24091654e61SYifei Jiang 24191654e61SYifei Jiang int kvm_arch_get_registers(CPUState *cs) 24291654e61SYifei Jiang { 243937f0b45SYifei Jiang int ret = 0; 244937f0b45SYifei Jiang 245937f0b45SYifei Jiang ret = kvm_riscv_get_regs_core(cs); 246937f0b45SYifei Jiang if (ret) { 247937f0b45SYifei Jiang return ret; 248937f0b45SYifei Jiang } 249937f0b45SYifei Jiang 250937f0b45SYifei Jiang ret = kvm_riscv_get_regs_csr(cs); 251937f0b45SYifei Jiang if (ret) { 252937f0b45SYifei Jiang return ret; 253937f0b45SYifei Jiang } 254937f0b45SYifei Jiang 255937f0b45SYifei Jiang ret = kvm_riscv_get_regs_fp(cs); 256937f0b45SYifei Jiang if (ret) { 257937f0b45SYifei Jiang return ret; 258937f0b45SYifei Jiang } 259937f0b45SYifei Jiang 260937f0b45SYifei Jiang return ret; 26191654e61SYifei Jiang } 26291654e61SYifei Jiang 26391654e61SYifei Jiang int kvm_arch_put_registers(CPUState *cs, int level) 26491654e61SYifei Jiang { 265*9997cc1eSYifei Jiang int ret = 0; 266*9997cc1eSYifei Jiang 267*9997cc1eSYifei Jiang ret = kvm_riscv_put_regs_core(cs); 268*9997cc1eSYifei Jiang if (ret) { 269*9997cc1eSYifei Jiang return ret; 270*9997cc1eSYifei Jiang } 271*9997cc1eSYifei Jiang 272*9997cc1eSYifei Jiang ret = kvm_riscv_put_regs_csr(cs); 273*9997cc1eSYifei Jiang if (ret) { 274*9997cc1eSYifei Jiang return ret; 275*9997cc1eSYifei Jiang } 276*9997cc1eSYifei Jiang 277*9997cc1eSYifei Jiang ret = kvm_riscv_put_regs_fp(cs); 278*9997cc1eSYifei Jiang if (ret) { 279*9997cc1eSYifei Jiang return ret; 280*9997cc1eSYifei Jiang } 281*9997cc1eSYifei Jiang 282*9997cc1eSYifei Jiang return ret; 28391654e61SYifei Jiang } 28491654e61SYifei Jiang 28591654e61SYifei Jiang int kvm_arch_release_virq_post(int virq) 28691654e61SYifei Jiang { 28791654e61SYifei Jiang return 0; 28891654e61SYifei Jiang } 28991654e61SYifei Jiang 29091654e61SYifei Jiang int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 29191654e61SYifei Jiang uint64_t address, uint32_t data, PCIDevice *dev) 29291654e61SYifei Jiang { 29391654e61SYifei Jiang return 0; 29491654e61SYifei Jiang } 29591654e61SYifei Jiang 29691654e61SYifei Jiang int kvm_arch_destroy_vcpu(CPUState *cs) 29791654e61SYifei Jiang { 29891654e61SYifei Jiang return 0; 29991654e61SYifei Jiang } 30091654e61SYifei Jiang 30191654e61SYifei Jiang unsigned long kvm_arch_vcpu_id(CPUState *cpu) 30291654e61SYifei Jiang { 30391654e61SYifei Jiang return cpu->cpu_index; 30491654e61SYifei Jiang } 30591654e61SYifei Jiang 30691654e61SYifei Jiang void kvm_arch_init_irq_routing(KVMState *s) 30791654e61SYifei Jiang { 30891654e61SYifei Jiang } 30991654e61SYifei Jiang 31091654e61SYifei Jiang int kvm_arch_init_vcpu(CPUState *cs) 31191654e61SYifei Jiang { 3120a312b85SYifei Jiang int ret = 0; 3130a312b85SYifei Jiang target_ulong isa; 3140a312b85SYifei Jiang RISCVCPU *cpu = RISCV_CPU(cs); 3150a312b85SYifei Jiang CPURISCVState *env = &cpu->env; 3160a312b85SYifei Jiang uint64_t id; 3170a312b85SYifei Jiang 3180a312b85SYifei Jiang id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, 3190a312b85SYifei Jiang KVM_REG_RISCV_CONFIG_REG(isa)); 3200a312b85SYifei Jiang ret = kvm_get_one_reg(cs, id, &isa); 3210a312b85SYifei Jiang if (ret) { 3220a312b85SYifei Jiang return ret; 3230a312b85SYifei Jiang } 3240a312b85SYifei Jiang env->misa_ext = isa; 3250a312b85SYifei Jiang 3260a312b85SYifei Jiang return ret; 32791654e61SYifei Jiang } 32891654e61SYifei Jiang 32991654e61SYifei Jiang int kvm_arch_msi_data_to_gsi(uint32_t data) 33091654e61SYifei Jiang { 33191654e61SYifei Jiang abort(); 33291654e61SYifei Jiang } 33391654e61SYifei Jiang 33491654e61SYifei Jiang int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 33591654e61SYifei Jiang int vector, PCIDevice *dev) 33691654e61SYifei Jiang { 33791654e61SYifei Jiang return 0; 33891654e61SYifei Jiang } 33991654e61SYifei Jiang 34091654e61SYifei Jiang int kvm_arch_init(MachineState *ms, KVMState *s) 34191654e61SYifei Jiang { 34291654e61SYifei Jiang return 0; 34391654e61SYifei Jiang } 34491654e61SYifei Jiang 34591654e61SYifei Jiang int kvm_arch_irqchip_create(KVMState *s) 34691654e61SYifei Jiang { 34791654e61SYifei Jiang return 0; 34891654e61SYifei Jiang } 34991654e61SYifei Jiang 35091654e61SYifei Jiang int kvm_arch_process_async_events(CPUState *cs) 35191654e61SYifei Jiang { 35291654e61SYifei Jiang return 0; 35391654e61SYifei Jiang } 35491654e61SYifei Jiang 35591654e61SYifei Jiang void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 35691654e61SYifei Jiang { 35791654e61SYifei Jiang } 35891654e61SYifei Jiang 35991654e61SYifei Jiang MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 36091654e61SYifei Jiang { 36191654e61SYifei Jiang return MEMTXATTRS_UNSPECIFIED; 36291654e61SYifei Jiang } 36391654e61SYifei Jiang 36491654e61SYifei Jiang bool kvm_arch_stop_on_emulation_error(CPUState *cs) 36591654e61SYifei Jiang { 36691654e61SYifei Jiang return true; 36791654e61SYifei Jiang } 36891654e61SYifei Jiang 36991654e61SYifei Jiang int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 37091654e61SYifei Jiang { 37191654e61SYifei Jiang return 0; 37291654e61SYifei Jiang } 37391654e61SYifei Jiang 37491654e61SYifei Jiang bool kvm_arch_cpu_check_are_resettable(void) 37591654e61SYifei Jiang { 37691654e61SYifei Jiang return true; 37791654e61SYifei Jiang } 378