Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / common / include / util.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: util.h
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#ifndef _UTIL_H
50#define _UTIL_H
51
52#pragma ident "@(#)util.h 1.22 07/09/11 SMI"
53
54#ifdef __cplusplus
55extern "C" {
56#endif
57
58#include <vcpu.h>
59#include <abort.h>
60#include <strand.h>
61#include <platform/util.h>
62
63/*
64 * Size generation constants
65 */
66#define KB * 1024
67#define MB * 1024LL KB
68#define GB * 1024LL MB
69
70/*
71 * Time constants
72 */
73#define MHZ * 1000000
74#define NS_PER_S 1000000000
75#define MS_PER_NS 1000000
76
77/*
78 * L2$ line state
79 */
80#define L2_LINE_CLEAN 0
81#define L2_LINE_DIRTY 1
82#define L2_LINE_INVALID 2
83#define L2_LINE_NOT_FOUND 3
84
85/*
86 * prefetch function to invalidate an L2$ line
87 */
88#define INVALIDATE_CACHE_LINE 0x18
89
90/* BEGIN CSTYLED */
91
92/*
93 * VCPU2GUEST_STRUCT - get the current guestp from a vcpup
94 *
95 * Delay Slot: safe in a delay slot
96 * Register overlap: vcpu and root may be the same register
97 */
98#define VCPU2GUEST_STRUCT(vcpu, guest) \
99 ldx [vcpu + CPU_GUEST], guest
100
101
102/* FIXME: do we ever use the following? */
103/*
104 * VCPU2ROOT_STRUCT - get the rootp from a vcpup
105 *
106 * Delay Slot: safe in a delay slot if vcpup is valid
107 * Register overlap: vcpu and root may be the same register
108 */
109#define VCPU2ROOT_STRUCT(vcpu, root) \
110 ldx [vcpu + CPU_ROOT], root
111
112
113/*
114 * VCPU2STRAND_STRUCT - get the current strandp from a vcpup
115 *
116 * Delay Slot: safe in a delay slot
117 * Register overlap: vcpu and strand may be the same register
118 */
119#define VCPU2STRAND_STRUCT(vcpu, strand) \
120 ldx [vcpu + CPU_STRAND], strand
121
122
123#define HSCRATCH_STRAND_STRUCT HSCRATCH0
124#define HSCRATCH_VCPU_STRUCT HSCRATCH1
125#define SCRATCHPAD_MEMBAR /* nothing for niagara */
126
127/*
128 * VCPU_STRUCT - get the current vcpup from scratch
129 *
130 * Delay Slot: not safe in a delay slot
131 */
132#define VCPU_STRUCT(vcpu) \
133 mov HSCRATCH_VCPU_STRUCT, vcpu ;\
134 ldxa [vcpu]ASI_HSCRATCHPAD, vcpu
135
136/*
137 * SET_VCPU_STRUCT - set the vcpup into scratch
138 */
139#define SET_VCPU_STRUCT(vcpu, scr1) \
140 mov HSCRATCH_VCPU_STRUCT, scr1 ;\
141 stxa vcpu, [scr1]ASI_HSCRATCHPAD ;\
142 SCRATCHPAD_MEMBAR
143
144/*
145 * STRAND_STRUCT - get the current strandp from scratch
146 *
147 * Delay Slot: not safe in a delay slot
148 */
149#define STRAND_STRUCT(strand) \
150 mov HSCRATCH_STRAND_STRUCT, strand ;\
151 ldxa [strand]ASI_HSCRATCHPAD, strand
152
153/*
154 * SET_STRAND_STRUCT - set the strandp into scratch
155 */
156#define SET_STRAND_STRUCT(strand, scr1) \
157 mov HSCRATCH_STRAND_STRUCT, scr1 ;\
158 stxa strand, [scr1]ASI_HSCRATCHPAD ;\
159 SCRATCHPAD_MEMBAR
160
161/*
162 * STRAND2CONFIG_STRUCT - get the current configp from strandp
163 */
164#define STRAND2CONFIG_STRUCT(strand, configp) \
165 ldx [strand + STRAND_CONFIGP], configp
166
167/*
168 * CONFIG_STRUCT - get the current configp from scratch
169 *
170 * Delay Slot: safe in a delay slot
171 */
172#define CONFIG_STRUCT(configp) \
173 STRAND_STRUCT(configp) ;\
174 STRAND2CONFIG_STRUCT(configp, configp)
175
176 /* For the moment alias */
177#define ROOT_STRUCT(configp) CONFIG_STRUCT(configp)
178
179/*
180 * LOCK_ADDR - get the lock address from scratch
181 *
182 * Delay Slot: not safe in a delay slot
183 */
184#define LOCK_ADDR(LOCK, addr) \
185 CONFIG_STRUCT(addr) ;\
186 inc LOCK, addr
187
188
189/*
190 * VCPU_GUEST_STRUCT - get both the current vcpup and guestp from scratch
191 *
192 * Delay Slot: not safe in a delay slot
193 * Register overlap: if vcpu and guest are the same then only the guest
194 * is returned, see GUEST_STRUCT
195 */
196#define VCPU_GUEST_STRUCT(vcpu, guest) \
197 VCPU_STRUCT(vcpu) ;\
198 VCPU2GUEST_STRUCT(vcpu, guest)
199
200
201/*
202 * GUEST_STRUCT - get the current guestp from scratch
203 *
204 * Delay Slot: safe in a delay slot
205 */
206#define GUEST_STRUCT(guest) \
207 VCPU_GUEST_STRUCT(guest, guest)
208
209
210/*
211 * CTRL_DOMAIN - returns the service domain guest structure ptr
212 *
213 * Delay Slot: Safe in a delay slot
214 */
215#define CTRL_DOMAIN(guestp, scr1, scr2) \
216 CONFIG_STRUCT(scr1) ;\
217 ldx [scr1 + CONFIG_HVCTL_LDC], scr2 ;\
218 mulx scr2, LDC_ENDPOINT_SIZE, scr2 ;\
219 ldx [scr1 + CONFIG_HV_LDCS], guestp ;\
220 add guestp, scr2, guestp ;\
221 ldx [guestp + LDC_TARGET_GUEST], guestp
222
223/*
224 * PID2CPUP - convert physical cpu number to a pointer to the vcpu
225 * cpu structure thats currently running on it.
226 * FIXME: This needs removing .. including all uses
227 * because it's just rubbish!
228 */
229#define PID2VCPUP(pid, cpup, scr1, scr2) \
230 .pushlocals ;\
231 mov %g0, scr2 ;\
2321: ;\
233 cmp scr2, (NVCPUS - 1) ;\
234 bg,a 2f ;\
235 mov %g0, cpup ;\
236 set VCPU_SIZE, scr1 ;\
237 mulx scr2, scr1, cpup ;\
238 CONFIG_STRUCT(scr1) ;\
239 ldx [scr1 + CONFIG_VCPUS], scr1 ;\
240 add scr1, cpup, cpup ;\
241 VCPU2STRAND_STRUCT(cpup, scr1) ;\
242 ldub [scr1 + STRAND_ID], scr1 ;\
243 cmp scr1, pid ;\
244 bne,a %icc, 1b ;\
245 inc scr2 ;\
2462: ;\
247 .poplocals
248
249
250/* the VCPUID2CPUP macro below assumes the array step is 8 */
251#if GUEST_VCPUS_INCR != 8
252#error "GUEST_VCPUS_INCR is not 8"
253#endif
254
255#define GUEST_VCPUS_SHIFT 3
256
257/*
258 * VCPUID2CPUP - convert a guest virtual cpu number to a pointer
259 * to the corresponding virtual cpu struct
260 *
261 * Register overlap: vcpuid and cpup may be the same register
262 * Delay Slot: safe in a delay slot
263 */
264#define VCPUID2CPUP(guestp, vcpuid, cpup, fail_label, scr1) \
265 cmp vcpuid, NVCPUS ;\
266 bgeu,pn %xcc, fail_label ;\
267 sllx vcpuid, GUEST_VCPUS_SHIFT, cpup ;\
268 set GUEST_VCPUS, scr1 ;\
269 add cpup, scr1, cpup ;\
270 ldx [guestp + cpup], cpup ;\
271 brz,pn cpup, fail_label ;\
272 nop
273
274
275/*
276 * PCPUID2COREID - derive core id from physical cpu id
277 *
278 * Register overlap: pid and coreid may be the same register
279 * Delay slot: safe and complete in a delay slot
280 */
281#define PCPUID2COREID(pid, coreid) \
282 srlx pid, CPUID_2_COREID_SHIFT, coreid
283
284
285/*
286 * Standard return-from-hcall with status "errno"
287 */
288#define HCALL_RET(errno) \
289 mov errno, %o0 ;\
290 done
291
292/*
293 * HVCALL - make a subroutine call
294 * HVJMP - jmp to subroutine in reg
295 * HVRET - return from a subroutine call
296 *
297 * This hypervisor has a convention of using %g7 as the the
298 * return address.
299 */
300#define HVCALL(x) \
301 ba,pt %xcc, x ;\
302 rd %pc, %g7
303
304#define HVJMP(reg, pc) \
305 jmpl reg, pc ;\
306 nop
307
308#define HVRET \
309 jmp %g7 + SZ_INSTR ;\
310 nop
311
312/*
313 * Strand stack operations
314 *
315 * These macros are deprecated, but aliased for back compatibility
316 * CPU_PUSH - push a val into the stack
317 * CPU_POP - pop val from the stack
318 * These macros temporarily push and pop values that need storing
319 * STRAND_PUSH - push a val into the stack
320 * STRAND_POP - pop val from the stack
321 *
322 */
323
324#define CPU_PUSH(val, scr1, scr2, scr3) \
325 STRAND_PUSH(val, scr1, scr2)
326
327#define CPU_POP(val, scr1, scr2, scr3) \
328 STRAND_POP(val, scr1)
329
330 /* Stack is empty if ptr = 0 */
331
332#define STRAND_PUSH(val, scr1, scr2) \
333 STRAND_STRUCT(scr1) ;\
334 add scr1, STRAND_MINI_STACK, scr1 ;\
335 ldx [scr1 + MINI_STACK_PTR], scr2 /* get stack ptr */ ;\
336 cmp scr2, MINI_STACK_VAL_INCR*MINI_STACK_DEPTH ;\
337 bge,a,pn %xcc, hvabort ;\
338 rd %pc, %g1 ;\
339 add scr2, MINI_STACK_VAL_INCR, scr2 /* next element */ ;\
340 stx scr2, [scr1 + MINI_STACK_PTR] ;\
341 add scr2, scr1, scr2 ;\
342 /* store at previous ptr value */ ;\
343 stx val, [scr2 + MINI_STACK_VAL - MINI_STACK_VAL_INCR]
344
345
346#define STRAND_POP(val, scr1) \
347 STRAND_STRUCT(scr1) ;\
348 add scr1, STRAND_MINI_STACK, scr1 ;\
349 ldx [scr1 + MINI_STACK_PTR], val ;\
350 brlez,a,pn val, hvabort ;\
351 rd %pc, %g1 ;\
352 sub val, MINI_STACK_VAL_INCR, val ;\
353 stx val, [scr1 + MINI_STACK_PTR] ;\
354 add scr1, val, scr1 ;\
355 ldx [scr1 + MINI_STACK_VAL], val
356
357
358/*
359 * ATOMIC_OR_64 - atomically logical-or a value in a memory location
360 */
361#define ATOMIC_OR_64(addr, value, scr1, scr2) \
362 .pushlocals ;\
363 ldx [addr], scr1 ;\
3640: or scr1, value, scr2 ;\
365 casx [addr], scr1, scr2 ;\
366 cmp scr1, scr2 ;\
367 bne,a,pn %xcc, 0b ;\
368 mov scr2, scr1 ;\
369 .poplocals
370
371/*
372 * ATOMIC_ANDN_64 - atomically logical-andn a value in a memory location
373 * Returns oldvalue
374 */
375#define ATOMIC_ANDN_64(addr, value, oldvalue, scr2) \
376 .pushlocals ;\
377 ldx [addr], oldvalue ;\
3780: andn oldvalue, value, scr2 ;\
379 casx [addr], oldvalue, scr2 ;\
380 cmp oldvalue, scr2 ;\
381 bne,a,pn %xcc, 0b ;\
382 mov scr2, oldvalue ;\
383 .poplocals
384
385/*
386 * ATOMIC_SWAP_64 - swaps the value at addr with newvalue, returns
387 * the previous contents of addr as oldvalue
388 */
389#define ATOMIC_SWAP_64(addr, newvalue, oldvalue, scr2) \
390 .pushlocals ;\
391 ldx [addr], scr2 ;\
3920: mov newvalue, oldvalue ;\
393 casx [addr], scr2, oldvalue ;\
394 cmp scr2, oldvalue ;\
395 bne,a,pn %xcc, 0b ;\
396 mov oldvalue, scr2 ;\
397 .poplocals
398
399/*
400 * ATOMIC_ADD_64 - atomically add to a value stored in memory
401 */
402#define ATOMIC_ADD_64(addr, value, newvalue, scr2) \
403 .pushlocals ;\
404 ldx [addr], newvalue ;\
4050: add newvalue, value, scr2 ;\
406 casx [addr], newvalue, scr2 ;\
407 cmp newvalue, scr2 ;\
408 bne,a,pn %xcc, 0b ;\
409 mov scr2, newvalue ;\
410 add newvalue, value, newvalue ;\
411 .poplocals
412
413
414/*
415 * Locking primitives
416 */
417#define MEMBAR_ENTER \
418 /* membar #StoreLoad|#StoreStore not necessary on Niagara */
419#define MEMBAR_EXIT \
420 /* membar #LoadStore|#StoreStore not necessary on Niagara */
421
422/*
423 * SPINLOCK_ENTER - claim lock by setting it to cpu#+1 spinning until it is
424 * free
425 */
426#define SPINLOCK_ENTER(lock, scr1, scr2) \
427 .pushlocals ;\
428 STRAND_STRUCT(scr1) ;\
429 ldub [scr1 + STRAND_ID], scr2 /* my ID */ ;\
430 inc scr2 /* lockID = cpuid + 1 */ ;\
431 mov 0, scr1 ;\
4321: ;\
433 brz,pn scr1, 2f ;\
434 nop ;\
435 ;\
436 be,a %xcc, hvabort ;\
437 rd %pc, %g1 ;\
4382: ;\
439 mov scr2, scr1 ;\
440 casx [lock], %g0, scr1 /* if zero, write my lockID */ ;\
441 brnz,a,pn scr1, 1b ;\
442 cmp scr2, scr1 ;\
443 MEMBAR_ENTER ;\
444 .poplocals
445
446/*
447 * SPINLOCK_EXIT - release lock
448 */
449#define SPINLOCK_EXIT(lock) ;\
450 MEMBAR_EXIT ;\
451 stx %g0, [lock]
452
453#define IS_CPU_IN_ERROR(cpup, scr1) \
454 ldx [cpup + CPU_STATUS], scr1 ;\
455 cmp scr1, CPU_STATE_ERROR
456
457/*
458 * LABEL_ADDRESS(label, reg)
459 *
460 * Args:
461 * label - assembler label
462 * reg - will hold the address of the label
463 *
464 * Calculate the (relocated) address of the target label. Only
465 * works if the target label is no more than 4092 bytes away from
466 * the current assembly origin. Also requires that the label be
467 * in the same source file, and in the same section as the macro
468 * invokation.
469 */
470#define LABEL_ADDRESS(label, reg) \
471 .pushlocals ;\
4720: rd %pc, reg ;\
473 add reg, (label) - 0b, reg ;\
474 .poplocals
475
476
477/*
478 * RELOC_OFFSET(scr, reg)
479 *
480 * Args:
481 * scr - scratch register, different from "reg"
482 * reg - will hold the value of the relocation offset
483 *
484 * Calculates the offset of the current image relative to the
485 * address assigned by the linker. The returned offset value can be
486 * subtracted from labels calcuated with "setx" to obtain the actual
487 * address after relocation.
488 */
489#define RELOC_OFFSET(scr, reg) \
490 .pushlocals ;\
491 setx 0f, scr, reg /* reg = linker */ ;\
4920: rd %pc, scr /* scr = actual */ ;\
493 sub reg, scr, reg /* reg = l - a */ ;\
494 .poplocals
495
496#define DELAY_SECS(scr1, scr2, SECS) \
497 CPU_STRUCT(scr1) ;\
498 CPU2ROOT_STRUCT(scr1, scr2) ;\
499 ldx [scr2 + CONFIG_STICKFREQUENCY], scr2 ;\
500 mulx scr2, SECS, scr2 ;\
501 rd STICK, scr1 ;\
502 add scr1, scr2, scr1 ;\
5030: ;\
504 rd STICK, scr2 ;\
505 cmp scr2, scr1 ;\
506 blu %xcc, 0b ;\
507 nop
508
509/*
510 * SMALL_COPY_MACRO - byte-wise copy a small region of memory.
511 *
512 * Args:
513 * src - starting address
514 * len - length of region to copy
515 * dest - destination address
516 * scr - scratch
517 *
518 * All arguments are clobbered.
519 */
520#define SMALL_COPY_MACRO(src, len, dest, scr) \
521 .pushlocals ;\
5221: ldub [src], scr ;\
523 inc src ;\
524 deccc len ;\
525 stb scr, [dest] ;\
526 bnz,pt %xcc, 1b ;\
527 inc dest ;\
528 .poplocals
529
530/*
531 * SMALL_ZERO_MACRO - byte-wise zero a small region of memory.
532 *
533 * Args:
534 * addr - starting address
535 * len - length of region to copy
536 *
537 * All arguments are clobbered.
538 */
539#define SMALL_ZERO_MACRO(addr, len) \
540 .pushlocals ;\
541 brz,pn len, 2f ;\
542 nop ;\
5431: stb %g0, [addr] ;\
544 deccc len ;\
545 bnz,pt %xcc, 1b ;\
546 inc addr ;\
5472: ;\
548 .poplocals
549
550/*
551 * Cstyle macro for minimum
552 */
553#define MIN(x, y) \
554 ((x) < (y) ? (x) : (y)) \
555
556/* END CSTYLED */
557
558#ifdef __cplusplus
559}
560#endif
561
562#endif /* _UTIL_H */