@@ -781,16 +781,175 @@ static const struct kvm_io_device_ops kvm_eiointc_virt_ops = {
781
781
.write = kvm_eiointc_virt_write ,
782
782
};
783
783
784
+ static int kvm_eiointc_ctrl_access (struct kvm_device * dev ,
785
+ struct kvm_device_attr * attr )
786
+ {
787
+ int ret = 0 ;
788
+ unsigned long flags ;
789
+ unsigned long type = (unsigned long )attr -> attr ;
790
+ u32 i , start_irq ;
791
+ void __user * data ;
792
+ struct loongarch_eiointc * s = dev -> kvm -> arch .eiointc ;
793
+
794
+ data = (void __user * )attr -> addr ;
795
+ spin_lock_irqsave (& s -> lock , flags );
796
+ switch (type ) {
797
+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU :
798
+ if (copy_from_user (& s -> num_cpu , data , 4 ))
799
+ ret = - EFAULT ;
800
+ break ;
801
+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE :
802
+ if (copy_from_user (& s -> features , data , 4 ))
803
+ ret = - EFAULT ;
804
+ if (!(s -> features & BIT (EIOINTC_HAS_VIRT_EXTENSION )))
805
+ s -> status |= BIT (EIOINTC_ENABLE );
806
+ break ;
807
+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_LOAD_FINISHED :
808
+ eiointc_set_sw_coreisr (s );
809
+ for (i = 0 ; i < (EIOINTC_IRQS / 4 ); i ++ ) {
810
+ start_irq = i * 4 ;
811
+ eiointc_update_sw_coremap (s , start_irq ,
812
+ (void * )& s -> coremap .reg_u32 [i ], sizeof (u32 ), false);
813
+ }
814
+ break ;
815
+ default :
816
+ break ;
817
+ }
818
+ spin_unlock_irqrestore (& s -> lock , flags );
819
+
820
+ return ret ;
821
+ }
822
+
823
+ static int kvm_eiointc_regs_access (struct kvm_device * dev ,
824
+ struct kvm_device_attr * attr ,
825
+ bool is_write )
826
+ {
827
+ int addr , cpuid , offset , ret = 0 ;
828
+ unsigned long flags ;
829
+ void * p = NULL ;
830
+ void __user * data ;
831
+ struct loongarch_eiointc * s ;
832
+
833
+ s = dev -> kvm -> arch .eiointc ;
834
+ addr = attr -> attr ;
835
+ cpuid = addr >> 16 ;
836
+ addr &= 0xffff ;
837
+ data = (void __user * )attr -> addr ;
838
+ switch (addr ) {
839
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END :
840
+ offset = (addr - EIOINTC_NODETYPE_START ) / 4 ;
841
+ p = & s -> nodetype .reg_u32 [offset ];
842
+ break ;
843
+ case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END :
844
+ offset = (addr - EIOINTC_IPMAP_START ) / 4 ;
845
+ p = & s -> ipmap .reg_u32 [offset ];
846
+ break ;
847
+ case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END :
848
+ offset = (addr - EIOINTC_ENABLE_START ) / 4 ;
849
+ p = & s -> enable .reg_u32 [offset ];
850
+ break ;
851
+ case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END :
852
+ offset = (addr - EIOINTC_BOUNCE_START ) / 4 ;
853
+ p = & s -> bounce .reg_u32 [offset ];
854
+ break ;
855
+ case EIOINTC_ISR_START ... EIOINTC_ISR_END :
856
+ offset = (addr - EIOINTC_ISR_START ) / 4 ;
857
+ p = & s -> isr .reg_u32 [offset ];
858
+ break ;
859
+ case EIOINTC_COREISR_START ... EIOINTC_COREISR_END :
860
+ offset = (addr - EIOINTC_COREISR_START ) / 4 ;
861
+ p = & s -> coreisr .reg_u32 [cpuid ][offset ];
862
+ break ;
863
+ case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END :
864
+ offset = (addr - EIOINTC_COREMAP_START ) / 4 ;
865
+ p = & s -> coremap .reg_u32 [offset ];
866
+ break ;
867
+ default :
868
+ kvm_err ("%s: unknown eiointc register, addr = %d\n" , __func__ , addr );
869
+ return - EINVAL ;
870
+ }
871
+
872
+ spin_lock_irqsave (& s -> lock , flags );
873
+ if (is_write ) {
874
+ if (copy_from_user (p , data , 4 ))
875
+ ret = - EFAULT ;
876
+ } else {
877
+ if (copy_to_user (data , p , 4 ))
878
+ ret = - EFAULT ;
879
+ }
880
+ spin_unlock_irqrestore (& s -> lock , flags );
881
+
882
+ return ret ;
883
+ }
884
+
885
+ static int kvm_eiointc_sw_status_access (struct kvm_device * dev ,
886
+ struct kvm_device_attr * attr ,
887
+ bool is_write )
888
+ {
889
+ int addr , ret = 0 ;
890
+ unsigned long flags ;
891
+ void * p = NULL ;
892
+ void __user * data ;
893
+ struct loongarch_eiointc * s ;
894
+
895
+ s = dev -> kvm -> arch .eiointc ;
896
+ addr = attr -> attr ;
897
+ addr &= 0xffff ;
898
+
899
+ data = (void __user * )attr -> addr ;
900
+ switch (addr ) {
901
+ case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_NUM_CPU :
902
+ p = & s -> num_cpu ;
903
+ break ;
904
+ case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_FEATURE :
905
+ p = & s -> features ;
906
+ break ;
907
+ case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_STATE :
908
+ p = & s -> status ;
909
+ break ;
910
+ default :
911
+ kvm_err ("%s: unknown eiointc register, addr = %d\n" , __func__ , addr );
912
+ return - EINVAL ;
913
+ }
914
+ spin_lock_irqsave (& s -> lock , flags );
915
+ if (is_write ) {
916
+ if (copy_from_user (p , data , 4 ))
917
+ ret = - EFAULT ;
918
+ } else {
919
+ if (copy_to_user (data , p , 4 ))
920
+ ret = - EFAULT ;
921
+ }
922
+ spin_unlock_irqrestore (& s -> lock , flags );
923
+
924
+ return ret ;
925
+ }
926
+
784
927
static int kvm_eiointc_get_attr (struct kvm_device * dev ,
785
928
struct kvm_device_attr * attr )
786
929
{
787
- return 0 ;
930
+ switch (attr -> group ) {
931
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS :
932
+ return kvm_eiointc_regs_access (dev , attr , false);
933
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS :
934
+ return kvm_eiointc_sw_status_access (dev , attr , false);
935
+ default :
936
+ return - EINVAL ;
937
+ }
788
938
}
789
939
790
940
static int kvm_eiointc_set_attr (struct kvm_device * dev ,
791
941
struct kvm_device_attr * attr )
792
942
{
793
- return 0 ;
943
+ switch (attr -> group ) {
944
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL :
945
+ return kvm_eiointc_ctrl_access (dev , attr );
946
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS :
947
+ return kvm_eiointc_regs_access (dev , attr , true);
948
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS :
949
+ return kvm_eiointc_sw_status_access (dev , attr , true);
950
+ default :
951
+ return - EINVAL ;
952
+ }
794
953
}
795
954
796
955
static int kvm_eiointc_create (struct kvm_device * dev , u32 type )
0 commit comments