[Skiboot] [RFC PATCH v5 12/16] Load the ultravisor from flash and decompress

Alexey Kardashevskiy aik at ozlabs.ru
Thu Mar 12 12:08:52 AEDT 2020



On 28/02/2020 07:40, Ryan Grimm 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 laster in init_uv.


s/laster/later/ ?

> 
> 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      | 102 ++++++++++++++++++++++++++++++++++++++-----
>  include/platform.h   |   1 +
>  include/ultravisor.h |   4 +-
>  6 files changed, 100 insertions(+), 11 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 f124f893..1300ab03 100644
> --- a/core/init.c
> +++ b/core/init.c
> @@ -1300,6 +1300,7 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
>  
>  	preload_capp_ucode();
>  	start_preload_kernel();
> +	uv_preload_image();


Can this be a part of init_uv()?


>  
>  	/* Catalog decompression routine */
>  	imc_decompress_catalog();
> diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c
> index 7592ee07..0411f035 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
> @@ -2372,6 +2373,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 ea14d8bd..277faeeb 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 = false;
>  
> +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,
> @@ -69,10 +74,52 @@ int start_ultravisor(void *fdt)
>  	return OPAL_SUCCESS;
>  }
>  
> +static int uv_decompress_image(void)
> +{
> +	struct xz_decompress *uv_xz;


xz_decompress is really small, allocate it on stack. Thanks,


> +	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 = malloc(sizeof(struct xz_decompress));
> +	if (!uv_xz) {
> +		prerror("UV: Cannot allocate memory for decompression of UV\n");
> +		return OPAL_NO_MEM;
> +	}
> +
> +	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)) {
> +		prerror("UV: XZ decompression failed status 0x%x\n", uv_xz->status);
> +		free(uv_xz);
> +		return OPAL_INTERNAL_ERROR;
> +	}
> +
> +	free(uv_xz);
> +	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");
> @@ -82,23 +129,58 @@ void init_uv()
>  	uv_fw_node = dt_find_compatible_node(dt_root, NULL, "ibm,uv-firmware");
>  	if (!uv_fw_node) {
>  		prerror("UV: No ibm,uv-firmware node found\n");
> -		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;
> -	}
> +	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 6ecdbe47..04491d6a 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 0d4d4939..26a986cd 100644
> --- a/include/ultravisor.h
> +++ b/include/ultravisor.h
> @@ -8,7 +8,8 @@
>  #include <types.h>
>  #include <processor.h>
>  
> -#define UV_LOAD_MAX_SIZE        0x200000
> +#define MAX_COMPRESSED_UV_IMAGE_SIZE	0x40000 /* 256 Kilobytes */
> +#define UV_LOAD_MAX_SIZE		0x200000
>  
>  #define UCALL_BUFSIZE 4
>  #define UV_READ_SCOM  0xF114
> @@ -19,6 +20,7 @@ extern int start_uv(uint64_t entry, void *fdt);
>  extern bool uv_present;
>  
>  int start_ultravisor(void *fdt);
> +void uv_preload_image(void);
>  void init_uv(void);
>  
>  static inline int uv_xscom_read(u64 partid, u64 pcb_addr, u64 *val)
> 

-- 
Alexey


More information about the Skiboot mailing list