linux/arch/sparc/kernel/mdesc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* mdesc.c: Sun4V machine description handling.
   3 *
   4 * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
   5 */
   6#include <linux/kernel.h>
   7#include <linux/types.h>
   8#include <linux/log2.h>
   9#include <linux/list.h>
  10#include <linux/slab.h>
  11#include <linux/mm.h>
  12#include <linux/miscdevice.h>
  13#include <linux/memblock.h>
  14#include <linux/export.h>
  15#include <linux/refcount.h>
  16
  17#include <asm/cpudata.h>
  18#include <asm/hypervisor.h>
  19#include <asm/mdesc.h>
  20#include <asm/prom.h>
  21#include <linux/uaccess.h>
  22#include <asm/oplib.h>
  23#include <asm/smp.h>
  24#include <asm/adi.h>
  25
  26/* Unlike the OBP device tree, the machine description is a full-on
  27 * DAG.  An arbitrary number of ARCs are possible from one
  28 * node to other nodes and thus we can't use the OBP device_node
  29 * data structure to represent these nodes inside of the kernel.
  30 *
  31 * Actually, it isn't even a DAG, because there are back pointers
  32 * which create cycles in the graph.
  33 *
  34 * mdesc_hdr and mdesc_elem describe the layout of the data structure
  35 * we get from the Hypervisor.
  36 */
  37struct mdesc_hdr {
  38        u32     version; /* Transport version */
  39        u32     node_sz; /* node block size */
  40        u32     name_sz; /* name block size */
  41        u32     data_sz; /* data block size */
  42        char    data[];
  43} __attribute__((aligned(16)));
  44
  45struct mdesc_elem {
  46        u8      tag;
  47#define MD_LIST_END     0x00
  48#define MD_NODE         0x4e
  49#define MD_NODE_END     0x45
  50#define MD_NOOP         0x20
  51#define MD_PROP_ARC     0x61
  52#define MD_PROP_VAL     0x76
  53#define MD_PROP_STR     0x73
  54#define MD_PROP_DATA    0x64
  55        u8      name_len;
  56        u16     resv;
  57        u32     name_offset;
  58        union {
  59                struct {
  60                        u32     data_len;
  61                        u32     data_offset;
  62                } data;
  63                u64     val;
  64        } d;
  65};
  66
  67struct mdesc_mem_ops {
  68        struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
  69        void (*free)(struct mdesc_handle *handle);
  70};
  71
  72struct mdesc_handle {
  73        struct list_head        list;
  74        struct mdesc_mem_ops    *mops;
  75        void                    *self_base;
  76        refcount_t              refcnt;
  77        unsigned int            handle_size;
  78        struct mdesc_hdr        mdesc;
  79};
  80
  81typedef int (*mdesc_node_info_get_f)(struct mdesc_handle *, u64,
  82                                     union md_node_info *);
  83typedef void (*mdesc_node_info_rel_f)(union md_node_info *);
  84typedef bool (*mdesc_node_match_f)(union md_node_info *, union md_node_info *);
  85
  86struct md_node_ops {
  87        char                    *name;
  88        mdesc_node_info_get_f   get_info;
  89        mdesc_node_info_rel_f   rel_info;
  90        mdesc_node_match_f      node_match;
  91};
  92
  93static int get_vdev_port_node_info(struct mdesc_handle *md, u64 node,
  94                                   union md_node_info *node_info);
  95static void rel_vdev_port_node_info(union md_node_info *node_info);
  96static bool vdev_port_node_match(union md_node_info *a_node_info,
  97                                 union md_node_info *b_node_info);
  98
  99static int get_ds_port_node_info(struct mdesc_handle *md, u64 node,
 100                                 union md_node_info *node_info);
 101static void rel_ds_port_node_info(union md_node_info *node_info);
 102static bool ds_port_node_match(union md_node_info *a_node_info,
 103                               union md_node_info *b_node_info);
 104
 105/* supported node types which can be registered */
 106static struct md_node_ops md_node_ops_table[] = {
 107        {"virtual-device-port", get_vdev_port_node_info,
 108         rel_vdev_port_node_info, vdev_port_node_match},
 109        {"domain-services-port", get_ds_port_node_info,
 110         rel_ds_port_node_info, ds_port_node_match},
 111        {NULL, NULL, NULL, NULL}
 112};
 113
 114static void mdesc_get_node_ops(const char *node_name,
 115                               mdesc_node_info_get_f *get_info_f,
 116                               mdesc_node_info_rel_f *rel_info_f,
 117                               mdesc_node_match_f *match_f)
 118{
 119        int i;
 120
 121        if (get_info_f)
 122                *get_info_f = NULL;
 123
 124        if (rel_info_f)
 125                *rel_info_f = NULL;
 126
 127        if (match_f)
 128                *match_f = NULL;
 129
 130        if (!node_name)
 131                return;
 132
 133        for (i = 0; md_node_ops_table[i].name != NULL; i++) {
 134                if (strcmp(md_node_ops_table[i].name, node_name) == 0) {
 135                        if (get_info_f)
 136                                *get_info_f = md_node_ops_table[i].get_info;
 137
 138                        if (rel_info_f)
 139                                *rel_info_f = md_node_ops_table[i].rel_info;
 140
 141                        if (match_f)
 142                                *match_f = md_node_ops_table[i].node_match;
 143
 144                        break;
 145                }
 146        }
 147}
 148
 149static void mdesc_handle_init(struct mdesc_handle *hp,
 150                              unsigned int handle_size,
 151                              void *base)
 152{
 153        BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
 154
 155        memset(hp, 0, handle_size);
 156        INIT_LIST_HEAD(&hp->list);
 157        hp->self_base = base;
 158        refcount_set(&hp->refcnt, 1);
 159        hp->handle_size = handle_size;
 160}
 161
 162static struct mdesc_handle * __init mdesc_memblock_alloc(unsigned int mdesc_size)
 163{
 164        unsigned int handle_size, alloc_size;
 165        struct mdesc_handle *hp;
 166        unsigned long paddr;
 167
 168        handle_size = (sizeof(struct mdesc_handle) -
 169                       sizeof(struct mdesc_hdr) +
 170                       mdesc_size);
 171        alloc_size = PAGE_ALIGN(handle_size);
 172
 173        paddr = memblock_phys_alloc(alloc_size, PAGE_SIZE);
 174
 175        hp = NULL;
 176        if (paddr) {
 177                hp = __va(paddr);
 178                mdesc_handle_init(hp, handle_size, hp);
 179        }
 180        return hp;
 181}
 182
 183static void __init mdesc_memblock_free(struct mdesc_handle *hp)
 184{
 185        unsigned int alloc_size;
 186        unsigned long start;
 187
 188        BUG_ON(refcount_read(&hp->refcnt) != 0);
 189        BUG_ON(!list_empty(&hp->list));
 190
 191        alloc_size = PAGE_ALIGN(hp->handle_size);
 192        start = __pa(hp);
 193        memblock_free_late(start, alloc_size);
 194}
 195
 196static struct mdesc_mem_ops memblock_mdesc_ops = {
 197        .alloc = mdesc_memblock_alloc,
 198        .free  = mdesc_memblock_free,
 199};
 200
 201static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
 202{
 203        unsigned int handle_size;
 204        struct mdesc_handle *hp;
 205        unsigned long addr;
 206        void *base;
 207
 208        handle_size = (sizeof(struct mdesc_handle) -
 209                       sizeof(struct mdesc_hdr) +
 210                       mdesc_size);
 211        base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_RETRY_MAYFAIL);
 212        if (!base)
 213                return NULL;
 214
 215        addr = (unsigned long)base;
 216        addr = (addr + 15UL) & ~15UL;
 217        hp = (struct mdesc_handle *) addr;
 218
 219        mdesc_handle_init(hp, handle_size, base);
 220
 221        return hp;
 222}
 223
 224static void mdesc_kfree(struct mdesc_handle *hp)
 225{
 226        BUG_ON(refcount_read(&hp->refcnt) != 0);
 227        BUG_ON(!list_empty(&hp->list));
 228
 229        kfree(hp->self_base);
 230}
 231
 232static struct mdesc_mem_ops kmalloc_mdesc_memops = {
 233        .alloc = mdesc_kmalloc,
 234        .free  = mdesc_kfree,
 235};
 236
 237static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
 238                                        struct mdesc_mem_ops *mops)
 239{
 240        struct mdesc_handle *hp = mops->alloc(mdesc_size);
 241
 242        if (hp)
 243                hp->mops = mops;
 244
 245        return hp;
 246}
 247
 248static void mdesc_free(struct mdesc_handle *hp)
 249{
 250        hp->mops->free(hp);
 251}
 252
 253static struct mdesc_handle *cur_mdesc;
 254static LIST_HEAD(mdesc_zombie_list);
 255static DEFINE_SPINLOCK(mdesc_lock);
 256
 257struct mdesc_handle *mdesc_grab(void)
 258{
 259        struct mdesc_handle *hp;
 260        unsigned long flags;
 261
 262        spin_lock_irqsave(&mdesc_lock, flags);
 263        hp = cur_mdesc;
 264        if (hp)
 265                refcount_inc(&hp->refcnt);
 266        spin_unlock_irqrestore(&mdesc_lock, flags);
 267
 268        return hp;
 269}
 270EXPORT_SYMBOL(mdesc_grab);
 271
 272void mdesc_release(struct mdesc_handle *hp)
 273{
 274        unsigned long flags;
 275
 276        spin_lock_irqsave(&mdesc_lock, flags);
 277        if (refcount_dec_and_test(&hp->refcnt)) {
 278                list_del_init(&hp->list);
 279                hp->mops->free(hp);
 280        }
 281        spin_unlock_irqrestore(&mdesc_lock, flags);
 282}
 283EXPORT_SYMBOL(mdesc_release);
 284
 285static DEFINE_MUTEX(mdesc_mutex);
 286static struct mdesc_notifier_client *client_list;
 287
 288void mdesc_register_notifier(struct mdesc_notifier_client *client)
 289{
 290        bool supported = false;
 291        u64 node;
 292        int i;
 293
 294        mutex_lock(&mdesc_mutex);
 295
 296        /* check to see if the node is supported for registration */
 297        for (i = 0; md_node_ops_table[i].name != NULL; i++) {
 298                if (strcmp(md_node_ops_table[i].name, client->node_name) == 0) {
 299                        supported = true;
 300                        break;
 301                }
 302        }
 303
 304        if (!supported) {
 305                pr_err("MD: %s node not supported\n", client->node_name);
 306                mutex_unlock(&mdesc_mutex);
 307                return;
 308        }
 309
 310        client->next = client_list;
 311        client_list = client;
 312
 313        mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
 314                client->add(cur_mdesc, node, client->node_name);
 315
 316        mutex_unlock(&mdesc_mutex);
 317}
 318
 319static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node)
 320{
 321        const u64 *id;
 322        u64 a;
 323
 324        id = NULL;
 325        mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
 326                u64 target;
 327
 328                target = mdesc_arc_target(hp, a);
 329                id = mdesc_get_property(hp, target,
 330                                        "cfg-handle", NULL);
 331                if (id)
 332                        break;
 333        }
 334
 335        return id;
 336}
 337
 338static int get_vdev_port_node_info(struct mdesc_handle *md, u64 node,
 339                                   union md_node_info *node_info)
 340{
 341        const u64 *parent_cfg_hdlp;
 342        const char *name;
 343        const u64 *idp;
 344
 345        /*
 346         * Virtual device nodes are distinguished by:
 347         * 1. "id" property
 348         * 2. "name" property
 349         * 3. parent node "cfg-handle" property
 350         */
 351        idp = mdesc_get_property(md, node, "id", NULL);
 352        name = mdesc_get_property(md, node, "name", NULL);
 353        parent_cfg_hdlp = parent_cfg_handle(md, node);
 354
 355        if (!idp || !name || !parent_cfg_hdlp)
 356                return -1;
 357
 358        node_info->vdev_port.id = *idp;
 359        node_info->vdev_port.name = kstrdup_const(name, GFP_KERNEL);
 360        if (!node_info->vdev_port.name)
 361                return -1;
 362        node_info->vdev_port.parent_cfg_hdl = *parent_cfg_hdlp;
 363
 364        return 0;
 365}
 366
 367static void rel_vdev_port_node_info(union md_node_info *node_info)
 368{
 369        if (node_info && node_info->vdev_port.name) {
 370                kfree_const(node_info->vdev_port.name);
 371                node_info->vdev_port.name = NULL;
 372        }
 373}
 374
 375static bool vdev_port_node_match(union md_node_info *a_node_info,
 376                                 union md_node_info *b_node_info)
 377{
 378        if (a_node_info->vdev_port.id != b_node_info->vdev_port.id)
 379                return false;
 380
 381        if (a_node_info->vdev_port.parent_cfg_hdl !=
 382            b_node_info->vdev_port.parent_cfg_hdl)
 383                return false;
 384
 385        if (strncmp(a_node_info->vdev_port.name,
 386                    b_node_info->vdev_port.name, MDESC_MAX_STR_LEN) != 0)
 387                return false;
 388
 389        return true;
 390}
 391
 392static int get_ds_port_node_info(struct mdesc_handle *md, u64 node,
 393                                 union md_node_info *node_info)
 394{
 395        const u64 *idp;
 396
 397        /* DS port nodes use the "id" property to distinguish them */
 398        idp = mdesc_get_property(md, node, "id", NULL);
 399        if (!idp)
 400                return -1;
 401
 402        node_info->ds_port.id = *idp;
 403
 404        return 0;
 405}
 406
 407static void rel_ds_port_node_info(union md_node_info *node_info)
 408{
 409}
 410
 411static bool ds_port_node_match(union md_node_info *a_node_info,
 412                               union md_node_info *b_node_info)
 413{
 414        if (a_node_info->ds_port.id != b_node_info->ds_port.id)
 415                return false;
 416
 417        return true;
 418}
 419
 420/* Run 'func' on nodes which are in A but not in B.  */
 421static void invoke_on_missing(const char *name,
 422                              struct mdesc_handle *a,
 423                              struct mdesc_handle *b,
 424                              void (*func)(struct mdesc_handle *, u64,
 425                                           const char *node_name))
 426{
 427        mdesc_node_info_get_f get_info_func;
 428        mdesc_node_info_rel_f rel_info_func;
 429        mdesc_node_match_f node_match_func;
 430        union md_node_info a_node_info;
 431        union md_node_info b_node_info;
 432        bool found;
 433        u64 a_node;
 434        u64 b_node;
 435        int rv;
 436
 437        /*
 438         * Find the get_info, rel_info and node_match ops for the given
 439         * node name
 440         */
 441        mdesc_get_node_ops(name, &get_info_func, &rel_info_func,
 442                           &node_match_func);
 443
 444        /* If we didn't find a match, the node type is not supported */
 445        if (!get_info_func || !rel_info_func || !node_match_func) {
 446                pr_err("MD: %s node type is not supported\n", name);
 447                return;
 448        }
 449
 450        mdesc_for_each_node_by_name(a, a_node, name) {
 451                found = false;
 452
 453                rv = get_info_func(a, a_node, &a_node_info);
 454                if (rv != 0) {
 455                        pr_err("MD: Cannot find 1 or more required match properties for %s node.\n",
 456                               name);
 457                        continue;
 458                }
 459
 460                /* Check each node in B for node matching a_node */
 461                mdesc_for_each_node_by_name(b, b_node, name) {
 462                        rv = get_info_func(b, b_node, &b_node_info);
 463                        if (rv != 0)
 464                                continue;
 465
 466                        if (node_match_func(&a_node_info, &b_node_info)) {
 467                                found = true;
 468                                rel_info_func(&b_node_info);
 469                                break;
 470                        }
 471
 472                        rel_info_func(&b_node_info);
 473                }
 474
 475                rel_info_func(&a_node_info);
 476
 477                if (!found)
 478                        func(a, a_node, name);
 479        }
 480}
 481
 482static void notify_one(struct mdesc_notifier_client *p,
 483                       struct mdesc_handle *old_hp,
 484                       struct mdesc_handle *new_hp)
 485{
 486        invoke_on_missing(p->node_name, old_hp, new_hp, p->remove);
 487        invoke_on_missing(p->node_name, new_hp, old_hp, p->add);
 488}
 489
 490static void mdesc_notify_clients(struct mdesc_handle *old_hp,
 491                                 struct mdesc_handle *new_hp)
 492{
 493        struct mdesc_notifier_client *p = client_list;
 494
 495        while (p) {
 496                notify_one(p, old_hp, new_hp);
 497                p = p->next;
 498        }
 499}
 500
 501void mdesc_update(void)
 502{
 503        unsigned long len, real_len, status;
 504        struct mdesc_handle *hp, *orig_hp;
 505        unsigned long flags;
 506
 507        mutex_lock(&mdesc_mutex);
 508
 509        (void) sun4v_mach_desc(0UL, 0UL, &len);
 510
 511        hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
 512        if (!hp) {
 513                printk(KERN_ERR "MD: mdesc alloc fails\n");
 514                goto out;
 515        }
 516
 517        status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
 518        if (status != HV_EOK || real_len > len) {
 519                printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
 520                       status);
 521                refcount_dec(&hp->refcnt);
 522                mdesc_free(hp);
 523                goto out;
 524        }
 525
 526        spin_lock_irqsave(&mdesc_lock, flags);
 527        orig_hp = cur_mdesc;
 528        cur_mdesc = hp;
 529        spin_unlock_irqrestore(&mdesc_lock, flags);
 530
 531        mdesc_notify_clients(orig_hp, hp);
 532
 533        spin_lock_irqsave(&mdesc_lock, flags);
 534        if (refcount_dec_and_test(&orig_hp->refcnt))
 535                mdesc_free(orig_hp);
 536        else
 537                list_add(&orig_hp->list, &mdesc_zombie_list);
 538        spin_unlock_irqrestore(&mdesc_lock, flags);
 539
 540out:
 541        mutex_unlock(&mdesc_mutex);
 542}
 543
 544u64 mdesc_get_node(struct mdesc_handle *hp, const char *node_name,
 545                   union md_node_info *node_info)
 546{
 547        mdesc_node_info_get_f get_info_func;
 548        mdesc_node_info_rel_f rel_info_func;
 549        mdesc_node_match_f node_match_func;
 550        union md_node_info hp_node_info;
 551        u64 hp_node;
 552        int rv;
 553
 554        if (hp == NULL || node_name == NULL || node_info == NULL)
 555                return MDESC_NODE_NULL;
 556
 557        /* Find the ops for the given node name */
 558        mdesc_get_node_ops(node_name, &get_info_func, &rel_info_func,
 559                           &node_match_func);
 560
 561        /* If we didn't find ops for the given node name, it is not supported */
 562        if (!get_info_func || !rel_info_func || !node_match_func) {
 563                pr_err("MD: %s node is not supported\n", node_name);
 564                return -EINVAL;
 565        }
 566
 567        mdesc_for_each_node_by_name(hp, hp_node, node_name) {
 568                rv = get_info_func(hp, hp_node, &hp_node_info);
 569                if (rv != 0)
 570                        continue;
 571
 572                if (node_match_func(node_info, &hp_node_info))
 573                        break;
 574
 575                rel_info_func(&hp_node_info);
 576        }
 577
 578        rel_info_func(&hp_node_info);
 579
 580        return hp_node;
 581}
 582EXPORT_SYMBOL(mdesc_get_node);
 583
 584int mdesc_get_node_info(struct mdesc_handle *hp, u64 node,
 585                        const char *node_name, union md_node_info *node_info)
 586{
 587        mdesc_node_info_get_f get_info_func;
 588        int rv;
 589
 590        if (hp == NULL || node == MDESC_NODE_NULL ||
 591            node_name == NULL || node_info == NULL)
 592                return -EINVAL;
 593
 594        /* Find the get_info op for the given node name */
 595        mdesc_get_node_ops(node_name, &get_info_func, NULL, NULL);
 596
 597        /* If we didn't find a get_info_func, the node name is not supported */
 598        if (get_info_func == NULL) {
 599                pr_err("MD: %s node is not supported\n", node_name);
 600                return -EINVAL;
 601        }
 602
 603        rv = get_info_func(hp, node, node_info);
 604        if (rv != 0) {
 605                pr_err("MD: Cannot find 1 or more required match properties for %s node.\n",
 606                       node_name);
 607                return -1;
 608        }
 609
 610        return 0;
 611}
 612EXPORT_SYMBOL(mdesc_get_node_info);
 613
 614static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
 615{
 616        return (struct mdesc_elem *) mdesc->data;
 617}
 618
 619static void *name_block(struct mdesc_hdr *mdesc)
 620{
 621        return ((void *) node_block(mdesc)) + mdesc->node_sz;
 622}
 623
 624static void *data_block(struct mdesc_hdr *mdesc)
 625{
 626        return ((void *) name_block(mdesc)) + mdesc->name_sz;
 627}
 628
 629u64 mdesc_node_by_name(struct mdesc_handle *hp,
 630                       u64 from_node, const char *name)
 631{
 632        struct mdesc_elem *ep = node_block(&hp->mdesc);
 633        const char *names = name_block(&hp->mdesc);
 634        u64 last_node = hp->mdesc.node_sz / 16;
 635        u64 ret;
 636
 637        if (from_node == MDESC_NODE_NULL) {
 638                ret = from_node = 0;
 639        } else if (from_node >= last_node) {
 640                return MDESC_NODE_NULL;
 641        } else {
 642                ret = ep[from_node].d.val;
 643        }
 644
 645        while (ret < last_node) {
 646                if (ep[ret].tag != MD_NODE)
 647                        return MDESC_NODE_NULL;
 648                if (!strcmp(names + ep[ret].name_offset, name))
 649                        break;
 650                ret = ep[ret].d.val;
 651        }
 652        if (ret >= last_node)
 653                ret = MDESC_NODE_NULL;
 654        return ret;
 655}
 656EXPORT_SYMBOL(mdesc_node_by_name);
 657
 658const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
 659                               const char *name, int *lenp)
 660{
 661        const char *names = name_block(&hp->mdesc);
 662        u64 last_node = hp->mdesc.node_sz / 16;
 663        void *data = data_block(&hp->mdesc);
 664        struct mdesc_elem *ep;
 665
 666        if (node == MDESC_NODE_NULL || node >= last_node)
 667                return NULL;
 668
 669        ep = node_block(&hp->mdesc) + node;
 670        ep++;
 671        for (; ep->tag != MD_NODE_END; ep++) {
 672                void *val = NULL;
 673                int len = 0;
 674
 675                switch (ep->tag) {
 676                case MD_PROP_VAL:
 677                        val = &ep->d.val;
 678                        len = 8;
 679                        break;
 680
 681                case MD_PROP_STR:
 682                case MD_PROP_DATA:
 683                        val = data + ep->d.data.data_offset;
 684                        len = ep->d.data.data_len;
 685                        break;
 686
 687                default:
 688                        break;
 689                }
 690                if (!val)
 691                        continue;
 692
 693                if (!strcmp(names + ep->name_offset, name)) {
 694                        if (lenp)
 695                                *lenp = len;
 696                        return val;
 697                }
 698        }
 699
 700        return NULL;
 701}
 702EXPORT_SYMBOL(mdesc_get_property);
 703
 704u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
 705{
 706        struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
 707        const char *names = name_block(&hp->mdesc);
 708        u64 last_node = hp->mdesc.node_sz / 16;
 709
 710        if (from == MDESC_NODE_NULL || from >= last_node)
 711                return MDESC_NODE_NULL;
 712
 713        ep = base + from;
 714
 715        ep++;
 716        for (; ep->tag != MD_NODE_END; ep++) {
 717                if (ep->tag != MD_PROP_ARC)
 718                        continue;
 719
 720                if (strcmp(names + ep->name_offset, arc_type))
 721                        continue;
 722
 723                return ep - base;
 724        }
 725
 726        return MDESC_NODE_NULL;
 727}
 728EXPORT_SYMBOL(mdesc_next_arc);
 729
 730u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
 731{
 732        struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
 733
 734        ep = base + arc;
 735
 736        return ep->d.val;
 737}
 738EXPORT_SYMBOL(mdesc_arc_target);
 739
 740const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
 741{
 742        struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
 743        const char *names = name_block(&hp->mdesc);
 744        u64 last_node = hp->mdesc.node_sz / 16;
 745
 746        if (node == MDESC_NODE_NULL || node >= last_node)
 747                return NULL;
 748
 749        ep = base + node;
 750        if (ep->tag != MD_NODE)
 751                return NULL;
 752
 753        return names + ep->name_offset;
 754}
 755EXPORT_SYMBOL(mdesc_node_name);
 756
 757static u64 max_cpus = 64;
 758
 759static void __init report_platform_properties(void)
 760{
 761        struct mdesc_handle *hp = mdesc_grab();
 762        u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
 763        const char *s;
 764        const u64 *v;
 765
 766        if (pn == MDESC_NODE_NULL) {
 767                prom_printf("No platform node in machine-description.\n");
 768                prom_halt();
 769        }
 770
 771        s = mdesc_get_property(hp, pn, "banner-name", NULL);
 772        printk("PLATFORM: banner-name [%s]\n", s);
 773        s = mdesc_get_property(hp, pn, "name", NULL);
 774        printk("PLATFORM: name [%s]\n", s);
 775
 776        v = mdesc_get_property(hp, pn, "hostid", NULL);
 777        if (v)
 778                printk("PLATFORM: hostid [%08llx]\n", *v);
 779        v = mdesc_get_property(hp, pn, "serial#", NULL);
 780        if (v)
 781                printk("PLATFORM: serial# [%08llx]\n", *v);
 782        v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
 783        printk("PLATFORM: stick-frequency [%08llx]\n", *v);
 784        v = mdesc_get_property(hp, pn, "mac-address", NULL);
 785        if (v)
 786                printk("PLATFORM: mac-address [%llx]\n", *v);
 787        v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
 788        if (v)
 789                printk("PLATFORM: watchdog-resolution [%llu ms]\n", *v);
 790        v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
 791        if (v)
 792                printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v);
 793        v = mdesc_get_property(hp, pn, "max-cpus", NULL);
 794        if (v) {
 795                max_cpus = *v;
 796                printk("PLATFORM: max-cpus [%llu]\n", max_cpus);
 797        }
 798
 799#ifdef CONFIG_SMP
 800        {
 801                int max_cpu, i;
 802
 803                if (v) {
 804                        max_cpu = *v;
 805                        if (max_cpu > NR_CPUS)
 806                                max_cpu = NR_CPUS;
 807                } else {
 808                        max_cpu = NR_CPUS;
 809                }
 810                for (i = 0; i < max_cpu; i++)
 811                        set_cpu_possible(i, true);
 812        }
 813#endif
 814
 815        mdesc_release(hp);
 816}
 817
 818static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp)
 819{
 820        const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
 821        const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
 822        const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
 823        const char *type;
 824        int type_len;
 825
 826        type = mdesc_get_property(hp, mp, "type", &type_len);
 827
 828        switch (*level) {
 829        case 1:
 830                if (of_find_in_proplist(type, "instn", type_len)) {
 831                        c->icache_size = *size;
 832                        c->icache_line_size = *line_size;
 833                } else if (of_find_in_proplist(type, "data", type_len)) {
 834                        c->dcache_size = *size;
 835                        c->dcache_line_size = *line_size;
 836                }
 837                break;
 838
 839        case 2:
 840                c->ecache_size = *size;
 841                c->ecache_line_size = *line_size;
 842                break;
 843
 844        default:
 845                break;
 846        }
 847
 848        if (*level == 1) {
 849                u64 a;
 850
 851                mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
 852                        u64 target = mdesc_arc_target(hp, a);
 853                        const char *name = mdesc_node_name(hp, target);
 854
 855                        if (!strcmp(name, "cache"))
 856                                fill_in_one_cache(c, hp, target);
 857                }
 858        }
 859}
 860
 861static void find_back_node_value(struct mdesc_handle *hp, u64 node,
 862                                 char *srch_val,
 863                                 void (*func)(struct mdesc_handle *, u64, int),
 864                                 u64 val, int depth)
 865{
 866        u64 arc;
 867
 868        /* Since we have an estimate of recursion depth, do a sanity check. */
 869        if (depth == 0)
 870                return;
 871
 872        mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) {
 873                u64 n = mdesc_arc_target(hp, arc);
 874                const char *name = mdesc_node_name(hp, n);
 875
 876                if (!strcmp(srch_val, name))
 877                        (*func)(hp, n, val);
 878
 879                find_back_node_value(hp, n, srch_val, func, val, depth-1);
 880        }
 881}
 882
 883static void __mark_core_id(struct mdesc_handle *hp, u64 node,
 884                           int core_id)
 885{
 886        const u64 *id = mdesc_get_property(hp, node, "id", NULL);
 887
 888        if (*id < num_possible_cpus())
 889                cpu_data(*id).core_id = core_id;
 890}
 891
 892static void __mark_max_cache_id(struct mdesc_handle *hp, u64 node,
 893                                int max_cache_id)
 894{
 895        const u64 *id = mdesc_get_property(hp, node, "id", NULL);
 896
 897        if (*id < num_possible_cpus()) {
 898                cpu_data(*id).max_cache_id = max_cache_id;
 899
 900                /**
 901                 * On systems without explicit socket descriptions socket
 902                 * is max_cache_id
 903                 */
 904                cpu_data(*id).sock_id = max_cache_id;
 905        }
 906}
 907
 908static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
 909                          int core_id)
 910{
 911        find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10);
 912}
 913
 914static void mark_max_cache_ids(struct mdesc_handle *hp, u64 mp,
 915                               int max_cache_id)
 916{
 917        find_back_node_value(hp, mp, "cpu", __mark_max_cache_id,
 918                             max_cache_id, 10);
 919}
 920
 921static void set_core_ids(struct mdesc_handle *hp)
 922{
 923        int idx;
 924        u64 mp;
 925
 926        idx = 1;
 927
 928        /* Identify unique cores by looking for cpus backpointed to by
 929         * level 1 instruction caches.
 930         */
 931        mdesc_for_each_node_by_name(hp, mp, "cache") {
 932                const u64 *level;
 933                const char *type;
 934                int len;
 935
 936                level = mdesc_get_property(hp, mp, "level", NULL);
 937                if (*level != 1)
 938                        continue;
 939
 940                type = mdesc_get_property(hp, mp, "type", &len);
 941                if (!of_find_in_proplist(type, "instn", len))
 942                        continue;
 943
 944                mark_core_ids(hp, mp, idx);
 945                idx++;
 946        }
 947}
 948
 949static int set_max_cache_ids_by_cache(struct mdesc_handle *hp, int level)
 950{
 951        u64 mp;
 952        int idx = 1;
 953        int fnd = 0;
 954
 955        /**
 956         * Identify unique highest level of shared cache by looking for cpus
 957         * backpointed to by shared level N caches.
 958         */
 959        mdesc_for_each_node_by_name(hp, mp, "cache") {
 960                const u64 *cur_lvl;
 961
 962                cur_lvl = mdesc_get_property(hp, mp, "level", NULL);
 963                if (*cur_lvl != level)
 964                        continue;
 965                mark_max_cache_ids(hp, mp, idx);
 966                idx++;
 967                fnd = 1;
 968        }
 969        return fnd;
 970}
 971
 972static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp)
 973{
 974        int idx = 1;
 975
 976        mdesc_for_each_node_by_name(hp, mp, "socket") {
 977                u64 a;
 978
 979                mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
 980                        u64 t = mdesc_arc_target(hp, a);
 981                        const char *name;
 982                        const u64 *id;
 983
 984                        name = mdesc_node_name(hp, t);
 985                        if (strcmp(name, "cpu"))
 986                                continue;
 987
 988                        id = mdesc_get_property(hp, t, "id", NULL);
 989                        if (*id < num_possible_cpus())
 990                                cpu_data(*id).sock_id = idx;
 991                }
 992                idx++;
 993        }
 994}
 995
 996static void set_sock_ids(struct mdesc_handle *hp)
 997{
 998        u64 mp;
 999
1000        /**
1001         * Find the highest level of shared cache which pre-T7 is also
1002         * the socket.
1003         */
1004        if (!set_max_cache_ids_by_cache(hp, 3))
1005                set_max_cache_ids_by_cache(hp, 2);
1006
1007        /* If machine description exposes sockets data use it.*/
1008        mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets");
1009        if (mp != MDESC_NODE_NULL)
1010                set_sock_ids_by_socket(hp, mp);
1011}
1012
1013static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
1014{
1015        u64 a;
1016
1017        mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
1018                u64 t = mdesc_arc_target(hp, a);
1019                const char *name;
1020                const u64 *id;
1021
1022                name = mdesc_node_name(hp, t);
1023                if (strcmp(name, "cpu"))
1024                        continue;
1025
1026                id = mdesc_get_property(hp, t, "id", NULL);
1027                if (*id < NR_CPUS)
1028                        cpu_data(*id).proc_id = proc_id;
1029        }
1030}
1031
1032static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
1033{
1034        int idx;
1035        u64 mp;
1036
1037        idx = 0;
1038        mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
1039                const char *type;
1040                int len;
1041
1042                type = mdesc_get_property(hp, mp, "type", &len);
1043                if (!of_find_in_proplist(type, "int", len) &&
1044                    !of_find_in_proplist(type, "integer", len))
1045                        continue;
1046
1047                mark_proc_ids(hp, mp, idx);
1048                idx++;
1049        }
1050}
1051
1052static void set_proc_ids(struct mdesc_handle *hp)
1053{
1054        __set_proc_ids(hp, "exec_unit");
1055        __set_proc_ids(hp, "exec-unit");
1056}
1057
1058static void get_one_mondo_bits(const u64 *p, unsigned int *mask,
1059                               unsigned long def, unsigned long max)
1060{
1061        u64 val;
1062
1063        if (!p)
1064                goto use_default;
1065        val = *p;
1066
1067        if (!val || val >= 64)
1068                goto use_default;
1069
1070        if (val > max)
1071                val = max;
1072
1073        *mask = ((1U << val) * 64U) - 1U;
1074        return;
1075
1076use_default:
1077        *mask = ((1U << def) * 64U) - 1U;
1078}
1079
1080static void get_mondo_data(struct mdesc_handle *hp, u64 mp,
1081                           struct trap_per_cpu *tb)
1082{
1083        static int printed;
1084        const u64 *val;
1085
1086        val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
1087        get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7, ilog2(max_cpus * 2));
1088
1089        val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
1090        get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7, 8);
1091
1092        val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
1093        get_one_mondo_bits(val, &tb->resum_qmask, 6, 7);
1094
1095        val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
1096        get_one_mondo_bits(val, &tb->nonresum_qmask, 2, 2);
1097        if (!printed++) {
1098                pr_info("SUN4V: Mondo queue sizes "
1099                        "[cpu(%u) dev(%u) r(%u) nr(%u)]\n",
1100                        tb->cpu_mondo_qmask + 1,
1101                        tb->dev_mondo_qmask + 1,
1102                        tb->resum_qmask + 1,
1103                        tb->nonresum_qmask + 1);
1104        }
1105}
1106
1107static void *mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask)
1108{
1109        struct mdesc_handle *hp = mdesc_grab();
1110        void *ret = NULL;
1111        u64 mp;
1112
1113        mdesc_for_each_node_by_name(hp, mp, "cpu") {
1114                const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
1115                int cpuid = *id;
1116
1117#ifdef CONFIG_SMP
1118                if (cpuid >= NR_CPUS) {
1119                        printk(KERN_WARNING "Ignoring CPU %d which is "
1120                               ">= NR_CPUS (%d)\n",
1121                               cpuid, NR_CPUS);
1122                        continue;
1123                }
1124                if (!cpumask_test_cpu(cpuid, mask))
1125                        continue;
1126#endif
1127
1128                ret = func(hp, mp, cpuid, arg);
1129                if (ret)
1130                        goto out;
1131        }
1132out:
1133        mdesc_release(hp);
1134        return ret;
1135}
1136
1137static void *record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid,
1138                            void *arg)
1139{
1140        ncpus_probed++;
1141#ifdef CONFIG_SMP
1142        set_cpu_present(cpuid, true);
1143#endif
1144        return NULL;
1145}
1146
1147void mdesc_populate_present_mask(cpumask_t *mask)
1148{
1149        if (tlb_type != hypervisor)
1150                return;
1151
1152        ncpus_probed = 0;
1153        mdesc_iterate_over_cpus(record_one_cpu, NULL, mask);
1154}
1155
1156static void * __init check_one_pgsz(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
1157{
1158        const u64 *pgsz_prop = mdesc_get_property(hp, mp, "mmu-page-size-list", NULL);
1159        unsigned long *pgsz_mask = arg;
1160        u64 val;
1161
1162        val = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K |
1163               HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB);
1164        if (pgsz_prop)
1165                val = *pgsz_prop;
1166
1167        if (!*pgsz_mask)
1168                *pgsz_mask = val;
1169        else
1170                *pgsz_mask &= val;
1171        return NULL;
1172}
1173
1174void __init mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask)
1175{
1176        *pgsz_mask = 0;
1177        mdesc_iterate_over_cpus(check_one_pgsz, pgsz_mask, mask);
1178}
1179
1180static void *fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid,
1181                             void *arg)
1182{
1183        const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
1184        struct trap_per_cpu *tb;
1185        cpuinfo_sparc *c;
1186        u64 a;
1187
1188#ifndef CONFIG_SMP
1189        /* On uniprocessor we only want the values for the
1190         * real physical cpu the kernel booted onto, however
1191         * cpu_data() only has one entry at index 0.
1192         */
1193        if (cpuid != real_hard_smp_processor_id())
1194                return NULL;
1195        cpuid = 0;
1196#endif
1197
1198        c = &cpu_data(cpuid);
1199        c->clock_tick = *cfreq;
1200
1201        tb = &trap_block[cpuid];
1202        get_mondo_data(hp, mp, tb);
1203
1204        mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
1205                u64 j, t = mdesc_arc_target(hp, a);
1206                const char *t_name;
1207
1208                t_name = mdesc_node_name(hp, t);
1209                if (!strcmp(t_name, "cache")) {
1210                        fill_in_one_cache(c, hp, t);
1211                        continue;
1212                }
1213
1214                mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
1215                        u64 n = mdesc_arc_target(hp, j);
1216                        const char *n_name;
1217
1218                        n_name = mdesc_node_name(hp, n);
1219                        if (!strcmp(n_name, "cache"))
1220                                fill_in_one_cache(c, hp, n);
1221                }
1222        }
1223
1224        c->core_id = 0;
1225        c->proc_id = -1;
1226
1227        return NULL;
1228}
1229
1230void mdesc_fill_in_cpu_data(cpumask_t *mask)
1231{
1232        struct mdesc_handle *hp;
1233
1234        mdesc_iterate_over_cpus(fill_in_one_cpu, NULL, mask);
1235
1236        hp = mdesc_grab();
1237
1238        set_core_ids(hp);
1239        set_proc_ids(hp);
1240        set_sock_ids(hp);
1241
1242        mdesc_release(hp);
1243
1244        smp_fill_in_sib_core_maps();
1245}
1246
1247/* mdesc_open() - Grab a reference to mdesc_handle when /dev/mdesc is
1248 * opened. Hold this reference until /dev/mdesc is closed to ensure
1249 * mdesc data structure is not released underneath us. Store the
1250 * pointer to mdesc structure in private_data for read and seek to use
1251 */
1252static int mdesc_open(struct inode *inode, struct file *file)
1253{
1254        struct mdesc_handle *hp = mdesc_grab();
1255
1256        if (!hp)
1257                return -ENODEV;
1258
1259        file->private_data = hp;
1260
1261        return 0;
1262}
1263
1264static ssize_t mdesc_read(struct file *file, char __user *buf,
1265                          size_t len, loff_t *offp)
1266{
1267        struct mdesc_handle *hp = file->private_data;
1268        unsigned char *mdesc;
1269        int bytes_left, count = len;
1270
1271        if (*offp >= hp->handle_size)
1272                return 0;
1273
1274        bytes_left = hp->handle_size - *offp;
1275        if (count > bytes_left)
1276                count = bytes_left;
1277
1278        mdesc = (unsigned char *)&hp->mdesc;
1279        mdesc += *offp;
1280        if (!copy_to_user(buf, mdesc, count)) {
1281                *offp += count;
1282                return count;
1283        } else {
1284                return -EFAULT;
1285        }
1286}
1287
1288static loff_t mdesc_llseek(struct file *file, loff_t offset, int whence)
1289{
1290        struct mdesc_handle *hp = file->private_data;
1291
1292        return no_seek_end_llseek_size(file, offset, whence, hp->handle_size);
1293}
1294
1295/* mdesc_close() - /dev/mdesc is being closed, release the reference to
1296 * mdesc structure.
1297 */
1298static int mdesc_close(struct inode *inode, struct file *file)
1299{
1300        mdesc_release(file->private_data);
1301        return 0;
1302}
1303
1304static const struct file_operations mdesc_fops = {
1305        .open    = mdesc_open,
1306        .read    = mdesc_read,
1307        .llseek  = mdesc_llseek,
1308        .release = mdesc_close,
1309        .owner   = THIS_MODULE,
1310};
1311
1312static struct miscdevice mdesc_misc = {
1313        .minor  = MISC_DYNAMIC_MINOR,
1314        .name   = "mdesc",
1315        .fops   = &mdesc_fops,
1316};
1317
1318static int __init mdesc_misc_init(void)
1319{
1320        return misc_register(&mdesc_misc);
1321}
1322
1323__initcall(mdesc_misc_init);
1324
1325void __init sun4v_mdesc_init(void)
1326{
1327        struct mdesc_handle *hp;
1328        unsigned long len, real_len, status;
1329
1330        (void) sun4v_mach_desc(0UL, 0UL, &len);
1331
1332        printk("MDESC: Size is %lu bytes.\n", len);
1333
1334        hp = mdesc_alloc(len, &memblock_mdesc_ops);
1335        if (hp == NULL) {
1336                prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
1337                prom_halt();
1338        }
1339
1340        status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
1341        if (status != HV_EOK || real_len > len) {
1342                prom_printf("sun4v_mach_desc fails, err(%lu), "
1343                            "len(%lu), real_len(%lu)\n",
1344                            status, len, real_len);
1345                mdesc_free(hp);
1346                prom_halt();
1347        }
1348
1349        cur_mdesc = hp;
1350
1351        mdesc_adi_init();
1352        report_platform_properties();
1353}
1354