Assorted fixes, cleanups and enhancements.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJW1YDIAAoJEN7Pa5PG8C+v2IYP/RsoJmh4au+JLB4Um+cDNlJD
 3r+E53W4mO3ItZhTomCNhAmBZg1T84u3VuJU7Ix0oZMuSeZGHllly3V37fCsZOG0
 mYDzLvSlWXlWA7gLYtr7hQFDvDr1PBi+zMMTBWYcae1TkdZlW+MIUFrh0EHTarc2
 bxT4GGPfAdcYCxlqj6AQf8kYZipKLiBoHXyCyHhVDtgDk087rGkVbUdZRoUUO7h1
 xXKinL+Z710GFzsLONd2hlEO+60EqzVDiYPeYK3dEYhj+Rr/ZKqUtd7lGCAffqki
 czoiVz5sQkM/PoSn+UPdFR8khXmRvTL2rH9W0Ho2xBibyW2ViSCmgMzAmDxnMDXj
 MPg0JD/zd+mY3y1APXacIx0rppJs3iQyDrrAwPk0sJolHz4mIKpyYkkUWfvxgBqj
 lDnpbdEuz0e2HOu0lG3dTeEhGQIrENo3Xxee252PnrrNVoE2Man9Gx4lC0TdW/rK
 GZufQTdTnH9EHf4kuNsWoRRaevqdguz2wichO+sDWdoKW28kP11o26s+TAMpUf1L
 oMBMPA7dFYpUWm5X8mHwP+w7Jdo3+rbahdj+1cKtf+0GQxsyHTbTvY8VvBAGFHD3
 uooooSDh7Tqly0zBMU1RsbdBpw85QG4KX6NFl1/IKcUvXq+8S+s/mldg5mxnFK8U
 Iwl324KNGrfdoZZ6u5d6
 =8wMZ
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20160301' into staging

Assorted fixes, cleanups and enhancements.

# gpg: Signature made Tue 01 Mar 2016 11:45:12 GMT using RSA key ID C6F02FAF
# gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"

* remotes/cohuck/tags/s390x-20160301:
  s390x/css: only suspend when enabled by orb
  MAINTAINERS: Remove entry for hw/s390x/s390-virtio-bus.[ch]
  MAINTAINERS: Remove the old s390-virtio machine
  s390x/pci: use PCI_MSIX_FLAGS on retrieving the MSIX entries
  s390x/css: Use static initialization for channel_subsys fields
  s390x/css: Allocate channel_subsys statically
  s390x/pci: fix reg/dereg irq functions
  s390x/css: introduce indicator refcounting interfaces
  s390x/virtio: old machine leftovers
  watchdog/diag288: avoid race condition on expired watchdog
  s390x: remove {kvm_}s390_virtio_irq()
  s390x: fix debug statement in trigger_page_fault()
  s390x/kvm: sync fprs via kvm_run
  linux-headers: update against kvm/next

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-03-01 13:09:55 +00:00
commit 9c279bec75
23 changed files with 246 additions and 240 deletions

View File

