From eddbf7e249875f60db7c22abebcaa67d8a24f20d Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Mon, 24 Aug 2020 20:09:16 +0800 Subject: [PATCH 1/9] linux-header: Update linux/kvm.h Update linux/kvm.h on https://gitee.com/openeuler/kernel/tree/kernel-5.5/ Only use this header file, so do not update all linux headers. Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- linux-headers/linux/kvm.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 9804495a46..ff6fb2ff53 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -236,6 +236,7 @@ struct kvm_hyperv_exit { #define KVM_EXIT_IOAPIC_EOI 26 #define KVM_EXIT_HYPERV 27 #define KVM_EXIT_ARM_NISV 28 +#define KVM_EXIT_RISCV_SBI 28 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -400,6 +401,13 @@ struct kvm_run { __u64 esr_iss; __u64 fault_ipa; } arm_nisv; + /* KVM_EXIT_RISCV_SBI */ + struct { + unsigned long extension_id; + unsigned long function_id; + unsigned long args[6]; + unsigned long ret[2]; + } riscv_sbi; /* Fix the size of the union. */ char padding[256]; }; -- Gitee From 4266c8e48eec2731f95513abb250dcdf65eb87d9 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Mon, 24 Aug 2020 20:09:32 +0800 Subject: [PATCH 2/9] target/riscv: Add target/riscv/kvm.c to place the public kvm interface Add target/riscv/kvm.c to place kvm_arch_* function needed by kvm/kvm-all.c. Meanwhile, add kvm support in configure file. Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- configure | 1 + target/riscv/Makefile.objs | 1 + target/riscv/kvm.c | 128 +++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 target/riscv/kvm.c diff --git a/configure b/configure index b969dee675..10565e588a 100755 --- a/configure +++ b/configure @@ -200,6 +200,7 @@ supported_kvm_target() { x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \ mips:mips | mipsel:mips | \ ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \ + riscv32:riscv32 | riscv64:riscv64 | \ s390x:s390x) return 0 ;; diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs index ff651f69f6..7ea8f4c3da 100644 --- a/target/riscv/Makefile.objs +++ b/target/riscv/Makefile.objs @@ -1,5 +1,6 @@ obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o obj-$(CONFIG_SOFTMMU) += pmp.o +obj-$(CONFIG_KVM) += kvm.o ifeq ($(CONFIG_SOFTMMU),y) obj-y += monitor.o diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c new file mode 100644 index 0000000000..997907dfc9 --- /dev/null +++ b/target/riscv/kvm.c @@ -0,0 +1,128 @@ +/* + * RISC-V implementation of KVM hooks + * + * Copyright (c) 2020 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see ;. + */ + +#include "qemu/osdep.h" +#include + +#include + +#include "qemu-common.h" +#include "qemu/timer.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" +#include "sysemu/kvm_int.h" +#include "cpu.h" +#include "trace.h" +#include "hw/pci/pci.h" +#include "exec/memattrs.h" +#include "exec/address-spaces.h" +#include "hw/boards.h" +#include "hw/irq.h" +#include "qemu/log.h" +#include "hw/loader.h" + +const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO +}; + +int kvm_arch_get_registers(CPUState *cs) +{ + return 0; +} + +int kvm_arch_put_registers(CPUState *cs, int level) +{ + return 0; +} + +int kvm_arch_release_virq_post(int virq) +{ + return 0; +} + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data, PCIDevice *dev) +{ + return 0; +} + +int kvm_arch_destroy_vcpu(CPUState *cs) +{ + return 0; +} + +unsigned long kvm_arch_vcpu_id(CPUState *cpu) +{ + return cpu->cpu_index; +} + +void kvm_arch_init_irq_routing(KVMState *s) +{ +} + +int kvm_arch_init_vcpu(CPUState *cs) +{ + return 0; +} + +int kvm_arch_msi_data_to_gsi(uint32_t data) +{ + abort(); +} + +int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, + int vector, PCIDevice *dev) +{ + return 0; +} + +int kvm_arch_init(MachineState *ms, KVMState *s) +{ + return 0; +} + +int kvm_arch_irqchip_create(KVMState *s) +{ + return 0; +} + +int kvm_arch_process_async_events(CPUState *cs) +{ + return 0; +} + +void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) +{ +} + +MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) +{ + return MEMTXATTRS_UNSPECIFIED; +} + +bool kvm_arch_stop_on_emulation_error(CPUState *cs) +{ + return true; +} + +int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) +{ + return 0; +} -- Gitee From f933f3a4b5d1a41ce04fd1e22d0347d1012d2b96 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Mon, 24 Aug 2020 20:09:46 +0800 Subject: [PATCH 3/9] target/riscv: Implement function kvm_arch_init_vcpu Get isa info from kvm while kvm init. Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- target/riscv/kvm.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 997907dfc9..4ead8c0151 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -38,6 +38,18 @@ #include "qemu/log.h" #include "hw/loader.h" +static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) +{ + __u64 id = KVM_REG_RISCV | type | idx; + +#if defined(TARGET_RISCV32) + id |= KVM_REG_SIZE_U32; +#elif defined(TARGET_RISCV64) + id |= KVM_REG_SIZE_U64; +#endif + return id; +} + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; @@ -79,7 +91,19 @@ void kvm_arch_init_irq_routing(KVMState *s) int kvm_arch_init_vcpu(CPUState *cs) { - return 0; + int ret = 0; + target_ulong isa; + RISCVCPU *cpu = RISCV_CPU(cs); + __u64 id; + + id = kvm_riscv_reg_id(KVM_REG_RISCV_CONFIG, KVM_REG_RISCV_CONFIG_REG(isa)); + ret = kvm_get_one_reg(cs, id, &isa); + if (ret) { + return ret; + } + cpu->env.misa = isa; + + return ret; } int kvm_arch_msi_data_to_gsi(uint32_t data) -- Gitee From 08f53a38ff3e319943cf49a88360994a8ef7c988 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Mon, 24 Aug 2020 20:09:59 +0800 Subject: [PATCH 4/9] target/riscv: Implement kvm_arch_get_registers Get GPR CSR and FP registers from kvm by KVM_GET_ONE_REG ioctl. Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- target/riscv/kvm.c | 144 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 143 insertions(+), 1 deletion(-) diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 4ead8c0151..5ec2bb99ba 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -50,13 +50,155 @@ static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) return id; } +#define RISCV_CORE_REG(name) kvm_riscv_reg_id(KVM_REG_RISCV_CORE, \ + KVM_REG_RISCV_CORE_REG(name)) + +#define RISCV_CSR_REG(name) kvm_riscv_reg_id(KVM_REG_RISCV_CSR, \ + KVM_REG_RISCV_CSR_REG(name)) + +#define RISCV_FP_F_REG(idx) kvm_riscv_reg_id(KVM_REG_RISCV_FP_F, idx) + +#define RISCV_FP_D_REG(idx) kvm_riscv_reg_id(KVM_REG_RISCV_FP_D, idx) + +static int kvm_riscv_get_regs_core(CPUState *cs) +{ + int ret = 0; + int i; + target_ulong reg; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + ret = kvm_get_one_reg(cs, RISCV_CORE_REG(regs.pc), ®); + if (ret) { + return ret; + } + env->pc = reg; + + for (i = 1; i < 32; i++) { + __u64 id = kvm_riscv_reg_id(KVM_REG_RISCV_CORE, i); + ret = kvm_get_one_reg(cs, id, ®); + if (ret) { + return ret; + } + env->gpr[i] = reg; + } + + return ret; +} + +static int kvm_riscv_get_regs_csr(CPUState *cs) +{ + int ret = 0; + target_ulong reg; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sstatus), ®); + if (ret) { + return ret; + } + env->mstatus = reg; + + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sie), ®); + if (ret) { + return ret; + } + env->mie = reg; + + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(stvec), ®); + if (ret) { + return ret; + } + env->stvec = reg; + + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sscratch), ®); + if (ret) { + return ret; + } + env->sscratch = reg; + + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sepc), ®); + if (ret) { + return ret; + } + env->sepc = reg; + + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(scause), ®); + if (ret) { + return ret; + } + env->scause = reg; + + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(sip), ®); + if (ret) { + return ret; + } + env->mip = reg; + + ret = kvm_get_one_reg(cs, RISCV_CSR_REG(satp), ®); + if (ret) { + return ret; + } + env->satp = reg; + + return ret; +} + +static int kvm_riscv_get_regs_fp(CPUState *cs) +{ + int ret = 0; + int i; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + if (riscv_has_ext(env, RVD)) { + uint64_t reg; + for (i = 0; i < 32; i++) { + ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(i), ®); + if (ret) { + return ret; + } + env->fpr[i] = reg; + } + return ret; + } + + if (riscv_has_ext(env, RVF)) { + uint32_t reg; + for (i = 0; i < 32; i++) { + ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(i), ®); + if (ret) { + return ret; + } + env->fpr[i] = reg; + } + return ret; + } + + return ret; +} + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; int kvm_arch_get_registers(CPUState *cs) { - return 0; + int ret = 0; + + ret = kvm_riscv_get_regs_core(cs); + if (ret) { + return ret; + } + + ret = kvm_riscv_get_regs_csr(cs); + if (ret) { + return ret; + } + + ret = kvm_riscv_get_regs_fp(cs); + if (ret) { + return ret; + } + + return ret; } int kvm_arch_put_registers(CPUState *cs, int level) -- Gitee From e4e6aac0930a4b8eb7b73dc2a1f85ab07390a8b5 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Mon, 24 Aug 2020 20:10:09 +0800 Subject: [PATCH 5/9] target/riscv: Implement kvm_arch_put_registers Put GPR CSR and FP registers to kvm by KVM_SET_ONE_REG ioctl Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- target/riscv/kvm.c | 136 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 1 deletion(-) diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 5ec2bb99ba..9810a02b49 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -85,6 +85,31 @@ static int kvm_riscv_get_regs_core(CPUState *cs) return ret; } +static int kvm_riscv_put_regs_core(CPUState *cs) +{ + int ret = 0; + int i; + target_ulong reg; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + reg = env->pc; + ret = kvm_set_one_reg(cs, RISCV_CORE_REG(regs.pc), ®); + if (ret) { + return ret; + } + + for (i = 1; i < 32; i++) { + __u64 id = kvm_riscv_reg_id(KVM_REG_RISCV_CORE, i); + reg = env->gpr[i]; + ret = kvm_set_one_reg(cs, id, ®); + if (ret) { + return ret; + } + } + + return ret; +} + static int kvm_riscv_get_regs_csr(CPUState *cs) { int ret = 0; @@ -142,6 +167,64 @@ static int kvm_riscv_get_regs_csr(CPUState *cs) return ret; } +static int kvm_riscv_put_regs_csr(CPUState *cs) +{ + int ret = 0; + target_ulong reg; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + reg = env->mstatus; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sstatus), ®); + if (ret) { + return ret; + } + + reg = env->mie; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sie), ®); + if (ret) { + return ret; + } + + reg = env->stvec; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(stvec), ®); + if (ret) { + return ret; + } + + reg = env->sscratch; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sscratch), ®); + if (ret) { + return ret; + } + + reg = env->sepc; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sepc), ®); + if (ret) { + return ret; + } + + reg = env->scause; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(scause), ®); + if (ret) { + return ret; + } + + reg = env->mip; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(sip), ®); + if (ret) { + return ret; + } + + reg = env->satp; + ret = kvm_set_one_reg(cs, RISCV_CSR_REG(satp), ®); + if (ret) { + return ret; + } + + return ret; +} + + static int kvm_riscv_get_regs_fp(CPUState *cs) { int ret = 0; @@ -175,6 +258,40 @@ static int kvm_riscv_get_regs_fp(CPUState *cs) return ret; } +static int kvm_riscv_put_regs_fp(CPUState *cs) +{ + int ret = 0; + int i; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + if (riscv_has_ext(env, RVD)) { + uint64_t reg; + for (i = 0; i < 32; i++) { + reg = env->fpr[i]; + ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(i), ®); + if (ret) { + return ret; + } + } + return ret; + } + + if (riscv_has_ext(env, RVF)) { + uint32_t reg; + for (i = 0; i < 32; i++) { + reg = env->fpr[i]; + ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(i), ®); + if (ret) { + return ret; + } + } + return ret; + } + + return ret; +} + + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; @@ -203,7 +320,24 @@ int kvm_arch_get_registers(CPUState *cs) int kvm_arch_put_registers(CPUState *cs, int level) { - return 0; + int ret = 0; + + ret = kvm_riscv_put_regs_core(cs); + if (ret) { + return ret; + } + + ret = kvm_riscv_put_regs_csr(cs); + if (ret) { + return ret; + } + + ret = kvm_riscv_put_regs_fp(cs); + if (ret) { + return ret; + } + + return ret; } int kvm_arch_release_virq_post(int virq) -- Gitee From 3d2254fd1a9705add074dd8849f761cf9bea7ced Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Mon, 24 Aug 2020 20:10:15 +0800 Subject: [PATCH 6/9] target/riscv: Support start kernel directly by KVM Get kernel and fdt start address in virt.c, and pass them to KVM when cpu reset. In addition, add kvm_riscv.h to place riscv specific interface. Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- hw/riscv/virt.c | 15 +++++++++++++-- target/riscv/cpu.c | 4 ++++ target/riscv/cpu.h | 3 +++ target/riscv/kvm.c | 13 +++++++++++++ target/riscv/kvm_riscv.h | 24 ++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 target/riscv/kvm_riscv.h diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index e01925ff3d..270c4a8876 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -43,6 +43,7 @@ #include "exec/address-spaces.h" #include "hw/pci/pci.h" #include "hw/pci-host/gpex.h" +#include "sysemu/kvm.h" #include @@ -498,6 +499,9 @@ static void riscv_virt_board_init(MachineState *machine) target_ulong start_addr = memmap[VIRT_DRAM].base; DeviceState *mmio_plic, *virtio_plic, *pcie_plic; int i, j, base_hartid, hart_count; + uint64_t kernel_entry = 0; + hwaddr start_fdt; + CPUState *cs; /* Check socket count limit */ if (VIRT_SOCKETS_MAX < riscv_socket_count(machine)) { @@ -607,7 +611,7 @@ static void riscv_virt_board_init(MachineState *machine) memmap[VIRT_DRAM].base, NULL); if (machine->kernel_filename) { - uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, + kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL); if (machine->initrd_filename) { @@ -661,10 +665,17 @@ static void riscv_virt_board_init(MachineState *machine) exit(1); } qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); + start_fdt = memmap[VIRT_MROM].base + sizeof(reset_vec); rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), - memmap[VIRT_MROM].base + sizeof(reset_vec), + start_fdt, &address_space_memory); + for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) { + RISCVCPU *riscv_cpu = RISCV_CPU(cs); + riscv_cpu->env.loader_start = kernel_entry; + riscv_cpu->env.fdt_start = start_fdt; + } + /* SiFive Test MMIO device */ sifive_test_create(memmap[VIRT_TEST].base); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index eeb91f8513..73af94efbd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -28,6 +28,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "fpu/softfloat-helpers.h" +#include "kvm_riscv.h" /* RISC-V CPU definitions */ @@ -336,6 +337,9 @@ static void riscv_cpu_reset(DeviceState *dev) cs->exception_index = EXCP_NONE; env->load_res = -1; set_default_nan_mode(1, &env->fp_status); +#ifdef CONFIG_KVM + kvm_riscv_reset_vcpu(cpu); +#endif } static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 1bb5271511..df6d95b162 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -206,6 +206,9 @@ struct CPURISCVState { /* Fields from here on are preserved across CPU reset. */ QEMUTimer *timer; /* Internal timer */ + + hwaddr loader_start; + hwaddr fdt_start; }; #define RISCV_CPU_CLASS(klass) \ diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 9810a02b49..8cc9daaba9 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -37,6 +37,7 @@ #include "hw/irq.h" #include "qemu/log.h" #include "hw/loader.h" +#include "kvm_riscv.h" static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) { @@ -426,3 +427,15 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { return 0; } + +void kvm_riscv_reset_vcpu(RISCVCPU *cpu) +{ + CPURISCVState *env = &cpu->env; + + if (!kvm_enabled()) { + return; + } + env->pc = cpu->env.loader_start; + env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ + env->gpr[11] = cpu->env.fdt_start; /* a1 */ +} diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h new file mode 100644 index 0000000000..80a4ee721a --- /dev/null +++ b/target/riscv/kvm_riscv.h @@ -0,0 +1,24 @@ +/* + * QEMU KVM support -- RISC-V specific functions. + * + * Copyright (c) 2020 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see ;. + */ + +#ifndef QEMU_KVM_RISCV_H +#define QEMU_KVM_RISCV_H + +void kvm_riscv_reset_vcpu(RISCVCPU *cpu); + +#endif -- Gitee From 801cfa825bbbfffbb6bc29118513abfa96db44cd Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Mon, 24 Aug 2020 20:24:25 +0800 Subject: [PATCH 7/9] hw/riscv: PLIC update external interrupt by KVM when kvm enabled Only support supervisor external interrupt currently. Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- hw/riscv/sifive_plic.c | 31 ++++++++++++++++++++++--------- target/riscv/kvm.c | 20 ++++++++++++++++++++ target/riscv/kvm_riscv.h | 1 + 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c index f88bb48053..be2fb0706e 100644 --- a/hw/riscv/sifive_plic.c +++ b/hw/riscv/sifive_plic.c @@ -29,6 +29,8 @@ #include "target/riscv/cpu.h" #include "sysemu/sysemu.h" #include "hw/riscv/sifive_plic.h" +#include "sysemu/kvm.h" +#include "kvm_riscv.h" #define RISCV_DEBUG_PLIC 0 @@ -145,15 +147,26 @@ static void sifive_plic_update(SiFivePLICState *plic) continue; } int level = sifive_plic_irqs_pending(plic, addrid); - switch (mode) { - case PLICMode_M: - riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level)); - break; - case PLICMode_S: - riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, BOOL_TO_MASK(level)); - break; - default: - break; + if (kvm_enabled()) { + if (mode == PLICMode_M) { + continue; + } +#ifdef CONFIG_KVM + kvm_riscv_set_irq(RISCV_CPU(cpu), IRQ_S_EXT, level); +#endif + } else { + switch (mode) { + case PLICMode_M: + riscv_cpu_update_mip(RISCV_CPU(cpu), + MIP_MEIP, BOOL_TO_MASK(level)); + break; + case PLICMode_S: + riscv_cpu_update_mip(RISCV_CPU(cpu), + MIP_SEIP, BOOL_TO_MASK(level)); + break; + default: + break; + } } } diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 8cc9daaba9..6460746b2d 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -439,3 +439,23 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu) env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ env->gpr[11] = cpu->env.fdt_start; /* a1 */ } + +void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level) +{ + int ret; + unsigned virq = level ? KVM_INTERRUPT_SET : KVM_INTERRUPT_UNSET; + + if (irq != IRQ_S_EXT) { + return; + } + + if (!kvm_enabled()) { + return; + } + + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); + if (ret < 0) { + perror("Set irq failed"); + abort(); + } +} diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h index 80a4ee721a..b3ab2c3d96 100644 --- a/target/riscv/kvm_riscv.h +++ b/target/riscv/kvm_riscv.h @@ -20,5 +20,6 @@ #define QEMU_KVM_RISCV_H void kvm_riscv_reset_vcpu(RISCVCPU *cpu); +void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level); #endif -- Gitee From ce7cf415ce371ff10d9de60c5e009531f1989d05 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Mon, 24 Aug 2020 20:25:16 +0800 Subject: [PATCH 8/9] target/riscv: Handler KVM_EXIT_RISCV_SBI exit Use char-fe handler console sbi call, which implement early console io while apply 'earlycon=sbi' into kernel parameters. The common SBI interface sbi_ecall_interface.h is introduced from https://github.com/riscv/opensbi/blob/master/include/sbi/sbi_ecall_interface.h. Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- target/riscv/kvm.c | 42 ++++++++++++++++- target/riscv/sbi_ecall_interface.h | 72 ++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 target/riscv/sbi_ecall_interface.h diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 6460746b2d..d0d02aad5c 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -38,6 +38,8 @@ #include "qemu/log.h" #include "hw/loader.h" #include "kvm_riscv.h" +#include "sbi_ecall_interface.h" +#include "chardev/char-fe.h" static __u64 kvm_riscv_reg_id(__u64 type, __u64 idx) { @@ -423,9 +425,47 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs) return true; } +static int kvm_riscv_handle_sbi(struct kvm_run *run) +{ + int ret = 0; + unsigned char ch; + switch (run->riscv_sbi.extension_id) { + case SBI_EXT_0_1_CONSOLE_PUTCHAR: + ch = run->riscv_sbi.args[0]; + qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch)); + break; + case SBI_EXT_0_1_CONSOLE_GETCHAR: + ret = qemu_chr_fe_read_all(serial_hd(0)->be, &ch, sizeof(ch)); + if (ret == sizeof(ch)) { + run->riscv_sbi.args[0] = ch; + } else { + run->riscv_sbi.args[0] = -1; + } + break; + default: + qemu_log_mask(LOG_UNIMP, + "%s: un-handled SBI EXIT, specific reasons is %lu\n", + __func__, run->riscv_sbi.extension_id); + ret = -1; + break; + } + return ret; +} + int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { - return 0; + int ret = 0; + switch (run->exit_reason) { + case KVM_EXIT_RISCV_SBI: + ret = kvm_riscv_handle_sbi(run); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", + __func__, run->exit_reason); + ret = -1; + break; + } + return ret; } void kvm_riscv_reset_vcpu(RISCVCPU *cpu) diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h new file mode 100644 index 0000000000..d8f3cb3ba5 --- /dev/null +++ b/target/riscv/sbi_ecall_interface.h @@ -0,0 +1,72 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel Date: Mon, 24 Aug 2020 20:25:41 +0800 Subject: [PATCH 9/9] target/riscv: add host cpu type Currently, host cpu is inherited simply. Signed-off-by: Yifei Jiang Signed-off-by: Yipeng Yin --- target/riscv/cpu.c | 6 ++++++ target/riscv/cpu.h | 1 + 2 files changed, 7 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 73af94efbd..b7de444fbf 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -192,6 +192,10 @@ static void rv64imacu_nommu_cpu_init(Object *obj) set_feature(env, RISCV_FEATURE_PMP); } +static void riscv_host_cpu_init(Object *obj) +{ +} + #endif static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) @@ -603,10 +607,12 @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), #elif defined(TARGET_RISCV64) DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base64_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64imacu_nommu_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64gcsu_priv1_10_0_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), #endif }; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index df6d95b162..f69f38df75 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -40,6 +40,7 @@ #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") +#define TYPE_RISCV_CPU_HOST RISCV_CPU_TYPE_NAME("host") #define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2)) #define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2)) -- Gitee