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

First set of s390x patches for 2.9:
- rework of the zpci code, giving us proper multibus support
- introduction of the 2.9 machine
- fixes and improvements

# gpg: Signature made Fri 20 Jan 2017 09:11:58 GMT
# gpg:                using RSA key 0xDECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20170120-v2:
  virtio-ccw: fix ring sizing
  s390x/pci: merge msix init functions
  s390x/pci: handle PCIBridge bus number
  s390x/pci: use hashtable to look up zpci via fh
  s390x/pci: PCI multibus bridge handling
  s390x/pci: optimize calling s390_get_phb()
  s390x/pci: change the device array to a list
  s390x/pci: dynamically allocate iommu
  s390x/pci: make S390PCIIOMMU inherit Object
  s390x/kvm: use kvm_gsi_routing_enabled in flic
  s390x: add compat machine for 2.9
  s390x: remove double compat statement

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2017-01-20 15:53:58 +00:00
10 changed files with 334 additions and 182 deletions
+2 -2
View File
@@ -201,7 +201,7 @@ static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
.addr = (uint64_t)&adapter,
};
if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
if (!kvm_gsi_routing_enabled()) {
/* nothing to do */
return 0;
}
@@ -226,7 +226,7 @@ static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
KVMS390FLICState *flic = KVM_S390_FLIC(fs);
int r;
if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
if (!kvm_gsi_routing_enabled()) {
/* nothing to do */
return 0;
}
+236 -125
View File
File diff suppressed because it is too large Load Diff
+32 -14
View File
@@ -23,10 +23,11 @@
#define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost"
#define TYPE_S390_PCI_BUS "s390-pcibus"
#define TYPE_S390_PCI_DEVICE "zpci"
#define TYPE_S390_PCI_IOMMU "s390-pci-iommu"
#define FH_MASK_ENABLE 0x80000000
#define FH_MASK_INSTANCE 0x7f000000
#define FH_MASK_SHM 0x00ff0000
#define FH_MASK_INDEX 0x0000001f
#define FH_MASK_INDEX 0x0000ffff
#define FH_SHM_VFIO 0x00010000
#define FH_SHM_EMUL 0x00020000
#define S390_PCIPT_ADAPTER 2
@@ -42,6 +43,8 @@
OBJECT_CHECK(S390PCIBus, (obj), TYPE_S390_PCI_BUS)
#define S390_PCI_DEVICE(obj) \
OBJECT_CHECK(S390PCIBusDevice, (obj), TYPE_S390_PCI_DEVICE)
#define S390_PCI_IOMMU(obj) \
OBJECT_CHECK(S390PCIIOMMU, (obj), TYPE_S390_PCI_IOMMU)
#define HP_EVENT_TO_CONFIGURED 0x0301
#define HP_EVENT_RESERVED_TO_STANDBY 0x0302
@@ -258,24 +261,34 @@ typedef struct S390MsixInfo {
uint32_t pba_offset;
} S390MsixInfo;
typedef struct S390PCIBusDevice S390PCIBusDevice;
typedef struct S390PCIIOMMU {
Object parent_obj;
S390PCIBusDevice *pbdev;
AddressSpace as;
MemoryRegion mr;
MemoryRegion iommu_mr;
bool enabled;
uint64_t g_iota;
uint64_t pba;
uint64_t pal;
} S390PCIIOMMU;
typedef struct S390PCIIOMMUTable {
uint64_t key;
S390PCIIOMMU *iommu[PCI_SLOT_MAX];
} S390PCIIOMMUTable;
typedef struct S390PCIBusDevice {
DeviceState qdev;
PCIDevice *pdev;
ZpciState state;
bool iommu_enabled;
char *target;
uint16_t uid;
uint32_t idx;
uint32_t fh;
uint32_t fid;
bool fid_defined;
uint64_t g_iota;
uint64_t pba;
uint64_t pal;
uint64_t fmb_addr;
uint8_t isc;
uint16_t noi;
@@ -283,11 +296,11 @@ typedef struct S390PCIBusDevice {
S390MsixInfo msix;
AdapterRoutes routes;
S390PCIIOMMU *iommu;
MemoryRegion iommu_mr;
MemoryRegion msix_notify_mr;
IndAddr *summary_ind;
IndAddr *indicator;
QEMUTimer *release_timer;
QTAILQ_ENTRY(S390PCIBusDevice) link;
} S390PCIBusDevice;
typedef struct S390PCIBus {
@@ -296,23 +309,28 @@ typedef struct S390PCIBus {
typedef struct S390pciState {
PCIHostState parent_obj;
uint32_t next_idx;
int bus_no;
S390PCIBus *bus;
S390PCIBusDevice *pbdev[PCI_SLOT_MAX];
S390PCIIOMMU *iommu[PCI_SLOT_MAX];
GHashTable *iommu_table;
GHashTable *zpci_table;
QTAILQ_HEAD(, SeiContainer) pending_sei;
QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs;
} S390pciState;
S390pciState *s390_get_phb(void);
int chsc_sei_nt2_get_event(void *res);
int chsc_sei_nt2_have_event(void);
void s390_pci_sclp_configure(SCCB *sccb);
void s390_pci_sclp_deconfigure(SCCB *sccb);
void s390_pci_iommu_enable(S390PCIBusDevice *pbdev);
void s390_pci_iommu_disable(S390PCIBusDevice *pbdev);
void s390_pci_iommu_enable(S390PCIIOMMU *iommu);
void s390_pci_iommu_disable(S390PCIIOMMU *iommu);
void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
uint64_t faddr, uint32_t e);
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx);
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh);
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid);
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev);
S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx);
S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh);
S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid);
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
S390PCIBusDevice *pbdev);
#endif
+39 -35
View File
@@ -38,6 +38,7 @@ static void s390_set_status_code(CPUS390XState *env,
static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
{
S390PCIBusDevice *pbdev = NULL;
S390pciState *s = s390_get_phb();
uint32_t res_code, initial_l2, g_l2;
int rc, i;
uint64_t resume_token;
@@ -65,14 +66,14 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
resume_token = ldq_p(&rrb->request.resume_token);
if (resume_token) {
pbdev = s390_pci_find_dev_by_idx(resume_token);
pbdev = s390_pci_find_dev_by_idx(s, resume_token);
if (!pbdev) {
res_code = CLP_RC_LISTPCI_BADRT;
rc = -EINVAL;
goto out;
}
} else {
pbdev = s390_pci_find_next_avail_dev(NULL);
pbdev = s390_pci_find_next_avail_dev(s, NULL);
}
if (lduw_p(&rrb->response.hdr.len) < 48) {
@@ -118,7 +119,7 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
lduw_p(&rrb->response.fh_list[i].device_id),
ldl_p(&rrb->response.fh_list[i].fid),
ldl_p(&rrb->response.fh_list[i].fh));
pbdev = s390_pci_find_next_avail_dev(pbdev);
pbdev = s390_pci_find_next_avail_dev(s, pbdev);
i++;
}
@@ -148,6 +149,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
uint8_t buffer[4096 * 2];
uint8_t cc = 0;
CPUS390XState *env = &cpu->env;
S390pciState *s = s390_get_phb();
int i;
cpu_synchronize_state(CPU(cpu));
@@ -202,7 +204,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
ClpReqSetPci *reqsetpci = (ClpReqSetPci *)reqh;
ClpRspSetPci *ressetpci = (ClpRspSetPci *)resh;
pbdev = s390_pci_find_dev_by_fh(ldl_p(&reqsetpci->fh));
pbdev = s390_pci_find_dev_by_fh(s, ldl_p(&reqsetpci->fh));
if (!pbdev) {
stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FH);
goto out;
@@ -253,7 +255,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
ClpReqQueryPci *reqquery = (ClpReqQueryPci *)reqh;
ClpRspQueryPci *resquery = (ClpRspQueryPci *)resh;
pbdev = s390_pci_find_dev_by_fh(ldl_p(&reqquery->fh));
pbdev = s390_pci_find_dev_by_fh(s, ldl_p(&reqquery->fh));
if (!pbdev) {
DPRINTF("query pci no pci dev\n");
stw_p(&resquery->hdr.rsp, CLP_RC_SETPCIFN_FH);
@@ -338,7 +340,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
len = env->regs[r2] & 0xf;
offset = env->regs[r2 + 1];
pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("pcilg no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
@@ -471,7 +473,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
len = env->regs[r2] & 0xf;
offset = env->regs[r2 + 1];
pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("pcistg no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
@@ -555,6 +557,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
CPUS390XState *env = &cpu->env;
uint32_t fh;
S390PCIBusDevice *pbdev;
S390PCIIOMMU *iommu;
hwaddr start, end;
IOMMUTLBEntry entry;
MemoryRegion *mr;
@@ -575,7 +578,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
start = env->regs[r2];
end = start + env->regs[r2 + 1];
pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("rpcit no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
@@ -597,7 +600,8 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
break;
}
if (!pbdev->g_iota) {
iommu = pbdev->iommu;
if (!iommu->g_iota) {
pbdev->state = ZPCI_FS_ERROR;
setcc(cpu, ZPCI_PCI_LS_ERR);
s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
@@ -606,7 +610,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
goto out;
}
if (end < pbdev->pba || start > pbdev->pal) {
if (end < iommu->pba || start > iommu->pal) {
pbdev->state = ZPCI_FS_ERROR;
setcc(cpu, ZPCI_PCI_LS_ERR);
s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
@@ -615,7 +619,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
goto out;
}
mr = &pbdev->iommu_mr;
mr = &iommu->iommu_mr;
while (start < end) {
entry = mr->iommu_ops->translate(mr, start, 0);
@@ -677,7 +681,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
return 0;
}
pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("pcistb no pci dev fh 0x%x\n", fh);
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
@@ -783,7 +787,7 @@ int pci_dereg_irqs(S390PCIBusDevice *pbdev)
return 0;
}
static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib)
{
uint64_t pba = ldq_p(&fib.pba);
uint64_t pal = ldq_p(&fib.pal);
@@ -803,21 +807,21 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
return -EINVAL;
}
pbdev->pba = pba;
pbdev->pal = pal;
pbdev->g_iota = g_iota;
iommu->pba = pba;
iommu->pal = pal;
iommu->g_iota = g_iota;
s390_pci_iommu_enable(pbdev);
s390_pci_iommu_enable(iommu);
return 0;
}
void pci_dereg_ioat(S390PCIBusDevice *pbdev)
void pci_dereg_ioat(S390PCIIOMMU *iommu)
{
s390_pci_iommu_disable(pbdev);
pbdev->pba = 0;
pbdev->pal = 0;
pbdev->g_iota = 0;
s390_pci_iommu_disable(iommu);
iommu->pba = 0;
iommu->pal = 0;
iommu->g_iota = 0;
}
int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
@@ -843,7 +847,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
return 0;
}
pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("mpcifc no pci dev fh 0x%x\n", fh);
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
@@ -892,10 +896,10 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
if (dmaas != 0) {
cc = ZPCI_PCI_LS_ERR;
s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
} else if (pbdev->iommu_enabled) {
} else if (pbdev->iommu->enabled) {
cc = ZPCI_PCI_LS_ERR;
s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
} else if (reg_ioat(env, pbdev, fib)) {
} else if (reg_ioat(env, pbdev->iommu, fib)) {
cc = ZPCI_PCI_LS_ERR;
s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
}
@@ -904,23 +908,23 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
if (dmaas != 0) {
cc = ZPCI_PCI_LS_ERR;
s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
} else if (!pbdev->iommu_enabled) {
} else if (!pbdev->iommu->enabled) {
cc = ZPCI_PCI_LS_ERR;
s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
} else {
pci_dereg_ioat(pbdev);
pci_dereg_ioat(pbdev->iommu);
}
break;
case ZPCI_MOD_FC_REREG_IOAT:
if (dmaas != 0) {
cc = ZPCI_PCI_LS_ERR;
s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL);
} else if (!pbdev->iommu_enabled) {
} else if (!pbdev->iommu->enabled) {
cc = ZPCI_PCI_LS_ERR;
s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE);
} else {
pci_dereg_ioat(pbdev);
if (reg_ioat(env, pbdev, fib)) {
pci_dereg_ioat(pbdev->iommu);
if (reg_ioat(env, pbdev->iommu, fib)) {
cc = ZPCI_PCI_LS_ERR;
s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES);
}
@@ -988,7 +992,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
return 0;
}
pbdev = s390_pci_find_dev_by_idx(fh & FH_MASK_INDEX);
pbdev = s390_pci_find_dev_by_idx(s390_get_phb(), fh & FH_MASK_INDEX);
if (!pbdev) {
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
return 0;
@@ -1015,7 +1019,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
fib.fc |= 0x40;
case ZPCI_FS_ENABLED:
fib.fc |= 0x80;
if (pbdev->iommu_enabled) {
if (pbdev->iommu->enabled) {
fib.fc |= 0x10;
}
if (!(fh & FH_MASK_ENABLE)) {
@@ -1028,9 +1032,9 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
return 0;
}
stq_p(&fib.pba, pbdev->pba);
stq_p(&fib.pal, pbdev->pal);
stq_p(&fib.iota, pbdev->g_iota);
stq_p(&fib.pba, pbdev->iommu->pba);
stq_p(&fib.pal, pbdev->iommu->pal);
stq_p(&fib.iota, pbdev->iommu->g_iota);
stq_p(&fib.aibv, pbdev->routes.adapter.ind_addr);
stq_p(&fib.aisb, pbdev->routes.adapter.summary_addr);
stq_p(&fib.fmb_addr, pbdev->fmb_addr);
+1 -1
View File
@@ -292,7 +292,7 @@ typedef struct ZpciFib {
} QEMU_PACKED ZpciFib;
int pci_dereg_irqs(S390PCIBusDevice *pbdev);
void pci_dereg_ioat(S390PCIBusDevice *pbdev);
void pci_dereg_ioat(S390PCIIOMMU *iommu);
int clp_service_call(S390CPU *cpu, uint8_t r2);
int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2);
+16 -3
View File
@@ -335,11 +335,13 @@ static const TypeInfo ccw_machine_info = {
} \
type_init(ccw_machine_register_##suffix)
#define CCW_COMPAT_2_8 \
HW_COMPAT_2_8
#define CCW_COMPAT_2_7 \
HW_COMPAT_2_7
#define CCW_COMPAT_2_6 \
CCW_COMPAT_2_7 \
HW_COMPAT_2_6 \
{\
.driver = TYPE_S390_IPL,\
@@ -352,7 +354,6 @@ static const TypeInfo ccw_machine_info = {
},
#define CCW_COMPAT_2_5 \
CCW_COMPAT_2_6 \
HW_COMPAT_2_5
#define CCW_COMPAT_2_4 \
@@ -395,14 +396,26 @@ static const TypeInfo ccw_machine_info = {
.value = "0",\
},
static void ccw_machine_2_9_instance_options(MachineState *machine)
{
}
static void ccw_machine_2_9_class_options(MachineClass *mc)
{
}
DEFINE_CCW_MACHINE(2_9, "2.9", true);
static void ccw_machine_2_8_instance_options(MachineState *machine)
{
ccw_machine_2_9_instance_options(machine);
}
static void ccw_machine_2_8_class_options(MachineClass *mc)
{
ccw_machine_2_9_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_8);
}
DEFINE_CCW_MACHINE(2_8, "2.8", true);
DEFINE_CCW_MACHINE(2_8, "2.8", false);
static void ccw_machine_2_7_instance_options(MachineState *machine)
{
+1 -1
View File
@@ -149,7 +149,7 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
} else {
if (info) {
/* virtio-1 allows changing the ring size. */
if (virtio_queue_get_num(vdev, index) < num) {
if (virtio_queue_get_max_num(vdev, index) < num) {
/* Fail if we exceed the maximum number. */
return -EINVAL;
}
+5
View File
@@ -1249,6 +1249,11 @@ int virtio_queue_get_num(VirtIODevice *vdev, int n)
return vdev->vq[n].vring.num;
}
int virtio_queue_get_max_num(VirtIODevice *vdev, int n)
{
return vdev->vq[n].vring.num_default;
}
int virtio_get_num_queues(VirtIODevice *vdev)
{
int i;
+1
View File
@@ -228,6 +228,7 @@ void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr);
hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n);
void virtio_queue_set_num(VirtIODevice *vdev, int n, int num);
int virtio_queue_get_num(VirtIODevice *vdev, int n);
int virtio_queue_get_max_num(VirtIODevice *vdev, int n);
int virtio_get_num_queues(VirtIODevice *vdev);
void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc,
hwaddr avail, hwaddr used);
+1 -1
View File
@@ -2301,7 +2301,7 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
uint32_t idx = data >> ZPCI_MSI_VEC_BITS;
uint32_t vec = data & ZPCI_MSI_VEC_MASK;
pbdev = s390_pci_find_dev_by_idx(idx);
pbdev = s390_pci_find_dev_by_idx(s390_get_phb(), idx);
if (!pbdev) {
DPRINTF("add_msi_route no dev\n");
return -ENODEV;