#include "s390-pci-bus.h"
#include "exec/memory-internal.h"
#include "qemu/error-report.h"
+#include "sysemu/hw_accel.h"
-/* #define DEBUG_S390PCI_INST */
-#ifdef DEBUG_S390PCI_INST
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, "s390pci-inst: " fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
+#ifndef DEBUG_S390PCI_INST
+#define DEBUG_S390PCI_INST 0
#endif
+#define DPRINTF(fmt, ...) \
+ do { \
+ if (DEBUG_S390PCI_INST) { \
+ fprintf(stderr, "s390pci-inst: " fmt, ## __VA_ARGS__); \
+ } \
+ } while (0)
+
static void s390_set_status_code(CPUS390XState *env,
uint8_t r, uint64_t status_code)
{
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;
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) {
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++;
}
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));
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;
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);
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);
return 0;
}
-static void update_msix_table_msg_data(S390PCIBusDevice *pbdev, uint64_t offset,
- uint64_t *data, uint8_t len)
-{
- uint32_t val;
- uint8_t *msg_data;
-
- if (offset % PCI_MSIX_ENTRY_SIZE != 8) {
- return;
- }
-
- if (len != 4) {
- DPRINTF("access msix table msg data but len is %d\n", len);
- return;
- }
-
- msg_data = (uint8_t *)data - offset % PCI_MSIX_ENTRY_SIZE +
- PCI_MSIX_ENTRY_VECTOR_CTRL;
- val = pci_get_long(msg_data) |
- ((pbdev->fh & FH_MASK_INDEX) << ZPCI_MSI_VEC_BITS);
- pci_set_long(msg_data, val);
- DPRINTF("update msix msg_data to 0x%" PRIx64 "\n", *data);
-}
-
static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias)
{
if (pbdev->msix.available && pbdev->msix.table_bar == pcias &&
offset >= pbdev->msix.table_offset &&
- offset <= pbdev->msix.table_offset +
- (pbdev->msix.entries - 1) * PCI_MSIX_ENTRY_SIZE) {
+ offset < (pbdev->msix.table_offset +
+ pbdev->msix.entries * PCI_MSIX_ENTRY_SIZE)) {
return 1;
} else {
return 0;
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);
if (trap_msix(pbdev, offset, pcias)) {
offset = offset - pbdev->msix.table_offset;
mr = &pbdev->pdev->msix_table_mmio;
- update_msix_table_msg_data(pbdev, offset, &data, len);
} else {
mr = pbdev->pdev->io_regions[pcias].memory;
}
CPUS390XState *env = &cpu->env;
uint32_t fh;
S390PCIBusDevice *pbdev;
+ S390PCIIOMMU *iommu;
hwaddr start, end;
IOMMUTLBEntry entry;
- MemoryRegion *mr;
+ IOMMUMemoryRegion *iommu_mr;
+ IOMMUMemoryRegionClass *imrc;
cpu_synchronize_state(CPU(cpu));
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);
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);
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);
goto out;
}
- mr = &pbdev->iommu_mr;
+ iommu_mr = &iommu->iommu_mr;
+ imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
+
while (start < end) {
- entry = mr->iommu_ops->translate(mr, start, 0);
+ entry = imrc->translate(iommu_mr, start, IOMMU_NONE);
if (!entry.translated_addr) {
pbdev->state = ZPCI_FS_ERROR;
goto out;
}
- memory_region_notify_iommu(mr, entry);
+ memory_region_notify_iommu(iommu_mr, entry);
start += entry.addr_mask + 1;
}
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);
static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
{
int ret, len;
+ uint8_t isc = FIB_DATA_ISC(ldl_p(&fib.data));
- ret = css_register_io_adapter(S390_PCIPT_ADAPTER,
- FIB_DATA_ISC(ldl_p(&fib.data)), true, false,
- &pbdev->routes.adapter.adapter_id);
- assert(ret == 0);
-
+ pbdev->routes.adapter.adapter_id = css_get_adapter_id(
+ CSS_IO_ADAPTER_PCI, isc);
pbdev->summary_ind = get_indicator(ldq_p(&fib.aisb), sizeof(uint64_t));
len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long);
pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len);
pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data));
pbdev->routes.adapter.ind_addr = ldq_p(&fib.aibv);
pbdev->routes.adapter.ind_offset = FIB_DATA_AIBVO(ldl_p(&fib.data));
- pbdev->isc = FIB_DATA_ISC(ldl_p(&fib.data));
+ pbdev->isc = isc;
pbdev->noi = FIB_DATA_NOI(ldl_p(&fib.data));
pbdev->sum = FIB_DATA_SUM(ldl_p(&fib.data));
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);
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)
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);
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);
}
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);
}
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;
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)) {
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);