From 205e5de4251f4c18e1f17f2e7aaa42ff92c3e05f Mon Sep 17 00:00:00 2001 From: Pierre Morel Date: Wed, 24 Aug 2016 12:46:34 +0200 Subject: s390x/pci: re-arrange variable declarations Pull mr variable declarations at the top of the functions instead of mixing them up with the code. This is in preparation for followup patches. Signed-off-by: Pierre Morel Reviewed-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- hw/s390x/s390-pci-inst.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index f069b11..80a51049 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -315,6 +315,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) S390PCIBusDevice *pbdev; uint64_t offset; uint64_t data; + MemoryRegion *mr; uint8_t len; uint32_t fh; uint8_t pcias; @@ -363,7 +364,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) program_interrupt(env, PGM_OPERAND, 4); return 0; } - MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory; + mr = pbdev->pdev->io_regions[pcias].memory; memory_region_dispatch_read(mr, offset, &data, len, MEMTXATTRS_UNSPECIFIED); } else if (pcias == 15) { @@ -442,6 +443,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) CPUS390XState *env = &cpu->env; uint64_t offset, data; S390PCIBusDevice *pbdev; + MemoryRegion *mr; uint8_t len; uint32_t fh; uint8_t pcias; @@ -491,7 +493,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) program_interrupt(env, PGM_OPERAND, 4); return 0; } - MemoryRegion *mr; + if (trap_msix(pbdev, offset, pcias)) { offset = offset - pbdev->msix.table_offset; mr = &pbdev->pdev->msix_table_mmio; -- cgit v1.1 From 8f95595072c3d91645c21d27cd02dd0b8d920f77 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Tue, 6 Sep 2016 14:00:44 +0800 Subject: s390x/pci: assign msix io region for each pci device For efficiency we now assign one msix io region for each pci device and provide it with the pointer to the zPCI device as opaque parameter. In addition, we remove msix address space and add msix io region as a subregion to the root memory region of pci device. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Christian Borntraeger --- hw/s390x/s390-pci-bus.c | 37 ++++++++++++++++++++++++++----------- hw/s390x/s390-pci-bus.h | 4 ++-- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'hw') diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index ac8f06d..fe5fc4e 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -383,7 +383,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, uint64_t pte; uint32_t flags; S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, iommu_mr); - S390pciState *s; IOMMUTLBEntry ret = { .target_as = &address_space_memory, .iova = 0, @@ -405,12 +404,10 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr); - s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)->qbus.parent); /* s390 does not have an APIC mapped to main storage so we use * a separate AddressSpace only for msix notifications */ if (addr == ZPCI_MSI_ADDR) { - ret.target_as = &s->msix_notify_as; ret.iova = addr; ret.translated_addr = addr; ret.addr_mask = 0xfff; @@ -476,7 +473,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { - S390PCIBusDevice *pbdev; + S390PCIBusDevice *pbdev = opaque; uint32_t io_int_word; uint32_t idx = data >> ZPCI_MSI_VEC_BITS; uint32_t vec = data & ZPCI_MSI_VEC_MASK; @@ -486,7 +483,6 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data, idx, vec); - pbdev = s390_pci_find_dev_by_idx(idx); if (!pbdev) { e |= (vec << ERR_EVENT_MVN_OFFSET); s390_pci_generate_error_event(ERR_EVENT_NOMSI, idx, 0, addr, e); @@ -548,10 +544,6 @@ static void s390_pcihost_init_as(S390pciState *s) s->iommu[i] = iommu; } - - memory_region_init_io(&s->msix_notify_mr, OBJECT(s), - &s390_msi_ctrl_ops, s, "msix-s390", UINT64_MAX); - address_space_init(&s->msix_notify_as, &s->msix_notify_mr, "msix-pci"); } static int s390_pcihost_init(SysBusDevice *dev) @@ -581,7 +573,7 @@ static int s390_pcihost_init(SysBusDevice *dev) return 0; } -static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev) +static int s390_pci_setup_msix(S390PCIBusDevice *pbdev) { uint8_t pos; uint16_t ctrl; @@ -609,6 +601,26 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev) return 0; } +static void s390_pci_msix_init(S390PCIBusDevice *pbdev) +{ + char *name; + + name = g_strdup_printf("msix-s390-%04x", pbdev->uid); + + memory_region_init_io(&pbdev->msix_notify_mr, OBJECT(pbdev), + &s390_msi_ctrl_ops, pbdev, name, PAGE_SIZE); + memory_region_add_subregion(&pbdev->iommu->mr, ZPCI_MSI_ADDR, + &pbdev->msix_notify_mr); + + g_free(name); +} + +static void s390_pci_msix_free(S390PCIBusDevice *pbdev) +{ + memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->msix_notify_mr); + object_unparent(OBJECT(&pbdev->msix_notify_mr)); +} + static S390PCIBusDevice *s390_pci_device_new(const char *target) { DeviceState *dev = NULL; @@ -662,7 +674,9 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, pbdev->pdev = pdev; pbdev->iommu = s->iommu[PCI_SLOT(pdev->devfn)]; pbdev->state = ZPCI_FS_STANDBY; - s390_pcihost_setup_msix(pbdev); + + s390_pci_msix_init(pbdev); + s390_pci_setup_msix(pbdev); if (dev->hotplugged) { s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY, @@ -749,6 +763,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED, pbdev->fh, pbdev->fid); object_unparent(OBJECT(pci_dev)); + s390_pci_msix_free(pbdev); pbdev->pdev = NULL; pbdev->state = ZPCI_FS_RESERVED; out: diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 4f564e0..7f27013 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -82,6 +82,7 @@ #define ZPCI_EDMA_ADDR 0x1ffffffffffffffULL #define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) #define PAGE_DEFAULT_ACC 0 #define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) @@ -283,6 +284,7 @@ typedef struct S390PCIBusDevice { AdapterRoutes routes; S390PCIIOMMU *iommu; MemoryRegion iommu_mr; + MemoryRegion msix_notify_mr; IndAddr *summary_ind; IndAddr *indicator; QEMUTimer *release_timer; @@ -297,8 +299,6 @@ typedef struct S390pciState { S390PCIBus *bus; S390PCIBusDevice *pbdev[PCI_SLOT_MAX]; S390PCIIOMMU *iommu[PCI_SLOT_MAX]; - AddressSpace msix_notify_as; - MemoryRegion msix_notify_mr; QTAILQ_HEAD(, SeiContainer) pending_sei; } S390pciState; -- cgit v1.1 From bfcec59a23f42dcac18a434bd48bd60d6fc0e563 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Tue, 6 Sep 2016 14:01:29 +0800 Subject: s390x/pci: code cleanup Now that each S390 PCI device uses an IO region as MSIX region. The code in s390_translate_iommu() will never be triggered. Let's remove it. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Christian Borntraeger --- hw/s390x/s390-pci-bus.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'hw') diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index fe5fc4e..b7f8bca 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -404,17 +404,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr); - /* s390 does not have an APIC mapped to main storage so we use - * a separate AddressSpace only for msix notifications - */ - if (addr == ZPCI_MSI_ADDR) { - ret.iova = addr; - ret.translated_addr = addr; - ret.addr_mask = 0xfff; - ret.perm = IOMMU_RW; - return ret; - } - if (addr < pbdev->pba || addr > pbdev->pal) { return ret; } -- cgit v1.1 From c679e74d2e29fa08ede9121d59aee4e9675611d7 Mon Sep 17 00:00:00 2001 From: Sascha Silbe Date: Mon, 19 Sep 2016 21:12:03 +0200 Subject: s390x/css: {c,h,t,r,x}sch: require enable AND device number valid According to the PoP, subchannels are only considered operational if they are enabled _and_ the device number is valid. With the current checks being enabled _or_ having a valid device number was sufficient. This caused qemu to allow IO on subchannels that were not enabled. Fix the checks to require both bits to be set. Signed-off-by: Sascha Silbe Reviewed-by: Cornelia Huck Reviewed-by: Halil Pasic Signed-off-by: Christian Borntraeger --- hw/s390x/css.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/s390x/css.c b/hw/s390x/css.c index b0e81ef..0f2580d 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -775,7 +775,7 @@ int css_do_xsch(SubchDev *sch) PMCW *p = &sch->curr_status.pmcw; int ret; - if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) { + if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { ret = -ENODEV; goto out; } @@ -815,7 +815,7 @@ int css_do_csch(SubchDev *sch) PMCW *p = &sch->curr_status.pmcw; int ret; - if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) { + if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { ret = -ENODEV; goto out; } @@ -837,7 +837,7 @@ int css_do_hsch(SubchDev *sch) PMCW *p = &sch->curr_status.pmcw; int ret; - if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) { + if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { ret = -ENODEV; goto out; } @@ -913,7 +913,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb) PMCW *p = &sch->curr_status.pmcw; int ret; - if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) { + if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { ret = -ENODEV; goto out; } @@ -990,7 +990,7 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len) uint16_t stctl; IRB irb; - if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) { + if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { return 3; } @@ -1196,7 +1196,7 @@ int css_do_rsch(SubchDev *sch) PMCW *p = &sch->curr_status.pmcw; int ret; - if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) { + if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { ret = -ENODEV; goto out; } -- cgit v1.1