From patchwork Thu Mar 9 05:08:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: maddy X-Patchwork-Id: 736827 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vdz2r5R3dz9sNj for ; Thu, 9 Mar 2017 16:09:24 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3vdz2r4V2XzDqbB for ; Thu, 9 Mar 2017 16:09:24 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3vdz214vYkzDqXx for ; Thu, 9 Mar 2017 16:08:41 +1100 (AEDT) Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v294wbf4032362 for ; Thu, 9 Mar 2017 00:08:30 -0500 Received: from e28smtp03.in.ibm.com (e28smtp03.in.ibm.com [125.16.236.3]) by mx0a-001b2d01.pphosted.com with ESMTP id 292y9bjmvw-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 09 Mar 2017 00:08:30 -0500 Received: from localhost by e28smtp03.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 9 Mar 2017 10:38:27 +0530 Received: from d28relay02.in.ibm.com (9.184.220.59) by e28smtp03.in.ibm.com (192.168.1.133) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 9 Mar 2017 10:38:25 +0530 Received: from d28av07.in.ibm.com (d28av07.in.ibm.com [9.184.220.146]) by d28relay02.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v2958PLk11730958 for ; Thu, 9 Mar 2017 10:38:25 +0530 Received: from d28av07.in.ibm.com (localhost [127.0.0.1]) by d28av07.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id v2958Nv7021590 for ; Thu, 9 Mar 2017 10:38:25 +0530 Received: from SrihariSrinidhi.in.ibm.com (sriharisrinidhi.in.ibm.com [9.121.0.27]) by d28av07.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v2958Etw021476; Thu, 9 Mar 2017 10:38:23 +0530 From: Madhavan Srinivasan To: stewart@linux.vnet.ibm.com Date: Thu, 9 Mar 2017 10:38:05 +0530 X-Mailer: git-send-email 2.7.4 In-Reply-To: <1489036089-6529-1-git-send-email-maddy@linux.vnet.ibm.com> References: <1489036089-6529-1-git-send-email-maddy@linux.vnet.ibm.com> X-TM-AS-MML: disable x-cbid: 17030905-0008-0000-0000-0000053AA005 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17030905-0009-0000-0000-0000134527B2 Message-Id: <1489036089-6529-7-git-send-email-maddy@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-03-09_04:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=40 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1702020001 definitions=main-1703090039 Subject: [Skiboot] [PATCH v7 06/10] skiboot: Find the IMC DTB X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mikey@neuling.org, skiboot@lists.ozlabs.org MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" From: Hemant Kumar IMC (In Memory Collection) catalog is a repository of information about the Performance Monitoring Units (PMUs) and their events under the IMC infrastructure. The information include : - The PMU names - Event names - Event description - Event offsets - Event scale - Event unit The catalog is provided as a flattened device tree (dtb). Processors with different PVR values may have different PMU or event names. Hence, for each processor, there can be multiple device tree binaries (dtbs) containing the IMC information. Each of the dtb is compressed and forms a sub-partition inside the PNOR partition "IMA_CATALOG". Here is a link to the commit adding this partition to PNOR : https://github.com/open-power/pnor/commit/c940142c6dc64dd176096dc648f433c889919e84 So, each compressed dtb forms a sub-partition inside the IMA_CATALOG partition and can be accessed/loaded through a sub-partition id which is nothing but the PVR id. Based on the current processor's PVR, the appropriate sub-partion will be loaded. IMA_CATALOG partition ----------- Sub-id (E.g) | | |Catalog 1| 0x100 |---------| | | |Catalog 2| 0x200 <------ Current processor's PVR (0x200) |---------| ... In the above example, if the current processor's PVR is 0x200, catalog 2 should be loaded. Note however, that the catalog information is in the form of a dtb and the dtb is compressed too. So, the sub-partition loaded must be decompressed first before we can actually use it (which is done in subsequent patches). It is important to mention here that while a PNOR image built for one processor is specific to only that processor and isn't portable, a single system generation (Processor version) may have multiple revisions and these revisions may have some changes in their IMC PMUs and events, and hence, the need for multiple IMC DTBs. The sub-partition that we obtain from the IMA_CATALOG partition is a compressed device tree binary. We uncompress it using the libxz's functions. After uncompressing it, we link the device tree binary to the system's device tree. The kernel can now access the device tree and get the IMC PMUs and their events' information. Not all the IMC PMUs listed in the device tree may be available. This is indicated by imc availability vector (which is a part of the IMC control block structure). We need to check this vector and make sure to remove the IMC device nodes which are unavailable. Signed-off-by: Hemant Kumar [maddy: updated nest_pmu[] struct, dt_expand_* and fixed disable_unavailable_units()] Signed-off-by: Madhavan Srinivasan --- core/flash.c | 1 + core/init.c | 4 + hw/Makefile.inc | 2 +- hw/imc.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/imc.h | 1 + include/platform.h | 1 + 6 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 hw/imc.c diff --git a/core/flash.c b/core/flash.c index 793401c94615..e5f8452a17c7 100644 --- a/core/flash.c +++ b/core/flash.c @@ -421,6 +421,7 @@ static struct { { RESOURCE_ID_KERNEL, RESOURCE_SUBID_NONE, "BOOTKERNEL" }, { RESOURCE_ID_INITRAMFS,RESOURCE_SUBID_NONE, "ROOTFS" }, { RESOURCE_ID_CAPP, RESOURCE_SUBID_SUPPORTED, "CAPP" }, + { RESOURCE_ID_CATALOG, RESOURCE_SUBID_SUPPORTED, "IMA_CATALOG" }, }; diff --git a/core/init.c b/core/init.c index cfb50424884c..9dfe8e8a8783 100644 --- a/core/init.c +++ b/core/init.c @@ -47,6 +47,7 @@ #include #include #include +#include enum proc_gen proc_gen; @@ -915,6 +916,9 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) /* Init SLW related stuff, including fastsleep */ slw_init(); + /* Init In-Memory Collection related stuff (load the IMC dtb into memory) */ + imc_init(); + op_display(OP_LOG, OP_MOD_INIT, 0x0002); phb3_preload_vpd(); diff --git a/hw/Makefile.inc b/hw/Makefile.inc index d87f85e485b9..fa560e62a822 100644 --- a/hw/Makefile.inc +++ b/hw/Makefile.inc @@ -1,7 +1,7 @@ # -*-Makefile-*- SUBDIRS += hw HW_OBJS = xscom.o chiptod.o gx.o cec.o lpc.o lpc-uart.o psi.o -HW_OBJS += homer.o slw.o occ.o fsi-master.o centaur.o +HW_OBJS += homer.o slw.o occ.o fsi-master.o centaur.o imc.o HW_OBJS += nx.o nx-rng.o nx-crypto.o nx-842.o HW_OBJS += p7ioc.o p7ioc-inits.o p7ioc-phb.o HW_OBJS += phb3.o sfc-ctrl.o fake-rtc.o bt.o p8-i2c.o prd.o diff --git a/hw/imc.c b/hw/imc.c new file mode 100644 index 000000000000..76b9659b752d --- /dev/null +++ b/hw/imc.c @@ -0,0 +1,257 @@ +/* Copyright 2016 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +/* + * Nest IMC PMU names along with their bit values as represented in the + * imc_chip_avl_vector(in struct imc_chip_cb, look at include/imc.h). + * nest_pmus[] is an array containing all the possible nest IMC PMU node names. + */ +char const *nest_pmus[] = { + "powerbus0", + "mcs0", + "mcs1", + "mcs2", + "mcs3", + "mcs4", + "mcs5", + "mcs6", + "mcs7", + "mba0", + "mba1", + "mba2", + "mba3", + "mba4", + "mba5", + "mba6", + "mba7", + "cen0", + "cen1", + "cen2", + "cen3", + "cen4", + "cen5", + "cen6", + "cen7", + "xlink0", + "xlink1", + "xlink2", + "mcd0", + "mcd1", + "phb0", + "phb1", + "phb2", + "resvd", + "nx", + "capp0", + "capp1", + "vas", + "int", + "alink0", + "alink1", + "alink2", + "nvlink0", + "nvlink1", + "nvlink2", + "nvlink3", + "nvlink4", + "nvlink5", + /* reserved bits : 48 - 64 */ +}; + + +static struct imc_chip_cb *get_imc_cb(void) +{ + uint64_t cb_loc; + struct proc_chip *chip = get_chip(this_cpu()->chip_id); + + cb_loc = chip->homer_base + P9_CB_STRUCT_OFFSET; + return (struct imc_chip_cb *)cb_loc; +} + +/* + * Decompresses the blob obtained from the IMA_CATALOG sub-partition + * in "buf" of size "size", assigns the uncompressed device tree + * binary to "fdt" and returns. + * Returns 0 on success and -1 on error. + */ +static int decompress_subpartition(char *buf, size_t size, void **fdt) +{ + struct xz_dec *s; + struct xz_buf b; + void *data; + int ret = 0; + + /* Initialize the xz library first */ + xz_crc32_init(); + s = xz_dec_init(XZ_SINGLE, 0); + if (s == NULL) + { + prerror("IMC: initialization error for xz\n"); + return -1; + } + + /* Allocate memory for the uncompressed data */ + data = malloc(IMC_DTB_SIZE); + if (!data) { + prerror("IMC: memory allocation error\n"); + ret = -1; + goto err; + } + + /* + * Source address : buf + * Source size : size + * Destination address : data + * Destination size : IMC_DTB_SIZE + */ + b.in = buf; + b.in_pos = 0; + b.in_size = size; + b.out = data; + b.out_pos = 0; + b.out_size = IMC_DTB_SIZE; + + /* Start decompressing */ + ret = xz_dec_run(s, &b); + if (ret != XZ_STREAM_END) { + prerror("IMC: failed to decompress subpartition\n"); + free(data); + ret = -1; + } + *fdt = data; + +err: + /* Clean up memory */ + xz_dec_end(s); + return ret; +} + +/* + * Remove the PMU device nodes from the ncoming new subtree, if they are not + * available in the hardware. The availability is described by the + * control block's imc_chip_avl_vector. + * Each bit represents a device unit. If the device is available, then + * the bit is set else its unset. + */ +static int disable_unavailable_units(struct dt_node *dev) +{ + uint64_t avl_vec; + struct imc_chip_cb *cb; + struct dt_node *target; + int i; + + /* Fetch the IMC control block structure */ + cb = get_imc_cb(); + + avl_vec = be64_to_cpu(cb->imc_chip_avl_vector); + for (i = 0; i < MAX_AVL; i++) { + if (!(PPC_BITMASK(i, i) & avl_vec)) { + /* Check if the device node exists */ + target = dt_find_by_name(dev, nest_pmus[i]); + if (!target) + continue; + /* Remove the device node */ + dt_free(target); + } + } + + return 0; +} + +/* + * Fetch the IMA_CATALOG partition and find the appropriate sub-partition + * based on the platform's PVR. + * Decompress the sub-partition and link the imc device tree to the + * existing device tree. + */ +void imc_init(void) +{ + char *buf = NULL; + size_t size = IMC_DTB_SIZE; + uint32_t pvr = mfspr(SPR_PVR); + int ret; + struct dt_node *dev; + void *fdt = NULL; + struct dt_fixup_p parent; + + /* Enable only for power 9 */ + if (proc_gen != proc_gen_p9) + return; + + buf = malloc(IMC_DTB_SIZE); + if (!buf) { + prerror("IMC: Memory allocation Failed\n"); + return; + } + + ret = start_preload_resource(RESOURCE_ID_CATALOG, + pvr, buf, &size); + if (ret != OPAL_SUCCESS) + goto err; + + ret = wait_for_resource_loaded(RESOURCE_ID_CATALOG, + pvr); + if (ret != OPAL_SUCCESS) { + prerror("IMC Catalog load failed\n"); + return; + } + + /* Decompress the subpartition now */ + ret = decompress_subpartition(buf, size, &fdt); + if (ret < 0) + goto err; + + /* Create a device tree entry for imc counters */ + dev = dt_new_root("imc-counters"); + if (!dev) + goto err; + + /* Attach the new fdt to the imc-counters node */ + ret = dt_expand_node(dev, fdt, 0); + if (ret < 0) { + dt_free(dev); + goto err; + } + + ret = dt_fixup_populate_llist(dev, &parent, "events"); + if (ret < 0) { + dt_free(dev); + goto err; + } + + /* Fixup the phandle for the IMC device tree */ + dt_fixup_phandle(dev, &parent); + dt_fixup_list_free(&parent); + + /* Check availability of the Nest PMU units from the availability vector */ + disable_unavailable_units(dev); + + if (!dt_attach_root(dt_root, dev)) { + dt_free(dev); + goto err; + } + + return; +err: + prerror("IMC Devices not added\n"); + free(buf); +} diff --git a/include/imc.h b/include/imc.h index 09effc0c2c3c..d2f5d4edda1d 100644 --- a/include/imc.h +++ b/include/imc.h @@ -122,4 +122,5 @@ struct imc_chip_cb #define MAX_AVL 48 /* Reserved bits : 48-64 */ +void imc_init(void); #endif /* __IMC_H */ diff --git a/include/platform.h b/include/platform.h index 9133204207d6..246daf285e75 100644 --- a/include/platform.h +++ b/include/platform.h @@ -27,6 +27,7 @@ enum resource_id { RESOURCE_ID_KERNEL, RESOURCE_ID_INITRAMFS, RESOURCE_ID_CAPP, + RESOURCE_ID_CATALOG, }; #define RESOURCE_SUBID_NONE 0 #define RESOURCE_SUBID_SUPPORTED 1