1 | /* Facilities specific to the PowerPC architecture |
2 | Copyright (C) 2012-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #ifndef _SYS_PLATFORM_PPC_H |
20 | #define _SYS_PLATFORM_PPC_H 1 |
21 | |
22 | #include <features.h> |
23 | #include <stdint.h> |
24 | #include <bits/ppc.h> |
25 | |
26 | /* Read the Time Base Register. */ |
27 | static __inline__ uint64_t |
28 | __ppc_get_timebase (void) |
29 | { |
30 | #if __GNUC_PREREQ (4, 8) |
31 | return __builtin_ppc_get_timebase (); |
32 | #else |
33 | # ifdef __powerpc64__ |
34 | uint64_t __tb; |
35 | /* "volatile" is necessary here, because the user expects this assembly |
36 | isn't moved after an optimization. */ |
37 | __asm__ volatile ("mfspr %0, 268" : "=r" (__tb)); |
38 | return __tb; |
39 | # else /* not __powerpc64__ */ |
40 | uint32_t __tbu, __tbl, __tmp; \ |
41 | __asm__ volatile ("0:\n\t" |
42 | "mftbu %0\n\t" |
43 | "mftbl %1\n\t" |
44 | "mftbu %2\n\t" |
45 | "cmpw %0, %2\n\t" |
46 | "bne- 0b" |
47 | : "=r" (__tbu), "=r" (__tbl), "=r" (__tmp)); |
48 | return (((uint64_t) __tbu << 32) | __tbl); |
49 | # endif /* not __powerpc64__ */ |
50 | #endif |
51 | } |
52 | |
53 | /* The following functions provide hints about the usage of shared processor |
54 | resources, as defined in ISA 2.06 and newer. */ |
55 | |
56 | /* Provides a hint that performance will probably be improved if shared |
57 | resources dedicated to the executing processor are released for use by other |
58 | processors. */ |
59 | static __inline__ void |
60 | __ppc_yield (void) |
61 | { |
62 | __asm__ volatile ("or 27,27,27" ); |
63 | } |
64 | |
65 | /* Provides a hint that performance will probably be improved if shared |
66 | resources dedicated to the executing processor are released until |
67 | all outstanding storage accesses to caching-inhibited storage have been |
68 | completed. */ |
69 | static __inline__ void |
70 | __ppc_mdoio (void) |
71 | { |
72 | __asm__ volatile ("or 29,29,29" ); |
73 | } |
74 | |
75 | /* Provides a hint that performance will probably be improved if shared |
76 | resources dedicated to the executing processor are released until all |
77 | outstanding storage accesses to cacheable storage for which the data is not |
78 | in the cache have been completed. */ |
79 | static __inline__ void |
80 | __ppc_mdoom (void) |
81 | { |
82 | __asm__ volatile ("or 30,30,30" ); |
83 | } |
84 | |
85 | |
86 | /* ISA 2.05 and beyond support the Program Priority Register (PPR) to adjust |
87 | thread priorities based on lock acquisition, wait and release. The ISA |
88 | defines the use of form 'or Rx,Rx,Rx' as the way to modify the PRI field. |
89 | The unprivileged priorities are: |
90 | Rx = 1 (low) |
91 | Rx = 2 (medium) |
92 | Rx = 6 (medium-low/normal) |
93 | The 'or' instruction form is a nop in previous hardware, so it is safe to |
94 | use unguarded. The default value is 'medium'. |
95 | */ |
96 | |
97 | static __inline__ void |
98 | __ppc_set_ppr_med (void) |
99 | { |
100 | __asm__ volatile ("or 2,2,2" ); |
101 | } |
102 | |
103 | static __inline__ void |
104 | __ppc_set_ppr_med_low (void) |
105 | { |
106 | __asm__ volatile ("or 6,6,6" ); |
107 | } |
108 | |
109 | static __inline__ void |
110 | __ppc_set_ppr_low (void) |
111 | { |
112 | __asm__ volatile ("or 1,1,1" ); |
113 | } |
114 | |
115 | /* Power ISA 2.07 (Book II, Chapter 3) extends the priorities that can be set |
116 | to the Program Priority Register (PPR). The form 'or Rx,Rx,Rx' is used to |
117 | modify the PRI field of the PPR, the same way as described above. |
118 | The new priority levels are: |
119 | Rx = 31 (very low) |
120 | Rx = 5 (medium high) |
121 | Any program can set the priority to very low, low, medium low, and medium, |
122 | as these are unprivileged. |
123 | The medium high priority, on the other hand, is privileged, and may only be |
124 | set during certain time intervals by problem-state programs. If the program |
125 | priority is medium high when the time interval expires or if an attempt is |
126 | made to set the priority to medium high when it is not allowed, the PRI |
127 | field is set to medium. |
128 | */ |
129 | |
130 | #ifdef _ARCH_PWR8 |
131 | |
132 | static __inline__ void |
133 | __ppc_set_ppr_very_low (void) |
134 | { |
135 | __asm__ volatile ("or 31,31,31" ); |
136 | } |
137 | |
138 | static __inline__ void |
139 | __ppc_set_ppr_med_high (void) |
140 | { |
141 | __asm__ volatile ("or 5,5,5" ); |
142 | } |
143 | |
144 | #endif |
145 | |
146 | #endif /* sys/platform/ppc.h */ |
147 | |