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