diff mbox

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

Message ID 20150216151533.1774.39642.stgit@thinktux.in.ibm.com
State Superseded
Headers show

Commit Message

Ananth N Mavinakayanahalli Feb. 16, 2015, 3:15 p.m. UTC
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@in.ibm.com>
---
 core/hostservices.c    |  117 +++++++++++++++++++++++++++++++++++-------------
 core/init.c            |    3 +
 include/hostservices.h |    1 
 3 files changed, 89 insertions(+), 32 deletions(-)

Comments

Vasant Hegde Feb. 16, 2015, 4:16 p.m. UTC | #1
n 02/16/2015 08:45 PM, Ananth N Mavinakayanahalli wrote:
> See bz121430 for one such case.

I think we shouldn't refer our bugzilla number here as its internal bugzilla.

> 
> 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@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;


Better OPAL_NO_MEM;

Rest looks good.

-Vasant
Ananth N Mavinakayanahalli Feb. 16, 2015, 4:40 p.m. UTC | #2
On Mon, Feb 16, 2015 at 09:46:32PM +0530, Vasant Hegde wrote:
> n 02/16/2015 08:45 PM, Ananth N Mavinakayanahalli wrote:
> > See bz121430 for one such case.
> 
> I think we shouldn't refer our bugzilla number here as its internal bugzilla.

Agreed.

...

> > +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;
> 
> 
> Better OPAL_NO_MEM;

Sure. Will make the change.

> Rest looks good.

Thanks for the review.

Ananth
Benjamin Herrenschmidt Feb. 16, 2015, 9:18 p.m. UTC | #3
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@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@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
Ananth N Mavinakayanahalli Feb. 17, 2015, 4:20 a.m. UTC | #4
On Tue, Feb 17, 2015 at 08:18:57AM +1100, Benjamin Herrenschmidt wrote:
> On Mon, 2015-02-16 at 20:45 +0530, Ananth N Mavinakayanahalli wrote:

...

> > +/* 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.

Ugh! Right.. will fix.

...

> >  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.

Sure, will check.

> 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.

Will do.

Thanks for the review!

Ananth
Ananth N Mavinakayanahalli Feb. 17, 2015, 6:42 a.m. UTC | #5
On Tue, Feb 17, 2015 at 09:50:51AM +0530, Ananth N Mavinakayanahalli wrote:
> On Tue, Feb 17, 2015 at 08:18:57AM +1100, Benjamin Herrenschmidt wrote:
> > On Mon, 2015-02-16 at 20:45 +0530, Ananth N Mavinakayanahalli wrote:

...

> > > +	/* 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.
> 
> Sure, will check.

The FSP apparently can service a FETCH_SP_DATA after HV functional --
end of OPL. We can stick the preload in there... but... the FSP folks
aren't sure about the earliest time we can get a OCC load; I will write
to the OCC folks to get that info.

End of OPL is significantly early wrt loading other lids... so we will
not hit the concurrency seen now.

Ananth
Benjamin Herrenschmidt Feb. 17, 2015, 7:57 a.m. UTC | #6
On Tue, 2015-02-17 at 12:12 +0530, Ananth N Mavinakayanahalli wrote:
> The FSP apparently can service a FETCH_SP_DATA after HV functional --
> end of OPL. We can stick the preload in there... but... the FSP folks
> aren't sure about the earliest time we can get a OCC load; I will
> write
> to the OCC folks to get that info.
> 
> End of OPL is significantly early wrt loading other lids... so we will
> not hit the concurrency seen now.

No but if we get an OCC load request while we are preloading we are
stuffed, so we need to make sure we get that bit right.

Worst case, we put the OCC load request message in a private queue until
we have finished preloading LIDs and process them when we are done.

Cheers,
Ben.
diff mbox

Patch

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]);
+}
+
+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();
+
 	/* 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);