From patchwork Tue Nov 28 20:33:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Hildenbrand X-Patchwork-Id: 842279 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ymb8043Hkz9sNV for ; Wed, 29 Nov 2017 07:37:36 +1100 (AEDT) Received: from localhost ([::1]:39992 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eJmdK-0003Ko-IF for incoming@patchwork.ozlabs.org; Tue, 28 Nov 2017 15:37:34 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46412) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eJmZg-0000vV-6B for qemu-devel@nongnu.org; Tue, 28 Nov 2017 15:33:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eJmZe-0003fu-1v for qemu-devel@nongnu.org; Tue, 28 Nov 2017 15:33:48 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52576) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eJmZd-0003fJ-Oq; Tue, 28 Nov 2017 15:33:45 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BF1E86016B; Tue, 28 Nov 2017 20:33:44 +0000 (UTC) Received: from t460s.redhat.com (ovpn-116-100.ams2.redhat.com [10.36.116.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2C3D060851; Tue, 28 Nov 2017 20:33:43 +0000 (UTC) From: David Hildenbrand To: qemu-s390x@nongnu.org, qemu-devel@nongnu.org Date: Tue, 28 Nov 2017 21:33:15 +0100 Message-Id: <20171128203326.6062-6-david@redhat.com> In-Reply-To: <20171128203326.6062-1-david@redhat.com> References: <20171128203326.6062-1-david@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 28 Nov 2017 20:33:44 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v1 for-2.12 05/15] s390x/pci: pass the retaddr to all PCI instructions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Christian Borntraeger , Cornelia Huck , David Hildenbrand , Alexander Graf , Richard Henderson Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Once we wire up TCG, we will need the retaddr to correctly inject program interrupts. As we want to get rid of the function program_interrupt(), convert PCI code too. For KVM, we can simply pass a 0. Convert program_interrupt() to program_interrupt_ra() directly, making use of the passed address. Signed-off-by: David Hildenbrand Reviewed-by: Richard Henderson --- hw/s390x/s390-pci-inst.c | 83 +++++++++++++++++++++++++----------------------- hw/s390x/s390-pci-inst.h | 16 ++++++---- target/s390x/kvm.c | 14 ++++---- 3 files changed, 59 insertions(+), 54 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 8e088f3dc9..15ba8f55ae 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -142,7 +142,7 @@ out: return rc; } -int clp_service_call(S390CPU *cpu, uint8_t r2) +int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) { ClpReqHdr *reqh; ClpRspHdr *resh; @@ -158,7 +158,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) cpu_synchronize_state(CPU(cpu)); if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, 4); + program_interrupt_ra(env, PGM_PRIVILEGED, 4, ra); return 0; } @@ -168,7 +168,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) reqh = (ClpReqHdr *)buffer; req_len = lduw_p(&reqh->len); if (req_len < 16 || req_len > 8184 || (req_len % 8 != 0)) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } @@ -179,11 +179,11 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) resh = (ClpRspHdr *)(buffer + req_len); res_len = lduw_p(&resh->len); if (res_len < 8 || res_len > 8176 || (res_len % 8 != 0)) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } if ((req_len + res_len) > 8192) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } @@ -314,7 +314,7 @@ out: return 0; } -int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) +int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) { CPUS390XState *env = &cpu->env; S390PCIBusDevice *pbdev; @@ -329,12 +329,12 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) cpu_synchronize_state(CPU(cpu)); if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, 4); + program_interrupt_ra(env, PGM_PRIVILEGED, 4, ra); return 0; } if (r2 & 0x1) { - program_interrupt(env, PGM_SPECIFICATION, 4); + program_interrupt_ra(env, PGM_SPECIFICATION, 4, ra); return 0; } @@ -367,19 +367,19 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) if (pcias < 6) { if ((8 - (offset & 0x7)) < len) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } mr = pbdev->pdev->io_regions[pcias].memory; result = memory_region_dispatch_read(mr, offset, &data, len, MEMTXATTRS_UNSPECIFIED); if (result != MEMTX_OK) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } } else if (pcias == 15) { if ((4 - (offset & 0x3)) < len) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } data = pci_host_config_read_common( @@ -398,7 +398,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) data = bswap64(data); break; default: - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } } else { @@ -425,7 +425,7 @@ static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias) } } -int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) +int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) { CPUS390XState *env = &cpu->env; uint64_t offset, data; @@ -439,12 +439,12 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) cpu_synchronize_state(CPU(cpu)); if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, 4); + program_interrupt_ra(env, PGM_PRIVILEGED, 4, ra); return 0; } if (r2 & 0x1) { - program_interrupt(env, PGM_SPECIFICATION, 4); + program_interrupt_ra(env, PGM_SPECIFICATION, 4, ra); return 0; } @@ -478,7 +478,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) data = env->regs[r1]; if (pcias < 6) { if ((8 - (offset & 0x7)) < len) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } @@ -492,12 +492,12 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) result = memory_region_dispatch_write(mr, offset, data, len, MEMTXATTRS_UNSPECIFIED); if (result != MEMTX_OK) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } } else if (pcias == 15) { if ((4 - (offset & 0x3)) < len) { - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } switch (len) { @@ -513,7 +513,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) data = bswap64(data); break; default: - program_interrupt(env, PGM_OPERAND, 4); + program_interrupt_ra(env, PGM_OPERAND, 4, ra); return 0; } @@ -531,7 +531,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) return 0; } -int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) +int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) { CPUS390XState *env = &cpu->env; uint32_t fh; @@ -545,12 +545,12 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) cpu_synchronize_state(CPU(cpu)); if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, 4); + program_interrupt_ra(env, PGM_PRIVILEGED, 4, ra); goto out; } if (r2 & 0x1) { - program_interrupt(env, PGM_SPECIFICATION, 4); + program_interrupt_ra(env, PGM_SPECIFICATION, 4, ra); goto out; } @@ -624,7 +624,7 @@ out: } int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, - uint8_t ar) + uint8_t ar, uintptr_t ra) { CPUS390XState *env = &cpu->env; S390PCIBusDevice *pbdev; @@ -637,7 +637,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, uint8_t buffer[128]; if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, 6); + program_interrupt_ra(env, PGM_PRIVILEGED, 6, ra); return 0; } @@ -659,7 +659,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, case 128: break; default: - program_interrupt(env, PGM_SPECIFICATION, 6); + program_interrupt_ra(env, PGM_SPECIFICATION, 6, ra); return 0; } @@ -687,7 +687,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, mr = pbdev->pdev->io_regions[pcias].memory; if (!memory_region_access_valid(mr, env->regs[r3], len, true)) { - program_interrupt(env, PGM_OPERAND, 6); + program_interrupt_ra(env, PGM_OPERAND, 6, ra); return 0; } @@ -700,7 +700,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, ldq_p(buffer + i * 8), 8, MEMTXATTRS_UNSPECIFIED); if (result != MEMTX_OK) { - program_interrupt(env, PGM_OPERAND, 6); + program_interrupt_ra(env, PGM_OPERAND, 6, ra); return 0; } } @@ -767,7 +767,8 @@ int pci_dereg_irqs(S390PCIBusDevice *pbdev) return 0; } -static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib) +static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib, + uintptr_t ra) { uint64_t pba = ldq_p(&fib.pba); uint64_t pal = ldq_p(&fib.pal); @@ -776,14 +777,14 @@ static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib) uint8_t t = (g_iota >> 11) & 0x1; if (pba > pal || pba < ZPCI_SDMA_ADDR || pal > ZPCI_EDMA_ADDR) { - program_interrupt(env, PGM_OPERAND, 6); + program_interrupt_ra(env, PGM_OPERAND, 6, ra); return -EINVAL; } /* currently we only support designation type 1 with translation */ if (!(dt == ZPCI_IOTA_RTTO && t)) { error_report("unsupported ioat dt %d t %d", dt, t); - program_interrupt(env, PGM_OPERAND, 6); + program_interrupt_ra(env, PGM_OPERAND, 6, ra); return -EINVAL; } @@ -804,7 +805,8 @@ void pci_dereg_ioat(S390PCIIOMMU *iommu) iommu->g_iota = 0; } -int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) +int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, + uintptr_t ra) { CPUS390XState *env = &cpu->env; uint8_t oc, dmaas; @@ -814,7 +816,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) uint64_t cc = ZPCI_PCI_LS_OK; if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, 6); + program_interrupt_ra(env, PGM_PRIVILEGED, 6, ra); return 0; } @@ -823,7 +825,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) fh = env->regs[r1] >> 32; if (fiba & 0x7) { - program_interrupt(env, PGM_SPECIFICATION, 6); + program_interrupt_ra(env, PGM_SPECIFICATION, 6, ra); return 0; } @@ -850,7 +852,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } if (fib.fmt != 0) { - program_interrupt(env, PGM_OPERAND, 6); + program_interrupt_ra(env, PGM_OPERAND, 6, ra); return 0; } @@ -879,7 +881,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } 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->iommu, fib)) { + } else if (reg_ioat(env, pbdev->iommu, fib, ra)) { cc = ZPCI_PCI_LS_ERR; s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES); } @@ -904,7 +906,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); } else { pci_dereg_ioat(pbdev->iommu); - if (reg_ioat(env, pbdev->iommu, fib)) { + if (reg_ioat(env, pbdev->iommu, fib, ra)) { cc = ZPCI_PCI_LS_ERR; s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES); } @@ -935,7 +937,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) pbdev->fmb_addr = ldq_p(&fib.fmb_addr); break; default: - program_interrupt(&cpu->env, PGM_OPERAND, 6); + program_interrupt_ra(&cpu->env, PGM_OPERAND, 6, ra); cc = ZPCI_PCI_LS_ERR; } @@ -943,7 +945,8 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) return 0; } -int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, + uintptr_t ra) { CPUS390XState *env = &cpu->env; uint8_t dmaas; @@ -954,7 +957,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) uint64_t cc = ZPCI_PCI_LS_OK; if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, 6); + program_interrupt_ra(env, PGM_PRIVILEGED, 6, ra); return 0; } @@ -968,7 +971,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } if (fiba & 0x7) { - program_interrupt(env, PGM_SPECIFICATION, 6); + program_interrupt_ra(env, PGM_SPECIFICATION, 6, ra); return 0; } diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h index 94a959f91c..93ef290101 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/hw/s390x/s390-pci-inst.h @@ -293,13 +293,15 @@ typedef struct ZpciFib { int pci_dereg_irqs(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); -int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); +int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra); +int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); +int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); +int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, - uint8_t ar); -int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar); -int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar); + uint8_t ar, uintptr_t ra); +int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, + uintptr_t ra); +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, + uintptr_t ra); #endif diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 7c7aa0fa5a..061abf9d4b 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -1230,7 +1230,7 @@ static int kvm_clp_service_call(S390CPU *cpu, struct kvm_run *run) uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16; if (s390_has_feat(S390_FEAT_ZPCI)) { - return clp_service_call(cpu, r2); + return clp_service_call(cpu, r2, 0); } else { return -1; } @@ -1242,7 +1242,7 @@ static int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run) uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16; if (s390_has_feat(S390_FEAT_ZPCI)) { - return pcilg_service_call(cpu, r1, r2); + return pcilg_service_call(cpu, r1, r2, 0); } else { return -1; } @@ -1254,7 +1254,7 @@ static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run) uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16; if (s390_has_feat(S390_FEAT_ZPCI)) { - return pcistg_service_call(cpu, r1, r2); + return pcistg_service_call(cpu, r1, r2, 0); } else { return -1; } @@ -1270,7 +1270,7 @@ static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run) cpu_synchronize_state(CPU(cpu)); fiba = get_base_disp_rxy(cpu, run, &ar); - return stpcifc_service_call(cpu, r1, fiba, ar); + return stpcifc_service_call(cpu, r1, fiba, ar, 0); } else { return -1; } @@ -1302,7 +1302,7 @@ static int kvm_rpcit_service_call(S390CPU *cpu, struct kvm_run *run) uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16; if (s390_has_feat(S390_FEAT_ZPCI)) { - return rpcit_service_call(cpu, r1, r2); + return rpcit_service_call(cpu, r1, r2, 0); } else { return -1; } @@ -1319,7 +1319,7 @@ static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run) cpu_synchronize_state(CPU(cpu)); gaddr = get_base_disp_rsy(cpu, run, &ar); - return pcistb_service_call(cpu, r1, r3, gaddr, ar); + return pcistb_service_call(cpu, r1, r3, gaddr, ar, 0); } else { return -1; } @@ -1335,7 +1335,7 @@ static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run) cpu_synchronize_state(CPU(cpu)); fiba = get_base_disp_rxy(cpu, run, &ar); - return mpcifc_service_call(cpu, r1, fiba, ar); + return mpcifc_service_call(cpu, r1, fiba, ar, 0); } else { return -1; }