RISC-V: KVM: Factor-out ISA checks into separate sources
The KVM ISA extension related checks are not VCPU specific and should be factored out of vcpu_onereg.c into separate sources. Signed-off-by: Anup Patel <anup.patel@oss.qualcomm.com> Reviewed-by: Radim Krčmář <radim.krcmar@oss.qualcomm.com> Link: https://lore.kernel.org/r/20260120080013.2153519-6-anup.patel@oss.qualcomm.com Signed-off-by: Anup Patel <anup@brainfault.org>master
parent
cf05b059d5
commit
e0b5cfc316
|
|
@ -311,10 +311,6 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
|||
|
||||
void __kvm_riscv_switch_to(struct kvm_vcpu_arch *vcpu_arch);
|
||||
|
||||
int __kvm_riscv_isa_check_host(unsigned long kvm_ext, unsigned long *guest_ext);
|
||||
#define kvm_riscv_isa_check_host(ext) \
|
||||
__kvm_riscv_isa_check_host(KVM_RISCV_ISA_EXT_##ext, NULL)
|
||||
|
||||
void kvm_riscv_vcpu_setup_isa(struct kvm_vcpu *vcpu);
|
||||
unsigned long kvm_riscv_vcpu_num_regs(struct kvm_vcpu *vcpu);
|
||||
int kvm_riscv_vcpu_copy_reg_indices(struct kvm_vcpu *vcpu,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2026 Qualcomm Technologies, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __KVM_RISCV_ISA_H
|
||||
#define __KVM_RISCV_ISA_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
unsigned long kvm_riscv_base2isa_ext(unsigned long base_ext);
|
||||
|
||||
int __kvm_riscv_isa_check_host(unsigned long ext, unsigned long *base_ext);
|
||||
#define kvm_riscv_isa_check_host(ext) \
|
||||
__kvm_riscv_isa_check_host(KVM_RISCV_ISA_EXT_##ext, NULL)
|
||||
|
||||
bool kvm_riscv_isa_enable_allowed(unsigned long ext);
|
||||
bool kvm_riscv_isa_disable_allowed(unsigned long ext);
|
||||
|
||||
#endif
|
||||
|
|
@ -15,6 +15,7 @@ kvm-y += aia_aplic.o
|
|||
kvm-y += aia_device.o
|
||||
kvm-y += aia_imsic.o
|
||||
kvm-y += gstage.o
|
||||
kvm-y += isa.o
|
||||
kvm-y += main.o
|
||||
kvm-y += mmu.o
|
||||
kvm-y += nacl.o
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include <linux/irqchip/riscv-imsic.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <asm/kvm_isa.h>
|
||||
|
||||
static int aia_create(struct kvm_device *dev, u32 type)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,253 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2026 Qualcomm Technologies, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <asm/kvm_isa.h>
|
||||
#include <asm/vector.h>
|
||||
|
||||
#define KVM_ISA_EXT_ARR(ext) \
|
||||
[KVM_RISCV_ISA_EXT_##ext] = RISCV_ISA_EXT_##ext
|
||||
|
||||
/* Mapping between KVM ISA Extension ID & guest ISA extension ID */
|
||||
static const unsigned long kvm_isa_ext_arr[] = {
|
||||
/* Single letter extensions (alphabetically sorted) */
|
||||
[KVM_RISCV_ISA_EXT_A] = RISCV_ISA_EXT_a,
|
||||
[KVM_RISCV_ISA_EXT_C] = RISCV_ISA_EXT_c,
|
||||
[KVM_RISCV_ISA_EXT_D] = RISCV_ISA_EXT_d,
|
||||
[KVM_RISCV_ISA_EXT_F] = RISCV_ISA_EXT_f,
|
||||
[KVM_RISCV_ISA_EXT_H] = RISCV_ISA_EXT_h,
|
||||
[KVM_RISCV_ISA_EXT_I] = RISCV_ISA_EXT_i,
|
||||
[KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
|
||||
[KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
|
||||
/* Multi letter extensions (alphabetically sorted) */
|
||||
KVM_ISA_EXT_ARR(SMNPM),
|
||||
KVM_ISA_EXT_ARR(SMSTATEEN),
|
||||
KVM_ISA_EXT_ARR(SSAIA),
|
||||
KVM_ISA_EXT_ARR(SSCOFPMF),
|
||||
KVM_ISA_EXT_ARR(SSNPM),
|
||||
KVM_ISA_EXT_ARR(SSTC),
|
||||
KVM_ISA_EXT_ARR(SVADE),
|
||||
KVM_ISA_EXT_ARR(SVADU),
|
||||
KVM_ISA_EXT_ARR(SVINVAL),
|
||||
KVM_ISA_EXT_ARR(SVNAPOT),
|
||||
KVM_ISA_EXT_ARR(SVPBMT),
|
||||
KVM_ISA_EXT_ARR(SVVPTC),
|
||||
KVM_ISA_EXT_ARR(ZAAMO),
|
||||
KVM_ISA_EXT_ARR(ZABHA),
|
||||
KVM_ISA_EXT_ARR(ZACAS),
|
||||
KVM_ISA_EXT_ARR(ZALASR),
|
||||
KVM_ISA_EXT_ARR(ZALRSC),
|
||||
KVM_ISA_EXT_ARR(ZAWRS),
|
||||
KVM_ISA_EXT_ARR(ZBA),
|
||||
KVM_ISA_EXT_ARR(ZBB),
|
||||
KVM_ISA_EXT_ARR(ZBC),
|
||||
KVM_ISA_EXT_ARR(ZBKB),
|
||||
KVM_ISA_EXT_ARR(ZBKC),
|
||||
KVM_ISA_EXT_ARR(ZBKX),
|
||||
KVM_ISA_EXT_ARR(ZBS),
|
||||
KVM_ISA_EXT_ARR(ZCA),
|
||||
KVM_ISA_EXT_ARR(ZCB),
|
||||
KVM_ISA_EXT_ARR(ZCD),
|
||||
KVM_ISA_EXT_ARR(ZCF),
|
||||
KVM_ISA_EXT_ARR(ZCLSD),
|
||||
KVM_ISA_EXT_ARR(ZCMOP),
|
||||
KVM_ISA_EXT_ARR(ZFA),
|
||||
KVM_ISA_EXT_ARR(ZFBFMIN),
|
||||
KVM_ISA_EXT_ARR(ZFH),
|
||||
KVM_ISA_EXT_ARR(ZFHMIN),
|
||||
KVM_ISA_EXT_ARR(ZICBOM),
|
||||
KVM_ISA_EXT_ARR(ZICBOP),
|
||||
KVM_ISA_EXT_ARR(ZICBOZ),
|
||||
KVM_ISA_EXT_ARR(ZICCRSE),
|
||||
KVM_ISA_EXT_ARR(ZICNTR),
|
||||
KVM_ISA_EXT_ARR(ZICOND),
|
||||
KVM_ISA_EXT_ARR(ZICSR),
|
||||
KVM_ISA_EXT_ARR(ZIFENCEI),
|
||||
KVM_ISA_EXT_ARR(ZIHINTNTL),
|
||||
KVM_ISA_EXT_ARR(ZIHINTPAUSE),
|
||||
KVM_ISA_EXT_ARR(ZIHPM),
|
||||
KVM_ISA_EXT_ARR(ZILSD),
|
||||
KVM_ISA_EXT_ARR(ZIMOP),
|
||||
KVM_ISA_EXT_ARR(ZKND),
|
||||
KVM_ISA_EXT_ARR(ZKNE),
|
||||
KVM_ISA_EXT_ARR(ZKNH),
|
||||
KVM_ISA_EXT_ARR(ZKR),
|
||||
KVM_ISA_EXT_ARR(ZKSED),
|
||||
KVM_ISA_EXT_ARR(ZKSH),
|
||||
KVM_ISA_EXT_ARR(ZKT),
|
||||
KVM_ISA_EXT_ARR(ZTSO),
|
||||
KVM_ISA_EXT_ARR(ZVBB),
|
||||
KVM_ISA_EXT_ARR(ZVBC),
|
||||
KVM_ISA_EXT_ARR(ZVFBFMIN),
|
||||
KVM_ISA_EXT_ARR(ZVFBFWMA),
|
||||
KVM_ISA_EXT_ARR(ZVFH),
|
||||
KVM_ISA_EXT_ARR(ZVFHMIN),
|
||||
KVM_ISA_EXT_ARR(ZVKB),
|
||||
KVM_ISA_EXT_ARR(ZVKG),
|
||||
KVM_ISA_EXT_ARR(ZVKNED),
|
||||
KVM_ISA_EXT_ARR(ZVKNHA),
|
||||
KVM_ISA_EXT_ARR(ZVKNHB),
|
||||
KVM_ISA_EXT_ARR(ZVKSED),
|
||||
KVM_ISA_EXT_ARR(ZVKSH),
|
||||
KVM_ISA_EXT_ARR(ZVKT),
|
||||
};
|
||||
|
||||
unsigned long kvm_riscv_base2isa_ext(unsigned long base_ext)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) {
|
||||
if (kvm_isa_ext_arr[i] == base_ext)
|
||||
return i;
|
||||
}
|
||||
|
||||
return KVM_RISCV_ISA_EXT_MAX;
|
||||
}
|
||||
|
||||
int __kvm_riscv_isa_check_host(unsigned long kvm_ext, unsigned long *base_ext)
|
||||
{
|
||||
unsigned long host_ext;
|
||||
|
||||
if (kvm_ext >= KVM_RISCV_ISA_EXT_MAX ||
|
||||
kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr))
|
||||
return -ENOENT;
|
||||
|
||||
kvm_ext = array_index_nospec(kvm_ext, ARRAY_SIZE(kvm_isa_ext_arr));
|
||||
switch (kvm_isa_ext_arr[kvm_ext]) {
|
||||
case RISCV_ISA_EXT_SMNPM:
|
||||
/*
|
||||
* Pointer masking effective in (H)S-mode is provided by the
|
||||
* Smnpm extension, so that extension is reported to the guest,
|
||||
* even though the CSR bits for configuring VS-mode pointer
|
||||
* masking on the host side are part of the Ssnpm extension.
|
||||
*/
|
||||
host_ext = RISCV_ISA_EXT_SSNPM;
|
||||
break;
|
||||
default:
|
||||
host_ext = kvm_isa_ext_arr[kvm_ext];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!__riscv_isa_extension_available(NULL, host_ext))
|
||||
return -ENOENT;
|
||||
|
||||
if (base_ext)
|
||||
*base_ext = kvm_isa_ext_arr[kvm_ext];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool kvm_riscv_isa_enable_allowed(unsigned long ext)
|
||||
{
|
||||
switch (ext) {
|
||||
case KVM_RISCV_ISA_EXT_H:
|
||||
return false;
|
||||
case KVM_RISCV_ISA_EXT_SSCOFPMF:
|
||||
/* Sscofpmf depends on interrupt filtering defined in ssaia */
|
||||
return !kvm_riscv_isa_check_host(SSAIA);
|
||||
case KVM_RISCV_ISA_EXT_SVADU:
|
||||
/*
|
||||
* The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
|
||||
* Guest OS can use Svadu only when host OS enable Svadu.
|
||||
*/
|
||||
return arch_has_hw_pte_young();
|
||||
case KVM_RISCV_ISA_EXT_V:
|
||||
return riscv_v_vstate_ctrl_user_allowed();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kvm_riscv_isa_disable_allowed(unsigned long ext)
|
||||
{
|
||||
switch (ext) {
|
||||
/* Extensions which don't have any mechanism to disable */
|
||||
case KVM_RISCV_ISA_EXT_A:
|
||||
case KVM_RISCV_ISA_EXT_C:
|
||||
case KVM_RISCV_ISA_EXT_I:
|
||||
case KVM_RISCV_ISA_EXT_M:
|
||||
/* There is not architectural config bit to disable sscofpmf completely */
|
||||
case KVM_RISCV_ISA_EXT_SSCOFPMF:
|
||||
case KVM_RISCV_ISA_EXT_SSNPM:
|
||||
case KVM_RISCV_ISA_EXT_SSTC:
|
||||
case KVM_RISCV_ISA_EXT_SVINVAL:
|
||||
case KVM_RISCV_ISA_EXT_SVNAPOT:
|
||||
case KVM_RISCV_ISA_EXT_SVVPTC:
|
||||
case KVM_RISCV_ISA_EXT_ZAAMO:
|
||||
case KVM_RISCV_ISA_EXT_ZABHA:
|
||||
case KVM_RISCV_ISA_EXT_ZACAS:
|
||||
case KVM_RISCV_ISA_EXT_ZALASR:
|
||||
case KVM_RISCV_ISA_EXT_ZALRSC:
|
||||
case KVM_RISCV_ISA_EXT_ZAWRS:
|
||||
case KVM_RISCV_ISA_EXT_ZBA:
|
||||
case KVM_RISCV_ISA_EXT_ZBB:
|
||||
case KVM_RISCV_ISA_EXT_ZBC:
|
||||
case KVM_RISCV_ISA_EXT_ZBKB:
|
||||
case KVM_RISCV_ISA_EXT_ZBKC:
|
||||
case KVM_RISCV_ISA_EXT_ZBKX:
|
||||
case KVM_RISCV_ISA_EXT_ZBS:
|
||||
case KVM_RISCV_ISA_EXT_ZCA:
|
||||
case KVM_RISCV_ISA_EXT_ZCB:
|
||||
case KVM_RISCV_ISA_EXT_ZCD:
|
||||
case KVM_RISCV_ISA_EXT_ZCF:
|
||||
case KVM_RISCV_ISA_EXT_ZCMOP:
|
||||
case KVM_RISCV_ISA_EXT_ZFA:
|
||||
case KVM_RISCV_ISA_EXT_ZFBFMIN:
|
||||
case KVM_RISCV_ISA_EXT_ZFH:
|
||||
case KVM_RISCV_ISA_EXT_ZFHMIN:
|
||||
case KVM_RISCV_ISA_EXT_ZICBOP:
|
||||
case KVM_RISCV_ISA_EXT_ZICCRSE:
|
||||
case KVM_RISCV_ISA_EXT_ZICNTR:
|
||||
case KVM_RISCV_ISA_EXT_ZICOND:
|
||||
case KVM_RISCV_ISA_EXT_ZICSR:
|
||||
case KVM_RISCV_ISA_EXT_ZIFENCEI:
|
||||
case KVM_RISCV_ISA_EXT_ZIHINTNTL:
|
||||
case KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
|
||||
case KVM_RISCV_ISA_EXT_ZIHPM:
|
||||
case KVM_RISCV_ISA_EXT_ZIMOP:
|
||||
case KVM_RISCV_ISA_EXT_ZKND:
|
||||
case KVM_RISCV_ISA_EXT_ZKNE:
|
||||
case KVM_RISCV_ISA_EXT_ZKNH:
|
||||
case KVM_RISCV_ISA_EXT_ZKR:
|
||||
case KVM_RISCV_ISA_EXT_ZKSED:
|
||||
case KVM_RISCV_ISA_EXT_ZKSH:
|
||||
case KVM_RISCV_ISA_EXT_ZKT:
|
||||
case KVM_RISCV_ISA_EXT_ZTSO:
|
||||
case KVM_RISCV_ISA_EXT_ZVBB:
|
||||
case KVM_RISCV_ISA_EXT_ZVBC:
|
||||
case KVM_RISCV_ISA_EXT_ZVFBFMIN:
|
||||
case KVM_RISCV_ISA_EXT_ZVFBFWMA:
|
||||
case KVM_RISCV_ISA_EXT_ZVFH:
|
||||
case KVM_RISCV_ISA_EXT_ZVFHMIN:
|
||||
case KVM_RISCV_ISA_EXT_ZVKB:
|
||||
case KVM_RISCV_ISA_EXT_ZVKG:
|
||||
case KVM_RISCV_ISA_EXT_ZVKNED:
|
||||
case KVM_RISCV_ISA_EXT_ZVKNHA:
|
||||
case KVM_RISCV_ISA_EXT_ZVKNHB:
|
||||
case KVM_RISCV_ISA_EXT_ZVKSED:
|
||||
case KVM_RISCV_ISA_EXT_ZVKSH:
|
||||
case KVM_RISCV_ISA_EXT_ZVKT:
|
||||
return false;
|
||||
/* Extensions which can be disabled using Smstateen */
|
||||
case KVM_RISCV_ISA_EXT_SSAIA:
|
||||
return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN);
|
||||
case KVM_RISCV_ISA_EXT_SVADE:
|
||||
/*
|
||||
* The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
|
||||
* Svade can't be disabled unless we support Svadu.
|
||||
*/
|
||||
return arch_has_hw_pte_young();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/nospec.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/kvm_isa.h>
|
||||
|
||||
#ifdef CONFIG_FPU
|
||||
void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu *vcpu)
|
||||
|
|
|
|||
|
|
@ -15,261 +15,19 @@
|
|||
#include <linux/kvm_host.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/kvm_isa.h>
|
||||
#include <asm/kvm_vcpu_vector.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/vector.h>
|
||||
|
||||
#define KVM_RISCV_BASE_ISA_MASK GENMASK(25, 0)
|
||||
|
||||
#define KVM_ISA_EXT_ARR(ext) \
|
||||
[KVM_RISCV_ISA_EXT_##ext] = RISCV_ISA_EXT_##ext
|
||||
|
||||
/* Mapping between KVM ISA Extension ID & guest ISA extension ID */
|
||||
static const unsigned long kvm_isa_ext_arr[] = {
|
||||
/* Single letter extensions (alphabetically sorted) */
|
||||
[KVM_RISCV_ISA_EXT_A] = RISCV_ISA_EXT_a,
|
||||
[KVM_RISCV_ISA_EXT_C] = RISCV_ISA_EXT_c,
|
||||
[KVM_RISCV_ISA_EXT_D] = RISCV_ISA_EXT_d,
|
||||
[KVM_RISCV_ISA_EXT_F] = RISCV_ISA_EXT_f,
|
||||
[KVM_RISCV_ISA_EXT_H] = RISCV_ISA_EXT_h,
|
||||
[KVM_RISCV_ISA_EXT_I] = RISCV_ISA_EXT_i,
|
||||
[KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
|
||||
[KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
|
||||
/* Multi letter extensions (alphabetically sorted) */
|
||||
KVM_ISA_EXT_ARR(SMNPM),
|
||||
KVM_ISA_EXT_ARR(SMSTATEEN),
|
||||
KVM_ISA_EXT_ARR(SSAIA),
|
||||
KVM_ISA_EXT_ARR(SSCOFPMF),
|
||||
KVM_ISA_EXT_ARR(SSNPM),
|
||||
KVM_ISA_EXT_ARR(SSTC),
|
||||
KVM_ISA_EXT_ARR(SVADE),
|
||||
KVM_ISA_EXT_ARR(SVADU),
|
||||
KVM_ISA_EXT_ARR(SVINVAL),
|
||||
KVM_ISA_EXT_ARR(SVNAPOT),
|
||||
KVM_ISA_EXT_ARR(SVPBMT),
|
||||
KVM_ISA_EXT_ARR(SVVPTC),
|
||||
KVM_ISA_EXT_ARR(ZAAMO),
|
||||
KVM_ISA_EXT_ARR(ZABHA),
|
||||
KVM_ISA_EXT_ARR(ZACAS),
|
||||
KVM_ISA_EXT_ARR(ZALASR),
|
||||
KVM_ISA_EXT_ARR(ZALRSC),
|
||||
KVM_ISA_EXT_ARR(ZAWRS),
|
||||
KVM_ISA_EXT_ARR(ZBA),
|
||||
KVM_ISA_EXT_ARR(ZBB),
|
||||
KVM_ISA_EXT_ARR(ZBC),
|
||||
KVM_ISA_EXT_ARR(ZBKB),
|
||||
KVM_ISA_EXT_ARR(ZBKC),
|
||||
KVM_ISA_EXT_ARR(ZBKX),
|
||||
KVM_ISA_EXT_ARR(ZBS),
|
||||
KVM_ISA_EXT_ARR(ZCA),
|
||||
KVM_ISA_EXT_ARR(ZCB),
|
||||
KVM_ISA_EXT_ARR(ZCD),
|
||||
KVM_ISA_EXT_ARR(ZCF),
|
||||
KVM_ISA_EXT_ARR(ZCLSD),
|
||||
KVM_ISA_EXT_ARR(ZCMOP),
|
||||
KVM_ISA_EXT_ARR(ZFA),
|
||||
KVM_ISA_EXT_ARR(ZFBFMIN),
|
||||
KVM_ISA_EXT_ARR(ZFH),
|
||||
KVM_ISA_EXT_ARR(ZFHMIN),
|
||||
KVM_ISA_EXT_ARR(ZICBOM),
|
||||
KVM_ISA_EXT_ARR(ZICBOP),
|
||||
KVM_ISA_EXT_ARR(ZICBOZ),
|
||||
KVM_ISA_EXT_ARR(ZICCRSE),
|
||||
KVM_ISA_EXT_ARR(ZICNTR),
|
||||
KVM_ISA_EXT_ARR(ZICOND),
|
||||
KVM_ISA_EXT_ARR(ZICSR),
|
||||
KVM_ISA_EXT_ARR(ZIFENCEI),
|
||||
KVM_ISA_EXT_ARR(ZIHINTNTL),
|
||||
KVM_ISA_EXT_ARR(ZIHINTPAUSE),
|
||||
KVM_ISA_EXT_ARR(ZIHPM),
|
||||
KVM_ISA_EXT_ARR(ZILSD),
|
||||
KVM_ISA_EXT_ARR(ZIMOP),
|
||||
KVM_ISA_EXT_ARR(ZKND),
|
||||
KVM_ISA_EXT_ARR(ZKNE),
|
||||
KVM_ISA_EXT_ARR(ZKNH),
|
||||
KVM_ISA_EXT_ARR(ZKR),
|
||||
KVM_ISA_EXT_ARR(ZKSED),
|
||||
KVM_ISA_EXT_ARR(ZKSH),
|
||||
KVM_ISA_EXT_ARR(ZKT),
|
||||
KVM_ISA_EXT_ARR(ZTSO),
|
||||
KVM_ISA_EXT_ARR(ZVBB),
|
||||
KVM_ISA_EXT_ARR(ZVBC),
|
||||
KVM_ISA_EXT_ARR(ZVFBFMIN),
|
||||
KVM_ISA_EXT_ARR(ZVFBFWMA),
|
||||
KVM_ISA_EXT_ARR(ZVFH),
|
||||
KVM_ISA_EXT_ARR(ZVFHMIN),
|
||||
KVM_ISA_EXT_ARR(ZVKB),
|
||||
KVM_ISA_EXT_ARR(ZVKG),
|
||||
KVM_ISA_EXT_ARR(ZVKNED),
|
||||
KVM_ISA_EXT_ARR(ZVKNHA),
|
||||
KVM_ISA_EXT_ARR(ZVKNHB),
|
||||
KVM_ISA_EXT_ARR(ZVKSED),
|
||||
KVM_ISA_EXT_ARR(ZVKSH),
|
||||
KVM_ISA_EXT_ARR(ZVKT),
|
||||
};
|
||||
|
||||
static unsigned long kvm_riscv_vcpu_base2isa_ext(unsigned long base_ext)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) {
|
||||
if (kvm_isa_ext_arr[i] == base_ext)
|
||||
return i;
|
||||
}
|
||||
|
||||
return KVM_RISCV_ISA_EXT_MAX;
|
||||
}
|
||||
|
||||
int __kvm_riscv_isa_check_host(unsigned long kvm_ext, unsigned long *base_ext)
|
||||
{
|
||||
unsigned long host_ext;
|
||||
|
||||
if (kvm_ext >= KVM_RISCV_ISA_EXT_MAX ||
|
||||
kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr))
|
||||
return -ENOENT;
|
||||
|
||||
kvm_ext = array_index_nospec(kvm_ext, ARRAY_SIZE(kvm_isa_ext_arr));
|
||||
switch (kvm_isa_ext_arr[kvm_ext]) {
|
||||
case RISCV_ISA_EXT_SMNPM:
|
||||
/*
|
||||
* Pointer masking effective in (H)S-mode is provided by the
|
||||
* Smnpm extension, so that extension is reported to the guest,
|
||||
* even though the CSR bits for configuring VS-mode pointer
|
||||
* masking on the host side are part of the Ssnpm extension.
|
||||
*/
|
||||
host_ext = RISCV_ISA_EXT_SSNPM;
|
||||
break;
|
||||
default:
|
||||
host_ext = kvm_isa_ext_arr[kvm_ext];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!__riscv_isa_extension_available(NULL, host_ext))
|
||||
return -ENOENT;
|
||||
|
||||
if (base_ext)
|
||||
*base_ext = kvm_isa_ext_arr[kvm_ext];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext)
|
||||
{
|
||||
switch (ext) {
|
||||
case KVM_RISCV_ISA_EXT_H:
|
||||
return false;
|
||||
case KVM_RISCV_ISA_EXT_SSCOFPMF:
|
||||
/* Sscofpmf depends on interrupt filtering defined in ssaia */
|
||||
return !kvm_riscv_isa_check_host(SSAIA);
|
||||
case KVM_RISCV_ISA_EXT_SVADU:
|
||||
/*
|
||||
* The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
|
||||
* Guest OS can use Svadu only when host OS enable Svadu.
|
||||
*/
|
||||
return arch_has_hw_pte_young();
|
||||
case KVM_RISCV_ISA_EXT_V:
|
||||
return riscv_v_vstate_ctrl_user_allowed();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
|
||||
{
|
||||
switch (ext) {
|
||||
/* Extensions which don't have any mechanism to disable */
|
||||
case KVM_RISCV_ISA_EXT_A:
|
||||
case KVM_RISCV_ISA_EXT_C:
|
||||
case KVM_RISCV_ISA_EXT_I:
|
||||
case KVM_RISCV_ISA_EXT_M:
|
||||
/* There is not architectural config bit to disable sscofpmf completely */
|
||||
case KVM_RISCV_ISA_EXT_SSCOFPMF:
|
||||
case KVM_RISCV_ISA_EXT_SSNPM:
|
||||
case KVM_RISCV_ISA_EXT_SSTC:
|
||||
case KVM_RISCV_ISA_EXT_SVINVAL:
|
||||
case KVM_RISCV_ISA_EXT_SVNAPOT:
|
||||
case KVM_RISCV_ISA_EXT_SVVPTC:
|
||||
case KVM_RISCV_ISA_EXT_ZAAMO:
|
||||
case KVM_RISCV_ISA_EXT_ZABHA:
|
||||
case KVM_RISCV_ISA_EXT_ZACAS:
|
||||
case KVM_RISCV_ISA_EXT_ZALASR:
|
||||
case KVM_RISCV_ISA_EXT_ZALRSC:
|
||||
case KVM_RISCV_ISA_EXT_ZAWRS:
|
||||
case KVM_RISCV_ISA_EXT_ZBA:
|
||||
case KVM_RISCV_ISA_EXT_ZBB:
|
||||
case KVM_RISCV_ISA_EXT_ZBC:
|
||||
case KVM_RISCV_ISA_EXT_ZBKB:
|
||||
case KVM_RISCV_ISA_EXT_ZBKC:
|
||||
case KVM_RISCV_ISA_EXT_ZBKX:
|
||||
case KVM_RISCV_ISA_EXT_ZBS:
|
||||
case KVM_RISCV_ISA_EXT_ZCA:
|
||||
case KVM_RISCV_ISA_EXT_ZCB:
|
||||
case KVM_RISCV_ISA_EXT_ZCD:
|
||||
case KVM_RISCV_ISA_EXT_ZCF:
|
||||
case KVM_RISCV_ISA_EXT_ZCMOP:
|
||||
case KVM_RISCV_ISA_EXT_ZFA:
|
||||
case KVM_RISCV_ISA_EXT_ZFBFMIN:
|
||||
case KVM_RISCV_ISA_EXT_ZFH:
|
||||
case KVM_RISCV_ISA_EXT_ZFHMIN:
|
||||
case KVM_RISCV_ISA_EXT_ZICBOP:
|
||||
case KVM_RISCV_ISA_EXT_ZICCRSE:
|
||||
case KVM_RISCV_ISA_EXT_ZICNTR:
|
||||
case KVM_RISCV_ISA_EXT_ZICOND:
|
||||
case KVM_RISCV_ISA_EXT_ZICSR:
|
||||
case KVM_RISCV_ISA_EXT_ZIFENCEI:
|
||||
case KVM_RISCV_ISA_EXT_ZIHINTNTL:
|
||||
case KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
|
||||
case KVM_RISCV_ISA_EXT_ZIHPM:
|
||||
case KVM_RISCV_ISA_EXT_ZIMOP:
|
||||
case KVM_RISCV_ISA_EXT_ZKND:
|
||||
case KVM_RISCV_ISA_EXT_ZKNE:
|
||||
case KVM_RISCV_ISA_EXT_ZKNH:
|
||||
case KVM_RISCV_ISA_EXT_ZKR:
|
||||
case KVM_RISCV_ISA_EXT_ZKSED:
|
||||
case KVM_RISCV_ISA_EXT_ZKSH:
|
||||
case KVM_RISCV_ISA_EXT_ZKT:
|
||||
case KVM_RISCV_ISA_EXT_ZTSO:
|
||||
case KVM_RISCV_ISA_EXT_ZVBB:
|
||||
case KVM_RISCV_ISA_EXT_ZVBC:
|
||||
case KVM_RISCV_ISA_EXT_ZVFBFMIN:
|
||||
case KVM_RISCV_ISA_EXT_ZVFBFWMA:
|
||||
case KVM_RISCV_ISA_EXT_ZVFH:
|
||||
case KVM_RISCV_ISA_EXT_ZVFHMIN:
|
||||
case KVM_RISCV_ISA_EXT_ZVKB:
|
||||
case KVM_RISCV_ISA_EXT_ZVKG:
|
||||
case KVM_RISCV_ISA_EXT_ZVKNED:
|
||||
case KVM_RISCV_ISA_EXT_ZVKNHA:
|
||||
case KVM_RISCV_ISA_EXT_ZVKNHB:
|
||||
case KVM_RISCV_ISA_EXT_ZVKSED:
|
||||
case KVM_RISCV_ISA_EXT_ZVKSH:
|
||||
case KVM_RISCV_ISA_EXT_ZVKT:
|
||||
return false;
|
||||
/* Extensions which can be disabled using Smstateen */
|
||||
case KVM_RISCV_ISA_EXT_SSAIA:
|
||||
return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN);
|
||||
case KVM_RISCV_ISA_EXT_SVADE:
|
||||
/*
|
||||
* The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
|
||||
* Svade can't be disabled unless we support Svadu.
|
||||
*/
|
||||
return arch_has_hw_pte_young();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void kvm_riscv_vcpu_setup_isa(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long guest_ext, i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(kvm_isa_ext_arr); i++) {
|
||||
for (i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) {
|
||||
if (__kvm_riscv_isa_check_host(i, &guest_ext))
|
||||
continue;
|
||||
if (kvm_riscv_vcpu_isa_enable_allowed(i))
|
||||
if (kvm_riscv_isa_enable_allowed(i))
|
||||
set_bit(guest_ext, vcpu->arch.isa);
|
||||
}
|
||||
}
|
||||
|
|
@ -363,15 +121,15 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
|
|||
if (!vcpu->arch.ran_atleast_once) {
|
||||
/* Ignore the enable/disable request for certain extensions */
|
||||
for (i = 0; i < RISCV_ISA_EXT_BASE; i++) {
|
||||
isa_ext = kvm_riscv_vcpu_base2isa_ext(i);
|
||||
isa_ext = kvm_riscv_base2isa_ext(i);
|
||||
if (isa_ext >= KVM_RISCV_ISA_EXT_MAX) {
|
||||
reg_val &= ~BIT(i);
|
||||
continue;
|
||||
}
|
||||
if (!kvm_riscv_vcpu_isa_enable_allowed(isa_ext))
|
||||
if (!kvm_riscv_isa_enable_allowed(isa_ext))
|
||||
if (reg_val & BIT(i))
|
||||
reg_val &= ~BIT(i);
|
||||
if (!kvm_riscv_vcpu_isa_disable_allowed(isa_ext))
|
||||
if (!kvm_riscv_isa_disable_allowed(isa_ext))
|
||||
if (!(reg_val & BIT(i)))
|
||||
reg_val |= BIT(i);
|
||||
}
|
||||
|
|
@ -715,10 +473,10 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
|
|||
* extension can be disabled
|
||||
*/
|
||||
if (reg_val == 1 &&
|
||||
kvm_riscv_vcpu_isa_enable_allowed(reg_num))
|
||||
kvm_riscv_isa_enable_allowed(reg_num))
|
||||
set_bit(guest_ext, vcpu->arch.isa);
|
||||
else if (!reg_val &&
|
||||
kvm_riscv_vcpu_isa_disable_allowed(reg_num))
|
||||
kvm_riscv_isa_disable_allowed(reg_num))
|
||||
clear_bit(guest_ext, vcpu->arch.isa);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -7,16 +7,17 @@
|
|||
*/
|
||||
|
||||
#define pr_fmt(fmt) "riscv-kvm-pmu: " fmt
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/perf/riscv_pmu.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/kvm_isa.h>
|
||||
#include <asm/kvm_vcpu_sbi.h>
|
||||
#include <asm/kvm_vcpu_pmu.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define kvm_pmu_num_counters(pmu) ((pmu)->num_hw_ctrs + (pmu)->num_fw_ctrs)
|
||||
#define get_event_type(x) (((x) & SBI_PMU_EVENT_IDX_TYPE_MASK) >> 16)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <clocksource/timer-riscv.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/kvm_isa.h>
|
||||
#include <asm/kvm_nacl.h>
|
||||
#include <asm/kvm_vcpu_timer.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/kvm_host.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/kvm_isa.h>
|
||||
#include <asm/kvm_vcpu_vector.h>
|
||||
#include <asm/vector.h>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue