@@ -374,6 +374,101 @@ static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu,
374374 return 0 ;
375375}
376376
377+ /* Mapping between KVM ISA Extension ID & Host ISA extension ID */
378+ static unsigned long kvm_isa_ext_arr [] = {
379+ RISCV_ISA_EXT_a ,
380+ RISCV_ISA_EXT_c ,
381+ RISCV_ISA_EXT_d ,
382+ RISCV_ISA_EXT_f ,
383+ RISCV_ISA_EXT_h ,
384+ RISCV_ISA_EXT_i ,
385+ RISCV_ISA_EXT_m ,
386+ };
387+
388+ static int kvm_riscv_vcpu_get_reg_isa_ext (struct kvm_vcpu * vcpu ,
389+ const struct kvm_one_reg * reg )
390+ {
391+ unsigned long __user * uaddr =
392+ (unsigned long __user * )(unsigned long )reg -> addr ;
393+ unsigned long reg_num = reg -> id & ~(KVM_REG_ARCH_MASK |
394+ KVM_REG_SIZE_MASK |
395+ KVM_REG_RISCV_ISA_EXT );
396+ unsigned long reg_val = 0 ;
397+ unsigned long host_isa_ext ;
398+
399+ if (KVM_REG_SIZE (reg -> id ) != sizeof (unsigned long ))
400+ return - EINVAL ;
401+
402+ if (reg_num >= KVM_RISCV_ISA_EXT_MAX || reg_num >= ARRAY_SIZE (kvm_isa_ext_arr ))
403+ return - EINVAL ;
404+
405+ host_isa_ext = kvm_isa_ext_arr [reg_num ];
406+ if (__riscv_isa_extension_available (& vcpu -> arch .isa , host_isa_ext ))
407+ reg_val = 1 ; /* Mark the given extension as available */
408+
409+ if (copy_to_user (uaddr , & reg_val , KVM_REG_SIZE (reg -> id )))
410+ return - EFAULT ;
411+
412+ return 0 ;
413+ }
414+
415+ static int kvm_riscv_vcpu_set_reg_isa_ext (struct kvm_vcpu * vcpu ,
416+ const struct kvm_one_reg * reg )
417+ {
418+ unsigned long __user * uaddr =
419+ (unsigned long __user * )(unsigned long )reg -> addr ;
420+ unsigned long reg_num = reg -> id & ~(KVM_REG_ARCH_MASK |
421+ KVM_REG_SIZE_MASK |
422+ KVM_REG_RISCV_ISA_EXT );
423+ unsigned long reg_val ;
424+ unsigned long host_isa_ext ;
425+ unsigned long host_isa_ext_mask ;
426+
427+ if (KVM_REG_SIZE (reg -> id ) != sizeof (unsigned long ))
428+ return - EINVAL ;
429+
430+ if (reg_num >= KVM_RISCV_ISA_EXT_MAX || reg_num >= ARRAY_SIZE (kvm_isa_ext_arr ))
431+ return - EINVAL ;
432+
433+ if (copy_from_user (& reg_val , uaddr , KVM_REG_SIZE (reg -> id )))
434+ return - EFAULT ;
435+
436+ host_isa_ext = kvm_isa_ext_arr [reg_num ];
437+ if (!__riscv_isa_extension_available (NULL , host_isa_ext ))
438+ return - EOPNOTSUPP ;
439+
440+ if (host_isa_ext >= RISCV_ISA_EXT_BASE &&
441+ host_isa_ext < RISCV_ISA_EXT_MAX ) {
442+ /*
443+ * Multi-letter ISA extension. Currently there is no provision
444+ * to enable/disable the multi-letter ISA extensions for guests.
445+ * Return success if the request is to enable any ISA extension
446+ * that is available in the hardware.
447+ * Return -EOPNOTSUPP otherwise.
448+ */
449+ if (!reg_val )
450+ return - EOPNOTSUPP ;
451+ else
452+ return 0 ;
453+ }
454+
455+ /* Single letter base ISA extension */
456+ if (!vcpu -> arch .ran_atleast_once ) {
457+ host_isa_ext_mask = BIT_MASK (host_isa_ext );
458+ if (!reg_val && (host_isa_ext_mask & KVM_RISCV_ISA_DISABLE_ALLOWED ))
459+ vcpu -> arch .isa &= ~host_isa_ext_mask ;
460+ else
461+ vcpu -> arch .isa |= host_isa_ext_mask ;
462+ vcpu -> arch .isa &= riscv_isa_extension_base (NULL );
463+ vcpu -> arch .isa &= KVM_RISCV_ISA_ALLOWED ;
464+ kvm_riscv_vcpu_fp_reset (vcpu );
465+ } else {
466+ return - EOPNOTSUPP ;
467+ }
468+
469+ return 0 ;
470+ }
471+
377472static int kvm_riscv_vcpu_set_reg (struct kvm_vcpu * vcpu ,
378473 const struct kvm_one_reg * reg )
379474{
@@ -391,6 +486,8 @@ static int kvm_riscv_vcpu_set_reg(struct kvm_vcpu *vcpu,
391486 else if ((reg -> id & KVM_REG_RISCV_TYPE_MASK ) == KVM_REG_RISCV_FP_D )
392487 return kvm_riscv_vcpu_set_reg_fp (vcpu , reg ,
393488 KVM_REG_RISCV_FP_D );
489+ else if ((reg -> id & KVM_REG_RISCV_TYPE_MASK ) == KVM_REG_RISCV_ISA_EXT )
490+ return kvm_riscv_vcpu_set_reg_isa_ext (vcpu , reg );
394491
395492 return - EINVAL ;
396493}
@@ -412,6 +509,8 @@ static int kvm_riscv_vcpu_get_reg(struct kvm_vcpu *vcpu,
412509 else if ((reg -> id & KVM_REG_RISCV_TYPE_MASK ) == KVM_REG_RISCV_FP_D )
413510 return kvm_riscv_vcpu_get_reg_fp (vcpu , reg ,
414511 KVM_REG_RISCV_FP_D );
512+ else if ((reg -> id & KVM_REG_RISCV_TYPE_MASK ) == KVM_REG_RISCV_ISA_EXT )
513+ return kvm_riscv_vcpu_get_reg_isa_ext (vcpu , reg );
415514
416515 return - EINVAL ;
417516}
0 commit comments