Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / huron / src / rng.s
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: rng.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 "@(#)rng.s 1.2 07/07/19 SMI"
50
51 .file "rng.s"
52
53#include <sys/asm_linkage.h>
54#include <sys/htypes.h>
55#include <asi.h>
56#include <mmu.h>
57#include <hypervisor.h>
58#include <rng_api.h>
59#include <rng.h>
60#include <sun4v/asi.h>
61#include <sparcv9/asi.h>
62
63#include <debug.h>
64#include <offsets.h>
65#include <util.h>
66
67/*
68 * Delay necessary because of how CTL bits are serially
69 * sent to RNG hardware.
70 */
71#define CTL_REG_DELAY_CYCLES 64
72
73#define CTL_REG_DELAY(scr) \
74 .pushlocals ; \
75 mov CTL_REG_DELAY_CYCLES, scr ; \
760: ; \
77 brnz,pt scr, 0b ; \
78 dec scr ; \
79 .poplocals
80
81/*
82 * Locking primitives for RNG_LOCK
83 */
84#define RNG_TRYLOCK(rng, scr, lck) \
85 mov -1, lck ; \
86 add rng, RNG_LOCK, scr ; \
87 casa [scr]ASI_P, %g0, lck
88
89#define RNG_UNLOCK(rng) \
90 st %g0, [rng + RNG_LOCK]
91
92
93/*
94 *-----------------------------------------------------------
95 * Function: rng_get_diag_control()
96 * Arguments:
97 * Input:
98 * Output:
99 * %o0 - EOK (on success),
100 * EWOULDBLOCK, ENOACCESS (on failure)
101 *-----------------------------------------------------------
102 */
103 ENTRY_NP(hcall_rng_get_diag_control)
104
105 /*
106 * Check that caller has CTL access.
107 */
108 GUEST_STRUCT(%g3)
109 setx GUEST_RNG_CTL_ACCESSIBLE, %g5, %g2
110 ldx [%g3 + %g2], %g2
111 brz,a,pn %g2, herr_noaccess
112 nop
113
114 ROOT_STRUCT(%g4)
115 ldx [%g4 + CONFIG_RNG], %g1
116
117 RNG_TRYLOCK(%g1, %g5, %g2)
118 brnz,pn %g2, herr_wouldblock
119 nop
120
121 ldx [%g3 + GUEST_GID], %g3
122 stx %g3, [%g1 + RNG_CTL + RNG_CTLDATA_GUESTID]
123
124 RNG_UNLOCK(%g1)
125
126 HCALL_RET(EOK)
127
128 SET_SIZE(hcall_rng_get_diag_control)
129
130/*
131 *-----------------------------------------------------------
132 * Function: rng_ctl_read(struct rng_ctlregs rctlptr)
133 * Arguments:
134 * Input:
135 * %o0 - struct rng_ctlregs pointer
136 * Output:
137 * %o0 - EOK (on success),
138 * EWOULDBLOCK, ENOACCESS, EBADALIGN, ENORADDR (on failure)
139 * %o1 - RNG state
140 * %o2 - Ready delta (system ticks)
141 *-----------------------------------------------------------
142 */
143 ENTRY_NP(hcall_rng_ctl_read)
144
145 btst SZ_LONG - 1, %o0
146 bnz,pn %xcc, herr_badalign
147 nop
148
149 /*
150 * Check that caller has CTL access.
151 */
152 GUEST_STRUCT(%g3)
153 setx GUEST_RNG_CTL_ACCESSIBLE, %g5, %g4
154 ldx [%g3 + %g4], %g4
155 brz,pn %g4, herr_noaccess
156 nop
157
158 ROOT_STRUCT(%g4)
159 ldx [%g4 + CONFIG_RNG], %g1
160
161 brz,pn %o0, rdc_noregs
162 nop
163
164 mov RNG_CTLREGS_SIZE, %g2
165 RA2PA_RANGE_CONV_UNK_SIZE(%g3, %o0, %g2, herr_noraddr, %g5, %g4)
166 ! %g4 PA
167
168rdc_noregs:
169 RNG_TRYLOCK(%g1, %g5, %g2)
170 brnz,a,pn %g2, herr_wouldblock
171 mov %g0, %o2
172
173 ldx [%g1 + RNG_CTL + RNG_CTLDATA_STATE], %o1
174 ldx [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME], %g3
175 rd STICK, %g5 ! current time
176 sub %g3, %g5, %o2
177 cmp %g5, %g3
178 movgeu %xcc, %g0, %o2 ! delta
179
180 brz,pn %o0, rdc_ret
181 nop
182
183 ldx [%g1 + RNG_CTL + RNG_CTLDATA_REGS + RNG_CTLREGS_REG0], %g3
184 stx %g3, [%g4 + RNG_CTLREGS_REG0]
185 ldx [%g1 + RNG_CTL + RNG_CTLDATA_REGS + RNG_CTLREGS_REG1], %g3
186 stx %g3, [%g4 + RNG_CTLREGS_REG1]
187 ldx [%g1 + RNG_CTL + RNG_CTLDATA_REGS + RNG_CTLREGS_REG2], %g3
188 stx %g3, [%g4 + RNG_CTLREGS_REG2]
189 ldx [%g1 + RNG_CTL + RNG_CTLDATA_REGS + RNG_CTLREGS_REG3], %g3
190 stx %g3, [%g4 + RNG_CTLREGS_REG3]
191
192rdc_ret:
193 RNG_UNLOCK(%g1)
194
195 HCALL_RET(EOK)
196
197 SET_SIZE(hcall_rng_ctl_read)
198
199/*
200 *-----------------------------------------------------------
201 * Function: rng_ctl_write(struct rng_ctlregs rctlptr, uint64_t nstate,
202 * uint64_t wtimeout)
203 * Arguments:
204 * Input:
205 * %o0 - struct rng_ctlregs pointer
206 * %o1 - New state
207 * %o2 - Watchdog timeout (system ticks)
208 * Output:
209 * %o0 - EOK (on success),
210 * EWOULDBLOCK, ENOACCESS, EBADALIGN, ENORADDR,
211 * EIO, EINVAL (on failure)
212 * %o1 - Ready delta (system ticks)
213 *-----------------------------------------------------------
214 */
215 ENTRY_NP(hcall_rng_ctl_write)
216
217 btst SZ_LONG - 1, %o0
218 bnz,pn %xcc, herr_badalign
219 nop
220
221 /*
222 * Check that caller has diagnostic access & control.
223 */
224 GUEST_STRUCT(%g3)
225 setx GUEST_RNG_CTL_ACCESSIBLE, %g5, %g4
226 ldx [%g3 + %g4], %g4
227 brz,pn %g4, herr_noaccess
228 nop
229
230 mov RNG_CTLREGS_SIZE, %g2
231 RA2PA_RANGE_CONV_UNK_SIZE(%g3, %o0, %g2, herr_noraddr, %g5, %g7)
232 mov %g7, %o0
233 ! %o0 PA
234
235 ROOT_STRUCT(%g4)
236 ldx [%g4 + CONFIG_RNG], %g1
237
238 RNG_TRYLOCK(%g1, %g5, %g2)
239 brnz,a,pn %g2, herr_wouldblock
240 mov %g0, %o1
241
242 ldx [%g3 + GUEST_GID], %g5
243 ldx [%g1 + RNG_CTL + RNG_CTLDATA_GUESTID], %g4
244 cmp %g5, %g4
245 bne,a,pn %xcc, wrc_ret
246 mov EIO, %g6
247
248 cmp %o1, RNG_STATE_CONFIGURED
249 be,pt %xcc, wrc_config
250 cmp %o1, RNG_STATE_HEALTHCHECK
251 be,pn %xcc, wrc_config
252 cmp %o1, RNG_STATE_UNCONFIGURED
253 be,pn %xcc, wrc_unconfig
254 cmp %o1, RNG_STATE_ERROR
255 bne,a,pn %xcc, wrc_ret
256 mov EINVAL, %g6
257
258wrc_unconfig:
259 /*
260 * newstate = UNCONFIGURED or ERROR.
261 */
262 stx %o1, [%g1 + RNG_CTL + RNG_CTLDATA_STATE]
263 ldx [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME], %g4
264 rd STICK, %g5 ! current time
265 sub %g4, %g5, %o1
266 cmp %g5, %g4
267 movgeu %xcc, %g0, %o1
268 ba wrc_ret
269 mov EOK, %g6
270
271wrc_config:
272 /*
273 * newstate = CONFIGURED or HEALTHCHECK.
274 *
275 * Verify that CTL is ready to be changed.
276 */
277 ldx [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME], %g4
278 rd STICK, %g5 ! current time
279 mov EWOULDBLOCK, %g6
280 cmp %g5, %g4
281 bl,a,pn %xcc, wrc_ret
282 sub %g4, %g5, %o1
283
284 stx %g5, [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME]
285
286 setx RNG_CTL_MASK, %g6, %g2
287 /*
288 * Check callers CTLREG values and make sure they are
289 * valid values first.
290 */
291 ldx [%o0 + RNG_CTLREGS_REG0], %g3
292 andncc %g3, %g2, %g0
293 bnz,a,pn %xcc, wrc_ret
294 mov EINVAL, %g6
295 ldx [%o0 + RNG_CTLREGS_REG1], %g4
296 andncc %g4, %g2, %g0
297 bnz,a,pn %xcc, wrc_ret
298 mov EINVAL, %g6
299 ldx [%o0 + RNG_CTLREGS_REG2], %g5
300 andncc %g5, %g2, %g0
301 bnz,a,pn %xcc, wrc_ret
302 mov EINVAL, %g6
303 ldx [%o0 + RNG_CTLREGS_REG3], %g6
304 andncc %g6, %g2, %g0
305 bnz,a,pn %xcc, wrc_ret
306 mov EINVAL, %g6
307 /*
308 * Values are valid. Save a copy off in our CTLDATA.
309 */
310 stx %g3, [%g1 + RNG_CTL + RNG_CTLDATA_REGS + RNG_CTLREGS_REG0]
311 stx %g4, [%g1 + RNG_CTL + RNG_CTLDATA_REGS + RNG_CTLREGS_REG1]
312 stx %g5, [%g1 + RNG_CTL + RNG_CTLDATA_REGS + RNG_CTLREGS_REG2]
313 stx %g6, [%g1 + RNG_CTL + RNG_CTLDATA_REGS + RNG_CTLREGS_REG3]
314 /*
315 * Store values into RNG.CTL.
316 * The RNG hardware control register is funky. You store
317 * to different control registers by specifying different
318 * bits in the value being stored, but all stores happen
319 * against the same RNG.CTL address.
320 */
321 setx RNG_CTL_ADDR, %o0, %g2
322 stx %g3, [%g2]
323 CTL_REG_DELAY(%o0)
324 stx %g4, [%g2]
325 CTL_REG_DELAY(%o0)
326 stx %g5, [%g2]
327 CTL_REG_DELAY(%o0)
328 stx %g6, [%g2]
329 CTL_REG_DELAY(%o0)
330 /*
331 * If caller specified a watchdog timeout value of 0,
332 * then that means no watchdog necessary. If caller
333 * specified negative value then overwrite to 0.
334 */
335 cmp %o2, %g0
336 movl %xcc, %g0, %o2
337 rd STICK, %g5
338 add %g5, %o2, %g5
339 stx %g5, [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME]
340 stx %o1, [%g1 + RNG_CTL + RNG_CTLDATA_STATE]
341 mov %o2, %o1
342 mov EOK, %g6
343
344wrc_ret:
345 RNG_UNLOCK(%g1)
346
347 HCALL_RET(%g6)
348
349 SET_SIZE(hcall_rng_ctl_write)
350
351/*
352 *-----------------------------------------------------------
353 * Function: rng_data_read_diag(uint64_t addr, uint64_t sz)
354 * Arguments:
355 * Input:
356 * %o0 - Address of data buffer
357 * %o1 - Size of data buffer (bytes)
358 * Output:
359 * %o0 - EOK (on success),
360 * EWOULDBLOCK, ENOACCESS, EBADALIGN, ENORADDR,
361 * EIO, EINVAL (on failure)
362 * %o1 - Ready delta (system ticks)
363 *-----------------------------------------------------------
364 */
365 ENTRY_NP(hcall_rng_data_read_diag)
366
367 btst SZ_LONG - 1, %o0
368 bnz,pn %xcc, herr_badalign
369 nop
370
371 /*
372 * Check that caller has diagnostic access & control.
373 */
374 GUEST_STRUCT(%g3)
375 setx GUEST_RNG_CTL_ACCESSIBLE, %g5, %g4
376 ldx [%g3 + %g4], %g4
377 brz,pn %g4, herr_noaccess
378 nop
379
380 /*
381 * Verify size falls within desired range:
382 * RNG_DATA_MINLEN...RNG_DATA_MAXLEN
383 */
384 btst SZ_LONG - 1, %o1
385 bnz,pn %xcc, herr_badalign
386 nop
387 setx RNG_DATA_MAXLEN, %g5, %g4
388 cmp %o1, %g4
389 bgu,pn %xcc, herr_inval
390 cmp %o1, RNG_DATA_MINLEN
391 blu,pn %xcc, herr_inval
392 nop
393
394 RA2PA_RANGE_CONV_UNK_SIZE(%g3, %o0, %o1, herr_noraddr, %g2, %g7)
395 mov %g7, %o0
396
397 ROOT_STRUCT(%g4)
398 ldx [%g4 + CONFIG_RNG], %g1
399
400 RNG_TRYLOCK(%g1, %g5, %g2)
401 brnz,a,pn %g2, herr_wouldblock
402 mov %g0, %o1
403
404 ldx [%g3 + GUEST_GID], %g5
405 ldx [%g1 + RNG_CTL + RNG_CTLDATA_GUESTID], %g4
406 cmp %g5, %g4
407 bne,a,pn %xcc, rdg_ret
408 mov EIO, %g6
409
410 /*
411 * Check that the RNG is ready,
412 * i.e. STICK >= ctldata.readytime.
413 */
414 ldx [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME], %g4
415 rd STICK, %g5 ! current time
416 mov EWOULDBLOCK, %g6
417 cmp %g5, %g4
418 bl,a,pn %xcc, rdg_ret
419 sub %g4, %g5, %o1
420
421 stx %g5, [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME]
422
423 setx RNG_DATA_ADDR, %g3, %g4
424
425rdg_rdloop:
426 ldx [%g4], %g3 ! read RNG.DATA
427 stx %g3, [%o0]
428 sub %o1, SZ_LONG, %o1
429 brgz,pt %o1, rdg_rdloop
430 add %o0, SZ_LONG, %o0
431
432 mov EOK, %g6
433 !!
434 !! %o1 == 0 after loop.
435 !!
436
437rdg_ret:
438 RNG_UNLOCK(%g1)
439
440 HCALL_RET(%g6)
441
442 SET_SIZE(hcall_rng_data_read_diag)
443
444/*
445 *-----------------------------------------------------------
446 * Function: rng_data_read(uint64_t addr)
447 * Arguments:
448 * Input:
449 * %o0 - Address of data buffer (size = 8 bytes)
450 * Output:
451 * %o0 - EOK (on success),
452 * EWOULDBLOCK, ENOACCESS, EBADALIGN, ENORADDR,
453 * EIO (on failure)
454 * %o1 - Ready delta (system ticks)
455 *-----------------------------------------------------------
456 */
457 ENTRY_NP(hcall_rng_data_read)
458
459 btst SZ_LONG - 1, %o0
460 bnz,pn %xcc, herr_badalign
461 nop
462
463 GUEST_STRUCT(%g3)
464
465 mov SZ_LONG, %g5
466 RA2PA_RANGE_CONV_UNK_SIZE(%g3, %o0, %g5, herr_noraddr, %g2, %g7)
467 mov %g7, %o0
468 !!
469 !! %o0 = physical address of buffer
470 !!
471
472 ROOT_STRUCT(%g4)
473 ldx [%g4 + CONFIG_RNG], %g1
474
475 RNG_TRYLOCK(%g1, %g5, %g2)
476 brnz,pn %g2, herr_wouldblock
477 mov %g0, %o1 ! *tdelta = 0
478
479 ldx [%g1 + RNG_CTL + RNG_CTLDATA_STATE], %g4
480 cmp %g4, RNG_STATE_CONFIGURED
481 be,pt %xcc, rdd_chkrdy
482 ldx [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME], %g2
483
484 mov EIO, %g6
485 cmp %g4, RNG_STATE_ERROR
486 ba rdd_ret
487 move %xcc, ENOACCESS, %g6
488
489rdd_chkrdy:
490 rd STICK, %g3 ! current time
491 sub %g2, %g3, %o1
492 cmp %g3, %g2
493 bl,pn %xcc, rdd_ret
494 mov EWOULDBLOCK, %g6
495
496 stx %g3, [%g1 + RNG_CTL + RNG_CTLDATA_READYTIME]
497
498 setx RNG_DATA_ADDR, %g3, %g4
499 ldx [%g4], %g3 ! read RNG.DATA
500 stx %g3, [%o0]
501 mov EOK, %g6
502
503rdd_ret:
504 RNG_UNLOCK(%g1)
505
506 HCALL_RET(%g6)
507
508 SET_SIZE(hcall_rng_data_read)