From patchwork Thu Sep 5 13:29:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Grimm X-Patchwork-Id: 1158436 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46PM8N1zPvz9sP3 for ; Thu, 5 Sep 2019 23:33:24 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 46PM8M4pWKzDr5J for ; Thu, 5 Sep 2019 23:33:23 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=grimm@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com 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 46PM480DfwzDqw9 for ; Thu, 5 Sep 2019 23:29:43 +1000 (AEST) Received: from pps.filterd (m0187473.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x85DSqG9063302; Thu, 5 Sep 2019 09:29:41 -0400 Received: from ppma02wdc.us.ibm.com (aa.5b.37a9.ip4.static.sl-reverse.com [169.55.91.170]) by mx0a-001b2d01.pphosted.com with ESMTP id 2uu37mr644-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 05 Sep 2019 09:29:40 -0400 Received: from pps.filterd (ppma02wdc.us.ibm.com [127.0.0.1]) by ppma02wdc.us.ibm.com (8.16.0.27/8.16.0.27) with SMTP id x85DQTQR003576; Thu, 5 Sep 2019 13:29:31 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma02wdc.us.ibm.com with ESMTP id 2uqgh79jht-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 05 Sep 2019 13:29:31 +0000 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x85DTV6j54460736 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 5 Sep 2019 13:29:31 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EE4F0124053; Thu, 5 Sep 2019 13:29:30 +0000 (GMT) Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A7569124052; Thu, 5 Sep 2019 13:29:30 +0000 (GMT) Received: from alain.ibm.com (unknown [9.85.158.174]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTP; Thu, 5 Sep 2019 13:29:30 +0000 (GMT) From: Ryan Grimm To: skiboot@lists.ozlabs.org Date: Thu, 5 Sep 2019 09:29:14 -0400 Message-Id: <20190905132919.8765-4-grimm@linux.ibm.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190905132919.8765-1-grimm@linux.ibm.com> References: <20190905132919.8765-1-grimm@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-09-05_04:, , 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-1906280000 definitions=main-1909050132 Subject: [Skiboot] [RFC PATCH 3/8] pef: Load ultravisor from pnor/flash X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryan Grimm Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" From: Santosh Sivaraj Ultravisor firmware is present as a lid file or as 'UVISOR' partition. Use flash resource load helper to load ultravisor firmware into secure memory area pointed by the hdata. Signed-off-by: Santosh Sivaraj [ grimm: Define load identifiers for ultra.lid.xz ] [ grimm: Improve error logging ] Signed-off-by: Ryan Grimm --- core/flash.c | 1 + core/init.c | 14 +++++ hw/fsp/fsp.c | 2 + hw/ultravisor.c | 129 +++++++++++++++++++++++++++++++++++++++++++ include/platform.h | 1 + include/ultravisor.h | 4 ++ 6 files changed, 151 insertions(+) diff --git a/core/flash.c b/core/flash.c index 203b695d..a9c25486 100644 --- a/core/flash.c +++ b/core/flash.c @@ -42,6 +42,7 @@ static struct { { RESOURCE_ID_INITRAMFS,RESOURCE_SUBID_NONE, "ROOTFS" }, { RESOURCE_ID_CAPP, RESOURCE_SUBID_SUPPORTED, "CAPP" }, { RESOURCE_ID_IMA_CATALOG, RESOURCE_SUBID_SUPPORTED, "IMA_CATALOG" }, + { RESOURCE_ID_UV_IMAGE, RESOURCE_SUBID_NONE, "UVISOR" }, { RESOURCE_ID_VERSION, RESOURCE_SUBID_NONE, "VERSION" }, { RESOURCE_ID_KERNEL_FW, RESOURCE_SUBID_NONE, "BOOTKERNFW" }, }; diff --git a/core/init.c b/core/init.c index 25d827f2..08989b2d 100644 --- a/core/init.c +++ b/core/init.c @@ -44,6 +44,7 @@ #include #include #include +#include enum proc_gen proc_gen; unsigned int pcie_max_link_speed; @@ -1203,6 +1204,11 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) pci_nvram_init(); preload_capp_ucode(); + + /* preload and decompress ultravisor image */ + uv_preload_image(); + uv_decompress_image(); + start_preload_kernel(); /* Catalog decompression routine */ @@ -1258,6 +1264,14 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) /* Add the list of interrupts going to OPAL */ add_opal_interrupts(); + /* Init uiltravisor software */ + fdt = create_dtb(dt_root, false); + if (!fdt) { + op_display(OP_FATAL, OP_MOD_INIT, 2); + abort(); + } + init_uv(fdt); + /* Now release parts of memory nodes we haven't used ourselves... */ mem_region_release_unused(); diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c index 6fa6534f..829e56f4 100644 --- a/hw/fsp/fsp.c +++ b/hw/fsp/fsp.c @@ -114,6 +114,7 @@ static u64 fsp_hir_timeout; #define KERNEL_LID_PHYP 0x80a00701 #define KERNEL_LID_OPAL 0x80f00101 #define INITRAMFS_LID_OPAL 0x80f00102 +#define ULTRA_LID_OPAL 0x80f00105 /* * We keep track on last logged values for some things to print only on @@ -2375,6 +2376,7 @@ static struct { } fsp_lid_map[] = { { RESOURCE_ID_KERNEL, RESOURCE_SUBID_NONE, KERNEL_LID_OPAL }, { RESOURCE_ID_INITRAMFS,RESOURCE_SUBID_NONE, INITRAMFS_LID_OPAL }, + { RESOURCE_ID_UV_IMAGE, RESOURCE_SUBID_NONE, ULTRA_LID_OPAL }, { RESOURCE_ID_IMA_CATALOG,IMA_CATALOG_NIMBUS, 0x80f00103 }, { RESOURCE_ID_CAPP, CAPP_IDX_MURANO_DD20, 0x80a02002 }, { RESOURCE_ID_CAPP, CAPP_IDX_MURANO_DD21, 0x80a02001 }, diff --git a/hw/ultravisor.c b/hw/ultravisor.c index f79699ef..4f049254 100644 --- a/hw/ultravisor.c +++ b/hw/ultravisor.c @@ -24,6 +24,10 @@ #include #include +static char *uv_image = NULL; +static size_t uv_image_size; +struct xz_decompress *uv_xz = NULL; + static struct dt_node *add_uv_dt_node(void) { struct dt_node *dev, *uv; @@ -59,6 +63,37 @@ static struct dt_node *find_uv_node(void) return uv_node; } +void init_uv(const void *fdt) +{ + struct dt_node *node; + const struct dt_property *base; + + assert(fdt); + + if (!is_msr_bit_set(MSR_S)) + return; + + if (!uv_xz) + return; + + wait_xz_decompress(uv_xz); + if (uv_xz->status) + goto load_error; + + /* the uncompressed location will be the base address of ultravisor */ + node = find_uv_node(); + base = dt_find_property(node, "uv-base-address"); + if (base) + dt_del_property(node, (struct dt_property *)base); + + dt_add_property_u64(node, "uv-base-address", (uint64_t)uv_xz->dst); + + /* TODO start ultravisor */ +load_error: + free(uv_image); + free(uv_xz); +} + static bool dt_append_memory_range(struct dt_node *node, __be64 start, __be64 len) { @@ -131,3 +166,97 @@ bool uv_add_mem_range(__be64 start, __be64 end) return ret; } + +static bool uv_on_hw(void) +{ + return (is_msr_bit_set(MSR_S) && + !(proc_chip_quirks & QUIRK_MAMBO_CALLOUTS) && + (proc_gen >= proc_gen_p9)); +} + +/* + * Preload the uv image from SMF pnor partition + */ +void uv_preload_image(void) +{ + int ret; + + + if (uv_on_hw() == false) + return; + + prlog(PR_DEBUG, "UV preload starting\n"); + + uv_image_size = MAX_COMPRESSED_UV_IMAGE_SIZE; + uv_image = malloc(MAX_COMPRESSED_UV_IMAGE_SIZE); + if (!uv_image) { + prerror("Memory allocation for ultravisor failed\n"); + return; + } + + ret = start_preload_resource(RESOURCE_ID_UV_IMAGE, RESOURCE_SUBID_NONE, + uv_image, &uv_image_size); + + if (ret != OPAL_SUCCESS) { + prerror("UV: Failed to preload Ultravisor image: %d\n", ret); + free(uv_image); + uv_image = NULL; + } +} + +/* + * Decompress the UV image + * + * This function modifies the uv_image variable to point to the decompressed + * image location. + */ +void uv_decompress_image(void) +{ + const struct dt_property *ranges; + struct dt_node *uv_node; + uint64_t *range; + + if (uv_on_hw() == false) + return; + + if (uv_image == NULL) { + prerror("UV: Preload hasn't started yet! Aborting.\n"); + return; + } + + if (wait_for_resource_loaded(RESOURCE_ID_UV_IMAGE, + RESOURCE_SUBID_NONE) != OPAL_SUCCESS) { + prerror("UV: Ultravisor image load failed\n"); + return; + } + + uv_node = dt_find_by_name(dt_root, "ibm,uv-firmware"); + if (!uv_node) { + prerror("UV: Cannot find ibm,uv-firmware node\n"); + return; + } + + ranges = dt_find_property(uv_node, "secure-memory-ranges"); + if (!ranges) { + prerror("UV: Cannot find secure-memory-ranges"); + return; + } + + uv_xz = malloc(sizeof(struct xz_decompress)); + if (!uv_xz) { + prerror("UV: Cannot allocate memory for decompression of UV\n"); + return; + } + + /* the load area is the first secure memory range */ + range = (void *)ranges->prop; + uv_xz->dst = (void *)dt_get_number(range, 2); + uv_xz->dst_size = dt_get_number(range + 1, 2); + uv_xz->src = uv_image; + uv_xz->src_size = uv_image_size; + + /* TODO security and integrity checks? */ + xz_start_decompress(uv_xz); + if ((uv_xz->status != OPAL_PARTIAL) && (uv_xz->status != OPAL_SUCCESS)) + prerror("UV: XZ decompression failed status 0x%x\n", uv_xz->status); +} diff --git a/include/platform.h b/include/platform.h index 0b043856..259550d4 100644 --- a/include/platform.h +++ b/include/platform.h @@ -17,6 +17,7 @@ enum resource_id { RESOURCE_ID_INITRAMFS, RESOURCE_ID_CAPP, RESOURCE_ID_IMA_CATALOG, + RESOURCE_ID_UV_IMAGE, RESOURCE_ID_VERSION, RESOURCE_ID_KERNEL_FW, }; diff --git a/include/ultravisor.h b/include/ultravisor.h index d038d42b..08f10da4 100644 --- a/include/ultravisor.h +++ b/include/ultravisor.h @@ -20,8 +20,12 @@ /* Bit 15 of an address should be set for it to be used as a secure memory area * for the secure virtual machines */ #define UV_SECURE_MEM_BIT (PPC_BIT(15)) +#define MAX_COMPRESSED_UV_IMAGE_SIZE 0x40000 /* 256 Kilobytes */ extern int start_uv(uint64_t entry, void *ptr); extern bool uv_add_mem_range(__be64 start, __be64 end); +extern void uv_preload_image(void); +extern void uv_decompress_image(void); +extern void init_uv(const void *fdt); #endif /* __ULTRAVISOR_H */