@@ -314,16 +314,133 @@ static const struct kvm_io_device_ops kvm_pch_pic_ops = {
314314 .write = kvm_pch_pic_write ,
315315};
316316
317+ static int kvm_pch_pic_init (struct kvm_device * dev , u64 addr )
318+ {
319+ int ret ;
320+ struct kvm * kvm = dev -> kvm ;
321+ struct kvm_io_device * device ;
322+ struct loongarch_pch_pic * s = dev -> kvm -> arch .pch_pic ;
323+
324+ s -> pch_pic_base = addr ;
325+ device = & s -> device ;
326+ /* init device by pch pic writing and reading ops */
327+ kvm_iodevice_init (device , & kvm_pch_pic_ops );
328+ mutex_lock (& kvm -> slots_lock );
329+ /* register pch pic device */
330+ ret = kvm_io_bus_register_dev (kvm , KVM_MMIO_BUS , addr , PCH_PIC_SIZE , device );
331+ mutex_unlock (& kvm -> slots_lock );
332+
333+ return (ret < 0 ) ? - EFAULT : 0 ;
334+ }
335+
336+ /* used by user space to get or set pch pic registers */
337+ static int kvm_pch_pic_regs_access (struct kvm_device * dev ,
338+ struct kvm_device_attr * attr ,
339+ bool is_write )
340+ {
341+ int addr , offset , len = 8 , ret = 0 ;
342+ void __user * data ;
343+ void * p = NULL ;
344+ struct loongarch_pch_pic * s ;
345+
346+ s = dev -> kvm -> arch .pch_pic ;
347+ addr = attr -> attr ;
348+ data = (void __user * )attr -> addr ;
349+
350+ /* get pointer to pch pic register by addr */
351+ switch (addr ) {
352+ case PCH_PIC_MASK_START :
353+ p = & s -> mask ;
354+ break ;
355+ case PCH_PIC_HTMSI_EN_START :
356+ p = & s -> htmsi_en ;
357+ break ;
358+ case PCH_PIC_EDGE_START :
359+ p = & s -> edge ;
360+ break ;
361+ case PCH_PIC_AUTO_CTRL0_START :
362+ p = & s -> auto_ctrl0 ;
363+ break ;
364+ case PCH_PIC_AUTO_CTRL1_START :
365+ p = & s -> auto_ctrl1 ;
366+ break ;
367+ case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END :
368+ offset = addr - PCH_PIC_ROUTE_ENTRY_START ;
369+ p = & s -> route_entry [offset ];
370+ len = 1 ;
371+ break ;
372+ case PCH_PIC_HTMSI_VEC_START ... PCH_PIC_HTMSI_VEC_END :
373+ offset = addr - PCH_PIC_HTMSI_VEC_START ;
374+ p = & s -> htmsi_vector [offset ];
375+ len = 1 ;
376+ break ;
377+ case PCH_PIC_INT_IRR_START :
378+ p = & s -> irr ;
379+ break ;
380+ case PCH_PIC_INT_ISR_START :
381+ p = & s -> isr ;
382+ break ;
383+ case PCH_PIC_POLARITY_START :
384+ p = & s -> polarity ;
385+ break ;
386+ default :
387+ return - EINVAL ;
388+ }
389+
390+ spin_lock (& s -> lock );
391+ /* write or read value according to is_write */
392+ if (is_write ) {
393+ if (copy_from_user (p , data , len ))
394+ ret = - EFAULT ;
395+ } else {
396+ if (copy_to_user (data , p , len ))
397+ ret = - EFAULT ;
398+ }
399+ spin_unlock (& s -> lock );
400+
401+ return ret ;
402+ }
403+
317404static int kvm_pch_pic_get_attr (struct kvm_device * dev ,
318405 struct kvm_device_attr * attr )
319406{
320- return 0 ;
407+ switch (attr -> group ) {
408+ case KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS :
409+ return kvm_pch_pic_regs_access (dev , attr , false);
410+ default :
411+ return - EINVAL ;
412+ }
321413}
322414
323415static int kvm_pch_pic_set_attr (struct kvm_device * dev ,
324416 struct kvm_device_attr * attr )
325417{
326- return 0 ;
418+ u64 addr ;
419+ void __user * uaddr = (void __user * )(long )attr -> addr ;
420+
421+ switch (attr -> group ) {
422+ case KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL :
423+ switch (attr -> attr ) {
424+ case KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT :
425+ if (copy_from_user (& addr , uaddr , sizeof (addr )))
426+ return - EFAULT ;
427+
428+ if (!dev -> kvm -> arch .pch_pic ) {
429+ kvm_err ("%s: please create pch_pic irqchip first!\n" , __func__ );
430+ return - ENODEV ;
431+ }
432+
433+ return kvm_pch_pic_init (dev , addr );
434+ default :
435+ kvm_err ("%s: unknown group (%d) attr (%lld)\n" , __func__ , attr -> group ,
436+ attr -> attr );
437+ return - EINVAL ;
438+ }
439+ case KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS :
440+ return kvm_pch_pic_regs_access (dev , attr , true);
441+ default :
442+ return - EINVAL ;
443+ }
327444}
328445
329446static int kvm_pch_pic_create (struct kvm_device * dev , u32 type )
0 commit comments