[Skiboot] [PATCH v8 07/11] Load the ultravisor from flash and decompress
Oliver O'Halloran
oohall at gmail.com
Fri Aug 28 14:54:50 AEST 2020
On Thu, Aug 27, 2020 at 4:41 AM Ryan Grimm <grimm at linux.ibm.com> wrote:
>
> The ultravisor, labeled UVISOR is preloaded from the PNOR in
> main_cpu_entry after the kernel is preloaded. This also works on
> FSP-based systems with an ultra.lid on the FSP.
>
> Skiboot decompresses it later in init_uv.
>
> Signed-off-by: Santosh Sivaraj <santosh at linux.ibm.com>
> Signed-off-by: Ryan Grimm <grimm at linux.ibm.com>
> ---
> core/flash.c | 1 +
> core/init.c | 1 +
> hw/fsp/fsp.c | 2 +
> hw/ultravisor.c | 95 +++++++++++++++++++++++++++++++++++++++-----
> include/platform.h | 1 +
> include/ultravisor.h | 3 ++
> 6 files changed, 93 insertions(+), 10 deletions(-)
>
> diff --git a/core/flash.c b/core/flash.c
> index de748641..bc44a4e5 100644
> --- a/core/flash.c
> +++ b/core/flash.c
> @@ -45,6 +45,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 91754962..77dfb36f 100644
> --- a/core/init.c
> +++ b/core/init.c
> @@ -1319,6 +1319,7 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
>
> preload_capp_ucode();
> start_preload_kernel();
> + uv_preload_image();
>
> /* Catalog decompression routine */
> imc_decompress_catalog();
> diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c
> index 70452cf9..7b564f93 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
> @@ -2381,6 +2382,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 467f0ca6..34c16404 100644
> --- a/hw/ultravisor.c
> +++ b/hw/ultravisor.c
> @@ -10,11 +10,16 @@
> #include <cpu.h>
> #include <debug_descriptor.h>
> #include <console.h>
> +#include <chip.h>
> +#include <libstb/container.h>
>
> static struct dt_node *uv_fw_node;
> static uint64_t uv_base_addr;
> bool uv_present;
>
> +static char *uv_image = NULL;
> +static size_t uv_image_size;
> +
> struct memcons uv_memcons __section(".data.memcons") = {
> .magic = MEMCONS_MAGIC,
> .obuf_phys = INMEM_UV_CON_START,
> @@ -70,10 +75,44 @@ int start_ultravisor(void *fdt)
> return OPAL_SUCCESS;
> }
>
> +static int uv_decompress_image(void)
> +{
> + struct xz_decompress uv_xz;
> + uint64_t uv_fw_size;
> +
> + if (!uv_image) {
> + prerror("UV: Preload hasn't started yet! Aborting.\n");
> + return OPAL_INTERNAL_ERROR;
> + }
> +
> + if (wait_for_resource_loaded(RESOURCE_ID_UV_IMAGE,
> + RESOURCE_SUBID_NONE) != OPAL_SUCCESS) {
> + prerror("UV: Ultravisor image load failed\n");
> + return OPAL_INTERNAL_ERROR;
> + }
> +
> + uv_xz.dst = (void *)dt_get_address(uv_fw_node, 0, &uv_fw_size);
> + uv_xz.dst_size = uv_fw_size;
> + uv_xz.src_size = uv_image_size;
> + uv_xz.src = uv_image;
> +
> + if (stb_is_container((void*)uv_xz.src, uv_xz.src_size))
> + uv_xz.src = uv_xz.src + SECURE_BOOT_HEADERS_SIZE;
> +
> + xz_start_decompress(&uv_xz);
> + if ((uv_xz.status != OPAL_PARTIAL) && (uv_xz.status != OPAL_SUCCESS)) {
Weird indentation and why would we get OPAL_PARTIAL here?
> + prerror("UV: XZ decompression failed status 0x%x\n", uv_xz.status);
> + return OPAL_INTERNAL_ERROR;
> + }
> +
> + return OPAL_SUCCESS;
> +}
> +
> void init_uv()
> {
> uint64_t uv_dt_src, uv_fw_sz;
> struct dt_node *reserved_mem;
> + int ret;
>
> if (!is_msr_bit_set(MSR_S)) {
> prlog(PR_DEBUG, "UV: S bit not set\n");
> @@ -84,23 +123,59 @@ void init_uv()
> if (!uv_fw_node) {
> prlog(PR_DEBUG, "UV: No ibm,uv-firmware node found, disabling pef\n");
> cpu_disable_pef();
> - return;
> + goto err;
> }
>
> - reserved_mem = dt_find_by_path(dt_root, "/reserved-memory/ibm,uv-firmware");
> - if (!reserved_mem) {
> - prerror("UV: No reserved memory for ibm,uv-firmware found\n");
> - return;
> - }
> + /* If decompress fails, look for reserved memory by Mambo tcl or cronus BML */
> + ret = uv_decompress_image();
> + if (ret) {
> + reserved_mem = dt_find_by_path(dt_root, "/reserved-memory/ibm,uv-firmware");
> + if (!reserved_mem) {
> + prerror("UV: No reserved memory for ibm,uv-firmware found\n");
> + return;
> + }
>
> - uv_dt_src = dt_get_address(reserved_mem, 0, &uv_fw_sz);
> - uv_base_addr = dt_get_address(uv_fw_node, 0, NULL);
> + uv_dt_src = dt_get_address(reserved_mem, 0, &uv_fw_sz);
> + uv_base_addr = dt_get_address(uv_fw_node, 0, NULL);
>
> - prlog(PR_INFO, "UV: Copying 0x%llx bytes to protected memory 0x%llx from 0x%llx\n",
> + prlog(PR_INFO, "UV: Copying 0x%llx bytes to protected memory 0x%llx from 0x%llx\n",
> uv_fw_sz, uv_base_addr, uv_dt_src);
>
> - memcpy((void *)uv_base_addr, (void *)uv_dt_src, uv_fw_sz);
> + memcpy((void *)uv_base_addr, (void *)uv_dt_src, uv_fw_sz);
> + }
>
> dt_add_property_u64(uv_fw_node, "memcons", (u64)&uv_memcons);
> debug_descriptor.uv_memcons_phys = (u64)&uv_memcons;
> +err:
> + local_free(uv_image);
> +}
> +
> +/*
> + * Preload the UV image from PNOR partition
> + *
> + * uv_image is allocated locally to the chip and freed here if preload fails
> + * or free in init_uv
> + */
> +void uv_preload_image(void)
> +{
> + struct proc_chip *chip = next_chip(NULL);
> + int ret;
> +
> + prlog(PR_DEBUG, "UV: Preload starting\n");
> +
> + uv_image_size = MAX_COMPRESSED_UV_IMAGE_SIZE;
> + uv_image = local_alloc(chip->id, uv_image_size, uv_image_size);
> + if (!uv_image) {
> + prerror("UV: Memory allocation failed\n");
> + return;
> + }
> + memset(uv_image, 0, uv_image_size);
> +
> + ret = start_preload_resource(RESOURCE_ID_UV_IMAGE, RESOURCE_SUBID_NONE,
> + uv_image, &uv_image_size);
> +
> + if (ret != OPAL_SUCCESS) {
> + local_free(uv_image);
> + prerror("UV: platform load failed: %d\n", ret);
> + }
> }
> diff --git a/include/platform.h b/include/platform.h
> index ef93278b..57b2eeef 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 84217d66..8048cb76 100644
> --- a/include/ultravisor.h
> +++ b/include/ultravisor.h
> @@ -64,4 +64,7 @@ static inline int uv_xscom_write(u64 partid, u64 pcb_addr, u64 val)
> return ucall(UV_WRITE_SCOM, retbuf, partid, pcb_addr, val);
> }
>
> +#define MAX_COMPRESSED_UV_IMAGE_SIZE 0x40000 /* 256 Kilobytes */
> +void uv_preload_image(void);
> +
> #endif /* __ULTRAVISOR_H */
> --
> 2.18.4
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
More information about the Skiboot
mailing list