<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>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. </div><div><br></div><div>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. <br><br><div>Patrick Williams</div><div><span style="font-size: 13pt;">Sent from my iPhone</span></div></div><div><br>On Jun 30, 2015, at 3:03 AM, Jeremy Kerr <<a href="mailto:jk@ozlabs.org">jk@ozlabs.org</a>> wrote:<br><br></div><blockquote type="cite"><div><span>We have a provision for multiple instances of the same PRD range. For</span><br><span>example, multiple-socket systems may have a PRD range per socket.</span><br><span></span><br><span>This change adds an 'int instance' argument to the get_reserved_mem()</span><br><span>call, allowing HBRT to request a specific instance of a range. We bump</span><br><span>the hinterface version in indicate that this new parameter is</span><br><span>present.</span><br><span></span><br><span>These ranges can be provided by ibm,prd-instance properties in the</span><br><span>reserved-memory nodes. If these are provided, they'll be used, otherwise</span><br><span>opal-prd will number the instances automatically, based on increading</span><br><span>physical addreses.</span><br><span></span><br><span>Signed-off-by: Jeremy Kerr <<a href="mailto:jk@ozlabs.org">jk@ozlabs.org</a>></span><br><span></span><br><span>---</span><br><span> external/opal-prd/hostboot-interface.h | 3 </span><br><span> external/opal-prd/opal-prd.c | 122 +++++++++++++++++++++++--</span><br><span> external/opal-prd/thunk.S | 2 </span><br><span> 3 files changed, 117 insertions(+), 10 deletions(-)</span><br><span></span><br><span>diff --git a/external/opal-prd/hostboot-interface.h b/external/opal-prd/hostboot-interface.h</span><br><span>index a518f50..3c162aa 100644</span><br><span>--- a/external/opal-prd/hostboot-interface.h</span><br><span>+++ b/external/opal-prd/hostboot-interface.h</span><br><span>@@ -117,10 +117,11 @@ struct host_interfaces {</span><br><span> * name.</span><br><span> *</span><br><span> * @param[in] Devtree name (ex. "ibm,hbrt-vpd-image")</span><br><span>+ * @param[in] Devtree instance</span><br><span> * @return physical address of region (or NULL).</span><br><span> * @platform FSP,OpenPOWER</span><br><span> */</span><br><span>- uint64_t (*get_reserved_mem)(const char*);</span><br><span>+ uint64_t (*get_reserved_mem)(const char *name, uint32_t instance);</span><br><span></span><br><span> /**</span><br><span> * @brief Force a core to be awake, or clear the force</span><br><span>diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c</span><br><span>index 9f686c5..98fd86b 100644</span><br><span>--- a/external/opal-prd/opal-prd.c</span><br><span>+++ b/external/opal-prd/opal-prd.c</span><br><span>@@ -60,6 +60,8 @@ struct prd_range {</span><br><span> const char *name;</span><br><span> uint64_t physaddr;</span><br><span> uint64_t size;</span><br><span>+ bool multiple;</span><br><span>+ uint32_t instance;</span><br><span> };</span><br><span></span><br><span> struct opal_prd_ctx {</span><br><span>@@ -68,6 +70,7 @@ struct opal_prd_ctx {</span><br><span> struct opal_prd_info info;</span><br><span> struct prd_range *ranges;</span><br><span> int n_ranges;</span><br><span>+ bool fw_range_instances;</span><br><span> long page_size;</span><br><span> void *code_addr;</span><br><span> size_t code_size;</span><br><span>@@ -127,7 +130,7 @@ struct func_desc {</span><br><span> void *toc;</span><br><span> } hbrt_entry;</span><br><span></span><br><span>-static struct prd_range *find_range(const char *name)</span><br><span>+static struct prd_range *find_range(const char *name, uint32_t instance)</span><br><span> {</span><br><span> struct prd_range *range;</span><br><span> unsigned int i;</span><br><span>@@ -135,8 +138,13 @@ static struct prd_range *find_range(const char *name)</span><br><span> for (i = 0; i < ctx->n_ranges; i++) {</span><br><span> range = &ctx->ranges[i];</span><br><span></span><br><span>- if (!strcmp(range->name, name))</span><br><span>- return range;</span><br><span>+ if (strcmp(range->name, name))</span><br><span>+ continue;</span><br><span>+</span><br><span>+ if (range->multiple && range->instance != instance)</span><br><span>+ continue;</span><br><span>+</span><br><span>+ return range;</span><br><span> }</span><br><span></span><br><span> return NULL;</span><br><span>@@ -273,7 +281,7 @@ int hservice_scom_write(uint64_t chip_id, uint64_t addr,</span><br><span> return 0;</span><br><span> }</span><br><span></span><br><span>-uint64_t hservice_get_reserved_mem(const char *name)</span><br><span>+uint64_t hservice_get_reserved_mem(const char *name, uint32_t instance)</span><br><span> {</span><br><span> uint64_t align_physaddr, offset;</span><br><span> struct prd_range *range;</span><br><span>@@ -281,7 +289,7 @@ uint64_t hservice_get_reserved_mem(const char *name)</span><br><span></span><br><span> pr_debug("IMAGE: hservice_get_reserved_mem: %s", name);</span><br><span></span><br><span>- range = find_range(name);</span><br><span>+ range = find_range(name, instance);</span><br><span> if (!range) {</span><br><span> pr_log(LOG_WARNING, "IMAGE: get_reserved_mem: "</span><br><span> "no such range %s", name);</span><br><span>@@ -672,7 +680,7 @@ static int map_hbrt_physmem(struct opal_prd_ctx *ctx, const char *name)</span><br><span> struct prd_range *range;</span><br><span> void *buf;</span><br><span></span><br><span>- range = find_range(name);</span><br><span>+ range = find_range(name, 0);</span><br><span> if (!range) {</span><br><span> pr_log(LOG_ERR, "IMAGE: can't find code region %s", name);</span><br><span> return -1;</span><br><span>@@ -770,11 +778,12 @@ static int open_and_read(const char *path, void **bufp, int *lenp)</span><br><span> static int prd_init_one_range(struct opal_prd_ctx *ctx, const char *path,</span><br><span> struct dirent *dirent)</span><br><span> {</span><br><span>- char *label_path, *reg_path;</span><br><span>+ char *label_path, *reg_path, *instance_path;</span><br><span> struct prd_range *range;</span><br><span> int label_len, len, rc;</span><br><span>- char *label;</span><br><span>+ __be32 *instance;</span><br><span> __be64 *reg;</span><br><span>+ char *label;</span><br><span> void *buf;</span><br><span></span><br><span> rc = asprintf(&label_path, "%s/%s/ibm,prd-label", path, dirent->d_name);</span><br><span>@@ -783,6 +792,13 @@ static int prd_init_one_range(struct opal_prd_ctx *ctx, const char *path,</span><br><span> "node: %m");</span><br><span> return -1;</span><br><span> }</span><br><span>+ rc = asprintf(&instance_path, "%s/%s/ibm,prd-instance",</span><br><span>+ path, dirent->d_name);</span><br><span>+ if (rc < 0) {</span><br><span>+ pr_log(LOG_ERR, "FW: error creating 'ibm,prd-instance' path "</span><br><span>+ "node: %m");</span><br><span>+ return -1;</span><br><span>+ }</span><br><span> rc = asprintf(®_path, "%s/%s/reg", path, dirent->d_name);</span><br><span> if (rc < 0) {</span><br><span> pr_log(LOG_ERR, "FW: error creating 'reg' path "</span><br><span>@@ -823,16 +839,97 @@ static int prd_init_one_range(struct opal_prd_ctx *ctx, const char *path,</span><br><span> range->name = strndup(label, label_len);</span><br><span> range->physaddr = be64toh(reg[0]);</span><br><span> range->size = be64toh(reg[1]);</span><br><span>+</span><br><span>+ /* optional instance */</span><br><span>+ rc = open_and_read(instance_path, &buf, &len);</span><br><span>+ if (!rc && len == sizeof(*instance)) {</span><br><span>+ range->multiple = true;</span><br><span>+ range->instance = be32toh(*instance);</span><br><span>+ ctx->fw_range_instances = true;</span><br><span>+ }</span><br><span> rc = 0;</span><br><span></span><br><span> out_free:</span><br><span> free(reg);</span><br><span> free(label);</span><br><span>+ free(instance_path);</span><br><span> free(reg_path);</span><br><span> free(label_path);</span><br><span> return rc;</span><br><span> }</span><br><span></span><br><span>+static int compare_ranges(const void *ap, const void *bp)</span><br><span>+{</span><br><span>+ const struct prd_range *a = ap, *b = bp;</span><br><span>+ int rc;</span><br><span>+</span><br><span>+ rc = strcmp(a->name, b->name);</span><br><span>+ if (rc)</span><br><span>+ return rc;</span><br><span>+</span><br><span>+ if (a->physaddr < b->physaddr)</span><br><span>+ return -1;</span><br><span>+ else if (a->physaddr > b->physaddr)</span><br><span>+ return 1;</span><br><span>+</span><br><span>+ return 0;</span><br><span>+}</span><br><span>+</span><br><span>+static void assign_range_instances(struct opal_prd_ctx *ctx)</span><br><span>+{</span><br><span>+ int i;</span><br><span>+</span><br><span>+ if (!ctx->n_ranges)</span><br><span>+ return;</span><br><span>+</span><br><span>+ ctx->ranges[0].multiple = false;</span><br><span>+ ctx->ranges[0].instance = 0;</span><br><span>+</span><br><span>+ for (i = 1; i < ctx->n_ranges; i++) {</span><br><span>+ struct prd_range *cur, *prev;</span><br><span>+</span><br><span>+ cur = &ctx->ranges[i];</span><br><span>+ prev = &ctx->ranges[i-1];</span><br><span>+</span><br><span>+ if (!strcmp(cur->name, prev->name)) {</span><br><span>+ prev->multiple = true;</span><br><span>+ cur->multiple = true;</span><br><span>+ cur->instance = prev->instance + 1;</span><br><span>+ } else {</span><br><span>+ cur->multiple = false;</span><br><span>+ cur->instance = 0;</span><br><span>+ }</span><br><span>+ }</span><br><span>+}</span><br><span>+</span><br><span>+static void print_ranges(struct opal_prd_ctx *ctx)</span><br><span>+{</span><br><span>+ int i;</span><br><span>+</span><br><span>+ if (ctx->n_ranges == 0)</span><br><span>+ pr_log(LOG_INFO, "FW: No PRD ranges");</span><br><span>+</span><br><span>+ pr_log(LOG_DEBUG, "FW: %d PRD ranges, instances assigned by %s",</span><br><span>+ ctx->n_ranges,</span><br><span>+ ctx->fw_range_instances ? "firmware" : "userspace");</span><br><span>+</span><br><span>+ for (i = 0; i < ctx->n_ranges; i++) {</span><br><span>+ struct prd_range *range = &ctx->ranges[i];</span><br><span>+ char instance_str[20];</span><br><span>+</span><br><span>+ if (range->multiple)</span><br><span>+ snprintf(instance_str, sizeof(instance_str),</span><br><span>+ " [%d]", range->instance);</span><br><span>+ else</span><br><span>+ instance_str[0] = '\0';</span><br><span>+</span><br><span>+ pr_log(LOG_DEBUG, "FW: %016lx-%016lx %s%s", range->physaddr,</span><br><span>+ range->physaddr + range->size - 1,</span><br><span>+ range->name,</span><br><span>+ instance_str);</span><br><span>+ }</span><br><span>+}</span><br><span>+</span><br><span> static int prd_init_ranges(struct opal_prd_ctx *ctx)</span><br><span> {</span><br><span> struct dirent *dirent;</span><br><span>@@ -865,6 +962,15 @@ static int prd_init_ranges(struct opal_prd_ctx *ctx)</span><br><span> }</span><br><span></span><br><span> rc = 0;</span><br><span>+ /* sort ranges and assign instance numbers for duplicates (if the</span><br><span>+ * firmware doesn't number instances for us) */</span><br><span>+ qsort(ctx->ranges, ctx->n_ranges, sizeof(struct prd_range),</span><br><span>+ compare_ranges);</span><br><span>+</span><br><span>+ if (!ctx->fw_range_instances)</span><br><span>+ assign_range_instances(ctx);</span><br><span>+</span><br><span>+ print_ranges(ctx);</span><br><span></span><br><span> out_free:</span><br><span> free(path);</span><br><span>diff --git a/external/opal-prd/thunk.S b/external/opal-prd/thunk.S</span><br><span>index ab1e737..bd347f3 100644</span><br><span>--- a/external/opal-prd/thunk.S</span><br><span>+++ b/external/opal-prd/thunk.S</span><br><span>@@ -156,7 +156,7 @@ name##_thunk: ;\</span><br><span> .globl hinterface</span><br><span> hinterface:</span><br><span> /* HBRT interface version */</span><br><span>- .llong 1</span><br><span>+ .llong 2</span><br><span></span><br><span> /* Callout pointers */</span><br><span> CALLBACK_THUNK(hservice_puts)</span><br><span>_______________________________________________</span><br><span>Skiboot mailing list</span><br><span><a href="mailto:Skiboot@lists.ozlabs.org">Skiboot@lists.ozlabs.org</a></span><br><span><a href="https://lists.ozlabs.org/listinfo/skiboot">https://lists.ozlabs.org/listinfo/skiboot</a></span><br></div></blockquote></body></html>