@ -656,12 +656,6 @@ F: hw/*/grlib*
S390 Machines S390 Machines
------------- -------------
S390 Virtio
M: Alexander Graf <agraf@suse.de>
S: Maintained
F: hw/s390x/s390-*.c
X: hw/s390x/*pci*.[hc]
S390 Virtio-ccw S390 Virtio-ccw
M: Cornelia Huck <cornelia.huck@de.ibm.com> M: Cornelia Huck <cornelia.huck@de.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com> M: Christian Borntraeger <borntraeger@de.ibm.com>
@ -669,7 +663,6 @@ M: Alexander Graf <agraf@suse.de>
S: Supported S: Supported
F: hw/char/sclp*.[hc] F: hw/char/sclp*.[hc]
F: hw/s390x/ F: hw/s390x/
X: hw/s390x/s390-virtio-bus.[ch]
F: include/hw/s390x/ F: include/hw/s390x/
F: pc-bios/s390-ccw/ F: pc-bios/s390-ccw/
F: hw/watchdog/wdt_diag288.c F: hw/watchdog/wdt_diag288.c

View File

@ -60,9 +60,81 @@ typedef struct ChannelSubSys {
CssImage *css[MAX_CSSID + 1]; CssImage *css[MAX_CSSID + 1];
uint8_t default_cssid; uint8_t default_cssid;
QTAILQ_HEAD(, IoAdapter) io_adapters; QTAILQ_HEAD(, IoAdapter) io_adapters;
QTAILQ_HEAD(, IndAddr) indicator_addresses;
} ChannelSubSys; } ChannelSubSys;
static ChannelSubSys *channel_subsys; static ChannelSubSys channel_subsys = {
.pending_crws = QTAILQ_HEAD_INITIALIZER(channel_subsys.pending_crws),
.do_crw_mchk = true,
.sei_pending = false,
.do_crw_mchk = true,
.crws_lost = false,
.chnmon_active = false,
.io_adapters = QTAILQ_HEAD_INITIALIZER(channel_subsys.io_adapters),
.indicator_addresses =
QTAILQ_HEAD_INITIALIZER(channel_subsys.indicator_addresses),
};
IndAddr *get_indicator(hwaddr ind_addr, int len)
{
IndAddr *indicator;
QTAILQ_FOREACH(indicator, &channel_subsys.indicator_addresses, sibling) {
if (indicator->addr == ind_addr) {
indicator->refcnt++;
return indicator;
}
}
indicator = g_new0(IndAddr, 1);
indicator->addr = ind_addr;
indicator->len = len;
indicator->refcnt = 1;
QTAILQ_INSERT_TAIL(&channel_subsys.indicator_addresses,
indicator, sibling);
return indicator;
}
static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr,
bool do_map)
{
S390FLICState *fs = s390_get_flic();
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map);
}
void release_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
assert(indicator->refcnt > 0);
indicator->refcnt--;
if (indicator->refcnt > 0) {
return;
}
QTAILQ_REMOVE(&channel_subsys.indicator_addresses, indicator, sibling);
if (indicator->map) {
s390_io_adapter_map(adapter, indicator->map, false);
}
g_free(indicator);
}
int map_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
int ret;
if (indicator->map) {
return 0; /* already mapped is not an error */
}
indicator->map = indicator->addr;
ret = s390_io_adapter_map(adapter, indicator->map, true);
if ((ret != 0) && (ret != -ENOSYS)) {
goto out_err;
}
return 0;
out_err:
indicator->map = 0;
return ret;
}
int css_create_css_image(uint8_t cssid, bool default_image) int css_create_css_image(uint8_t cssid, bool default_image)
{ {
@ -70,12 +142,12 @@ int css_create_css_image(uint8_t cssid, bool default_image)
if (cssid > MAX_CSSID) { if (cssid > MAX_CSSID) {
return -EINVAL; return -EINVAL;
} }
if (channel_subsys->css[cssid]) { if (channel_subsys.css[cssid]) {
return -EBUSY; return -EBUSY;
} }
channel_subsys->css[cssid] = g_malloc0(sizeof(CssImage)); channel_subsys.css[cssid] = g_malloc0(sizeof(CssImage));
if (default_image) { if (default_image) {
channel_subsys->default_cssid = cssid; channel_subsys.default_cssid = cssid;
} }
return 0; return 0;
} }
@ -90,7 +162,7 @@ int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap,
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
*id = 0; *id = 0;
QTAILQ_FOREACH(adapter, &channel_subsys->io_adapters, sibling) { QTAILQ_FOREACH(adapter, &channel_subsys.io_adapters, sibling) {
if ((adapter->type == type) && (adapter->isc == isc)) { if ((adapter->type == type) && (adapter->isc == isc)) {
*id = adapter->id; *id = adapter->id;
found = true; found = true;
@ -110,7 +182,7 @@ int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap,
adapter->id = *id; adapter->id = *id;
adapter->isc = isc; adapter->isc = isc;
adapter->type = type; adapter->type = type;
QTAILQ_INSERT_TAIL(&channel_subsys->io_adapters, adapter, sibling); QTAILQ_INSERT_TAIL(&channel_subsys.io_adapters, adapter, sibling);
} else { } else {
g_free(adapter); g_free(adapter);
fprintf(stderr, "Unexpected error %d when registering adapter %d\n", fprintf(stderr, "Unexpected error %d when registering adapter %d\n",
@ -122,7 +194,7 @@ out:
uint16_t css_build_subchannel_id(SubchDev *sch) uint16_t css_build_subchannel_id(SubchDev *sch)
{ {
if (channel_subsys->max_cssid > 0) { if (channel_subsys.max_cssid > 0) {
return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1; return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1;
} }
return (sch->ssid << 1) | 1; return (sch->ssid << 1) | 1;
@ -270,7 +342,8 @@ static CCW1 copy_ccw_from_guest(hwaddr addr, bool fmt1)
return ret; return ret;
} }
static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr) static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
bool suspend_allowed)
{ {
int ret; int ret;
bool check_len; bool check_len;
@ -298,7 +371,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr)
} }
if (ccw.flags & CCW_FLAG_SUSPEND) { if (ccw.flags & CCW_FLAG_SUSPEND) {
return -EINPROGRESS; return suspend_allowed ? -EINPROGRESS : -EINVAL;
} }
check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC)); check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC));
@ -396,6 +469,7 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
SCSW *s = &sch->curr_status.scsw; SCSW *s = &sch->curr_status.scsw;
int path; int path;
int ret; int ret;
bool suspend_allowed;
/* Path management: In our simple css, we always choose the only path. */ /* Path management: In our simple css, we always choose the only path. */
path = 0x80; path = 0x80;
@ -415,12 +489,15 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
} }
sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT); sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT);
sch->ccw_no_data_cnt = 0; sch->ccw_no_data_cnt = 0;
suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND);
} else { } else {
s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND); s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND);
/* The channel program had been suspended before. */
suspend_allowed = true;
} }
sch->last_cmd_valid = false; sch->last_cmd_valid = false;
do { do {
ret = css_interpret_ccw(sch, sch->channel_prog); ret = css_interpret_ccw(sch, sch->channel_prog, suspend_allowed);
switch (ret) { switch (ret) {
case -EAGAIN: case -EAGAIN:
/* ccw chain, continue processing */ /* ccw chain, continue processing */
@ -778,12 +855,12 @@ static void css_update_chnmon(SubchDev *sch)
offset = sch->curr_status.pmcw.mbi << 5; offset = sch->curr_status.pmcw.mbi << 5;
count = address_space_lduw(&address_space_memory, count = address_space_lduw(&address_space_memory,
channel_subsys->chnmon_area + offset, channel_subsys.chnmon_area + offset,
MEMTXATTRS_UNSPECIFIED, MEMTXATTRS_UNSPECIFIED,
NULL); NULL);
count++; count++;
address_space_stw(&address_space_memory, address_space_stw(&address_space_memory,
channel_subsys->chnmon_area + offset, count, channel_subsys.chnmon_area + offset, count,
MEMTXATTRS_UNSPECIFIED, NULL); MEMTXATTRS_UNSPECIFIED, NULL);
} }
} }
@ -812,7 +889,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
} }
/* If monitoring is active, update counter. */ /* If monitoring is active, update counter. */
if (channel_subsys->chnmon_active) { if (channel_subsys.chnmon_active) {
css_update_chnmon(sch); css_update_chnmon(sch);
} }
sch->channel_prog = orb->cpa; sch->channel_prog = orb->cpa;
@ -971,16 +1048,16 @@ int css_do_stcrw(CRW *crw)
CrwContainer *crw_cont; CrwContainer *crw_cont;
int ret; int ret;
crw_cont = QTAILQ_FIRST(&channel_subsys->pending_crws); crw_cont = QTAILQ_FIRST(&channel_subsys.pending_crws);
if (crw_cont) { if (crw_cont) {
QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling); QTAILQ_REMOVE(&channel_subsys.pending_crws, crw_cont, sibling);
copy_crw_to_guest(crw, &crw_cont->crw); copy_crw_to_guest(crw, &crw_cont->crw);
g_free(crw_cont); g_free(crw_cont);
ret = 0; ret = 0;
} else { } else {
/* List was empty, turn crw machine checks on again. */ /* List was empty, turn crw machine checks on again. */
memset(crw, 0, sizeof(*crw)); memset(crw, 0, sizeof(*crw));
channel_subsys->do_crw_mchk = true; channel_subsys.do_crw_mchk = true;
ret = 1; ret = 1;
} }
@ -999,12 +1076,12 @@ void css_undo_stcrw(CRW *crw)
crw_cont = g_try_malloc0(sizeof(CrwContainer)); crw_cont = g_try_malloc0(sizeof(CrwContainer));
if (!crw_cont) { if (!crw_cont) {
channel_subsys->crws_lost = true; channel_subsys.crws_lost = true;
return; return;
} }
copy_crw_from_guest(&crw_cont->crw, crw); copy_crw_from_guest(&crw_cont->crw, crw);
QTAILQ_INSERT_HEAD(&channel_subsys->pending_crws, crw_cont, sibling); QTAILQ_INSERT_HEAD(&channel_subsys.pending_crws, crw_cont, sibling);
} }
int css_do_tpi(IOIntCode *int_code, int lowcore) int css_do_tpi(IOIntCode *int_code, int lowcore)
@ -1022,9 +1099,9 @@ int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid,
CssImage *css; CssImage *css;
if (!m && !cssid) { if (!m && !cssid) {
css = channel_subsys->css[channel_subsys->default_cssid]; css = channel_subsys.css[channel_subsys.default_cssid];
} else { } else {
css = channel_subsys->css[cssid]; css = channel_subsys.css[cssid];
} }
if (!css) { if (!css) {
return 0; return 0;
@ -1059,15 +1136,15 @@ void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo)
{ {
/* dct is currently ignored (not really meaningful for our devices) */ /* dct is currently ignored (not really meaningful for our devices) */
/* TODO: Don't ignore mbk. */ /* TODO: Don't ignore mbk. */
if (update && !channel_subsys->chnmon_active) { if (update && !channel_subsys.chnmon_active) {
/* Enable measuring. */ /* Enable measuring. */
channel_subsys->chnmon_area = mbo; channel_subsys.chnmon_area = mbo;
channel_subsys->chnmon_active = true; channel_subsys.chnmon_active = true;
} }
if (!update && channel_subsys->chnmon_active) { if (!update && channel_subsys.chnmon_active) {
/* Disable measuring. */ /* Disable measuring. */
channel_subsys->chnmon_area = 0; channel_subsys.chnmon_area = 0;
channel_subsys->chnmon_active = false; channel_subsys.chnmon_active = false;
} }
} }
@ -1095,7 +1172,7 @@ int css_do_rsch(SubchDev *sch)
} }
/* If monitoring is active, update counter. */ /* If monitoring is active, update counter. */
if (channel_subsys->chnmon_active) { if (channel_subsys.chnmon_active) {
css_update_chnmon(sch); css_update_chnmon(sch);
} }
@ -1111,23 +1188,23 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid)
{ {
uint8_t real_cssid; uint8_t real_cssid;
if (cssid > channel_subsys->max_cssid) { if (cssid > channel_subsys.max_cssid) {
return -EINVAL; return -EINVAL;
} }
if (channel_subsys->max_cssid == 0) { if (channel_subsys.max_cssid == 0) {
real_cssid = channel_subsys->default_cssid; real_cssid = channel_subsys.default_cssid;
} else { } else {
real_cssid = cssid; real_cssid = cssid;
} }
if (!channel_subsys->css[real_cssid]) { if (!channel_subsys.css[real_cssid]) {
return -EINVAL; return -EINVAL;
} }
if (!channel_subsys->css[real_cssid]->chpids[chpid].in_use) { if (!channel_subsys.css[real_cssid]->chpids[chpid].in_use) {
return -ENODEV; return -ENODEV;
} }
if (!channel_subsys->css[real_cssid]->chpids[chpid].is_virtual) { if (!channel_subsys.css[real_cssid]->chpids[chpid].is_virtual) {
fprintf(stderr, fprintf(stderr,
"rchp unsupported for non-virtual chpid %x.%02x!\n", "rchp unsupported for non-virtual chpid %x.%02x!\n",
real_cssid, chpid); real_cssid, chpid);
@ -1136,8 +1213,8 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid)
/* We don't really use a channel path, so we're done here. */ /* We don't really use a channel path, so we're done here. */
css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT,
channel_subsys->max_cssid > 0 ? 1 : 0, chpid); channel_subsys.max_cssid > 0 ? 1 : 0, chpid);
if (channel_subsys->max_cssid > 0) { if (channel_subsys.max_cssid > 0) {
css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 0, real_cssid << 8); css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 0, real_cssid << 8);
} }
return 0; return 0;
@ -1148,13 +1225,13 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
SubchSet *set; SubchSet *set;
uint8_t real_cssid; uint8_t real_cssid;
real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid; real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid;
if (real_cssid > MAX_CSSID || ssid > MAX_SSID || if (real_cssid > MAX_CSSID || ssid > MAX_SSID ||
!channel_subsys->css[real_cssid] || !channel_subsys.css[real_cssid] ||
!channel_subsys->css[real_cssid]->sch_set[ssid]) { !channel_subsys.css[real_cssid]->sch_set[ssid]) {
return true; return true;
} }
set = channel_subsys->css[real_cssid]->sch_set[ssid]; set = channel_subsys.css[real_cssid]->sch_set[ssid];
return schid > find_last_bit(set->schids_used, return schid > find_last_bit(set->schids_used,
(MAX_SCHID + 1) / sizeof(unsigned long)); (MAX_SCHID + 1) / sizeof(unsigned long));
} }
@ -1167,7 +1244,7 @@ static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
if (cssid > MAX_CSSID) { if (cssid > MAX_CSSID) {
return -EINVAL; return -EINVAL;
} }
css = channel_subsys->css[cssid]; css = channel_subsys.css[cssid];
if (!css) { if (!css) {
return -EINVAL; return -EINVAL;
} }
@ -1188,7 +1265,7 @@ void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type)
PMCW *p = &sch->curr_status.pmcw; PMCW *p = &sch->curr_status.pmcw;
SCSW *s = &sch->curr_status.scsw; SCSW *s = &sch->curr_status.scsw;
int i; int i;
CssImage *css = channel_subsys->css[sch->cssid]; CssImage *css = channel_subsys.css[sch->cssid];
assert(css != NULL); assert(css != NULL);
memset(p, 0, sizeof(PMCW)); memset(p, 0, sizeof(PMCW));
@ -1214,27 +1291,27 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid)
{ {
uint8_t real_cssid; uint8_t real_cssid;
real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid; real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid;
if (!channel_subsys->css[real_cssid]) { if (!channel_subsys.css[real_cssid]) {
return NULL; return NULL;
} }
if (!channel_subsys->css[real_cssid]->sch_set[ssid]) { if (!channel_subsys.css[real_cssid]->sch_set[ssid]) {
return NULL; return NULL;
} }
return channel_subsys->css[real_cssid]->sch_set[ssid]->sch[schid]; return channel_subsys.css[real_cssid]->sch_set[ssid]->sch[schid];
} }
bool css_subch_visible(SubchDev *sch) bool css_subch_visible(SubchDev *sch)
{ {
if (sch->ssid > channel_subsys->max_ssid) { if (sch->ssid > channel_subsys.max_ssid) {
return false; return false;
} }
if (sch->cssid != channel_subsys->default_cssid) { if (sch->cssid != channel_subsys.default_cssid) {
return (channel_subsys->max_cssid > 0); return (channel_subsys.max_cssid > 0);
} }
return true; return true;
@ -1242,20 +1319,20 @@ bool css_subch_visible(SubchDev *sch)
bool css_present(uint8_t cssid) bool css_present(uint8_t cssid)
{ {
return (channel_subsys->css[cssid] != NULL); return (channel_subsys.css[cssid] != NULL);
} }
bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno) bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno)
{ {
if (!channel_subsys->css[cssid]) { if (!channel_subsys.css[cssid]) {
return false; return false;
} }
if (!channel_subsys->css[cssid]->sch_set[ssid]) { if (!channel_subsys.css[cssid]->sch_set[ssid]) {
return false; return false;
} }
return !!test_bit(devno, return !!test_bit(devno,
channel_subsys->css[cssid]->sch_set[ssid]->devnos_used); channel_subsys.css[cssid]->sch_set[ssid]->devnos_used);
} }
void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid, void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
@ -1266,13 +1343,13 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
trace_css_assign_subch(sch ? "assign" : "deassign", cssid, ssid, schid, trace_css_assign_subch(sch ? "assign" : "deassign", cssid, ssid, schid,
devno); devno);
if (!channel_subsys->css[cssid]) { if (!channel_subsys.css[cssid]) {
fprintf(stderr, fprintf(stderr,
"Suspicious call to %s (%x.%x.%04x) for non-existing css!\n", "Suspicious call to %s (%x.%x.%04x) for non-existing css!\n",
__func__, cssid, ssid, schid); __func__, cssid, ssid, schid);
return; return;
} }
css = channel_subsys->css[cssid]; css = channel_subsys.css[cssid];
if (!css->sch_set[ssid]) { if (!css->sch_set[ssid]) {
css->sch_set[ssid] = g_malloc0(sizeof(SubchSet)); css->sch_set[ssid] = g_malloc0(sizeof(SubchSet));
@ -1297,7 +1374,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
/* TODO: Maybe use a static crw pool? */ /* TODO: Maybe use a static crw pool? */
crw_cont = g_try_malloc0(sizeof(CrwContainer)); crw_cont = g_try_malloc0(sizeof(CrwContainer));
if (!crw_cont) { if (!crw_cont) {
channel_subsys->crws_lost = true; channel_subsys.crws_lost = true;
return; return;
} }
crw_cont->crw.flags = (rsc << 8) | erc; crw_cont->crw.flags = (rsc << 8) | erc;
@ -1305,15 +1382,15 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
crw_cont->crw.flags |= CRW_FLAGS_MASK_C; crw_cont->crw.flags |= CRW_FLAGS_MASK_C;
} }
crw_cont->crw.rsid = rsid; crw_cont->crw.rsid = rsid;
if (channel_subsys->crws_lost) { if (channel_subsys.crws_lost) {
crw_cont->crw.flags |= CRW_FLAGS_MASK_R; crw_cont->crw.flags |= CRW_FLAGS_MASK_R;
channel_subsys->crws_lost = false; channel_subsys.crws_lost = false;
} }
QTAILQ_INSERT_TAIL(&channel_subsys->pending_crws, crw_cont, sibling); QTAILQ_INSERT_TAIL(&channel_subsys.pending_crws, crw_cont, sibling);
if (channel_subsys->do_crw_mchk) { if (channel_subsys.do_crw_mchk) {
channel_subsys->do_crw_mchk = false; channel_subsys.do_crw_mchk = false;
/* Inject crw pending machine check. */ /* Inject crw pending machine check. */
s390_crw_mchk(); s390_crw_mchk();
} }
@ -1328,9 +1405,9 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
if (add && !hotplugged) { if (add && !hotplugged) {
return; return;
} }
if (channel_subsys->max_cssid == 0) { if (channel_subsys.max_cssid == 0) {
/* Default cssid shows up as 0. */ /* Default cssid shows up as 0. */
guest_cssid = (cssid == channel_subsys->default_cssid) ? 0 : cssid; guest_cssid = (cssid == channel_subsys.default_cssid) ? 0 : cssid;
} else { } else {
/* Show real cssid to the guest. */ /* Show real cssid to the guest. */
guest_cssid = cssid; guest_cssid = cssid;
@ -1339,14 +1416,14 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
* Only notify for higher subchannel sets/channel subsystems if the * Only notify for higher subchannel sets/channel subsystems if the
* guest has enabled it. * guest has enabled it.
*/ */
if ((ssid > channel_subsys->max_ssid) || if ((ssid > channel_subsys.max_ssid) ||
(guest_cssid > channel_subsys->max_cssid) || (guest_cssid > channel_subsys.max_cssid) ||
((channel_subsys->max_cssid == 0) && ((channel_subsys.max_cssid == 0) &&
(cssid != channel_subsys->default_cssid))) { (cssid != channel_subsys.default_cssid))) {
return; return;
} }
chain_crw = (channel_subsys->max_ssid > 0) || chain_crw = (channel_subsys.max_ssid > 0) ||
(channel_subsys->max_cssid > 0); (channel_subsys.max_cssid > 0);
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, chain_crw ? 1 : 0, schid); css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, chain_crw ? 1 : 0, schid);
if (chain_crw) { if (chain_crw) {
css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0, css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0,
@ -1361,28 +1438,28 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
void css_generate_css_crws(uint8_t cssid) void css_generate_css_crws(uint8_t cssid)
{ {
if (!channel_subsys->sei_pending) { if (!channel_subsys.sei_pending) {
css_queue_crw(CRW_RSC_CSS, 0, 0, cssid); css_queue_crw(CRW_RSC_CSS, 0, 0, cssid);
} }
channel_subsys->sei_pending = true; channel_subsys.sei_pending = true;
} }
void css_clear_sei_pending(void) void css_clear_sei_pending(void)
{ {
channel_subsys->sei_pending = false; channel_subsys.sei_pending = false;
} }
int css_enable_mcsse(void) int css_enable_mcsse(void)
{ {
trace_css_enable_facility("mcsse"); trace_css_enable_facility("mcsse");
channel_subsys->max_cssid = MAX_CSSID; channel_subsys.max_cssid = MAX_CSSID;
return 0; return 0;
} }
int css_enable_mss(void) int css_enable_mss(void)
{ {
trace_css_enable_facility("mss"); trace_css_enable_facility("mss");
channel_subsys->max_ssid = MAX_SSID; channel_subsys.max_ssid = MAX_SSID;
return 0; return 0;
} }
@ -1505,28 +1582,15 @@ int subch_device_load(SubchDev *s, QEMUFile *f)
*/ */
if (s->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA) { if (s->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA) {
if (s->ssid) { if (s->ssid) {
channel_subsys->max_ssid = MAX_SSID; channel_subsys.max_ssid = MAX_SSID;
} }
if (s->cssid != channel_subsys->default_cssid) { if (s->cssid != channel_subsys.default_cssid) {
channel_subsys->max_cssid = MAX_CSSID; channel_subsys.max_cssid = MAX_CSSID;
} }
} }
return 0; return 0;
} }
static void css_init(void)
{
channel_subsys = g_malloc0(sizeof(*channel_subsys));
QTAILQ_INIT(&channel_subsys->pending_crws);
channel_subsys->sei_pending = false;
channel_subsys->do_crw_mchk = true;
channel_subsys->crws_lost = false;
channel_subsys->chnmon_active = false;
QTAILQ_INIT(&channel_subsys->io_adapters);
}
machine_init(css_init);
void css_reset_sch(SubchDev *sch) void css_reset_sch(SubchDev *sch)
{ {
PMCW *p = &sch->curr_status.pmcw; PMCW *p = &sch->curr_status.pmcw;
@ -1564,19 +1628,19 @@ void css_reset(void)
CrwContainer *crw_cont; CrwContainer *crw_cont;
/* Clean up monitoring. */ /* Clean up monitoring. */
channel_subsys->chnmon_active = false; channel_subsys.chnmon_active = false;
channel_subsys->chnmon_area = 0; channel_subsys.chnmon_area = 0;
/* Clear pending CRWs. */ /* Clear pending CRWs. */
while ((crw_cont = QTAILQ_FIRST(&channel_subsys->pending_crws))) { while ((crw_cont = QTAILQ_FIRST(&channel_subsys.pending_crws))) {
QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling); QTAILQ_REMOVE(&channel_subsys.pending_crws, crw_cont, sibling);
g_free(crw_cont); g_free(crw_cont);
} }
channel_subsys->sei_pending = false; channel_subsys.sei_pending = false;
channel_subsys->do_crw_mchk = true; channel_subsys.do_crw_mchk = true;
channel_subsys->crws_lost = false; channel_subsys.crws_lost = false;
/* Reset maximum ids. */ /* Reset maximum ids. */
channel_subsys->max_cssid = 0; channel_subsys.max_cssid = 0;
channel_subsys->max_ssid = 0; channel_subsys.max_ssid = 0;
} }

