Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / common / src / svcinternal.s
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: svcinternal.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 "@(#)svcinternal.s 1.15 07/06/07 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 <asi.h>
58#include <mmu.h>
59#include <sun4v/traps.h>
60#include <sun4v/asi.h>
61#include <sun4v/mmu.h>
62#include <sun4v/queue.h>
63#include <devices/pc16550.h>
64#include <fpga.h>
65
66#include <offsets.h>
67#include <config.h>
68#include <guest.h>
69#include <svc.h>
70#include <util.h>
71#include <debug.h>
72
73#define CHECKSUM_PKT(addr, len, retval, sum, tmp0) \
74 .pushlocals ;\
75 btst 1, len ;\
76 be,pt %xcc, 1f ;\
77 mov %g0, sum ;\
78 deccc len ;\
79 ldub [addr + len], sum ;\
801: lduh [addr], tmp0 ;\
81 add tmp0, sum, sum ;\
82 deccc 2, len ;\
83 bgt,pt %xcc, 1b ;\
84 inc 2, addr ;\
852: srl sum, 16, tmp0 ;\
86 sll sum, 16, sum ;\
87 srl sum, 16, sum ;\
88 brnz,pt tmp0, 2b ;\
89 add tmp0, sum, sum ;\
90 mov -1, len ;\
91 srl len, 16, len ;\
92 xor sum, len, retval ;\
93 .poplocals
94
95/*
96 * This is the internal access to the svc driver.
97 */
98#define r_svc %g1
99#define r_buf %g2
100#define r_len %g3
101#define r_tmp0 %g4
102#define r_tmp1 %g5
103#define r_svcbuf %g6
104/*
105 * svc_internal_send - Use this to send a packet from inside
106 * the hypervisor
107 *
108 * You had better be sure *you* are not holding the SVC_CTRL_LOCK..
109 *
110 * Arguments:
111 * %g1 = is the handle given to you by svc_register
112 * %g2 = buf
113 * %g3 = len
114 * %g7 = return address
115 * Return value:
116 * %g1 == 0 - ok
117 * %g1 != 0 - failed
118 */
119 ENTRY(svc_internal_send)
120 !! r_svc = %g1
121 !! r_tmp0 = %g4
122 !! r_tmp1 = %g5
123 LOCK(r_svc, SVC_CTRL_LOCK, r_tmp0, r_tmp1)
124 ld [r_svc + SVC_CTRL_CONFIG], r_tmp0 ! get status
125 btst SVC_CFG_TX, r_tmp0
126 bnz,pt %xcc, 1f ! cant TX on this SVC
127 ld [r_svc + SVC_CTRL_STATE], r_tmp0
128
129 mov -1, %g2 ! return FAILED.
130.svc_internal_send_fail:
1312: UNLOCK(r_svc, SVC_CTRL_LOCK)
132 mov %g2, %g1
133 HVRET
134
1351: btst SVC_FLAGS_TP, r_tmp0 ! TX pending?
136 bnz,a,pn %xcc, .svc_internal_send_fail
137 mov -2, %g2
138 ld [r_svc + SVC_CTRL_MTU], r_tmp0 ! size
139 dec SVC_PKT_SIZE, r_tmp0 ! mtu -= hdr
140 cmp r_len, r_tmp0
141 bgu,a,pn %xcc, .svc_internal_send_fail ! failed - too big!!
142 mov -3, %g2
143 ld [r_svc + SVC_CTRL_STATE], r_tmp0 ! get state flags
144 or r_tmp0, SVC_FLAGS_TP, r_tmp0
145 st r_tmp0, [r_svc SVC_CTRL_STATE]
146 UNLOCK(r_svc, SVC_CTRL_LOCK) ! set state
147 !! r_svc = %g1
148 !! r_tmp0 = %g4
149 !! r_tmp1 = %g5
150 !! r_svcbuf = %g6
151 ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], r_svcbuf
152 ld [r_svc + SVC_CTRL_XID], r_tmp0
153 st r_tmp0, [r_svcbuf + SVC_PKT_XID] ! xpid
154 sth %g0, [r_svcbuf + SVC_PKT_SUM] ! checksum=0
155 ld [r_svc + SVC_CTRL_SID], r_tmp0
156 sth r_tmp0, [r_svcbuf + SVC_PKT_SID] ! svcid
157 add r_len, SVC_PKT_SIZE, r_tmp0
158 stx r_tmp0, [r_svc + SVC_CTRL_SEND + SVC_LINK_SIZE] ! total size
159 add r_svcbuf, SVC_PKT_SIZE, r_tmp0 ! dest
160 SMALL_COPY_MACRO(r_buf, r_len, r_tmp0, r_tmp1)
161 ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_SIZE], r_len
162 CHECKSUM_PKT(r_svcbuf, r_len, r_buf, r_tmp0, r_tmp1) !
163 ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], r_svcbuf
164 sth r_buf, [r_svcbuf + SVC_PKT_SUM] ! checksum
165#undef r_svcbuf
166#undef r_buf
167#undef r_len
168#define r_root %g2
169#define r_tmp2 %g3
170#define r_tmp3 %g6
1711: ROOT_STRUCT(r_root) ! date root
172 ldx [r_root + CONFIG_SVCS], r_root ! svc root
173 brz,a,pn r_root, .svc_internal_send_return ! failed!
174 mov -4, %g1
175 LOCK(r_root, HV_SVC_DATA_LOCK, r_tmp0, r_tmp1)
176 ldx [r_root + HV_SVC_DATA_SENDT], r_tmp0 ! Tail
177 brz,pt r_tmp0, 1f
178 stx %g0, [r_svc + SVC_CTRL_SEND + SVC_LINK_NEXT] ! svc->next = 0
179 /* Tail was non NULL */
180 stx r_svc, [r_tmp0 + SVC_CTRL_SEND + SVC_LINK_NEXT]
1811: ldx [r_root + HV_SVC_DATA_SENDH], r_tmp0 ! Head
182 brnz,pt r_tmp0, 2f
183 stx r_svc, [r_root + HV_SVC_DATA_SENDT] ! set Tail
184 stx r_svc, [r_root + HV_SVC_DATA_SENDH]
185
186 /* If fpga is busy, don't send */
187 lduw [r_root + HV_SVC_DATA_SENDBUSY], r_tmp3
188 brnz,pn r_tmp3, 2f
189 nop
190
191 /* Head == NULL.. copy to SRAM, hit TX, enable SSI interrupts.. */
192 SEND_SVC_PACKET(r_root, r_svc, r_tmp0, r_tmp1, r_tmp2, r_tmp3)
1932:
194 UNLOCK(r_root, HV_SVC_DATA_LOCK)
195 mov 0, %g1
196.svc_internal_send_return:
197 HVRET
198 SET_SIZE(svc_internal_send)
199#undef r_svc
200#undef r_buf
201#undef r_len
202#undef r_tmp1
203#undef r_tmp2
204
205#define r_svc %g1
206#define r_buf %g2
207#define r_len %g3
208#define r_tmp0 %g4
209#define r_tmp1 %g5
210#define r_svcbuf %g6
211/*
212 * svc_internal_send_nolock - Use this to send a packet from inside
213 * the hypervisor. Caller is responsible for managing the sevices locks
214 *
215 * Arguments:
216 * %g1 = is the handle given to you by svc_register
217 * %g2 = buf
218 * %g3 = len
219 * %g7 = return address
220 * Return value:
221 * %g1 == 0 - ok
222 * %g1 != 0 - failed
223 */
224 ENTRY(svc_internal_send_nolock)
225 ld [r_svc + SVC_CTRL_MTU], r_tmp0 ! size
226 dec SVC_PKT_SIZE, r_tmp0 ! mtu -= hdr
227 cmp r_len, r_tmp0
228 bgu,a,pn %xcc, .svc_internal_send_fail_nolock ! failed - too big!!
229 mov -3, %g2
230 ld [r_svc + SVC_CTRL_STATE], r_tmp0 ! get state flags
231 or r_tmp0, SVC_FLAGS_TP, r_tmp0
232 st r_tmp0, [r_svc SVC_CTRL_STATE]
233 !! r_svc = %g1
234 !! r_tmp0 = %g4
235 !! r_tmp1 = %g5
236 !! r_svcbuf = %g6
237 ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], r_svcbuf
238 ld [r_svc + SVC_CTRL_XID], r_tmp0
239 st r_tmp0, [r_svcbuf + SVC_PKT_XID] ! xpid
240 sth %g0, [r_svcbuf + SVC_PKT_SUM] ! checksum=0
241 ld [r_svc + SVC_CTRL_SID], r_tmp0
242 sth r_tmp0, [r_svcbuf + SVC_PKT_SID] ! svcid
243 add r_len, SVC_PKT_SIZE, r_tmp0
244 stx r_tmp0, [r_svc + SVC_CTRL_SEND + SVC_LINK_SIZE] ! total size
245 add r_svcbuf, SVC_PKT_SIZE, r_tmp0 ! dest
246 SMALL_COPY_MACRO(r_buf, r_len, r_tmp0, r_tmp1)
247 ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_SIZE], r_len
248 CHECKSUM_PKT(r_svcbuf, r_len, r_buf, r_tmp0, r_tmp1) !
249 ldx [r_svc + SVC_CTRL_SEND + SVC_LINK_PA], r_svcbuf
250 sth r_buf, [r_svcbuf + SVC_PKT_SUM] ! checksum
251#undef r_svcbuf
252#undef r_buf
253#undef r_len
254#define r_root %g2
255#define r_tmp2 %g3
256#define r_tmp3 %g6
2571: ROOT_STRUCT(r_root) ! data root
258 ldx [r_root + CONFIG_SVCS], r_root ! svc root
259 brz,a,pn r_root, .svc_internal_send_return ! failed!
260 mov -4, %g1
261 ldx [r_root + HV_SVC_DATA_SENDT], r_tmp0 ! Tail
262 brz,pt r_tmp0, 1f
263 stx %g0, [r_svc + SVC_CTRL_SEND + SVC_LINK_NEXT] ! svc->next = 0
264 /* Tail was non NULL */
265 stx r_svc, [r_tmp0 + SVC_CTRL_SEND + SVC_LINK_NEXT]
2661: ldx [r_root + HV_SVC_DATA_SENDH], r_tmp0 ! Head
267 brnz,pt r_tmp0, 2f
268 stx r_svc, [r_root + HV_SVC_DATA_SENDT] ! set Tail
269 /* Head == NULL.. copy to SRAM, hit TX, enable SSI interrupts.. */
270 SEND_SVC_PACKET(r_root, r_svc, r_tmp0, r_tmp1, r_tmp2, r_tmp3)
271 stx r_svc, [r_root + HV_SVC_DATA_SENDH]
2722:
273 mov 0, %g1
274.svc_internal_send_return_nolock:
275.svc_internal_send_fail_nolock:
276 HVRET
277 SET_SIZE(svc_internal_send_nolock)
278#undef r_svc
279#undef r_buf
280#undef r_len
281#undef r_tmp1
282#undef r_tmp2
283
284#if 0 /* XXX unused? need to wire up for virtual interrupts */
285/*
286 * svc_internal_getstate - check state of a channel
287 *
288 * Arguments:
289 * %g1 is the handle given to you by svc_register
290 * Return value:
291 * %g1 is the service state value (SVC_CTRL_STATE)
292 */
293 ENTRY(svc_internal_getstate)
294 jmp %g7 + 4
295 ld [%g1 + SVC_CTRL_STATE], %g1
296 SET_SIZE(svc_internal_getstate)
297#endif
298
299#endif /* CONFIG_SVC */