<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(&reg_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>