View File

@ -12,6 +12,8 @@
#ifndef CSS_H #ifndef CSS_H
#define CSS_H #define CSS_H
#include "hw/s390x/adapter.h"
#include "hw/s390x/s390_flic.h"
#include "ioinst.h" #include "ioinst.h"
/* Channel subsystem constants. */ /* Channel subsystem constants. */
@ -86,6 +88,18 @@ struct SubchDev {
void *driver_data; void *driver_data;
}; };
typedef struct IndAddr {
hwaddr addr;
uint64_t map;
unsigned long refcnt;
int len;
QTAILQ_ENTRY(IndAddr) sibling;
} IndAddr;
IndAddr *get_indicator(hwaddr ind_addr, int len);
void release_indicator(AdapterInfo *adapter, IndAddr *indicator);
int map_indicator(AdapterInfo *adapter, IndAddr *indicator);
typedef SubchDev *(*css_subch_cb_func)(uint8_t m, uint8_t cssid, uint8_t ssid, typedef SubchDev *(*css_subch_cb_func)(uint8_t m, uint8_t cssid, uint8_t ssid,
uint16_t schid); uint16_t schid);
void subch_device_save(SubchDev *s, QEMUFile *f); void subch_device_save(SubchDev *s, QEMUFile *f);

View File

@ -524,7 +524,7 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
return 0; return 0;
} }
ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_CAP_FLAGS, ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_FLAGS,
pci_config_size(pbdev->pdev), sizeof(ctrl)); pci_config_size(pbdev->pdev), sizeof(ctrl));
table = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_TABLE, table = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_TABLE,
pci_config_size(pbdev->pdev), sizeof(table)); pci_config_size(pbdev->pdev), sizeof(table));

