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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 904b1bc was 904b1bc, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix remaining ccheck issues.

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