Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: svc_vbsc.s | |
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 | .ident "@(#)svc_vbsc.s 1.28 07/05/29 SMI" | |
50 | ||
51 | .file "svc_vbsc.s" | |
52 | ||
53 | #if defined(CONFIG_SVC) && defined(CONFIG_VBSC_SVC) | |
54 | ||
55 | #include <sys/asm_linkage.h> | |
56 | #include <sys/htypes.h> | |
57 | #include <hypervisor.h> | |
58 | #include <sparcv9/misc.h> | |
59 | #include <asi.h> | |
60 | #include <mmu.h> | |
61 | #include <fpga.h> | |
62 | #include <sun4v/traps.h> | |
63 | #include <sun4v/asi.h> | |
64 | #include <sun4v/mmu.h> | |
65 | #include <sun4v/errs_defs.h> | |
66 | ||
67 | #include <config.h> | |
68 | #include <guest.h> | |
69 | #include <strand.h> | |
70 | #include <offsets.h> | |
71 | #include <svc.h> | |
72 | #include <svc_vbsc.h> | |
73 | #include <errs_common.h> | |
74 | #include <util.h> | |
75 | #include <abort.h> | |
76 | #include <debug.h> | |
77 | ||
78 | /* | |
79 | * vbsc_send_polled - send a command to vbsc using polled I/O | |
80 | * | |
81 | * If VBSC does not accept the packet then | |
82 | * | |
83 | * %g1 - cmd[0] | |
84 | * %g2 - cmd[1] | |
85 | * %g3 - cmd[2] | |
86 | * %g7 - return address | |
87 | */ | |
88 | ENTRY_NP(vbsc_send_polled) | |
89 | .vbsc_send_polled_resend: | |
90 | setx FPGA_Q3OUT_BASE, %g4, %g5 | |
91 | setx FPGA_BASE + FPGA_SRAM_BASE, %g4, %g6 | |
92 | ||
93 | lduh [%g5 + FPGA_Q_BASE], %g4 | |
94 | add %g4, %g6, %g6 | |
95 | !! %g6 = sram buffer words | |
96 | ||
97 | stx %g3, [%g6 + (2 * 8)] | |
98 | stx %g2, [%g6 + (1 * 8)] | |
99 | stx %g1, [%g6 + (0 * 8)] | |
100 | mov 1, %g4 | |
101 | stb %g4, [%g5 + FPGA_Q_SEND] | |
102 | ||
103 | /* | |
104 | * Wait for a non-zero status. If we get an ACK then we're done. | |
105 | * Otherwise re-send the packet. Failure is not an option, even | |
106 | * to hv_abort we need to send a message to vbsc. So keep trying. | |
107 | */ | |
108 | .vbsc_send_polled_wait_for_ack: | |
109 | ldub [%g5 + FPGA_Q_STATUS], %g4 | |
110 | andcc %g4, (QINTR_ACK | QINTR_NACK | QINTR_BUSY | QINTR_ABORT), %g4 | |
111 | bz,pn %xcc, .vbsc_send_polled_wait_for_ack | |
112 | nop | |
113 | btst QINTR_ACK, %g4 | |
114 | bz,pt %xcc, .vbsc_send_polled_resend | |
115 | nop | |
116 | ||
117 | stb %g4, [%g5 + FPGA_Q_STATUS] ! clear status bits | |
118 | HVRET | |
119 | SET_SIZE(vbsc_send_polled) | |
120 | ||
121 | ||
122 | /* | |
123 | * vbsc_hv_start - notify VBSC that the hypervisor has started | |
124 | * | |
125 | * %g7 return address | |
126 | * | |
127 | * Called from setup environment | |
128 | */ | |
129 | ENTRY_NP(vbsc_hv_start) | |
130 | mov %g7, %o3 | |
131 | ||
132 | setx VBSC_HV_START, %g2, %g1 | |
133 | mov 0, %g2 | |
134 | mov 0, %g3 | |
135 | HVCALL(vbsc_send_polled) | |
136 | ||
137 | mov %o3, %g7 | |
138 | HVRET | |
139 | SET_SIZE(vbsc_hv_start) | |
140 | ||
141 | ||
142 | /* | |
143 | * vbsc_hv_abort - notify VBSC that hv has aborted | |
144 | * | |
145 | * %g1 contains reason for the abort | |
146 | * %g7 return address | |
147 | */ | |
148 | ENTRY_NP(vbsc_hv_abort) | |
149 | mov %g1, %g2 | |
150 | setx VBSC_HV_ABORT, %g3, %g1 | |
151 | mov 0, %g3 | |
152 | HVCALL(vbsc_send_polled) | |
153 | ||
154 | /* spin until the vbsc powers us down */ | |
155 | ba . | |
156 | nop | |
157 | SET_SIZE(vbsc_hv_abort) | |
158 | ||
159 | ||
160 | /* | |
161 | * vbsc_hv_plxreset - notify VBSC that the hypervisor has requested | |
162 | * a special reset due to PLX link training problems. VBSC knows to | |
163 | * do this quietly and prevent it from looping forever. | |
164 | * | |
165 | * %g1 plx link failure bitmask | |
166 | * %g7 return address | |
167 | * | |
168 | * Called from setup environment | |
169 | */ | |
170 | ENTRY_NP(vbsc_hv_plxreset) | |
171 | mov %g7, %o3 | |
172 | ||
173 | mov %g1, %g2 | |
174 | setx VBSC_HV_PLXRESET, %g3, %g1 | |
175 | mov 0, %g3 | |
176 | HVCALL(vbsc_send_polled) | |
177 | ||
178 | mov %o3, %g7 | |
179 | HVRET | |
180 | SET_SIZE(vbsc_hv_plxreset) | |
181 | ||
182 | ||
183 | /* | |
184 | * vbsc_guest_start - notify VBSC that a guest has started | |
185 | * | |
186 | * %g7 return address | |
187 | */ | |
188 | ENTRY_NP(vbsc_guest_start) | |
189 | mov %g7, %o3 | |
190 | ||
191 | setx VBSC_GUEST_ON, %g2, %g1 | |
192 | GUEST_STRUCT(%o2) | |
193 | set GUEST_GID, %o4 | |
194 | ldx [%o2 + %o4], %g2 | |
195 | add %g2, XPID_GUESTBASE, %g2 | |
196 | mov 0, %g3 | |
197 | HVCALL(vbsc_send_polled) | |
198 | ||
199 | mov %o3, %g7 | |
200 | HVRET | |
201 | SET_SIZE(vbsc_guest_start) | |
202 | ||
203 | ||
204 | /* | |
205 | * vbsc_guest_exit - notify VBSC that a guest has exited | |
206 | * | |
207 | * arg0 exit code (%o0) | |
208 | * -- | |
209 | * does not return | |
210 | */ | |
211 | ENTRY_NP(vbsc_guest_exit) | |
212 | setx VBSC_GUEST_OFF, %g2, %g1 | |
213 | GUEST_STRUCT(%o2) | |
214 | set GUEST_GID, %o4 | |
215 | ldx [%o2 + %o4], %g2 | |
216 | add %g2, XPID_GUESTBASE, %g2 | |
217 | ldx [%o2 + GUEST_TOD_OFFSET], %g3 | |
218 | HVCALL(vbsc_send_polled) | |
219 | ||
220 | /* spin until the vbsc powers us down */ | |
221 | ba . | |
222 | nop | |
223 | SET_SIZE(vbsc_guest_exit) | |
224 | ||
225 | ||
226 | /* | |
227 | * vbsc_guest_sir - notify vbsc that a guest requested a reset | |
228 | * | |
229 | * -- | |
230 | * does not return | |
231 | */ | |
232 | ENTRY_NP(vbsc_guest_sir) | |
233 | setx VBSC_GUEST_RESET, %g2, %g1 | |
234 | GUEST_STRUCT(%o2) | |
235 | set GUEST_GID, %o4 | |
236 | ldx [%o2 + %o4], %g2 | |
237 | add %g2, XPID_GUESTBASE, %g2 | |
238 | ldx [%o2 + GUEST_TOD_OFFSET], %g3 | |
239 | HVCALL(vbsc_send_polled) | |
240 | ||
241 | /* spin until the vbsc powers us down */ | |
242 | ba . | |
243 | nop | |
244 | SET_SIZE(vbsc_guest_sir) | |
245 | ||
246 | /* | |
247 | * vbsc_guest_wdexpire - notify vbsc that a guest's watchdog timer expired | |
248 | * Service Processor policy dictates what happens next. | |
249 | * | |
250 | * %g1: guestp | |
251 | * %g7: return address | |
252 | * -- | |
253 | */ | |
254 | ENTRY_NP(vbsc_guest_wdexpire) | |
255 | mov %g1, %g6 | |
256 | setx VBSC_GUEST_WDEXPIRE, %g2, %g1 | |
257 | set GUEST_GID, %g5 | |
258 | ldx [%g6 + %g5], %g2 | |
259 | add %g2, XPID_GUESTBASE, %g2 | |
260 | ldx [%g6 + GUEST_TOD_OFFSET], %g3 | |
261 | ba,a vbsc_send_polled ! tail call, returns to caller | |
262 | SET_SIZE(vbsc_guest_wdexpire) | |
263 | ||
264 | ||
265 | /* | |
266 | * vbsc_guest_tod_offset - notify VBSC of a guest's TOD offset | |
267 | * We don't retry here, failures are ignored. | |
268 | * | |
269 | * %g1 guestp | |
270 | * %g7 return address | |
271 | * | |
272 | * Clobbers %g1-6 | |
273 | * Called from guest hcall environment | |
274 | */ | |
275 | ||
276 | /* FIXME: Use a better buffer to send from ... */ | |
277 | /* Better yet this function / operation goes away entirely for LDoms */ | |
278 | ||
279 | ENTRY_NP(vbsc_guest_tod_offset) | |
280 | VCPU_STRUCT(%g2) | |
281 | inc CPU_SCR0, %g2 | |
282 | ||
283 | set GUEST_GID, %g3 | |
284 | ldx [%g1 + %g3], %g3 | |
285 | add %g3, XPID_GUESTBASE, %g3 | |
286 | stx %g3, [%g2 + 0x8] | |
287 | ||
288 | ldx [%g1 + GUEST_TOD_OFFSET], %g3 | |
289 | stx %g3, [%g2 + 0x10] | |
290 | ||
291 | setx VBSC_GUEST_TODOFFSET, %g4, %g3 | |
292 | stx %g3, [%g2 + 0x0] | |
293 | ||
294 | ROOT_STRUCT(%g1) | |
295 | ldx [%g1 + CONFIG_VBSC_SVCH], %g1 | |
296 | ||
297 | mov 8 * 3, %g3 | |
298 | ||
299 | !! %g1 svch | |
300 | !! %g2 buf | |
301 | !! %g3 length | |
302 | ba,pt %xcc, svc_internal_send ! tail call, returns to caller | |
303 | nop | |
304 | SET_SIZE(vbsc_guest_tod_offset) | |
305 | ||
306 | ||
307 | ||
308 | #define SIM_IRU_DIAG_ERPT(erpt_vbsc, reg1, reg2) \ | |
309 | set ERPT_TYPE_CPU, reg1 ;\ | |
310 | stx reg1, [erpt_vbsc + EVBSC_REPORT_TYPE] ;\ | |
311 | setx 0x10000000000001, reg2, reg1 ;\ | |
312 | stx reg1, [erpt_vbsc + EVBSC_EHDL] ;\ | |
313 | setx 0x002a372a4, reg2, reg1 ;\ | |
314 | stx reg1, [erpt_vbsc + EVBSC_STICK] ;\ | |
315 | setx 0x3e002310000607, reg2, reg1 ;\ | |
316 | stx reg1, [erpt_vbsc + EVBSC_CPUVER] ;\ | |
317 | setx 0x000000000, reg2, reg1 ;\ | |
318 | stx reg1, [erpt_vbsc + EVBSC_CPUSERIAL] ;\ | |
319 | setx 0x000010000, reg2, reg1 ;\ | |
320 | stx reg1, [erpt_vbsc + EVBSC_SPARC_AFSR] ;\ | |
321 | setx 0x000830550, reg2, reg1 ;\ | |
322 | stx reg1, [erpt_vbsc + EVBSC_SPARC_AFAR] ;\ | |
323 | setx 0x400000402, reg2, reg1 ;\ | |
324 | stx reg1, [erpt_vbsc + EVBSC_TSTATE] ;\ | |
325 | setx 0x000000800, reg2, reg1 ;\ | |
326 | stx reg1, [erpt_vbsc + EVBSC_HTSTATE] ;\ | |
327 | setx 0x000800610, reg2, reg1 ;\ | |
328 | stx reg1, [erpt_vbsc + EVBSC_TPC] ;\ | |
329 | set 0x0, reg1 ;\ | |
330 | stuh reg1, [erpt_vbsc + EVBSC_CPUID] ;\ | |
331 | set 0x63, reg1 ;\ | |
332 | stuh reg1, [erpt_vbsc + EVBSC_TT] ;\ | |
333 | set 0x1, reg1 ;\ | |
334 | stub reg1, [erpt_vbsc + EVBSC_TL] ;\ | |
335 | set 0x3, reg1 ;\ | |
336 | stub reg1, [erpt_vbsc + EVBSC_ERREN] | |
337 | ||
338 | #define SIM_IRC_DIAG_ERPT(erpt_vbsc, reg1, reg2) \ | |
339 | set ERPT_TYPE_CPU, reg1 ;\ | |
340 | stx reg1, [erpt_vbsc + EVBSC_REPORT_TYPE] ;\ | |
341 | setx 0x10000000000002, reg2, reg1 ;\ | |
342 | stx reg1, [erpt_vbsc + EVBSC_EHDL] ;\ | |
343 | setx 0x002a372a4, reg2, reg1 ;\ | |
344 | stx reg1, [erpt_vbsc + EVBSC_STICK] ;\ | |
345 | setx 0x3e002310000607, reg2, reg1 ;\ | |
346 | stx reg1, [erpt_vbsc + EVBSC_CPUVER] ;\ | |
347 | setx 0x000000000, reg2, reg1 ;\ | |
348 | stx reg1, [erpt_vbsc + EVBSC_CPUSERIAL] ;\ | |
349 | setx 0x000020000, reg2, reg1 ;\ | |
350 | stx reg1, [erpt_vbsc + EVBSC_SPARC_AFSR] ;\ | |
351 | setx 0x000830550, reg2, reg1 ;\ | |
352 | stx reg1, [erpt_vbsc + EVBSC_SPARC_AFAR] ;\ | |
353 | setx 0x400000402, reg2, reg1 ;\ | |
354 | stx reg1, [erpt_vbsc + EVBSC_TSTATE] ;\ | |
355 | setx 0x000000800, reg2, reg1 ;\ | |
356 | stx reg1, [erpt_vbsc + EVBSC_HTSTATE] ;\ | |
357 | setx 0x000800610, reg2, reg1 ;\ | |
358 | stx reg1, [erpt_vbsc + EVBSC_TPC] ;\ | |
359 | set 0x0, reg1 ;\ | |
360 | stuh reg1, [erpt_vbsc + EVBSC_CPUID] ;\ | |
361 | set 0x63, reg1 ;\ | |
362 | stuh reg1, [erpt_vbsc + EVBSC_TT] ;\ | |
363 | set 0x1, reg1 ;\ | |
364 | stub reg1, [erpt_vbsc + EVBSC_TL] ;\ | |
365 | set 0x3, reg1 ;\ | |
366 | stub reg1, [erpt_vbsc + EVBSC_ERREN] | |
367 | ||
368 | ||
369 | /* | |
370 | * vbsc_rx | |
371 | * | |
372 | * %g1 callback cookie (guest struct?XXX) | |
373 | * %g2 svc pointer | |
374 | * %g7 return address | |
375 | */ | |
376 | ENTRY(vbsc_rx) | |
377 | ROOT_STRUCT(%g1) | |
378 | ldx [%g1 + CONFIG_VBSC_SVCH], %g1 | |
379 | ||
380 | mov %g7, %g6 | |
381 | PRINT("vbsc_rx: "); PRINTX(%g1); PRINT("\r\n"); | |
382 | mov %g6, %g7 | |
383 | ||
384 | /* | |
385 | * We don't defer packets so clear the recv pending flag. | |
386 | * This is called on the cpu handling the interrupts so | |
387 | * the contents of the buffer will not get clobbered until | |
388 | * we return. | |
389 | */ | |
390 | ld [%g2 + SVC_CTRL_STATE], %g3 | |
391 | andn %g3, SVC_FLAGS_RI, %g3 | |
392 | st %g3, [%g2 + SVC_CTRL_STATE] ! clear RECV pending | |
393 | ||
394 | ldx [%g2 + SVC_CTRL_RECV + SVC_LINK_PA], %g2 | |
395 | inc SVC_PKT_SIZE, %g2 ! skip the header | |
396 | ||
397 | /* | |
398 | * Dispatch command | |
399 | */ | |
400 | ldub [%g2 + 6], %g4 | |
401 | cmp %g4, VBSC_CMD_GUEST_STATE | |
402 | be,pn %xcc, gueststatecmd | |
403 | cmp %g4, VBSC_CMD_HV | |
404 | be,pn %xcc, hvcmd | |
405 | cmp %g4, VBSC_CMD_READMEM | |
406 | be,pn %xcc, dbgrd | |
407 | cmp %g4, VBSC_CMD_WRITEMEM | |
408 | be,pn %xcc, dbgwr | |
409 | cmp %g4, VBSC_CMD_SENDERR | |
410 | be,pn %xcc, dbg_send_error | |
411 | nop | |
412 | vbsc_rx_finished: | |
413 | HVRET | |
414 | ||
415 | ||
416 | /* | |
417 | * hvcmd - Hypervisor Command | |
418 | */ | |
419 | hvcmd: | |
420 | ldub [%g2 + 7], %g4 | |
421 | cmp %g4, 'I' | |
422 | be,pn %xcc, hvcmd_ping | |
423 | nop | |
424 | ba,a vbsc_rx_finished | |
425 | ||
426 | /* | |
427 | * hvcmd_ping - nop, just respond | |
428 | */ | |
429 | hvcmd_ping: | |
430 | /* FIXME: find better scratch buffer */ | |
431 | VCPU_STRUCT(%g2) | |
432 | inc CPU_SCR0, %g2 | |
433 | setx VBSC_ACK(VBSC_CMD_HV, 'I'), %g4, %g3 | |
434 | stx %g3, [%g2 + 0x0] | |
435 | rdpr %tpc, %g3 | |
436 | st %g3, [%g2 + 0xc] | |
437 | srlx %g3, 32, %g3 | |
438 | st %g3, [%g2 + 0x8] | |
439 | ba,pt %xcc, svc_internal_send ! returns to caller!!!! | |
440 | mov 16, %g3 ! len | |
441 | ||
442 | /* | |
443 | * gueststatecmd - Request from VBSC to change guest state | |
444 | */ | |
445 | gueststatecmd: | |
446 | !! %g2 = incoming packet | |
447 | ||
448 | ldub [%g2 + 7], %g4 | |
449 | cmp %g4, GUEST_STATE_CMD_SHUTREQ | |
450 | be,pn %xcc, 1f | |
451 | cmp %g4, GUEST_STATE_CMD_DCOREREQ | |
452 | be,pn %xcc, 1f | |
453 | nop | |
454 | ba,a vbsc_rx_finished | |
455 | ||
456 | 1: | |
457 | /* | |
458 | * The use of XID is deprecated. The target of | |
459 | * the request is always the control domain. | |
460 | */ | |
461 | CTRL_DOMAIN(%g1, %g3, %g4) | |
462 | cmp %g1, 0 | |
463 | be,pn %xcc, vbsc_rx_finished | |
464 | nop | |
465 | ||
466 | /* | |
467 | * Check if the current vcpu is in the control | |
468 | * domain and running. If so, the state command | |
469 | * can be executed on the local strand. | |
470 | */ | |
471 | VCPU_STRUCT(%g3) | |
472 | ||
473 | !! %g1 = control domain guestp | |
474 | !! %g2 = incoming packet | |
475 | !! %g3 = current vcpup | |
476 | ||
477 | ldx [%g3 + CPU_GUEST], %g4 | |
478 | cmp %g1, %g4 | |
479 | bne,pn %xcc, reroutecmd | |
480 | nop | |
481 | ||
482 | ldx [%g3 + CPU_STATUS], %g4 | |
483 | cmp %g4, CPU_STATE_RUNNING | |
484 | bne,pn %xcc, reroutecmd | |
485 | nop | |
486 | ||
487 | ba,a executecmd | |
488 | ||
489 | reroutecmd: | |
490 | ||
491 | !! %g1 = control domain guestp | |
492 | !! %g2 = incoming packet | |
493 | ||
494 | /* | |
495 | * Loop through the vcpus in the control domain | |
496 | * until one is found that is running. If none | |
497 | * are found, the domain is not in an appropriate | |
498 | * state for the request so the request is dropped. | |
499 | */ | |
500 | ||
501 | mov 0, %g4 | |
502 | !! %g4 = current index | |
503 | 1: | |
504 | cmp %g4, (NVCPUS - 1) | |
505 | bgu,pn %xcc, vbsc_rx_finished ! no appropriate vcpu, ignore request | |
506 | nop | |
507 | sllx %g4, GUEST_VCPUS_SHIFT, %g3 | |
508 | add %g1, %g3, %g3 | |
509 | add %g3, GUEST_VCPUS, %g3 | |
510 | ldx [%g3], %g3 | |
511 | brz,a %g3, 1b ! skip any empty entries | |
512 | inc %g4 | |
513 | !! %g3 = current vcpup | |
514 | ||
515 | ! check the vcpu state | |
516 | ldx [%g3 + CPU_STATUS], %g5 | |
517 | cmp %g5, CPU_STATE_RUNNING | |
518 | bne,a %xcc, 1b | |
519 | inc %g4 | |
520 | ||
521 | executecmd: | |
522 | ||
523 | !! %g2 = incoming packet | |
524 | !! %g3 = target vcpup | |
525 | ||
526 | VCPU2STRAND_STRUCT(%g3, %g4) | |
527 | !! %g4 = target strandp | |
528 | ||
529 | ldub [%g2 + 7], %g5 | |
530 | cmp %g5, GUEST_STATE_CMD_SHUTREQ | |
531 | be,pn %xcc, hvcmd_guest_shutdown_request | |
532 | cmp %g5, GUEST_STATE_CMD_DCOREREQ | |
533 | be,pn %xcc, hvcmd_guest_dcore_request | |
534 | nop | |
535 | ba,a vbsc_rx_finished | |
536 | ||
537 | hvcmd_guest_shutdown_request: | |
538 | ||
539 | !! %g2 = incoming packet | |
540 | !! %g3 = target vcpup | |
541 | !! %g4 = target strandp | |
542 | ||
543 | #ifdef DEBUG | |
544 | mov %g7, %g5 | |
545 | PRINT("Control Domain shutdown request, target strand=0x") | |
546 | ldub [%g4 + STRAND_ID], %g6 | |
547 | PRINTX(%g6) | |
548 | PRINT("\r\n") | |
549 | mov %g5, %g7 | |
550 | #endif /* DEBUG */ | |
551 | ||
552 | ! retrieve the command argument from the packet | |
553 | ldx [%g2 + 0x10], %g2 | |
554 | !! %g2 = command argument (grace period in seconds) | |
555 | ||
556 | /* | |
557 | * Perform the action locally if the current | |
558 | * strand is the specified target. | |
559 | */ | |
560 | ||
561 | STRAND_STRUCT(%g5) | |
562 | cmp %g4, %g5 | |
563 | be,a,pt %xcc, guest_shutdown ! tail call, does not return here | |
564 | mov %g2, %g1 ! the required argument | |
565 | ||
566 | /* | |
567 | * Send a mondo to the specified strand to | |
568 | * perform the action. | |
569 | */ | |
570 | ||
571 | add %g4, STRAND_HV_TXMONDO, %g5 | |
572 | !! %g5 = strand mondop | |
573 | ||
574 | ! setup mondo structure | |
575 | mov HXCMD_GUEST_SHUTDOWN, %g6 | |
576 | stx %g6, [%g5 + HVM_CMD] | |
577 | STRAND_STRUCT(%g6) | |
578 | stx %g6, [%g5 + HVM_FROM_STRANDP] | |
579 | stx %g3, [%g5 + HVM_ARGS + HVM_GUESTCMD_VCPUP] | |
580 | stx %g2, [%g5 + HVM_ARGS + HVM_GUESTCMD_ARG] | |
581 | ||
582 | ! send the mondo | |
583 | mov %g4, %g1 ! arg1 = target strandp | |
584 | mov %g5, %g2 ! arg2 = strand mondop | |
585 | STRAND_PUSH(%g7, %g3, %g4) | |
586 | HVCALL(hvmondo_send) | |
587 | STRAND_POP(%g7, %g3) | |
588 | ||
589 | ba,a vbsc_rx_finished | |
590 | ||
591 | hvcmd_guest_dcore_request: | |
592 | ||
593 | !! %g2 = incoming packet | |
594 | !! %g3 = target vcpup | |
595 | !! %g4 = target strandp | |
596 | ||
597 | #ifdef DEBUG | |
598 | mov %g7, %g5 | |
599 | PRINT("Control Domain panic request, target strand=0x") | |
600 | ldub [%g4 + STRAND_ID], %g6 | |
601 | PRINTX(%g6) | |
602 | PRINT("\r\n") | |
603 | mov %g5, %g7 | |
604 | #endif /* DEBUG */ | |
605 | ||
606 | /* | |
607 | * Perform the action locally if the current | |
608 | * strand is the specified target. | |
609 | */ | |
610 | ||
611 | STRAND_STRUCT(%g5) | |
612 | cmp %g4, %g5 | |
613 | be,a,pt %xcc, guest_panic ! tail call, does not return here | |
614 | nop | |
615 | ||
616 | /* | |
617 | * Send a mondo to the specified strand to | |
618 | * perform the action. | |
619 | */ | |
620 | ||
621 | add %g4, STRAND_HV_TXMONDO, %g5 | |
622 | !! %g5 = strand mondop | |
623 | ||
624 | ! setup mondo structure | |
625 | mov HXCMD_GUEST_PANIC, %g6 | |
626 | stx %g6, [%g5 + HVM_CMD] | |
627 | STRAND_STRUCT(%g6) | |
628 | stx %g6, [%g5 + HVM_FROM_STRANDP] | |
629 | stx %g3, [%g5 + HVM_ARGS + HVM_GUESTCMD_VCPUP] | |
630 | ||
631 | ! send the mondo | |
632 | mov %g4, %g1 ! arg1 = target strandp | |
633 | mov %g5, %g2 ! arg2 = strand mondop | |
634 | STRAND_PUSH(%g7, %g3, %g4) | |
635 | HVCALL(hvmondo_send) | |
636 | STRAND_POP(%g7, %g3) | |
637 | ||
638 | ba,a vbsc_rx_finished | |
639 | ||
640 | /* | |
641 | * dbgrd - perform read transaction on behalf of vbsc | |
642 | */ | |
643 | dbgrd: | |
644 | ldx [%g2 + 8], %g3 ! ADDR | |
645 | ldub [%g2 + 7], %g6 ! size | |
646 | sub %g6, '0', %g6 | |
647 | ldub [%g2 + 5], %g4 ! asi? | |
648 | cmp %g4, 'A' | |
649 | bne,pt %xcc, 1f | |
650 | sllx %g6, 2, %g6 ! offset | |
651 | add %g6, 4*4, %g6 ! offset of ASIs | |
652 | srlx %g3, 56, %g4 | |
653 | and %g4, 0xff, %g4 | |
654 | wr %g4, %asi | |
655 | sllx %g3, 8, %g3 | |
656 | srlx %g3, 8, %g3 ! bits 0-56 | |
657 | 1: ba 1f | |
658 | rd %pc, %g4 | |
659 | ldub [%g3], %g6 | |
660 | lduh [%g3], %g6 | |
661 | ld [%g3], %g6 | |
662 | ldx [%g3], %g6 | |
663 | lduba [%g3] %asi, %g6 | |
664 | lduha [%g3] %asi, %g6 | |
665 | lda [%g3] %asi, %g6 | |
666 | ldxa [%g3] %asi, %g6 | |
667 | 1: add %g4, 4, %g4 | |
668 | jmp %g4 + %g6 ! CTI COUPLE!! | |
669 | ba 1f ! CTI COUPLE!! | |
670 | nop ! NEVER EXECUTED!! DONT DELETE | |
671 | 1: ba 1f | |
672 | rd %pc, %g2 | |
673 | .word 0 ! data buffer - upper 32 bits | |
674 | .word 0 ! data buffer - lower 32 bits | |
675 | 1: add %g2, 4, %g2 ! buf | |
676 | st %g6, [%g2 + 4] ! low bits | |
677 | srlx %g6, 32, %g6 | |
678 | st %g6, [%g2 + 0] ! upper bits | |
679 | ba svc_internal_send ! returns to caller!!!! | |
680 | mov 8, %g3 ! len | |
681 | ||
682 | /* | |
683 | * dbgwr - perform write transaction on behalf of vbsc | |
684 | */ | |
685 | dbgwr: | |
686 | ldx [%g2 + 0x10], %g3 ! ADDR | |
687 | ldub [%g2 + 7], %g6 ! size | |
688 | sub %g6, '0', %g6 | |
689 | ldub [%g2 + 5], %g1 ! asi? | |
690 | cmp %g1, 'A' | |
691 | bne,pt %xcc, 1f | |
692 | sllx %g6, 2, %g6 ! offset | |
693 | add %g6, 4*4, %g6 ! offset of ASIs | |
694 | srlx %g3, 56, %g4 | |
695 | and %g4, 0xff, %g4 | |
696 | wr %g4, %asi | |
697 | sllx %g3, 8, %g3 | |
698 | srlx %g3, 8, %g3 ! bits0-56 | |
699 | 1: ba 1f | |
700 | rd %pc, %g4 | |
701 | stb %g1, [%g3] | |
702 | sth %g1, [%g3] | |
703 | st %g1, [%g3] | |
704 | stx %g1, [%g3] | |
705 | stba %g1, [%g3] %asi | |
706 | stha %g1, [%g3] %asi | |
707 | sta %g1, [%g3] %asi | |
708 | stxa %g1, [%g3] %asi | |
709 | 1: add %g4, 4, %g4 | |
710 | ldx [%g2 + 8], %g1 ! get data | |
711 | jmp %g4 + %g6 ! CTI COUPLE!! | |
712 | jmp %g7 + 4 ! All done. | |
713 | nop ! NEVER EXECUTED!!! | |
714 | ||
715 | /* | |
716 | * dbg_send_error - send a fake error transaction back to vbsc | |
717 | */ | |
718 | dbg_send_error: | |
719 | #if 0 | |
720 | #ifdef DEBUG | |
721 | /* | |
722 | * Fill the error reports with valid information to | |
723 | * help test interaction with the FERG on the vbsc | |
724 | */ | |
725 | mov %g7, %g6 | |
726 | STRAND_STRUCT(%g3) | |
727 | add %g3, STRAND_CE_RPT + STRAND_VBSC_ERPT, %g4 | |
728 | SIM_IRC_DIAG_ERPT(%g4, %g5, %g7) | |
729 | add %g3, STRAND_UE_RPT + STRAND_VBSC_ERPT, %g4 | |
730 | SIM_IRU_DIAG_ERPT(%g4, %g5, %g7) | |
731 | PRINT("\r\n") | |
732 | mov %g6, %g7 | |
733 | #endif | |
734 | ||
735 | CPU_PUSH(%g7, %g1, %g2, %g3) | |
736 | STRAND_STRUCT(%g1) | |
737 | add %g1, STRAND_CE_RPT + STRAND_UNSENT_PKT, %g2 | |
738 | ldx [%g1 + STRAND_CONFIGP], %g6 | |
739 | ||
740 | #ifdef DEBUG | |
741 | /* | |
742 | * Send one error and mark another buffer to be | |
743 | * sent | |
744 | */ | |
745 | mov 1, %g7 | |
746 | stx %g7, [%g6 + CONFIG_ERRS_TO_SEND] | |
747 | set STRAND_UE_RPT + STRAND_UNSENT_PKT, %g3 | |
748 | add %g1, %g3, %g3 | |
749 | stx %g7, [%g3] | |
750 | #endif | |
751 | add %g1, STRAND_CE_RPT + STRAND_VBSC_ERPT, %g1 | |
752 | mov EVBSC_SIZE, %g3 | |
753 | HVCALL(send_diag_erpt) | |
754 | CPU_POP(%g7, %g1, %g2, %g3) | |
755 | #endif | |
756 | HVRET | |
757 | SET_SIZE(vbsc_rx) | |
758 | ||
759 | /* | |
760 | * vbsc_tx | |
761 | * | |
762 | * %g1 callback cookie | |
763 | * %g2 packet | |
764 | * %g7 return address | |
765 | */ | |
766 | ENTRY(vbsc_tx) | |
767 | mov %g7, %g6 | |
768 | PRINT("vbsc_tx: ") | |
769 | PRINTX(%g1) | |
770 | PRINT("\r\n") | |
771 | mov %g6, %g7 | |
772 | ||
773 | HVRET | |
774 | SET_SIZE(vbsc_tx) | |
775 | ||
776 | ||
777 | ||
778 | ||
779 | /* | |
780 | * vbsc_puts - print string on hypervisor console | |
781 | * | |
782 | * %g1 string pointer | |
783 | * %g7 return address | |
784 | */ | |
785 | ENTRY_NP(vbsc_puts) | |
786 | ||
787 | CPU_PUSH(%g7, %g2, %g3, %g4) | |
788 | CPU_PUSH(%g6, %g2, %g3, %g4) | |
789 | CPU_PUSH(%g5, %g2, %g3, %g4) | |
790 | CPU_PUSH(%l0, %g2, %g3, %g4) | |
791 | ||
792 | mov %g1, %l0 | |
793 | !! %l0 = string pointer | |
794 | ||
795 | 1: mov 8, %g5 | |
796 | mov 0, %g2 | |
797 | !! %g5 = loop count | |
798 | !! %g2 = debug-puthex arg1 | |
799 | ||
800 | 2: ldub [%l0], %g3 | |
801 | brz,pn %g3, .sendndone | |
802 | nop | |
803 | sllx %g2, 8, %g2 | |
804 | or %g2, %g3, %g2 ! arg1 = (arg1 << 8) | char | |
805 | deccc %g5 | |
806 | bnz,pt %xcc, 2b | |
807 | inc %l0 | |
808 | ||
809 | 3: | |
810 | setx VBSC_HV_PUTCHARS, %g3, %g1 | |
811 | HVCALL(vbsc_send_polled) | |
812 | ||
813 | ba,pt %xcc, 1b | |
814 | nop | |
815 | ||
816 | .sendndone: | |
817 | setx VBSC_HV_PUTCHARS, %g3, %g1 | |
818 | HVCALL(vbsc_send_polled) | |
819 | ||
820 | CPU_POP(%l0, %g1, %g2, %g3) | |
821 | CPU_POP(%g5, %g1, %g2, %g3) | |
822 | CPU_POP(%g6, %g1, %g2, %g3) | |
823 | CPU_POP(%g7, %g1, %g2, %g3) | |
824 | ||
825 | HVRET | |
826 | SET_SIZE(vbsc_puts) | |
827 | ||
828 | ||
829 | /* | |
830 | * vbsc_putx - print hex number on hypervisor console | |
831 | * | |
832 | * %g1 number | |
833 | * %g7 return address | |
834 | */ | |
835 | ENTRY_NP(vbsc_putx) | |
836 | mov %g1, %g2 | |
837 | setx VBSC_HV_PUTHEX, %g3, %g1 | |
838 | ba,a vbsc_send_polled | |
839 | /* tail call, returns directly to caller */ | |
840 | SET_SIZE(vbsc_putx) | |
841 | ||
842 | #endif /* CONFIG_SVC && CONFIG_VBSC_SVC */ |