Commit | Line | Data |
---|---|---|
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 | ||
72 | struct { | |
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 | ||
199 | void | |
200 | reloc_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 | ||
214 | hvctl_status_t | |
215 | preparse_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 | */ | |
245 | void | |
246 | accept_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 | */ | |
256 | uint64_t | |
257 | md_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 | } | |
293 | miss:; | |
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 | ||
302 | md_element_t * | |
303 | md_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 | ||
339 | done:; | |
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 | */ | |
350 | md_element_t * | |
351 | md_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 | ||
358 | again: | |
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 | ||
377 | int | |
378 | md_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 | ||
394 | md_element_t * | |
395 | md_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 | ||
411 | void | |
412 | md_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 | } |