Commit | Line | Data |
---|---|---|
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 ;\ | |
80 | 1: lduh [addr], tmp0 ;\ | |
81 | add tmp0, sum, sum ;\ | |
82 | deccc 2, len ;\ | |
83 | bgt,pt %xcc, 1b ;\ | |
84 | inc 2, addr ;\ | |
85 | 2: 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: | |
131 | 2: UNLOCK(r_svc, SVC_CTRL_LOCK) | |
132 | mov %g2, %g1 | |
133 | HVRET | |
134 | ||
135 | 1: 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 | |
171 | 1: 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] | |
181 | 1: 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) | |
193 | 2: | |
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 | |
257 | 1: 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] | |
266 | 1: 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] | |
272 | 2: | |
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 */ |