4 * Copyright 2014 IBM Corp.
5 * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com>
6 * Hong Bo Li <lihbbj@cn.ibm.com>
7 * Yi Min Zhao <zyimin@cn.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or (at
10 * your option) any later version. See the COPYING file in the top-level
14 #include "qemu/osdep.h"
15 #include "qemu-common.h"
17 #include "s390-pci-bus.h"
18 #include "s390-pci-inst.h"
19 #include <hw/pci/pci_bus.h>
20 #include <hw/pci/msi.h>
21 #include <qemu/error-report.h>
23 /* #define DEBUG_S390PCI_BUS */
24 #ifdef DEBUG_S390PCI_BUS
25 #define DPRINTF(fmt, ...) \
26 do { fprintf(stderr, "S390pci-bus: " fmt, ## __VA_ARGS__); } while (0)
28 #define DPRINTF(fmt, ...) \
32 int chsc_sei_nt2_get_event(void *res
)
34 ChscSeiNt2Res
*nt2_res
= (ChscSeiNt2Res
*)res
;
38 SeiContainer
*sei_cont
;
39 S390pciState
*s
= S390_PCI_HOST_BRIDGE(
40 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE
, NULL
));
46 sei_cont
= QTAILQ_FIRST(&s
->pending_sei
);
48 QTAILQ_REMOVE(&s
->pending_sei
, sei_cont
, link
);
50 nt2_res
->cc
= sei_cont
->cc
;
51 nt2_res
->length
= cpu_to_be16(sizeof(ChscSeiNt2Res
));
52 switch (sei_cont
->cc
) {
53 case 1: /* error event */
54 eccdf
= (PciCcdfErr
*)nt2_res
->ccdf
;
55 eccdf
->fid
= cpu_to_be32(sei_cont
->fid
);
56 eccdf
->fh
= cpu_to_be32(sei_cont
->fh
);
57 eccdf
->e
= cpu_to_be32(sei_cont
->e
);
58 eccdf
->faddr
= cpu_to_be64(sei_cont
->faddr
);
59 eccdf
->pec
= cpu_to_be16(sei_cont
->pec
);
61 case 2: /* availability event */
62 accdf
= (PciCcdfAvail
*)nt2_res
->ccdf
;
63 accdf
->fid
= cpu_to_be32(sei_cont
->fid
);
64 accdf
->fh
= cpu_to_be32(sei_cont
->fh
);
65 accdf
->pec
= cpu_to_be16(sei_cont
->pec
);
77 int chsc_sei_nt2_have_event(void)
79 S390pciState
*s
= S390_PCI_HOST_BRIDGE(
80 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE
, NULL
));
86 return !QTAILQ_EMPTY(&s
->pending_sei
);
89 S390PCIBusDevice
*s390_pci_find_dev_by_fid(uint32_t fid
)
91 S390PCIBusDevice
*pbdev
;
93 S390pciState
*s
= S390_PCI_HOST_BRIDGE(
94 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE
, NULL
));
100 for (i
= 0; i
< PCI_SLOT_MAX
; i
++) {
101 pbdev
= &s
->pbdev
[i
];
102 if ((pbdev
->fh
!= 0) && (pbdev
->fid
== fid
)) {
110 void s390_pci_sclp_configure(SCCB
*sccb
)
112 PciCfgSccb
*psccb
= (PciCfgSccb
*)sccb
;
113 S390PCIBusDevice
*pbdev
= s390_pci_find_dev_by_fid(be32_to_cpu(psccb
->aid
));
116 if (be16_to_cpu(sccb
->h
.length
) < 16) {
117 rc
= SCLP_RC_INSUFFICIENT_SCCB_LENGTH
;
122 if (pbdev
->configured
) {
123 rc
= SCLP_RC_NO_ACTION_REQUIRED
;
125 pbdev
->configured
= true;
126 rc
= SCLP_RC_NORMAL_COMPLETION
;
129 DPRINTF("sclp config no dev found\n");
130 rc
= SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED
;
133 psccb
->header
.response_code
= cpu_to_be16(rc
);
136 void s390_pci_sclp_deconfigure(SCCB
*sccb
)
138 PciCfgSccb
*psccb
= (PciCfgSccb
*)sccb
;
139 S390PCIBusDevice
*pbdev
= s390_pci_find_dev_by_fid(be32_to_cpu(psccb
->aid
));
142 if (be16_to_cpu(sccb
->h
.length
) < 16) {
143 rc
= SCLP_RC_INSUFFICIENT_SCCB_LENGTH
;
148 if (!pbdev
->configured
) {
149 rc
= SCLP_RC_NO_ACTION_REQUIRED
;
151 if (pbdev
->summary_ind
) {
152 pci_dereg_irqs(pbdev
);
154 if (pbdev
->iommu_enabled
) {
155 pci_dereg_ioat(pbdev
);
157 pbdev
->configured
= false;
158 rc
= SCLP_RC_NORMAL_COMPLETION
;
161 DPRINTF("sclp deconfig no dev found\n");
162 rc
= SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED
;
165 psccb
->header
.response_code
= cpu_to_be16(rc
);
168 static uint32_t s390_pci_get_pfid(PCIDevice
*pdev
)
170 return PCI_SLOT(pdev
->devfn
);
173 static uint32_t s390_pci_get_pfh(PCIDevice
*pdev
)
175 return PCI_SLOT(pdev
->devfn
) | FH_VIRT
;
178 S390PCIBusDevice
*s390_pci_find_dev_by_idx(uint32_t idx
)
180 S390PCIBusDevice
*pbdev
;
183 S390pciState
*s
= S390_PCI_HOST_BRIDGE(
184 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE
, NULL
));
190 for (i
= 0; i
< PCI_SLOT_MAX
; i
++) {
191 pbdev
= &s
->pbdev
[i
];
193 if (pbdev
->fh
== 0) {
206 S390PCIBusDevice
*s390_pci_find_dev_by_fh(uint32_t fh
)
208 S390PCIBusDevice
*pbdev
;
210 S390pciState
*s
= S390_PCI_HOST_BRIDGE(
211 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE
, NULL
));
217 for (i
= 0; i
< PCI_SLOT_MAX
; i
++) {
218 pbdev
= &s
->pbdev
[i
];
219 if (pbdev
->fh
== fh
) {
227 static void s390_pci_generate_event(uint8_t cc
, uint16_t pec
, uint32_t fh
,
228 uint32_t fid
, uint64_t faddr
, uint32_t e
)
230 SeiContainer
*sei_cont
;
231 S390pciState
*s
= S390_PCI_HOST_BRIDGE(
232 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE
, NULL
));
238 sei_cont
= g_malloc0(sizeof(SeiContainer
));
243 sei_cont
->faddr
= faddr
;
246 QTAILQ_INSERT_TAIL(&s
->pending_sei
, sei_cont
, link
);
247 css_generate_css_crws(0);
250 static void s390_pci_generate_plug_event(uint16_t pec
, uint32_t fh
,
253 s390_pci_generate_event(2, pec
, fh
, fid
, 0, 0);
256 static void s390_pci_generate_error_event(uint16_t pec
, uint32_t fh
,
257 uint32_t fid
, uint64_t faddr
,
260 s390_pci_generate_event(1, pec
, fh
, fid
, faddr
, e
);
263 static void s390_pci_set_irq(void *opaque
, int irq
, int level
)
268 static int s390_pci_map_irq(PCIDevice
*pci_dev
, int irq_num
)
274 static uint64_t s390_pci_get_table_origin(uint64_t iota
)
276 return iota
& ~ZPCI_IOTA_RTTO_FLAG
;
279 static unsigned int calc_rtx(dma_addr_t ptr
)
281 return ((unsigned long) ptr
>> ZPCI_RT_SHIFT
) & ZPCI_INDEX_MASK
;
284 static unsigned int calc_sx(dma_addr_t ptr
)
286 return ((unsigned long) ptr
>> ZPCI_ST_SHIFT
) & ZPCI_INDEX_MASK
;
289 static unsigned int calc_px(dma_addr_t ptr
)
291 return ((unsigned long) ptr
>> PAGE_SHIFT
) & ZPCI_PT_MASK
;
294 static uint64_t get_rt_sto(uint64_t entry
)
296 return ((entry
& ZPCI_TABLE_TYPE_MASK
) == ZPCI_TABLE_TYPE_RTX
)
297 ? (entry
& ZPCI_RTE_ADDR_MASK
)
301 static uint64_t get_st_pto(uint64_t entry
)
303 return ((entry
& ZPCI_TABLE_TYPE_MASK
) == ZPCI_TABLE_TYPE_SX
)
304 ? (entry
& ZPCI_STE_ADDR_MASK
)
308 static uint64_t s390_guest_io_table_walk(uint64_t guest_iota
,
309 uint64_t guest_dma_address
)
311 uint64_t sto_a
, pto_a
, px_a
;
312 uint64_t sto
, pto
, pte
;
313 uint32_t rtx
, sx
, px
;
315 rtx
= calc_rtx(guest_dma_address
);
316 sx
= calc_sx(guest_dma_address
);
317 px
= calc_px(guest_dma_address
);
319 sto_a
= guest_iota
+ rtx
* sizeof(uint64_t);
320 sto
= address_space_ldq(&address_space_memory
, sto_a
,
321 MEMTXATTRS_UNSPECIFIED
, NULL
);
322 sto
= get_rt_sto(sto
);
328 pto_a
= sto
+ sx
* sizeof(uint64_t);
329 pto
= address_space_ldq(&address_space_memory
, pto_a
,
330 MEMTXATTRS_UNSPECIFIED
, NULL
);
331 pto
= get_st_pto(pto
);
337 px_a
= pto
+ px
* sizeof(uint64_t);
338 pte
= address_space_ldq(&address_space_memory
, px_a
,
339 MEMTXATTRS_UNSPECIFIED
, NULL
);
345 static IOMMUTLBEntry
s390_translate_iommu(MemoryRegion
*iommu
, hwaddr addr
,
350 S390PCIBusDevice
*pbdev
= container_of(iommu
, S390PCIBusDevice
, iommu_mr
);
352 IOMMUTLBEntry ret
= {
353 .target_as
= &address_space_memory
,
355 .translated_addr
= 0,
356 .addr_mask
= ~(hwaddr
)0,
360 if (!pbdev
->configured
|| !pbdev
->pdev
||
361 !(pbdev
->fh
& FH_ENABLED
) || !pbdev
->iommu_enabled
) {
365 DPRINTF("iommu trans addr 0x%" PRIx64
"\n", addr
);
367 s
= S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev
->pdev
)->qbus
.parent
);
368 /* s390 does not have an APIC mapped to main storage so we use
369 * a separate AddressSpace only for msix notifications
371 if (addr
== ZPCI_MSI_ADDR
) {
372 ret
.target_as
= &s
->msix_notify_as
;
374 ret
.translated_addr
= addr
;
375 ret
.addr_mask
= 0xfff;
380 if (!pbdev
->g_iota
) {
381 pbdev
->error_state
= true;
382 pbdev
->lgstg_blocked
= true;
383 s390_pci_generate_error_event(ERR_EVENT_INVALAS
, pbdev
->fh
, pbdev
->fid
,
388 if (addr
< pbdev
->pba
|| addr
> pbdev
->pal
) {
389 pbdev
->error_state
= true;
390 pbdev
->lgstg_blocked
= true;
391 s390_pci_generate_error_event(ERR_EVENT_OORANGE
, pbdev
->fh
, pbdev
->fid
,
396 pte
= s390_guest_io_table_walk(s390_pci_get_table_origin(pbdev
->g_iota
),
400 pbdev
->error_state
= true;
401 pbdev
->lgstg_blocked
= true;
402 s390_pci_generate_error_event(ERR_EVENT_SERR
, pbdev
->fh
, pbdev
->fid
,
403 addr
, ERR_EVENT_Q_BIT
);
407 flags
= pte
& ZPCI_PTE_FLAG_MASK
;
409 ret
.translated_addr
= pte
& ZPCI_PTE_ADDR_MASK
;
410 ret
.addr_mask
= 0xfff;
412 if (flags
& ZPCI_PTE_INVALID
) {
413 ret
.perm
= IOMMU_NONE
;
421 static const MemoryRegionIOMMUOps s390_iommu_ops
= {
422 .translate
= s390_translate_iommu
,
425 static AddressSpace
*s390_pci_dma_iommu(PCIBus
*bus
, void *opaque
, int devfn
)
427 S390pciState
*s
= opaque
;
429 return &s
->pbdev
[PCI_SLOT(devfn
)].as
;
432 static uint8_t set_ind_atomic(uint64_t ind_loc
, uint8_t to_be_set
)
434 uint8_t ind_old
, ind_new
;
438 ind_addr
= cpu_physical_memory_map(ind_loc
, &len
, 1);
440 s390_pci_generate_error_event(ERR_EVENT_AIRERR
, 0, 0, 0, 0);
445 ind_new
= ind_old
| to_be_set
;
446 } while (atomic_cmpxchg(ind_addr
, ind_old
, ind_new
) != ind_old
);
447 cpu_physical_memory_unmap(ind_addr
, len
, 1, len
);
452 static void s390_msi_ctrl_write(void *opaque
, hwaddr addr
, uint64_t data
,
455 S390PCIBusDevice
*pbdev
;
456 uint32_t io_int_word
;
457 uint32_t fid
= data
>> ZPCI_MSI_VEC_BITS
;
458 uint32_t vec
= data
& ZPCI_MSI_VEC_MASK
;
463 DPRINTF("write_msix data 0x%" PRIx64
" fid %d vec 0x%x\n", data
, fid
, vec
);
465 pbdev
= s390_pci_find_dev_by_fid(fid
);
467 e
|= (vec
<< ERR_EVENT_MVN_OFFSET
);
468 s390_pci_generate_error_event(ERR_EVENT_NOMSI
, 0, fid
, addr
, e
);
472 if (!(pbdev
->fh
& FH_ENABLED
)) {
476 ind_bit
= pbdev
->routes
.adapter
.ind_offset
;
477 sum_bit
= pbdev
->routes
.adapter
.summary_offset
;
479 set_ind_atomic(pbdev
->routes
.adapter
.ind_addr
+ (ind_bit
+ vec
) / 8,
480 0x80 >> ((ind_bit
+ vec
) % 8));
481 if (!set_ind_atomic(pbdev
->routes
.adapter
.summary_addr
+ sum_bit
/ 8,
482 0x80 >> (sum_bit
% 8))) {
483 io_int_word
= (pbdev
->isc
<< 27) | IO_INT_WORD_AI
;
484 s390_io_interrupt(0, 0, 0, io_int_word
);
488 static uint64_t s390_msi_ctrl_read(void *opaque
, hwaddr addr
, unsigned size
)
493 static const MemoryRegionOps s390_msi_ctrl_ops
= {
494 .write
= s390_msi_ctrl_write
,
495 .read
= s390_msi_ctrl_read
,
496 .endianness
= DEVICE_LITTLE_ENDIAN
,
499 void s390_pci_iommu_enable(S390PCIBusDevice
*pbdev
)
501 uint64_t size
= pbdev
->pal
- pbdev
->pba
+ 1;
503 memory_region_init_iommu(&pbdev
->iommu_mr
, OBJECT(&pbdev
->mr
),
504 &s390_iommu_ops
, "iommu-s390", size
);
505 memory_region_add_subregion(&pbdev
->mr
, pbdev
->pba
, &pbdev
->iommu_mr
);
506 pbdev
->iommu_enabled
= true;
509 void s390_pci_iommu_disable(S390PCIBusDevice
*pbdev
)
511 memory_region_del_subregion(&pbdev
->mr
, &pbdev
->iommu_mr
);
512 object_unparent(OBJECT(&pbdev
->iommu_mr
));
513 pbdev
->iommu_enabled
= false;
516 static void s390_pcihost_init_as(S390pciState
*s
)
519 S390PCIBusDevice
*pbdev
;
521 for (i
= 0; i
< PCI_SLOT_MAX
; i
++) {
522 pbdev
= &s
->pbdev
[i
];
523 memory_region_init(&pbdev
->mr
, OBJECT(s
),
524 "iommu-root-s390", UINT64_MAX
);
525 address_space_init(&pbdev
->as
, &pbdev
->mr
, "iommu-pci");
528 memory_region_init_io(&s
->msix_notify_mr
, OBJECT(s
),
529 &s390_msi_ctrl_ops
, s
, "msix-s390", UINT64_MAX
);
530 address_space_init(&s
->msix_notify_as
, &s
->msix_notify_mr
, "msix-pci");
533 static int s390_pcihost_init(SysBusDevice
*dev
)
537 PCIHostState
*phb
= PCI_HOST_BRIDGE(dev
);
538 S390pciState
*s
= S390_PCI_HOST_BRIDGE(dev
);
540 DPRINTF("host_init\n");
542 b
= pci_register_bus(DEVICE(dev
), NULL
,
543 s390_pci_set_irq
, s390_pci_map_irq
, NULL
,
544 get_system_memory(), get_system_io(), 0, 64,
546 s390_pcihost_init_as(s
);
547 pci_setup_iommu(b
, s390_pci_dma_iommu
, s
);
550 qbus_set_hotplug_handler(bus
, DEVICE(dev
), NULL
);
552 QTAILQ_INIT(&s
->pending_sei
);
556 static int s390_pcihost_setup_msix(S390PCIBusDevice
*pbdev
)
562 pos
= pci_find_capability(pbdev
->pdev
, PCI_CAP_ID_MSIX
);
564 pbdev
->msix
.available
= false;
568 ctrl
= pci_host_config_read_common(pbdev
->pdev
, pos
+ PCI_MSIX_FLAGS
,
569 pci_config_size(pbdev
->pdev
), sizeof(ctrl
));
570 table
= pci_host_config_read_common(pbdev
->pdev
, pos
+ PCI_MSIX_TABLE
,
571 pci_config_size(pbdev
->pdev
), sizeof(table
));
572 pba
= pci_host_config_read_common(pbdev
->pdev
, pos
+ PCI_MSIX_PBA
,
573 pci_config_size(pbdev
->pdev
), sizeof(pba
));
575 pbdev
->msix
.table_bar
= table
& PCI_MSIX_FLAGS_BIRMASK
;
576 pbdev
->msix
.table_offset
= table
& ~PCI_MSIX_FLAGS_BIRMASK
;
577 pbdev
->msix
.pba_bar
= pba
& PCI_MSIX_FLAGS_BIRMASK
;
578 pbdev
->msix
.pba_offset
= pba
& ~PCI_MSIX_FLAGS_BIRMASK
;
579 pbdev
->msix
.entries
= (ctrl
& PCI_MSIX_FLAGS_QSIZE
) + 1;
580 pbdev
->msix
.available
= true;
584 static void s390_pcihost_hot_plug(HotplugHandler
*hotplug_dev
,
585 DeviceState
*dev
, Error
**errp
)
587 PCIDevice
*pci_dev
= PCI_DEVICE(dev
);
588 S390PCIBusDevice
*pbdev
;
589 S390pciState
*s
= S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev
)
592 pbdev
= &s
->pbdev
[PCI_SLOT(pci_dev
->devfn
)];
594 pbdev
->fid
= s390_pci_get_pfid(pci_dev
);
595 pbdev
->pdev
= pci_dev
;
596 pbdev
->configured
= true;
597 pbdev
->fh
= s390_pci_get_pfh(pci_dev
);
599 s390_pcihost_setup_msix(pbdev
);
601 if (dev
->hotplugged
) {
602 s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY
,
603 pbdev
->fh
, pbdev
->fid
);
604 s390_pci_generate_plug_event(HP_EVENT_TO_CONFIGURED
,
605 pbdev
->fh
, pbdev
->fid
);
609 static void s390_pcihost_hot_unplug(HotplugHandler
*hotplug_dev
,
610 DeviceState
*dev
, Error
**errp
)
612 PCIDevice
*pci_dev
= PCI_DEVICE(dev
);
613 S390pciState
*s
= S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev
)
615 S390PCIBusDevice
*pbdev
= &s
->pbdev
[PCI_SLOT(pci_dev
->devfn
)];
617 if (pbdev
->configured
) {
618 pbdev
->configured
= false;
619 s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES
,
620 pbdev
->fh
, pbdev
->fid
);
623 s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED
,
624 pbdev
->fh
, pbdev
->fid
);
628 object_unparent(OBJECT(pci_dev
));
631 static void s390_pcihost_class_init(ObjectClass
*klass
, void *data
)
633 SysBusDeviceClass
*k
= SYS_BUS_DEVICE_CLASS(klass
);
634 DeviceClass
*dc
= DEVICE_CLASS(klass
);
635 HotplugHandlerClass
*hc
= HOTPLUG_HANDLER_CLASS(klass
);
637 dc
->cannot_instantiate_with_device_add_yet
= true;
638 k
->init
= s390_pcihost_init
;
639 hc
->plug
= s390_pcihost_hot_plug
;
640 hc
->unplug
= s390_pcihost_hot_unplug
;
641 msi_nonbroken
= true;
644 static const TypeInfo s390_pcihost_info
= {
645 .name
= TYPE_S390_PCI_HOST_BRIDGE
,
646 .parent
= TYPE_PCI_HOST_BRIDGE
,
647 .instance_size
= sizeof(S390pciState
),
648 .class_init
= s390_pcihost_class_init
,
649 .interfaces
= (InterfaceInfo
[]) {
650 { TYPE_HOTPLUG_HANDLER
},
655 static void s390_pci_register_types(void)
657 type_register_static(&s390_pcihost_info
);
660 type_init(s390_pci_register_types
)