From patchwork Fri Dec 14 14:11:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre Morel X-Patchwork-Id: 10731229 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D1A41112C for ; Fri, 14 Dec 2018 14:12:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A70E52D540 for ; Fri, 14 Dec 2018 14:12:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9B1602D569; Fri, 14 Dec 2018 14:12:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CFB232D54C for ; Fri, 14 Dec 2018 14:12:47 +0000 (UTC) Received: from localhost ([::1]:33750 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gXoCs-0000Ks-Vt for patchwork-qemu-devel@patchwork.kernel.org; Fri, 14 Dec 2018 09:12:47 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55112) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gXoBh-0007s0-4N for qemu-devel@nongnu.org; Fri, 14 Dec 2018 09:11:34 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gXoBc-0004hg-4I for qemu-devel@nongnu.org; Fri, 14 Dec 2018 09:11:33 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:51400) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gXoBb-0004gn-Pt for qemu-devel@nongnu.org; Fri, 14 Dec 2018 09:11:27 -0500 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id wBEE95RC145680 for ; Fri, 14 Dec 2018 09:11:27 -0500 Received: from e06smtp04.uk.ibm.com (e06smtp04.uk.ibm.com [195.75.94.100]) by mx0a-001b2d01.pphosted.com with ESMTP id 2pcca6wcp5-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 14 Dec 2018 09:11:26 -0500 Received: from localhost by e06smtp04.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 14 Dec 2018 14:11:24 -0000 Received: from b06cxnps4076.portsmouth.uk.ibm.com (9.149.109.198) by e06smtp04.uk.ibm.com (192.168.101.134) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Fri, 14 Dec 2018 14:11:21 -0000 Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id wBEEBJul5112064 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 14 Dec 2018 14:11:19 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 94BE8A4051; Fri, 14 Dec 2018 14:11:19 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 24759A4040; Fri, 14 Dec 2018 14:11:19 +0000 (GMT) Received: from morel-ThinkPad-W530.boeblingen.de.ibm.com (unknown [9.145.23.224]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTP; Fri, 14 Dec 2018 14:11:19 +0000 (GMT) From: Pierre Morel To: walling@linux.ibm.com Date: Fri, 14 Dec 2018 15:11:18 +0100 X-Mailer: git-send-email 2.7.4 X-TM-AS-GCONF: 00 x-cbid: 18121414-0016-0000-0000-000002367B8D X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18121414-0017-0000-0000-0000328EBB6C Message-Id: <1544796678-12736-1-git-send-email-pmorel@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-12-14_07:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1812140126 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PATCH v3] s390x/pci: add common function measurement block 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: thuth@redhat.com, david@redhat.com, cohuck@redhat.com, qemu-devel@nongnu.org, pasic@linux.ibm.com, borntraeger@de.ibm.com, qemu-s390x@nongnu.org, rth@twiddle.net Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Yi Min Zhao Common function measurement block is used to report zPCI internal counters of successful pcilg/stg/stb and rpcit instructions to a memory location provided by the program. This patch introduces a new ZpciFmb structure and schedules a timer callback to copy the zPCI measures to the FMB in the guest memory at an interval time set to 4s by default. An error while attemping to update the FMB, would generated an error event to the guest. The pcilg/stg/stb and rpcit interception handlers issue, increase the related counter on success. The guest shall pass a null FMBA (FMB address) in the FIB (Function Information Block) when it issues a Modify PCI Function Control instrcuction to switch off FMB and stop the corresponding timer. Signed-off-by: Yi Min Zhao Signed-off-by: Pierre Morel --- hw/s390x/s390-pci-bus.c | 4 +- hw/s390x/s390-pci-bus.h | 29 ++++++++++ hw/s390x/s390-pci-inst.c | 138 +++++++++++++++++++++++++++++++++++++++++++++-- hw/s390x/s390-pci-inst.h | 1 + 4 files changed, 168 insertions(+), 4 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 060ff06..f0d34dd 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -989,6 +989,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, bus = pci_get_bus(pci_dev); devfn = pci_dev->devfn; object_unparent(OBJECT(pci_dev)); + fmb_timer_free(pbdev); s390_pci_msix_free(pbdev); s390_pci_iommu_free(s, bus, devfn); pbdev->pdev = NULL; @@ -1136,6 +1137,7 @@ static void s390_pci_device_realize(DeviceState *dev, Error **errp) } zpci->state = ZPCI_FS_RESERVED; + zpci->fmb.format = ZPCI_FMB_FORMAT; } static void s390_pci_device_reset(DeviceState *dev) @@ -1160,7 +1162,7 @@ static void s390_pci_device_reset(DeviceState *dev) pci_dereg_ioat(pbdev->iommu); } - pbdev->fmb_addr = 0; + fmb_timer_free(pbdev); } static void s390_pci_get_fid(Object *obj, Visitor *v, const char *name, diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 1f7f9b5..458cd3a 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -286,6 +286,33 @@ typedef struct S390PCIIOMMUTable { S390PCIIOMMU *iommu[PCI_SLOT_MAX]; } S390PCIIOMMUTable; +/* Function Measurement Block */ +#define DEFAULT_MUI 4000 +#define UPDATE_U_BIT 0x1ULL +#define FMBK_MASK 0xfULL + +typedef struct ZpciFmbFmt0 { + uint64_t dma_rbytes; + uint64_t dma_wbytes; +} ZpciFmbFmt0; + +#define ZPCI_FMB_CNT_LD 0 +#define ZPCI_FMB_CNT_ST 1 +#define ZPCI_FMB_CNT_STB 2 +#define ZPCI_FMB_CNT_RPCIT 3 +#define ZPCI_FMB_CNT_MAX 4 + +#define ZPCI_FMB_FORMAT 0 + +typedef struct ZpciFmb { + uint32_t format; + uint32_t sample; + uint64_t last_update; + uint64_t counter[ZPCI_FMB_CNT_MAX]; + ZpciFmbFmt0 fmt0; +} ZpciFmb; +QEMU_BUILD_BUG_MSG(offsetof(ZpciFmb, fmt0) != 48, "padding in ZpciFmb"); + struct S390PCIBusDevice { DeviceState qdev; PCIDevice *pdev; @@ -297,6 +324,8 @@ struct S390PCIBusDevice { uint32_t fid; bool fid_defined; uint64_t fmb_addr; + ZpciFmb fmb; + QEMUTimer *fmb_timer; uint8_t isc; uint16_t noi; uint16_t maxstbl; diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 7b61367..1ccc496 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -19,6 +19,7 @@ #include "exec/memory-internal.h" #include "qemu/error-report.h" #include "sysemu/hw_accel.h" +#include "hw/s390x/tod.h" #ifndef DEBUG_S390PCI_INST #define DEBUG_S390PCI_INST 0 @@ -293,7 +294,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) resgrp->fr = 1; stq_p(&resgrp->dasm, 0); stq_p(&resgrp->msia, ZPCI_MSI_ADDR); - stw_p(&resgrp->mui, 0); + stw_p(&resgrp->mui, DEFAULT_MUI); stw_p(&resgrp->i, 128); stw_p(&resgrp->maxstbl, 128); resgrp->version = 0; @@ -456,6 +457,8 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) return 0; } + pbdev->fmb.counter[ZPCI_FMB_CNT_LD]++; + env->regs[r1] = data; setcc(cpu, ZPCI_PCI_LS_OK); return 0; @@ -561,6 +564,8 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) return 0; } + pbdev->fmb.counter[ZPCI_FMB_CNT_ST]++; + setcc(cpu, ZPCI_PCI_LS_OK); return 0; } @@ -681,6 +686,7 @@ err: s390_set_status_code(env, r1, ZPCI_PCI_ST_FUNC_IN_ERR); s390_pci_generate_error_event(error, pbdev->fh, pbdev->fid, start, 0); } else { + pbdev->fmb.counter[ZPCI_FMB_CNT_RPCIT]++; setcc(cpu, ZPCI_PCI_LS_OK); } return 0; @@ -783,6 +789,8 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, } } + pbdev->fmb.counter[ZPCI_FMB_CNT_STB]++; + setcc(cpu, ZPCI_PCI_LS_OK); return 0; @@ -889,6 +897,104 @@ void pci_dereg_ioat(S390PCIIOMMU *iommu) iommu->g_iota = 0; } +void fmb_timer_free(S390PCIBusDevice *pbdev) +{ + if (pbdev->fmb_timer) { + timer_del(pbdev->fmb_timer); + timer_free(pbdev->fmb_timer); + pbdev->fmb_timer = NULL; + } + pbdev->fmb_addr = 0; + memset(&pbdev->fmb, 0, sizeof(ZpciFmb)); +} + +static int fmb_do_update64(S390PCIBusDevice *pbdev, int offset, int cnt) +{ + MemTxResult ret = MEMTX_ERROR; + uint64_t dst = pbdev->fmb_addr + offset; + uint64_t *src = (uint64_t *) ((unsigned long)(&pbdev->fmb) + offset); + int i; + + for (i = 0; i < cnt; i++, dst += 8, src++) { + address_space_stq_be(&address_space_memory, dst, *src, + MEMTXATTRS_UNSPECIFIED, &ret); + if (ret != MEMTX_OK) { + return ret; + } + } + return ret; +} + +static int fmb_do_update(S390PCIBusDevice *pbdev, int offset, int val, int len) +{ + MemTxResult ret; + uint64_t dst = pbdev->fmb_addr + offset; + + switch (len) { + case 4: + address_space_stl_be(&address_space_memory, dst, val, + MEMTXATTRS_UNSPECIFIED, + &ret); + break; + case 2: + address_space_stw_be(&address_space_memory, dst, val, + MEMTXATTRS_UNSPECIFIED, + &ret); + break; + case 1: + address_space_stb(&address_space_memory, dst, val, + MEMTXATTRS_UNSPECIFIED, + &ret); + break; + default: + ret = MEMTX_ERROR; + break; + } + if (ret != MEMTX_OK) { + s390_pci_generate_error_event(ERR_EVENT_FMBA, pbdev->fh, pbdev->fid, + pbdev->fmb_addr, 0); + fmb_timer_free(pbdev); + return 1; + } + + return 0; +} + +static void fmb_update(void *opaque) +{ + S390PCIBusDevice *pbdev = opaque; + int64_t t = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + uint8_t offset; + + /* Update U bit */ + pbdev->fmb.last_update |= UPDATE_U_BIT; + offset = offsetof(ZpciFmb, last_update); + if (fmb_do_update64(pbdev, offset, 1)) { + return; + } + + /* Update FMB sample count */ + offset = offsetof(ZpciFmb, sample); + if (fmb_do_update(pbdev, offset, pbdev->fmb.sample++, sizeof(pbdev->fmb.sample))) { + return; + } + /* Update FMB counters */ + offset = offsetof(ZpciFmb, counter); + if (fmb_do_update64(pbdev, offset, ZPCI_FMB_CNT_MAX)) { + return; + } + + /* Clear U bit and update the time */ + pbdev->fmb.last_update = time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); + pbdev->fmb.last_update <<= 1; + offset = offsetof(ZpciFmb, last_update); + if (fmb_do_update64(pbdev, offset, 1)) { + return; + } + + timer_mod(pbdev->fmb_timer, t + DEFAULT_MUI); +} + int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, uintptr_t ra) { @@ -1018,9 +1124,35 @@ 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); } break; - case ZPCI_MOD_FC_SET_MEASURE: - pbdev->fmb_addr = ldq_p(&fib.fmb_addr); + case ZPCI_MOD_FC_SET_MEASURE: { + uint64_t fmb_addr = ldq_p(&fib.fmb_addr); + + if (fmb_addr & FMBK_MASK) { + cc = ZPCI_PCI_LS_ERR; + s390_pci_generate_error_event(ERR_EVENT_FMBPRO, pbdev->fh, + pbdev->fid, fmb_addr, 0); + fmb_timer_free(pbdev); + break; + } + + if (!fmb_addr) { + /* Stop updating FMB. */ + fmb_timer_free(pbdev); + break; + } + + if (!pbdev->fmb_timer) { + pbdev->fmb_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, + fmb_update, pbdev); + } else if (timer_pending(pbdev->fmb_timer)) { + /* Remove pending timer to update FMB address. */ + timer_del(pbdev->fmb_timer); + } + pbdev->fmb_addr = fmb_addr; + timer_mod(pbdev->fmb_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + DEFAULT_MUI); break; + } default: s390_program_interrupt(&cpu->env, PGM_OPERAND, 6, ra); cc = ZPCI_PCI_LS_ERR; diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h index 91c3d61..fa3bf8b 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/hw/s390x/s390-pci-inst.h @@ -303,6 +303,7 @@ 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); +void fmb_timer_free(S390PCIBusDevice *pbdev); #define ZPCI_IO_BAR_MIN 0 #define ZPCI_IO_BAR_MAX 5