Skip to content

Commit 46ea384

Browse files
Farhan Alicohuck
authored andcommitted
vfio-ccw: Add support for the schib region
The schib region can be used to obtain the latest SCHIB from the host passthrough subchannel. Since the guest SCHIB is virtualized, we currently only update the path related information so that the guest is aware of any path related changes when it issues the 'stsch' instruction. Signed-off-by: Farhan Ali <[email protected]> Signed-off-by: Eric Farman <[email protected]> Reviewed-by: Cornelia Huck <[email protected]> Message-Id: <[email protected]> Signed-off-by: Cornelia Huck <[email protected]>
1 parent 2a3b9cb commit 46ea384

File tree

6 files changed

+99
-5
lines changed

6 files changed

+99
-5
lines changed

hw/s390x/css.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,11 +1335,20 @@ static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src)
13351335
}
13361336
}
13371337

1338-
int css_do_stsch(SubchDev *sch, SCHIB *schib)
1338+
IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib)
13391339
{
1340+
int ret;
1341+
1342+
/*
1343+
* For some subchannels, we may want to update parts of
1344+
* the schib (e.g., update path masks from the host device
1345+
* for passthrough subchannels).
1346+
*/
1347+
ret = s390_ccw_store(sch);
1348+
13401349
/* Use current status. */
13411350
copy_schib_to_guest(schib, &sch->curr_status);
1342-
return 0;
1351+
return ret;
13431352
}
13441353

13451354
static void copy_pmcw_from_guest(PMCW *dest, const PMCW *src)

hw/s390x/s390-ccw.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,27 @@ int s390_ccw_clear(SubchDev *sch)
5151
return cdc->handle_clear(sch);
5252
}
5353

54+
IOInstEnding s390_ccw_store(SubchDev *sch)
55+
{
56+
S390CCWDeviceClass *cdc = NULL;
57+
int ret = IOINST_CC_EXPECTED;
58+
59+
/*
60+
* This code is called for both virtual and passthrough devices,
61+
* but only applies to to the latter. This ugly check makes that
62+
* distinction for us.
63+
*/
64+
if (object_dynamic_cast(OBJECT(sch->driver_data), TYPE_S390_CCW)) {
65+
cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data);
66+
}
67+
68+
if (cdc && cdc->handle_store) {
69+
ret = cdc->handle_store(sch);
70+
}
71+
72+
return ret;
73+
}
74+
5475
static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
5576
char *sysfsdev,
5677
Error **errp)

hw/vfio/ccw.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ struct VFIOCCWDevice {
4141
uint64_t async_cmd_region_size;
4242
uint64_t async_cmd_region_offset;
4343
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;
4447
EventNotifier io_notifier;
4548
bool force_orb_pfch;
4649
bool warned_orb_pfch;
@@ -116,6 +119,51 @@ static IOInstEnding vfio_ccw_handle_request(SubchDev *sch)
116119
}
117120
}
118121

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+
119167
static int vfio_ccw_handle_clear(SubchDev *sch)
120168
{
121169
S390CCWDevice *cdev = sch->driver_data;
@@ -382,10 +430,23 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
382430
vcdev->async_cmd_region = g_malloc0(info->size);
383431
}
384432

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+
385445
g_free(info);
386446
return;
387447

388448
out_err:
449+
g_free(vcdev->schib_region);
389450
g_free(vcdev->async_cmd_region);
390451
g_free(vcdev->io_region);
391452
g_free(info);
@@ -394,6 +455,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
394455

395456
static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
396457
{
458+
g_free(vcdev->schib_region);
397459
g_free(vcdev->async_cmd_region);
398460
g_free(vcdev->io_region);
399461
}
@@ -569,6 +631,7 @@ static void vfio_ccw_class_init(ObjectClass *klass, void *data)
569631
cdc->handle_request = vfio_ccw_handle_request;
570632
cdc->handle_halt = vfio_ccw_handle_halt;
571633
cdc->handle_clear = vfio_ccw_handle_clear;
634+
cdc->handle_store = vfio_ccw_handle_store;
572635
}
573636

574637
static const TypeInfo vfio_ccw_info = {

include/hw/s390x/css.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ IOInstEnding do_subchannel_work_passthrough(SubchDev *sub);
218218

219219
int s390_ccw_halt(SubchDev *sch);
220220
int s390_ccw_clear(SubchDev *sch);
221+
IOInstEnding s390_ccw_store(SubchDev *sch);
221222

222223
typedef enum {
223224
CSS_IO_ADAPTER_VIRTIO = 0,
@@ -242,7 +243,7 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid,
242243
uint16_t schid);
243244
bool css_subch_visible(SubchDev *sch);
244245
void css_conditional_io_interrupt(SubchDev *sch);
245-
int css_do_stsch(SubchDev *sch, SCHIB *schib);
246+
IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib);
246247
bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid);
247248
IOInstEnding css_do_msch(SubchDev *sch, const SCHIB *schib);
248249
IOInstEnding css_do_xsch(SubchDev *sch);

include/hw/s390x/s390-ccw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ typedef struct S390CCWDeviceClass {
3737
IOInstEnding (*handle_request) (SubchDev *sch);
3838
int (*handle_halt) (SubchDev *sch);
3939
int (*handle_clear) (SubchDev *sch);
40+
IOInstEnding (*handle_store) (SubchDev *sch);
4041
} S390CCWDeviceClass;
4142

4243
#endif

target/s390x/ioinst.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
292292
sch = css_find_subch(m, cssid, ssid, schid);
293293
if (sch) {
294294
if (css_subch_visible(sch)) {
295-
css_do_stsch(sch, &schib);
296-
cc = 0;
295+
cc = css_do_stsch(sch, &schib);
297296
} else {
298297
/* Indicate no more subchannels in this css/ss */
299298
cc = 3;

0 commit comments

Comments
 (0)