1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2019 Western Digital Corporation or its affiliates. 4 * 5 * Authors: 6 * Anup Patel <anup.patel@wdc.com> 7 */ 8 9 #include <linux/errno.h> 10 #include <linux/err.h> 11 #include <linux/module.h> 12 #include <linux/kvm_host.h> 13 #include <asm/csr.h> 14 #include <asm/hwcap.h> 15 #include <asm/sbi.h> 16 17 long kvm_arch_dev_ioctl(struct file *filp, 18 unsigned int ioctl, unsigned long arg) 19 { 20 return -EINVAL; 21 } 22 23 int kvm_arch_check_processor_compat(void *opaque) 24 { 25 return 0; 26 } 27 28 int kvm_arch_hardware_setup(void *opaque) 29 { 30 return 0; 31 } 32 33 int kvm_arch_hardware_enable(void) 34 { 35 unsigned long hideleg, hedeleg; 36 37 hedeleg = 0; 38 hedeleg |= (1UL << EXC_INST_MISALIGNED); 39 hedeleg |= (1UL << EXC_BREAKPOINT); 40 hedeleg |= (1UL << EXC_SYSCALL); 41 hedeleg |= (1UL << EXC_INST_PAGE_FAULT); 42 hedeleg |= (1UL << EXC_LOAD_PAGE_FAULT); 43 hedeleg |= (1UL << EXC_STORE_PAGE_FAULT); 44 csr_write(CSR_HEDELEG, hedeleg); 45 46 hideleg = 0; 47 hideleg |= (1UL << IRQ_VS_SOFT); 48 hideleg |= (1UL << IRQ_VS_TIMER); 49 hideleg |= (1UL << IRQ_VS_EXT); 50 csr_write(CSR_HIDELEG, hideleg); 51 52 csr_write(CSR_HCOUNTEREN, -1UL); 53 54 csr_write(CSR_HVIP, 0); 55 56 return 0; 57 } 58 59 void kvm_arch_hardware_disable(void) 60 { 61 csr_write(CSR_HEDELEG, 0); 62 csr_write(CSR_HIDELEG, 0); 63 } 64 65 int kvm_arch_init(void *opaque) 66 { 67 const char *str; 68 69 if (!riscv_isa_extension_available(NULL, h)) { 70 kvm_info("hypervisor extension not available\n"); 71 return -ENODEV; 72 } 73 74 if (sbi_spec_is_0_1()) { 75 kvm_info("require SBI v0.2 or higher\n"); 76 return -ENODEV; 77 } 78 79 if (sbi_probe_extension(SBI_EXT_RFENCE) <= 0) { 80 kvm_info("require SBI RFENCE extension\n"); 81 return -ENODEV; 82 } 83 84 kvm_riscv_stage2_mode_detect(); 85 86 kvm_riscv_stage2_vmid_detect(); 87 88 kvm_info("hypervisor extension available\n"); 89 90 switch (kvm_riscv_stage2_mode()) { 91 case HGATP_MODE_SV32X4: 92 str = "Sv32x4"; 93 break; 94 case HGATP_MODE_SV39X4: 95 str = "Sv39x4"; 96 break; 97 case HGATP_MODE_SV48X4: 98 str = "Sv48x4"; 99 break; 100 default: 101 return -ENODEV; 102 } 103 kvm_info("using %s G-stage page table format\n", str); 104 105 kvm_info("VMID %ld bits available\n", kvm_riscv_stage2_vmid_bits()); 106 107 return 0; 108 } 109 110 void kvm_arch_exit(void) 111 { 112 } 113 114 static int riscv_kvm_init(void) 115 { 116 return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); 117 } 118 module_init(riscv_kvm_init); 119