Skip to content

Commit 7826c8f

Browse files
SiFiveHollandavpatel
authored andcommitted
RISC-V: KVM: Fix inclusion of Smnpm in the guest ISA bitmap
The Smnpm extension requires special handling because the guest ISA extension maps to a different extension (Ssnpm) on the host side. commit 1851e78 ("RISC-V: KVM: Allow Smnpm and Ssnpm extensions for guests") missed that the vcpu->arch.isa bit is based only on the host extension, so currently both KVM_RISCV_ISA_EXT_{SMNPM,SSNPM} map to vcpu->arch.isa[RISCV_ISA_EXT_SSNPM]. This does not cause any problems for the guest, because both extensions are force-enabled anyway when the host supports Ssnpm, but prevents checking for (guest) Smnpm in the SBI FWFT logic. Redefine kvm_isa_ext_arr to look up the guest extension, since only the guest -> host mapping is unambiguous. Factor out the logic for checking for host support of an extension, so this special case only needs to be handled in one place, and be explicit about which variables hold a host vs a guest ISA extension. Fixes: 1851e78 ("RISC-V: KVM: Allow Smnpm and Ssnpm extensions for guests") Signed-off-by: Samuel Holland <samuel.holland@sifive.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20250111004702.2813013-2-samuel.holland@sifive.com Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent 3729fe8 commit 7826c8f

1 file changed

Lines changed: 53 additions & 30 deletions

File tree

