@@ -44,7 +44,11 @@ struct VFIOCCWDevice {
44
44
uint64_t schib_region_size ;
45
45
uint64_t schib_region_offset ;
46
46
struct ccw_schib_region * schib_region ;
47
+ uint64_t crw_region_size ;
48
+ uint64_t crw_region_offset ;
49
+ struct ccw_crw_region * crw_region ;
47
50
EventNotifier io_notifier ;
51
+ EventNotifier crw_notifier ;
48
52
bool force_orb_pfch ;
49
53
bool warned_orb_pfch ;
50
54
};
@@ -254,6 +258,44 @@ static void vfio_ccw_reset(DeviceState *dev)
254
258
ioctl (vcdev -> vdev .fd , VFIO_DEVICE_RESET );
255
259
}
256
260
261
+ static void vfio_ccw_crw_read (VFIOCCWDevice * vcdev )
262
+ {
263
+ struct ccw_crw_region * region = vcdev -> crw_region ;
264
+ CRW crw ;
265
+ int size ;
266
+
267
+ /* Keep reading CRWs as long as data is returned */
268
+ do {
269
+ memset (region , 0 , sizeof (* region ));
270
+ size = pread (vcdev -> vdev .fd , region , vcdev -> crw_region_size ,
271
+ vcdev -> crw_region_offset );
272
+
273
+ if (size == -1 ) {
274
+ error_report ("vfio-ccw: Read crw region failed with errno=%d" ,
275
+ errno );
276
+ break ;
277
+ }
278
+
279
+ if (region -> crw == 0 ) {
280
+ /* No more CRWs to queue */
281
+ break ;
282
+ }
283
+
284
+ memcpy (& crw , & region -> crw , sizeof (CRW ));
285
+
286
+ css_crw_add_to_queue (crw );
287
+ } while (1 );
288
+ }
289
+
290
+ static void vfio_ccw_crw_notifier_handler (void * opaque )
291
+ {
292
+ VFIOCCWDevice * vcdev = opaque ;
293
+
294
+ while (event_notifier_test_and_clear (& vcdev -> crw_notifier )) {
295
+ vfio_ccw_crw_read (vcdev );
296
+ }
297
+ }
298
+
257
299
static void vfio_ccw_io_notifier_handler (void * opaque )
258
300
{
259
301
VFIOCCWDevice * vcdev = opaque ;
@@ -340,6 +382,10 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev,
340
382
notifier = & vcdev -> io_notifier ;
341
383
fd_read = vfio_ccw_io_notifier_handler ;
342
384
break ;
385
+ case VFIO_CCW_CRW_IRQ_INDEX :
386
+ notifier = & vcdev -> crw_notifier ;
387
+ fd_read = vfio_ccw_crw_notifier_handler ;
388
+ break ;
343
389
default :
344
390
error_setg (errp , "vfio: Unsupported device irq(%d)" , irq );
345
391
return ;
@@ -391,6 +437,9 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev,
391
437
case VFIO_CCW_IO_IRQ_INDEX :
392
438
notifier = & vcdev -> io_notifier ;
393
439
break ;
440
+ case VFIO_CCW_CRW_IRQ_INDEX :
441
+ notifier = & vcdev -> crw_notifier ;
442
+ break ;
394
443
default :
395
444
error_report ("vfio: Unsupported device irq(%d)" , irq );
396
445
return ;
@@ -468,10 +517,24 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
468
517
vcdev -> schib_region = g_malloc (info -> size );
469
518
}
470
519
520
+ ret = vfio_get_dev_region_info (vdev , VFIO_REGION_TYPE_CCW ,
521
+ VFIO_REGION_SUBTYPE_CCW_CRW , & info );
522
+
523
+ if (!ret ) {
524
+ vcdev -> crw_region_size = info -> size ;
525
+ if (sizeof (* vcdev -> crw_region ) != vcdev -> crw_region_size ) {
526
+ error_setg (errp , "vfio: Unexpected size of the CRW region" );
527
+ goto out_err ;
528
+ }
529
+ vcdev -> crw_region_offset = info -> offset ;
530
+ vcdev -> crw_region = g_malloc (info -> size );
531
+ }
532
+
471
533
g_free (info );
472
534
return ;
473
535
474
536
out_err :
537
+ g_free (vcdev -> crw_region );
475
538
g_free (vcdev -> schib_region );
476
539
g_free (vcdev -> async_cmd_region );
477
540
g_free (vcdev -> io_region );
@@ -481,6 +544,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
481
544
482
545
static void vfio_ccw_put_region (VFIOCCWDevice * vcdev )
483
546
{
547
+ g_free (vcdev -> crw_region );
484
548
g_free (vcdev -> schib_region );
485
549
g_free (vcdev -> async_cmd_region );
486
550
g_free (vcdev -> io_region );
@@ -596,6 +660,14 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
596
660
goto out_notifier_err ;
597
661
}
598
662
663
+ if (vcdev -> crw_region ) {
664
+ vfio_ccw_register_irq_notifier (vcdev , VFIO_CCW_CRW_IRQ_INDEX , & err );
665
+ if (err ) {
666
+ vfio_ccw_unregister_irq_notifier (vcdev , VFIO_CCW_IO_IRQ_INDEX );
667
+ goto out_notifier_err ;
668
+ }
669
+ }
670
+
599
671
return ;
600
672
601
673
out_notifier_err :
@@ -620,6 +692,7 @@ static void vfio_ccw_unrealize(DeviceState *dev)
620
692
S390CCWDeviceClass * cdc = S390_CCW_DEVICE_GET_CLASS (cdev );
621
693
VFIOGroup * group = vcdev -> vdev .group ;
622
694
695
+ vfio_ccw_unregister_irq_notifier (vcdev , VFIO_CCW_CRW_IRQ_INDEX );
623
696
vfio_ccw_unregister_irq_notifier (vcdev , VFIO_CCW_IO_IRQ_INDEX );
624
697
vfio_ccw_put_region (vcdev );
625
698
vfio_ccw_put_device (vcdev );
0 commit comments