Subversion Repositories HelenOS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Pavel Rimsky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup sparc64
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <debug.h>
  36. #include <panic.h>
  37. #include <func.h>
  38. #include <print.h>
  39. #include <arch/sun4v/md.h>
  40. #include <arch/sun4v/hypercall.h>
  41. #include <arch/mm/page.h>
  42.  
  43. /* maximum MD size estimate (in bytes) */
  44. #define MD_MAX_SIZE (16 * 1024)
  45.  
  46. /** element types (element tag values) */
  47. #define LIST_END    0x0 /**< End of element list */
  48. #define NODE        0x4e    /**< Start of node definition */
  49. #define NODE_END    0x45    /**< End of node definition */
  50. #define NOOP        0x20    /**< NOOP list element - to be ignored */
  51. #define PROP_ARC    0x61    /**< Node property arc'ing to another node */
  52. #define PROP_VAL    0x76    /**< Node property with an integer value */
  53. #define PROP_STR    0x73    /**< Node property with a string value */
  54. #define PROP_DATA   0x64    /**< Node property with a block of data */
  55.  
  56.  
  57. /** machine description header */
  58. typedef struct {
  59.     uint32_t transport_version; /**< Transport version number */
  60.     uint32_t node_blk_sz;       /**< Size in bytes of node block */
  61.     uint32_t name_blk_sz;       /**< Size in bytes of name block */
  62.     uint32_t data_blk_sz;       /**< Size in bytes of data block */
  63. } __attribute__ ((packed)) md_header_t;
  64.  
  65. /** machine description element (in the node block) */
  66. typedef struct {
  67.     uint8_t tag;            /**< Type of element */
  68.     uint8_t name_len;       /**< Length in bytes of element name */
  69.     uint16_t _reserved_field;   /**< reserved field (zeros) */
  70.     uint32_t name_offset;       /**< Location offset of name associated
  71.                          with this element relative to
  72.                          start of name block */
  73.     union {
  74.         /** for elements of type “PROP_STR” and of type “PROP_DATA” */
  75.         struct {
  76.             /** Length in bytes of data in data block */
  77.             uint32_t data_len;
  78.  
  79.             /**
  80.              * Location offset of data associated with this
  81.              * element relative to start of data block
  82.              */
  83.             uint32_t data_offset;
  84.         } y;
  85.  
  86.         /**
  87.          *  64 bit value for elements of tag type “NODE”, “PROP_VAL”
  88.          *  or “PROP_ARC”
  89.          */
  90.         uint64_t val;
  91.     } d;
  92. } __attribute__ ((packed)) md_element_t;
  93.  
  94. /** index of the element within the node block */
  95. typedef unsigned int element_idx_t;
  96.  
  97. /** buffer to which the machine description will be saved */
  98. static uint8_t mach_desc[MD_MAX_SIZE]
  99.      __attribute__ ((aligned (16)));
  100.  
  101.  
  102. /** returns pointer to the element at the given index */
  103. static md_element_t *get_element(element_idx_t idx)
  104. {
  105.     return (md_element_t *) (
  106.         mach_desc + sizeof(md_header_t) + idx * sizeof(md_element_t));
  107. }
  108.  
  109. /** returns the name of the element represented by the index */
  110. static const char *get_element_name(element_idx_t idx)
  111. {
  112.     md_header_t *md_header = (md_header_t *) mach_desc;
  113.     uintptr_t name_offset = get_element(idx)->name_offset;
  114.     return (char *) mach_desc + sizeof(md_header_t) +
  115.         md_header->node_blk_sz + name_offset;
  116. }
  117.  
  118. /** finds the name of the node represented by "node" */
  119. const char *md_get_node_name(md_node_t node)
  120. {
  121.     return get_element_name(node);
  122. }
  123.  
  124. /**
  125.  * Returns the value of the integer property of the given node.
  126.  *
  127.  * @param
  128.  */
  129. bool md_get_integer_property(md_node_t node, const char *key,
  130.     uint64_t *result)
  131. {
  132.     element_idx_t idx = node;  
  133.  
  134.     while (get_element(idx)->tag != NODE_END) {
  135.         idx++;
  136.         md_element_t *element = get_element(idx);
  137.         if (element->tag == PROP_VAL &&
  138.                 strcmp(key, get_element_name(idx)) == 0) {
  139.             *result = element->d.val;
  140.             return true;
  141.         }
  142.     }
  143.  
  144.     return false;
  145. }
  146.  
  147. /**
  148.  * Moves the child oterator to the next child (following sibling of the node
  149.  * the oterator currently points to).
  150.  *
  151.  * @param it    pointer to the iterator to be moved
  152.  */
  153. bool md_next_child(md_child_iter_t *it)
  154. {
  155.     element_idx_t backup = *it;
  156.  
  157.     while (get_element(*it)->tag != NODE_END) {
  158.         (*it)++;
  159.         md_element_t *element = get_element(*it);
  160.         if (element->tag == PROP_ARC &&
  161.                 strcmp("fwd", get_element_name(*it)) == 0) {
  162.             return true;
  163.         }
  164.     }
  165.  
  166.     *it = backup;
  167.     return false;
  168. }
  169.  
  170. /**
  171.  * Returns the node the iterator point to.
  172.  */
  173. md_node_t md_get_child_node(md_child_iter_t it)
  174. {
  175.     return get_element(it)->d.val;
  176. }
  177.  
  178. /**
  179.  * Helper function used to split a string to a part before the first
  180.  * slash sign and a part after the slash sign.
  181.  *
  182.  * @param str   pointer to the string to be split; when the function finishes,
  183.  *      it will contain only the part following the first slash sign of
  184.  *      the original string
  185.  * @param head  pointer to the string which will be set to the part before the
  186.  *      first slash sign
  187.  */
  188. static bool str_parse_head(char **str, char **head)
  189. {
  190.     *head = *str;
  191.  
  192.     char *cur = *str;
  193.     while (*cur != '\0') {
  194.         if (*cur == '/') {
  195.             *cur = '\0';
  196.             *str = cur + 1;
  197.             return true;
  198.         }
  199.         cur++;
  200.     }
  201.  
  202.     return false;
  203. }
  204.  
  205. /**
  206.  * Returns the descendant of the given node. The descendant is identified
  207.  * by a path where the node names are separated by a slash.
  208.  *
  209.  * Ex.: Let there be a node N with path "a/b/c/x/y/z" and let P represent the
  210.  * node with path "a/b/c". Then md_get_child(P, "x/y/z") will return N.
  211.  */
  212. md_node_t md_get_child(md_node_t node, char *name)
  213. {
  214.     bool more;
  215.  
  216.     do {
  217.         char *head;
  218.         more = str_parse_head(&name, &head);
  219.        
  220.         while (md_next_child(&node)) {
  221.             element_idx_t child = md_get_child_node(node);
  222.             if (strcmp(head, get_element_name(child)) == 0) {
  223.                 node = child;
  224.                 break;
  225.             }
  226.         }
  227.  
  228.     } while (more);
  229.  
  230.     return node;
  231. }
  232.  
  233. /** returns the root node of MD */
  234. md_node_t md_get_root(void)
  235. {
  236.     return 0;
  237. }
  238.  
  239. /**
  240.  * Returns the child iterator - a token to be passed to functions iterating
  241.  * through all the children of a node.
  242.  *
  243.  * @param node  a node whose children the iterator will be used
  244.  *      to iterate through
  245.  */
  246. md_child_iter_t md_get_child_iterator(md_node_t node)
  247. {
  248.     return node;
  249. }
  250.  
  251. /**
  252.  * Moves "node" to the node following "node" in the list of all the existing
  253.  * nodes of the MD whose name is "name".
  254.  */
  255. bool md_next_node(md_node_t *node, const char *name)
  256. {
  257.     md_element_t *element;
  258.     (*node)++;
  259.  
  260.     do {
  261.         element = get_element(*node);
  262.  
  263.         if (element->tag == NODE &&
  264.                 strcmp(name, get_element_name(*node)) == 0) {
  265.             return true;
  266.         }
  267.        
  268.         (*node)++;
  269.     } while (element->tag != LIST_END);
  270.  
  271.     return false;
  272. }
  273.  
  274. /**
  275.  * Retrieves the machine description from the hypervisor and saves it to
  276.  * a kernel buffer.
  277.  */
  278. void md_init(void)
  279. {
  280.     uint64_t retval = __hypercall_fast2(MACH_DESC, KA2PA(mach_desc),
  281.         MD_MAX_SIZE);
  282.     retval = retval;
  283.     if (retval != EOK) {
  284.         printf("Could not retrieve machine description, error = %d.\n",
  285.             retval);
  286.     }
  287. }
  288.  
  289. /** @}
  290.  */
  291.