-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RISC-V: Add initial skeletal KVM support
This patch adds initial skeletal KVM RISC-V support which has: 1. A simple implementation of arch specific VM functions except kvm_vm_ioctl_get_dirty_log() which will implemeted in-future as part of stage2 page loging. 2. Stubs of required arch specific VCPU functions except kvm_arch_vcpu_ioctl_run() which is semi-complete and extended by subsequent patches. 3. Stubs for required arch specific stage2 MMU functions. Signed-off-by: Anup Patel <[email protected]> Acked-by: Paolo Bonzini <[email protected]> Reviewed-by: Paolo Bonzini <[email protected]> Reviewed-by: Alexander Graf <[email protected]> Acked-by: Palmer Dabbelt <[email protected]>
- Loading branch information
Showing
12 changed files
with
805 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -562,4 +562,5 @@ source "kernel/power/Kconfig" | |
|
||
endmenu | ||
|
||
source "arch/riscv/kvm/Kconfig" | ||
source "drivers/firmware/Kconfig" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-only */ | ||
/* | ||
* Copyright (C) 2019 Western Digital Corporation or its affiliates. | ||
* | ||
* Authors: | ||
* Anup Patel <[email protected]> | ||
*/ | ||
|
||
#ifndef __RISCV_KVM_HOST_H__ | ||
#define __RISCV_KVM_HOST_H__ | ||
|
||
#include <linux/types.h> | ||
#include <linux/kvm.h> | ||
#include <linux/kvm_types.h> | ||
|
||
#ifdef CONFIG_64BIT | ||
#define KVM_MAX_VCPUS (1U << 16) | ||
#else | ||
#define KVM_MAX_VCPUS (1U << 9) | ||
#endif | ||
|
||
#define KVM_HALT_POLL_NS_DEFAULT 500000 | ||
|
||
#define KVM_VCPU_MAX_FEATURES 0 | ||
|
||
#define KVM_REQ_SLEEP \ | ||
KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) | ||
#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(1) | ||
|
||
struct kvm_vm_stat { | ||
struct kvm_vm_stat_generic generic; | ||
}; | ||
|
||
struct kvm_vcpu_stat { | ||
struct kvm_vcpu_stat_generic generic; | ||
u64 ecall_exit_stat; | ||
u64 wfi_exit_stat; | ||
u64 mmio_exit_user; | ||
u64 mmio_exit_kernel; | ||
u64 exits; | ||
}; | ||
|
||
struct kvm_arch_memory_slot { | ||
}; | ||
|
||
struct kvm_arch { | ||
/* stage2 page table */ | ||
pgd_t *pgd; | ||
phys_addr_t pgd_phys; | ||
}; | ||
|
||
struct kvm_cpu_trap { | ||
unsigned long sepc; | ||
unsigned long scause; | ||
unsigned long stval; | ||
unsigned long htval; | ||
unsigned long htinst; | ||
}; | ||
|
||
struct kvm_vcpu_arch { | ||
/* Don't run the VCPU (blocked) */ | ||
bool pause; | ||
|
||
/* SRCU lock index for in-kernel run loop */ | ||
int srcu_idx; | ||
}; | ||
|
||
static inline void kvm_arch_hardware_unsetup(void) {} | ||
static inline void kvm_arch_sync_events(struct kvm *kvm) {} | ||
static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {} | ||
static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {} | ||
|
||
void kvm_riscv_stage2_flush_cache(struct kvm_vcpu *vcpu); | ||
int kvm_riscv_stage2_alloc_pgd(struct kvm *kvm); | ||
void kvm_riscv_stage2_free_pgd(struct kvm *kvm); | ||
void kvm_riscv_stage2_update_hgatp(struct kvm_vcpu *vcpu); | ||
|
||
int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, | ||
struct kvm_cpu_trap *trap); | ||
|
||
static inline void __kvm_riscv_switch_to(struct kvm_vcpu_arch *vcpu_arch) {} | ||
|
||
#endif /* __RISCV_KVM_HOST_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef _ASM_RISCV_KVM_TYPES_H | ||
#define _ASM_RISCV_KVM_TYPES_H | ||
|
||
#define KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE 40 | ||
|
||
#endif /* _ASM_RISCV_KVM_TYPES_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ | ||
/* | ||
* Copyright (C) 2019 Western Digital Corporation or its affiliates. | ||
* | ||
* Authors: | ||
* Anup Patel <[email protected]> | ||
*/ | ||
|
||
#ifndef __LINUX_KVM_RISCV_H | ||
#define __LINUX_KVM_RISCV_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#include <linux/types.h> | ||
#include <asm/ptrace.h> | ||
|
||
#define __KVM_HAVE_READONLY_MEM | ||
|
||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 | ||
|
||
/* for KVM_GET_REGS and KVM_SET_REGS */ | ||
struct kvm_regs { | ||
}; | ||
|
||
/* for KVM_GET_FPU and KVM_SET_FPU */ | ||
struct kvm_fpu { | ||
}; | ||
|
||
/* KVM Debug exit structure */ | ||
struct kvm_debug_exit_arch { | ||
}; | ||
|
||
/* for KVM_SET_GUEST_DEBUG */ | ||
struct kvm_guest_debug_arch { | ||
}; | ||
|
||
/* definition of registers in kvm_run */ | ||
struct kvm_sync_regs { | ||
}; | ||
|
||
/* dummy definition */ | ||
struct kvm_sregs { | ||
}; | ||
|
||
#endif | ||
|
||
#endif /* __LINUX_KVM_RISCV_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# SPDX-License-Identifier: GPL-2.0 | ||
# | ||
# KVM configuration | ||
# | ||
|
||
source "virt/kvm/Kconfig" | ||
|
||
menuconfig VIRTUALIZATION | ||
bool "Virtualization" | ||
help | ||
Say Y here to get to see options for using your Linux host to run | ||
other operating systems inside virtual machines (guests). | ||
This option alone does not add any kernel code. | ||
|
||
If you say N, all options in this submenu will be skipped and | ||
disabled. | ||
|
||
if VIRTUALIZATION | ||
|
||
config KVM | ||
tristate "Kernel-based Virtual Machine (KVM) support (EXPERIMENTAL)" | ||
depends on RISCV_SBI && MMU | ||
select PREEMPT_NOTIFIERS | ||
select ANON_INODES | ||
select KVM_MMIO | ||
select HAVE_KVM_VCPU_ASYNC_IOCTL | ||
select SRCU | ||
help | ||
Support hosting virtualized guest machines. | ||
|
||
If unsure, say N. | ||
|
||
endif # VIRTUALIZATION |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# SPDX-License-Identifier: GPL-2.0 | ||
# | ||
# Makefile for RISC-V KVM support | ||
# | ||
|
||
ccflags-y += -I $(srctree)/$(src) | ||
|
||
KVM := ../../../virt/kvm | ||
|
||
obj-$(CONFIG_KVM) += kvm.o | ||
|
||
kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/binary_stats.o \ | ||
main.o vm.o mmu.o vcpu.o vcpu_exit.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copyright (C) 2019 Western Digital Corporation or its affiliates. | ||
* | ||
* Authors: | ||
* Anup Patel <[email protected]> | ||
*/ | ||
|
||
#include <linux/errno.h> | ||
#include <linux/err.h> | ||
#include <linux/module.h> | ||
#include <linux/kvm_host.h> | ||
#include <asm/csr.h> | ||
#include <asm/hwcap.h> | ||
#include <asm/sbi.h> | ||
|
||
long kvm_arch_dev_ioctl(struct file *filp, | ||
unsigned int ioctl, unsigned long arg) | ||
{ | ||
return -EINVAL; | ||
} | ||
|
||
int kvm_arch_check_processor_compat(void *opaque) | ||
{ | ||
return 0; | ||
} | ||
|
||
int kvm_arch_hardware_setup(void *opaque) | ||
{ | ||
return 0; | ||
} | ||
|
||
int kvm_arch_hardware_enable(void) | ||
{ | ||
unsigned long hideleg, hedeleg; | ||
|
||
hedeleg = 0; | ||
hedeleg |= (1UL << EXC_INST_MISALIGNED); | ||
hedeleg |= (1UL << EXC_BREAKPOINT); | ||
hedeleg |= (1UL << EXC_SYSCALL); | ||
hedeleg |= (1UL << EXC_INST_PAGE_FAULT); | ||
hedeleg |= (1UL << EXC_LOAD_PAGE_FAULT); | ||
hedeleg |= (1UL << EXC_STORE_PAGE_FAULT); | ||
csr_write(CSR_HEDELEG, hedeleg); | ||
|
||
hideleg = 0; | ||
hideleg |= (1UL << IRQ_VS_SOFT); | ||
hideleg |= (1UL << IRQ_VS_TIMER); | ||
hideleg |= (1UL << IRQ_VS_EXT); | ||
csr_write(CSR_HIDELEG, hideleg); | ||
|
||
csr_write(CSR_HCOUNTEREN, -1UL); | ||
|
||
csr_write(CSR_HVIP, 0); | ||
|
||
return 0; | ||
} | ||
|
||
void kvm_arch_hardware_disable(void) | ||
{ | ||
csr_write(CSR_HEDELEG, 0); | ||
csr_write(CSR_HIDELEG, 0); | ||
} | ||
|
||
int kvm_arch_init(void *opaque) | ||
{ | ||
if (!riscv_isa_extension_available(NULL, h)) { | ||
kvm_info("hypervisor extension not available\n"); | ||
return -ENODEV; | ||
} | ||
|
||
if (sbi_spec_is_0_1()) { | ||
kvm_info("require SBI v0.2 or higher\n"); | ||
return -ENODEV; | ||
} | ||
|
||
if (sbi_probe_extension(SBI_EXT_RFENCE) <= 0) { | ||
kvm_info("require SBI RFENCE extension\n"); | ||
return -ENODEV; | ||
} | ||
|
||
kvm_info("hypervisor extension available\n"); | ||
|
||
return 0; | ||
} | ||
|
||
void kvm_arch_exit(void) | ||
{ | ||
} | ||
|
||
static int riscv_kvm_init(void) | ||
{ | ||
return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); | ||
} | ||
module_init(riscv_kvm_init); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copyright (C) 2019 Western Digital Corporation or its affiliates. | ||
* | ||
* Authors: | ||
* Anup Patel <[email protected]> | ||
*/ | ||
|
||
#include <linux/bitops.h> | ||
#include <linux/errno.h> | ||
#include <linux/err.h> | ||
#include <linux/hugetlb.h> | ||
#include <linux/module.h> | ||
#include <linux/uaccess.h> | ||
#include <linux/vmalloc.h> | ||
#include <linux/kvm_host.h> | ||
#include <linux/sched/signal.h> | ||
#include <asm/page.h> | ||
#include <asm/pgtable.h> | ||
|
||
void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot) | ||
{ | ||
} | ||
|
||
void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free) | ||
{ | ||
} | ||
|
||
void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen) | ||
{ | ||
} | ||
|
||
void kvm_arch_flush_shadow_all(struct kvm *kvm) | ||
{ | ||
/* TODO: */ | ||
} | ||
|
||
void kvm_arch_flush_shadow_memslot(struct kvm *kvm, | ||
struct kvm_memory_slot *slot) | ||
{ | ||
} | ||
|
||
void kvm_arch_commit_memory_region(struct kvm *kvm, | ||
const struct kvm_userspace_memory_region *mem, | ||
struct kvm_memory_slot *old, | ||
const struct kvm_memory_slot *new, | ||
enum kvm_mr_change change) | ||
{ | ||
/* TODO: */ | ||
} | ||
|
||
int kvm_arch_prepare_memory_region(struct kvm *kvm, | ||
struct kvm_memory_slot *memslot, | ||
const struct kvm_userspace_memory_region *mem, | ||
enum kvm_mr_change change) | ||
{ | ||
/* TODO: */ | ||
return 0; | ||
} | ||
|
||
void kvm_riscv_stage2_flush_cache(struct kvm_vcpu *vcpu) | ||
{ | ||
/* TODO: */ | ||
} | ||
|
||
int kvm_riscv_stage2_alloc_pgd(struct kvm *kvm) | ||
{ | ||
/* TODO: */ | ||
return 0; | ||
} | ||
|
||
void kvm_riscv_stage2_free_pgd(struct kvm *kvm) | ||
{ | ||
/* TODO: */ | ||
} | ||
|
||
void kvm_riscv_stage2_update_hgatp(struct kvm_vcpu *vcpu) | ||
{ | ||
/* TODO: */ | ||
} |
Oops, something went wrong.