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