source: mainline/kernel/arch/sparc64/include/arch/asm.h@ 128359eb

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 128359eb was 128359eb, checked in by Martin Decky <martin@…>, 6 years ago

Replace get_stack_base() with builtin_frame_address(0)

The usage of an intrinsic function to obtain the current stack pointer
should provide the compuler more room for performance optimizations than
the hand-written (and volatile) inline assembly block.

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/*
2 * Copyright (c) 2005 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_sparc64
30 * @{
31 */
32/** @file
33 */
34
35#ifndef KERN_sparc64_ASM_H_
36#define KERN_sparc64_ASM_H_
37
38#include <typedefs.h>
39#include <align.h>
40#include <arch/register.h>
41#include <config.h>
42#include <arch/stack.h>
43#include <barrier.h>
44#include <trace.h>
45
46_NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t v)
47{
48 *port = v;
49 memory_barrier();
50}
51
52_NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t v)
53{
54 *port = v;
55 memory_barrier();
56}
57
58_NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t v)
59{
60 *port = v;
61 memory_barrier();
62}
63
64_NO_TRACE static inline uint8_t pio_read_8(ioport8_t *port)
65{
66 uint8_t rv = *port;
67 memory_barrier();
68 return rv;
69}
70
71_NO_TRACE static inline uint16_t pio_read_16(ioport16_t *port)
72{
73 uint16_t rv = *port;
74 memory_barrier();
75 return rv;
76}
77
78_NO_TRACE static inline uint32_t pio_read_32(ioport32_t *port)
79{
80 uint32_t rv = *port;
81 memory_barrier();
82 return rv;
83}
84
85/** Read Processor State register.
86 *
87 * @return Value of PSTATE register.
88 *
89 */
90_NO_TRACE static inline uint64_t pstate_read(void)
91{
92 uint64_t v;
93
94 asm volatile (
95 "rdpr %%pstate, %[v]\n"
96 : [v] "=r" (v)
97 );
98
99 return v;
100}
101
102/** Write Processor State register.
103 *
104 * @param v New value of PSTATE register.
105 *
106 */
107_NO_TRACE static inline void pstate_write(uint64_t v)
108{
109 asm volatile (
110 "wrpr %[v], %[zero], %%pstate\n"
111 :: [v] "r" (v),
112 [zero] "i" (0)
113 );
114}
115
116/** Read TICK_compare Register.
117 *
118 * @return Value of TICK_comapre register.
119 *
120 */
121_NO_TRACE static inline uint64_t tick_compare_read(void)
122{
123 uint64_t v;
124
125 asm volatile (
126 "rd %%tick_cmpr, %[v]\n"
127 : [v] "=r" (v)
128 );
129
130 return v;
131}
132
133/** Write TICK_compare Register.
134 *
135 * @param v New value of TICK_comapre register.
136 *
137 */
138_NO_TRACE static inline void tick_compare_write(uint64_t v)
139{
140 asm volatile (
141 "wr %[v], %[zero], %%tick_cmpr\n"
142 :: [v] "r" (v),
143 [zero] "i" (0)
144 );
145}
146
147/** Read STICK_compare Register.
148 *
149 * @return Value of STICK_compare register.
150 *
151 */
152_NO_TRACE static inline uint64_t stick_compare_read(void)
153{
154 uint64_t v;
155
156 asm volatile (
157 "rd %%asr25, %[v]\n"
158 : [v] "=r" (v)
159 );
160
161 return v;
162}
163
164/** Write STICK_compare Register.
165 *
166 * @param v New value of STICK_comapre register.
167 *
168 */
169_NO_TRACE static inline void stick_compare_write(uint64_t v)
170{
171 asm volatile (
172 "wr %[v], %[zero], %%asr25\n"
173 :: [v] "r" (v),
174 [zero] "i" (0)
175 );
176}
177
178/** Read TICK Register.
179 *
180 * @return Value of TICK register.
181 *
182 */
183_NO_TRACE static inline uint64_t tick_read(void)
184{
185 uint64_t v;
186
187 asm volatile (
188 "rdpr %%tick, %[v]\n"
189 : [v] "=r" (v)
190 );
191
192 return v;
193}
194
195/** Write TICK Register.
196 *
197 * @param v New value of TICK register.
198 *
199 */
200_NO_TRACE static inline void tick_write(uint64_t v)
201{
202 asm volatile (
203 "wrpr %[v], %[zero], %%tick\n"
204 :: [v] "r" (v),
205 [zero] "i" (0)
206 );
207}
208
209/** Read FPRS Register.
210 *
211 * @return Value of FPRS register.
212 *
213 */
214_NO_TRACE static inline uint64_t fprs_read(void)
215{
216 uint64_t v;
217
218 asm volatile (
219 "rd %%fprs, %[v]\n"
220 : [v] "=r" (v)
221 );
222
223 return v;
224}
225
226/** Write FPRS Register.
227 *
228 * @param v New value of FPRS register.
229 *
230 */
231_NO_TRACE static inline void fprs_write(uint64_t v)
232{
233 asm volatile (
234 "wr %[v], %[zero], %%fprs\n"
235 :: [v] "r" (v),
236 [zero] "i" (0)
237 );
238}
239
240/** Read SOFTINT Register.
241 *
242 * @return Value of SOFTINT register.
243 *
244 */
245_NO_TRACE static inline uint64_t softint_read(void)
246{
247 uint64_t v;
248
249 asm volatile (
250 "rd %%softint, %[v]\n"
251 : [v] "=r" (v)
252 );
253
254 return v;
255}
256
257/** Write SOFTINT Register.
258 *
259 * @param v New value of SOFTINT register.
260 *
261 */
262_NO_TRACE static inline void softint_write(uint64_t v)
263{
264 asm volatile (
265 "wr %[v], %[zero], %%softint\n"
266 :: [v] "r" (v),
267 [zero] "i" (0)
268 );
269}
270
271/** Write CLEAR_SOFTINT Register.
272 *
273 * Bits set in CLEAR_SOFTINT register will be cleared in SOFTINT register.
274 *
275 * @param v New value of CLEAR_SOFTINT register.
276 *
277 */
278_NO_TRACE static inline void clear_softint_write(uint64_t v)
279{
280 asm volatile (
281 "wr %[v], %[zero], %%clear_softint\n"
282 :: [v] "r" (v),
283 [zero] "i" (0)
284 );
285}
286
287/** Write SET_SOFTINT Register.
288 *
289 * Bits set in SET_SOFTINT register will be set in SOFTINT register.
290 *
291 * @param v New value of SET_SOFTINT register.
292 *
293 */
294_NO_TRACE static inline void set_softint_write(uint64_t v)
295{
296 asm volatile (
297 "wr %[v], %[zero], %%set_softint\n"
298 :: [v] "r" (v),
299 [zero] "i" (0)
300 );
301}
302
303/** Enable interrupts.
304 *
305 * Enable interrupts and return previous
306 * value of IPL.
307 *
308 * @return Old interrupt priority level.
309 *
310 */
311_NO_TRACE static inline ipl_t interrupts_enable(void)
312{
313 pstate_reg_t pstate;
314 uint64_t value = pstate_read();
315
316 pstate.value = value;
317 pstate.ie = true;
318 pstate_write(pstate.value);
319
320 return (ipl_t) value;
321}
322
323/** Disable interrupts.
324 *
325 * Disable interrupts and return previous
326 * value of IPL.
327 *
328 * @return Old interrupt priority level.
329 *
330 */
331_NO_TRACE static inline ipl_t interrupts_disable(void)
332{
333 pstate_reg_t pstate;
334 uint64_t value = pstate_read();
335
336 pstate.value = value;
337 pstate.ie = false;
338 pstate_write(pstate.value);
339
340 return (ipl_t) value;
341}
342
343/** Restore interrupt priority level.
344 *
345 * Restore IPL.
346 *
347 * @param ipl Saved interrupt priority level.
348 *
349 */
350_NO_TRACE static inline void interrupts_restore(ipl_t ipl)
351{
352 pstate_reg_t pstate;
353
354 pstate.value = pstate_read();
355 pstate.ie = ((pstate_reg_t)(uint64_t) ipl).ie;
356 pstate_write(pstate.value);
357}
358
359/** Return interrupt priority level.
360 *
361 * Return IPL.
362 *
363 * @return Current interrupt priority level.
364 *
365 */
366_NO_TRACE static inline ipl_t interrupts_read(void)
367{
368 return (ipl_t) pstate_read();
369}
370
371/** Check interrupts state.
372 *
373 * @return True if interrupts are disabled.
374 *
375 */
376_NO_TRACE static inline bool interrupts_disabled(void)
377{
378 pstate_reg_t pstate;
379
380 pstate.value = pstate_read();
381 return !pstate.ie;
382}
383
384/** Read Version Register.
385 *
386 * @return Value of VER register.
387 *
388 */
389_NO_TRACE static inline uint64_t ver_read(void)
390{
391 uint64_t v;
392
393 asm volatile (
394 "rdpr %%ver, %[v]\n"
395 : [v] "=r" (v)
396 );
397
398 return v;
399}
400
401/** Read Trap Program Counter register.
402 *
403 * @return Current value in TPC.
404 *
405 */
406_NO_TRACE static inline uint64_t tpc_read(void)
407{
408 uint64_t v;
409
410 asm volatile (
411 "rdpr %%tpc, %[v]\n"
412 : [v] "=r" (v)
413 );
414
415 return v;
416}
417
418/** Read Trap Level register.
419 *
420 * @return Current value in TL.
421 *
422 */
423_NO_TRACE static inline uint64_t tl_read(void)
424{
425 uint64_t v;
426
427 asm volatile (
428 "rdpr %%tl, %[v]\n"
429 : [v] "=r" (v)
430 );
431
432 return v;
433}
434
435/** Read Trap Base Address register.
436 *
437 * @return Current value in TBA.
438 *
439 */
440_NO_TRACE static inline uint64_t tba_read(void)
441{
442 uint64_t v;
443
444 asm volatile (
445 "rdpr %%tba, %[v]\n"
446 : [v] "=r" (v)
447 );
448
449 return v;
450}
451
452/** Write Trap Base Address register.
453 *
454 * @param v New value of TBA.
455 *
456 */
457_NO_TRACE static inline void tba_write(uint64_t v)
458{
459 asm volatile (
460 "wrpr %[v], %[zero], %%tba\n"
461 :: [v] "r" (v),
462 [zero] "i" (0)
463 );
464}
465
466/** Load uint64_t from alternate space.
467 *
468 * @param asi ASI determining the alternate space.
469 * @param va Virtual address within the ASI.
470 *
471 * @return Value read from the virtual address in
472 * the specified address space.
473 *
474 */
475_NO_TRACE static inline uint64_t asi_u64_read(asi_t asi, uintptr_t va)
476{
477 uint64_t v;
478
479 asm volatile (
480 "ldxa [%[va]] %[asi], %[v]\n"
481 : [v] "=r" (v)
482 : [va] "r" (va),
483 [asi] "i" ((unsigned int) asi)
484 );
485
486 return v;
487}
488
489/** Store uint64_t to alternate space.
490 *
491 * @param asi ASI determining the alternate space.
492 * @param va Virtual address within the ASI.
493 * @param v Value to be written.
494 *
495 */
496_NO_TRACE static inline void asi_u64_write(asi_t asi, uintptr_t va, uint64_t v)
497{
498 asm volatile (
499 "stxa %[v], [%[va]] %[asi]\n"
500 :: [v] "r" (v),
501 [va] "r" (va),
502 [asi] "i" ((unsigned int) asi)
503 : "memory"
504 );
505}
506
507/** Flush all valid register windows to memory. */
508_NO_TRACE static inline void flushw(void)
509{
510 asm volatile ("flushw\n");
511}
512
513/** Switch to nucleus by setting TL to 1. */
514_NO_TRACE static inline void nucleus_enter(void)
515{
516 asm volatile ("wrpr %g0, 1, %tl\n");
517}
518
519/** Switch from nucleus by setting TL to 0. */
520_NO_TRACE static inline void nucleus_leave(void)
521{
522 asm volatile ("wrpr %g0, %g0, %tl\n");
523}
524
525extern void cpu_halt(void) __attribute__((noreturn));
526extern void cpu_sleep(void);
527extern void asm_delay_loop(const uint32_t usec);
528
529extern uint64_t read_from_ag_g6(void);
530extern uint64_t read_from_ag_g7(void);
531extern void write_to_ag_g6(uint64_t val);
532extern void write_to_ag_g7(uint64_t val);
533extern void write_to_ig_g6(uint64_t val);
534
535extern void switch_to_userspace(uint64_t pc, uint64_t sp, uint64_t uarg);
536
537#endif
538
539/** @}
540 */
Note: See TracBrowser for help on using the repository browser.