View File

@ -233,6 +233,8 @@ typedef struct S390PCIBusDevice {
AddressSpace as; AddressSpace as;
MemoryRegion mr; MemoryRegion mr;
MemoryRegion iommu_mr; MemoryRegion iommu_mr;
IndAddr *summary_ind;
IndAddr *indicator;
} S390PCIBusDevice; } S390PCIBusDevice;
typedef struct S390pciState { typedef struct S390pciState {

View File

@ -621,19 +621,19 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib) static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
{ {
int ret; int ret, len;
S390FLICState *fs = s390_get_flic();
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
ret = css_register_io_adapter(S390_PCIPT_ADAPTER, ret = css_register_io_adapter(S390_PCIPT_ADAPTER,
FIB_DATA_ISC(ldl_p(&fib.data)), true, false, FIB_DATA_ISC(ldl_p(&fib.data)), true, false,
&pbdev->routes.adapter.adapter_id); &pbdev->routes.adapter.adapter_id);
assert(ret == 0); assert(ret == 0);
fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id, pbdev->summary_ind = get_indicator(ldq_p(&fib.aisb), sizeof(uint64_t));
ldq_p(&fib.aisb), true); len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long);
fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id, pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len);
ldq_p(&fib.aibv), true);
map_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
map_indicator(&pbdev->routes.adapter, pbdev->indicator);
pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb); pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb);
pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data)); pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data));
@ -649,12 +649,11 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
static int dereg_irqs(S390PCIBusDevice *pbdev) static int dereg_irqs(S390PCIBusDevice *pbdev)
{ {
S390FLICState *fs = s390_get_flic(); release_indicator(&pbdev->routes.adapter, pbdev->summary_ind);
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); release_indicator(&pbdev->routes.adapter, pbdev->indicator);
fsc->io_adapter_map(fs, pbdev->routes.adapter.adapter_id,
pbdev->routes.adapter.ind_addr, false);
pbdev->summary_ind = NULL;
pbdev->indicator = NULL;
pbdev->routes.adapter.summary_addr = 0; pbdev->routes.adapter.summary_addr = 0;
pbdev->routes.adapter.summary_offset = 0; pbdev->routes.adapter.summary_offset = 0;
pbdev->routes.adapter.ind_addr = 0; pbdev->routes.adapter.ind_addr = 0;

View File

@ -54,8 +54,6 @@
#endif #endif
#define MAX_BLK_DEVS 10 #define MAX_BLK_DEVS 10
#define S390_MACHINE "s390-virtio"
#define TYPE_S390_MACHINE MACHINE_TYPE_NAME(S390_MACHINE)
#define S390_TOD_CLOCK_VALUE_MISSING 0x00 #define S390_TOD_CLOCK_VALUE_MISSING 0x00
#define S390_TOD_CLOCK_VALUE_PRESENT 0x01 #define S390_TOD_CLOCK_VALUE_PRESENT 0x01

View File

@ -32,69 +32,6 @@
#include "virtio-ccw.h" #include "virtio-ccw.h"
#include "trace.h" #include "trace.h"
static QTAILQ_HEAD(, IndAddr) indicator_addresses =
QTAILQ_HEAD_INITIALIZER(indicator_addresses);
static IndAddr *get_indicator(hwaddr ind_addr, int len)
{
IndAddr *indicator;
QTAILQ_FOREACH(indicator, &indicator_addresses, sibling) {
if (indicator->addr == ind_addr) {
indicator->refcnt++;
return indicator;
}
}
indicator = g_new0(IndAddr, 1);
indicator->addr = ind_addr;
indicator->len = len;
indicator->refcnt = 1;
QTAILQ_INSERT_TAIL(&indicator_addresses, indicator, sibling);
return indicator;
}
static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr,
bool do_map)
{
S390FLICState *fs = s390_get_flic();
S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map);
}
static void release_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
assert(indicator->refcnt > 0);
indicator->refcnt--;
if (indicator->refcnt > 0) {
return;
}
QTAILQ_REMOVE(&indicator_addresses, indicator, sibling);
if (indicator->map) {
s390_io_adapter_map(adapter, indicator->map, false);
}
g_free(indicator);
}
static int map_indicator(AdapterInfo *adapter, IndAddr *indicator)
{
int ret;
if (indicator->map) {
return 0; /* already mapped is not an error */
}
indicator->map = indicator->addr;
ret = s390_io_adapter_map(adapter, indicator->map, true);
if ((ret != 0) && (ret != -ENOSYS)) {
goto out_err;
}
return 0;
out_err:
indicator->map = 0;
return ret;
}
static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
VirtioCcwDevice *dev); VirtioCcwDevice *dev);

