@@ -41,6 +41,9 @@ struct VFIOCCWDevice {
41
41
uint64_t async_cmd_region_size ;
42
42
uint64_t async_cmd_region_offset ;
43
43
struct ccw_cmd_region * async_cmd_region ;
44
+ uint64_t schib_region_size ;
45
+ uint64_t schib_region_offset ;
46
+ struct ccw_schib_region * schib_region ;
44
47
EventNotifier io_notifier ;
45
48
bool force_orb_pfch ;
46
49
bool warned_orb_pfch ;
@@ -116,6 +119,51 @@ static IOInstEnding vfio_ccw_handle_request(SubchDev *sch)
116
119
}
117
120
}
118
121
122
+ static IOInstEnding vfio_ccw_handle_store (SubchDev * sch )
123
+ {
124
+ S390CCWDevice * cdev = sch -> driver_data ;
125
+ VFIOCCWDevice * vcdev = DO_UPCAST (VFIOCCWDevice , cdev , cdev );
126
+ SCHIB * schib = & sch -> curr_status ;
127
+ struct ccw_schib_region * region = vcdev -> schib_region ;
128
+ SCHIB * s ;
129
+ int ret ;
130
+
131
+ /* schib region not available so nothing else to do */
132
+ if (!region ) {
133
+ return IOINST_CC_EXPECTED ;
134
+ }
135
+
136
+ memset (region , 0 , sizeof (* region ));
137
+ ret = pread (vcdev -> vdev .fd , region , vcdev -> schib_region_size ,
138
+ vcdev -> schib_region_offset );
139
+
140
+ if (ret == -1 ) {
141
+ /*
142
+ * Device is probably damaged, but store subchannel does not
143
+ * have a nonzero cc defined for this scenario. Log an error,
144
+ * and presume things are otherwise fine.
145
+ */
146
+ error_report ("vfio-ccw: store region read failed with errno=%d" , errno );
147
+ return IOINST_CC_EXPECTED ;
148
+ }
149
+
150
+ /*
151
+ * Selectively copy path-related bits of the SCHIB,
152
+ * rather than copying the entire struct.
153
+ */
154
+ s = (SCHIB * )region -> schib_area ;
155
+ schib -> pmcw .pnom = s -> pmcw .pnom ;
156
+ schib -> pmcw .lpum = s -> pmcw .lpum ;
157
+ schib -> pmcw .pam = s -> pmcw .pam ;
158
+ schib -> pmcw .pom = s -> pmcw .pom ;
159
+
160
+ if (s -> scsw .flags & SCSW_FLAGS_MASK_PNO ) {
161
+ schib -> scsw .flags |= SCSW_FLAGS_MASK_PNO ;
162
+ }
163
+
164
+ return IOINST_CC_EXPECTED ;
165
+ }
166
+
119
167
static int vfio_ccw_handle_clear (SubchDev * sch )
120
168
{
121
169
S390CCWDevice * cdev = sch -> driver_data ;
@@ -382,10 +430,23 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
382
430
vcdev -> async_cmd_region = g_malloc0 (info -> size );
383
431
}
384
432
433
+ ret = vfio_get_dev_region_info (vdev , VFIO_REGION_TYPE_CCW ,
434
+ VFIO_REGION_SUBTYPE_CCW_SCHIB , & info );
435
+ if (!ret ) {
436
+ vcdev -> schib_region_size = info -> size ;
437
+ if (sizeof (* vcdev -> schib_region ) != vcdev -> schib_region_size ) {
438
+ error_setg (errp , "vfio: Unexpected size of the schib region" );
439
+ goto out_err ;
440
+ }
441
+ vcdev -> schib_region_offset = info -> offset ;
442
+ vcdev -> schib_region = g_malloc (info -> size );
443
+ }
444
+
385
445
g_free (info );
386
446
return ;
387
447
388
448
out_err :
449
+ g_free (vcdev -> schib_region );
389
450
g_free (vcdev -> async_cmd_region );
390
451
g_free (vcdev -> io_region );
391
452
g_free (info );
@@ -394,6 +455,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
394
455
395
456
static void vfio_ccw_put_region (VFIOCCWDevice * vcdev )
396
457
{
458
+ g_free (vcdev -> schib_region );
397
459
g_free (vcdev -> async_cmd_region );
398
460
g_free (vcdev -> io_region );
399
461
}
@@ -569,6 +631,7 @@ static void vfio_ccw_class_init(ObjectClass *klass, void *data)
569
631
cdc -> handle_request = vfio_ccw_handle_request ;
570
632
cdc -> handle_halt = vfio_ccw_handle_halt ;
571
633
cdc -> handle_clear = vfio_ccw_handle_clear ;
634
+ cdc -> handle_store = vfio_ccw_handle_store ;
572
635
}
573
636
574
637
static const TypeInfo vfio_ccw_info = {
0 commit comments