source: mainline/kernel/arch/sparc64/src/sun4v/md.c

Last change on this file was c5429fe, checked in by Jakub Jermar <jakub@…>, 7 years ago

Disambiguate architecture specific doxygroups

  • Property mode set to 100644
File size: 8.3 KB
RevLine 
[74cbac7d]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
[c5429fe]29/** @addtogroup kernel_sparc64
[74cbac7d]30 * @{
31 */
32/** @file
33 */
34
35#include <debug.h>
36#include <panic.h>
[b2e121a]37#include <halt.h>
[b2fa1204]38#include <log.h>
[19f857a]39#include <str.h>
[74cbac7d]40#include <arch/sun4v/md.h>
41#include <arch/sun4v/hypercall.h>
42#include <arch/mm/page.h>
43
44/* maximum MD size estimate (in bytes) */
45#define MD_MAX_SIZE (64 * 1024)
46
47/** element types (element tag values) */
48#define LIST_END 0x0 /**< End of element list */
49#define NODE 0x4e /**< Start of node definition */
50#define NODE_END 0x45 /**< End of node definition */
51#define NOOP 0x20 /**< NOOP list element - to be ignored */
52#define PROP_ARC 0x61 /**< Node property arc'ing to another node */
53#define PROP_VAL 0x76 /**< Node property with an integer value */
54#define PROP_STR 0x73 /**< Node property with a string value */
55#define PROP_DATA 0x64 /**< Node property with a block of data */
56
57/** machine description header */
58typedef 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 */
[3bacee1]63} __attribute__((packed)) md_header_t;
[74cbac7d]64
65/** machine description element (in the node block) */
66typedef struct {
[904b1bc]67 /** Type of element */
68 uint8_t tag;
69 /** Length in bytes of element name */
70 uint8_t name_len;
71 /** Reserved field (zeros) */
72 uint16_t _reserved_field;
73 /** Location offset of name associated with this element relative to
74 * start of name block
75 */
76 uint32_t name_offset;
77
[74cbac7d]78 union {
79 /** for elements of type “PROP_STR” and of type “PROP_DATA” */
80 struct {
81 /** Length in bytes of data in data block */
82 uint32_t data_len;
83
84 /**
85 * Location offset of data associated with this
86 * element relative to start of data block
87 */
88 uint32_t data_offset;
89 } y;
90
91 /**
92 * 64 bit value for elements of tag type “NODE”, “PROP_VAL”
93 * or “PROP_ARC”
94 */
95 uint64_t val;
96 } d;
[3bacee1]97} __attribute__((packed)) md_element_t;
[74cbac7d]98
99/** index of the element within the node block */
100typedef unsigned int element_idx_t;
101
102/** buffer to which the machine description will be saved */
103static uint8_t mach_desc[MD_MAX_SIZE]
[3bacee1]104 __attribute__((aligned(16)));
[74cbac7d]105
106/** returns pointer to the element at the given index */
107static md_element_t *get_element(element_idx_t idx)
108{
[7da160b]109 return (md_element_t *) (mach_desc +
110 sizeof(md_header_t) + idx * sizeof(md_element_t));
[74cbac7d]111}
112
113/** returns the name of the element represented by the index */
114static const char *get_element_name(element_idx_t idx)
115{
116 md_header_t *md_header = (md_header_t *) mach_desc;
117 uintptr_t name_offset = get_element(idx)->name_offset;
118 return (char *) mach_desc + sizeof(md_header_t) +
[7da160b]119 md_header->node_blk_sz + name_offset;
[74cbac7d]120}
121
122/** finds the name of the node represented by "node" */
123const char *md_get_node_name(md_node_t node)
124{
125 return get_element_name(node);
126}
127
128/**
129 * Returns the value of the integer property of the given node.
130 *
[1b20da0]131 * @param
[74cbac7d]132 */
133bool md_get_integer_property(md_node_t node, const char *key,
[3bacee1]134 uint64_t *result)
[74cbac7d]135{
[1b20da0]136 element_idx_t idx = node;
[74cbac7d]137
138 while (get_element(idx)->tag != NODE_END) {
139 idx++;
140 md_element_t *element = get_element(idx);
141 if (element->tag == PROP_VAL &&
[7da160b]142 str_cmp(key, get_element_name(idx)) == 0) {
[74cbac7d]143 *result = element->d.val;
144 return true;
145 }
146 }
147
148 return false;
149}
150
151/**
152 * Returns the value of the string property of the given node.
153 *
[1b20da0]154 * @param
[74cbac7d]155 */
156bool md_get_string_property(md_node_t node, const char *key,
[3bacee1]157 const char **result)
[74cbac7d]158{
159 md_header_t *md_header = (md_header_t *) mach_desc;
160 element_idx_t idx = node;
161
162 while (get_element(idx)->tag != NODE_END) {
163 idx++;
164 md_element_t *element = get_element(idx);
165 if (element->tag == PROP_DATA &&
[7da160b]166 str_cmp(key, get_element_name(idx)) == 0) {
[74cbac7d]167 *result = (char *) mach_desc + sizeof(md_header_t) +
[7da160b]168 md_header->node_blk_sz + md_header->name_blk_sz +
169 element->d.y.data_offset;
[74cbac7d]170 return true;
171 }
172 }
173
174 return false;
175}
176
177/**
178 * Moves the child oterator to the next child (following sibling of the node
179 * the oterator currently points to).
180 *
181 * @param it pointer to the iterator to be moved
182 */
183bool md_next_child(md_child_iter_t *it)
184{
185 element_idx_t backup = *it;
186
187 while (get_element(*it)->tag != NODE_END) {
188 (*it)++;
189 md_element_t *element = get_element(*it);
190 if (element->tag == PROP_ARC &&
[7da160b]191 str_cmp("fwd", get_element_name(*it)) == 0) {
[74cbac7d]192 return true;
193 }
194 }
195
196 *it = backup;
197 return false;
198}
199
200/**
201 * Returns the node the iterator point to.
202 */
203md_node_t md_get_child_node(md_child_iter_t it)
204{
205 return get_element(it)->d.val;
206}
207
208/**
209 * Helper function used to split a string to a part before the first
210 * slash sign and a part after the slash sign.
211 *
212 * @param str pointer to the string to be split; when the function finishes,
213 * it will contain only the part following the first slash sign of
214 * the original string
215 * @param head pointer to the string which will be set to the part before the
216 * first slash sign
217 */
218static bool str_parse_head(char **str, char **head)
219{
220 *head = *str;
221
222 char *cur = *str;
223 while (*cur != '\0') {
224 if (*cur == '/') {
225 *cur = '\0';
226 *str = cur + 1;
227 return true;
228 }
229 cur++;
230 }
231
232 return false;
233}
234
235/**
236 * Returns the descendant of the given node. The descendant is identified
237 * by a path where the node names are separated by a slash.
238 *
239 * Ex.: Let there be a node N with path "a/b/c/x/y/z" and let P represent the
240 * node with path "a/b/c". Then md_get_child(P, "x/y/z") will return N.
241 */
242md_node_t md_get_child(md_node_t node, char *name)
243{
244 bool more;
245
246 do {
247 char *head;
248 more = str_parse_head(&name, &head);
[a35b458]249
[74cbac7d]250 while (md_next_child(&node)) {
251 element_idx_t child = md_get_child_node(node);
252 if (str_cmp(head, get_element_name(child)) == 0) {
253 node = child;
254 break;
255 }
256 }
257
258 } while (more);
259
260 return node;
261}
262
263/** returns the root node of MD */
264md_node_t md_get_root(void)
265{
266 return 0;
267}
268
269/**
270 * Returns the child iterator - a token to be passed to functions iterating
271 * through all the children of a node.
272 *
273 * @param node a node whose children the iterator will be used
274 * to iterate through
275 */
276md_child_iter_t md_get_child_iterator(md_node_t node)
277{
278 return node;
279}
280
281/**
282 * Moves "node" to the node following "node" in the list of all the existing
[1b20da0]283 * nodes of the MD whose name is "name".
[74cbac7d]284 */
285bool md_next_node(md_node_t *node, const char *name)
286{
287 md_element_t *element;
288 (*node)++;
289
290 do {
291 element = get_element(*node);
292
293 if (element->tag == NODE &&
[7da160b]294 str_cmp(name, get_element_name(*node)) == 0) {
[74cbac7d]295 return true;
296 }
[a35b458]297
[74cbac7d]298 (*node)++;
299 } while (element->tag != LIST_END);
300
301 return false;
302}
303
304/**
305 * Retrieves the machine description from the hypervisor and saves it to
306 * a kernel buffer.
307 */
308void md_init(void)
309{
310 uint64_t retval = __hypercall_fast2(MACH_DESC, KA2PA(mach_desc),
[7da160b]311 MD_MAX_SIZE);
[74cbac7d]312
313 retval = retval;
[7da160b]314 if (retval != HV_EOK) {
[b2fa1204]315 log(LF_ARCH, LVL_ERROR, "Could not retrieve machine "
316 "description, error=%" PRIu64 ".", retval);
[74cbac7d]317 }
318}
319
320/** @}
321 */
Note: See TracBrowser for help on using the repository browser.