s390x/sclp: properly guard pci-specific functions

If we do not provide zpci, pci reconfiguration via sclp is not available
either. I/O adapter configuration, however, should always be present.

Rename the values that refer to I/O adapter configuration (instead of only
pci) to make things clearer.

Move length checking of the sccb for I/O adapter configuration into the
common sclp code (out of the pci code). This also fixes an issue that
the pci code would refer to a field in the sccb before checking whether
it was actually long enough.

Check for the adapter type in the sccb and return unrecognized adapter
type if the guest tries to issue I/O adapter configure/deconfigure for
a type other than pci or for pci if the zpci facility is not provided.

Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Reviewed-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
Cornelia Huck 2017-07-06 17:13:14 +02:00
parent d32bd032d8
commit 80b7a26536
4 changed files with 48 additions and 29 deletions

View File

@ -122,16 +122,11 @@ S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid)
void s390_pci_sclp_configure(SCCB *sccb) void s390_pci_sclp_configure(SCCB *sccb)
{ {
PciCfgSccb *psccb = (PciCfgSccb *)sccb; IoaCfgSccb *psccb = (IoaCfgSccb *)sccb;
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(), S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(),
be32_to_cpu(psccb->aid)); be32_to_cpu(psccb->aid));
uint16_t rc; uint16_t rc;
if (be16_to_cpu(sccb->h.length) < 16) {
rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
goto out;
}
if (!pbdev) { if (!pbdev) {
DPRINTF("sclp config no dev found\n"); DPRINTF("sclp config no dev found\n");
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
@ -155,16 +150,11 @@ out:
void s390_pci_sclp_deconfigure(SCCB *sccb) void s390_pci_sclp_deconfigure(SCCB *sccb)
{ {
PciCfgSccb *psccb = (PciCfgSccb *)sccb; IoaCfgSccb *psccb = (IoaCfgSccb *)sccb;
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(), S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(),
be32_to_cpu(psccb->aid)); be32_to_cpu(psccb->aid));
uint16_t rc; uint16_t rc;
if (be16_to_cpu(sccb->h.length) < 16) {
rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
goto out;
}
if (!pbdev) { if (!pbdev) {
DPRINTF("sclp deconfig no dev found\n"); DPRINTF("sclp deconfig no dev found\n");
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;

View File

@ -244,14 +244,6 @@ typedef struct ChscSeiNt2Res {
uint8_t ccdf[4016]; uint8_t ccdf[4016];
} QEMU_PACKED ChscSeiNt2Res; } QEMU_PACKED ChscSeiNt2Res;
typedef struct PciCfgSccb {
SCCBHeader header;
uint8_t atype;
uint8_t reserved1;
uint16_t reserved2;
uint32_t aid;
} QEMU_PACKED PciCfgSccb;
typedef struct S390MsixInfo { typedef struct S390MsixInfo {
bool available; bool available;
uint8_t table_bar; uint8_t table_bar;

View File

@ -80,7 +80,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
prepare_cpu_entries(sclp, read_info->entries, cpu_count); prepare_cpu_entries(sclp, read_info->entries, cpu_count);
read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO | read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
SCLP_HAS_PCI_RECONFIG); SCLP_HAS_IOA_RECONFIG);
/* Memory Hotplug is only supported for the ccw machine type */ /* Memory Hotplug is only supported for the ccw machine type */
if (mhd) { if (mhd) {
@ -354,6 +354,35 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
} }
static void sclp_configure_io_adapter(SCLPDevice *sclp, SCCB *sccb,
bool configure)
{
int rc;
if (be16_to_cpu(sccb->h.length) < 16) {
rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
goto out_err;
}
switch (((IoaCfgSccb *)sccb)->atype) {
case SCLP_RECONFIG_PCI_ATYPE:
if (s390_has_feat(S390_FEAT_ZPCI)) {
if (configure) {
s390_pci_sclp_configure(sccb);
} else {
s390_pci_sclp_deconfigure(sccb);
}
return;
}
/* fallthrough */
default:
rc = SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED;
}
out_err:
sccb->h.response_code = cpu_to_be16(rc);
}
static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code) static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
{ {
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp); SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
@ -384,11 +413,11 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
case SCLP_UNASSIGN_STORAGE: case SCLP_UNASSIGN_STORAGE:
sclp_c->unassign_storage(sclp, sccb); sclp_c->unassign_storage(sclp, sccb);
break; break;
case SCLP_CMDW_CONFIGURE_PCI: case SCLP_CMDW_CONFIGURE_IOA:
s390_pci_sclp_configure(sccb); sclp_configure_io_adapter(sclp, sccb, true);
break; break;
case SCLP_CMDW_DECONFIGURE_PCI: case SCLP_CMDW_DECONFIGURE_IOA:
s390_pci_sclp_deconfigure(sccb); sclp_configure_io_adapter(sclp, sccb, false);
break; break;
default: default:
efc->command_handler(ef, sccb, code); efc->command_handler(ef, sccb, code);

View File

@ -44,10 +44,10 @@
#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001 #define SCLP_CMDW_DECONFIGURE_CPU 0x00100001
/* SCLP PCI codes */ /* SCLP PCI codes */
#define SCLP_HAS_PCI_RECONFIG 0x0000000040000000ULL #define SCLP_HAS_IOA_RECONFIG 0x0000000040000000ULL
#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001 #define SCLP_CMDW_CONFIGURE_IOA 0x001a0001
#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001 #define SCLP_CMDW_DECONFIGURE_IOA 0x001b0001
#define SCLP_RECONFIG_PCI_ATPYE 2 #define SCLP_RECONFIG_PCI_ATYPE 2
/* SCLP response codes */ /* SCLP response codes */
#define SCLP_RC_NORMAL_READ_COMPLETION 0x0010 #define SCLP_RC_NORMAL_READ_COMPLETION 0x0010
@ -168,6 +168,14 @@ typedef struct AssignStorage {
uint16_t rn; uint16_t rn;
} QEMU_PACKED AssignStorage; } QEMU_PACKED AssignStorage;
typedef struct IoaCfgSccb {
SCCBHeader header;
uint8_t atype;
uint8_t reserved1;
uint16_t reserved2;
uint32_t aid;
} QEMU_PACKED IoaCfgSccb;
typedef struct SCCB { typedef struct SCCB {
SCCBHeader h; SCCBHeader h;
char data[SCCB_DATA_LEN]; char data[SCCB_DATA_LEN];