Commit 9d05c1fe authored by Anup Patel's avatar Anup Patel Committed by Anup Patel

RISC-V: KVM: Implement stage2 page table programming

This patch implements all required functions for programming
the stage2 page table for each Guest/VM.

At high-level, the flow of stage2 related functions is similar
from KVM ARM/ARM64 implementation but the stage2 page table
format is quite different for KVM RISC-V.

[jiangyifei: stage2 dirty log support]
Signed-off-by: default avatarYifei Jiang <jiangyifei@huawei.com>
Signed-off-by: default avatarAnup Patel <anup.patel@wdc.com>
Acked-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Acked-by: default avatarPalmer Dabbelt <palmerdabbelt@google.com>
parent fd7bb4a2
...@@ -70,6 +70,13 @@ struct kvm_mmio_decode { ...@@ -70,6 +70,13 @@ struct kvm_mmio_decode {
int return_handled; int return_handled;
}; };
#define KVM_MMU_PAGE_CACHE_NR_OBJS 32
struct kvm_mmu_page_cache {
int nobjs;
void *objects[KVM_MMU_PAGE_CACHE_NR_OBJS];
};
struct kvm_cpu_trap { struct kvm_cpu_trap {
unsigned long sepc; unsigned long sepc;
unsigned long scause; unsigned long scause;
...@@ -171,6 +178,9 @@ struct kvm_vcpu_arch { ...@@ -171,6 +178,9 @@ struct kvm_vcpu_arch {
/* MMIO instruction details */ /* MMIO instruction details */
struct kvm_mmio_decode mmio_decode; struct kvm_mmio_decode mmio_decode;
/* Cache pages needed to program page tables with spinlock held */
struct kvm_mmu_page_cache mmu_page_cache;
/* VCPU power-off state */ /* VCPU power-off state */
bool power_off; bool power_off;
...@@ -198,6 +208,8 @@ void kvm_riscv_stage2_flush_cache(struct kvm_vcpu *vcpu); ...@@ -198,6 +208,8 @@ void kvm_riscv_stage2_flush_cache(struct kvm_vcpu *vcpu);
int kvm_riscv_stage2_alloc_pgd(struct kvm *kvm); int kvm_riscv_stage2_alloc_pgd(struct kvm *kvm);
void kvm_riscv_stage2_free_pgd(struct kvm *kvm); void kvm_riscv_stage2_free_pgd(struct kvm *kvm);
void kvm_riscv_stage2_update_hgatp(struct kvm_vcpu *vcpu); void kvm_riscv_stage2_update_hgatp(struct kvm_vcpu *vcpu);
void kvm_riscv_stage2_mode_detect(void);
unsigned long kvm_riscv_stage2_mode(void);
void kvm_riscv_stage2_vmid_detect(void); void kvm_riscv_stage2_vmid_detect(void);
unsigned long kvm_riscv_stage2_vmid_bits(void); unsigned long kvm_riscv_stage2_vmid_bits(void);
......
...@@ -23,6 +23,7 @@ config KVM ...@@ -23,6 +23,7 @@ config KVM
select PREEMPT_NOTIFIERS select PREEMPT_NOTIFIERS
select ANON_INODES select ANON_INODES
select KVM_MMIO select KVM_MMIO
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select HAVE_KVM_VCPU_ASYNC_IOCTL select HAVE_KVM_VCPU_ASYNC_IOCTL
select HAVE_KVM_EVENTFD select HAVE_KVM_EVENTFD
select SRCU select SRCU
......
...@@ -64,6 +64,8 @@ void kvm_arch_hardware_disable(void) ...@@ -64,6 +64,8 @@ void kvm_arch_hardware_disable(void)
int kvm_arch_init(void *opaque) int kvm_arch_init(void *opaque)
{ {
const char *str;
if (!riscv_isa_extension_available(NULL, h)) { if (!riscv_isa_extension_available(NULL, h)) {
kvm_info("hypervisor extension not available\n"); kvm_info("hypervisor extension not available\n");
return -ENODEV; return -ENODEV;
...@@ -79,10 +81,27 @@ int kvm_arch_init(void *opaque) ...@@ -79,10 +81,27 @@ int kvm_arch_init(void *opaque)
return -ENODEV; return -ENODEV;
} }
kvm_riscv_stage2_mode_detect();
kvm_riscv_stage2_vmid_detect(); kvm_riscv_stage2_vmid_detect();
kvm_info("hypervisor extension available\n"); kvm_info("hypervisor extension available\n");
switch (kvm_riscv_stage2_mode()) {
case HGATP_MODE_SV32X4:
str = "Sv32x4";
break;
case HGATP_MODE_SV39X4:
str = "Sv39x4";
break;
case HGATP_MODE_SV48X4:
str = "Sv48x4";
break;
default:
return -ENODEV;
}
kvm_info("using %s G-stage page table format\n", str);
kvm_info("VMID %ld bits available\n", kvm_riscv_stage2_vmid_bits()); kvm_info("VMID %ld bits available\n", kvm_riscv_stage2_vmid_bits());
return 0; return 0;
......
This diff is collapsed.
...@@ -27,12 +27,6 @@ const struct kvm_stats_header kvm_vm_stats_header = { ...@@ -27,12 +27,6 @@ const struct kvm_stats_header kvm_vm_stats_header = {
sizeof(kvm_vm_stats_desc), sizeof(kvm_vm_stats_desc),
}; };
int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
{
/* TODO: To be added later. */
return -EOPNOTSUPP;
}
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{ {
int r; int r;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment