diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/s390x/css.c | 12 | ||||
-rw-r--r-- | hw/s390x/s390-pci-bus.c | 48 | ||||
-rw-r--r-- | hw/s390x/s390-pci-bus.h | 4 | ||||
-rw-r--r-- | hw/s390x/s390-pci-inst.c | 6 |
4 files changed, 38 insertions, 32 deletions
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; } diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index ac8f06d..b7f8bca 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,19 +404,6 @@ 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; - ret.perm = IOMMU_RW; - return ret; - } - if (addr < pbdev->pba || addr > pbdev->pal) { return ret; } @@ -476,7 +462,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 +472,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 +533,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 +562,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 +590,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 +663,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 +752,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; 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; |