Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / common / src / svc_common.s
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: svc_common.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_common.s 1.27 07/05/30 SMI"
50
51#ifdef CONFIG_SVC /* { */
52
53#include <sys/asm_linkage.h>
54#include <sys/htypes.h>
55#include <hypervisor.h>
56#include <sparcv9/misc.h>
57#include <sparcv9/asi.h>
58#include <asi.h>
59#include <mmu.h>
60#include <hprivregs.h>
61#include <fpga.h>
62#include <intr.h>
63#include <sun4v/traps.h>
64#include <sun4v/asi.h>
65#include <sun4v/mmu.h>
66#include <sun4v/queue.h>
67#include <offsets.h>
68#include <config.h>
69#include <strand.h>
70#include <guest.h>
71#include <debug.h>
72#include <svc.h>
73#include <abort.h>
74#include <util.h>
75#include <ldc.h>
76#include <vdev_intr.h>
77
78/*
79 * checksum_pkt
80 *
81 * In
82 * %g1 = buffer
83 * %g2 = len
84 * Out
85 * %g1 = checksum
86 * %g3 = scratched
87 * %g4 = scratched
88 */
89#define addr %g1
90#define len %g2
91#define tmp0 %g3
92#define sum %g4
93#define retval %g1
94 ENTRY_NP(checksum_pkt)
95 btst 1, len ! len&1 ?
96 bz,pt %xcc, 1f
97 mov %g0, sum ! sum=0
98 subcc len, 1, len ! decr
99 ldub [addr + len], sum ! preload sum with last byte
100 bne,pt %xcc, 1f ! zero?
101 sub %g0, 1, tmp0 ! this will probably NEVER happen!!
102 xor sum, tmp0, retval ! as this pkt would be too short
103 HVRET ! return sum.
1041: lduh [addr], tmp0
105 add tmp0, sum, sum
106 subcc len, 2, len
107 bgt,pt %xcc, 1b
108 add addr, 2, addr
1092: srl sum, 16, tmp0 ! get upper 16 bits
110 sll sum, 16, sum
111 srl sum, 16, sum ! chuck upper 16 bits
112 brnz,pt tmp0, 2b
113 add tmp0, sum, sum
114 sub %g0, 1, len
115 srl len, 16, len ! 0xffff
116 xor sum, len, retval
117 HVRET
118#undef addr
119#undef len
120#undef tmp0
121#undef sum
122#undef retval
123 SET_SIZE(checksum_pkt)
124
125
126/*
127 * svc_intr_getstate - return a service's current interrupt state
128 *
129 * Get the state, mask with the enable bits, or TX and RX with
130 * the abort bit, return the result. non-zero means intr pending.
131 *
132 * %g1 - svc pointer
133 * --
134 * %g1 - current state
135 */
136 ENTRY_NP(svc_intr_getstate)
137 ld [%g1 + SVC_CTRL_STATE], %g1
138 and %g1, (SVC_FLAGS_RE | SVC_FLAGS_TE), %g2 ! XXX FLAGS MASK
139 and %g1, (SVC_FLAGS_RI | SVC_FLAGS_TI), %g3
140 srl %g2, 1, %g2
141 and %g2, %g3, %g2
142 srl %g2, 2, %g3
143 or %g2, %g3, %g2
144 and %g2, 1, %g2
145 srl %g1, ABORT_SHIFT, %g1 ! abort..
146 or %g2, %g1, %g1
147 HVRET
148 SET_SIZE(svc_intr_getstate)
149
150
151#if CONFIG_FPGA /* { */
152
153#define FPGA_MBOX_INT_ENABLE(x) \
154 setx FPGA_INTR_BASE, r_tmp2, r_tmp3 ;\
155 mov x, r_tmp2 ;\
156 stb r_tmp2, [r_tmp3 + FPGA_MBOX_INTR_ENABLE]
157
158#define r_tmp1 %g1
159#define r_tmp2 %g2
160#define r_tmp3 %g3
161#define r_svc %g4
162#define r_chan %g5
163#define r_root %g6
164#define r_tmp4 %g7
165
166#endif /* } */
167
168
169/*
170 * svc_isr - The mailbox interrupt service routine..
171 * we will retry here, as we do not expect to be 'called'
172 *
173 * r_cpu (%g1) comes from the mondo vector handler.
174 *
175 * svc_process:
176 * if (intr_status & IRQ_QUEUE_IN) {
177 * goto svc_rx_intr;
178 * }
179 * if (intr_status & IRQ_QUEUE_OUT)
180 * goto svc_tx_intr;
181 * if (intr_status & IRQ_LDC_OUT)
182 * goto svc_ldc_tx_intr;
183 * retry;
184 *
185 * isr_common:
186 * UNLOCK(lock);
187 * goto svc_process;
188 *
189 * svc_rx_intr:
190 * ...
191 * goto isr_common;
192 *
193 * svc_tx_intr:
194 * LOCK(lock);
195 * ...
196 * goto isr_common;
197 */
198 ENTRY_NP(svc_isr)
199
200#ifdef CONFIG_FPGA /* { */
201 ldx [%g1 + CPU_ROOT], r_root ! root data
202svc_process:
203 setx FPGA_INTR_BASE, r_tmp3, r_tmp2
204 ldub [r_tmp2 + FPGA_MBOX_INTR_STATUS], %g4
205
206 btst IRQ_QUEUE_IN, %g4
207 bnz,pt %xcc, svc_rx_intr
208 btst IRQ_QUEUE_OUT, %g4
209 bnz,pt %xcc, svc_tx_intr
210 btst IRQ_LDC_OUT, %g4
211 bnz,pt %xcc, svc_ldc_tx_intr
212 nop ! more intr srcs here!
213 ! XXX enable FPGA interrupts.
214 FPGA_MBOX_INT_ENABLE(IRQ_QUEUE_IN|IRQ_QUEUE_OUT|IRQ_LDC_OUT)
215
216 /*
217 * Check for a pending non-resumable error. This flag will
218 * be set if the rx handler queued a non-resumable error
219 * to force a guest panic. The non-resumable trap must be
220 * generated only after FPGA interrupts are reenabled, so
221 * it is performed here after the rx processing is complete.
222 */
223 STRAND_STRUCT(%g1)
224 set STRAND_NRPENDING, %g2
225 ldx [%g1 + %g2], %g3
226 brnz,a,pt %g3, nonresumable_error_trap
227 stx %g0, [%g1 + %g2]
228
229 retry
230
231 ALTENTRY(isr_common)
232 /* reload registers */
233 VCPU_STRUCT(%g1)
234 ROOT_STRUCT(r_root)
235 ldx [r_root + CONFIG_SVCS], r_svc
236 ba,a svc_process ! r_root is ptr to root data
237 nop
238 SET_SIZE(isr_common)
239#endif /* } */
240
241 SET_SIZE(svc_isr)
242
243
244#if CONFIG_FPGA /* { */
245
246#define INT_ENABLE(x) \
247 ba isr_common ;\
248 mov x, %g1
249
250#define TX_INTR_DONE(x) \
251 VCPU_STRUCT(%g1) ;\
252 ROOT_STRUCT(r_root) ;\
253 ldx [r_root + CONFIG_SVCS], r_svc ;\
254 UNLOCK(r_svc, HV_SVC_DATA_LOCK) ;\
255 INT_ENABLE(x)
256
257#define RX_INTR_DONE(status,r_chan) \
258 mov status, %g1 ;\
259 stb %g1, [r_chan + FPGA_Q_STATUS] ;\
260 INT_ENABLE(IRQ_QUEUE_IN)
261
262 ENTRY_NP(svc_rx_intr)
263#ifdef INTR_DEBUG
264 PRINT("Got an SSI FPGA RX Interrupt\r\n")
265#endif
266 ldx [r_root + CONFIG_SVCS], r_svc
267 ldx [r_svc + HV_SVC_DATA_RXCHANNEL], r_chan ! regs
268 lduh [r_chan + FPGA_Q_SIZE], %g2 ! len
269 brz,pn %g2, rxbadpkt
270 ldx [r_svc + HV_SVC_DATA_RXBASE], %g1 ! buffer
271 HVCALL(checksum_pkt)
272 brnz,pn %g1, rxbadpkt
273 ldx [r_root + CONFIG_SVCS], r_svc
274 ld [r_svc + HV_SVC_DATA_NUM_SVCS], r_tmp3 ! numsvcs
275 ldx [r_svc + HV_SVC_DATA_RXBASE], r_tmp1 ! buffer addr
276 add r_svc, HV_SVC_DATA_SVC, r_svc ! svc base
2779: ld [r_tmp1 + SVC_PKT_XID], r_tmp2
278 ld [r_svc + SVC_CTRL_XID], r_tmp4 ! svc partid
279 cmp r_tmp2, r_tmp4
280 bne,pn %xcc, 1f
281 lduh [r_tmp1 + SVC_PKT_SID], r_tmp2
282 ld [r_svc + SVC_CTRL_SID], r_tmp4
283 cmp r_tmp2, r_tmp4
284 beq,pn %xcc, rxintr_gotone
2851: subcc r_tmp3, 1, r_tmp3 ! nsvcs--
286 bne,pn %xcc, 9b
287 add r_svc, SVC_CTRL_SIZE, r_svc ! next
288rxsvc_abort:
289 PRINT("Aborted Transport to bad XPID/SVC\r\n")
290 RX_INTR_DONE(QINTR_ABORT, r_chan)
291rxintr_gotone:
292#ifdef INTRDEBUG
293 PRINT("Found: "); PRINTX(r_svc); PRINT("\r\n")
294#endif
295 ld [r_svc + SVC_CTRL_CONFIG], r_tmp4 ! check config bits
296 btst SVC_CFG_RX, r_tmp4 ! can RX ?
297 bz,pn %xcc, rxsvc_abort
298 ld [r_svc + SVC_CTRL_STATE], r_tmp4
299 btst SVC_FLAGS_RI, r_tmp4 ! buffer available?
300 bnz,pn %xcc, rx_busy
301 nop
302 ! XXX need mutex!!
303 lduh [r_chan + FPGA_Q_SIZE], r_tmp1 ! len
304 stx r_tmp1, [r_svc + SVC_CTRL_RECV + SVC_LINK_SIZE] ! len
305 ldx [r_svc + SVC_CTRL_RECV + SVC_LINK_PA], r_tmp3 ! dest
306 ldx [r_root + CONFIG_SVCS], r_tmp2
307 ldx [r_tmp2 + HV_SVC_DATA_RXBASE], r_tmp2 ! src
308 SMALL_COPY_MACRO(r_tmp2, r_tmp1, r_tmp3, r_tmp4)
309 LOCK(r_svc, SVC_CTRL_LOCK, r_tmp3, r_tmp4)
310 ld [r_svc + SVC_CTRL_STATE], r_tmp4
311 btst SVC_CFG_CALLBACK, r_tmp4
312#define r_hvrxcallback r_tmp4
313 or r_tmp4, SVC_FLAGS_RI, r_tmp4
314 bnz,pn %xcc, do_hvrxcallback ! HV callback
315 st r_tmp4, [r_svc + SVC_CTRL_STATE] ! RX pending
316 UNLOCK(r_svc, SVC_CTRL_LOCK)
317 btst SVC_FLAGS_RE, r_tmp4 ! RECV intr enabled?
318 bz,pn %xcc, 2f
319 ldx [r_svc + SVC_CTRL_INTR_COOKIE], %g1 ! Cookie
320 PRINT("XXX - SVC INTR SENDING RX PENDING INTR - XXX\r\n")
321 ba vdev_intr_generate ! deliver??
322 rd %pc, %g7
3232:
324 ROOT_STRUCT(r_root)
325 ldx [r_root + CONFIG_SVCS], r_svc
326 ldx [r_svc + HV_SVC_DATA_RXCHANNEL], r_chan ! regs
327 RX_INTR_DONE(QINTR_ACK, r_chan)
328rx_busy:
329 PRINT("SVC Buffer Busy\r\n")
330 RX_INTR_DONE(QINTR_BUSY, r_chan)
331rxbadpkt:
332 PRINT("SVC RX Bad packet: "); PRINTX(%g1); PRINT("\r\n")
333 RX_INTR_DONE(QINTR_NACK, r_chan)
334 SET_SIZE(svc_rx_intr)
335
336
337 ENTRY_NP(svc_tx_intr)
338#ifdef INTR_DEBUG
339 PRINT("Got an SSI FPGA TX Interrupt: ")
340 ldx [%g1 + CPU_ROOT], r_root ! data root
341 ldx [r_root + HV_SVC_DATA_TXCHANNEL], r_chan ! regs
342 ldub [r_chan + FPGA_Q_STATUS], r_tmp3 ! status
343 PRINTX(r_tmp3)
344 PRINT("\r\n")
345#endif
346 ! XXX need mutex!!
347 ldx [%g1 + CPU_ROOT], r_root ! data root
348 ldx [r_root + CONFIG_SVCS], r_root ! svc root
349
350 LOCK(r_root, HV_SVC_DATA_LOCK, r_svc, r_chan)
351
352 ldx [r_root + HV_SVC_DATA_SENDH], r_svc ! head of tx q
353 brz,pn r_svc, tx_nointr
354 ldx [r_root + HV_SVC_DATA_TXCHANNEL], r_chan ! regs
355 ldub [r_chan + FPGA_Q_STATUS], r_tmp3 ! status
356 sth %g0, [r_chan + FPGA_Q_SIZE] ! len=0
357 btst QINTR_ACK, r_tmp3
358 bnz,pt %xcc, txpacket_ack
359 btst QINTR_NACK, r_tmp3
360 bnz,pt %xcc, txpacket_nack
361 btst QINTR_BUSY, r_tmp3
362 bnz,pt %xcc, txpacket_busy
363 btst QINTR_ABORT, r_tmp3
364 bnz,pt %xcc, txpacket_abort
365 nop
366#ifdef INTR_DEBUG
367 PRINT("XXX unserviced bits in tx status register: ")
368 PRINTX(r_tmp3)
369 PRINT("\r\n")
370#endif
371 TX_INTR_DONE(IRQ_QUEUE_OUT)
372
373txpacket_nack:
374#ifdef INTR_DEBUG
375 PRINT("txSVC NACK!!\r\n")
376#endif
377 ba defer_pkt
378 mov 1, %g7 ! Nack..
379
380txpacket_abort:
381#ifdef INTR_DEBUG
382 PRINT("txSVC Abort!!\r\n")
383#endif
384 LOCK(r_svc, SVC_CTRL_LOCK, r_tmp2, r_tmp1)
385 ld [r_svc + SVC_CTRL_STATE], r_tmp2
386 andn r_tmp2, SVC_FLAGS_TP, r_tmp2
387 or r_tmp2, SVC_FLAG_ABORT, r_tmp2
388 st r_tmp2, [r_svc + SVC_CTRL_STATE]
389 UNLOCK(r_svc, SVC_CTRL_LOCK)
390 ba txintr_done
391 stb r_tmp3, [r_chan + FPGA_Q_STATUS] ! clr status
392
393txpacket_busy:
394#ifdef INTR_DEBUG
395 PRINT("txSVC Busy!!\r\n")
396#endif
397 mov 0, %g7 ! ??? Ack?
398 /*FALLTHROUGH*/
399
400defer_pkt:
401 !! %g7 = 1=NACK, 0=BUSY ??? something.
402 stb r_tmp3, [r_chan + FPGA_Q_STATUS] ! clr status
403#ifdef INTR_DEBUG
404 PRINT("Deferring..\r\n")
405#endif
406 ROOT_STRUCT(r_root)
407 ldx [r_root + CONFIG_SVCS], r_root ! svc root
408#if 1 /* XXX */
409 /*
410 * XXX we should delay and resend later or at least put this
411 * packet on the end of the queue so other packets have a chance.
412 */
413 ldx [r_root + HV_SVC_DATA_SENDH], r_svc ! head of tx q
414 SEND_SVC_PACKET(r_root, r_svc, r_tmp1, r_tmp2, r_tmp3, r_tmp4)
415 ba txintr_done
416 nop
417#else
418 /*
419 * Move the current head to the end of the queue:
420 * if (head->next != NULL) {
421 * tmp1 = head
422 * head = tmp1->next
423 * tmp1->next = NULL
424 * tail->next = tmp1
425 * tail = tmp1
426 * }
427 */
428 ldx [r_root + HV_SVC_DATA_SENDH], r_tmp1
429 ldx [r_tmp1 + SVC_CTRL_SEND + SVC_LINK_NEXT], r_tmp2
430 brz,pt r_tmp2, hv_txintr ! only item on list
431 nop
432 stx r_tmp2, [r_root + HV_SVC_DATA_SENDH]
433 stx %g0, [r_tmp1 + SVC_CTRL_SEND + SVC_LINK_NEXT]
434 ldx [r_root + HV_SVC_DATA_SENDT], r_tmp2
435 stx r_tmp1, [r_tmp2 + SVC_CTRL_SEND + SVC_LINK_NEXT]
436 stx r_tmp1, [r_root + HV_SVC_DATA_SENDT]
437#ifdef INTR_DEBUG
438 PRINT("round-robin\r\n")
439#endif
440 ba,pt %xcc, hv_txintr
441 nop
442#endif
443
444txpacket_ack:
445 stb r_tmp3, [r_chan + FPGA_Q_STATUS] ! clr status
446 LOCK(r_svc, SVC_CTRL_LOCK, r_tmp2, r_tmp1)
447
448 /* Mark busy, prevents svc_internal_send from touching fpga */
449 mov -1, r_tmp2
450 stw r_tmp2, [r_root + HV_SVC_DATA_SENDBUSY]
451
452 /* Remove head from list prior to calling the tx callback */
453 ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_NEXT], r_tmp2
454 stx r_tmp2, [r_root + HV_SVC_DATA_SENDH]
455 brz,a,pt r_tmp2, 1f
456 stx %g0, [r_root + HV_SVC_DATA_SENDT]
4571: stx %g0, [r_svc + SVC_CTRL_SEND + SVC_LINK_NEXT]
458
459 ld [r_svc + SVC_CTRL_STATE], r_tmp2
460 andn r_tmp2, SVC_FLAGS_TP, r_tmp2
461 or r_tmp2, SVC_FLAGS_TI, r_tmp2
462 st r_tmp2, [r_svc + SVC_CTRL_STATE]
463 btst SVC_CFG_CALLBACK, r_tmp2
464#define r_hvtxcallback r_tmp2
465 bnz,pn %xcc, do_hvtxcallback ! HV callback
466 nop
467 UNLOCK(r_svc, SVC_CTRL_LOCK)
468 btst SVC_FLAGS_TE, r_tmp2
469 bz,pn %xcc, hv_txintr
470 ldx [r_svc + SVC_CTRL_INTR_COOKIE], %g1 ! Cookie
471 ba vdev_intr_generate ! deliver??
472 rd %pc, %g7
473hv_txintr:
474 ! rebuild the regs we care about
475 VCPU_STRUCT(%g1)
476 ROOT_STRUCT(r_root)
477 ldx [r_root + CONFIG_SVCS], r_root ! svc root
478
479 /* clear busy */
480 stw %g0, [r_root + HV_SVC_DATA_SENDBUSY]
481
482 ldx [r_root + HV_SVC_DATA_SENDH], r_svc ! head of tx q
483#ifdef INTR_DEBUG
484 PRINT("Next Packet: "); PRINTX(r_svc); PRINT("\r\n")
485#endif
486 brz,pn r_svc, txintr_done
487 nop
488 SEND_SVC_PACKET(r_root, r_svc, r_tmp1, r_tmp2, r_tmp3, r_tmp4)
489txintr_done:
490 TX_INTR_DONE(IRQ_QUEUE_OUT)
491
492tx_nointr:
493 ldub [r_chan + FPGA_Q_STATUS], r_tmp3 ! get status
494 stb r_tmp3, [r_chan + FPGA_Q_STATUS] ! clr status
495 TX_INTR_DONE(IRQ_QUEUE_OUT)
496 SET_SIZE(svc_tx_intr)
497#undef r_tmp1
498#if 0
499#undef r_tmp3
500#undef r_tmp2
501#undef r_svc
502#undef r_chan
503#endif
504
505/*
506 * SAVE/RESTORE_SVCREGS - save/restore all registers except %g7 which
507 * gets clobbered
508 */
509#define SAVE_SVCREGS \
510 VCPU_STRUCT(%g7) ;\
511 add %g7, CPU_SVCREGS, %g7 ;\
512 stx %g1, [%g7 + 0x00] ;\
513 stx %g2, [%g7 + 0x08] ;\
514 stx %g3, [%g7 + 0x10] ;\
515 stx %g4, [%g7 + 0x18] ;\
516 stx %g5, [%g7 + 0x20] ;\
517 stx %g6, [%g7 + 0x28] ;
518
519#define RESTORE_SVCREGS \
520 VCPU_STRUCT(%g7) ;\
521 add %g7, CPU_SVCREGS, %g7 ;\
522 ldx [%g7 + 0x00], %g1 ;\
523 ldx [%g7 + 0x08], %g2 ;\
524 ldx [%g7 + 0x10], %g3 ;\
525 ldx [%g7 + 0x18], %g4 ;\
526 ldx [%g7 + 0x20], %g5 ;\
527 ldx [%g7 + 0x28], %g6
528
529/*
530 * Perform a hypervisor callback for a receive channel
531 *
532 * The callback cookie is passed in %g1.
533 * The svc pointer %g2, state is RI. If the
534 * packet has been successfully processed then the callback
535 * routine needs to clear the RI flag.
536 */
537 ENTRY_NP(do_hvrxcallback)
538#ifdef INTRDEBUG
539 PRINT("do_hvrxcallback\r\n")
540#endif
541 UNLOCK(r_svc, SVC_CTRL_LOCK)
542 ldx [r_svc + SVC_CTRL_CALLBACK + SVC_CALLBACK_RX], %g7
543 brz,pn %g7, 9f
544 nop
545 SAVE_SVCREGS
546#ifdef INTRDEBUG
547 PRINT("HV RX Callback: "); PRINTX(r_svc); PRINT("\r\n")
548#endif
549 ldx [r_svc + SVC_CTRL_CALLBACK + SVC_CALLBACK_RX], %g7
550 ldx [r_svc + SVC_CTRL_CALLBACK + SVC_CALLBACK_COOKIE], %g1
551 mov r_svc, %g2
552 jmp %g7
553 rd %pc, %g7
554 RESTORE_SVCREGS
5559: RX_INTR_DONE(QINTR_ACK, r_chan)
556 SET_SIZE(do_hvrxcallback)
557
558 ENTRY_NP(do_hvtxcallback)
559#ifdef INTRDEBUG
560 PRINT("do_hvtxcallback\r\n")
561#endif
562 UNLOCK(r_svc, SVC_CTRL_LOCK)
563 ldx [r_svc + SVC_CTRL_CALLBACK + SVC_CALLBACK_TX], %g1
564 brz,pn %g1, hv_txintr
565 nop
566 SAVE_SVCREGS
567#ifdef INTRDEBUG
568 PRINT("HV TX Callback: "); PRINTX(r_svc); PRINT("\r\n")
569#endif
570 ldx [r_svc + SVC_CTRL_CALLBACK + SVC_CALLBACK_TX], %g6
571 ldx [r_svc + SVC_CTRL_CALLBACK + SVC_CALLBACK_COOKIE], %g1
572 !! XXX is this useful
573 ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], %g2
574 add %g2, SVC_PKT_SIZE, %g2 ! skip header
575 jmp %g6
576 rd %pc, %g7
577 RESTORE_SVCREGS
5789: ba hv_txintr
579 nop
580 SET_SIZE(do_hvtxcallback)
581#undef r_tmp3
582#undef r_tmp2
583#undef r_tmp4
584#undef r_svc
585#undef r_chan
586
587#endif /* } */
588#endif /* } CONFIG_SVC */