Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / common / src / res_guest.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: res_guest.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 "@(#)res_guest.c 1.6 07/06/07 SMI"
50
51#include <stdarg.h>
52#include <sys/htypes.h>
53#include <traps.h>
54#include <cache.h>
55#include <mmu.h>
56#include <sun4v/asi.h>
57#include <vdev_intr.h>
58#include <ncs.h>
59#include <cyclic.h>
60#include <support.h>
61#include <strand.h>
62#include <vcpu.h>
63#include <guest.h>
64#include <pcie.h>
65#include <vdev_ops.h>
66#include <fpga.h>
67#include <ldc.h>
68#include <config.h>
69#include <offsets.h>
70#include <hvctl.h>
71#include <md.h>
72#include <abort.h>
73#include <hypervisor.h>
74#include <proto.h>
75
76/*
77 * (re)-configuration code to handle HV guest resources
78 */
79
80static hvctl_status_t res_guest_parse_1(bin_md_t *mdp, md_element_t *guestnodep,
81 hvctl_res_error_t *fail_codep, int *fail_res_idp);
82
83static void res_guest_commit_config(guest_t *guestp);
84static void res_guest_commit_unconfig(guest_t *guestp);
85static void res_guest_commit_modify(guest_t *guestp);
86
87
88void config_a_guest_device_vino(guest_t *guestp, int ino, uint8_t type);
89void unconfig_a_guest_device_vino(guest_t *guestp, int ino, uint8_t type);
90void config_guest_virtual_device(guest_t *guestp, uint64_t cfg_handle);
91void unconfig_guest_virtual_device(guest_t *guestp);
92void config_guest_channel_device(guest_t *guestp, uint64_t cfg_handle);
93void unconfig_guest_channel_device(guest_t *guestp);
94
95void
96init_guest(int i)
97{
98 guest_t *gp;
99 hvctl_msg_t *asmsg;
100 int j;
101
102 gp = (guest_t *)config.guests;
103 gp = &(gp[i]);
104
105 /* clear out everything ! */
106 c_bzero(gp, sizeof (*gp));
107
108 gp->guestid = i;
109 gp->state = GUEST_STATE_UNCONFIGURED;
110
111 /* FIXME: remove the configp pointer */
112 gp->configp = &config;
113
114 gp->pip.vdev_cfghandle = INVALID_CFGHANDLE;
115 gp->pip.cdev_cfghandle = INVALID_CFGHANDLE;
116
117 for (j = 0; j < NUM_RA2PA_SEGMENTS; j++) {
118 init_ra2pa_segment(&(gp->ra2pa_segment[j]));
119 }
120
121 asmsg = (hvctl_msg_t *)gp->async_buf;
122 asmsg->hdr.op = HVctl_op_new_res_stat;
123
124 /* Everything else gets whacked when we (re)config the guest */
125}
126
127
128
129
130/*
131 * Guest MD support functions.
132 */
133void
134res_guest_prep()
135{
136 guest_t *gp;
137 int i;
138
139 gp = config.guests;
140
141 for (i = 0; i < NGUESTS; i++, gp++) {
142 gp->pip.res.flags = (gp->state == GUEST_STATE_UNCONFIGURED) ?
143 RESF_Noop : RESF_Unconfig;
144 }
145}
146
147
148hvctl_status_t
149res_guest_parse(bin_md_t *mdp, hvctl_res_error_t *fail_codep,
150 md_element_t **failnodepp, int *fail_res_idp)
151{
152 md_element_t *mdep;
153 uint64_t arc_token;
154 uint64_t node_token;
155 md_element_t *guest_nodep;
156
157 mdp = (bin_md_t *)config.parse_hvmd;
158
159 DBG(c_printf("\nGuest configuration:\n"));
160
161 mdep = md_find_node(mdp, NULL, MDNAME(guests));
162 if (mdep == NULL) {
163 DBG(c_printf("Missing guests node in HVMD\n"));
164 *failnodepp = NULL;
165 *fail_res_idp = 0;
166 return (HVctl_st_badmd);
167 }
168
169 arc_token = MDARC(MDNAME(fwd));
170 node_token = MDNODE(MDNAME(guest));
171
172 while (NULL != (mdep = md_find_node_by_arc(mdp, mdep, arc_token,
173 node_token, &guest_nodep))) {
174 hvctl_status_t status;
175 status = res_guest_parse_1(mdp, guest_nodep, fail_codep,
176 fail_res_idp);
177 if (status != HVctl_st_ok) {
178 *failnodepp = guest_nodep;
179 return (status);
180 }
181 }
182 return (HVctl_st_ok);
183}
184
185hvctl_status_t
186res_guest_parse_1(bin_md_t *mdp, md_element_t *guest_nodep,
187 hvctl_res_error_t *fail_codep, int *fail_res_idp)
188{
189 uint64_t resource_id, unbind, cfg_handle, base_memsize;
190 uint64_t arc_token, node_token;
191 guest_t *guestp;
192 md_element_t *mblock_nodep, *mdep, *base_mblock;
193 md_element_t *devices_nodep;
194
195 DBG(c_printf("res_guest_parse_1\n"));
196 DBG(md_dump_node(mdp, guest_nodep));
197
198 if (!md_node_get_val(mdp, guest_nodep, MDNAME(resource_id),
199 &resource_id)) {
200 DBG(c_printf("Missing resource_id in guest node\n"));
201 *fail_codep = HVctl_e_guest_missing_id;
202 *fail_res_idp = 0;
203 return (HVctl_st_badmd);
204 }
205 if (resource_id >= NGUESTS) {
206 DBG(c_printf("Invalid resource_id in guest node\n"));
207 *fail_codep = HVctl_e_guest_invalid_id;
208 *fail_res_idp = 0;
209 return (HVctl_st_badmd);
210 }
211
212 guestp = config.guests;
213 guestp = &(guestp[resource_id]);
214
215 DBG(c_printf("Guest 0x%x @ 0x%x\n", resource_id, (uint64_t)guestp));
216
217 *fail_res_idp = resource_id;
218
219 /*
220 * If guest is being unbound check that it is stopped.
221 */
222 if (!md_node_get_val(mdp, guest_nodep, MDNAME(unbind), &unbind))
223 unbind = 0;
224 if (unbind != 0) {
225 if (guestp->state != GUEST_STATE_STOPPED) {
226 *fail_codep = HVctl_e_guest_active;
227 return (HVctl_st_eillegal);
228 }
229 }
230
231 /*
232 * Now fill in basic properties for this guest ...
233 *
234 * FIXME: These should be available is the guest is
235 * live yes ?
236 */
237
238#define GET_PROPERTY(_g_val, _md_name) \
239 do { \
240 uint64_t _x; \
241 if (!md_node_get_val(mdp, guest_nodep, \
242 MDNAME(_md_name), &_x)) { \
243 DBG(c_printf("Missing "#_md_name" in " \
244 "guest node\n")); \
245 goto missing_prop; \
246 } \
247 _g_val = _x; \
248 } while (0)
249
250 /* A guest can't change ID, so just push it in */
251 GET_PROPERTY(guestp->guestid, resource_id);
252 GET_PROPERTY(guestp->pip.rom_base, rombase);
253 GET_PROPERTY(guestp->pip.rom_size, romsize);
254
255 GET_PROPERTY(guestp->pip.md_pa, mdpa);
256
257#ifdef CONFIG_CN_UART
258 if (!md_node_get_val(mdp, guest_nodep, MDNAME(uartbase),
259 &guestp->pip.uartbase)) {
260 guestp->pip.uartbase = -1LL;
261 }
262#endif
263
264#ifdef CONFIG_DISK
265 if (!md_node_get_val(mdp, guest_nodep, MDNAME(diskpa),
266 &guestp->pip.diskpa)) {
267 guestp->pip.diskpa = -1LL;
268 }
269#endif
270
271 /*
272 * Check for a reset-reason property
273 *
274 * FIXME: How sensible is this in an LDoms world?
275 * This is fine unless master start gets called somehow as
276 * part of the guest reconfig - so dont do that unless
277 * you really mean it !
278 *
279 * FIXME: Again - why re-do if guest configured already
280 */
281 if (!md_node_get_val(mdp, guest_nodep, MDNAME(reset_reason),
282 &guestp->pip.reset_reason)) {
283 guestp->pip.reset_reason = RESET_REASON_POR;
284 }
285
286 /*
287 * Determine guest realbase.
288 */
289 guestp->pip.real_base = UINT64_MAX;
290 guestp->pip.real_limit = 0;
291 guestp->pip.mem_offset = 0;
292
293 arc_token = MDARC(MDNAME(fwd));
294 node_token = MDNODE(MDNAME(mblock));
295
296 base_mblock = NULL;
297 mdep = guest_nodep;
298
299 while (NULL != (mdep = md_find_node_by_arc(mdp, mdep,
300 arc_token, node_token, &mblock_nodep))) {
301 uint64_t realbase, membase;
302 if (!md_node_get_val(mdp, mblock_nodep, MDNAME(realbase),
303 &realbase)) {
304 DBG(c_printf("Missing realbase in mblock node\n"));
305 goto missing_prop;
306 }
307
308 /*
309 * Initialise guest real_base, real_limit and mem_offset
310 * Note: real_limit/mem_offset are required for N2 MMu HWTW
311 * FIXME: real_limit will not work for segmented memory
312 */
313 if (realbase < guestp->pip.real_base) {
314 guestp->pip.real_base = realbase;
315 base_mblock = mblock_nodep;
316 if (!md_node_get_val(mdp, mblock_nodep, MDNAME(membase),
317 &membase)) {
318 membase = guestp->pip.real_base;
319 }
320 guestp->pip.mem_offset = membase -
321 guestp->pip.real_base;
322 }
323 if (!md_node_get_val(mdp, base_mblock, MDNAME(memsize),
324 &base_memsize)) {
325 base_memsize = 0;
326 }
327 if (guestp->pip.real_limit < (realbase + base_memsize))
328 guestp->pip.real_limit = (realbase + base_memsize);
329 }
330
331 if (base_mblock == NULL) {
332 DBG(c_printf("Missing mblock node in guest node\n"));
333 goto missing_prop;
334 }
335
336 if (!md_node_get_val(mdp, base_mblock, MDNAME(memsize),
337 &base_memsize)) {
338 DBG(c_printf("Missing memsize in mblock node\n"));
339 goto missing_prop;
340 }
341
342 if (guestp->pip.rom_size > base_memsize) {
343 *fail_codep = HVctl_e_guest_base_mblock_too_small;
344 return (HVctl_st_badmd);
345 }
346
347#undef GET_PROPERTY
348
349
350 /*
351 * Look for the "perfctraccess" property. This property
352 * must be present and set to a non-zero value for the
353 * guest to have access to the JBUS/DRAM perf counters
354 */
355
356 /*
357 * FIXME; These probably need to be their own resource !
358 */
359
360 if (!md_node_get_val(mdp, guest_nodep, MDNAME(perfctraccess),
361 &guestp->pip.perfreg_accessible)) {
362 guestp->pip.perfreg_accessible = 0;
363 }
364
365 /*
366 * Look for "diagpriv" property. This property enables
367 * the guest to execute arbitrary hyperprivileged code.
368 */
369 if (!md_node_get_val(mdp, guest_nodep, MDNAME(diagpriv),
370 &guestp->pip.diagpriv)) {
371#ifdef CONFIG_BRINGUP
372 guestp->pip.diagpriv = -1;
373#else
374 guestp->pip.diagpriv = 0;
375#endif
376 }
377
378 /*
379 * Look for "rngctlaccessible" property. This property enables
380 * the guest to access the N2 RNG if available.
381 */
382 if (!md_node_get_val(mdp, guest_nodep, MDNAME(rngctlaccessible),
383 &guestp->rng_ctl_accessible)) {
384 guestp->rng_ctl_accessible = 0;
385 }
386
387 /*
388 * Look for "perfctrhtaccess" property. This property enables
389 * the guest to access the N2 hyper-privileged events if available.
390 */
391 if (!md_node_get_val(mdp, guest_nodep, MDNAME(perfctrhtaccess),
392 &guestp->perfreght_accessible)) {
393 guestp->perfreght_accessible = 0;
394 }
395
396 /*
397 * Per guest TOD offset ...
398 * FIXME:
399 * This property doesn't trigger a modify op if the guest is already
400 * live. So changes are only visible after a reconfig when the
401 * domain is stopped.
402 */
403 if (!md_node_get_val(mdp, guest_nodep, MDNAME(todoffset),
404 &guestp->pip.tod_offset)) {
405 guestp->pip.tod_offset = 0;
406 }
407
408 /*
409 * Now look for the guest devices ...
410 * FIXME: Needs updating so devices can be DR'd in.
411 */
412
413 if (NULL != md_find_node_by_arc(mdp, guest_nodep, MDARC(MDNAME(fwd)),
414 MDNODE(MDNAME(virtual_devices)), &devices_nodep)) {
415 if (!md_node_get_val(mdp, devices_nodep, MDNAME(cfghandle),
416 &cfg_handle)) {
417 DBG(c_printf("Missing cfg_handle in device node\n"));
418 goto missing_prop;
419 }
420 DBG(md_dump_node(mdp, devices_nodep));
421 guestp->pip.vdev_cfghandle = cfg_handle;
422 }
423
424 if (NULL != md_find_node_by_arc(mdp, guest_nodep, MDARC(MDNAME(fwd)),
425 MDNODE(MDNAME(channel_devices)), &devices_nodep)) {
426 if (!md_node_get_val(mdp, devices_nodep, MDNAME(cfghandle),
427 &cfg_handle)) {
428 DBG(c_printf("Missing cfg_handle in device node\n"));
429 goto missing_prop;
430 }
431 DBG(md_dump_node(mdp, devices_nodep));
432 guestp->pip.cdev_cfghandle = cfg_handle;
433 }
434 DBG(c_printf("End of guest parse 1\n"));
435
436 /*
437 * Now we go and figureout what we need to do to the
438 * guest to update or configure its state.
439 *
440 * Memory was dealt with earlier.
441 */
442 if (guestp->state == GUEST_STATE_UNCONFIGURED) {
443 DBG(c_printf("\t\tElected to config guest\n"));
444 guestp->pip.res.flags = RESF_Config;
445 } else {
446 /*
447 * what kind of a re-configure is this ?
448 * Since guest structures dont really bind to anything, stuff
449 * binds to them, this is a modify IMHO, but only if stuff
450 * actually got modified ..
451 *
452 * Note: it is implicit in this test that an MD update
453 * *requires* that the mdpa changes. Since the prospect of
454 * and MD update inplace while the guest is running is
455 * frightening and likely to break the guest this is a
456 * suffient condion. If Zeus updates the MD in place we
457 * have really big problems on our hands .. not sure we
458 * can detect this easily.
459 *
460 * We ignore dynamic updates of uartbase and diskpa
461 * since they should be detected above and denied if the
462 * the domain is running.
463 */
464
465 if (guestp->pip.rom_base != guestp->rom_base ||
466 guestp->pip.rom_size != guestp->rom_size ||
467 guestp->pip.md_pa != guestp->md_pa ||
468 guestp->pip.reset_reason != guestp->reset_reason ||
469 guestp->pip.perfreg_accessible !=
470 guestp->perfreg_accessible ||
471 guestp->pip.diagpriv != guestp->diagpriv ||
472 ((guestp->pip.vdev_cfghandle != INVALID_CFGHANDLE) &&
473 (guestp->pip.vdev_cfghandle != guestp->vdev_cfghandle)) ||
474 ((guestp->pip.cdev_cfghandle != INVALID_CFGHANDLE) &&
475 (guestp->pip.cdev_cfghandle != guestp->cdev_cfghandle)) ||
476 guestp->pip.tod_offset != guestp->tod_offset) {
477 DBG(c_printf("\t\tElected to modify guest\n"));
478 guestp->pip.res.flags = RESF_Modify;
479 } else {
480 guestp->pip.res.flags = RESF_Noop;
481 DBG(c_printf("\t\tElected to ignore guest\n"));
482 }
483 }
484
485 return (HVctl_st_ok);
486
487missing_prop:;
488 *fail_codep = HVctl_e_guest_missing_property;
489 return (HVctl_st_badmd);
490}
491
492
493 /*
494 * Simple suite of checks based on the flags for this resource
495 */
496
497hvctl_status_t
498res_guest_postparse(hvctl_res_error_t *fail_codep, int *fail_res_idp)
499{
500 guest_t *gp;
501 int i;
502
503 gp = config.guests;
504
505 for (i = 0; i < NGUESTS; i++, gp++) {
506 switch (gp->pip.res.flags) {
507 case RESF_Noop:
508 break;
509 case RESF_Unconfig:
510 if (gp->state != GUEST_STATE_STOPPED) {
511 *fail_codep = HVctl_e_guest_active;
512 goto fail;
513 }
514 break;
515 case RESF_Config:
516 break;
517 case RESF_Rebind:
518 ASSERT(0); /* not supported */
519 break;
520 case RESF_Modify:
521 break;
522 default:
523 ASSERT(0);
524 }
525 }
526 return (HVctl_st_ok);
527
528fail:
529 *fail_res_idp = i;
530 return (HVctl_st_badmd);
531}
532
533
534
535
536void
537res_guest_commit(int flag)
538{
539 guest_t *gp;
540 int i;
541
542 gp = config.guests;
543
544 for (i = 0; i < NGUESTS; i++, gp++) {
545 /* if not this ops turn move on */
546 if (gp->pip.res.flags != flag) continue;
547
548 switch (gp->pip.res.flags) {
549 case RESF_Noop:
550 DBG(c_printf("guest 0x%x : noop\n", i));
551 break;
552 case RESF_Unconfig:
553 res_guest_commit_unconfig(gp);
554 break;
555 case RESF_Config:
556 res_guest_commit_config(gp);
557 break;
558 case RESF_Rebind:
559 DBG(c_printf("guest 0x%x : rebind\n", i));
560 ASSERT(0); /* not supported */
561 break;
562 case RESF_Modify:
563 res_guest_commit_modify(gp);
564 break;
565 default:
566 ASSERT(0);
567 }
568
569 gp->pip.res.flags = RESF_Noop; /* cleanup */
570 }
571}
572
573
574void
575reset_guest_state(guest_t *guestp)
576{
577 ASSERT(guestp->state == GUEST_STATE_STOPPED);
578
579 reset_api_hcall_table(guestp);
580 DBG(c_printf("\tguest hcall table @ 0x%x\n", guestp->hcall_table));
581
582 reset_guest_perm_mappings(guestp);
583
584 reset_guest_ldc_mapins(guestp);
585}
586
587
588/*
589 * reconfigure common path - also shared with commit
590 */
591void
592res_guest_commit_modify(guest_t *guestp)
593{
594 DBG(c_printf("modify guest 0x%x\n", guestp->guestid));
595 ASSERT(guestp->state != GUEST_STATE_UNCONFIGURED);
596
597 guestp->rom_base = guestp->pip.rom_base;
598 guestp->rom_size = guestp->pip.rom_size;
599 guestp->real_base = guestp->pip.real_base;
600 guestp->real_limit = guestp->pip.real_limit;
601 guestp->mem_offset = guestp->pip.mem_offset;
602
603 guestp->md_pa = guestp->pip.md_pa;
604 /*
605 * Compute the Guests MD size
606 */
607 config_guest_md(guestp);
608
609
610#ifdef CONFIG_DISK
611 guestp->disk.size = 0LL;
612 guestp->disk.pa = guestp->pip.diskpa;
613#endif
614
615#ifdef T1_FPGA_SNET
616 guestp->snet.ino = guestp->pip.snet_ino;
617 guestp->snet.pa = guestp->pip.snet_pa;
618#endif
619
620 /*
621 * Look for the "perfctraccess" property. This property
622 * must be present and set to a non-zero value for the
623 * guest to have access to the JBUS/DRAM perf counters
624 */
625 guestp->perfreg_accessible = guestp->pip.perfreg_accessible;
626
627 /*
628 * Look for "diagpriv" property. This property enables
629 * the guest to execute arbitrary hyperprivileged code.
630 */
631 guestp->diagpriv = guestp->pip.diagpriv;
632
633 /*
634 * Assume entry point is at base of real memory
635 */
636 guestp->entry = guestp->real_base;
637 guestp->reset_reason = guestp->pip.reset_reason;
638
639 /*
640 * Modify devops.
641 */
642 unconfig_guest_virtual_device(guestp);
643 unconfig_guest_channel_device(guestp);
644 config_guest_virtual_device(guestp, guestp->pip.vdev_cfghandle);
645 config_guest_channel_device(guestp, guestp->pip.cdev_cfghandle);
646
647}
648
649
650void
651res_guest_commit_config(guest_t *guestp)
652{
653 int x;
654
655 DBG(c_printf("commit config guest 0x%x : config\n", guestp->guestid));
656 ASSERT(guestp->state == GUEST_STATE_UNCONFIGURED);
657
658 /*
659 * Now fill in basic properties for this guest ...
660 *
661 * FIXME: These should be available if the guest is
662 * live yes ?
663 */
664 guestp->ldc_mapin_basera = LDC_MAPIN_BASERA;
665 guestp->ldc_mapin_size = LDC_MAPIN_RASIZE;
666
667 guestp->state = GUEST_STATE_STOPPED;
668 res_guest_commit_modify(guestp);
669
670 /*
671 * TOD is configured once at the begining of time.
672 * we don't allow external modifies as that would warp
673 * the time value each time the guest gets and update
674 * after the guest had modified itself.
675 */
676 guestp->tod_offset = guestp->pip.tod_offset;
677
678 /*
679 * At the time of first guest config mark all INO2LDC
680 * mappings as NULL
681 */
682 for (x = 0; x < MAX_LDC_INOS; x++) {
683 guestp->ldc_ino2endpoint[x].endpointp = NULL;
684 guestp->ldc_ino2endpoint[x].mapregp = NULL;
685 }
686
687 /*
688 * FIXME: Should we really care to track this - why not
689 * just use the constant; MAX_LDC_CHANNELS
690 */
691 guestp->ldc_max_channel_idx = MAX_LDC_CHANNELS;
692 /* we might check that all the LDC endpoints are !live */
693 /* kind of pointless since we are moving them to a global */
694
695
696 /*
697 * clear out the devops table.
698 */
699 for (int y = 0; y < NVINOS; y++) {
700 guestp->vino2inst.vino[y] = DEVOPS_RESERVED;
701 }
702
703 for (int x = 0; x < NDEVIDS; x++) {
704 guestp->dev2inst[x] = DEVOPS_RESERVED;
705 }
706
707 config_guest_virtual_device(guestp, guestp->pip.vdev_cfghandle);
708 config_guest_channel_device(guestp, guestp->pip.cdev_cfghandle);
709
710
711 /* until we boot it ... */
712 ASSERT(guestp->state == GUEST_STATE_STOPPED);
713 reset_guest_state(guestp);
714
715
716 DBG(c_printf("End of guest setup\n"));
717}
718
719
720void
721res_guest_commit_unconfig(guest_t *guestp)
722{
723 /* preserve the guest ID ... err thats about it */
724
725 DBG(c_printf("guest 0x%x : unconfig\n", guestp->guestid));
726
727 ASSERT(guestp->state == GUEST_STATE_STOPPED);
728
729 unconfig_guest_virtual_device(guestp);
730 unconfig_guest_channel_device(guestp);
731 /*
732 * clear out the devops table.
733 */
734 for (int y = 0; y < NVINOS; y++) {
735 guestp->vino2inst.vino[y] = DEVOPS_RESERVED;
736 }
737
738 for (int x = 0; x < NDEVIDS; x++) {
739 guestp->dev2inst[x] = DEVOPS_RESERVED;
740 }
741
742
743 init_guest(guestp->guestid);
744
745 /* Just incase we add more phases */
746 guestp->pip.res.flags = RESF_Noop;
747}
748
749void
750config_a_guest_device_vino(guest_t *guestp, int ino, uint8_t type)
751{
752 uint64_t cfg_handle = INVALID_CFGHANDLE;
753
754 switch (type) {
755 case DEVOPS_VDEV:
756 cfg_handle = guestp->vdev_cfghandle;
757 break;
758 case DEVOPS_CDEV:
759 cfg_handle = guestp->cdev_cfghandle;
760 break;
761 default:
762 break;
763 };
764
765 DBG(c_printf("guest device:\n\tcfg handle 0x%x 0x%x\n",
766 cfg_handle, ino));
767 ASSERT(cfg_handle != INVALID_CFGHANDLE);
768 guestp->vino2inst.vino[cfg_handle + ino] = type;
769
770}
771
772void
773unconfig_a_guest_device_vino(guest_t *guestp, int ino, uint8_t type)
774{
775 uint64_t cfg_handle = INVALID_CFGHANDLE;
776
777 switch (type) {
778 case DEVOPS_VDEV:
779 cfg_handle = guestp->vdev_cfghandle;
780 break;
781 case DEVOPS_CDEV:
782 cfg_handle = guestp->cdev_cfghandle;
783 break;
784 default:
785 break;
786 };
787
788 ASSERT(cfg_handle != INVALID_CFGHANDLE);
789 guestp->vino2inst.vino[cfg_handle + ino] = DEVOPS_RESERVED;
790
791}
792
793void
794config_guest_virtual_device(guest_t *guestp, uint64_t cfg_handle)
795{
796 uint8_t devid;
797
798 ASSERT(cfg_handle != INVALID_CFGHANDLE);
799 if (cfg_handle == INVALID_CFGHANDLE)
800 return;
801
802 guestp->vdev_cfghandle = cfg_handle;
803
804 devid = guestp->vdev_cfghandle >> DEVCFGPA_SHIFT;
805 guestp->dev2inst[devid] = DEVOPS_VDEV;
806}
807
808void
809unconfig_guest_virtual_device(guest_t *guestp)
810{
811 uint8_t devid;
812
813 devid = guestp->vdev_cfghandle >> DEVCFGPA_SHIFT;
814 guestp->dev2inst[devid] = DEVOPS_RESERVED;
815
816 guestp->vdev_cfghandle = INVALID_CFGHANDLE;
817
818}
819
820void
821config_guest_channel_device(guest_t *guestp, uint64_t cfg_handle)
822{
823 uint8_t devid, edevid;
824 int x;
825
826 ASSERT(cfg_handle != INVALID_CFGHANDLE);
827 if (cfg_handle == INVALID_CFGHANDLE)
828 return;
829
830 guestp->cdev_cfghandle = cfg_handle;
831
832 devid = guestp->cdev_cfghandle >> DEVCFGPA_SHIFT;
833 edevid = (guestp->cdev_cfghandle + MAX_LDC_INOS) >> DEVCFGPA_SHIFT;
834
835 for (x = devid; x < edevid; x++)
836 guestp->dev2inst[x] = DEVOPS_CDEV;
837
838}
839
840void
841unconfig_guest_channel_device(guest_t *guestp)
842{
843 uint8_t devid, edevid;
844 int x;
845
846 devid = guestp->cdev_cfghandle >> DEVCFGPA_SHIFT;
847 edevid = (guestp->cdev_cfghandle + MAX_LDC_INOS) >> DEVCFGPA_SHIFT;
848
849 for (x = devid; x < edevid; x++)
850 guestp->dev2inst[x] = DEVOPS_RESERVED;
851
852 guestp->cdev_cfghandle = INVALID_CFGHANDLE;
853
854}