View File

@ -23,7 +23,8 @@
#include <hw/virtio/virtio-balloon.h> #include <hw/virtio/virtio-balloon.h>
#include <hw/virtio/virtio-rng.h> #include <hw/virtio/virtio-rng.h>
#include <hw/virtio/virtio-bus.h> #include <hw/virtio/virtio-bus.h>
#include <hw/s390x/s390_flic.h>
#include "css.h"
#define VIRTUAL_CSSID 0xfe #define VIRTUAL_CSSID 0xfe
@ -75,14 +76,6 @@ typedef struct VirtIOCCWDeviceClass {
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1 #define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT) #define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
typedef struct IndAddr {
hwaddr addr;
uint64_t map;
unsigned long refcnt;
int len;
QTAILQ_ENTRY(IndAddr) sibling;
} IndAddr;
struct VirtioCcwDevice { struct VirtioCcwDevice {
DeviceState parent_obj; DeviceState parent_obj;
SubchDev *sch; SubchDev *sch;

View File

@ -51,15 +51,19 @@ static void diag288_reset(void *opaque)
static void diag288_timer_expired(void *dev) static void diag288_timer_expired(void *dev)
{ {
qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n"); qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
watchdog_perform_action(); /* Reset the watchdog only if the guest gets notified about
/* Reset the watchdog only if the guest was notified about expiry. */ * expiry. watchdog_perform_action() may temporarily relinquish
* the BQL; reset before triggering the action to avoid races with
* diag288 instructions. */
switch (get_watchdog_action()) { switch (get_watchdog_action()) {
case WDT_DEBUG: case WDT_DEBUG:
case WDT_NONE: case WDT_NONE:
case WDT_PAUSE: case WDT_PAUSE:
return; break;
default:
wdt_diag288_reset(dev);
} }
wdt_diag288_reset(dev); watchdog_perform_action();
} }
static int wdt_diag288_handle_timer(DIAG288State *diag288, static int wdt_diag288_handle_timer(DIAG288State *diag288,

View File

@ -416,6 +416,8 @@
#define __NR_execveat (__NR_SYSCALL_BASE+387) #define __NR_execveat (__NR_SYSCALL_BASE+387)
#define __NR_userfaultfd (__NR_SYSCALL_BASE+388) #define __NR_userfaultfd (__NR_SYSCALL_BASE+388)
#define __NR_membarrier (__NR_SYSCALL_BASE+389) #define __NR_membarrier (__NR_SYSCALL_BASE+389)
#define __NR_mlock2 (__NR_SYSCALL_BASE+390)
#define __NR_copy_file_range (__NR_SYSCALL_BASE+391)
/* /*
* The following SWIs are ARM private. * The following SWIs are ARM private.

View File

@ -388,18 +388,7 @@
#define __NR_switch_endian 363 #define __NR_switch_endian 363
#define __NR_userfaultfd 364 #define __NR_userfaultfd 364
#define __NR_membarrier 365 #define __NR_membarrier 365
#define __NR_semop 366
#define __NR_semget 367
#define __NR_semctl 368
#define __NR_semtimedop 369
#define __NR_msgsnd 370
#define __NR_msgrcv 371
#define __NR_msgget 372
#define __NR_msgctl 373
#define __NR_shmat 374
#define __NR_shmdt 375
#define __NR_shmget 376
#define __NR_shmctl 377
#define __NR_mlock2 378 #define __NR_mlock2 378
#define __NR_copy_file_range 379
#endif /* _ASM_POWERPC_UNISTD_H_ */ #endif /* _ASM_POWERPC_UNISTD_H_ */

View File

@ -153,6 +153,8 @@ struct kvm_guest_debug_arch {
#define KVM_SYNC_ARCH0 (1UL << 4) #define KVM_SYNC_ARCH0 (1UL << 4)
#define KVM_SYNC_PFAULT (1UL << 5) #define KVM_SYNC_PFAULT (1UL << 5)
#define KVM_SYNC_VRS (1UL << 6) #define KVM_SYNC_VRS (1UL << 6)
#define KVM_SYNC_RICCB (1UL << 7)
#define KVM_SYNC_FPRS (1UL << 8)
/* definition of registers in kvm_run */ /* definition of registers in kvm_run */
struct kvm_sync_regs { struct kvm_sync_regs {
__u64 prefix; /* prefix register */ __u64 prefix; /* prefix register */
@ -167,9 +169,14 @@ struct kvm_sync_regs {
__u64 pft; /* pfault token [PFAULT] */ __u64 pft; /* pfault token [PFAULT] */
__u64 pfs; /* pfault select [PFAULT] */ __u64 pfs; /* pfault select [PFAULT] */
__u64 pfc; /* pfault compare [PFAULT] */ __u64 pfc; /* pfault compare [PFAULT] */
__u64 vrs[32][2]; /* vector registers */ union {
__u64 vrs[32][2]; /* vector registers (KVM_SYNC_VRS) */
__u64 fprs[16]; /* fp registers (KVM_SYNC_FPRS) */
};
__u8 reserved[512]; /* for future vector expansion */ __u8 reserved[512]; /* for future vector expansion */
__u32 fpc; /* only valid with vector registers */ __u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
__u8 padding[52]; /* riccb needs to be 64byte aligned */
__u8 riccb[64]; /* runtime instrumentation controls block */
}; };
#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1) #define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)

View File

@ -310,7 +310,8 @@
#define __NR_recvmsg 372 #define __NR_recvmsg 372
#define __NR_shutdown 373 #define __NR_shutdown 373
#define __NR_mlock2 374 #define __NR_mlock2 374
#define NR_syscalls 375 #define __NR_copy_file_range 375
#define NR_syscalls 376
/* /*
* There are some system calls that are not present on 64 bit, some * There are some system calls that are not present on 64 bit, some

View File

@ -374,5 +374,6 @@
#define __NR_userfaultfd 374 #define __NR_userfaultfd 374
#define __NR_membarrier 375 #define __NR_membarrier 375
#define __NR_mlock2 376 #define __NR_mlock2 376
#define __NR_copy_file_range 377
#endif /* _ASM_X86_UNISTD_32_H */ #endif /* _ASM_X86_UNISTD_32_H */

View File

@ -327,5 +327,6 @@
#define __NR_userfaultfd 323 #define __NR_userfaultfd 323
#define __NR_membarrier 324 #define __NR_membarrier 324
#define __NR_mlock2 325 #define __NR_mlock2 325
#define __NR_copy_file_range 326
#endif /* _ASM_X86_UNISTD_64_H */ #endif /* _ASM_X86_UNISTD_64_H */

View File

@ -282,6 +282,7 @@
#define __NR_userfaultfd (__X32_SYSCALL_BIT + 323) #define __NR_userfaultfd (__X32_SYSCALL_BIT + 323)
#define __NR_membarrier (__X32_SYSCALL_BIT + 324) #define __NR_membarrier (__X32_SYSCALL_BIT + 324)
#define __NR_mlock2 (__X32_SYSCALL_BIT + 325) #define __NR_mlock2 (__X32_SYSCALL_BIT + 325)
#define __NR_copy_file_range (__X32_SYSCALL_BIT + 326)
#define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512) #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
#define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513) #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
#define __NR_ioctl (__X32_SYSCALL_BIT + 514) #define __NR_ioctl (__X32_SYSCALL_BIT + 514)

View File

@ -541,7 +541,13 @@ struct kvm_s390_pgm_info {
__u8 exc_access_id; __u8 exc_access_id;
__u8 per_access_id; __u8 per_access_id;
__u8 op_access_id; __u8 op_access_id;
__u8 pad[3]; #define KVM_S390_PGM_FLAGS_ILC_VALID 0x01
#define KVM_S390_PGM_FLAGS_ILC_0 0x02
#define KVM_S390_PGM_FLAGS_ILC_1 0x04
#define KVM_S390_PGM_FLAGS_ILC_MASK 0x06
#define KVM_S390_PGM_FLAGS_NO_REWIND 0x08
__u8 flags;
__u8 pad[2];
}; };
struct kvm_s390_prefix_info { struct kvm_s390_prefix_info {
@ -849,6 +855,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_SPLIT_IRQCHIP 121 #define KVM_CAP_SPLIT_IRQCHIP 121
#define KVM_CAP_IOEVENTFD_ANY_LENGTH 122 #define KVM_CAP_IOEVENTFD_ANY_LENGTH 122
#define KVM_CAP_HYPERV_SYNIC 123 #define KVM_CAP_HYPERV_SYNIC 123
#define KVM_CAP_S390_RI 124
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING

View File

@ -38,6 +38,13 @@
#define VFIO_SPAPR_TCE_v2_IOMMU 7 #define VFIO_SPAPR_TCE_v2_IOMMU 7
/*
* The No-IOMMU IOMMU offers no translation or isolation for devices and
* supports no ioctls outside of VFIO_CHECK_EXTENSION. Use of VFIO's No-IOMMU
* code will taint the host kernel and should be used with extreme caution.
*/
#define VFIO_NOIOMMU_IOMMU 8
/* /*
* The IOCTL interface is designed for extensibility by embedding the * The IOCTL interface is designed for extensibility by embedding the
* structure length (argsz) and flags into structures passed between * structure length (argsz) and flags into structures passed between
@ -568,8 +575,10 @@ struct vfio_iommu_spapr_tce_create {
__u32 flags; __u32 flags;
/* in */ /* in */
__u32 page_shift; __u32 page_shift;
__u32 __resv1;
__u64 window_size; __u64 window_size;
__u32 levels; __u32 levels;
__u32 __resv2;
/* out */ /* out */
__u64 start_addr; __u64 start_addr;
}; };

View File

@ -470,10 +470,8 @@ void s390x_tod_timer(void *opaque);
void s390x_cpu_timer(void *opaque); void s390x_cpu_timer(void *opaque);
int s390_virtio_hypercall(CPUS390XState *env); int s390_virtio_hypercall(CPUS390XState *env);
void s390_virtio_irq(int config_change, uint64_t token);
#ifdef CONFIG_KVM #ifdef CONFIG_KVM
void kvm_s390_virtio_irq(int config_change, uint64_t token);
void kvm_s390_service_interrupt(uint32_t parm); void kvm_s390_service_interrupt(uint32_t parm);
void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq); void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq); void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
@ -484,9 +482,6 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock); int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
#else #else
static inline void kvm_s390_virtio_irq(int config_change, uint64_t token)
{
}
static inline void kvm_s390_service_interrupt(uint32_t parm) static inline void kvm_s390_service_interrupt(uint32_t parm)
{ {
} }

View File

@ -28,17 +28,6 @@ void s390_sclp_extint(uint32_t parm)
} }
} }
void s390_virtio_irq(int config_change, uint64_t token)
{
if (kvm_enabled()) {
kvm_s390_virtio_irq(config_change, token);
} else {
S390CPU *dummy_cpu = s390_cpu_addr2state(0);
cpu_inject_ext(dummy_cpu, EXT_VIRTIO, config_change, token);
}
}
void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
uint32_t io_int_parm, uint32_t io_int_word) uint32_t io_int_parm, uint32_t io_int_word)
{ {

View File

@ -342,6 +342,12 @@ int kvm_arch_put_registers(CPUState *cs, int level)
} }
cs->kvm_run->s.regs.fpc = env->fpc; cs->kvm_run->s.regs.fpc = env->fpc;
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_VRS; cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_VRS;
} else if (can_sync_regs(cs, KVM_SYNC_FPRS)) {
for (i = 0; i < 16; i++) {
cs->kvm_run->s.regs.fprs[i] = get_freg(env, i)->ll;
}
cs->kvm_run->s.regs.fpc = env->fpc;
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_FPRS;
} else { } else {
/* Floating point */ /* Floating point */
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
@ -482,6 +488,11 @@ int kvm_arch_get_registers(CPUState *cs)
env->vregs[i][1].ll = cs->kvm_run->s.regs.vrs[i][1]; env->vregs[i][1].ll = cs->kvm_run->s.regs.vrs[i][1];
} }
env->fpc = cs->kvm_run->s.regs.fpc; env->fpc = cs->kvm_run->s.regs.fpc;
} else if (can_sync_regs(cs, KVM_SYNC_FPRS)) {
for (i = 0; i < 16; i++) {
get_freg(env, i)->ll = cs->kvm_run->s.regs.fprs[i];
}
env->fpc = cs->kvm_run->s.regs.fpc;
} else { } else {
r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu); r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
if (r < 0) { if (r < 0) {
@ -925,17 +936,6 @@ void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq)
__kvm_s390_floating_interrupt(irq); __kvm_s390_floating_interrupt(irq);
} }
void kvm_s390_virtio_irq(int config_change, uint64_t token)
{
struct kvm_s390_irq irq = {
.type = KVM_S390_INT_VIRTIO,
.u.ext.ext_params = config_change,
.u.ext.ext_params2 = token,
};
kvm_s390_floating_interrupt(&irq);
}
void kvm_s390_service_interrupt(uint32_t parm) void kvm_s390_service_interrupt(uint32_t parm)
{ {
struct kvm_s390_irq irq = { struct kvm_s390_irq irq = {

View File

@ -90,7 +90,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46; tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46;
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits); DPRINTF("%s: trans_exc_code=%016" PRIx64 "\n", __func__, tec);
if (!exc) { if (!exc) {
return; return;