[Skiboot] [RFC, PATCH] external/opal-prd: Allow instance numbers for PRD ranges

Patrick Williams III iawillia at us.ibm.com
Tue Jun 30 18:40:40 AEST 2015


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/31b51189/attachment-0001.html>


More information about the Skiboot mailing list