Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / common / src / mdsup.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: mdsup.c
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
46 * Use is subject to license terms.
47 */
48
49#pragma ident "@(#)mdsup.c 1.14 07/07/18 SMI"
50
51/*
52 * Support functions for MD scanning
53 */
54#include <sys/htypes.h>
55#include <vdev_intr.h>
56#include <support.h>
57#include <hvctl.h>
58#include <config.h>
59#include <md.h>
60
61#define HDN(_name) { \
62 (((uint64_t)&config.hdnametable.hdname_##_name) - \
63 ((uint64_t)&config.hdnametable)), #_name \
64 }
65
66#define HDN_X(_names, _offsetx) { \
67 (((uint64_t)&config.hdnametable.hdname_##_offsetx) - \
68 ((uint64_t)&config.hdnametable)), \
69 _names \
70 }
71
72struct {
73 uint64_t offset;
74 char *strp;
75} inittable[] = {
76 HDN(root),
77 HDN(fwd),
78 HDN(back),
79 HDN(id),
80 HDN(hvuart),
81 HDN(guest),
82 HDN(guests),
83 HDN(cpu),
84 HDN(cpus),
85#ifdef CONFIG_CRYPTO
86 HDN(mau),
87 HDN(maus),
88 HDN(cwq),
89 HDN(cwqs),
90#endif
91 HDN(pid),
92 HDN(vid),
93 HDN(strandid),
94 HDN(uartbase),
95 HDN(rombase),
96 HDN(romsize),
97#ifdef CONFIG_DISK
98 HDN(diskpa),
99#endif
100#ifdef T1_FPGA_SNET
101 HDN(snet),
102 HDN(snet_ino),
103 HDN(snet_pa),
104#endif
105 HDN(membase),
106 HDN(memsize),
107 HDN(memoffset),
108 HDN(realbase),
109 HDN(base),
110 HDN(size),
111 HDN(ino),
112 HDN(xid),
113 HDN(sid),
114 HDN(memory),
115 HDN(mblock),
116 HDN(hypervisor),
117 HDN(vpcidevice),
118 HDN(cfghandle),
119 HDN(ign),
120 HDN(cfgbase),
121 HDN(iobase),
122 HDN(pciregs),
123 HDN(tod),
124 HDN(devices),
125 HDN(device),
126 HDN(services),
127 HDN(service),
128 HDN(flags),
129 HDN(mtu),
130 HDN(link),
131 HDN(perfctraccess),
132 HDN(diagpriv),
133 HDN(rngctlaccessible),
134 HDN(perfctrhtaccess),
135 HDN(debugprintflags),
136 HDN(memscrubmax),
137 HDN(ldc_endpoints),
138 HDN(sp_ldc_endpoints),
139 HDN(ldc_endpoint),
140 HDN(channel),
141 HDN(target_type),
142 HDN(target_guest),
143 HDN(target_channel),
144 HDN(svc_id),
145 HDN(svc_arg),
146 HDN(svc_vino),
147 HDN(private_svc),
148 HDN(ldc_mapinrabase),
149 HDN(ldc_mapinsize),
150#ifdef CONFIG_SPLIT_SRAM /* { */
151 HDN(sram_ptrs),
152 HDN(inq_offset),
153 HDN(inq_data_offset),
154 HDN(inq_num_pkts),
155 HDN(outq_offset),
156 HDN(outq_data_offset),
157 HDN(outq_num_pkts),
158#endif /* } */
159 HDN(virtual_devices),
160 HDN(channel_devices),
161#ifdef CONFIG_PCIE /* { */
162 HDN(pcie_bus),
163 HDN(allow_bypass),
164#endif /* } */
165#ifdef STANDALONE_NET_DEVICES
166 HDN(network_device),
167#endif
168 HDN(resource_id),
169 HDN(idx),
170 HDN(unbind),
171 HDN(mdpa),
172 HDN(consoles),
173 HDN(console),
174 HDN(sys_hwtw_mode),
175#ifdef CONFIG_CLEANSER
176 HDN(l2scrub_interval),
177 HDN(l2scrub_entries),
178#endif
179 HDN_X("virtualdevices", vdevs),
180 HDN_X("partid", parttag),
181 HDN_X("tod-frequency", todfrequency),
182 HDN_X("tod-offset", todoffset),
183 HDN_X("stick-frequency", stickfrequency),
184 HDN_X("ce-blackout-sec", ceblackoutsec),
185 HDN_X("ce-poll-sec", cepollsec),
186 HDN_X("erpt-pa", erpt_pa),
187 HDN_X("erpt-size", erpt_size),
188 HDN_X("reset-reason", reset_reason),
189 HDN_X("tx-ino", tx_ino),
190 HDN_X("rx-ino", rx_ino),
191 HDN_X("content-version", content_version),
192#ifdef PLX_ERRATUM_LINK_HACK
193 HDN_X("ignore-plx-link-hack", ignore_plx_link_hack),
194#endif
195 { 0, 0 }
196};
197
198
199void
200reloc_hvmd_names()
201{
202 int64_t namereloc;
203 int i;
204
205 /* -KPIC doesnt relocate preinitialized structure pointers */
206 namereloc = (-config.reloc);
207
208 for (i = 0; inittable[i].strp != NULL; i++) {
209 inittable[i].strp += namereloc;
210 }
211}
212
213
214hvctl_status_t
215preparse_hvmd(bin_md_t *mdp)
216{
217 uint64_t basep;
218 int i;
219
220 config.parse_hvmd = mdp; /* stash it */
221
222 if (TR_MAJOR(ntoh32(mdp->hdr.transport_version)) !=
223 TR_MAJOR(MD_TRANSPORT_VERSION)) {
224 DBG(c_printf("Hypervisor MD major version mismatch\n"));
225 return (HVctl_st_badmd);
226 }
227
228 basep = (uint64_t)&config.hdnametable;
229 for (i = 0; inittable[i].strp != NULL; i++) {
230 uint64_t tag;
231 tag = md_find_name_tag(mdp, inittable[i].strp);
232 *((uint64_t *)(basep + inittable[i].offset)) = tag;
233 }
234
235 return (HVctl_st_ok);
236}
237
238
239/*
240 * The HVMD update process is effectively double buffered we check the
241 * new one first, if there are any problems we fail it without making the
242 * configuration change which means we can roll back to the currently active
243 * HVMD on a (re)config failure and it is as if nothing ever happened.
244 */
245void
246accept_hvmd()
247{
248 config.active_hvmd = config.parse_hvmd;
249}
250
251
252/*
253 * Primitive scan to look for a matching string.
254 * If not found, then we return -1
255 */
256uint64_t
257md_find_name_tag(bin_md_t *mdp, char *namep)
258{
259 char *str_tablep;
260 int start_idx;
261 int size;
262
263 /* Find the address of the string table */
264 str_tablep = (char *)(((uint64_t)&(mdp->elem[0])) +
265 ntoh32(mdp->hdr.node_blk_sz));
266
267 size = ntoh32(mdp->hdr.name_blk_sz);
268
269 /*
270 * Dumb linear scan looking for the string in the
271 * string table.
272 */
273 for (start_idx = 0; start_idx < size; ) {
274 int i;
275 char *str_basep;
276
277 str_basep = str_tablep + start_idx;
278
279 /* Brute force match current and test string */
280 for (i = 0; ; i++) {
281 int ch1, ch2;
282
283 ch1 = namep[i];
284 ch2 = str_basep[i];
285
286 if (ch1 != ch2) goto miss;
287 if (ch1 == '\0') {
288 /* Match */
289 return ((((uint64_t)i)<<48) |
290 ((uint64_t)start_idx));
291 }
292 }
293miss:;
294 while (str_basep[i] != '\0') i++;
295 start_idx += i+1; /* start of next string */
296 }
297
298 return ((uint64_t)-1);
299}
300
301
302md_element_t *
303md_find_node(bin_md_t *mdp, md_element_t *startp, uint64_t token)
304{
305 int size;
306 md_element_t *elemp;
307 md_element_t *limp;
308 int namelen = (token>>48) & 0xff;
309 int nameoff = (token & 0xffffffff);
310
311 size = mdp->hdr.node_blk_sz / MD_ELEMENT_SIZE;
312
313 elemp = (startp == NULL) ? &(mdp->elem[0]) : startp;
314 limp = &(mdp->elem[size]);
315
316 do {
317 switch (elemp->tag) {
318 int idx;
319 case MDET_LIST_END: goto done;
320 case MDET_NODE:
321 if (ntoh32(elemp->name) == nameoff &&
322 ntoh8(elemp->namelen) == namelen) {
323 return (elemp);
324 }
325 idx = ntoh32(elemp->d.prop_idx); /* next node */
326 elemp = &(mdp->elem[idx]);
327 break;
328 case MDET_NULL:
329 elemp ++; /* skip to next element */
330 break;
331 default:
332 DBG(c_printf(
333 "Encountered elem type 0x%x in node search\n",
334 elemp->tag));
335 return (NULL);
336 }
337 } while (elemp >= mdp->elem && elemp < limp);
338
339done:;
340 return (NULL);
341}
342
343
344/*
345 * From a given element in a node, look for and follow an arc of the
346 * given token, check if the arc points to a node of the given
347 * token ... return both the arc pointer and the node pointed to if
348 * there is a match ... else return null.
349 */
350md_element_t *
351md_find_node_by_arc(bin_md_t *mdp, md_element_t *elemp,
352 uint64_t arc_token, uint64_t node_token, md_element_t **nodep)
353{
354
355 if (elemp == NULL)
356 return (NULL);
357
358again:
359 elemp = md_next_node_elem(mdp, elemp, arc_token);
360 if (elemp != NULL) {
361 md_element_t *mdep;
362 uint64_t *rawp;
363
364 mdep = &mdp->elem[ntoh64(elemp->d.prop_idx)];
365 rawp = (uint64_t *)mdep;
366
367 if (*rawp != node_token)
368 goto again;
369
370 *nodep = mdep;
371 return (elemp);
372 }
373 return (NULL);
374}
375
376
377int
378md_node_get_val(bin_md_t *mdp, md_element_t *nodep,
379 uint64_t name_token, uint64_t *valp)
380{
381 md_element_t *elemp;
382 uint64_t token;
383
384 token = MDVAL(name_token);
385
386 elemp = md_next_node_elem(mdp, nodep, token);
387 if (elemp != NULL) {
388 *valp = ntoh64(elemp->d.prop_val);
389 return (1);
390 }
391 return (0);
392}
393
394md_element_t *
395md_next_node_elem(bin_md_t *mdp, md_element_t *mdep, uint64_t token)
396{
397 while (mdep->tag != MDET_LIST_END && mdep->tag != MDET_NODE_END) {
398 uint64_t *rawp;
399
400 mdep++;
401 rawp = (uint64_t *)mdep;
402
403 if (*rawp == token)
404 return (mdep);
405 }
406
407 return (NULL);
408}
409
410
411void
412md_dump_node(bin_md_t *mdp, md_element_t *mdep)
413{
414#ifdef DEBUG
415 char *strp;
416 uint8_t *datap;
417
418 strp = (char *)&(mdp->elem[0]);
419 strp += mdp->hdr.node_blk_sz;
420 datap = (uint8_t *)(strp + mdp->hdr.name_blk_sz);
421
422 do {
423 switch (mdep->tag) {
424 case MDET_NULL: break;
425 case MDET_NODE:
426 c_printf("node %s node_0x%x {\n",
427 strp + mdep->name,
428 mdep - mdp->elem);
429 break;
430 case MDET_NODE_END:
431 c_printf("}\n");
432 return;
433 case MDET_LIST_END:
434 c_printf("}\nENDOFMD\n");
435 return;
436 case MDET_PROP_ARC:
437 c_printf("\t%s -> node_0x%x ;\n",
438 strp + mdep->name,
439 mdep->d.prop_idx);
440 break;
441 case MDET_PROP_VAL:
442 c_printf("\t%s = 0x%x ;\n",
443 strp + mdep->name,
444 mdep->d.prop_val);
445 break;
446 case MDET_PROP_STR:
447 c_printf("\t%s = 0x%x ;\n",
448 strp + mdep->name,
449 datap + mdep->d.prop_data.offset);
450 break;
451 case MDET_PROP_DAT:
452 c_printf("\t%s = { ... } /* len = 0x%x */ ;\n",
453 strp + mdep->name,
454 datap + mdep->d.prop_data.len);
455 break;
456 default:
457 c_printf("\tillegal MD tag 0x%x at elem index 0x%x\n",
458 mdep->tag,
459 mdep - mdp->elem);
460 }
461 mdep ++;
462 } while (1);
463#endif
464}