| @@ -1,493 +1,492 @@ | | | @@ -1,493 +1,492 @@ |
1 | /* $NetBSD: cpu.h,v 1.111 2020/06/27 07:33:51 macallan Exp $ */ | | 1 | /* $NetBSD: cpu.h,v 1.112 2020/07/06 10:50:32 rin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (C) 1999 Wolfgang Solfrank. | | 4 | * Copyright (C) 1999 Wolfgang Solfrank. |
5 | * Copyright (C) 1999 TooLs GmbH. | | 5 | * Copyright (C) 1999 TooLs GmbH. |
6 | * Copyright (C) 1995-1997 Wolfgang Solfrank. | | 6 | * Copyright (C) 1995-1997 Wolfgang Solfrank. |
7 | * Copyright (C) 1995-1997 TooLs GmbH. | | 7 | * Copyright (C) 1995-1997 TooLs GmbH. |
8 | * All rights reserved. | | 8 | * All rights reserved. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. All advertising materials mentioning features or use of this software | | 18 | * 3. All advertising materials mentioning features or use of this software |
19 | * must display the following acknowledgement: | | 19 | * must display the following acknowledgement: |
20 | * This product includes software developed by TooLs GmbH. | | 20 | * This product includes software developed by TooLs GmbH. |
21 | * 4. The name of TooLs GmbH may not be used to endorse or promote products | | 21 | * 4. The name of TooLs GmbH may not be used to endorse or promote products |
22 | * derived from this software without specific prior written permission. | | 22 | * derived from this software without specific prior written permission. |
23 | * | | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR | | 24 | * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR |
25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
27 | * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | | 27 | * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | | 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
29 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | | 29 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
30 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | | 30 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | | 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | | 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | */ | | 34 | */ |
35 | | | 35 | |
36 | #ifndef _POWERPC_CPU_H_ | | 36 | #ifndef _POWERPC_CPU_H_ |
37 | #define _POWERPC_CPU_H_ | | 37 | #define _POWERPC_CPU_H_ |
38 | | | 38 | |
39 | struct cache_info { | | 39 | struct cache_info { |
40 | int dcache_size; | | 40 | int dcache_size; |
41 | int dcache_line_size; | | 41 | int dcache_line_size; |
42 | int icache_size; | | 42 | int icache_size; |
43 | int icache_line_size; | | 43 | int icache_line_size; |
44 | }; | | 44 | }; |
45 | | | 45 | |
46 | #if defined(_KERNEL) || defined(_KMEMUSER) | | 46 | #if defined(_KERNEL) || defined(_KMEMUSER) |
47 | #if defined(_KERNEL_OPT) | | 47 | #if defined(_KERNEL_OPT) |
48 | #include "opt_lockdebug.h" | | | |
49 | #include "opt_modular.h" | | 48 | #include "opt_modular.h" |
50 | #include "opt_multiprocessor.h" | | 49 | #include "opt_multiprocessor.h" |
51 | #include "opt_ppcarch.h" | | 50 | #include "opt_ppcarch.h" |
52 | #endif | | 51 | #endif |
53 | | | 52 | |
54 | #ifdef _KERNEL | | 53 | #ifdef _KERNEL |
55 | #include <sys/intr.h> | | 54 | #include <sys/intr.h> |
56 | #include <sys/device_if.h> | | 55 | #include <sys/device_if.h> |
57 | #include <sys/evcnt.h> | | 56 | #include <sys/evcnt.h> |
58 | #include <sys/param.h> | | 57 | #include <sys/param.h> |
59 | #include <sys/kernel.h> | | 58 | #include <sys/kernel.h> |
60 | #endif | | 59 | #endif |
61 | | | 60 | |
62 | #include <sys/cpu_data.h> | | 61 | #include <sys/cpu_data.h> |
63 | | | 62 | |
64 | struct cpu_info { | | 63 | struct cpu_info { |
65 | struct cpu_data ci_data; /* MI per-cpu data */ | | 64 | struct cpu_data ci_data; /* MI per-cpu data */ |
66 | #ifdef _KERNEL | | 65 | #ifdef _KERNEL |
67 | device_t ci_dev; /* device of corresponding cpu */ | | 66 | device_t ci_dev; /* device of corresponding cpu */ |
68 | struct cpu_softc *ci_softc; /* private cpu info */ | | 67 | struct cpu_softc *ci_softc; /* private cpu info */ |
69 | struct lwp *ci_curlwp; /* current owner of the processor */ | | 68 | struct lwp *ci_curlwp; /* current owner of the processor */ |
70 | struct lwp *ci_onproc; /* current user LWP / kthread */ | | 69 | struct lwp *ci_onproc; /* current user LWP / kthread */ |
71 | struct pcb *ci_curpcb; | | 70 | struct pcb *ci_curpcb; |
72 | struct pmap *ci_curpm; | | 71 | struct pmap *ci_curpm; |
73 | struct lwp *ci_softlwps[SOFTINT_COUNT]; | | 72 | struct lwp *ci_softlwps[SOFTINT_COUNT]; |
74 | int ci_cpuid; /* from SPR_PIR */ | | 73 | int ci_cpuid; /* from SPR_PIR */ |
75 | | | 74 | |
76 | int ci_want_resched; | | 75 | int ci_want_resched; |
77 | volatile uint64_t ci_lastintr; | | 76 | volatile uint64_t ci_lastintr; |
78 | volatile u_long ci_lasttb; | | 77 | volatile u_long ci_lasttb; |
79 | volatile int ci_tickspending; | | 78 | volatile int ci_tickspending; |
80 | volatile int ci_cpl; | | 79 | volatile int ci_cpl; |
81 | volatile int ci_iactive; | | 80 | volatile int ci_iactive; |
82 | volatile int ci_idepth; | | 81 | volatile int ci_idepth; |
83 | union { | | 82 | union { |
84 | #if !defined(PPC_BOOKE) && !defined(_MODULE) | | 83 | #if !defined(PPC_BOOKE) && !defined(_MODULE) |
85 | volatile imask_t un1_ipending; | | 84 | volatile imask_t un1_ipending; |
86 | #define ci_ipending ci_un1.un1_ipending | | 85 | #define ci_ipending ci_un1.un1_ipending |
87 | #endif | | 86 | #endif |
88 | uint64_t un1_pad64; | | 87 | uint64_t un1_pad64; |
89 | } ci_un1; | | 88 | } ci_un1; |
90 | volatile uint32_t ci_pending_ipis; | | 89 | volatile uint32_t ci_pending_ipis; |
91 | int ci_mtx_oldspl; | | 90 | int ci_mtx_oldspl; |
92 | int ci_mtx_count; | | 91 | int ci_mtx_count; |
93 | #if defined(PPC_IBM4XX) || defined(MODULAR) || defined(_MODULE) | | 92 | #if defined(PPC_IBM4XX) || defined(MODULAR) || defined(_MODULE) |
94 | char *ci_intstk; | | 93 | char *ci_intstk; |
95 | #endif | | 94 | #endif |
96 | #define CI_SAVETEMP (0*CPUSAVE_LEN) | | 95 | #define CI_SAVETEMP (0*CPUSAVE_LEN) |
97 | #define CI_SAVEDDB (1*CPUSAVE_LEN) | | 96 | #define CI_SAVEDDB (1*CPUSAVE_LEN) |
98 | #define CI_SAVEIPKDB (2*CPUSAVE_LEN) /* obsolete */ | | 97 | #define CI_SAVEIPKDB (2*CPUSAVE_LEN) /* obsolete */ |
99 | #define CI_SAVEMMU (3*CPUSAVE_LEN) | | 98 | #define CI_SAVEMMU (3*CPUSAVE_LEN) |
100 | #define CI_SAVEMAX (4*CPUSAVE_LEN) | | 99 | #define CI_SAVEMAX (4*CPUSAVE_LEN) |
101 | #define CPUSAVE_LEN 8 | | 100 | #define CPUSAVE_LEN 8 |
102 | #if !defined(PPC_BOOKE) && !defined(MODULAR) && !defined(_MODULE) | | 101 | #if !defined(PPC_BOOKE) && !defined(MODULAR) && !defined(_MODULE) |
103 | #define CPUSAVE_SIZE (CI_SAVEMAX*CPUSAVE_LEN) | | 102 | #define CPUSAVE_SIZE (CI_SAVEMAX*CPUSAVE_LEN) |
104 | #else | | 103 | #else |
105 | #define CPUSAVE_SIZE 128 | | 104 | #define CPUSAVE_SIZE 128 |
106 | #endif | | 105 | #endif |
107 | #define CPUSAVE_R28 0 /* where r28 gets saved */ | | 106 | #define CPUSAVE_R28 0 /* where r28 gets saved */ |
108 | #define CPUSAVE_R29 1 /* where r29 gets saved */ | | 107 | #define CPUSAVE_R29 1 /* where r29 gets saved */ |
109 | #define CPUSAVE_R30 2 /* where r30 gets saved */ | | 108 | #define CPUSAVE_R30 2 /* where r30 gets saved */ |
110 | #define CPUSAVE_R31 3 /* where r31 gets saved */ | | 109 | #define CPUSAVE_R31 3 /* where r31 gets saved */ |
111 | #define CPUSAVE_DEAR 4 /* where IBM4XX SPR_DEAR gets saved */ | | 110 | #define CPUSAVE_DEAR 4 /* where IBM4XX SPR_DEAR gets saved */ |
112 | #define CPUSAVE_DAR 4 /* where OEA SPR_DAR gets saved */ | | 111 | #define CPUSAVE_DAR 4 /* where OEA SPR_DAR gets saved */ |
113 | #define CPUSAVE_ESR 5 /* where IBM4XX SPR_ESR gets saved */ | | 112 | #define CPUSAVE_ESR 5 /* where IBM4XX SPR_ESR gets saved */ |
114 | #define CPUSAVE_DSISR 5 /* where OEA SPR_DSISR gets saved */ | | 113 | #define CPUSAVE_DSISR 5 /* where OEA SPR_DSISR gets saved */ |
115 | #define CPUSAVE_SRR0 6 /* where SRR0 gets saved */ | | 114 | #define CPUSAVE_SRR0 6 /* where SRR0 gets saved */ |
116 | #define CPUSAVE_SRR1 7 /* where SRR1 gets saved */ | | 115 | #define CPUSAVE_SRR1 7 /* where SRR1 gets saved */ |
117 | register_t ci_savearea[CPUSAVE_SIZE]; | | 116 | register_t ci_savearea[CPUSAVE_SIZE]; |
118 | #if defined(PPC_BOOKE) || defined(MODULAR) || defined(_MODULE) | | 117 | #if defined(PPC_BOOKE) || defined(MODULAR) || defined(_MODULE) |
119 | uint32_t ci_pmap_asid_cur; | | 118 | uint32_t ci_pmap_asid_cur; |
120 | union pmap_segtab *ci_pmap_segtabs[2]; | | 119 | union pmap_segtab *ci_pmap_segtabs[2]; |
121 | #define ci_pmap_kern_segtab ci_pmap_segtabs[0] | | 120 | #define ci_pmap_kern_segtab ci_pmap_segtabs[0] |
122 | #define ci_pmap_user_segtab ci_pmap_segtabs[1] | | 121 | #define ci_pmap_user_segtab ci_pmap_segtabs[1] |
123 | struct pmap_tlb_info *ci_tlb_info; | | 122 | struct pmap_tlb_info *ci_tlb_info; |
124 | #endif /* PPC_BOOKE || MODULAR || _MODULE */ | | 123 | #endif /* PPC_BOOKE || MODULAR || _MODULE */ |
125 | struct cache_info ci_ci; | | 124 | struct cache_info ci_ci; |
126 | void *ci_sysmon_cookie; | | 125 | void *ci_sysmon_cookie; |
127 | void (*ci_idlespin)(void); | | 126 | void (*ci_idlespin)(void); |
128 | uint32_t ci_khz; | | 127 | uint32_t ci_khz; |
129 | struct evcnt ci_ev_clock; /* clock intrs */ | | 128 | struct evcnt ci_ev_clock; /* clock intrs */ |
130 | struct evcnt ci_ev_statclock; /* stat clock */ | | 129 | struct evcnt ci_ev_statclock; /* stat clock */ |
131 | struct evcnt ci_ev_traps; /* calls to trap() */ | | 130 | struct evcnt ci_ev_traps; /* calls to trap() */ |
132 | struct evcnt ci_ev_kdsi; /* kernel DSI traps */ | | 131 | struct evcnt ci_ev_kdsi; /* kernel DSI traps */ |
133 | struct evcnt ci_ev_udsi; /* user DSI traps */ | | 132 | struct evcnt ci_ev_udsi; /* user DSI traps */ |
134 | struct evcnt ci_ev_udsi_fatal; /* user DSI trap failures */ | | 133 | struct evcnt ci_ev_udsi_fatal; /* user DSI trap failures */ |
135 | struct evcnt ci_ev_kisi; /* kernel ISI traps */ | | 134 | struct evcnt ci_ev_kisi; /* kernel ISI traps */ |
136 | struct evcnt ci_ev_isi; /* user ISI traps */ | | 135 | struct evcnt ci_ev_isi; /* user ISI traps */ |
137 | struct evcnt ci_ev_isi_fatal; /* user ISI trap failures */ | | 136 | struct evcnt ci_ev_isi_fatal; /* user ISI trap failures */ |
138 | struct evcnt ci_ev_pgm; /* user PGM traps */ | | 137 | struct evcnt ci_ev_pgm; /* user PGM traps */ |
139 | struct evcnt ci_ev_debug; /* user debug traps */ | | 138 | struct evcnt ci_ev_debug; /* user debug traps */ |
140 | struct evcnt ci_ev_fpu; /* FPU traps */ | | 139 | struct evcnt ci_ev_fpu; /* FPU traps */ |
141 | struct evcnt ci_ev_fpusw; /* FPU context switch */ | | 140 | struct evcnt ci_ev_fpusw; /* FPU context switch */ |
142 | struct evcnt ci_ev_ali; /* Alignment traps */ | | 141 | struct evcnt ci_ev_ali; /* Alignment traps */ |
143 | struct evcnt ci_ev_ali_fatal; /* Alignment fatal trap */ | | 142 | struct evcnt ci_ev_ali_fatal; /* Alignment fatal trap */ |
144 | struct evcnt ci_ev_scalls; /* system call traps */ | | 143 | struct evcnt ci_ev_scalls; /* system call traps */ |
145 | struct evcnt ci_ev_vec; /* Altivec traps */ | | 144 | struct evcnt ci_ev_vec; /* Altivec traps */ |
146 | struct evcnt ci_ev_vecsw; /* Altivec context switches */ | | 145 | struct evcnt ci_ev_vecsw; /* Altivec context switches */ |
147 | struct evcnt ci_ev_umchk; /* user MCHK events */ | | 146 | struct evcnt ci_ev_umchk; /* user MCHK events */ |
148 | struct evcnt ci_ev_ipi; /* IPIs received */ | | 147 | struct evcnt ci_ev_ipi; /* IPIs received */ |
149 | struct evcnt ci_ev_tlbmiss_soft; /* tlb miss (no trap) */ | | 148 | struct evcnt ci_ev_tlbmiss_soft; /* tlb miss (no trap) */ |
150 | struct evcnt ci_ev_dtlbmiss_hard; /* data tlb miss (trap) */ | | 149 | struct evcnt ci_ev_dtlbmiss_hard; /* data tlb miss (trap) */ |
151 | struct evcnt ci_ev_itlbmiss_hard; /* instruction tlb miss (trap) */ | | 150 | struct evcnt ci_ev_itlbmiss_hard; /* instruction tlb miss (trap) */ |
152 | #endif /* _KERNEL */ | | 151 | #endif /* _KERNEL */ |
153 | }; | | 152 | }; |
154 | #endif /* _KERNEL || _KMEMUSER */ | | 153 | #endif /* _KERNEL || _KMEMUSER */ |
155 | | | 154 | |
156 | #ifdef _KERNEL | | 155 | #ifdef _KERNEL |
157 | | | 156 | |
158 | #if defined(MULTIPROCESSOR) && !defined(_MODULE) | | 157 | #if defined(MULTIPROCESSOR) && !defined(_MODULE) |
159 | struct cpu_hatch_data { | | 158 | struct cpu_hatch_data { |
160 | int hatch_running; | | 159 | int hatch_running; |
161 | device_t hatch_self; | | 160 | device_t hatch_self; |
162 | struct cpu_info *hatch_ci; | | 161 | struct cpu_info *hatch_ci; |
163 | uint32_t hatch_tbu; | | 162 | uint32_t hatch_tbu; |
164 | uint32_t hatch_tbl; | | 163 | uint32_t hatch_tbl; |
165 | #if defined(PPC_OEA64_BRIDGE) || defined (_ARCH_PPC64) | | 164 | #if defined(PPC_OEA64_BRIDGE) || defined (_ARCH_PPC64) |
166 | uint64_t hatch_hid0; | | 165 | uint64_t hatch_hid0; |
167 | uint64_t hatch_hid1; | | 166 | uint64_t hatch_hid1; |
168 | uint64_t hatch_hid4; | | 167 | uint64_t hatch_hid4; |
169 | uint64_t hatch_hid5; | | 168 | uint64_t hatch_hid5; |
170 | #else | | 169 | #else |
171 | uint32_t hatch_hid0; | | 170 | uint32_t hatch_hid0; |
172 | #endif | | 171 | #endif |
173 | uint32_t hatch_pir; | | 172 | uint32_t hatch_pir; |
174 | #if defined(PPC_OEA) || defined(PPC_OEA64_BRIDGE) | | 173 | #if defined(PPC_OEA) || defined(PPC_OEA64_BRIDGE) |
175 | uintptr_t hatch_asr; | | 174 | uintptr_t hatch_asr; |
176 | uintptr_t hatch_sdr1; | | 175 | uintptr_t hatch_sdr1; |
177 | uint32_t hatch_sr[16]; | | 176 | uint32_t hatch_sr[16]; |
178 | uintptr_t hatch_ibatu[8], hatch_ibatl[8]; | | 177 | uintptr_t hatch_ibatu[8], hatch_ibatl[8]; |
179 | uintptr_t hatch_dbatu[8], hatch_dbatl[8]; | | 178 | uintptr_t hatch_dbatu[8], hatch_dbatl[8]; |
180 | #endif | | 179 | #endif |
181 | #if defined(PPC_BOOKE) | | 180 | #if defined(PPC_BOOKE) |
182 | vaddr_t hatch_sp; | | 181 | vaddr_t hatch_sp; |
183 | u_int hatch_tlbidx; | | 182 | u_int hatch_tlbidx; |
184 | #endif | | 183 | #endif |
185 | }; | | 184 | }; |
186 | | | 185 | |
187 | struct cpuset_info { | | 186 | struct cpuset_info { |
188 | kcpuset_t *cpus_running; | | 187 | kcpuset_t *cpus_running; |
189 | kcpuset_t *cpus_hatched; | | 188 | kcpuset_t *cpus_hatched; |
190 | kcpuset_t *cpus_paused; | | 189 | kcpuset_t *cpus_paused; |
191 | kcpuset_t *cpus_resumed; | | 190 | kcpuset_t *cpus_resumed; |
192 | kcpuset_t *cpus_halted; | | 191 | kcpuset_t *cpus_halted; |
193 | }; | | 192 | }; |
194 | | | 193 | |
195 | extern struct cpuset_info cpuset_info; | | 194 | extern struct cpuset_info cpuset_info; |
196 | #endif /* MULTIPROCESSOR && !_MODULE */ | | 195 | #endif /* MULTIPROCESSOR && !_MODULE */ |
197 | | | 196 | |
198 | #if defined(MULTIPROCESSOR) || defined(_MODULE) | | 197 | #if defined(MULTIPROCESSOR) || defined(_MODULE) |
199 | #define cpu_number() (curcpu()->ci_index + 0) | | 198 | #define cpu_number() (curcpu()->ci_index + 0) |
200 | | | 199 | |
201 | #define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0) | | 200 | #define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0) |
202 | #define CPU_INFO_ITERATOR int | | 201 | #define CPU_INFO_ITERATOR int |
203 | #define CPU_INFO_FOREACH(cii, ci) \ | | 202 | #define CPU_INFO_FOREACH(cii, ci) \ |
204 | cii = 0, ci = &cpu_info[0]; cii < (ncpu ? ncpu : 1); cii++, ci++ | | 203 | cii = 0, ci = &cpu_info[0]; cii < (ncpu ? ncpu : 1); cii++, ci++ |
205 | | | 204 | |
206 | #else | | 205 | #else |
207 | #define cpu_number() 0 | | 206 | #define cpu_number() 0 |
208 | | | 207 | |
209 | #define CPU_IS_PRIMARY(ci) true | | 208 | #define CPU_IS_PRIMARY(ci) true |
210 | #define CPU_INFO_ITERATOR int | | 209 | #define CPU_INFO_ITERATOR int |
211 | #define CPU_INFO_FOREACH(cii, ci) \ | | 210 | #define CPU_INFO_FOREACH(cii, ci) \ |
212 | (void)cii, ci = curcpu(); ci != NULL; ci = NULL | | 211 | (void)cii, ci = curcpu(); ci != NULL; ci = NULL |
213 | | | 212 | |
214 | #endif /* MULTIPROCESSOR || _MODULE */ | | 213 | #endif /* MULTIPROCESSOR || _MODULE */ |
215 | | | 214 | |
216 | extern struct cpu_info cpu_info[]; | | 215 | extern struct cpu_info cpu_info[]; |
217 | | | 216 | |
218 | static __inline struct cpu_info * curcpu(void) __pure; | | 217 | static __inline struct cpu_info * curcpu(void) __pure; |
219 | static __inline struct cpu_info * | | 218 | static __inline struct cpu_info * |
220 | curcpu(void) | | 219 | curcpu(void) |
221 | { | | 220 | { |
222 | struct cpu_info *ci; | | 221 | struct cpu_info *ci; |
223 | | | 222 | |
224 | __asm volatile ("mfsprg0 %0" : "=r"(ci)); | | 223 | __asm volatile ("mfsprg0 %0" : "=r"(ci)); |
225 | return ci; | | 224 | return ci; |
226 | } | | 225 | } |
227 | | | 226 | |
228 | #ifdef __clang__ | | 227 | #ifdef __clang__ |
229 | #define curlwp (curcpu()->ci_curlwp) | | 228 | #define curlwp (curcpu()->ci_curlwp) |
230 | #else | | 229 | #else |
231 | register struct lwp *powerpc_curlwp __asm("r13"); | | 230 | register struct lwp *powerpc_curlwp __asm("r13"); |
232 | #define curlwp powerpc_curlwp | | 231 | #define curlwp powerpc_curlwp |
233 | #endif | | 232 | #endif |
234 | #define curpcb (curcpu()->ci_curpcb) | | 233 | #define curpcb (curcpu()->ci_curpcb) |
235 | #define curpm (curcpu()->ci_curpm) | | 234 | #define curpm (curcpu()->ci_curpm) |
236 | | | 235 | |
237 | static __inline register_t | | 236 | static __inline register_t |
238 | mfmsr(void) | | 237 | mfmsr(void) |
239 | { | | 238 | { |
240 | register_t msr; | | 239 | register_t msr; |
241 | | | 240 | |
242 | __asm volatile ("mfmsr %0" : "=r"(msr)); | | 241 | __asm volatile ("mfmsr %0" : "=r"(msr)); |
243 | return msr; | | 242 | return msr; |
244 | } | | 243 | } |
245 | | | 244 | |
246 | static __inline void | | 245 | static __inline void |
247 | mtmsr(register_t msr) | | 246 | mtmsr(register_t msr) |
248 | { | | 247 | { |
249 | //KASSERT(msr & PSL_CE); | | 248 | //KASSERT(msr & PSL_CE); |
250 | //KASSERT(msr & PSL_DE); | | 249 | //KASSERT(msr & PSL_DE); |
251 | __asm volatile ("mtmsr %0" : : "r"(msr)); | | 250 | __asm volatile ("mtmsr %0" : : "r"(msr)); |
252 | } | | 251 | } |
253 | | | 252 | |
254 | #if !defined(_MODULE) | | 253 | #if !defined(_MODULE) |
255 | static __inline uint32_t | | 254 | static __inline uint32_t |
256 | mftbl(void) | | 255 | mftbl(void) |
257 | { | | 256 | { |
258 | uint32_t tbl; | | 257 | uint32_t tbl; |
259 | | | 258 | |
260 | __asm volatile ( | | 259 | __asm volatile ( |
261 | #ifdef PPC_IBM403 | | 260 | #ifdef PPC_IBM403 |
262 | " mftblo %[tbl]" "\n" | | 261 | " mftblo %[tbl]" "\n" |
263 | #elif defined(PPC_BOOKE) | | 262 | #elif defined(PPC_BOOKE) |
264 | " mfspr %[tbl],268" "\n" | | 263 | " mfspr %[tbl],268" "\n" |
265 | #else | | 264 | #else |
266 | " mftbl %[tbl]" "\n" | | 265 | " mftbl %[tbl]" "\n" |
267 | #endif | | 266 | #endif |
268 | : [tbl] "=r" (tbl)); | | 267 | : [tbl] "=r" (tbl)); |
269 | | | 268 | |
270 | return tbl; | | 269 | return tbl; |
271 | } | | 270 | } |
272 | | | 271 | |
273 | static __inline uint64_t | | 272 | static __inline uint64_t |
274 | mftb(void) | | 273 | mftb(void) |
275 | { | | 274 | { |
276 | uint64_t tb; | | 275 | uint64_t tb; |
277 | | | 276 | |
278 | #ifdef _ARCH_PPC64 | | 277 | #ifdef _ARCH_PPC64 |
279 | __asm volatile ("mftb %0" : "=r"(tb)); | | 278 | __asm volatile ("mftb %0" : "=r"(tb)); |
280 | #else | | 279 | #else |
281 | int tmp; | | 280 | int tmp; |
282 | | | 281 | |
283 | __asm volatile ( | | 282 | __asm volatile ( |
284 | #ifdef PPC_IBM403 | | 283 | #ifdef PPC_IBM403 |
285 | "1: mftbhi %[tb]" "\n" | | 284 | "1: mftbhi %[tb]" "\n" |
286 | " mftblo %L[tb]" "\n" | | 285 | " mftblo %L[tb]" "\n" |
287 | " mftbhi %[tmp]" "\n" | | 286 | " mftbhi %[tmp]" "\n" |
288 | #elif defined(PPC_BOOKE) | | 287 | #elif defined(PPC_BOOKE) |
289 | "1: mfspr %[tb],269" "\n" | | 288 | "1: mfspr %[tb],269" "\n" |
290 | " mfspr %L[tb],268" "\n" | | 289 | " mfspr %L[tb],268" "\n" |
291 | " mfspr %[tmp],269" "\n" | | 290 | " mfspr %[tmp],269" "\n" |
292 | #else | | 291 | #else |
293 | "1: mftbu %[tb]" "\n" | | 292 | "1: mftbu %[tb]" "\n" |
294 | " mftb %L[tb]" "\n" | | 293 | " mftb %L[tb]" "\n" |
295 | " mftbu %[tmp]" "\n" | | 294 | " mftbu %[tmp]" "\n" |
296 | #endif | | 295 | #endif |
297 | " cmplw %[tb],%[tmp]" "\n" | | 296 | " cmplw %[tb],%[tmp]" "\n" |
298 | " bne- 1b" "\n" | | 297 | " bne- 1b" "\n" |
299 | : [tb] "=r" (tb), [tmp] "=r"(tmp) | | 298 | : [tb] "=r" (tb), [tmp] "=r"(tmp) |
300 | :: "cr0"); | | 299 | :: "cr0"); |
301 | #endif | | 300 | #endif |
302 | | | 301 | |
303 | return tb; | | 302 | return tb; |
304 | } | | 303 | } |
305 | | | 304 | |
306 | static __inline uint32_t | | 305 | static __inline uint32_t |
307 | mfrtcl(void) | | 306 | mfrtcl(void) |
308 | { | | 307 | { |
309 | uint32_t rtcl; | | 308 | uint32_t rtcl; |
310 | | | 309 | |
311 | __asm volatile ("mfrtcl %0" : "=r"(rtcl)); | | 310 | __asm volatile ("mfrtcl %0" : "=r"(rtcl)); |
312 | return rtcl; | | 311 | return rtcl; |
313 | } | | 312 | } |
314 | | | 313 | |
315 | static __inline void | | 314 | static __inline void |
316 | mfrtc(uint32_t *rtcp) | | 315 | mfrtc(uint32_t *rtcp) |
317 | { | | 316 | { |
318 | uint32_t tmp; | | 317 | uint32_t tmp; |
319 | | | 318 | |
320 | __asm volatile ( | | 319 | __asm volatile ( |
321 | "1: mfrtcu %[rtcu]" "\n" | | 320 | "1: mfrtcu %[rtcu]" "\n" |
322 | " mfrtcl %[rtcl]" "\n" | | 321 | " mfrtcl %[rtcl]" "\n" |
323 | " mfrtcu %[tmp]" "\n" | | 322 | " mfrtcu %[tmp]" "\n" |
324 | " cmplw %[rtcu],%[tmp]" "\n" | | 323 | " cmplw %[rtcu],%[tmp]" "\n" |
325 | " bne- 1b" | | 324 | " bne- 1b" |
326 | : [rtcu] "=r"(rtcp[0]), [rtcl] "=r"(rtcp[1]), [tmp] "=r"(tmp) | | 325 | : [rtcu] "=r"(rtcp[0]), [rtcl] "=r"(rtcp[1]), [tmp] "=r"(tmp) |
327 | :: "cr0"); | | 326 | :: "cr0"); |
328 | } | | 327 | } |
329 | | | 328 | |
330 | static __inline uint64_t | | 329 | static __inline uint64_t |
331 | rtc_nanosecs(void) | | 330 | rtc_nanosecs(void) |
332 | { | | 331 | { |
333 | /* | | 332 | /* |
334 | * 601 RTC/DEC registers share clock of 7.8125 MHz, 128 ns per tick. | | 333 | * 601 RTC/DEC registers share clock of 7.8125 MHz, 128 ns per tick. |
335 | * DEC has max of 25 bits, FFFFFF => 2.14748352 seconds. | | 334 | * DEC has max of 25 bits, FFFFFF => 2.14748352 seconds. |
336 | * RTCU is seconds, 32 bits. | | 335 | * RTCU is seconds, 32 bits. |
337 | * RTCL is nano-seconds, 23 bit counter from 0 - 999,999,872 (999,999,999 - 128 ns) | | 336 | * RTCL is nano-seconds, 23 bit counter from 0 - 999,999,872 (999,999,999 - 128 ns) |
338 | */ | | 337 | */ |
339 | uint64_t cycles; | | 338 | uint64_t cycles; |
340 | uint32_t tmp[2]; | | 339 | uint32_t tmp[2]; |
341 | | | 340 | |
342 | mfrtc(tmp); | | 341 | mfrtc(tmp); |
343 | | | 342 | |
344 | cycles = tmp[0] * 1000000000; | | 343 | cycles = tmp[0] * 1000000000; |
345 | cycles += (tmp[1] >> 7); | | 344 | cycles += (tmp[1] >> 7); |
346 | | | 345 | |
347 | return cycles; | | 346 | return cycles; |
348 | } | | 347 | } |
349 | #endif /* !_MODULE */ | | 348 | #endif /* !_MODULE */ |
350 | | | 349 | |
351 | static __inline uint32_t | | 350 | static __inline uint32_t |
352 | mfpvr(void) | | 351 | mfpvr(void) |
353 | { | | 352 | { |
354 | uint32_t pvr; | | 353 | uint32_t pvr; |
355 | | | 354 | |
356 | __asm volatile ("mfpvr %0" : "=r"(pvr)); | | 355 | __asm volatile ("mfpvr %0" : "=r"(pvr)); |
357 | return (pvr); | | 356 | return (pvr); |
358 | } | | 357 | } |
359 | | | 358 | |
360 | #ifdef _MODULE | | 359 | #ifdef _MODULE |
361 | extern const char __CPU_MAXNUM; | | 360 | extern const char __CPU_MAXNUM; |
362 | /* | | 361 | /* |
363 | * Make with 0xffff to force a R_PPC_ADDR16_LO without the | | 362 | * Make with 0xffff to force a R_PPC_ADDR16_LO without the |
364 | * corresponding R_PPC_ADDR16_HI relocation. | | 363 | * corresponding R_PPC_ADDR16_HI relocation. |
365 | */ | | 364 | */ |
366 | #define CPU_MAXNUM (((uintptr_t)&__CPU_MAXNUM)&0xffff) | | 365 | #define CPU_MAXNUM (((uintptr_t)&__CPU_MAXNUM)&0xffff) |
367 | #endif /* _MODULE */ | | 366 | #endif /* _MODULE */ |
368 | | | 367 | |
369 | #if !defined(_MODULE) | | 368 | #if !defined(_MODULE) |
370 | extern char *booted_kernel; | | 369 | extern char *booted_kernel; |
371 | extern int powersave; | | 370 | extern int powersave; |
372 | extern int cpu_timebase; | | 371 | extern int cpu_timebase; |
373 | extern int cpu_printfataltraps; | | 372 | extern int cpu_printfataltraps; |
374 | | | 373 | |
375 | struct cpu_info * | | 374 | struct cpu_info * |
376 | cpu_attach_common(device_t, int); | | 375 | cpu_attach_common(device_t, int); |
377 | void cpu_setup(device_t, struct cpu_info *); | | 376 | void cpu_setup(device_t, struct cpu_info *); |
378 | void cpu_identify(char *, size_t); | | 377 | void cpu_identify(char *, size_t); |
379 | void cpu_probe_cache(void); | | 378 | void cpu_probe_cache(void); |
380 | | | 379 | |
381 | void dcache_wb_page(vaddr_t); | | 380 | void dcache_wb_page(vaddr_t); |
382 | void dcache_wbinv_page(vaddr_t); | | 381 | void dcache_wbinv_page(vaddr_t); |
383 | void dcache_inv_page(vaddr_t); | | 382 | void dcache_inv_page(vaddr_t); |
384 | void dcache_zero_page(vaddr_t); | | 383 | void dcache_zero_page(vaddr_t); |
385 | void icache_inv_page(vaddr_t); | | 384 | void icache_inv_page(vaddr_t); |
386 | void dcache_wb(vaddr_t, vsize_t); | | 385 | void dcache_wb(vaddr_t, vsize_t); |
387 | void dcache_wbinv(vaddr_t, vsize_t); | | 386 | void dcache_wbinv(vaddr_t, vsize_t); |
388 | void dcache_inv(vaddr_t, vsize_t); | | 387 | void dcache_inv(vaddr_t, vsize_t); |
389 | void icache_inv(vaddr_t, vsize_t); | | 388 | void icache_inv(vaddr_t, vsize_t); |
390 | | | 389 | |
391 | void * mapiodev(paddr_t, psize_t, bool); | | 390 | void * mapiodev(paddr_t, psize_t, bool); |
392 | void unmapiodev(vaddr_t, vsize_t); | | 391 | void unmapiodev(vaddr_t, vsize_t); |
393 | | | 392 | |
394 | #ifdef MULTIPROCESSOR | | 393 | #ifdef MULTIPROCESSOR |
395 | int md_setup_trampoline(volatile struct cpu_hatch_data *, | | 394 | int md_setup_trampoline(volatile struct cpu_hatch_data *, |
396 | struct cpu_info *); | | 395 | struct cpu_info *); |
397 | void md_presync_timebase(volatile struct cpu_hatch_data *); | | 396 | void md_presync_timebase(volatile struct cpu_hatch_data *); |
398 | void md_start_timebase(volatile struct cpu_hatch_data *); | | 397 | void md_start_timebase(volatile struct cpu_hatch_data *); |
399 | void md_sync_timebase(volatile struct cpu_hatch_data *); | | 398 | void md_sync_timebase(volatile struct cpu_hatch_data *); |
400 | void md_setup_interrupts(void); | | 399 | void md_setup_interrupts(void); |
401 | int cpu_spinup(device_t, struct cpu_info *); | | 400 | int cpu_spinup(device_t, struct cpu_info *); |
402 | register_t | | 401 | register_t |
403 | cpu_hatch(void); | | 402 | cpu_hatch(void); |
404 | void cpu_spinup_trampoline(void); | | 403 | void cpu_spinup_trampoline(void); |
405 | void cpu_boot_secondary_processors(void); | | 404 | void cpu_boot_secondary_processors(void); |
406 | void cpu_halt(void); | | 405 | void cpu_halt(void); |
407 | void cpu_halt_others(void); | | 406 | void cpu_halt_others(void); |
408 | void cpu_pause(struct trapframe *); | | 407 | void cpu_pause(struct trapframe *); |
409 | void cpu_pause_others(void); | | 408 | void cpu_pause_others(void); |
410 | void cpu_resume(cpuid_t); | | 409 | void cpu_resume(cpuid_t); |
411 | void cpu_resume_others(void); | | 410 | void cpu_resume_others(void); |
412 | int cpu_is_paused(int); | | 411 | int cpu_is_paused(int); |
413 | void cpu_debug_dump(void); | | 412 | void cpu_debug_dump(void); |
414 | #endif /* MULTIPROCESSOR */ | | 413 | #endif /* MULTIPROCESSOR */ |
415 | #endif /* !_MODULE */ | | 414 | #endif /* !_MODULE */ |
416 | | | 415 | |
417 | #define cpu_proc_fork(p1, p2) | | 416 | #define cpu_proc_fork(p1, p2) |
418 | | | 417 | |
419 | #ifndef __HIDE_DELAY | | 418 | #ifndef __HIDE_DELAY |
420 | #define DELAY(n) delay(n) | | 419 | #define DELAY(n) delay(n) |
421 | void delay(unsigned int); | | 420 | void delay(unsigned int); |
422 | #endif /* __HIDE_DELAY */ | | 421 | #endif /* __HIDE_DELAY */ |
423 | | | 422 | |
424 | #define CLKF_USERMODE(cf) cpu_clkf_usermode(cf) | | 423 | #define CLKF_USERMODE(cf) cpu_clkf_usermode(cf) |
425 | #define CLKF_PC(cf) cpu_clkf_pc(cf) | | 424 | #define CLKF_PC(cf) cpu_clkf_pc(cf) |
426 | #define CLKF_INTR(cf) cpu_clkf_intr(cf) | | 425 | #define CLKF_INTR(cf) cpu_clkf_intr(cf) |
427 | | | 426 | |
428 | bool cpu_clkf_usermode(const struct clockframe *); | | 427 | bool cpu_clkf_usermode(const struct clockframe *); |
429 | vaddr_t cpu_clkf_pc(const struct clockframe *); | | 428 | vaddr_t cpu_clkf_pc(const struct clockframe *); |
430 | bool cpu_clkf_intr(const struct clockframe *); | | 429 | bool cpu_clkf_intr(const struct clockframe *); |
431 | | | 430 | |
432 | #define LWP_PC(l) cpu_lwp_pc(l) | | 431 | #define LWP_PC(l) cpu_lwp_pc(l) |
433 | | | 432 | |
434 | vaddr_t cpu_lwp_pc(struct lwp *); | | 433 | vaddr_t cpu_lwp_pc(struct lwp *); |
435 | | | 434 | |
436 | void cpu_ast(struct lwp *, struct cpu_info *); | | 435 | void cpu_ast(struct lwp *, struct cpu_info *); |
437 | void * cpu_uarea_alloc(bool); | | 436 | void * cpu_uarea_alloc(bool); |
438 | bool cpu_uarea_free(void *); | | 437 | bool cpu_uarea_free(void *); |
439 | void cpu_signotify(struct lwp *); | | 438 | void cpu_signotify(struct lwp *); |
440 | void cpu_need_proftick(struct lwp *); | | 439 | void cpu_need_proftick(struct lwp *); |
441 | | | 440 | |
442 | void cpu_fixup_stubs(void); | | 441 | void cpu_fixup_stubs(void); |
443 | | | 442 | |
444 | #if !defined(PPC_IBM4XX) && !defined(PPC_BOOKE) && !defined(_MODULE) | | 443 | #if !defined(PPC_IBM4XX) && !defined(PPC_BOOKE) && !defined(_MODULE) |
445 | int cpu_get_dfs(void); | | 444 | int cpu_get_dfs(void); |
446 | void cpu_set_dfs(int); | | 445 | void cpu_set_dfs(int); |
447 | | | 446 | |
448 | void oea_init(void (*)(void)); | | 447 | void oea_init(void (*)(void)); |
449 | void oea_startup(const char *); | | 448 | void oea_startup(const char *); |
450 | void oea_dumpsys(void); | | 449 | void oea_dumpsys(void); |
451 | void oea_install_extint(void (*)(void)); | | 450 | void oea_install_extint(void (*)(void)); |
452 | paddr_t kvtop(void *); | | 451 | paddr_t kvtop(void *); |
453 | | | 452 | |
454 | extern paddr_t msgbuf_paddr; | | 453 | extern paddr_t msgbuf_paddr; |
455 | extern int cpu_altivec; | | 454 | extern int cpu_altivec; |
456 | #endif | | 455 | #endif |
457 | | | 456 | |
458 | #endif /* _KERNEL */ | | 457 | #endif /* _KERNEL */ |
459 | | | 458 | |
460 | /* XXX The below breaks unified pmap on ppc32 */ | | 459 | /* XXX The below breaks unified pmap on ppc32 */ |
461 | | | 460 | |
462 | #if !defined(CACHELINESIZE) && !defined(_MODULE) \ | | 461 | #if !defined(CACHELINESIZE) && !defined(_MODULE) \ |
463 | && (defined(_KERNEL) || defined(_STANDALONE)) | | 462 | && (defined(_KERNEL) || defined(_STANDALONE)) |
464 | #if defined(PPC_IBM403) | | 463 | #if defined(PPC_IBM403) |
465 | #define CACHELINESIZE 16 | | 464 | #define CACHELINESIZE 16 |
466 | #define MAXCACHELINESIZE 16 | | 465 | #define MAXCACHELINESIZE 16 |
467 | #elif defined (PPC_OEA64_BRIDGE) | | 466 | #elif defined (PPC_OEA64_BRIDGE) |
468 | #define CACHELINESIZE 128 | | 467 | #define CACHELINESIZE 128 |
469 | #define MAXCACHELINESIZE 128 | | 468 | #define MAXCACHELINESIZE 128 |
470 | #else | | 469 | #else |
471 | #define CACHELINESIZE 32 | | 470 | #define CACHELINESIZE 32 |
472 | #define MAXCACHELINESIZE 32 | | 471 | #define MAXCACHELINESIZE 32 |
473 | #endif /* PPC_OEA64_BRIDGE */ | | 472 | #endif /* PPC_OEA64_BRIDGE */ |
474 | #endif | | 473 | #endif |
475 | | | 474 | |
476 | void __syncicache(void *, size_t); | | 475 | void __syncicache(void *, size_t); |
477 | | | 476 | |
478 | /* | | 477 | /* |
479 | * CTL_MACHDEP definitions. | | 478 | * CTL_MACHDEP definitions. |
480 | */ | | 479 | */ |
481 | #define CPU_CACHELINE 1 | | 480 | #define CPU_CACHELINE 1 |
482 | #define CPU_TIMEBASE 2 | | 481 | #define CPU_TIMEBASE 2 |
483 | #define CPU_CPUTEMP 3 | | 482 | #define CPU_CPUTEMP 3 |
484 | #define CPU_PRINTFATALTRAPS 4 | | 483 | #define CPU_PRINTFATALTRAPS 4 |
485 | #define CPU_CACHEINFO 5 | | 484 | #define CPU_CACHEINFO 5 |
486 | #define CPU_ALTIVEC 6 | | 485 | #define CPU_ALTIVEC 6 |
487 | #define CPU_MODEL 7 | | 486 | #define CPU_MODEL 7 |
488 | #define CPU_POWERSAVE 8 /* int: use CPU powersave mode */ | | 487 | #define CPU_POWERSAVE 8 /* int: use CPU powersave mode */ |
489 | #define CPU_BOOTED_DEVICE 9 /* string: device we booted from */ | | 488 | #define CPU_BOOTED_DEVICE 9 /* string: device we booted from */ |
490 | #define CPU_BOOTED_KERNEL 10 /* string: kernel we booted */ | | 489 | #define CPU_BOOTED_KERNEL 10 /* string: kernel we booted */ |
491 | #define CPU_EXECPROT 11 /* bool: PROT_EXEC works */ | | 490 | #define CPU_EXECPROT 11 /* bool: PROT_EXEC works */ |
492 | | | 491 | |
493 | #endif /* _POWERPC_CPU_H_ */ | | 492 | #endif /* _POWERPC_CPU_H_ */ |