@@ -278,6 +278,33 @@ static u32 imsic_mrif_topei(struct imsic_mrif *mrif, u32 nr_eix, u32 nr_msis)
278278 return 0 ;
279279}
280280
281+ static int imsic_mrif_isel_check (u32 nr_eix , unsigned long isel )
282+ {
283+ u32 num = 0 ;
284+
285+ switch (isel ) {
286+ case IMSIC_EIDELIVERY :
287+ case IMSIC_EITHRESHOLD :
288+ break ;
289+ case IMSIC_EIP0 ... IMSIC_EIP63 :
290+ num = isel - IMSIC_EIP0 ;
291+ break ;
292+ case IMSIC_EIE0 ... IMSIC_EIE63 :
293+ num = isel - IMSIC_EIE0 ;
294+ break ;
295+ default :
296+ return - ENOENT ;
297+ };
298+ #ifndef CONFIG_32BIT
299+ if (num & 0x1 )
300+ return - EINVAL ;
301+ #endif
302+ if ((num / 2 ) >= nr_eix )
303+ return - EINVAL ;
304+
305+ return 0 ;
306+ }
307+
281308static int imsic_mrif_rmw (struct imsic_mrif * mrif , u32 nr_eix ,
282309 unsigned long isel , unsigned long * val ,
283310 unsigned long new_val , unsigned long wr_mask )
@@ -408,6 +435,86 @@ static void imsic_vsfile_read(int vsfile_hgei, int vsfile_cpu, u32 nr_eix,
408435 imsic_vsfile_local_read , & idata , 1 );
409436}
410437
438+ struct imsic_vsfile_rw_data {
439+ int hgei ;
440+ int isel ;
441+ bool write ;
442+ unsigned long val ;
443+ };
444+
445+ static void imsic_vsfile_local_rw (void * data )
446+ {
447+ struct imsic_vsfile_rw_data * idata = data ;
448+ unsigned long new_hstatus , old_hstatus , old_vsiselect ;
449+
450+ old_vsiselect = csr_read (CSR_VSISELECT );
451+ old_hstatus = csr_read (CSR_HSTATUS );
452+ new_hstatus = old_hstatus & ~HSTATUS_VGEIN ;
453+ new_hstatus |= ((unsigned long )idata -> hgei ) << HSTATUS_VGEIN_SHIFT ;
454+ csr_write (CSR_HSTATUS , new_hstatus );
455+
456+ switch (idata -> isel ) {
457+ case IMSIC_EIDELIVERY :
458+ if (idata -> write )
459+ imsic_vs_csr_write (IMSIC_EIDELIVERY , idata -> val );
460+ else
461+ idata -> val = imsic_vs_csr_read (IMSIC_EIDELIVERY );
462+ break ;
463+ case IMSIC_EITHRESHOLD :
464+ if (idata -> write )
465+ imsic_vs_csr_write (IMSIC_EITHRESHOLD , idata -> val );
466+ else
467+ idata -> val = imsic_vs_csr_read (IMSIC_EITHRESHOLD );
468+ break ;
469+ case IMSIC_EIP0 ... IMSIC_EIP63 :
470+ case IMSIC_EIE0 ... IMSIC_EIE63 :
471+ #ifndef CONFIG_32BIT
472+ if (idata -> isel & 0x1 )
473+ break ;
474+ #endif
475+ if (idata -> write )
476+ imsic_eix_write (idata -> isel , idata -> val );
477+ else
478+ idata -> val = imsic_eix_read (idata -> isel );
479+ break ;
480+ default :
481+ break ;
482+ }
483+
484+ csr_write (CSR_HSTATUS , old_hstatus );
485+ csr_write (CSR_VSISELECT , old_vsiselect );
486+ }
487+
488+ static int imsic_vsfile_rw (int vsfile_hgei , int vsfile_cpu , u32 nr_eix ,
489+ unsigned long isel , bool write ,
490+ unsigned long * val )
491+ {
492+ int rc ;
493+ struct imsic_vsfile_rw_data rdata ;
494+
495+ /* We can only access register if we have a IMSIC VS-file */
496+ if (vsfile_cpu < 0 || vsfile_hgei <= 0 )
497+ return - EINVAL ;
498+
499+ /* Check IMSIC register iselect */
500+ rc = imsic_mrif_isel_check (nr_eix , isel );
501+ if (rc )
502+ return rc ;
503+
504+ /* We can only access register on local CPU */
505+ rdata .hgei = vsfile_hgei ;
506+ rdata .isel = isel ;
507+ rdata .write = write ;
508+ rdata .val = (write ) ? * val : 0 ;
509+ on_each_cpu_mask (cpumask_of (vsfile_cpu ),
510+ imsic_vsfile_local_rw , & rdata , 1 );
511+
512+ if (!write )
513+ * val = rdata .val ;
514+
515+ return 0 ;
516+ }
517+
411518static void imsic_vsfile_local_clear (int vsfile_hgei , u32 nr_eix )
412519{
413520 u32 i ;
@@ -759,6 +866,69 @@ int kvm_riscv_vcpu_aia_imsic_rmw(struct kvm_vcpu *vcpu, unsigned long isel,
759866 return rc ;
760867}
761868
869+ int kvm_riscv_aia_imsic_rw_attr (struct kvm * kvm , unsigned long type ,
870+ bool write , unsigned long * val )
871+ {
872+ u32 isel , vcpu_id ;
873+ unsigned long flags ;
874+ struct imsic * imsic ;
875+ struct kvm_vcpu * vcpu ;
876+ int rc , vsfile_hgei , vsfile_cpu ;
877+
878+ if (!kvm_riscv_aia_initialized (kvm ))
879+ return - ENODEV ;
880+
881+ vcpu_id = KVM_DEV_RISCV_AIA_IMSIC_GET_VCPU (type );
882+ vcpu = kvm_get_vcpu_by_id (kvm , vcpu_id );
883+ if (!vcpu )
884+ return - ENODEV ;
885+
886+ isel = KVM_DEV_RISCV_AIA_IMSIC_GET_ISEL (type );
887+ imsic = vcpu -> arch .aia_context .imsic_state ;
888+
889+ read_lock_irqsave (& imsic -> vsfile_lock , flags );
890+
891+ rc = 0 ;
892+ vsfile_hgei = imsic -> vsfile_hgei ;
893+ vsfile_cpu = imsic -> vsfile_cpu ;
894+ if (vsfile_cpu < 0 ) {
895+ if (write ) {
896+ rc = imsic_mrif_rmw (imsic -> swfile , imsic -> nr_eix ,
897+ isel , NULL , * val , -1UL );
898+ imsic_swfile_extirq_update (vcpu );
899+ } else
900+ rc = imsic_mrif_rmw (imsic -> swfile , imsic -> nr_eix ,
901+ isel , val , 0 , 0 );
902+ }
903+
904+ read_unlock_irqrestore (& imsic -> vsfile_lock , flags );
905+
906+ if (!rc && vsfile_cpu >= 0 )
907+ rc = imsic_vsfile_rw (vsfile_hgei , vsfile_cpu , imsic -> nr_eix ,
908+ isel , write , val );
909+
910+ return rc ;
911+ }
912+
913+ int kvm_riscv_aia_imsic_has_attr (struct kvm * kvm , unsigned long type )
914+ {
915+ u32 isel , vcpu_id ;
916+ struct imsic * imsic ;
917+ struct kvm_vcpu * vcpu ;
918+
919+ if (!kvm_riscv_aia_initialized (kvm ))
920+ return - ENODEV ;
921+
922+ vcpu_id = KVM_DEV_RISCV_AIA_IMSIC_GET_VCPU (type );
923+ vcpu = kvm_get_vcpu_by_id (kvm , vcpu_id );
924+ if (!vcpu )
925+ return - ENODEV ;
926+
927+ isel = KVM_DEV_RISCV_AIA_IMSIC_GET_ISEL (type );
928+ imsic = vcpu -> arch .aia_context .imsic_state ;
929+ return imsic_mrif_isel_check (imsic -> nr_eix , isel );
930+ }
931+
762932void kvm_riscv_vcpu_aia_imsic_reset (struct kvm_vcpu * vcpu )
763933{
764934 struct imsic * imsic = vcpu -> arch .aia_context .imsic_state ;
0 commit comments