arch/riscv/kvm/vcpu_onereg.c

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#define KVM_ISA_EXT_ARR(ext) \
2424
[KVM_RISCV_ISA_EXT_##ext] = RISCV_ISA_EXT_##ext
2525

26-
/* Mapping between KVM ISA Extension ID & Host ISA extension ID */
26+
/* Mapping between KVM ISA Extension ID & guest ISA extension ID */
2727
static const unsigned long kvm_isa_ext_arr[] = {
2828
/* Single letter extensions (alphabetically sorted) */
2929
[KVM_RISCV_ISA_EXT_A] = RISCV_ISA_EXT_a,
@@ -35,7 +35,7 @@ static const unsigned long kvm_isa_ext_arr[] = {
3535
[KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
3636
[KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
3737
/* Multi letter extensions (alphabetically sorted) */
38-
[KVM_RISCV_ISA_EXT_SMNPM] = RISCV_ISA_EXT_SSNPM,
38+
KVM_ISA_EXT_ARR(SMNPM),
3939
KVM_ISA_EXT_ARR(SMSTATEEN),
4040
KVM_ISA_EXT_ARR(SSAIA),
4141
KVM_ISA_EXT_ARR(SSCOFPMF),
@@ -112,6 +112,36 @@ static unsigned long kvm_riscv_vcpu_base2isa_ext(unsigned long base_ext)
112112
return KVM_RISCV_ISA_EXT_MAX;
113113
}
114114

115+
static int kvm_riscv_vcpu_isa_check_host(unsigned long kvm_ext, unsigned long *guest_ext)
116+
{
117+
unsigned long host_ext;
118+
119+
if (kvm_ext >= KVM_RISCV_ISA_EXT_MAX ||
120+
kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr))
121+
return -ENOENT;
122+
123+
*guest_ext = kvm_isa_ext_arr[kvm_ext];
124+
switch (*guest_ext) {
125+
case RISCV_ISA_EXT_SMNPM:
126+
/*
127+
* Pointer masking effective in (H)S-mode is provided by the
128+
* Smnpm extension, so that extension is reported to the guest,
129+
* even though the CSR bits for configuring VS-mode pointer
130+
* masking on the host side are part of the Ssnpm extension.
131+
*/
132+
host_ext = RISCV_ISA_EXT_SSNPM;
133+
break;
134+
default:
135+
host_ext = *guest_ext;
136+
break;
137+
}
138+
139+
if (!__riscv_isa_extension_available(NULL, host_ext))
140+
return -ENOENT;
141+
142+
return 0;
143+
}
144+
115145
static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext)
116146
{
117147
switch (ext) {
@@ -219,13 +249,13 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
219249

220250
void kvm_riscv_vcpu_setup_isa(struct kvm_vcpu *vcpu)
221251
{
222-
unsigned long host_isa, i;
252+
unsigned long guest_ext, i;
223253

224254
for (i = 0; i < ARRAY_SIZE(kvm_isa_ext_arr); i++) {
225-
host_isa = kvm_isa_ext_arr[i];
226-
if (__riscv_isa_extension_available(NULL, host_isa) &&
227-
kvm_riscv_vcpu_isa_enable_allowed(i))
228-
set_bit(host_isa, vcpu->arch.isa);
255+
if (kvm_riscv_vcpu_isa_check_host(i, &guest_ext))
256+
continue;
257+
if (kvm_riscv_vcpu_isa_enable_allowed(i))
258+
set_bit(guest_ext, vcpu->arch.isa);
229259
}
230260
}
231261

@@ -607,18 +637,15 @@ static int riscv_vcpu_get_isa_ext_single(struct kvm_vcpu *vcpu,
607637
unsigned long reg_num,
608638
unsigned long *reg_val)
609639
{
610-
unsigned long host_isa_ext;
611-
612-
if (reg_num >= KVM_RISCV_ISA_EXT_MAX ||
613-
reg_num >= ARRAY_SIZE(kvm_isa_ext_arr))
614-
return -ENOENT;
640+
unsigned long guest_ext;
641+
int ret;
615642

616-
host_isa_ext = kvm_isa_ext_arr[reg_num];
617-
if (!__riscv_isa_extension_available(NULL, host_isa_ext))
618-
return -ENOENT;
643+
ret = kvm_riscv_vcpu_isa_check_host(reg_num, &guest_ext);
644+
if (ret)
645+
return ret;
619646

620647
*reg_val = 0;
621-
if (__riscv_isa_extension_available(vcpu->arch.isa, host_isa_ext))
648+
if (__riscv_isa_extension_available(vcpu->arch.isa, guest_ext))
622649
*reg_val = 1; /* Mark the given extension as available */
623650

624651
return 0;
@@ -628,17 +655,14 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
628655
unsigned long reg_num,
629656
unsigned long reg_val)
630657
{
631-
unsigned long host_isa_ext;
632-
633-
if (reg_num >= KVM_RISCV_ISA_EXT_MAX ||
634-
reg_num >= ARRAY_SIZE(kvm_isa_ext_arr))
635-
return -ENOENT;
658+
unsigned long guest_ext;
659+
int ret;
636660

637-
host_isa_ext = kvm_isa_ext_arr[reg_num];
638-
if (!__riscv_isa_extension_available(NULL, host_isa_ext))
639-
return -ENOENT;
661+
ret = kvm_riscv_vcpu_isa_check_host(reg_num, &guest_ext);
662+
if (ret)
663+
return ret;
640664

641-
if (reg_val == test_bit(host_isa_ext, vcpu->arch.isa))
665+
if (reg_val == test_bit(guest_ext, vcpu->arch.isa))
642666
return 0;
643667

644668
if (!vcpu->arch.ran_atleast_once) {
@@ -648,10 +672,10 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
648672
*/
649673
if (reg_val == 1 &&
650674
kvm_riscv_vcpu_isa_enable_allowed(reg_num))
651-
set_bit(host_isa_ext, vcpu->arch.isa);
675+
set_bit(guest_ext, vcpu->arch.isa);
652676
else if (!reg_val &&
653677
kvm_riscv_vcpu_isa_disable_allowed(reg_num))
654-
clear_bit(host_isa_ext, vcpu->arch.isa);
678+
clear_bit(guest_ext, vcpu->arch.isa);
655679
else
656680
return -EINVAL;
657681
kvm_riscv_vcpu_fp_reset(vcpu);
@@ -1009,16 +1033,15 @@ static int copy_fp_d_reg_indices(const struct kvm_vcpu *vcpu,
10091033
static int copy_isa_ext_reg_indices(const struct kvm_vcpu *vcpu,
10101034
u64 __user *uindices)
10111035
{
1036+
unsigned long guest_ext;
10121037
unsigned int n = 0;
1013-
unsigned long isa_ext;
10141038

10151039
for (int i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) {
10161040
u64 size = IS_ENABLED(CONFIG_32BIT) ?
10171041
KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64;
10181042
u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_ISA_EXT | i;
10191043

1020-
isa_ext = kvm_isa_ext_arr[i];
1021-
if (!__riscv_isa_extension_available(NULL, isa_ext))
1044+
if (kvm_riscv_vcpu_isa_check_host(i, &guest_ext))
10221045
continue;
10231046

10241047
if (uindices) {

0 commit comments

Comments
 (0)