Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: svc_init.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 "@(#)svc_init.c 1.4 07/08/14 SMI" | |
50 | ||
51 | #ifdef CONFIG_SVC | |
52 | #include <stdarg.h> | |
53 | #include <sys/htypes.h> | |
54 | #include <vdev_ops.h> | |
55 | #include <vdev_intr.h> | |
56 | #include <ncs.h> | |
57 | #include <cyclic.h> | |
58 | #include <vcpu.h> | |
59 | #include <strand.h> | |
60 | #include <guest.h> | |
61 | #include <md.h> | |
62 | #include <debug.h> | |
63 | ||
64 | #include <svc.h> | |
65 | #include <svc_vbsc.h> | |
66 | ||
67 | ||
68 | static uint64_t | |
69 | c_svc_register(uint64_t cookie, uint64_t xid, uint64_t sid, uint64_t recv, | |
70 | uint64_t send) | |
71 | { | |
72 | hv_svc_data_t *r_svcp = config.svc; | |
73 | ||
74 | if (r_svcp != NULL) { | |
75 | svc_ctrl_t *r_svcsp = r_svcp->svcs; | |
76 | int i; | |
77 | ||
78 | /* for the requested services */ | |
79 | for (i = r_svcp->num_svcs; i > 0; i--, r_svcsp++) { | |
80 | ||
81 | if ((r_svcsp->xid == xid) && (r_svcsp->sid == sid)) { | |
82 | /* | |
83 | * attach the callbacks to this service | |
84 | * Ensure intrs are disabled on the channel | |
85 | * and set the CALLBACK flag in both the svc | |
86 | * config and state variables | |
87 | */ | |
88 | r_svcsp->config |= SVC_CFG_CALLBACK; | |
89 | r_svcsp->state |= SVC_CFG_CALLBACK; | |
90 | r_svcsp->callback.rx = (uint64_t)recv; | |
91 | r_svcsp->callback.tx = (uint64_t)send; | |
92 | r_svcsp->callback.cookie = cookie; | |
93 | return ((uint64_t)r_svcsp); | |
94 | } | |
95 | } | |
96 | } | |
97 | return (0); | |
98 | } | |
99 | ||
100 | /* | |
101 | * c_setup_err_svc - setup error service channel | |
102 | */ | |
103 | static void | |
104 | c_setup_err_svc() | |
105 | { | |
106 | uint64_t rv; | |
107 | strand_t *sp = c_mystrand(); | |
108 | ||
109 | rv = c_svc_register((uint64_t)sp, XPID_HV, SID_ERROR, | |
110 | (uint64_t)error_svc_rx, (uint64_t)error_svc_tx); | |
111 | ||
112 | if (rv == 0) { | |
113 | DBGINIT(c_printf("WARNING:c_setup_err_svc register fail\r\n")); | |
114 | } | |
115 | config.error_svch = rv; | |
116 | } | |
117 | ||
118 | #ifdef CONFIG_VBSC_SVC | |
119 | ||
120 | /* | |
121 | * c_setup_vbsc_svc - setup vbsc service channel | |
122 | */ | |
123 | static void | |
124 | c_setup_vbsc_svc() | |
125 | { | |
126 | uint64_t rv; | |
127 | strand_t *sp = c_mystrand(); | |
128 | ||
129 | /* Put error_svc handle into the debug structure */ | |
130 | config.vbsc_dbgerror.error_svch = config.error_svch; | |
131 | ||
132 | rv = c_svc_register((uint64_t)sp, XPID_HV, SID_VBSC_CTL, | |
133 | (uint64_t)vbsc_rx, (uint64_t)vbsc_tx); | |
134 | ||
135 | if (rv) { | |
136 | config.vbsc_svch = rv; | |
137 | } else { | |
138 | c_hvabort(-1); | |
139 | } | |
140 | } | |
141 | ||
142 | /* | |
143 | * c_vbsc_send_polled - send a vbsc command and poll for response | |
144 | */ | |
145 | static void | |
146 | c_vbsc_send_polled(uint64_t cmd1, uint64_t cmd2, uint64_t cmd3) | |
147 | { | |
148 | uint16_t fpga_cmd_offset; | |
149 | volatile uint8_t *fpga_statusp; | |
150 | uint16_t *fpga_basep; | |
151 | uint64_t *fpga_cmdp; | |
152 | uint8_t fpga_cmd_status; | |
153 | ||
154 | c_vbsc_send_polled_resend: | |
155 | fpga_basep = (uint16_t *)(FPGA_Q3OUT_BASE); | |
156 | fpga_statusp = (uint8_t *)fpga_basep; | |
157 | ||
158 | fpga_cmdp = (uint64_t *)(FPGA_BASE + FPGA_SRAM_BASE); | |
159 | fpga_cmd_offset = *((uint16_t *)((uint64_t)fpga_basep + FPGA_Q_BASE)); | |
160 | ||
161 | /* sram buffer words */ | |
162 | fpga_cmdp = (uint64_t *)((uint64_t)fpga_cmdp + | |
163 | (uint64_t)fpga_cmd_offset); | |
164 | ||
165 | /* insert the command bytes */ | |
166 | *(fpga_cmdp + 2) = cmd3; | |
167 | *(fpga_cmdp + 1) = cmd2; | |
168 | *(fpga_cmdp + 0) = cmd1; | |
169 | ||
170 | /* initiate the command */ | |
171 | *((uint8_t *)((uint64_t)fpga_statusp + FPGA_Q_SEND)) = 1; | |
172 | ||
173 | /* | |
174 | * Wait for a non-zero status. If we get an ACK then we're done. | |
175 | * Otherwise re-send the packet. Failure is not an option, even | |
176 | * to hv_abort we need to send a message to vbsc. So keep trying. | |
177 | */ | |
178 | fpga_statusp = (uint8_t *)((uint64_t)fpga_statusp + FPGA_Q_STATUS); | |
179 | do { | |
180 | fpga_cmd_status = *fpga_statusp; | |
181 | fpga_cmd_status &= (QINTR_ACK | QINTR_NACK | QINTR_BUSY | |
182 | | QINTR_ABORT); | |
183 | } while (fpga_cmd_status == 0); | |
184 | ||
185 | if (fpga_cmd_status & QINTR_ACK) { | |
186 | *fpga_statusp = fpga_cmd_status; /* ack the command */ | |
187 | } else { | |
188 | goto c_vbsc_send_polled_resend; | |
189 | } | |
190 | } | |
191 | ||
192 | /* | |
193 | * c_vbsc_guest_start - send a message indicating guest is starting | |
194 | */ | |
195 | void | |
196 | c_vbsc_guest_start(uint64_t gid) | |
197 | { | |
198 | guest_t *guestp = (guest_t *)config.guests; | |
199 | ||
200 | guestp = &(guestp[gid]); | |
201 | ||
202 | c_vbsc_send_polled(VBSC_GUEST_ON, guestp->guestid + XPID_GUESTBASE, 0); | |
203 | } | |
204 | #endif /* CONFIG_VBSC_SVC */ | |
205 | ||
206 | ||
207 | /* | |
208 | * c_svc_init - initialize the service channels | |
209 | */ | |
210 | void | |
211 | c_svc_init() | |
212 | { | |
213 | hv_svc_data_t *r_svcp = config.svc; | |
214 | svc_ctrl_t *r_svcsp = r_svcp->svcs; | |
215 | int i; | |
216 | ||
217 | /* for each of the configured services */ | |
218 | for (i = r_svcp->num_svcs; i > 0; i--, r_svcsp++) { | |
219 | ||
220 | /* if there is an RCV or XMT configured */ | |
221 | if (r_svcsp->config & (SVC_CFG_RE | SVC_CFG_TE)) { | |
222 | ||
223 | if (r_svcsp->xid >= XPID_GUESTBASE) { | |
224 | guest_t *guestp = (guest_t *)config.guests; | |
225 | ||
226 | /* determine the guest for this service */ | |
227 | guestp = &(guestp[r_svcsp->xid-XPID_GUESTBASE]); | |
228 | ||
229 | /* register the interrupt; save the cookie */ | |
230 | r_svcsp->intr_cookie = c_vdev_intr_register( | |
231 | guestp, r_svcsp->ino, r_svcsp, | |
232 | svc_intr_getstate, (intr_setstate_f)NULL); | |
233 | } | |
234 | } | |
235 | } | |
236 | ||
237 | #ifdef CONFIG_FPGA | |
238 | /* | |
239 | * Mailbox hardware initialization | |
240 | */ | |
241 | { | |
242 | volatile uint8_t *fpgap; | |
243 | uint8_t tmp; | |
244 | ||
245 | /* Clear previously-pending state */ | |
246 | fpgap = (uint8_t *)(FPGA_Q_BASE + FPGA_Q_STATUS); | |
247 | tmp = *fpgap; | |
248 | *fpgap = tmp; | |
249 | ||
250 | /* Enable interrupts */ | |
251 | fpgap = (uint8_t *)(FPGA_INTR_BASE + FPGA_MBOX_INTR_ENABLE); | |
252 | *fpgap = (IRQ_QUEUE_IN|IRQ_QUEUE_OUT|IRQ_LDC_OUT); | |
253 | } | |
254 | #endif /* CONFIG_FPGA */ | |
255 | ||
256 | /* Must be before setup_vbsc_svc */ | |
257 | c_setup_err_svc(); | |
258 | ||
259 | #ifdef CONFIG_VBSC_SVC | |
260 | DBGINIT(c_printf("c_svc_init: setup vbsc_svc\n")); | |
261 | c_setup_vbsc_svc(); | |
262 | #endif /* CONFIG_VBSC_SVC */ | |
263 | } | |
264 | #endif /* CONFIG_SVC */ |