[Skiboot] [RFC, PATCH] external/opal-prd: Allow instance numbers for PRD ranges
Daniel M Crowell
dcrowell at us.ibm.com
Tue Jun 30 23:54:36 AEST 2015
Yes, we need this right now to get the HOMER access to work on multi-proc
systems. The instance number will match the associate chip in this case.
--
Dan Crowell
Senior Software Engineer - Power Systems Enablement Firmware
IBM Rochester: t/l 553-2987
dcrowell at us.ibm.com
From: Patrick Williams III/Rochester/IBM
To: "Jeremy Kerr" <jk at ozlabs.org>
Cc: "skiboot at lists.ozlabs.org" <skiboot at lists.ozlabs.org>, Daniel M
Crowell/Rochester/IBM at ibmus
Date: 06/30/2015 03:40 AM
Subject: Re: [Skiboot] [RFC, PATCH] external/opal-prd: Allow
instance numbers for PRD ranges
Do we have a case of needing this upcoming? Even on multi-socket systems,
we currently make a single VPD section (which already handles multiple
Centaurs) so the need isn't coming to mind for me.
I would think we would tend to want them numbered in decreasing order
instead of increasing because the devtree, etc. is built from high address
down.
Patrick Williams
Sent from my iPhone
On Jun 30, 2015, at 3:03 AM, Jeremy Kerr <jk at ozlabs.org> wrote:
We have a provision for multiple instances of the same PRD range. For
example, multiple-socket systems may have a PRD range per socket.
This change adds an 'int instance' argument to the get_reserved_mem()
call, allowing HBRT to request a specific instance of a range. We bump
the hinterface version in indicate that this new parameter is
present.
These ranges can be provided by ibm,prd-instance properties in the
reserved-memory nodes. If these are provided, they'll be used, otherwise
opal-prd will number the instances automatically, based on increading
physical addreses.
Signed-off-by: Jeremy Kerr <jk at ozlabs.org>
---
external/opal-prd/hostboot-interface.h | 3
external/opal-prd/opal-prd.c | 122 +++++++++++++++++++++++--
external/opal-prd/thunk.S | 2
3 files changed, 117 insertions(+), 10 deletions(-)
diff --git a/external/opal-prd/hostboot-interface.h
b/external/opal-prd/hostboot-interface.h
index a518f50..3c162aa 100644
--- a/external/opal-prd/hostboot-interface.h
+++ b/external/opal-prd/hostboot-interface.h
@@ -117,10 +117,11 @@ struct host_interfaces {
* name.
*
* @param[in] Devtree name (ex. "ibm,hbrt-vpd-image")
+ * @param[in] Devtree instance
* @return physical address of region (or NULL).
* @platform FSP,OpenPOWER
*/
- uint64_t (*get_reserved_mem)(const char*);
+ uint64_t (*get_reserved_mem)(const char *name, uint32_t instance);
/**
* @brief Force a core to be awake, or clear the force
diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c
index 9f686c5..98fd86b 100644
--- a/external/opal-prd/opal-prd.c
+++ b/external/opal-prd/opal-prd.c
@@ -60,6 +60,8 @@ struct prd_range {
const char *name;
uint64_t physaddr;
uint64_t size;
+ bool multiple;
+ uint32_t instance;
};
struct opal_prd_ctx {
@@ -68,6 +70,7 @@ struct opal_prd_ctx {
struct opal_prd_info info;
struct prd_range *ranges;
int n_ranges;
+ bool fw_range_instances;
long page_size;
void *code_addr;
size_t code_size;
@@ -127,7 +130,7 @@ struct func_desc {
void *toc;
} hbrt_entry;
-static struct prd_range *find_range(const char *name)
+static struct prd_range *find_range(const char *name, uint32_t instance)
{
struct prd_range *range;
unsigned int i;
@@ -135,8 +138,13 @@ static struct prd_range *find_range(const char *name)
for (i = 0; i < ctx->n_ranges; i++) {
range = &ctx->ranges[i];
- if (!strcmp(range->name, name))
- return range;
+ if (strcmp(range->name, name))
+ continue;
+
+ if (range->multiple && range->instance != instance)
+ continue;
+
+ return range;
}
return NULL;
@@ -273,7 +281,7 @@ int hservice_scom_write(uint64_t chip_id, uint64_t
addr,
return 0;
}
-uint64_t hservice_get_reserved_mem(const char *name)
+uint64_t hservice_get_reserved_mem(const char *name, uint32_t instance)
{
uint64_t align_physaddr, offset;
struct prd_range *range;
@@ -281,7 +289,7 @@ uint64_t hservice_get_reserved_mem(const char *name)
pr_debug("IMAGE: hservice_get_reserved_mem: %s", name);
- range = find_range(name);
+ range = find_range(name, instance);
if (!range) {
pr_log(LOG_WARNING, "IMAGE: get_reserved_mem: "
"no such range %s", name);
@@ -672,7 +680,7 @@ static int map_hbrt_physmem(struct opal_prd_ctx *ctx,
const char *name)
struct prd_range *range;
void *buf;
- range = find_range(name);
+ range = find_range(name, 0);
if (!range) {
pr_log(LOG_ERR, "IMAGE: can't find code region %s", name);
return -1;
@@ -770,11 +778,12 @@ static int open_and_read(const char *path, void
**bufp, int *lenp)
static int prd_init_one_range(struct opal_prd_ctx *ctx, const char *path,
struct dirent *dirent)
{
- char *label_path, *reg_path;
+ char *label_path, *reg_path, *instance_path;
struct prd_range *range;
int label_len, len, rc;
- char *label;
+ __be32 *instance;
__be64 *reg;
+ char *label;
void *buf;
rc = asprintf(&label_path, "%s/%s/ibm,prd-label", path,
dirent->d_name);
@@ -783,6 +792,13 @@ static int prd_init_one_range(struct opal_prd_ctx
*ctx, const char *path,
"node: %m");
return -1;
}
+ rc = asprintf(&instance_path, "%s/%s/ibm,prd-instance",
+ path, dirent->d_name);
+ if (rc < 0) {
+ pr_log(LOG_ERR, "FW: error creating 'ibm,prd-instance' path "
+ "node: %m");
+ return -1;
+ }
rc = asprintf(®_path, "%s/%s/reg", path, dirent->d_name);
if (rc < 0) {
pr_log(LOG_ERR, "FW: error creating 'reg' path "
@@ -823,16 +839,97 @@ static int prd_init_one_range(struct opal_prd_ctx
*ctx, const char *path,
range->name = strndup(label, label_len);
range->physaddr = be64toh(reg[0]);
range->size = be64toh(reg[1]);
+
+ /* optional instance */
+ rc = open_and_read(instance_path, &buf, &len);
+ if (!rc && len == sizeof(*instance)) {
+ range->multiple = true;
+ range->instance = be32toh(*instance);
+ ctx->fw_range_instances = true;
+ }
rc = 0;
out_free:
free(reg);
free(label);
+ free(instance_path);
free(reg_path);
free(label_path);
return rc;
}
+static int compare_ranges(const void *ap, const void *bp)
+{
+ const struct prd_range *a = ap, *b = bp;
+ int rc;
+
+ rc = strcmp(a->name, b->name);
+ if (rc)
+ return rc;
+
+ if (a->physaddr < b->physaddr)
+ return -1;
+ else if (a->physaddr > b->physaddr)
+ return 1;
+
+ return 0;
+}
+
+static void assign_range_instances(struct opal_prd_ctx *ctx)
+{
+ int i;
+
+ if (!ctx->n_ranges)
+ return;
+
+ ctx->ranges[0].multiple = false;
+ ctx->ranges[0].instance = 0;
+
+ for (i = 1; i < ctx->n_ranges; i++) {
+ struct prd_range *cur, *prev;
+
+ cur = &ctx->ranges[i];
+ prev = &ctx->ranges[i-1];
+
+ if (!strcmp(cur->name, prev->name)) {
+ prev->multiple = true;
+ cur->multiple = true;
+ cur->instance = prev->instance + 1;
+ } else {
+ cur->multiple = false;
+ cur->instance = 0;
+ }
+ }
+}
+
+static void print_ranges(struct opal_prd_ctx *ctx)
+{
+ int i;
+
+ if (ctx->n_ranges == 0)
+ pr_log(LOG_INFO, "FW: No PRD ranges");
+
+ pr_log(LOG_DEBUG, "FW: %d PRD ranges, instances assigned by %s",
+ ctx->n_ranges,
+ ctx->fw_range_instances ? "firmware" : "userspace");
+
+ for (i = 0; i < ctx->n_ranges; i++) {
+ struct prd_range *range = &ctx->ranges[i];
+ char instance_str[20];
+
+ if (range->multiple)
+ snprintf(instance_str, sizeof(instance_str),
+ " [%d]", range->instance);
+ else
+ instance_str[0] = '\0';
+
+ pr_log(LOG_DEBUG, "FW: %016lx-%016lx %s%s", range->physaddr,
+ range->physaddr + range->size - 1,
+ range->name,
+ instance_str);
+ }
+}
+
static int prd_init_ranges(struct opal_prd_ctx *ctx)
{
struct dirent *dirent;
@@ -865,6 +962,15 @@ static int prd_init_ranges(struct opal_prd_ctx *ctx)
}
rc = 0;
+ /* sort ranges and assign instance numbers for duplicates (if the
+ * firmware doesn't number instances for us) */
+ qsort(ctx->ranges, ctx->n_ranges, sizeof(struct prd_range),
+ compare_ranges);
+
+ if (!ctx->fw_range_instances)
+ assign_range_instances(ctx);
+
+ print_ranges(ctx);
out_free:
free(path);
diff --git a/external/opal-prd/thunk.S b/external/opal-prd/thunk.S
index ab1e737..bd347f3 100644
--- a/external/opal-prd/thunk.S
+++ b/external/opal-prd/thunk.S
@@ -156,7 +156,7 @@ name##_thunk: ;\
.globl hinterface
hinterface:
/* HBRT interface version */
- .llong 1
+ .llong 2
/* Callout pointers */
CALLBACK_THUNK(hservice_puts)
_______________________________________________
Skiboot mailing list
Skiboot at lists.ozlabs.org
https://lists.ozlabs.org/listinfo/skiboot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/skiboot/attachments/20150630/8d479574/attachment-0001.html>
More information about the Skiboot
mailing list