@@ -781,16 +781,175 @@ static const struct kvm_io_device_ops kvm_eiointc_virt_ops = {
781781 .write = kvm_eiointc_virt_write ,
782782};
783783
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+
784927static int kvm_eiointc_get_attr (struct kvm_device * dev ,
785928 struct kvm_device_attr * attr )
786929{
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+ }
788938}
789939
790940static int kvm_eiointc_set_attr (struct kvm_device * dev ,
791941 struct kvm_device_attr * attr )
792942{
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+ }
794953}
795954
796955static int kvm_eiointc_create (struct kvm_device * dev , u32 type )
0 commit comments