@@ -314,16 +314,133 @@ static const struct kvm_io_device_ops kvm_pch_pic_ops = {
314
314
.write = kvm_pch_pic_write ,
315
315
};
316
316
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
+
317
404
static int kvm_pch_pic_get_attr (struct kvm_device * dev ,
318
405
struct kvm_device_attr * attr )
319
406
{
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
+ }
321
413
}
322
414
323
415
static int kvm_pch_pic_set_attr (struct kvm_device * dev ,
324
416
struct kvm_device_attr * attr )
325
417
{
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
+ }
327
444
}
328
445
329
446
static int kvm_pch_pic_create (struct kvm_device * dev , u32 type )
0 commit comments