1*e0b5cfc3SAnup Patel // SPDX-License-Identifier: GPL-2.0 2*e0b5cfc3SAnup Patel /* 3*e0b5cfc3SAnup Patel * Copyright (c) 2026 Qualcomm Technologies, Inc. 4*e0b5cfc3SAnup Patel */ 5*e0b5cfc3SAnup Patel 6*e0b5cfc3SAnup Patel #include <linux/cpufeature.h> 7*e0b5cfc3SAnup Patel #include <linux/errno.h> 8*e0b5cfc3SAnup Patel #include <linux/kvm_host.h> 9*e0b5cfc3SAnup Patel #include <linux/nospec.h> 10*e0b5cfc3SAnup Patel #include <linux/pgtable.h> 11*e0b5cfc3SAnup Patel #include <asm/kvm_isa.h> 12*e0b5cfc3SAnup Patel #include <asm/vector.h> 13*e0b5cfc3SAnup Patel 14*e0b5cfc3SAnup Patel #define KVM_ISA_EXT_ARR(ext) \ 15*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_##ext] = RISCV_ISA_EXT_##ext 16*e0b5cfc3SAnup Patel 17*e0b5cfc3SAnup Patel /* Mapping between KVM ISA Extension ID & guest ISA extension ID */ 18*e0b5cfc3SAnup Patel static const unsigned long kvm_isa_ext_arr[] = { 19*e0b5cfc3SAnup Patel /* Single letter extensions (alphabetically sorted) */ 20*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_A] = RISCV_ISA_EXT_a, 21*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_C] = RISCV_ISA_EXT_c, 22*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_D] = RISCV_ISA_EXT_d, 23*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_F] = RISCV_ISA_EXT_f, 24*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_H] = RISCV_ISA_EXT_h, 25*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_I] = RISCV_ISA_EXT_i, 26*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m, 27*e0b5cfc3SAnup Patel [KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v, 28*e0b5cfc3SAnup Patel /* Multi letter extensions (alphabetically sorted) */ 29*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SMNPM), 30*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SMSTATEEN), 31*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SSAIA), 32*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SSCOFPMF), 33*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SSNPM), 34*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SSTC), 35*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SVADE), 36*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SVADU), 37*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SVINVAL), 38*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SVNAPOT), 39*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SVPBMT), 40*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(SVVPTC), 41*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZAAMO), 42*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZABHA), 43*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZACAS), 44*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZALASR), 45*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZALRSC), 46*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZAWRS), 47*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZBA), 48*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZBB), 49*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZBC), 50*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZBKB), 51*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZBKC), 52*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZBKX), 53*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZBS), 54*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZCA), 55*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZCB), 56*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZCD), 57*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZCF), 58*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZCLSD), 59*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZCMOP), 60*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZFA), 61*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZFBFMIN), 62*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZFH), 63*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZFHMIN), 64*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZICBOM), 65*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZICBOP), 66*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZICBOZ), 67*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZICCRSE), 68*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZICNTR), 69*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZICOND), 70*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZICSR), 71*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZIFENCEI), 72*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZIHINTNTL), 73*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZIHINTPAUSE), 74*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZIHPM), 75*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZILSD), 76*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZIMOP), 77*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZKND), 78*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZKNE), 79*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZKNH), 80*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZKR), 81*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZKSED), 82*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZKSH), 83*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZKT), 84*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZTSO), 85*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVBB), 86*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVBC), 87*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVFBFMIN), 88*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVFBFWMA), 89*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVFH), 90*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVFHMIN), 91*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVKB), 92*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVKG), 93*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVKNED), 94*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVKNHA), 95*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVKNHB), 96*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVKSED), 97*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVKSH), 98*e0b5cfc3SAnup Patel KVM_ISA_EXT_ARR(ZVKT), 99*e0b5cfc3SAnup Patel }; 100*e0b5cfc3SAnup Patel 101*e0b5cfc3SAnup Patel unsigned long kvm_riscv_base2isa_ext(unsigned long base_ext) 102*e0b5cfc3SAnup Patel { 103*e0b5cfc3SAnup Patel unsigned long i; 104*e0b5cfc3SAnup Patel 105*e0b5cfc3SAnup Patel for (i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) { 106*e0b5cfc3SAnup Patel if (kvm_isa_ext_arr[i] == base_ext) 107*e0b5cfc3SAnup Patel return i; 108*e0b5cfc3SAnup Patel } 109*e0b5cfc3SAnup Patel 110*e0b5cfc3SAnup Patel return KVM_RISCV_ISA_EXT_MAX; 111*e0b5cfc3SAnup Patel } 112*e0b5cfc3SAnup Patel 113*e0b5cfc3SAnup Patel int __kvm_riscv_isa_check_host(unsigned long kvm_ext, unsigned long *base_ext) 114*e0b5cfc3SAnup Patel { 115*e0b5cfc3SAnup Patel unsigned long host_ext; 116*e0b5cfc3SAnup Patel 117*e0b5cfc3SAnup Patel if (kvm_ext >= KVM_RISCV_ISA_EXT_MAX || 118*e0b5cfc3SAnup Patel kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr)) 119*e0b5cfc3SAnup Patel return -ENOENT; 120*e0b5cfc3SAnup Patel 121*e0b5cfc3SAnup Patel kvm_ext = array_index_nospec(kvm_ext, ARRAY_SIZE(kvm_isa_ext_arr)); 122*e0b5cfc3SAnup Patel switch (kvm_isa_ext_arr[kvm_ext]) { 123*e0b5cfc3SAnup Patel case RISCV_ISA_EXT_SMNPM: 124*e0b5cfc3SAnup Patel /* 125*e0b5cfc3SAnup Patel * Pointer masking effective in (H)S-mode is provided by the 126*e0b5cfc3SAnup Patel * Smnpm extension, so that extension is reported to the guest, 127*e0b5cfc3SAnup Patel * even though the CSR bits for configuring VS-mode pointer 128*e0b5cfc3SAnup Patel * masking on the host side are part of the Ssnpm extension. 129*e0b5cfc3SAnup Patel */ 130*e0b5cfc3SAnup Patel host_ext = RISCV_ISA_EXT_SSNPM; 131*e0b5cfc3SAnup Patel break; 132*e0b5cfc3SAnup Patel default: 133*e0b5cfc3SAnup Patel host_ext = kvm_isa_ext_arr[kvm_ext]; 134*e0b5cfc3SAnup Patel break; 135*e0b5cfc3SAnup Patel } 136*e0b5cfc3SAnup Patel 137*e0b5cfc3SAnup Patel if (!__riscv_isa_extension_available(NULL, host_ext)) 138*e0b5cfc3SAnup Patel return -ENOENT; 139*e0b5cfc3SAnup Patel 140*e0b5cfc3SAnup Patel if (base_ext) 141*e0b5cfc3SAnup Patel *base_ext = kvm_isa_ext_arr[kvm_ext]; 142*e0b5cfc3SAnup Patel 143*e0b5cfc3SAnup Patel return 0; 144*e0b5cfc3SAnup Patel } 145*e0b5cfc3SAnup Patel 146*e0b5cfc3SAnup Patel bool kvm_riscv_isa_enable_allowed(unsigned long ext) 147*e0b5cfc3SAnup Patel { 148*e0b5cfc3SAnup Patel switch (ext) { 149*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_H: 150*e0b5cfc3SAnup Patel return false; 151*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SSCOFPMF: 152*e0b5cfc3SAnup Patel /* Sscofpmf depends on interrupt filtering defined in ssaia */ 153*e0b5cfc3SAnup Patel return !kvm_riscv_isa_check_host(SSAIA); 154*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SVADU: 155*e0b5cfc3SAnup Patel /* 156*e0b5cfc3SAnup Patel * The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero. 157*e0b5cfc3SAnup Patel * Guest OS can use Svadu only when host OS enable Svadu. 158*e0b5cfc3SAnup Patel */ 159*e0b5cfc3SAnup Patel return arch_has_hw_pte_young(); 160*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_V: 161*e0b5cfc3SAnup Patel return riscv_v_vstate_ctrl_user_allowed(); 162*e0b5cfc3SAnup Patel default: 163*e0b5cfc3SAnup Patel break; 164*e0b5cfc3SAnup Patel } 165*e0b5cfc3SAnup Patel 166*e0b5cfc3SAnup Patel return true; 167*e0b5cfc3SAnup Patel } 168*e0b5cfc3SAnup Patel 169*e0b5cfc3SAnup Patel bool kvm_riscv_isa_disable_allowed(unsigned long ext) 170*e0b5cfc3SAnup Patel { 171*e0b5cfc3SAnup Patel switch (ext) { 172*e0b5cfc3SAnup Patel /* Extensions which don't have any mechanism to disable */ 173*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_A: 174*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_C: 175*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_I: 176*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_M: 177*e0b5cfc3SAnup Patel /* There is not architectural config bit to disable sscofpmf completely */ 178*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SSCOFPMF: 179*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SSNPM: 180*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SSTC: 181*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SVINVAL: 182*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SVNAPOT: 183*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SVVPTC: 184*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZAAMO: 185*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZABHA: 186*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZACAS: 187*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZALASR: 188*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZALRSC: 189*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZAWRS: 190*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZBA: 191*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZBB: 192*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZBC: 193*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZBKB: 194*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZBKC: 195*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZBKX: 196*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZBS: 197*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZCA: 198*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZCB: 199*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZCD: 200*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZCF: 201*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZCMOP: 202*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZFA: 203*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZFBFMIN: 204*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZFH: 205*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZFHMIN: 206*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZICBOP: 207*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZICCRSE: 208*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZICNTR: 209*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZICOND: 210*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZICSR: 211*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZIFENCEI: 212*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZIHINTNTL: 213*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZIHINTPAUSE: 214*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZIHPM: 215*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZIMOP: 216*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZKND: 217*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZKNE: 218*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZKNH: 219*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZKR: 220*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZKSED: 221*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZKSH: 222*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZKT: 223*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZTSO: 224*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVBB: 225*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVBC: 226*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVFBFMIN: 227*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVFBFWMA: 228*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVFH: 229*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVFHMIN: 230*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVKB: 231*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVKG: 232*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVKNED: 233*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVKNHA: 234*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVKNHB: 235*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVKSED: 236*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVKSH: 237*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_ZVKT: 238*e0b5cfc3SAnup Patel return false; 239*e0b5cfc3SAnup Patel /* Extensions which can be disabled using Smstateen */ 240*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SSAIA: 241*e0b5cfc3SAnup Patel return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN); 242*e0b5cfc3SAnup Patel case KVM_RISCV_ISA_EXT_SVADE: 243*e0b5cfc3SAnup Patel /* 244*e0b5cfc3SAnup Patel * The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero. 245*e0b5cfc3SAnup Patel * Svade can't be disabled unless we support Svadu. 246*e0b5cfc3SAnup Patel */ 247*e0b5cfc3SAnup Patel return arch_has_hw_pte_young(); 248*e0b5cfc3SAnup Patel default: 249*e0b5cfc3SAnup Patel break; 250*e0b5cfc3SAnup Patel } 251*e0b5cfc3SAnup Patel 252*e0b5cfc3SAnup Patel return true; 253*e0b5cfc3SAnup Patel } 254