[Skiboot] [PATCH 3/3] ... to prevent any potential poller recursions during lid load.

Benjamin Herrenschmidt benh at kernel.crashing.org
Tue Feb 17 08:18:57 AEDT 2015


On Mon, 2015-02-16 at 20:45 +0530, Ananth N Mavinakayanahalli wrote:
> See bz121430 for one such case.
> 
> With this change:
> 
> ...
> 
> [10810950484,5] CUPD: P side ML Keyword = FW830.00
> [10832756491,6] HBRT: 1 lids to load
> [10832762732,7] FSP: Fetch data id: 05 sid: 81e00430 to 0x306cf500(0x100000
> bytes)
> [10832766825,7] FSP:  0x00100000 bytes balign=306cf000 boff=500 bsize=101000
> [10857829395,5] CUPD: Marker LID id : size : status = 0x80a08001 : 0x5d0 : 0x0
> [10966464432,7] FSP:   -> rc=0x00 off: 00000000 twritten: 0007fb80
> [10966468418,7] HBRT: LID 0x81e00430 successfully loaded, len=0x31b83db8
> 
> ...
> 
> [19485180658,7] HBRT: stopOCCs() rc  = 0
> [19582727570,6] OCC: Got OCC Load message, scope=0x2 dbob=0x0 seq=0x10
> [19582732660,7] HBRT: OCC Load requested
> [19582734678,7] HBRT: Calling loadOCC() homer 0000000401400000, occ_common_area
> 0000000400800000, chip 0000
> [19582803643,6] HBRT: Lid load request for 0x81e00430
> [19582806532,7] HBRT: Serviced from cache, len=0x7fb80
> [19582996931,7] HBRT: -> rc = 0
> [19582999113,7] HBRT: Calling loadOCC() homer 0000000401c00000, occ_common_area
> 0000000400800000, chip 0001
> [19583097594,6] HBRT: Lid load request for 0x81e00430
> [19583100343,7] HBRT: Serviced from cache, len=0x7fb80
> [19583274638,7] HBRT: -> rc = 0
> [19583277114,6] HBRT: OCC Start requested
> 
> 
> Signed-off-by: Ananth N Mavinakayanahalli <ananth at in.ibm.com>
> ---
>  core/hostservices.c    |  117 +++++++++++++++++++++++++++++++++++-------------
>  core/init.c            |    3 +
>  include/hostservices.h |    1 
>  3 files changed, 89 insertions(+), 32 deletions(-)
> 
> diff --git a/core/hostservices.c b/core/hostservices.c
> index 952f6b8..1bda67f 100644
> --- a/core/hostservices.c
> +++ b/core/hostservices.c
> @@ -386,36 +386,26 @@ static int hservice_scom_write(uint64_t chip_id, uint64_t addr,
>  	return xscom_write(chip_id, addr, val);
>  }
>  
> -static int hservice_lid_load(uint32_t lid, void **buf, size_t *len)
> +struct hbrt_lid {
> +	void *load_addr;
> +	size_t len;
> +	uint32_t id;
> +	struct list_node link;
> +};
> +static LIST_HEAD(hbrt_lid_list);
> +
> +/* TODO: Few of the following routines can be generalized */
> +static int __hservice_lid_load(uint32_t lid, void **buf, size_t *len)
>  {
>  	int rc;
> -	static void *lid_cache;
> -	static size_t lid_cache_len;
> -	static uint32_t lid_cache_id;
> -
> -	prlog(PR_INFO, "HBRT: LID load request for 0x%08x\n", lid);
>  
>  	/* Adjust LID side first or we get a cache mismatch */
>  	lid = fsp_adjust_lid_side(lid);
>  
> -	/* Check for cache */
> -	if (lid_cache && lid_cache_id == lid) {
> -		*buf = lid_cache;
> -		*len = lid_cache_len;
> -		prlog(PR_DEBUG, "HBRT: Serviced from cache, len=0x%lx\n",
> -		      lid_cache_len);
> -		return 0;
> -	}
> -
> -	/* Cache mismatch, discard old one */
> -	if (lid_cache) {
> -		prlog(PR_DEBUG, "HBRT: Cache mismatch, discarding old"
> -		      " 0x%08x\n", lid_cache_id);
> -		free(lid_cache);
> -		lid_cache = NULL;
> -	}
> -
> -	/* Allocate a new buffer and load the LID into it */
> +	/*
> +	 * Allocate a new buffer and load the LID into it
> +	 * XXX: We currently use the same size for each HBRT lid.
> +	 */
>  	*buf = malloc(HBRT_LOAD_LID_SIZE);
>  	*len = HBRT_LOAD_LID_SIZE;
>  	rc = fsp_fetch_data(0, FSP_DATASET_NONSP_LID, lid, 0, *buf, len);
> @@ -424,17 +414,80 @@ static int hservice_lid_load(uint32_t lid, void **buf, size_t *len)
>  		*len = 0;
>  	*buf = realloc(*buf, *len);
>  
> -	/* We managed, let's cache it */
> -	if (rc == 0 && *len) {
> -		lid_cache = *buf;
> -		lid_cache_len = *len;
> -		lid_cache_id = lid;
> +	prlog(PR_DEBUG, "HBRT: LID 0x%08x successfully loaded, len=0x%lx\n",
> +			lid, (unsigned long)len);
>  
> -		prlog(PR_DEBUG, "HBRT: LID 0x%08x successfully loaded and"
> -		      " cached, len=0x%lx\n", lid, lid_cache_len);
> +	return rc;
> +}
> +
> +static int __hservice_lid_preload(const uint32_t lid)
> +{
> +	struct hbrt_lid *hlid;
> +	void *buf;
> +	size_t len;
> +	int rc;
> +
> +	hlid = zalloc(sizeof(struct hbrt_lid));
> +	if (!hlid) {
> +		prerror("HBRT: Could not allocate struct hbrt_lid\n");
> +		return -ENOMEM;
>  	}
>  
> -	return rc;
> +	rc = __hservice_lid_load(lid, &buf, &len);
> +	if (rc) {
> +		free(hlid);
> +		return rc;
> +	}
> +
> +	hlid->load_addr = buf;
> +	hlid->len = len;
> +	hlid->id = lid;
> +	list_add_tail(&hbrt_lid_list, &hlid->link);
> +
> +	return 0;
> +}
> +
> +/* Find and preload all lids needed by hostservices */
> +void hservices_lid_preload(void)
> +{
> +	const uint32_t *lid_list = NULL;
> +	size_t num_lids;
> +
> +	if (!hservice_runtime)
> +		return;
> +
> +	lid_list = (const uint32_t *)hservice_runtime->get_lid_list(&num_lids);
> +	if (!lid_list) {
> +		prerror("HBRT: get_lid_list() returned NULL\n");
> +		return;
> +	}
> +
> +	prlog(PR_INFO, "HBRT: %d lids to load\n", (int)num_lids);
> +
> +	/* Currently HBRT needs only one (OCC) lid */
> +	while (num_lids--)
> +		__hservice_lid_preload(lid_list[num_lids]);

The above looks wrong... for this to work you'd need to use --num_lids,
otherwise, for let's say 2 lids, you would try to load 2, then 1 instead
of 1 then 0.

> +}
> +
> +static int hservice_lid_load(uint32_t lid, void **buf, size_t *len)
> +{
> +	struct hbrt_lid *hlid;
> +
> +	prlog(PR_INFO, "HBRT: Lid load request for 0x%08x\n", lid);
> +
> +	if (list_empty(&hbrt_lid_list))	/* Should not happen */
> +		hservices_lid_preload();
> +
> +	list_for_each(&hbrt_lid_list, hlid, link) {
> +		if (hlid->id == lid) {
> +			*buf = hlid->load_addr;
> +			*len = hlid->len;
> +			prlog(PR_DEBUG, "HBRT: Serviced from cache,"
> +					" len=0x%lx\n", hlid->len);
> +			return 0;
> +		}
> +	}
> +	return -ENOENT;
>  }
>  
>  static int hservice_lid_unload(void *buf __unused)
> diff --git a/core/init.c b/core/init.c
> index 0b29e2b..018f10f 100644
> --- a/core/init.c
> +++ b/core/init.c
> @@ -645,6 +645,9 @@ void __noreturn main_cpu_entry(const void *fdt, u32 master_cpu)
>  	if (platform.init)
>  		platform.init();
>  
> +	/* Preload hostservices lids */
> +	hservices_lid_preload();
> +

Definitely not the right place to call this.

My worry is I think we can get the OCC messages at any time after the
OPL, but the preload itself can take time operating on FSP and so must
be done after FSP is ready.

Can you check with the FSP people when exactly we can start getting the
startOCC messages ? Is it after we set the HV state ? We need to stick
the preload just before that.

In fact, build this patch on top of Jeremy's that moves hservices_init
to the FSP platform code, and put the preload code right in the place
where the FSP will be able to service the load request and before it
will send us the OCC commands. 

>  	/* Setup dummy console nodes if it's enabled */
>  	if (dummy_console_enabled())
>  		dummy_console_add_nodes();
> diff --git a/include/hostservices.h b/include/hostservices.h
> index 7279c8e..c8958a3 100644
> --- a/include/hostservices.h
> +++ b/include/hostservices.h
> @@ -18,6 +18,7 @@
>  #define __HOSTSERVICES_H
>  
>  bool hservices_init(void);
> +void hservices_lid_preload(void);
>  
>  int host_services_occ_load(void);
>  int host_services_occ_start(void);
> 
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot




More information about the Skiboot mailing list