diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/parisc/kernel |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/parisc/kernel')
46 files changed, 26744 insertions, 0 deletions
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile new file mode 100644 index 000000000000..171f9c239f60 --- /dev/null +++ b/arch/parisc/kernel/Makefile | |||
@@ -0,0 +1,24 @@ | |||
1 | # | ||
2 | # Makefile for arch/parisc/kernel | ||
3 | # | ||
4 | |||
5 | extra-y := init_task.o head.o vmlinux.lds | ||
6 | |||
7 | AFLAGS_entry.o := -traditional | ||
8 | AFLAGS_pacache.o := -traditional | ||
9 | CFLAGS_ioctl32.o := -Ifs/ | ||
10 | |||
11 | obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \ | ||
12 | pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ | ||
13 | ptrace.o hardware.o inventory.o drivers.o semaphore.o \ | ||
14 | signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \ | ||
15 | process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \ | ||
16 | topology.o | ||
17 | |||
18 | obj-$(CONFIG_SMP) += smp.o | ||
19 | obj-$(CONFIG_PA11) += pci-dma.o | ||
20 | obj-$(CONFIG_PCI) += pci.o | ||
21 | obj-$(CONFIG_MODULES) += module.o | ||
22 | obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o | ||
23 | # only supported for PCX-W/U in 64-bit mode at the moment | ||
24 | obj-$(CONFIG_64BIT) += perf.o perf_asm.o | ||
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c new file mode 100644 index 000000000000..1ad44f92d6e4 --- /dev/null +++ b/arch/parisc/kernel/asm-offsets.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * Generate definitions needed by assembly language modules. | ||
3 | * This code generates raw asm output which is post-processed to extract | ||
4 | * and format the required data. | ||
5 | * | ||
6 | * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org> | ||
7 | * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org> | ||
8 | * Copyright (C) 2000 Sam Creasey <sammy@sammy.net> | ||
9 | * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org> | ||
10 | * Copyright (C) 2001 Paul Bame <bame at parisc-linux.org> | ||
11 | * Copyright (C) 2001 Richard Hirst <rhirst at parisc-linux.org> | ||
12 | * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> | ||
13 | * Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #include <linux/types.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/thread_info.h> | ||
33 | #include <linux/version.h> | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/hardirq.h> | ||
36 | |||
37 | #include <asm/pgtable.h> | ||
38 | #include <asm/ptrace.h> | ||
39 | #include <asm/processor.h> | ||
40 | #include <asm/pdc.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | |||
43 | #define DEFINE(sym, val) \ | ||
44 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | ||
45 | |||
46 | #define BLANK() asm volatile("\n->" : : ) | ||
47 | |||
48 | #ifdef __LP64__ | ||
49 | #define FRAME_SIZE 128 | ||
50 | #else | ||
51 | #define FRAME_SIZE 64 | ||
52 | #endif | ||
53 | |||
54 | #define align(x,y) (((x)+FRAME_SIZE+(y)-1) - (((x)+(y)-1)%(y))) | ||
55 | |||
56 | int main(void) | ||
57 | { | ||
58 | DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); | ||
59 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); | ||
60 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); | ||
61 | DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending)); | ||
62 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); | ||
63 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); | ||
64 | DEFINE(TASK_PERSONALITY, offsetof(struct task_struct, personality)); | ||
65 | DEFINE(TASK_PID, offsetof(struct task_struct, pid)); | ||
66 | BLANK(); | ||
67 | DEFINE(TASK_REGS, offsetof(struct task_struct, thread.regs)); | ||
68 | DEFINE(TASK_PT_PSW, offsetof(struct task_struct, thread.regs.gr[ 0])); | ||
69 | DEFINE(TASK_PT_GR1, offsetof(struct task_struct, thread.regs.gr[ 1])); | ||
70 | DEFINE(TASK_PT_GR2, offsetof(struct task_struct, thread.regs.gr[ 2])); | ||
71 | DEFINE(TASK_PT_GR3, offsetof(struct task_struct, thread.regs.gr[ 3])); | ||
72 | DEFINE(TASK_PT_GR4, offsetof(struct task_struct, thread.regs.gr[ 4])); | ||
73 | DEFINE(TASK_PT_GR5, offsetof(struct task_struct, thread.regs.gr[ 5])); | ||
74 | DEFINE(TASK_PT_GR6, offsetof(struct task_struct, thread.regs.gr[ 6])); | ||
75 | DEFINE(TASK_PT_GR7, offsetof(struct task_struct, thread.regs.gr[ 7])); | ||
76 | DEFINE(TASK_PT_GR8, offsetof(struct task_struct, thread.regs.gr[ 8])); | ||
77 | DEFINE(TASK_PT_GR9, offsetof(struct task_struct, thread.regs.gr[ 9])); | ||
78 | DEFINE(TASK_PT_GR10, offsetof(struct task_struct, thread.regs.gr[10])); | ||
79 | DEFINE(TASK_PT_GR11, offsetof(struct task_struct, thread.regs.gr[11])); | ||
80 | DEFINE(TASK_PT_GR12, offsetof(struct task_struct, thread.regs.gr[12])); | ||
81 | DEFINE(TASK_PT_GR13, offsetof(struct task_struct, thread.regs.gr[13])); | ||
82 | DEFINE(TASK_PT_GR14, offsetof(struct task_struct, thread.regs.gr[14])); | ||
83 | DEFINE(TASK_PT_GR15, offsetof(struct task_struct, thread.regs.gr[15])); | ||
84 | DEFINE(TASK_PT_GR16, offsetof(struct task_struct, thread.regs.gr[16])); | ||
85 | DEFINE(TASK_PT_GR17, offsetof(struct task_struct, thread.regs.gr[17])); | ||
86 | DEFINE(TASK_PT_GR18, offsetof(struct task_struct, thread.regs.gr[18])); | ||
87 | DEFINE(TASK_PT_GR19, offsetof(struct task_struct, thread.regs.gr[19])); | ||
88 | DEFINE(TASK_PT_GR20, offsetof(struct task_struct, thread.regs.gr[20])); | ||
89 | DEFINE(TASK_PT_GR21, offsetof(struct task_struct, thread.regs.gr[21])); | ||
90 | DEFINE(TASK_PT_GR22, offsetof(struct task_struct, thread.regs.gr[22])); | ||
91 | DEFINE(TASK_PT_GR23, offsetof(struct task_struct, thread.regs.gr[23])); | ||
92 | DEFINE(TASK_PT_GR24, offsetof(struct task_struct, thread.regs.gr[24])); | ||
93 | DEFINE(TASK_PT_GR25, offsetof(struct task_struct, thread.regs.gr[25])); | ||
94 | DEFINE(TASK_PT_GR26, offsetof(struct task_struct, thread.regs.gr[26])); | ||
95 | DEFINE(TASK_PT_GR27, offsetof(struct task_struct, thread.regs.gr[27])); | ||
96 | DEFINE(TASK_PT_GR28, offsetof(struct task_struct, thread.regs.gr[28])); | ||
97 | DEFINE(TASK_PT_GR29, offsetof(struct task_struct, thread.regs.gr[29])); | ||
98 | DEFINE(TASK_PT_GR30, offsetof(struct task_struct, thread.regs.gr[30])); | ||
99 | DEFINE(TASK_PT_GR31, offsetof(struct task_struct, thread.regs.gr[31])); | ||
100 | DEFINE(TASK_PT_FR0, offsetof(struct task_struct, thread.regs.fr[ 0])); | ||
101 | DEFINE(TASK_PT_FR1, offsetof(struct task_struct, thread.regs.fr[ 1])); | ||
102 | DEFINE(TASK_PT_FR2, offsetof(struct task_struct, thread.regs.fr[ 2])); | ||
103 | DEFINE(TASK_PT_FR3, offsetof(struct task_struct, thread.regs.fr[ 3])); | ||
104 | DEFINE(TASK_PT_FR4, offsetof(struct task_struct, thread.regs.fr[ 4])); | ||
105 | DEFINE(TASK_PT_FR5, offsetof(struct task_struct, thread.regs.fr[ 5])); | ||
106 | DEFINE(TASK_PT_FR6, offsetof(struct task_struct, thread.regs.fr[ 6])); | ||
107 | DEFINE(TASK_PT_FR7, offsetof(struct task_struct, thread.regs.fr[ 7])); | ||
108 | DEFINE(TASK_PT_FR8, offsetof(struct task_struct, thread.regs.fr[ 8])); | ||
109 | DEFINE(TASK_PT_FR9, offsetof(struct task_struct, thread.regs.fr[ 9])); | ||
110 | DEFINE(TASK_PT_FR10, offsetof(struct task_struct, thread.regs.fr[10])); | ||
111 | DEFINE(TASK_PT_FR11, offsetof(struct task_struct, thread.regs.fr[11])); | ||
112 | DEFINE(TASK_PT_FR12, offsetof(struct task_struct, thread.regs.fr[12])); | ||
113 | DEFINE(TASK_PT_FR13, offsetof(struct task_struct, thread.regs.fr[13])); | ||
114 | DEFINE(TASK_PT_FR14, offsetof(struct task_struct, thread.regs.fr[14])); | ||
115 | DEFINE(TASK_PT_FR15, offsetof(struct task_struct, thread.regs.fr[15])); | ||
116 | DEFINE(TASK_PT_FR16, offsetof(struct task_struct, thread.regs.fr[16])); | ||
117 | DEFINE(TASK_PT_FR17, offsetof(struct task_struct, thread.regs.fr[17])); | ||
118 | DEFINE(TASK_PT_FR18, offsetof(struct task_struct, thread.regs.fr[18])); | ||
119 | DEFINE(TASK_PT_FR19, offsetof(struct task_struct, thread.regs.fr[19])); | ||
120 | DEFINE(TASK_PT_FR20, offsetof(struct task_struct, thread.regs.fr[20])); | ||
121 | DEFINE(TASK_PT_FR21, offsetof(struct task_struct, thread.regs.fr[21])); | ||
122 | DEFINE(TASK_PT_FR22, offsetof(struct task_struct, thread.regs.fr[22])); | ||
123 | DEFINE(TASK_PT_FR23, offsetof(struct task_struct, thread.regs.fr[23])); | ||
124 | DEFINE(TASK_PT_FR24, offsetof(struct task_struct, thread.regs.fr[24])); | ||
125 | DEFINE(TASK_PT_FR25, offsetof(struct task_struct, thread.regs.fr[25])); | ||
126 | DEFINE(TASK_PT_FR26, offsetof(struct task_struct, thread.regs.fr[26])); | ||
127 | DEFINE(TASK_PT_FR27, offsetof(struct task_struct, thread.regs.fr[27])); | ||
128 | DEFINE(TASK_PT_FR28, offsetof(struct task_struct, thread.regs.fr[28])); | ||
129 | DEFINE(TASK_PT_FR29, offsetof(struct task_struct, thread.regs.fr[29])); | ||
130 | DEFINE(TASK_PT_FR30, offsetof(struct task_struct, thread.regs.fr[30])); | ||
131 | DEFINE(TASK_PT_FR31, offsetof(struct task_struct, thread.regs.fr[31])); | ||
132 | DEFINE(TASK_PT_SR0, offsetof(struct task_struct, thread.regs.sr[ 0])); | ||
133 | DEFINE(TASK_PT_SR1, offsetof(struct task_struct, thread.regs.sr[ 1])); | ||
134 | DEFINE(TASK_PT_SR2, offsetof(struct task_struct, thread.regs.sr[ 2])); | ||
135 | DEFINE(TASK_PT_SR3, offsetof(struct task_struct, thread.regs.sr[ 3])); | ||
136 | DEFINE(TASK_PT_SR4, offsetof(struct task_struct, thread.regs.sr[ 4])); | ||
137 | DEFINE(TASK_PT_SR5, offsetof(struct task_struct, thread.regs.sr[ 5])); | ||
138 | DEFINE(TASK_PT_SR6, offsetof(struct task_struct, thread.regs.sr[ 6])); | ||
139 | DEFINE(TASK_PT_SR7, offsetof(struct task_struct, thread.regs.sr[ 7])); | ||
140 | DEFINE(TASK_PT_IASQ0, offsetof(struct task_struct, thread.regs.iasq[0])); | ||
141 | DEFINE(TASK_PT_IASQ1, offsetof(struct task_struct, thread.regs.iasq[1])); | ||
142 | DEFINE(TASK_PT_IAOQ0, offsetof(struct task_struct, thread.regs.iaoq[0])); | ||
143 | DEFINE(TASK_PT_IAOQ1, offsetof(struct task_struct, thread.regs.iaoq[1])); | ||
144 | DEFINE(TASK_PT_CR27, offsetof(struct task_struct, thread.regs.cr27)); | ||
145 | DEFINE(TASK_PT_ORIG_R28, offsetof(struct task_struct, thread.regs.orig_r28)); | ||
146 | DEFINE(TASK_PT_KSP, offsetof(struct task_struct, thread.regs.ksp)); | ||
147 | DEFINE(TASK_PT_KPC, offsetof(struct task_struct, thread.regs.kpc)); | ||
148 | DEFINE(TASK_PT_SAR, offsetof(struct task_struct, thread.regs.sar)); | ||
149 | DEFINE(TASK_PT_IIR, offsetof(struct task_struct, thread.regs.iir)); | ||
150 | DEFINE(TASK_PT_ISR, offsetof(struct task_struct, thread.regs.isr)); | ||
151 | DEFINE(TASK_PT_IOR, offsetof(struct task_struct, thread.regs.ior)); | ||
152 | BLANK(); | ||
153 | DEFINE(TASK_SZ, sizeof(struct task_struct)); | ||
154 | DEFINE(TASK_SZ_ALGN, align(sizeof(struct task_struct), 64)); | ||
155 | BLANK(); | ||
156 | DEFINE(PT_PSW, offsetof(struct pt_regs, gr[ 0])); | ||
157 | DEFINE(PT_GR1, offsetof(struct pt_regs, gr[ 1])); | ||
158 | DEFINE(PT_GR2, offsetof(struct pt_regs, gr[ 2])); | ||
159 | DEFINE(PT_GR3, offsetof(struct pt_regs, gr[ 3])); | ||
160 | DEFINE(PT_GR4, offsetof(struct pt_regs, gr[ 4])); | ||
161 | DEFINE(PT_GR5, offsetof(struct pt_regs, gr[ 5])); | ||
162 | DEFINE(PT_GR6, offsetof(struct pt_regs, gr[ 6])); | ||
163 | DEFINE(PT_GR7, offsetof(struct pt_regs, gr[ 7])); | ||
164 | DEFINE(PT_GR8, offsetof(struct pt_regs, gr[ 8])); | ||
165 | DEFINE(PT_GR9, offsetof(struct pt_regs, gr[ 9])); | ||
166 | DEFINE(PT_GR10, offsetof(struct pt_regs, gr[10])); | ||
167 | DEFINE(PT_GR11, offsetof(struct pt_regs, gr[11])); | ||
168 | DEFINE(PT_GR12, offsetof(struct pt_regs, gr[12])); | ||
169 | DEFINE(PT_GR13, offsetof(struct pt_regs, gr[13])); | ||
170 | DEFINE(PT_GR14, offsetof(struct pt_regs, gr[14])); | ||
171 | DEFINE(PT_GR15, offsetof(struct pt_regs, gr[15])); | ||
172 | DEFINE(PT_GR16, offsetof(struct pt_regs, gr[16])); | ||
173 | DEFINE(PT_GR17, offsetof(struct pt_regs, gr[17])); | ||
174 | DEFINE(PT_GR18, offsetof(struct pt_regs, gr[18])); | ||
175 | DEFINE(PT_GR19, offsetof(struct pt_regs, gr[19])); | ||
176 | DEFINE(PT_GR20, offsetof(struct pt_regs, gr[20])); | ||
177 | DEFINE(PT_GR21, offsetof(struct pt_regs, gr[21])); | ||
178 | DEFINE(PT_GR22, offsetof(struct pt_regs, gr[22])); | ||
179 | DEFINE(PT_GR23, offsetof(struct pt_regs, gr[23])); | ||
180 | DEFINE(PT_GR24, offsetof(struct pt_regs, gr[24])); | ||
181 | DEFINE(PT_GR25, offsetof(struct pt_regs, gr[25])); | ||
182 | DEFINE(PT_GR26, offsetof(struct pt_regs, gr[26])); | ||
183 | DEFINE(PT_GR27, offsetof(struct pt_regs, gr[27])); | ||
184 | DEFINE(PT_GR28, offsetof(struct pt_regs, gr[28])); | ||
185 | DEFINE(PT_GR29, offsetof(struct pt_regs, gr[29])); | ||
186 | DEFINE(PT_GR30, offsetof(struct pt_regs, gr[30])); | ||
187 | DEFINE(PT_GR31, offsetof(struct pt_regs, gr[31])); | ||
188 | DEFINE(PT_FR0, offsetof(struct pt_regs, fr[ 0])); | ||
189 | DEFINE(PT_FR1, offsetof(struct pt_regs, fr[ 1])); | ||
190 | DEFINE(PT_FR2, offsetof(struct pt_regs, fr[ 2])); | ||
191 | DEFINE(PT_FR3, offsetof(struct pt_regs, fr[ 3])); | ||
192 | DEFINE(PT_FR4, offsetof(struct pt_regs, fr[ 4])); | ||
193 | DEFINE(PT_FR5, offsetof(struct pt_regs, fr[ 5])); | ||
194 | DEFINE(PT_FR6, offsetof(struct pt_regs, fr[ 6])); | ||
195 | DEFINE(PT_FR7, offsetof(struct pt_regs, fr[ 7])); | ||
196 | DEFINE(PT_FR8, offsetof(struct pt_regs, fr[ 8])); | ||
197 | DEFINE(PT_FR9, offsetof(struct pt_regs, fr[ 9])); | ||
198 | DEFINE(PT_FR10, offsetof(struct pt_regs, fr[10])); | ||
199 | DEFINE(PT_FR11, offsetof(struct pt_regs, fr[11])); | ||
200 | DEFINE(PT_FR12, offsetof(struct pt_regs, fr[12])); | ||
201 | DEFINE(PT_FR13, offsetof(struct pt_regs, fr[13])); | ||
202 | DEFINE(PT_FR14, offsetof(struct pt_regs, fr[14])); | ||
203 | DEFINE(PT_FR15, offsetof(struct pt_regs, fr[15])); | ||
204 | DEFINE(PT_FR16, offsetof(struct pt_regs, fr[16])); | ||
205 | DEFINE(PT_FR17, offsetof(struct pt_regs, fr[17])); | ||
206 | DEFINE(PT_FR18, offsetof(struct pt_regs, fr[18])); | ||
207 | DEFINE(PT_FR19, offsetof(struct pt_regs, fr[19])); | ||
208 | DEFINE(PT_FR20, offsetof(struct pt_regs, fr[20])); | ||
209 | DEFINE(PT_FR21, offsetof(struct pt_regs, fr[21])); | ||
210 | DEFINE(PT_FR22, offsetof(struct pt_regs, fr[22])); | ||
211 | DEFINE(PT_FR23, offsetof(struct pt_regs, fr[23])); | ||
212 | DEFINE(PT_FR24, offsetof(struct pt_regs, fr[24])); | ||
213 | DEFINE(PT_FR25, offsetof(struct pt_regs, fr[25])); | ||
214 | DEFINE(PT_FR26, offsetof(struct pt_regs, fr[26])); | ||
215 | DEFINE(PT_FR27, offsetof(struct pt_regs, fr[27])); | ||
216 | DEFINE(PT_FR28, offsetof(struct pt_regs, fr[28])); | ||
217 | DEFINE(PT_FR29, offsetof(struct pt_regs, fr[29])); | ||
218 | DEFINE(PT_FR30, offsetof(struct pt_regs, fr[30])); | ||
219 | DEFINE(PT_FR31, offsetof(struct pt_regs, fr[31])); | ||
220 | DEFINE(PT_SR0, offsetof(struct pt_regs, sr[ 0])); | ||
221 | DEFINE(PT_SR1, offsetof(struct pt_regs, sr[ 1])); | ||
222 | DEFINE(PT_SR2, offsetof(struct pt_regs, sr[ 2])); | ||
223 | DEFINE(PT_SR3, offsetof(struct pt_regs, sr[ 3])); | ||
224 | DEFINE(PT_SR4, offsetof(struct pt_regs, sr[ 4])); | ||
225 | DEFINE(PT_SR5, offsetof(struct pt_regs, sr[ 5])); | ||
226 | DEFINE(PT_SR6, offsetof(struct pt_regs, sr[ 6])); | ||
227 | DEFINE(PT_SR7, offsetof(struct pt_regs, sr[ 7])); | ||
228 | DEFINE(PT_IASQ0, offsetof(struct pt_regs, iasq[0])); | ||
229 | DEFINE(PT_IASQ1, offsetof(struct pt_regs, iasq[1])); | ||
230 | DEFINE(PT_IAOQ0, offsetof(struct pt_regs, iaoq[0])); | ||
231 | DEFINE(PT_IAOQ1, offsetof(struct pt_regs, iaoq[1])); | ||
232 | DEFINE(PT_CR27, offsetof(struct pt_regs, cr27)); | ||
233 | DEFINE(PT_ORIG_R28, offsetof(struct pt_regs, orig_r28)); | ||
234 | DEFINE(PT_KSP, offsetof(struct pt_regs, ksp)); | ||
235 | DEFINE(PT_KPC, offsetof(struct pt_regs, kpc)); | ||
236 | DEFINE(PT_SAR, offsetof(struct pt_regs, sar)); | ||
237 | DEFINE(PT_IIR, offsetof(struct pt_regs, iir)); | ||
238 | DEFINE(PT_ISR, offsetof(struct pt_regs, isr)); | ||
239 | DEFINE(PT_IOR, offsetof(struct pt_regs, ior)); | ||
240 | DEFINE(PT_SIZE, sizeof(struct pt_regs)); | ||
241 | DEFINE(PT_SZ_ALGN, align(sizeof(struct pt_regs), 64)); | ||
242 | BLANK(); | ||
243 | DEFINE(TI_TASK, offsetof(struct thread_info, task)); | ||
244 | DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); | ||
245 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | ||
246 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); | ||
247 | DEFINE(TI_SEGMENT, offsetof(struct thread_info, addr_limit)); | ||
248 | DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); | ||
249 | DEFINE(THREAD_SZ, sizeof(struct thread_info)); | ||
250 | DEFINE(THREAD_SZ_ALGN, align(sizeof(struct thread_info), 64)); | ||
251 | BLANK(); | ||
252 | DEFINE(IRQSTAT_SIRQ_PEND, offsetof(irq_cpustat_t, __softirq_pending)); | ||
253 | DEFINE(IRQSTAT_SZ, sizeof(irq_cpustat_t)); | ||
254 | BLANK(); | ||
255 | DEFINE(ICACHE_BASE, offsetof(struct pdc_cache_info, ic_base)); | ||
256 | DEFINE(ICACHE_STRIDE, offsetof(struct pdc_cache_info, ic_stride)); | ||
257 | DEFINE(ICACHE_COUNT, offsetof(struct pdc_cache_info, ic_count)); | ||
258 | DEFINE(ICACHE_LOOP, offsetof(struct pdc_cache_info, ic_loop)); | ||
259 | DEFINE(DCACHE_BASE, offsetof(struct pdc_cache_info, dc_base)); | ||
260 | DEFINE(DCACHE_STRIDE, offsetof(struct pdc_cache_info, dc_stride)); | ||
261 | DEFINE(DCACHE_COUNT, offsetof(struct pdc_cache_info, dc_count)); | ||
262 | DEFINE(DCACHE_LOOP, offsetof(struct pdc_cache_info, dc_loop)); | ||
263 | DEFINE(ITLB_SID_BASE, offsetof(struct pdc_cache_info, it_sp_base)); | ||
264 | DEFINE(ITLB_SID_STRIDE, offsetof(struct pdc_cache_info, it_sp_stride)); | ||
265 | DEFINE(ITLB_SID_COUNT, offsetof(struct pdc_cache_info, it_sp_count)); | ||
266 | DEFINE(ITLB_OFF_BASE, offsetof(struct pdc_cache_info, it_off_base)); | ||
267 | DEFINE(ITLB_OFF_STRIDE, offsetof(struct pdc_cache_info, it_off_stride)); | ||
268 | DEFINE(ITLB_OFF_COUNT, offsetof(struct pdc_cache_info, it_off_count)); | ||
269 | DEFINE(ITLB_LOOP, offsetof(struct pdc_cache_info, it_loop)); | ||
270 | DEFINE(DTLB_SID_BASE, offsetof(struct pdc_cache_info, dt_sp_base)); | ||
271 | DEFINE(DTLB_SID_STRIDE, offsetof(struct pdc_cache_info, dt_sp_stride)); | ||
272 | DEFINE(DTLB_SID_COUNT, offsetof(struct pdc_cache_info, dt_sp_count)); | ||
273 | DEFINE(DTLB_OFF_BASE, offsetof(struct pdc_cache_info, dt_off_base)); | ||
274 | DEFINE(DTLB_OFF_STRIDE, offsetof(struct pdc_cache_info, dt_off_stride)); | ||
275 | DEFINE(DTLB_OFF_COUNT, offsetof(struct pdc_cache_info, dt_off_count)); | ||
276 | DEFINE(DTLB_LOOP, offsetof(struct pdc_cache_info, dt_loop)); | ||
277 | BLANK(); | ||
278 | DEFINE(PA_BLOCKSTEP_BIT, 31-PT_BLOCKSTEP_BIT); | ||
279 | DEFINE(PA_SINGLESTEP_BIT, 31-PT_SINGLESTEP_BIT); | ||
280 | BLANK(); | ||
281 | DEFINE(ASM_PMD_SHIFT, PMD_SHIFT); | ||
282 | DEFINE(ASM_PGDIR_SHIFT, PGDIR_SHIFT); | ||
283 | DEFINE(ASM_BITS_PER_PGD, BITS_PER_PGD); | ||
284 | DEFINE(ASM_BITS_PER_PMD, BITS_PER_PMD); | ||
285 | DEFINE(ASM_BITS_PER_PTE, BITS_PER_PTE); | ||
286 | DEFINE(ASM_PGD_PMD_OFFSET, -(PAGE_SIZE << PGD_ORDER)); | ||
287 | DEFINE(ASM_PMD_ENTRY, ((PAGE_OFFSET & PMD_MASK) >> PMD_SHIFT)); | ||
288 | DEFINE(ASM_PGD_ENTRY, PAGE_OFFSET >> PGDIR_SHIFT); | ||
289 | DEFINE(ASM_PGD_ENTRY_SIZE, PGD_ENTRY_SIZE); | ||
290 | DEFINE(ASM_PMD_ENTRY_SIZE, PMD_ENTRY_SIZE); | ||
291 | DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE); | ||
292 | DEFINE(ASM_PT_INITIAL, PT_INITIAL); | ||
293 | DEFINE(ASM_PAGE_SIZE, PAGE_SIZE); | ||
294 | BLANK(); | ||
295 | DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); | ||
296 | DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); | ||
297 | DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr)); | ||
298 | return 0; | ||
299 | } | ||
diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c new file mode 100644 index 000000000000..d1833f164bbe --- /dev/null +++ b/arch/parisc/kernel/binfmt_elf32.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Support for 32-bit Linux/Parisc ELF binaries on 64 bit kernels | ||
3 | * | ||
4 | * Copyright (C) 2000 John Marvin | ||
5 | * Copyright (C) 2000 Hewlett Packard Co. | ||
6 | * | ||
7 | * Heavily inspired from various other efforts to do the same thing | ||
8 | * (ia64,sparc64/mips64) | ||
9 | */ | ||
10 | |||
11 | /* Make sure include/asm-parisc/elf.h does the right thing */ | ||
12 | |||
13 | #define ELF_CLASS ELFCLASS32 | ||
14 | |||
15 | #define ELF_CORE_COPY_REGS(dst, pt) \ | ||
16 | memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \ | ||
17 | { int i; \ | ||
18 | for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \ | ||
19 | for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \ | ||
20 | } \ | ||
21 | dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \ | ||
22 | dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \ | ||
23 | dst[44] = (elf_greg_t) pt->sar; dst[45] = (elf_greg_t) pt->iir; \ | ||
24 | dst[46] = (elf_greg_t) pt->isr; dst[47] = (elf_greg_t) pt->ior; \ | ||
25 | dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \ | ||
26 | dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \ | ||
27 | dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \ | ||
28 | dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \ | ||
29 | dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \ | ||
30 | dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \ | ||
31 | dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \ | ||
32 | dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15); | ||
33 | |||
34 | |||
35 | typedef unsigned int elf_greg_t; | ||
36 | |||
37 | #include <linux/spinlock.h> | ||
38 | #include <asm/processor.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/elfcore.h> | ||
41 | #include <linux/compat.h> /* struct compat_timeval */ | ||
42 | |||
43 | #define elf_prstatus elf_prstatus32 | ||
44 | struct elf_prstatus32 | ||
45 | { | ||
46 | struct elf_siginfo pr_info; /* Info associated with signal */ | ||
47 | short pr_cursig; /* Current signal */ | ||
48 | unsigned int pr_sigpend; /* Set of pending signals */ | ||
49 | unsigned int pr_sighold; /* Set of held signals */ | ||
50 | pid_t pr_pid; | ||
51 | pid_t pr_ppid; | ||
52 | pid_t pr_pgrp; | ||
53 | pid_t pr_sid; | ||
54 | struct compat_timeval pr_utime; /* User time */ | ||
55 | struct compat_timeval pr_stime; /* System time */ | ||
56 | struct compat_timeval pr_cutime; /* Cumulative user time */ | ||
57 | struct compat_timeval pr_cstime; /* Cumulative system time */ | ||
58 | elf_gregset_t pr_reg; /* GP registers */ | ||
59 | int pr_fpvalid; /* True if math co-processor being used. */ | ||
60 | }; | ||
61 | |||
62 | #define elf_prpsinfo elf_prpsinfo32 | ||
63 | struct elf_prpsinfo32 | ||
64 | { | ||
65 | char pr_state; /* numeric process state */ | ||
66 | char pr_sname; /* char for pr_state */ | ||
67 | char pr_zomb; /* zombie */ | ||
68 | char pr_nice; /* nice val */ | ||
69 | unsigned int pr_flag; /* flags */ | ||
70 | u16 pr_uid; | ||
71 | u16 pr_gid; | ||
72 | pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; | ||
73 | /* Lots missing */ | ||
74 | char pr_fname[16]; /* filename of executable */ | ||
75 | char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ | ||
76 | }; | ||
77 | |||
78 | #define elf_addr_t unsigned int | ||
79 | #define init_elf_binfmt init_elf32_binfmt | ||
80 | |||
81 | #define ELF_PLATFORM ("PARISC32\0") | ||
82 | |||
83 | /* | ||
84 | * We should probably use this macro to set a flag somewhere to indicate | ||
85 | * this is a 32 on 64 process. We could use PER_LINUX_32BIT, or we | ||
86 | * could set a processor dependent flag in the thread_struct. | ||
87 | */ | ||
88 | |||
89 | #define SET_PERSONALITY(ex, ibcs2) \ | ||
90 | current->personality = PER_LINUX32; \ | ||
91 | current->thread.map_base = DEFAULT_MAP_BASE32; \ | ||
92 | current->thread.task_size = DEFAULT_TASK_SIZE32 \ | ||
93 | |||
94 | #undef cputime_to_timeval | ||
95 | #define cputime_to_timeval cputime_to_compat_timeval | ||
96 | static __inline__ void | ||
97 | cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) | ||
98 | { | ||
99 | unsigned long jiffies = cputime_to_jiffies(cputime); | ||
100 | value->tv_usec = (jiffies % HZ) * (1000000L / HZ); | ||
101 | value->tv_sec = jiffies / HZ; | ||
102 | } | ||
103 | |||
104 | #include "../../../fs/binfmt_elf.c" | ||
105 | |||
106 | /* Set up a separate execution domain for ELF32 binaries running | ||
107 | * on an ELF64 kernel */ | ||
108 | |||
109 | static struct exec_domain parisc32_exec_domain = { | ||
110 | .name = "Linux/ELF32", | ||
111 | .pers_low = PER_LINUX32, | ||
112 | .pers_high = PER_LINUX32, | ||
113 | }; | ||
114 | |||
115 | static int __init parisc32_exec_init(void) | ||
116 | { | ||
117 | /* steal the identity signal mappings from the default domain */ | ||
118 | parisc32_exec_domain.signal_map = default_exec_domain.signal_map; | ||
119 | parisc32_exec_domain.signal_invmap = default_exec_domain.signal_invmap; | ||
120 | |||
121 | register_exec_domain(&parisc32_exec_domain); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | __initcall(parisc32_exec_init); | ||
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c new file mode 100644 index 000000000000..f46a07a79218 --- /dev/null +++ b/arch/parisc/kernel/cache.c | |||
@@ -0,0 +1,366 @@ | |||
1 | /* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $ | ||
2 | * | ||
3 | * This file is subject to the terms and conditions of the GNU General Public | ||
4 | * License. See the file "COPYING" in the main directory of this archive | ||
5 | * for more details. | ||
6 | * | ||
7 | * Copyright (C) 1999 Helge Deller (07-13-1999) | ||
8 | * Copyright (C) 1999 SuSE GmbH Nuernberg | ||
9 | * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org) | ||
10 | * | ||
11 | * Cache and TLB management | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/seq_file.h> | ||
20 | #include <linux/pagemap.h> | ||
21 | |||
22 | #include <asm/pdc.h> | ||
23 | #include <asm/cache.h> | ||
24 | #include <asm/cacheflush.h> | ||
25 | #include <asm/tlbflush.h> | ||
26 | #include <asm/system.h> | ||
27 | #include <asm/page.h> | ||
28 | #include <asm/pgalloc.h> | ||
29 | #include <asm/processor.h> | ||
30 | |||
31 | int split_tlb; | ||
32 | int dcache_stride; | ||
33 | int icache_stride; | ||
34 | EXPORT_SYMBOL(dcache_stride); | ||
35 | |||
36 | |||
37 | #if defined(CONFIG_SMP) | ||
38 | /* On some machines (e.g. ones with the Merced bus), there can be | ||
39 | * only a single PxTLB broadcast at a time; this must be guaranteed | ||
40 | * by software. We put a spinlock around all TLB flushes to | ||
41 | * ensure this. | ||
42 | */ | ||
43 | DEFINE_SPINLOCK(pa_tlb_lock); | ||
44 | EXPORT_SYMBOL(pa_tlb_lock); | ||
45 | #endif | ||
46 | |||
47 | struct pdc_cache_info cache_info; | ||
48 | #ifndef CONFIG_PA20 | ||
49 | static struct pdc_btlb_info btlb_info; | ||
50 | #endif | ||
51 | |||
52 | #ifdef CONFIG_SMP | ||
53 | void | ||
54 | flush_data_cache(void) | ||
55 | { | ||
56 | on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1); | ||
57 | } | ||
58 | void | ||
59 | flush_instruction_cache(void) | ||
60 | { | ||
61 | on_each_cpu((void (*)(void *))flush_instruction_cache_local, NULL, 1, 1); | ||
62 | } | ||
63 | #endif | ||
64 | |||
65 | void | ||
66 | flush_cache_all_local(void) | ||
67 | { | ||
68 | flush_instruction_cache_local(); | ||
69 | flush_data_cache_local(); | ||
70 | } | ||
71 | EXPORT_SYMBOL(flush_cache_all_local); | ||
72 | |||
73 | /* flushes EVERYTHING (tlb & cache) */ | ||
74 | |||
75 | void | ||
76 | flush_all_caches(void) | ||
77 | { | ||
78 | flush_cache_all(); | ||
79 | flush_tlb_all(); | ||
80 | } | ||
81 | EXPORT_SYMBOL(flush_all_caches); | ||
82 | |||
83 | void | ||
84 | update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) | ||
85 | { | ||
86 | struct page *page = pte_page(pte); | ||
87 | |||
88 | if (pfn_valid(page_to_pfn(page)) && page_mapping(page) && | ||
89 | test_bit(PG_dcache_dirty, &page->flags)) { | ||
90 | |||
91 | flush_kernel_dcache_page(page_address(page)); | ||
92 | clear_bit(PG_dcache_dirty, &page->flags); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | void | ||
97 | show_cache_info(struct seq_file *m) | ||
98 | { | ||
99 | seq_printf(m, "I-cache\t\t: %ld KB\n", | ||
100 | cache_info.ic_size/1024 ); | ||
101 | seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %d-way associative)\n", | ||
102 | cache_info.dc_size/1024, | ||
103 | (cache_info.dc_conf.cc_wt ? "WT":"WB"), | ||
104 | (cache_info.dc_conf.cc_sh ? ", shared I/D":""), | ||
105 | (cache_info.dc_conf.cc_assoc) | ||
106 | ); | ||
107 | |||
108 | seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n", | ||
109 | cache_info.it_size, | ||
110 | cache_info.dt_size, | ||
111 | cache_info.dt_conf.tc_sh ? " - shared with ITLB":"" | ||
112 | ); | ||
113 | |||
114 | #ifndef CONFIG_PA20 | ||
115 | /* BTLB - Block TLB */ | ||
116 | if (btlb_info.max_size==0) { | ||
117 | seq_printf(m, "BTLB\t\t: not supported\n" ); | ||
118 | } else { | ||
119 | seq_printf(m, | ||
120 | "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n" | ||
121 | "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n" | ||
122 | "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n", | ||
123 | btlb_info.max_size, (int)4096, | ||
124 | btlb_info.max_size>>8, | ||
125 | btlb_info.fixed_range_info.num_i, | ||
126 | btlb_info.fixed_range_info.num_d, | ||
127 | btlb_info.fixed_range_info.num_comb, | ||
128 | btlb_info.variable_range_info.num_i, | ||
129 | btlb_info.variable_range_info.num_d, | ||
130 | btlb_info.variable_range_info.num_comb | ||
131 | ); | ||
132 | } | ||
133 | #endif | ||
134 | } | ||
135 | |||
136 | void __init | ||
137 | parisc_cache_init(void) | ||
138 | { | ||
139 | if (pdc_cache_info(&cache_info) < 0) | ||
140 | panic("parisc_cache_init: pdc_cache_info failed"); | ||
141 | |||
142 | #if 0 | ||
143 | printk("ic_size %lx dc_size %lx it_size %lx\n", | ||
144 | cache_info.ic_size, | ||
145 | cache_info.dc_size, | ||
146 | cache_info.it_size); | ||
147 | |||
148 | printk("DC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n", | ||
149 | cache_info.dc_base, | ||
150 | cache_info.dc_stride, | ||
151 | cache_info.dc_count, | ||
152 | cache_info.dc_loop); | ||
153 | |||
154 | printk("dc_conf = 0x%lx alias %d blk %d line %d shift %d\n", | ||
155 | *(unsigned long *) (&cache_info.dc_conf), | ||
156 | cache_info.dc_conf.cc_alias, | ||
157 | cache_info.dc_conf.cc_block, | ||
158 | cache_info.dc_conf.cc_line, | ||
159 | cache_info.dc_conf.cc_shift); | ||
160 | printk(" wt %d sh %d cst %d assoc %d\n", | ||
161 | cache_info.dc_conf.cc_wt, | ||
162 | cache_info.dc_conf.cc_sh, | ||
163 | cache_info.dc_conf.cc_cst, | ||
164 | cache_info.dc_conf.cc_assoc); | ||
165 | |||
166 | printk("IC base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n", | ||
167 | cache_info.ic_base, | ||
168 | cache_info.ic_stride, | ||
169 | cache_info.ic_count, | ||
170 | cache_info.ic_loop); | ||
171 | |||
172 | printk("ic_conf = 0x%lx alias %d blk %d line %d shift %d\n", | ||
173 | *(unsigned long *) (&cache_info.ic_conf), | ||
174 | cache_info.ic_conf.cc_alias, | ||
175 | cache_info.ic_conf.cc_block, | ||
176 | cache_info.ic_conf.cc_line, | ||
177 | cache_info.ic_conf.cc_shift); | ||
178 | printk(" wt %d sh %d cst %d assoc %d\n", | ||
179 | cache_info.ic_conf.cc_wt, | ||
180 | cache_info.ic_conf.cc_sh, | ||
181 | cache_info.ic_conf.cc_cst, | ||
182 | cache_info.ic_conf.cc_assoc); | ||
183 | |||
184 | printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n", | ||
185 | cache_info.dt_conf.tc_sh, | ||
186 | cache_info.dt_conf.tc_page, | ||
187 | cache_info.dt_conf.tc_cst, | ||
188 | cache_info.dt_conf.tc_aid, | ||
189 | cache_info.dt_conf.tc_pad1); | ||
190 | |||
191 | printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n", | ||
192 | cache_info.it_conf.tc_sh, | ||
193 | cache_info.it_conf.tc_page, | ||
194 | cache_info.it_conf.tc_cst, | ||
195 | cache_info.it_conf.tc_aid, | ||
196 | cache_info.it_conf.tc_pad1); | ||
197 | #endif | ||
198 | |||
199 | split_tlb = 0; | ||
200 | if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) { | ||
201 | if (cache_info.dt_conf.tc_sh == 2) | ||
202 | printk(KERN_WARNING "Unexpected TLB configuration. " | ||
203 | "Will flush I/D separately (could be optimized).\n"); | ||
204 | |||
205 | split_tlb = 1; | ||
206 | } | ||
207 | |||
208 | /* "New and Improved" version from Jim Hull | ||
209 | * (1 << (cc_block-1)) * (cc_line << (4 + cnf.cc_shift)) | ||
210 | */ | ||
211 | #define CAFL_STRIDE(cnf) (cnf.cc_line << (3 + cnf.cc_block + cnf.cc_shift)) | ||
212 | dcache_stride = CAFL_STRIDE(cache_info.dc_conf); | ||
213 | icache_stride = CAFL_STRIDE(cache_info.ic_conf); | ||
214 | #undef CAFL_STRIDE | ||
215 | |||
216 | #ifndef CONFIG_PA20 | ||
217 | if (pdc_btlb_info(&btlb_info) < 0) { | ||
218 | memset(&btlb_info, 0, sizeof btlb_info); | ||
219 | } | ||
220 | #endif | ||
221 | |||
222 | if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == | ||
223 | PDC_MODEL_NVA_UNSUPPORTED) { | ||
224 | printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n"); | ||
225 | #if 0 | ||
226 | panic("SMP kernel required to avoid non-equivalent aliasing"); | ||
227 | #endif | ||
228 | } | ||
229 | } | ||
230 | |||
231 | void disable_sr_hashing(void) | ||
232 | { | ||
233 | int srhash_type; | ||
234 | |||
235 | switch (boot_cpu_data.cpu_type) { | ||
236 | case pcx: /* We shouldn't get this far. setup.c should prevent it. */ | ||
237 | BUG(); | ||
238 | return; | ||
239 | |||
240 | case pcxs: | ||
241 | case pcxt: | ||
242 | case pcxt_: | ||
243 | srhash_type = SRHASH_PCXST; | ||
244 | break; | ||
245 | |||
246 | case pcxl: | ||
247 | srhash_type = SRHASH_PCXL; | ||
248 | break; | ||
249 | |||
250 | case pcxl2: /* pcxl2 doesn't support space register hashing */ | ||
251 | return; | ||
252 | |||
253 | default: /* Currently all PA2.0 machines use the same ins. sequence */ | ||
254 | srhash_type = SRHASH_PA20; | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | disable_sr_hashing_asm(srhash_type); | ||
259 | } | ||
260 | |||
261 | void flush_dcache_page(struct page *page) | ||
262 | { | ||
263 | struct address_space *mapping = page_mapping(page); | ||
264 | struct vm_area_struct *mpnt; | ||
265 | struct prio_tree_iter iter; | ||
266 | unsigned long offset; | ||
267 | unsigned long addr; | ||
268 | pgoff_t pgoff; | ||
269 | pte_t *pte; | ||
270 | unsigned long pfn = page_to_pfn(page); | ||
271 | |||
272 | |||
273 | if (mapping && !mapping_mapped(mapping)) { | ||
274 | set_bit(PG_dcache_dirty, &page->flags); | ||
275 | return; | ||
276 | } | ||
277 | |||
278 | flush_kernel_dcache_page(page_address(page)); | ||
279 | |||
280 | if (!mapping) | ||
281 | return; | ||
282 | |||
283 | pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | ||
284 | |||
285 | /* We have carefully arranged in arch_get_unmapped_area() that | ||
286 | * *any* mappings of a file are always congruently mapped (whether | ||
287 | * declared as MAP_PRIVATE or MAP_SHARED), so we only need | ||
288 | * to flush one address here for them all to become coherent */ | ||
289 | |||
290 | flush_dcache_mmap_lock(mapping); | ||
291 | vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) { | ||
292 | offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; | ||
293 | addr = mpnt->vm_start + offset; | ||
294 | |||
295 | /* Flush instructions produce non access tlb misses. | ||
296 | * On PA, we nullify these instructions rather than | ||
297 | * taking a page fault if the pte doesn't exist. | ||
298 | * This is just for speed. If the page translation | ||
299 | * isn't there, there's no point exciting the | ||
300 | * nadtlb handler into a nullification frenzy */ | ||
301 | |||
302 | |||
303 | if(!(pte = translation_exists(mpnt, addr))) | ||
304 | continue; | ||
305 | |||
306 | /* make sure we really have this page: the private | ||
307 | * mappings may cover this area but have COW'd this | ||
308 | * particular page */ | ||
309 | if(pte_pfn(*pte) != pfn) | ||
310 | continue; | ||
311 | |||
312 | __flush_cache_page(mpnt, addr); | ||
313 | |||
314 | break; | ||
315 | } | ||
316 | flush_dcache_mmap_unlock(mapping); | ||
317 | } | ||
318 | EXPORT_SYMBOL(flush_dcache_page); | ||
319 | |||
320 | /* Defined in arch/parisc/kernel/pacache.S */ | ||
321 | EXPORT_SYMBOL(flush_kernel_dcache_range_asm); | ||
322 | EXPORT_SYMBOL(flush_kernel_dcache_page); | ||
323 | EXPORT_SYMBOL(flush_data_cache_local); | ||
324 | EXPORT_SYMBOL(flush_kernel_icache_range_asm); | ||
325 | |||
326 | void clear_user_page_asm(void *page, unsigned long vaddr) | ||
327 | { | ||
328 | /* This function is implemented in assembly in pacache.S */ | ||
329 | extern void __clear_user_page_asm(void *page, unsigned long vaddr); | ||
330 | |||
331 | purge_tlb_start(); | ||
332 | __clear_user_page_asm(page, vaddr); | ||
333 | purge_tlb_end(); | ||
334 | } | ||
335 | |||
336 | #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ | ||
337 | int parisc_cache_flush_threshold = FLUSH_THRESHOLD; | ||
338 | |||
339 | void parisc_setup_cache_timing(void) | ||
340 | { | ||
341 | unsigned long rangetime, alltime; | ||
342 | extern char _text; /* start of kernel code, defined by linker */ | ||
343 | extern char _end; /* end of BSS, defined by linker */ | ||
344 | unsigned long size; | ||
345 | |||
346 | alltime = mfctl(16); | ||
347 | flush_data_cache(); | ||
348 | alltime = mfctl(16) - alltime; | ||
349 | |||
350 | size = (unsigned long)(&_end - _text); | ||
351 | rangetime = mfctl(16); | ||
352 | flush_kernel_dcache_range((unsigned long)&_text, size); | ||
353 | rangetime = mfctl(16) - rangetime; | ||
354 | |||
355 | printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n", | ||
356 | alltime, size, rangetime); | ||
357 | |||
358 | /* Racy, but if we see an intermediate value, it's ok too... */ | ||
359 | parisc_cache_flush_threshold = size * alltime / rangetime; | ||
360 | |||
361 | parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1); | ||
362 | if (!parisc_cache_flush_threshold) | ||
363 | parisc_cache_flush_threshold = FLUSH_THRESHOLD; | ||
364 | |||
365 | printk("Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); | ||
366 | } | ||
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c new file mode 100644 index 000000000000..ebf186656afb --- /dev/null +++ b/arch/parisc/kernel/drivers.c | |||
@@ -0,0 +1,765 @@ | |||
1 | /* | ||
2 | * drivers.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Copyright (c) 1999 The Puffin Group | ||
10 | * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard | ||
11 | * Copyright (c) 2001 Helge Deller <deller@gmx.de> | ||
12 | * Copyright (c) 2001,2002 Ryan Bradetich | ||
13 | * Copyright (c) 2004-2005 Thibaut VARENE <varenet@parisc-linux.org> | ||
14 | * | ||
15 | * The file handles registering devices and drivers, then matching them. | ||
16 | * It's the closest we get to a dating agency. | ||
17 | * | ||
18 | * If you're thinking about modifying this file, here are some gotchas to | ||
19 | * bear in mind: | ||
20 | * - 715/Mirage device paths have a dummy device between Lasi and its children | ||
21 | * - The EISA adapter may show up as a sibling or child of Wax | ||
22 | * - Dino has an optionally functional serial port. If firmware enables it, | ||
23 | * it shows up as a child of Dino. If firmware disables it, the buswalk | ||
24 | * finds it and it shows up as a child of Cujo | ||
25 | * - Dino has both parisc and pci devices as children | ||
26 | * - parisc devices are discovered in a random order, including children | ||
27 | * before parents in some cases. | ||
28 | */ | ||
29 | |||
30 | #include <linux/slab.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/spinlock.h> | ||
35 | #include <linux/string.h> | ||
36 | #include <asm/hardware.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <asm/pdc.h> | ||
39 | #include <asm/parisc-device.h> | ||
40 | |||
41 | /* See comments in include/asm-parisc/pci.h */ | ||
42 | struct hppa_dma_ops *hppa_dma_ops; | ||
43 | EXPORT_SYMBOL(hppa_dma_ops); | ||
44 | |||
45 | static struct device root = { | ||
46 | .bus_id = "parisc", | ||
47 | }; | ||
48 | |||
49 | #define for_each_padev(padev) \ | ||
50 | for (padev = next_dev(&root); padev != NULL; \ | ||
51 | padev = next_dev(&padev->dev)) | ||
52 | |||
53 | #define check_dev(padev) \ | ||
54 | (padev->id.hw_type != HPHW_FAULTY) ? padev : next_dev(&padev->dev) | ||
55 | |||
56 | /** | ||
57 | * next_dev - enumerates registered devices | ||
58 | * @dev: the previous device returned from next_dev | ||
59 | * | ||
60 | * next_dev does a depth-first search of the tree, returning parents | ||
61 | * before children. Returns NULL when there are no more devices. | ||
62 | */ | ||
63 | static struct parisc_device *next_dev(struct device *dev) | ||
64 | { | ||
65 | if (!list_empty(&dev->children)) { | ||
66 | dev = list_to_dev(dev->children.next); | ||
67 | return check_dev(to_parisc_device(dev)); | ||
68 | } | ||
69 | |||
70 | while (dev != &root) { | ||
71 | if (dev->node.next != &dev->parent->children) { | ||
72 | dev = list_to_dev(dev->node.next); | ||
73 | return to_parisc_device(dev); | ||
74 | } | ||
75 | dev = dev->parent; | ||
76 | } | ||
77 | |||
78 | return NULL; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * match_device - Report whether this driver can handle this device | ||
83 | * @driver: the PA-RISC driver to try | ||
84 | * @dev: the PA-RISC device to try | ||
85 | */ | ||
86 | static int match_device(struct parisc_driver *driver, struct parisc_device *dev) | ||
87 | { | ||
88 | const struct parisc_device_id *ids; | ||
89 | |||
90 | for (ids = driver->id_table; ids->sversion; ids++) { | ||
91 | if ((ids->sversion != SVERSION_ANY_ID) && | ||
92 | (ids->sversion != dev->id.sversion)) | ||
93 | continue; | ||
94 | |||
95 | if ((ids->hw_type != HWTYPE_ANY_ID) && | ||
96 | (ids->hw_type != dev->id.hw_type)) | ||
97 | continue; | ||
98 | |||
99 | if ((ids->hversion != HVERSION_ANY_ID) && | ||
100 | (ids->hversion != dev->id.hversion)) | ||
101 | continue; | ||
102 | |||
103 | return 1; | ||
104 | } | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static void claim_device(struct parisc_driver *driver, struct parisc_device *dev) | ||
109 | { | ||
110 | dev->driver = driver; | ||
111 | request_mem_region(dev->hpa, 0x1000, driver->name); | ||
112 | } | ||
113 | |||
114 | static int parisc_driver_probe(struct device *dev) | ||
115 | { | ||
116 | int rc; | ||
117 | struct parisc_device *pa_dev = to_parisc_device(dev); | ||
118 | struct parisc_driver *pa_drv = to_parisc_driver(dev->driver); | ||
119 | |||
120 | rc = pa_drv->probe(pa_dev); | ||
121 | |||
122 | if(!rc) | ||
123 | claim_device(pa_drv, pa_dev); | ||
124 | |||
125 | return rc; | ||
126 | } | ||
127 | |||
128 | static int parisc_driver_remove(struct device *dev) | ||
129 | { | ||
130 | struct parisc_device *pa_dev = to_parisc_device(dev); | ||
131 | struct parisc_driver *pa_drv = to_parisc_driver(dev->driver); | ||
132 | if (pa_drv->remove) | ||
133 | pa_drv->remove(pa_dev); | ||
134 | release_mem_region(pa_dev->hpa, 0x1000); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | |||
140 | /** | ||
141 | * register_parisc_driver - Register this driver if it can handle a device | ||
142 | * @driver: the PA-RISC driver to try | ||
143 | */ | ||
144 | int register_parisc_driver(struct parisc_driver *driver) | ||
145 | { | ||
146 | /* FIXME: we need this because apparently the sti | ||
147 | * driver can be registered twice */ | ||
148 | if(driver->drv.name) { | ||
149 | printk(KERN_WARNING | ||
150 | "BUG: skipping previously registered driver %s\n", | ||
151 | driver->name); | ||
152 | return 1; | ||
153 | } | ||
154 | |||
155 | if (!driver->probe) { | ||
156 | printk(KERN_WARNING | ||
157 | "BUG: driver %s has no probe routine\n", | ||
158 | driver->name); | ||
159 | return 1; | ||
160 | } | ||
161 | |||
162 | driver->drv.bus = &parisc_bus_type; | ||
163 | |||
164 | /* We install our own probe and remove routines */ | ||
165 | WARN_ON(driver->drv.probe != NULL); | ||
166 | WARN_ON(driver->drv.remove != NULL); | ||
167 | |||
168 | driver->drv.probe = parisc_driver_probe; | ||
169 | driver->drv.remove = parisc_driver_remove; | ||
170 | driver->drv.name = driver->name; | ||
171 | |||
172 | return driver_register(&driver->drv); | ||
173 | } | ||
174 | EXPORT_SYMBOL(register_parisc_driver); | ||
175 | |||
176 | /** | ||
177 | * count_parisc_driver - count # of devices this driver would match | ||
178 | * @driver: the PA-RISC driver to try | ||
179 | * | ||
180 | * Use by IOMMU support to "guess" the right size IOPdir. | ||
181 | * Formula is something like memsize/(num_iommu * entry_size). | ||
182 | */ | ||
183 | int count_parisc_driver(struct parisc_driver *driver) | ||
184 | { | ||
185 | struct parisc_device *device; | ||
186 | int cnt = 0; | ||
187 | |||
188 | for_each_padev(device) { | ||
189 | if (match_device(driver, device)) | ||
190 | cnt++; | ||
191 | } | ||
192 | |||
193 | return cnt; | ||
194 | } | ||
195 | |||
196 | |||
197 | |||
198 | /** | ||
199 | * unregister_parisc_driver - Unregister this driver from the list of drivers | ||
200 | * @driver: the PA-RISC driver to unregister | ||
201 | */ | ||
202 | int unregister_parisc_driver(struct parisc_driver *driver) | ||
203 | { | ||
204 | driver_unregister(&driver->drv); | ||
205 | return 0; | ||
206 | } | ||
207 | EXPORT_SYMBOL(unregister_parisc_driver); | ||
208 | |||
209 | static struct parisc_device *find_device_by_addr(unsigned long hpa) | ||
210 | { | ||
211 | struct parisc_device *dev; | ||
212 | for_each_padev(dev) { | ||
213 | if (dev->hpa == hpa) | ||
214 | return dev; | ||
215 | } | ||
216 | return NULL; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * find_pa_parent_type - Find a parent of a specific type | ||
221 | * @dev: The device to start searching from | ||
222 | * @type: The device type to search for. | ||
223 | * | ||
224 | * Walks up the device tree looking for a device of the specified type. | ||
225 | * If it finds it, it returns it. If not, it returns NULL. | ||
226 | */ | ||
227 | const struct parisc_device * | ||
228 | find_pa_parent_type(const struct parisc_device *padev, int type) | ||
229 | { | ||
230 | const struct device *dev = &padev->dev; | ||
231 | while (dev != &root) { | ||
232 | struct parisc_device *candidate = to_parisc_device(dev); | ||
233 | if (candidate->id.hw_type == type) | ||
234 | return candidate; | ||
235 | dev = dev->parent; | ||
236 | } | ||
237 | |||
238 | return NULL; | ||
239 | } | ||
240 | |||
241 | #ifdef CONFIG_PCI | ||
242 | static inline int is_pci_dev(struct device *dev) | ||
243 | { | ||
244 | return dev->bus == &pci_bus_type; | ||
245 | } | ||
246 | #else | ||
247 | static inline int is_pci_dev(struct device *dev) | ||
248 | { | ||
249 | return 0; | ||
250 | } | ||
251 | #endif | ||
252 | |||
253 | /* | ||
254 | * get_node_path fills in @path with the firmware path to the device. | ||
255 | * Note that if @node is a parisc device, we don't fill in the 'mod' field. | ||
256 | * This is because both callers pass the parent and fill in the mod | ||
257 | * themselves. If @node is a PCI device, we do fill it in, even though this | ||
258 | * is inconsistent. | ||
259 | */ | ||
260 | static void get_node_path(struct device *dev, struct hardware_path *path) | ||
261 | { | ||
262 | int i = 5; | ||
263 | memset(&path->bc, -1, 6); | ||
264 | |||
265 | if (is_pci_dev(dev)) { | ||
266 | unsigned int devfn = to_pci_dev(dev)->devfn; | ||
267 | path->mod = PCI_FUNC(devfn); | ||
268 | path->bc[i--] = PCI_SLOT(devfn); | ||
269 | dev = dev->parent; | ||
270 | } | ||
271 | |||
272 | while (dev != &root) { | ||
273 | if (is_pci_dev(dev)) { | ||
274 | unsigned int devfn = to_pci_dev(dev)->devfn; | ||
275 | path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn)<< 5); | ||
276 | } else if (dev->bus == &parisc_bus_type) { | ||
277 | path->bc[i--] = to_parisc_device(dev)->hw_path; | ||
278 | } | ||
279 | dev = dev->parent; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | static char *print_hwpath(struct hardware_path *path, char *output) | ||
284 | { | ||
285 | int i; | ||
286 | for (i = 0; i < 6; i++) { | ||
287 | if (path->bc[i] == -1) | ||
288 | continue; | ||
289 | output += sprintf(output, "%u/", (unsigned char) path->bc[i]); | ||
290 | } | ||
291 | output += sprintf(output, "%u", (unsigned char) path->mod); | ||
292 | return output; | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * print_pa_hwpath - Returns hardware path for PA devices | ||
297 | * dev: The device to return the path for | ||
298 | * output: Pointer to a previously-allocated array to place the path in. | ||
299 | * | ||
300 | * This function fills in the output array with a human-readable path | ||
301 | * to a PA device. This string is compatible with that used by PDC, and | ||
302 | * may be printed on the outside of the box. | ||
303 | */ | ||
304 | char *print_pa_hwpath(struct parisc_device *dev, char *output) | ||
305 | { | ||
306 | struct hardware_path path; | ||
307 | |||
308 | get_node_path(dev->dev.parent, &path); | ||
309 | path.mod = dev->hw_path; | ||
310 | return print_hwpath(&path, output); | ||
311 | } | ||
312 | EXPORT_SYMBOL(print_pa_hwpath); | ||
313 | |||
314 | #if defined(CONFIG_PCI) || defined(CONFIG_ISA) | ||
315 | /** | ||
316 | * get_pci_node_path - Determines the hardware path for a PCI device | ||
317 | * @pdev: The device to return the path for | ||
318 | * @path: Pointer to a previously-allocated array to place the path in. | ||
319 | * | ||
320 | * This function fills in the hardware_path structure with the route to | ||
321 | * the specified PCI device. This structure is suitable for passing to | ||
322 | * PDC calls. | ||
323 | */ | ||
324 | void get_pci_node_path(struct pci_dev *pdev, struct hardware_path *path) | ||
325 | { | ||
326 | get_node_path(&pdev->dev, path); | ||
327 | } | ||
328 | EXPORT_SYMBOL(get_pci_node_path); | ||
329 | |||
330 | /** | ||
331 | * print_pci_hwpath - Returns hardware path for PCI devices | ||
332 | * dev: The device to return the path for | ||
333 | * output: Pointer to a previously-allocated array to place the path in. | ||
334 | * | ||
335 | * This function fills in the output array with a human-readable path | ||
336 | * to a PCI device. This string is compatible with that used by PDC, and | ||
337 | * may be printed on the outside of the box. | ||
338 | */ | ||
339 | char *print_pci_hwpath(struct pci_dev *dev, char *output) | ||
340 | { | ||
341 | struct hardware_path path; | ||
342 | |||
343 | get_pci_node_path(dev, &path); | ||
344 | return print_hwpath(&path, output); | ||
345 | } | ||
346 | EXPORT_SYMBOL(print_pci_hwpath); | ||
347 | |||
348 | #endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */ | ||
349 | |||
350 | static void setup_bus_id(struct parisc_device *padev) | ||
351 | { | ||
352 | struct hardware_path path; | ||
353 | char *output = padev->dev.bus_id; | ||
354 | int i; | ||
355 | |||
356 | get_node_path(padev->dev.parent, &path); | ||
357 | |||
358 | for (i = 0; i < 6; i++) { | ||
359 | if (path.bc[i] == -1) | ||
360 | continue; | ||
361 | output += sprintf(output, "%u:", (unsigned char) path.bc[i]); | ||
362 | } | ||
363 | sprintf(output, "%u", (unsigned char) padev->hw_path); | ||
364 | } | ||
365 | |||
366 | struct parisc_device * create_tree_node(char id, struct device *parent) | ||
367 | { | ||
368 | struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL); | ||
369 | if (!dev) | ||
370 | return NULL; | ||
371 | |||
372 | memset(dev, 0, sizeof(*dev)); | ||
373 | dev->hw_path = id; | ||
374 | dev->id.hw_type = HPHW_FAULTY; | ||
375 | |||
376 | dev->dev.parent = parent; | ||
377 | setup_bus_id(dev); | ||
378 | |||
379 | dev->dev.bus = &parisc_bus_type; | ||
380 | dev->dma_mask = 0xffffffffUL; /* PARISC devices are 32-bit */ | ||
381 | |||
382 | /* make the generic dma mask a pointer to the parisc one */ | ||
383 | dev->dev.dma_mask = &dev->dma_mask; | ||
384 | dev->dev.coherent_dma_mask = dev->dma_mask; | ||
385 | device_register(&dev->dev); | ||
386 | |||
387 | return dev; | ||
388 | } | ||
389 | |||
390 | /** | ||
391 | * alloc_tree_node - returns a device entry in the iotree | ||
392 | * @parent: the parent node in the tree | ||
393 | * @id: the element of the module path for this entry | ||
394 | * | ||
395 | * Checks all the children of @parent for a matching @id. If none | ||
396 | * found, it allocates a new device and returns it. | ||
397 | */ | ||
398 | static struct parisc_device * alloc_tree_node(struct device *parent, char id) | ||
399 | { | ||
400 | struct device *dev; | ||
401 | |||
402 | list_for_each_entry(dev, &parent->children, node) { | ||
403 | struct parisc_device *padev = to_parisc_device(dev); | ||
404 | if (padev->hw_path == id) | ||
405 | return padev; | ||
406 | } | ||
407 | |||
408 | return create_tree_node(id, parent); | ||
409 | } | ||
410 | |||
411 | static struct parisc_device *create_parisc_device(struct hardware_path *modpath) | ||
412 | { | ||
413 | int i; | ||
414 | struct device *parent = &root; | ||
415 | for (i = 0; i < 6; i++) { | ||
416 | if (modpath->bc[i] == -1) | ||
417 | continue; | ||
418 | parent = &alloc_tree_node(parent, modpath->bc[i])->dev; | ||
419 | } | ||
420 | return alloc_tree_node(parent, modpath->mod); | ||
421 | } | ||
422 | |||
423 | struct parisc_device * | ||
424 | alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) | ||
425 | { | ||
426 | int status; | ||
427 | unsigned long bytecnt; | ||
428 | u8 iodc_data[32]; | ||
429 | struct parisc_device *dev; | ||
430 | const char *name; | ||
431 | |||
432 | /* Check to make sure this device has not already been added - Ryan */ | ||
433 | if (find_device_by_addr(hpa) != NULL) | ||
434 | return NULL; | ||
435 | |||
436 | status = pdc_iodc_read(&bytecnt, hpa, 0, &iodc_data, 32); | ||
437 | if (status != PDC_OK) | ||
438 | return NULL; | ||
439 | |||
440 | dev = create_parisc_device(mod_path); | ||
441 | if (dev->id.hw_type != HPHW_FAULTY) { | ||
442 | char p[64]; | ||
443 | print_pa_hwpath(dev, p); | ||
444 | printk("Two devices have hardware path %s. Please file a bug with HP.\n" | ||
445 | "In the meantime, you could try rearranging your cards.\n", p); | ||
446 | return NULL; | ||
447 | } | ||
448 | |||
449 | dev->id.hw_type = iodc_data[3] & 0x1f; | ||
450 | dev->id.hversion = (iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4); | ||
451 | dev->id.hversion_rev = iodc_data[1] & 0x0f; | ||
452 | dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) | | ||
453 | (iodc_data[5] << 8) | iodc_data[6]; | ||
454 | dev->hpa = hpa; | ||
455 | name = parisc_hardware_description(&dev->id); | ||
456 | if (name) { | ||
457 | strlcpy(dev->name, name, sizeof(dev->name)); | ||
458 | } | ||
459 | |||
460 | return dev; | ||
461 | } | ||
462 | |||
463 | static int parisc_generic_match(struct device *dev, struct device_driver *drv) | ||
464 | { | ||
465 | return match_device(to_parisc_driver(drv), to_parisc_device(dev)); | ||
466 | } | ||
467 | |||
468 | #define pa_dev_attr(name, field, format_string) \ | ||
469 | static ssize_t name##_show(struct device *dev, char *buf) \ | ||
470 | { \ | ||
471 | struct parisc_device *padev = to_parisc_device(dev); \ | ||
472 | return sprintf(buf, format_string, padev->field); \ | ||
473 | } | ||
474 | |||
475 | #define pa_dev_attr_id(field, format) pa_dev_attr(field, id.field, format) | ||
476 | |||
477 | pa_dev_attr(irq, irq, "%u\n"); | ||
478 | pa_dev_attr_id(hw_type, "0x%02x\n"); | ||
479 | pa_dev_attr(rev, id.hversion_rev, "0x%x\n"); | ||
480 | pa_dev_attr_id(hversion, "0x%03x\n"); | ||
481 | pa_dev_attr_id(sversion, "0x%05x\n"); | ||
482 | |||
483 | static struct device_attribute parisc_device_attrs[] = { | ||
484 | __ATTR_RO(irq), | ||
485 | __ATTR_RO(hw_type), | ||
486 | __ATTR_RO(rev), | ||
487 | __ATTR_RO(hversion), | ||
488 | __ATTR_RO(sversion), | ||
489 | __ATTR_NULL, | ||
490 | }; | ||
491 | |||
492 | struct bus_type parisc_bus_type = { | ||
493 | .name = "parisc", | ||
494 | .match = parisc_generic_match, | ||
495 | .dev_attrs = parisc_device_attrs, | ||
496 | }; | ||
497 | |||
498 | /** | ||
499 | * register_parisc_device - Locate a driver to manage this device. | ||
500 | * @dev: The parisc device. | ||
501 | * | ||
502 | * Search the driver list for a driver that is willing to manage | ||
503 | * this device. | ||
504 | */ | ||
505 | int register_parisc_device(struct parisc_device *dev) | ||
506 | { | ||
507 | if (!dev) | ||
508 | return 0; | ||
509 | |||
510 | if (dev->driver) | ||
511 | return 1; | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * match_pci_device - Matches a pci device against a given hardware path | ||
518 | * entry. | ||
519 | * @dev: the generic device (known to be contained by a pci_dev). | ||
520 | * @index: the current BC index | ||
521 | * @modpath: the hardware path. | ||
522 | * @return: true if the device matches the hardware path. | ||
523 | */ | ||
524 | static int match_pci_device(struct device *dev, int index, | ||
525 | struct hardware_path *modpath) | ||
526 | { | ||
527 | struct pci_dev *pdev = to_pci_dev(dev); | ||
528 | int id; | ||
529 | |||
530 | if (index == 5) { | ||
531 | /* we are at the end of the path, and on the actual device */ | ||
532 | unsigned int devfn = pdev->devfn; | ||
533 | return ((modpath->bc[5] == PCI_SLOT(devfn)) && | ||
534 | (modpath->mod == PCI_FUNC(devfn))); | ||
535 | } | ||
536 | |||
537 | id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5); | ||
538 | return (modpath->bc[index] == id); | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * match_parisc_device - Matches a parisc device against a given hardware | ||
543 | * path entry. | ||
544 | * @dev: the generic device (known to be contained by a parisc_device). | ||
545 | * @index: the current BC index | ||
546 | * @modpath: the hardware path. | ||
547 | * @return: true if the device matches the hardware path. | ||
548 | */ | ||
549 | static int match_parisc_device(struct device *dev, int index, | ||
550 | struct hardware_path *modpath) | ||
551 | { | ||
552 | struct parisc_device *curr = to_parisc_device(dev); | ||
553 | char id = (index == 6) ? modpath->mod : modpath->bc[index]; | ||
554 | |||
555 | return (curr->hw_path == id); | ||
556 | } | ||
557 | |||
558 | /** | ||
559 | * parse_tree_node - returns a device entry in the iotree | ||
560 | * @parent: the parent node in the tree | ||
561 | * @index: the current BC index | ||
562 | * @modpath: the hardware_path struct to match a device against | ||
563 | * @return: The corresponding device if found, NULL otherwise. | ||
564 | * | ||
565 | * Checks all the children of @parent for a matching @id. If none | ||
566 | * found, it returns NULL. | ||
567 | */ | ||
568 | static struct device * | ||
569 | parse_tree_node(struct device *parent, int index, struct hardware_path *modpath) | ||
570 | { | ||
571 | struct device *device; | ||
572 | |||
573 | list_for_each_entry(device, &parent->children, node) { | ||
574 | if (device->bus == &parisc_bus_type) { | ||
575 | if (match_parisc_device(device, index, modpath)) | ||
576 | return device; | ||
577 | } else if (is_pci_dev(device)) { | ||
578 | if (match_pci_device(device, index, modpath)) | ||
579 | return device; | ||
580 | } else if (device->bus == NULL) { | ||
581 | /* we are on a bus bridge */ | ||
582 | struct device *new = parse_tree_node(device, index, modpath); | ||
583 | if (new) | ||
584 | return new; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | return NULL; | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * hwpath_to_device - Finds the generic device corresponding to a given hardware path. | ||
593 | * @modpath: the hardware path. | ||
594 | * @return: The target device, NULL if not found. | ||
595 | */ | ||
596 | struct device *hwpath_to_device(struct hardware_path *modpath) | ||
597 | { | ||
598 | int i; | ||
599 | struct device *parent = &root; | ||
600 | for (i = 0; i < 6; i++) { | ||
601 | if (modpath->bc[i] == -1) | ||
602 | continue; | ||
603 | parent = parse_tree_node(parent, i, modpath); | ||
604 | if (!parent) | ||
605 | return NULL; | ||
606 | } | ||
607 | if (is_pci_dev(parent)) /* pci devices already parse MOD */ | ||
608 | return parent; | ||
609 | else | ||
610 | return parse_tree_node(parent, 6, modpath); | ||
611 | } | ||
612 | EXPORT_SYMBOL(hwpath_to_device); | ||
613 | |||
614 | /** | ||
615 | * device_to_hwpath - Populates the hwpath corresponding to the given device. | ||
616 | * @param dev the target device | ||
617 | * @param path pointer to a previously allocated hwpath struct to be filled in | ||
618 | */ | ||
619 | void device_to_hwpath(struct device *dev, struct hardware_path *path) | ||
620 | { | ||
621 | struct parisc_device *padev; | ||
622 | if (dev->bus == &parisc_bus_type) { | ||
623 | padev = to_parisc_device(dev); | ||
624 | get_node_path(dev->parent, path); | ||
625 | path->mod = padev->hw_path; | ||
626 | } else if (is_pci_dev(dev)) { | ||
627 | get_node_path(dev, path); | ||
628 | } | ||
629 | } | ||
630 | EXPORT_SYMBOL(device_to_hwpath); | ||
631 | |||
632 | #define BC_PORT_MASK 0x8 | ||
633 | #define BC_LOWER_PORT 0x8 | ||
634 | |||
635 | #define BUS_CONVERTER(dev) \ | ||
636 | ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT)) | ||
637 | |||
638 | #define IS_LOWER_PORT(dev) \ | ||
639 | ((gsc_readl(dev->hpa + offsetof(struct bc_module, io_status)) \ | ||
640 | & BC_PORT_MASK) == BC_LOWER_PORT) | ||
641 | |||
642 | #define MAX_NATIVE_DEVICES 64 | ||
643 | #define NATIVE_DEVICE_OFFSET 0x1000 | ||
644 | |||
645 | #define FLEX_MASK F_EXTEND(0xfffc0000) | ||
646 | #define IO_IO_LOW offsetof(struct bc_module, io_io_low) | ||
647 | #define IO_IO_HIGH offsetof(struct bc_module, io_io_high) | ||
648 | #define READ_IO_IO_LOW(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_LOW) | ||
649 | #define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_HIGH) | ||
650 | |||
651 | static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, | ||
652 | struct device *parent); | ||
653 | |||
654 | void walk_lower_bus(struct parisc_device *dev) | ||
655 | { | ||
656 | unsigned long io_io_low, io_io_high; | ||
657 | |||
658 | if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev)) | ||
659 | return; | ||
660 | |||
661 | if(dev->id.hw_type == HPHW_IOA) { | ||
662 | io_io_low = (unsigned long)(signed int)(READ_IO_IO_LOW(dev) << 16); | ||
663 | io_io_high = io_io_low + MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET; | ||
664 | } else { | ||
665 | io_io_low = (READ_IO_IO_LOW(dev) + ~FLEX_MASK) & FLEX_MASK; | ||
666 | io_io_high = (READ_IO_IO_HIGH(dev)+ ~FLEX_MASK) & FLEX_MASK; | ||
667 | } | ||
668 | |||
669 | walk_native_bus(io_io_low, io_io_high, &dev->dev); | ||
670 | } | ||
671 | |||
672 | /** | ||
673 | * walk_native_bus -- Probe a bus for devices | ||
674 | * @io_io_low: Base address of this bus. | ||
675 | * @io_io_high: Last address of this bus. | ||
676 | * @parent: The parent bus device. | ||
677 | * | ||
678 | * A native bus (eg Runway or GSC) may have up to 64 devices on it, | ||
679 | * spaced at intervals of 0x1000 bytes. PDC may not inform us of these | ||
680 | * devices, so we have to probe for them. Unfortunately, we may find | ||
681 | * devices which are not physically connected (such as extra serial & | ||
682 | * keyboard ports). This problem is not yet solved. | ||
683 | */ | ||
684 | static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, | ||
685 | struct device *parent) | ||
686 | { | ||
687 | int i, devices_found = 0; | ||
688 | unsigned long hpa = io_io_low; | ||
689 | struct hardware_path path; | ||
690 | |||
691 | get_node_path(parent, &path); | ||
692 | do { | ||
693 | for(i = 0; i < MAX_NATIVE_DEVICES; i++, hpa += NATIVE_DEVICE_OFFSET) { | ||
694 | struct parisc_device *dev; | ||
695 | |||
696 | /* Was the device already added by Firmware? */ | ||
697 | dev = find_device_by_addr(hpa); | ||
698 | if (!dev) { | ||
699 | path.mod = i; | ||
700 | dev = alloc_pa_dev(hpa, &path); | ||
701 | if (!dev) | ||
702 | continue; | ||
703 | |||
704 | register_parisc_device(dev); | ||
705 | devices_found++; | ||
706 | } | ||
707 | walk_lower_bus(dev); | ||
708 | } | ||
709 | } while(!devices_found && hpa < io_io_high); | ||
710 | } | ||
711 | |||
712 | #define CENTRAL_BUS_ADDR F_EXTEND(0xfff80000) | ||
713 | |||
714 | /** | ||
715 | * walk_central_bus - Find devices attached to the central bus | ||
716 | * | ||
717 | * PDC doesn't tell us about all devices in the system. This routine | ||
718 | * finds devices connected to the central bus. | ||
719 | */ | ||
720 | void walk_central_bus(void) | ||
721 | { | ||
722 | walk_native_bus(CENTRAL_BUS_ADDR, | ||
723 | CENTRAL_BUS_ADDR + (MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET), | ||
724 | &root); | ||
725 | } | ||
726 | |||
727 | static void print_parisc_device(struct parisc_device *dev) | ||
728 | { | ||
729 | char hw_path[64]; | ||
730 | static int count; | ||
731 | |||
732 | print_pa_hwpath(dev, hw_path); | ||
733 | printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }", | ||
734 | ++count, dev->name, dev->hpa, hw_path, dev->id.hw_type, | ||
735 | dev->id.hversion_rev, dev->id.hversion, dev->id.sversion); | ||
736 | |||
737 | if (dev->num_addrs) { | ||
738 | int k; | ||
739 | printk(", additional addresses: "); | ||
740 | for (k = 0; k < dev->num_addrs; k++) | ||
741 | printk("0x%lx ", dev->addr[k]); | ||
742 | } | ||
743 | printk("\n"); | ||
744 | } | ||
745 | |||
746 | /** | ||
747 | * init_parisc_bus - Some preparation to be done before inventory | ||
748 | */ | ||
749 | void init_parisc_bus(void) | ||
750 | { | ||
751 | bus_register(&parisc_bus_type); | ||
752 | device_register(&root); | ||
753 | get_device(&root); | ||
754 | } | ||
755 | |||
756 | /** | ||
757 | * print_parisc_devices - Print out a list of devices found in this system | ||
758 | */ | ||
759 | void print_parisc_devices(void) | ||
760 | { | ||
761 | struct parisc_device *dev; | ||
762 | for_each_padev(dev) { | ||
763 | print_parisc_device(dev); | ||
764 | } | ||
765 | } | ||
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S new file mode 100644 index 000000000000..ee58d37dbb27 --- /dev/null +++ b/arch/parisc/kernel/entry.S | |||
@@ -0,0 +1,2426 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * kernel entry points (interruptions, system call wrappers) | ||
5 | * Copyright (C) 1999,2000 Philipp Rumpf | ||
6 | * Copyright (C) 1999 SuSE GmbH Nuernberg | ||
7 | * Copyright (C) 2000 Hewlett-Packard (John Marvin) | ||
8 | * Copyright (C) 1999 Hewlett-Packard (Frank Rowand) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2, or (at your option) | ||
13 | * any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #include <linux/config.h> | ||
26 | #include <asm/offsets.h> | ||
27 | |||
28 | /* we have the following possibilities to act on an interruption: | ||
29 | * - handle in assembly and use shadowed registers only | ||
30 | * - save registers to kernel stack and handle in assembly or C */ | ||
31 | |||
32 | |||
33 | #include <asm/assembly.h> /* for LDREG/STREG defines */ | ||
34 | #include <asm/pgtable.h> | ||
35 | #include <asm/psw.h> | ||
36 | #include <asm/signal.h> | ||
37 | #include <asm/unistd.h> | ||
38 | #include <asm/thread_info.h> | ||
39 | |||
40 | #ifdef __LP64__ | ||
41 | #define CMPIB cmpib,* | ||
42 | #define CMPB cmpb,* | ||
43 | #define COND(x) *x | ||
44 | |||
45 | .level 2.0w | ||
46 | #else | ||
47 | #define CMPIB cmpib, | ||
48 | #define CMPB cmpb, | ||
49 | #define COND(x) x | ||
50 | |||
51 | .level 2.0 | ||
52 | #endif | ||
53 | |||
54 | .import pa_dbit_lock,data | ||
55 | |||
56 | /* space_to_prot macro creates a prot id from a space id */ | ||
57 | |||
58 | #if (SPACEID_SHIFT) == 0 | ||
59 | .macro space_to_prot spc prot | ||
60 | depd,z \spc,62,31,\prot | ||
61 | .endm | ||
62 | #else | ||
63 | .macro space_to_prot spc prot | ||
64 | extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot | ||
65 | .endm | ||
66 | #endif | ||
67 | |||
68 | /* Switch to virtual mapping, trashing only %r1 */ | ||
69 | .macro virt_map | ||
70 | rsm PSW_SM_Q,%r0 | ||
71 | tovirt_r1 %r29 | ||
72 | mfsp %sr7, %r1 | ||
73 | or,= %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */ | ||
74 | mtsp %r1, %sr3 | ||
75 | mtsp %r0, %sr4 | ||
76 | mtsp %r0, %sr5 | ||
77 | mtsp %r0, %sr6 | ||
78 | mtsp %r0, %sr7 | ||
79 | load32 KERNEL_PSW, %r1 | ||
80 | mtctl %r1, %cr22 | ||
81 | mtctl %r0, %cr17 /* Clear IIASQ tail */ | ||
82 | mtctl %r0, %cr17 /* Clear IIASQ head */ | ||
83 | load32 4f, %r1 | ||
84 | mtctl %r1, %cr18 /* Set IIAOQ tail */ | ||
85 | ldo 4(%r1), %r1 | ||
86 | mtctl %r1, %cr18 /* Set IIAOQ head */ | ||
87 | rfir | ||
88 | nop | ||
89 | 4: | ||
90 | .endm | ||
91 | |||
92 | /* | ||
93 | * The "get_stack" macros are responsible for determining the | ||
94 | * kernel stack value. | ||
95 | * | ||
96 | * For Faults: | ||
97 | * If sr7 == 0 | ||
98 | * Already using a kernel stack, so call the | ||
99 | * get_stack_use_r30 macro to push a pt_regs structure | ||
100 | * on the stack, and store registers there. | ||
101 | * else | ||
102 | * Need to set up a kernel stack, so call the | ||
103 | * get_stack_use_cr30 macro to set up a pointer | ||
104 | * to the pt_regs structure contained within the | ||
105 | * task pointer pointed to by cr30. Set the stack | ||
106 | * pointer to point to the end of the task structure. | ||
107 | * | ||
108 | * For Interrupts: | ||
109 | * If sr7 == 0 | ||
110 | * Already using a kernel stack, check to see if r30 | ||
111 | * is already pointing to the per processor interrupt | ||
112 | * stack. If it is, call the get_stack_use_r30 macro | ||
113 | * to push a pt_regs structure on the stack, and store | ||
114 | * registers there. Otherwise, call get_stack_use_cr31 | ||
115 | * to get a pointer to the base of the interrupt stack | ||
116 | * and push a pt_regs structure on that stack. | ||
117 | * else | ||
118 | * Need to set up a kernel stack, so call the | ||
119 | * get_stack_use_cr30 macro to set up a pointer | ||
120 | * to the pt_regs structure contained within the | ||
121 | * task pointer pointed to by cr30. Set the stack | ||
122 | * pointer to point to the end of the task structure. | ||
123 | * N.B: We don't use the interrupt stack for the | ||
124 | * first interrupt from userland, because signals/ | ||
125 | * resched's are processed when returning to userland, | ||
126 | * and we can sleep in those cases. | ||
127 | * | ||
128 | * Note that we use shadowed registers for temps until | ||
129 | * we can save %r26 and %r29. %r26 is used to preserve | ||
130 | * %r8 (a shadowed register) which temporarily contained | ||
131 | * either the fault type ("code") or the eirr. We need | ||
132 | * to use a non-shadowed register to carry the value over | ||
133 | * the rfir in virt_map. We use %r26 since this value winds | ||
134 | * up being passed as the argument to either do_cpu_irq_mask | ||
135 | * or handle_interruption. %r29 is used to hold a pointer | ||
136 | * the register save area, and once again, it needs to | ||
137 | * be a non-shadowed register so that it survives the rfir. | ||
138 | * | ||
139 | * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame. | ||
140 | */ | ||
141 | |||
142 | .macro get_stack_use_cr30 | ||
143 | |||
144 | /* we save the registers in the task struct */ | ||
145 | |||
146 | mfctl %cr30, %r1 | ||
147 | tophys %r1,%r9 | ||
148 | LDREG TI_TASK(%r9), %r1 /* thread_info -> task_struct */ | ||
149 | tophys %r1,%r9 | ||
150 | ldo TASK_REGS(%r9),%r9 | ||
151 | STREG %r30, PT_GR30(%r9) | ||
152 | STREG %r29,PT_GR29(%r9) | ||
153 | STREG %r26,PT_GR26(%r9) | ||
154 | copy %r9,%r29 | ||
155 | mfctl %cr30, %r1 | ||
156 | ldo THREAD_SZ_ALGN(%r1), %r30 | ||
157 | .endm | ||
158 | |||
159 | .macro get_stack_use_r30 | ||
160 | |||
161 | /* we put a struct pt_regs on the stack and save the registers there */ | ||
162 | |||
163 | tophys %r30,%r9 | ||
164 | STREG %r30,PT_GR30(%r9) | ||
165 | ldo PT_SZ_ALGN(%r30),%r30 | ||
166 | STREG %r29,PT_GR29(%r9) | ||
167 | STREG %r26,PT_GR26(%r9) | ||
168 | copy %r9,%r29 | ||
169 | .endm | ||
170 | |||
171 | .macro rest_stack | ||
172 | LDREG PT_GR1(%r29), %r1 | ||
173 | LDREG PT_GR30(%r29),%r30 | ||
174 | LDREG PT_GR29(%r29),%r29 | ||
175 | .endm | ||
176 | |||
177 | /* default interruption handler | ||
178 | * (calls traps.c:handle_interruption) */ | ||
179 | .macro def code | ||
180 | b intr_save | ||
181 | ldi \code, %r8 | ||
182 | .align 32 | ||
183 | .endm | ||
184 | |||
185 | /* Interrupt interruption handler | ||
186 | * (calls irq.c:do_cpu_irq_mask) */ | ||
187 | .macro extint code | ||
188 | b intr_extint | ||
189 | mfsp %sr7,%r16 | ||
190 | .align 32 | ||
191 | .endm | ||
192 | |||
193 | .import os_hpmc, code | ||
194 | |||
195 | /* HPMC handler */ | ||
196 | .macro hpmc code | ||
197 | nop /* must be a NOP, will be patched later */ | ||
198 | load32 PA(os_hpmc), %r3 | ||
199 | bv,n 0(%r3) | ||
200 | nop | ||
201 | .word 0 /* checksum (will be patched) */ | ||
202 | .word PA(os_hpmc) /* address of handler */ | ||
203 | .word 0 /* length of handler */ | ||
204 | .endm | ||
205 | |||
206 | /* | ||
207 | * Performance Note: Instructions will be moved up into | ||
208 | * this part of the code later on, once we are sure | ||
209 | * that the tlb miss handlers are close to final form. | ||
210 | */ | ||
211 | |||
212 | /* Register definitions for tlb miss handler macros */ | ||
213 | |||
214 | va = r8 /* virtual address for which the trap occured */ | ||
215 | spc = r24 /* space for which the trap occured */ | ||
216 | |||
217 | #ifndef __LP64__ | ||
218 | |||
219 | /* | ||
220 | * itlb miss interruption handler (parisc 1.1 - 32 bit) | ||
221 | */ | ||
222 | |||
223 | .macro itlb_11 code | ||
224 | |||
225 | mfctl %pcsq, spc | ||
226 | b itlb_miss_11 | ||
227 | mfctl %pcoq, va | ||
228 | |||
229 | .align 32 | ||
230 | .endm | ||
231 | #endif | ||
232 | |||
233 | /* | ||
234 | * itlb miss interruption handler (parisc 2.0) | ||
235 | */ | ||
236 | |||
237 | .macro itlb_20 code | ||
238 | mfctl %pcsq, spc | ||
239 | #ifdef __LP64__ | ||
240 | b itlb_miss_20w | ||
241 | #else | ||
242 | b itlb_miss_20 | ||
243 | #endif | ||
244 | mfctl %pcoq, va | ||
245 | |||
246 | .align 32 | ||
247 | .endm | ||
248 | |||
249 | #ifndef __LP64__ | ||
250 | /* | ||
251 | * naitlb miss interruption handler (parisc 1.1 - 32 bit) | ||
252 | * | ||
253 | * Note: naitlb misses will be treated | ||
254 | * as an ordinary itlb miss for now. | ||
255 | * However, note that naitlb misses | ||
256 | * have the faulting address in the | ||
257 | * IOR/ISR. | ||
258 | */ | ||
259 | |||
260 | .macro naitlb_11 code | ||
261 | |||
262 | mfctl %isr,spc | ||
263 | b itlb_miss_11 | ||
264 | mfctl %ior,va | ||
265 | /* FIXME: If user causes a naitlb miss, the priv level may not be in | ||
266 | * lower bits of va, where the itlb miss handler is expecting them | ||
267 | */ | ||
268 | |||
269 | .align 32 | ||
270 | .endm | ||
271 | #endif | ||
272 | |||
273 | /* | ||
274 | * naitlb miss interruption handler (parisc 2.0) | ||
275 | * | ||
276 | * Note: naitlb misses will be treated | ||
277 | * as an ordinary itlb miss for now. | ||
278 | * However, note that naitlb misses | ||
279 | * have the faulting address in the | ||
280 | * IOR/ISR. | ||
281 | */ | ||
282 | |||
283 | .macro naitlb_20 code | ||
284 | |||
285 | mfctl %isr,spc | ||
286 | #ifdef __LP64__ | ||
287 | b itlb_miss_20w | ||
288 | #else | ||
289 | b itlb_miss_20 | ||
290 | #endif | ||
291 | mfctl %ior,va | ||
292 | /* FIXME: If user causes a naitlb miss, the priv level may not be in | ||
293 | * lower bits of va, where the itlb miss handler is expecting them | ||
294 | */ | ||
295 | |||
296 | .align 32 | ||
297 | .endm | ||
298 | |||
299 | #ifndef __LP64__ | ||
300 | /* | ||
301 | * dtlb miss interruption handler (parisc 1.1 - 32 bit) | ||
302 | */ | ||
303 | |||
304 | .macro dtlb_11 code | ||
305 | |||
306 | mfctl %isr, spc | ||
307 | b dtlb_miss_11 | ||
308 | mfctl %ior, va | ||
309 | |||
310 | .align 32 | ||
311 | .endm | ||
312 | #endif | ||
313 | |||
314 | /* | ||
315 | * dtlb miss interruption handler (parisc 2.0) | ||
316 | */ | ||
317 | |||
318 | .macro dtlb_20 code | ||
319 | |||
320 | mfctl %isr, spc | ||
321 | #ifdef __LP64__ | ||
322 | b dtlb_miss_20w | ||
323 | #else | ||
324 | b dtlb_miss_20 | ||
325 | #endif | ||
326 | mfctl %ior, va | ||
327 | |||
328 | .align 32 | ||
329 | .endm | ||
330 | |||
331 | #ifndef __LP64__ | ||
332 | /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */ | ||
333 | |||
334 | .macro nadtlb_11 code | ||
335 | |||
336 | mfctl %isr,spc | ||
337 | b nadtlb_miss_11 | ||
338 | mfctl %ior,va | ||
339 | |||
340 | .align 32 | ||
341 | .endm | ||
342 | #endif | ||
343 | |||
344 | /* nadtlb miss interruption handler (parisc 2.0) */ | ||
345 | |||
346 | .macro nadtlb_20 code | ||
347 | |||
348 | mfctl %isr,spc | ||
349 | #ifdef __LP64__ | ||
350 | b nadtlb_miss_20w | ||
351 | #else | ||
352 | b nadtlb_miss_20 | ||
353 | #endif | ||
354 | mfctl %ior,va | ||
355 | |||
356 | .align 32 | ||
357 | .endm | ||
358 | |||
359 | #ifndef __LP64__ | ||
360 | /* | ||
361 | * dirty bit trap interruption handler (parisc 1.1 - 32 bit) | ||
362 | */ | ||
363 | |||
364 | .macro dbit_11 code | ||
365 | |||
366 | mfctl %isr,spc | ||
367 | b dbit_trap_11 | ||
368 | mfctl %ior,va | ||
369 | |||
370 | .align 32 | ||
371 | .endm | ||
372 | #endif | ||
373 | |||
374 | /* | ||
375 | * dirty bit trap interruption handler (parisc 2.0) | ||
376 | */ | ||
377 | |||
378 | .macro dbit_20 code | ||
379 | |||
380 | mfctl %isr,spc | ||
381 | #ifdef __LP64__ | ||
382 | b dbit_trap_20w | ||
383 | #else | ||
384 | b dbit_trap_20 | ||
385 | #endif | ||
386 | mfctl %ior,va | ||
387 | |||
388 | .align 32 | ||
389 | .endm | ||
390 | |||
391 | /* The following are simple 32 vs 64 bit instruction | ||
392 | * abstractions for the macros */ | ||
393 | .macro EXTR reg1,start,length,reg2 | ||
394 | #ifdef __LP64__ | ||
395 | extrd,u \reg1,32+\start,\length,\reg2 | ||
396 | #else | ||
397 | extrw,u \reg1,\start,\length,\reg2 | ||
398 | #endif | ||
399 | .endm | ||
400 | |||
401 | .macro DEP reg1,start,length,reg2 | ||
402 | #ifdef __LP64__ | ||
403 | depd \reg1,32+\start,\length,\reg2 | ||
404 | #else | ||
405 | depw \reg1,\start,\length,\reg2 | ||
406 | #endif | ||
407 | .endm | ||
408 | |||
409 | .macro DEPI val,start,length,reg | ||
410 | #ifdef __LP64__ | ||
411 | depdi \val,32+\start,\length,\reg | ||
412 | #else | ||
413 | depwi \val,\start,\length,\reg | ||
414 | #endif | ||
415 | .endm | ||
416 | |||
417 | /* In LP64, the space contains part of the upper 32 bits of the | ||
418 | * fault. We have to extract this and place it in the va, | ||
419 | * zeroing the corresponding bits in the space register */ | ||
420 | .macro space_adjust spc,va,tmp | ||
421 | #ifdef __LP64__ | ||
422 | extrd,u \spc,63,SPACEID_SHIFT,\tmp | ||
423 | depd %r0,63,SPACEID_SHIFT,\spc | ||
424 | depd \tmp,31,SPACEID_SHIFT,\va | ||
425 | #endif | ||
426 | .endm | ||
427 | |||
428 | .import swapper_pg_dir,code | ||
429 | |||
430 | /* Get the pgd. For faults on space zero (kernel space), this | ||
431 | * is simply swapper_pg_dir. For user space faults, the | ||
432 | * pgd is stored in %cr25 */ | ||
433 | .macro get_pgd spc,reg | ||
434 | ldil L%PA(swapper_pg_dir),\reg | ||
435 | ldo R%PA(swapper_pg_dir)(\reg),\reg | ||
436 | or,COND(=) %r0,\spc,%r0 | ||
437 | mfctl %cr25,\reg | ||
438 | .endm | ||
439 | |||
440 | /* | ||
441 | space_check(spc,tmp,fault) | ||
442 | |||
443 | spc - The space we saw the fault with. | ||
444 | tmp - The place to store the current space. | ||
445 | fault - Function to call on failure. | ||
446 | |||
447 | Only allow faults on different spaces from the | ||
448 | currently active one if we're the kernel | ||
449 | |||
450 | */ | ||
451 | .macro space_check spc,tmp,fault | ||
452 | mfsp %sr7,\tmp | ||
453 | or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page | ||
454 | * as kernel, so defeat the space | ||
455 | * check if it is */ | ||
456 | copy \spc,\tmp | ||
457 | or,COND(=) %r0,\tmp,%r0 /* nullify if executing as kernel */ | ||
458 | cmpb,COND(<>),n \tmp,\spc,\fault | ||
459 | .endm | ||
460 | |||
461 | /* Look up a PTE in a 2-Level scheme (faulting at each | ||
462 | * level if the entry isn't present | ||
463 | * | ||
464 | * NOTE: we use ldw even for LP64, since the short pointers | ||
465 | * can address up to 1TB | ||
466 | */ | ||
467 | .macro L2_ptep pmd,pte,index,va,fault | ||
468 | #if PT_NLEVELS == 3 | ||
469 | EXTR \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index | ||
470 | #else | ||
471 | EXTR \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index | ||
472 | #endif | ||
473 | DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */ | ||
474 | copy %r0,\pte | ||
475 | ldw,s \index(\pmd),\pmd | ||
476 | bb,>=,n \pmd,_PxD_PRESENT_BIT,\fault | ||
477 | DEP %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */ | ||
478 | copy \pmd,%r9 | ||
479 | #ifdef __LP64__ | ||
480 | shld %r9,PxD_VALUE_SHIFT,\pmd | ||
481 | #else | ||
482 | shlw %r9,PxD_VALUE_SHIFT,\pmd | ||
483 | #endif | ||
484 | EXTR \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index | ||
485 | DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */ | ||
486 | shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd | ||
487 | LDREG %r0(\pmd),\pte /* pmd is now pte */ | ||
488 | bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault | ||
489 | .endm | ||
490 | |||
491 | /* Look up PTE in a 3-Level scheme. | ||
492 | * | ||
493 | * Here we implement a Hybrid L2/L3 scheme: we allocate the | ||
494 | * first pmd adjacent to the pgd. This means that we can | ||
495 | * subtract a constant offset to get to it. The pmd and pgd | ||
496 | * sizes are arranged so that a single pmd covers 4GB (giving | ||
497 | * a full LP64 process access to 8TB) so our lookups are | ||
498 | * effectively L2 for the first 4GB of the kernel (i.e. for | ||
499 | * all ILP32 processes and all the kernel for machines with | ||
500 | * under 4GB of memory) */ | ||
501 | .macro L3_ptep pgd,pte,index,va,fault | ||
502 | extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index | ||
503 | copy %r0,\pte | ||
504 | extrd,u,*= \va,31,32,%r0 | ||
505 | ldw,s \index(\pgd),\pgd | ||
506 | extrd,u,*= \va,31,32,%r0 | ||
507 | bb,>=,n \pgd,_PxD_PRESENT_BIT,\fault | ||
508 | extrd,u,*= \va,31,32,%r0 | ||
509 | shld \pgd,PxD_VALUE_SHIFT,\index | ||
510 | extrd,u,*= \va,31,32,%r0 | ||
511 | copy \index,\pgd | ||
512 | extrd,u,*<> \va,31,32,%r0 | ||
513 | ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd | ||
514 | L2_ptep \pgd,\pte,\index,\va,\fault | ||
515 | .endm | ||
516 | |||
517 | /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and | ||
518 | * don't needlessly dirty the cache line if it was already set */ | ||
519 | .macro update_ptep ptep,pte,tmp,tmp1 | ||
520 | ldi _PAGE_ACCESSED,\tmp1 | ||
521 | or \tmp1,\pte,\tmp | ||
522 | and,COND(<>) \tmp1,\pte,%r0 | ||
523 | STREG \tmp,0(\ptep) | ||
524 | .endm | ||
525 | |||
526 | /* Set the dirty bit (and accessed bit). No need to be | ||
527 | * clever, this is only used from the dirty fault */ | ||
528 | .macro update_dirty ptep,pte,tmp | ||
529 | ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp | ||
530 | or \tmp,\pte,\pte | ||
531 | STREG \pte,0(\ptep) | ||
532 | .endm | ||
533 | |||
534 | /* Convert the pte and prot to tlb insertion values. How | ||
535 | * this happens is quite subtle, read below */ | ||
536 | .macro make_insert_tlb spc,pte,prot | ||
537 | space_to_prot \spc \prot /* create prot id from space */ | ||
538 | /* The following is the real subtlety. This is depositing | ||
539 | * T <-> _PAGE_REFTRAP | ||
540 | * D <-> _PAGE_DIRTY | ||
541 | * B <-> _PAGE_DMB (memory break) | ||
542 | * | ||
543 | * Then incredible subtlety: The access rights are | ||
544 | * _PAGE_GATEWAY _PAGE_EXEC _PAGE_READ | ||
545 | * See 3-14 of the parisc 2.0 manual | ||
546 | * | ||
547 | * Finally, _PAGE_READ goes in the top bit of PL1 (so we | ||
548 | * trigger an access rights trap in user space if the user | ||
549 | * tries to read an unreadable page */ | ||
550 | depd \pte,8,7,\prot | ||
551 | |||
552 | /* PAGE_USER indicates the page can be read with user privileges, | ||
553 | * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1 | ||
554 | * contains _PAGE_READ */ | ||
555 | extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0 | ||
556 | depdi 7,11,3,\prot | ||
557 | /* If we're a gateway page, drop PL2 back to zero for promotion | ||
558 | * to kernel privilege (so we can execute the page as kernel). | ||
559 | * Any privilege promotion page always denys read and write */ | ||
560 | extrd,u,*= \pte,_PAGE_GATEWAY_BIT+32,1,%r0 | ||
561 | depd %r0,11,2,\prot /* If Gateway, Set PL2 to 0 */ | ||
562 | |||
563 | /* Get rid of prot bits and convert to page addr for iitlbt */ | ||
564 | |||
565 | depd %r0,63,PAGE_SHIFT,\pte | ||
566 | extrd,u \pte,56,32,\pte | ||
567 | .endm | ||
568 | |||
569 | /* Identical macro to make_insert_tlb above, except it | ||
570 | * makes the tlb entry for the differently formatted pa11 | ||
571 | * insertion instructions */ | ||
572 | .macro make_insert_tlb_11 spc,pte,prot | ||
573 | zdep \spc,30,15,\prot | ||
574 | dep \pte,8,7,\prot | ||
575 | extru,= \pte,_PAGE_NO_CACHE_BIT,1,%r0 | ||
576 | depi 1,12,1,\prot | ||
577 | extru,= \pte,_PAGE_USER_BIT,1,%r0 | ||
578 | depi 7,11,3,\prot /* Set for user space (1 rsvd for read) */ | ||
579 | extru,= \pte,_PAGE_GATEWAY_BIT,1,%r0 | ||
580 | depi 0,11,2,\prot /* If Gateway, Set PL2 to 0 */ | ||
581 | |||
582 | /* Get rid of prot bits and convert to page addr for iitlba */ | ||
583 | |||
584 | depi 0,31,12,\pte | ||
585 | extru \pte,24,25,\pte | ||
586 | |||
587 | .endm | ||
588 | |||
589 | /* This is for ILP32 PA2.0 only. The TLB insertion needs | ||
590 | * to extend into I/O space if the address is 0xfXXXXXXX | ||
591 | * so we extend the f's into the top word of the pte in | ||
592 | * this case */ | ||
593 | .macro f_extend pte,tmp | ||
594 | extrd,s \pte,42,4,\tmp | ||
595 | addi,<> 1,\tmp,%r0 | ||
596 | extrd,s \pte,63,25,\pte | ||
597 | .endm | ||
598 | |||
599 | /* The alias region is an 8MB aligned 16MB to do clear and | ||
600 | * copy user pages at addresses congruent with the user | ||
601 | * virtual address. | ||
602 | * | ||
603 | * To use the alias page, you set %r26 up with the to TLB | ||
604 | * entry (identifying the physical page) and %r23 up with | ||
605 | * the from tlb entry (or nothing if only a to entry---for | ||
606 | * clear_user_page_asm) */ | ||
607 | .macro do_alias spc,tmp,tmp1,va,pte,prot,fault | ||
608 | cmpib,COND(<>),n 0,\spc,\fault | ||
609 | ldil L%(TMPALIAS_MAP_START),\tmp | ||
610 | #if defined(__LP64__) && (TMPALIAS_MAP_START >= 0x80000000) | ||
611 | /* on LP64, ldi will sign extend into the upper 32 bits, | ||
612 | * which is behaviour we don't want */ | ||
613 | depdi 0,31,32,\tmp | ||
614 | #endif | ||
615 | copy \va,\tmp1 | ||
616 | DEPI 0,31,23,\tmp1 | ||
617 | cmpb,COND(<>),n \tmp,\tmp1,\fault | ||
618 | ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot | ||
619 | depd,z \prot,8,7,\prot | ||
620 | /* | ||
621 | * OK, it is in the temp alias region, check whether "from" or "to". | ||
622 | * Check "subtle" note in pacache.S re: r23/r26. | ||
623 | */ | ||
624 | #ifdef __LP64__ | ||
625 | extrd,u,*= \va,41,1,%r0 | ||
626 | #else | ||
627 | extrw,u,= \va,9,1,%r0 | ||
628 | #endif | ||
629 | or,COND(tr) %r23,%r0,\pte | ||
630 | or %r26,%r0,\pte | ||
631 | .endm | ||
632 | |||
633 | |||
634 | /* | ||
635 | * Align fault_vector_20 on 4K boundary so that both | ||
636 | * fault_vector_11 and fault_vector_20 are on the | ||
637 | * same page. This is only necessary as long as we | ||
638 | * write protect the kernel text, which we may stop | ||
639 | * doing once we use large page translations to cover | ||
640 | * the static part of the kernel address space. | ||
641 | */ | ||
642 | |||
643 | .export fault_vector_20 | ||
644 | |||
645 | .text | ||
646 | |||
647 | .align 4096 | ||
648 | |||
649 | fault_vector_20: | ||
650 | /* First vector is invalid (0) */ | ||
651 | .ascii "cows can fly" | ||
652 | .byte 0 | ||
653 | .align 32 | ||
654 | |||
655 | hpmc 1 | ||
656 | def 2 | ||
657 | def 3 | ||
658 | extint 4 | ||
659 | def 5 | ||
660 | itlb_20 6 | ||
661 | def 7 | ||
662 | def 8 | ||
663 | def 9 | ||
664 | def 10 | ||
665 | def 11 | ||
666 | def 12 | ||
667 | def 13 | ||
668 | def 14 | ||
669 | dtlb_20 15 | ||
670 | #if 0 | ||
671 | naitlb_20 16 | ||
672 | #else | ||
673 | def 16 | ||
674 | #endif | ||
675 | nadtlb_20 17 | ||
676 | def 18 | ||
677 | def 19 | ||
678 | dbit_20 20 | ||
679 | def 21 | ||
680 | def 22 | ||
681 | def 23 | ||
682 | def 24 | ||
683 | def 25 | ||
684 | def 26 | ||
685 | def 27 | ||
686 | def 28 | ||
687 | def 29 | ||
688 | def 30 | ||
689 | def 31 | ||
690 | |||
691 | #ifndef __LP64__ | ||
692 | |||
693 | .export fault_vector_11 | ||
694 | |||
695 | .align 2048 | ||
696 | |||
697 | fault_vector_11: | ||
698 | /* First vector is invalid (0) */ | ||
699 | .ascii "cows can fly" | ||
700 | .byte 0 | ||
701 | .align 32 | ||
702 | |||
703 | hpmc 1 | ||
704 | def 2 | ||
705 | def 3 | ||
706 | extint 4 | ||
707 | def 5 | ||
708 | itlb_11 6 | ||
709 | def 7 | ||
710 | def 8 | ||
711 | def 9 | ||
712 | def 10 | ||
713 | def 11 | ||
714 | def 12 | ||
715 | def 13 | ||
716 | def 14 | ||
717 | dtlb_11 15 | ||
718 | #if 0 | ||
719 | naitlb_11 16 | ||
720 | #else | ||
721 | def 16 | ||
722 | #endif | ||
723 | nadtlb_11 17 | ||
724 | def 18 | ||
725 | def 19 | ||
726 | dbit_11 20 | ||
727 | def 21 | ||
728 | def 22 | ||
729 | def 23 | ||
730 | def 24 | ||
731 | def 25 | ||
732 | def 26 | ||
733 | def 27 | ||
734 | def 28 | ||
735 | def 29 | ||
736 | def 30 | ||
737 | def 31 | ||
738 | |||
739 | #endif | ||
740 | |||
741 | .import handle_interruption,code | ||
742 | .import do_cpu_irq_mask,code | ||
743 | |||
744 | /* | ||
745 | * r26 = function to be called | ||
746 | * r25 = argument to pass in | ||
747 | * r24 = flags for do_fork() | ||
748 | * | ||
749 | * Kernel threads don't ever return, so they don't need | ||
750 | * a true register context. We just save away the arguments | ||
751 | * for copy_thread/ret_ to properly set up the child. | ||
752 | */ | ||
753 | |||
754 | #define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */ | ||
755 | #define CLONE_UNTRACED 0x00800000 | ||
756 | |||
757 | .export __kernel_thread, code | ||
758 | .import do_fork | ||
759 | __kernel_thread: | ||
760 | STREG %r2, -RP_OFFSET(%r30) | ||
761 | |||
762 | copy %r30, %r1 | ||
763 | ldo PT_SZ_ALGN(%r30),%r30 | ||
764 | #ifdef __LP64__ | ||
765 | /* Yo, function pointers in wide mode are little structs... -PB */ | ||
766 | ldd 24(%r26), %r2 | ||
767 | STREG %r2, PT_GR27(%r1) /* Store childs %dp */ | ||
768 | ldd 16(%r26), %r26 | ||
769 | |||
770 | STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */ | ||
771 | copy %r0, %r22 /* user_tid */ | ||
772 | #endif | ||
773 | STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ | ||
774 | STREG %r25, PT_GR25(%r1) | ||
775 | ldil L%CLONE_UNTRACED, %r26 | ||
776 | ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */ | ||
777 | or %r26, %r24, %r26 /* will have kernel mappings. */ | ||
778 | ldi 1, %r25 /* stack_start, signals kernel thread */ | ||
779 | stw %r0, -52(%r30) /* user_tid */ | ||
780 | #ifdef __LP64__ | ||
781 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
782 | #endif | ||
783 | BL do_fork, %r2 | ||
784 | copy %r1, %r24 /* pt_regs */ | ||
785 | |||
786 | /* Parent Returns here */ | ||
787 | |||
788 | LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2 | ||
789 | ldo -PT_SZ_ALGN(%r30), %r30 | ||
790 | bv %r0(%r2) | ||
791 | nop | ||
792 | |||
793 | /* | ||
794 | * Child Returns here | ||
795 | * | ||
796 | * copy_thread moved args from temp save area set up above | ||
797 | * into task save area. | ||
798 | */ | ||
799 | |||
800 | .export ret_from_kernel_thread | ||
801 | ret_from_kernel_thread: | ||
802 | |||
803 | /* Call schedule_tail first though */ | ||
804 | BL schedule_tail, %r2 | ||
805 | nop | ||
806 | |||
807 | LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 | ||
808 | LDREG TASK_PT_GR25(%r1), %r26 | ||
809 | #ifdef __LP64__ | ||
810 | LDREG TASK_PT_GR27(%r1), %r27 | ||
811 | LDREG TASK_PT_GR22(%r1), %r22 | ||
812 | #endif | ||
813 | LDREG TASK_PT_GR26(%r1), %r1 | ||
814 | ble 0(%sr7, %r1) | ||
815 | copy %r31, %r2 | ||
816 | |||
817 | #ifdef __LP64__ | ||
818 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
819 | loadgp /* Thread could have been in a module */ | ||
820 | #endif | ||
821 | b sys_exit | ||
822 | ldi 0, %r26 | ||
823 | |||
824 | .import sys_execve, code | ||
825 | .export __execve, code | ||
826 | __execve: | ||
827 | copy %r2, %r15 | ||
828 | copy %r30, %r16 | ||
829 | ldo PT_SZ_ALGN(%r30), %r30 | ||
830 | STREG %r26, PT_GR26(%r16) | ||
831 | STREG %r25, PT_GR25(%r16) | ||
832 | STREG %r24, PT_GR24(%r16) | ||
833 | #ifdef __LP64__ | ||
834 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
835 | #endif | ||
836 | BL sys_execve, %r2 | ||
837 | copy %r16, %r26 | ||
838 | |||
839 | cmpib,=,n 0,%r28,intr_return /* forward */ | ||
840 | |||
841 | /* yes, this will trap and die. */ | ||
842 | copy %r15, %r2 | ||
843 | copy %r16, %r30 | ||
844 | bv %r0(%r2) | ||
845 | nop | ||
846 | |||
847 | .align 4 | ||
848 | |||
849 | /* | ||
850 | * struct task_struct *_switch_to(struct task_struct *prev, | ||
851 | * struct task_struct *next) | ||
852 | * | ||
853 | * switch kernel stacks and return prev */ | ||
854 | .export _switch_to, code | ||
855 | _switch_to: | ||
856 | STREG %r2, -RP_OFFSET(%r30) | ||
857 | |||
858 | callee_save | ||
859 | |||
860 | load32 _switch_to_ret, %r2 | ||
861 | |||
862 | STREG %r2, TASK_PT_KPC(%r26) | ||
863 | LDREG TASK_PT_KPC(%r25), %r2 | ||
864 | |||
865 | STREG %r30, TASK_PT_KSP(%r26) | ||
866 | LDREG TASK_PT_KSP(%r25), %r30 | ||
867 | LDREG TASK_THREAD_INFO(%r25), %r25 | ||
868 | bv %r0(%r2) | ||
869 | mtctl %r25,%cr30 | ||
870 | |||
871 | _switch_to_ret: | ||
872 | mtctl %r0, %cr0 /* Needed for single stepping */ | ||
873 | callee_rest | ||
874 | |||
875 | LDREG -RP_OFFSET(%r30), %r2 | ||
876 | bv %r0(%r2) | ||
877 | copy %r26, %r28 | ||
878 | |||
879 | /* | ||
880 | * Common rfi return path for interruptions, kernel execve, and | ||
881 | * sys_rt_sigreturn (sometimes). The sys_rt_sigreturn syscall will | ||
882 | * return via this path if the signal was received when the process | ||
883 | * was running; if the process was blocked on a syscall then the | ||
884 | * normal syscall_exit path is used. All syscalls for traced | ||
885 | * proceses exit via intr_restore. | ||
886 | * | ||
887 | * XXX If any syscalls that change a processes space id ever exit | ||
888 | * this way, then we will need to copy %sr3 in to PT_SR[3..7], and | ||
889 | * adjust IASQ[0..1]. | ||
890 | * | ||
891 | * Note that the following code uses a "relied upon translation". | ||
892 | * See the parisc ACD for details. The ssm is necessary due to a | ||
893 | * PCXT bug. | ||
894 | */ | ||
895 | |||
896 | .align 4096 | ||
897 | |||
898 | .export syscall_exit_rfi | ||
899 | syscall_exit_rfi: | ||
900 | mfctl %cr30,%r16 | ||
901 | LDREG TI_TASK(%r16), %r16 /* thread_info -> task_struct */ | ||
902 | ldo TASK_REGS(%r16),%r16 | ||
903 | /* Force iaoq to userspace, as the user has had access to our current | ||
904 | * context via sigcontext. Also Filter the PSW for the same reason. | ||
905 | */ | ||
906 | LDREG PT_IAOQ0(%r16),%r19 | ||
907 | depi 3,31,2,%r19 | ||
908 | STREG %r19,PT_IAOQ0(%r16) | ||
909 | LDREG PT_IAOQ1(%r16),%r19 | ||
910 | depi 3,31,2,%r19 | ||
911 | STREG %r19,PT_IAOQ1(%r16) | ||
912 | LDREG PT_PSW(%r16),%r19 | ||
913 | load32 USER_PSW_MASK,%r1 | ||
914 | #ifdef __LP64__ | ||
915 | load32 USER_PSW_HI_MASK,%r20 | ||
916 | depd %r20,31,32,%r1 | ||
917 | #endif | ||
918 | and %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */ | ||
919 | load32 USER_PSW,%r1 | ||
920 | or %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */ | ||
921 | STREG %r19,PT_PSW(%r16) | ||
922 | |||
923 | /* | ||
924 | * If we aren't being traced, we never saved space registers | ||
925 | * (we don't store them in the sigcontext), so set them | ||
926 | * to "proper" values now (otherwise we'll wind up restoring | ||
927 | * whatever was last stored in the task structure, which might | ||
928 | * be inconsistent if an interrupt occured while on the gateway | ||
929 | * page) Note that we may be "trashing" values the user put in | ||
930 | * them, but we don't support the the user changing them. | ||
931 | */ | ||
932 | |||
933 | STREG %r0,PT_SR2(%r16) | ||
934 | mfsp %sr3,%r19 | ||
935 | STREG %r19,PT_SR0(%r16) | ||
936 | STREG %r19,PT_SR1(%r16) | ||
937 | STREG %r19,PT_SR3(%r16) | ||
938 | STREG %r19,PT_SR4(%r16) | ||
939 | STREG %r19,PT_SR5(%r16) | ||
940 | STREG %r19,PT_SR6(%r16) | ||
941 | STREG %r19,PT_SR7(%r16) | ||
942 | |||
943 | intr_return: | ||
944 | /* NOTE: Need to enable interrupts incase we schedule. */ | ||
945 | ssm PSW_SM_I, %r0 | ||
946 | |||
947 | /* Check for software interrupts */ | ||
948 | |||
949 | .import irq_stat,data | ||
950 | |||
951 | load32 irq_stat,%r19 | ||
952 | #ifdef CONFIG_SMP | ||
953 | mfctl %cr30,%r1 | ||
954 | ldw TI_CPU(%r1),%r1 /* get cpu # - int */ | ||
955 | /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount | ||
956 | ** irq_stat[] is defined using ____cacheline_aligned. | ||
957 | */ | ||
958 | #ifdef __LP64__ | ||
959 | shld %r1, 6, %r20 | ||
960 | #else | ||
961 | shlw %r1, 5, %r20 | ||
962 | #endif | ||
963 | add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */ | ||
964 | #endif /* CONFIG_SMP */ | ||
965 | |||
966 | LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */ | ||
967 | cmpib,<>,n 0,%r20,intr_do_softirq /* forward */ | ||
968 | |||
969 | intr_check_resched: | ||
970 | |||
971 | /* check for reschedule */ | ||
972 | mfctl %cr30,%r1 | ||
973 | LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ | ||
974 | bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */ | ||
975 | |||
976 | intr_check_sig: | ||
977 | /* As above */ | ||
978 | mfctl %cr30,%r1 | ||
979 | LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_SIGPENDING */ | ||
980 | bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */ | ||
981 | |||
982 | intr_restore: | ||
983 | copy %r16,%r29 | ||
984 | ldo PT_FR31(%r29),%r1 | ||
985 | rest_fp %r1 | ||
986 | rest_general %r29 | ||
987 | |||
988 | /* Create a "relied upon translation" PA 2.0 Arch. F-5 */ | ||
989 | ssm 0,%r0 | ||
990 | nop | ||
991 | nop | ||
992 | nop | ||
993 | nop | ||
994 | nop | ||
995 | nop | ||
996 | nop | ||
997 | tophys_r1 %r29 | ||
998 | rsm (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0 | ||
999 | |||
1000 | /* Restore space id's and special cr's from PT_REGS | ||
1001 | * structure pointed to by r29 */ | ||
1002 | rest_specials %r29 | ||
1003 | |||
1004 | /* Important: Note that rest_stack restores r29 | ||
1005 | * last (we are using it)! It also restores r1 and r30. */ | ||
1006 | rest_stack | ||
1007 | |||
1008 | rfi | ||
1009 | nop | ||
1010 | nop | ||
1011 | nop | ||
1012 | nop | ||
1013 | nop | ||
1014 | nop | ||
1015 | nop | ||
1016 | nop | ||
1017 | |||
1018 | .import do_softirq,code | ||
1019 | intr_do_softirq: | ||
1020 | bl do_softirq,%r2 | ||
1021 | #ifdef __LP64__ | ||
1022 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1023 | #else | ||
1024 | nop | ||
1025 | #endif | ||
1026 | b intr_check_resched | ||
1027 | nop | ||
1028 | |||
1029 | .import schedule,code | ||
1030 | intr_do_resched: | ||
1031 | /* Only do reschedule if we are returning to user space */ | ||
1032 | LDREG PT_IASQ0(%r16), %r20 | ||
1033 | CMPIB= 0,%r20,intr_restore /* backward */ | ||
1034 | nop | ||
1035 | LDREG PT_IASQ1(%r16), %r20 | ||
1036 | CMPIB= 0,%r20,intr_restore /* backward */ | ||
1037 | nop | ||
1038 | |||
1039 | #ifdef __LP64__ | ||
1040 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1041 | #endif | ||
1042 | |||
1043 | ldil L%intr_check_sig, %r2 | ||
1044 | b schedule | ||
1045 | ldo R%intr_check_sig(%r2), %r2 | ||
1046 | |||
1047 | |||
1048 | .import do_signal,code | ||
1049 | intr_do_signal: | ||
1050 | /* | ||
1051 | This check is critical to having LWS | ||
1052 | working. The IASQ is zero on the gateway | ||
1053 | page and we cannot deliver any signals until | ||
1054 | we get off the gateway page. | ||
1055 | |||
1056 | Only do signals if we are returning to user space | ||
1057 | */ | ||
1058 | LDREG PT_IASQ0(%r16), %r20 | ||
1059 | CMPIB= 0,%r20,intr_restore /* backward */ | ||
1060 | nop | ||
1061 | LDREG PT_IASQ1(%r16), %r20 | ||
1062 | CMPIB= 0,%r20,intr_restore /* backward */ | ||
1063 | nop | ||
1064 | |||
1065 | copy %r0, %r24 /* unsigned long in_syscall */ | ||
1066 | copy %r16, %r25 /* struct pt_regs *regs */ | ||
1067 | #ifdef __LP64__ | ||
1068 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1069 | #endif | ||
1070 | |||
1071 | BL do_signal,%r2 | ||
1072 | copy %r0, %r26 /* sigset_t *oldset = NULL */ | ||
1073 | |||
1074 | b intr_check_sig | ||
1075 | nop | ||
1076 | |||
1077 | /* | ||
1078 | * External interrupts. | ||
1079 | */ | ||
1080 | |||
1081 | intr_extint: | ||
1082 | CMPIB=,n 0,%r16,1f | ||
1083 | get_stack_use_cr30 | ||
1084 | b,n 3f | ||
1085 | |||
1086 | 1: | ||
1087 | #if 0 /* Interrupt Stack support not working yet! */ | ||
1088 | mfctl %cr31,%r1 | ||
1089 | copy %r30,%r17 | ||
1090 | /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/ | ||
1091 | #ifdef __LP64__ | ||
1092 | depdi 0,63,15,%r17 | ||
1093 | #else | ||
1094 | depi 0,31,15,%r17 | ||
1095 | #endif | ||
1096 | CMPB=,n %r1,%r17,2f | ||
1097 | get_stack_use_cr31 | ||
1098 | b,n 3f | ||
1099 | #endif | ||
1100 | 2: | ||
1101 | get_stack_use_r30 | ||
1102 | |||
1103 | 3: | ||
1104 | save_specials %r29 | ||
1105 | virt_map | ||
1106 | save_general %r29 | ||
1107 | |||
1108 | ldo PT_FR0(%r29), %r24 | ||
1109 | save_fp %r24 | ||
1110 | |||
1111 | loadgp | ||
1112 | |||
1113 | copy %r29, %r26 /* arg0 is pt_regs */ | ||
1114 | copy %r29, %r16 /* save pt_regs */ | ||
1115 | |||
1116 | ldil L%intr_return, %r2 | ||
1117 | |||
1118 | #ifdef __LP64__ | ||
1119 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1120 | #endif | ||
1121 | |||
1122 | b do_cpu_irq_mask | ||
1123 | ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */ | ||
1124 | |||
1125 | |||
1126 | /* Generic interruptions (illegal insn, unaligned, page fault, etc) */ | ||
1127 | |||
1128 | .export intr_save, code /* for os_hpmc */ | ||
1129 | |||
1130 | intr_save: | ||
1131 | mfsp %sr7,%r16 | ||
1132 | CMPIB=,n 0,%r16,1f | ||
1133 | get_stack_use_cr30 | ||
1134 | b 2f | ||
1135 | copy %r8,%r26 | ||
1136 | |||
1137 | 1: | ||
1138 | get_stack_use_r30 | ||
1139 | copy %r8,%r26 | ||
1140 | |||
1141 | 2: | ||
1142 | save_specials %r29 | ||
1143 | |||
1144 | /* If this trap is a itlb miss, skip saving/adjusting isr/ior */ | ||
1145 | |||
1146 | /* | ||
1147 | * FIXME: 1) Use a #define for the hardwired "6" below (and in | ||
1148 | * traps.c. | ||
1149 | * 2) Once we start executing code above 4 Gb, we need | ||
1150 | * to adjust iasq/iaoq here in the same way we | ||
1151 | * adjust isr/ior below. | ||
1152 | */ | ||
1153 | |||
1154 | CMPIB=,n 6,%r26,skip_save_ior | ||
1155 | |||
1156 | /* save_specials left ipsw value in r8 for us to test */ | ||
1157 | |||
1158 | mfctl %cr20, %r16 /* isr */ | ||
1159 | mfctl %cr21, %r17 /* ior */ | ||
1160 | |||
1161 | #ifdef __LP64__ | ||
1162 | /* | ||
1163 | * If the interrupted code was running with W bit off (32 bit), | ||
1164 | * clear the b bits (bits 0 & 1) in the ior. | ||
1165 | */ | ||
1166 | extrd,u,*<> %r8,PSW_W_BIT,1,%r0 | ||
1167 | depdi 0,1,2,%r17 | ||
1168 | |||
1169 | /* | ||
1170 | * FIXME: This code has hardwired assumptions about the split | ||
1171 | * between space bits and offset bits. This will change | ||
1172 | * when we allow alternate page sizes. | ||
1173 | */ | ||
1174 | |||
1175 | /* adjust isr/ior. */ | ||
1176 | |||
1177 | extrd,u %r16,63,7,%r1 /* get high bits from isr for ior */ | ||
1178 | depd %r1,31,7,%r17 /* deposit them into ior */ | ||
1179 | depdi 0,63,7,%r16 /* clear them from isr */ | ||
1180 | #endif | ||
1181 | STREG %r16, PT_ISR(%r29) | ||
1182 | STREG %r17, PT_IOR(%r29) | ||
1183 | |||
1184 | |||
1185 | skip_save_ior: | ||
1186 | virt_map | ||
1187 | save_general %r29 | ||
1188 | |||
1189 | ldo PT_FR0(%r29), %r25 | ||
1190 | save_fp %r25 | ||
1191 | |||
1192 | loadgp | ||
1193 | |||
1194 | copy %r29, %r25 /* arg1 is pt_regs */ | ||
1195 | #ifdef __LP64__ | ||
1196 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1197 | #endif | ||
1198 | |||
1199 | ldil L%intr_check_sig, %r2 | ||
1200 | copy %r25, %r16 /* save pt_regs */ | ||
1201 | |||
1202 | b handle_interruption | ||
1203 | ldo R%intr_check_sig(%r2), %r2 | ||
1204 | |||
1205 | |||
1206 | /* | ||
1207 | * Note for all tlb miss handlers: | ||
1208 | * | ||
1209 | * cr24 contains a pointer to the kernel address space | ||
1210 | * page directory. | ||
1211 | * | ||
1212 | * cr25 contains a pointer to the current user address | ||
1213 | * space page directory. | ||
1214 | * | ||
1215 | * sr3 will contain the space id of the user address space | ||
1216 | * of the current running thread while that thread is | ||
1217 | * running in the kernel. | ||
1218 | */ | ||
1219 | |||
1220 | /* | ||
1221 | * register number allocations. Note that these are all | ||
1222 | * in the shadowed registers | ||
1223 | */ | ||
1224 | |||
1225 | t0 = r1 /* temporary register 0 */ | ||
1226 | va = r8 /* virtual address for which the trap occured */ | ||
1227 | t1 = r9 /* temporary register 1 */ | ||
1228 | pte = r16 /* pte/phys page # */ | ||
1229 | prot = r17 /* prot bits */ | ||
1230 | spc = r24 /* space for which the trap occured */ | ||
1231 | ptp = r25 /* page directory/page table pointer */ | ||
1232 | |||
1233 | #ifdef __LP64__ | ||
1234 | |||
1235 | dtlb_miss_20w: | ||
1236 | space_adjust spc,va,t0 | ||
1237 | get_pgd spc,ptp | ||
1238 | space_check spc,t0,dtlb_fault | ||
1239 | |||
1240 | L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w | ||
1241 | |||
1242 | update_ptep ptp,pte,t0,t1 | ||
1243 | |||
1244 | make_insert_tlb spc,pte,prot | ||
1245 | |||
1246 | idtlbt pte,prot | ||
1247 | |||
1248 | rfir | ||
1249 | nop | ||
1250 | |||
1251 | dtlb_check_alias_20w: | ||
1252 | do_alias spc,t0,t1,va,pte,prot,dtlb_fault | ||
1253 | |||
1254 | idtlbt pte,prot | ||
1255 | |||
1256 | rfir | ||
1257 | nop | ||
1258 | |||
1259 | nadtlb_miss_20w: | ||
1260 | space_adjust spc,va,t0 | ||
1261 | get_pgd spc,ptp | ||
1262 | space_check spc,t0,nadtlb_fault | ||
1263 | |||
1264 | L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w | ||
1265 | |||
1266 | update_ptep ptp,pte,t0,t1 | ||
1267 | |||
1268 | make_insert_tlb spc,pte,prot | ||
1269 | |||
1270 | idtlbt pte,prot | ||
1271 | |||
1272 | rfir | ||
1273 | nop | ||
1274 | |||
1275 | nadtlb_check_flush_20w: | ||
1276 | bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate | ||
1277 | |||
1278 | /* Insert a "flush only" translation */ | ||
1279 | |||
1280 | depdi,z 7,7,3,prot | ||
1281 | depdi 1,10,1,prot | ||
1282 | |||
1283 | /* Get rid of prot bits and convert to page addr for idtlbt */ | ||
1284 | |||
1285 | depdi 0,63,12,pte | ||
1286 | extrd,u pte,56,52,pte | ||
1287 | idtlbt pte,prot | ||
1288 | |||
1289 | rfir | ||
1290 | nop | ||
1291 | |||
1292 | #else | ||
1293 | |||
1294 | dtlb_miss_11: | ||
1295 | get_pgd spc,ptp | ||
1296 | |||
1297 | space_check spc,t0,dtlb_fault | ||
1298 | |||
1299 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 | ||
1300 | |||
1301 | update_ptep ptp,pte,t0,t1 | ||
1302 | |||
1303 | make_insert_tlb_11 spc,pte,prot | ||
1304 | |||
1305 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | ||
1306 | mtsp spc,%sr1 | ||
1307 | |||
1308 | idtlba pte,(%sr1,va) | ||
1309 | idtlbp prot,(%sr1,va) | ||
1310 | |||
1311 | mtsp t0, %sr1 /* Restore sr1 */ | ||
1312 | |||
1313 | rfir | ||
1314 | nop | ||
1315 | |||
1316 | dtlb_check_alias_11: | ||
1317 | |||
1318 | /* Check to see if fault is in the temporary alias region */ | ||
1319 | |||
1320 | cmpib,<>,n 0,spc,dtlb_fault /* forward */ | ||
1321 | ldil L%(TMPALIAS_MAP_START),t0 | ||
1322 | copy va,t1 | ||
1323 | depwi 0,31,23,t1 | ||
1324 | cmpb,<>,n t0,t1,dtlb_fault /* forward */ | ||
1325 | ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot | ||
1326 | depw,z prot,8,7,prot | ||
1327 | |||
1328 | /* | ||
1329 | * OK, it is in the temp alias region, check whether "from" or "to". | ||
1330 | * Check "subtle" note in pacache.S re: r23/r26. | ||
1331 | */ | ||
1332 | |||
1333 | extrw,u,= va,9,1,r0 | ||
1334 | or,tr %r23,%r0,pte /* If "from" use "from" page */ | ||
1335 | or %r26,%r0,pte /* else "to", use "to" page */ | ||
1336 | |||
1337 | idtlba pte,(va) | ||
1338 | idtlbp prot,(va) | ||
1339 | |||
1340 | rfir | ||
1341 | nop | ||
1342 | |||
1343 | nadtlb_miss_11: | ||
1344 | get_pgd spc,ptp | ||
1345 | |||
1346 | space_check spc,t0,nadtlb_fault | ||
1347 | |||
1348 | L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11 | ||
1349 | |||
1350 | update_ptep ptp,pte,t0,t1 | ||
1351 | |||
1352 | make_insert_tlb_11 spc,pte,prot | ||
1353 | |||
1354 | |||
1355 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | ||
1356 | mtsp spc,%sr1 | ||
1357 | |||
1358 | idtlba pte,(%sr1,va) | ||
1359 | idtlbp prot,(%sr1,va) | ||
1360 | |||
1361 | mtsp t0, %sr1 /* Restore sr1 */ | ||
1362 | |||
1363 | rfir | ||
1364 | nop | ||
1365 | |||
1366 | nadtlb_check_flush_11: | ||
1367 | bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate | ||
1368 | |||
1369 | /* Insert a "flush only" translation */ | ||
1370 | |||
1371 | zdepi 7,7,3,prot | ||
1372 | depi 1,10,1,prot | ||
1373 | |||
1374 | /* Get rid of prot bits and convert to page addr for idtlba */ | ||
1375 | |||
1376 | depi 0,31,12,pte | ||
1377 | extru pte,24,25,pte | ||
1378 | |||
1379 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | ||
1380 | mtsp spc,%sr1 | ||
1381 | |||
1382 | idtlba pte,(%sr1,va) | ||
1383 | idtlbp prot,(%sr1,va) | ||
1384 | |||
1385 | mtsp t0, %sr1 /* Restore sr1 */ | ||
1386 | |||
1387 | rfir | ||
1388 | nop | ||
1389 | |||
1390 | dtlb_miss_20: | ||
1391 | space_adjust spc,va,t0 | ||
1392 | get_pgd spc,ptp | ||
1393 | space_check spc,t0,dtlb_fault | ||
1394 | |||
1395 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 | ||
1396 | |||
1397 | update_ptep ptp,pte,t0,t1 | ||
1398 | |||
1399 | make_insert_tlb spc,pte,prot | ||
1400 | |||
1401 | f_extend pte,t0 | ||
1402 | |||
1403 | idtlbt pte,prot | ||
1404 | |||
1405 | rfir | ||
1406 | nop | ||
1407 | |||
1408 | dtlb_check_alias_20: | ||
1409 | do_alias spc,t0,t1,va,pte,prot,dtlb_fault | ||
1410 | |||
1411 | idtlbt pte,prot | ||
1412 | |||
1413 | rfir | ||
1414 | nop | ||
1415 | |||
1416 | nadtlb_miss_20: | ||
1417 | get_pgd spc,ptp | ||
1418 | |||
1419 | space_check spc,t0,nadtlb_fault | ||
1420 | |||
1421 | L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20 | ||
1422 | |||
1423 | update_ptep ptp,pte,t0,t1 | ||
1424 | |||
1425 | make_insert_tlb spc,pte,prot | ||
1426 | |||
1427 | f_extend pte,t0 | ||
1428 | |||
1429 | idtlbt pte,prot | ||
1430 | |||
1431 | rfir | ||
1432 | nop | ||
1433 | |||
1434 | nadtlb_check_flush_20: | ||
1435 | bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate | ||
1436 | |||
1437 | /* Insert a "flush only" translation */ | ||
1438 | |||
1439 | depdi,z 7,7,3,prot | ||
1440 | depdi 1,10,1,prot | ||
1441 | |||
1442 | /* Get rid of prot bits and convert to page addr for idtlbt */ | ||
1443 | |||
1444 | depdi 0,63,12,pte | ||
1445 | extrd,u pte,56,32,pte | ||
1446 | idtlbt pte,prot | ||
1447 | |||
1448 | rfir | ||
1449 | nop | ||
1450 | #endif | ||
1451 | |||
1452 | nadtlb_emulate: | ||
1453 | |||
1454 | /* | ||
1455 | * Non access misses can be caused by fdc,fic,pdc,lpa,probe and | ||
1456 | * probei instructions. We don't want to fault for these | ||
1457 | * instructions (not only does it not make sense, it can cause | ||
1458 | * deadlocks, since some flushes are done with the mmap | ||
1459 | * semaphore held). If the translation doesn't exist, we can't | ||
1460 | * insert a translation, so have to emulate the side effects | ||
1461 | * of the instruction. Since we don't insert a translation | ||
1462 | * we can get a lot of faults during a flush loop, so it makes | ||
1463 | * sense to try to do it here with minimum overhead. We only | ||
1464 | * emulate fdc,fic,pdc,probew,prober instructions whose base | ||
1465 | * and index registers are not shadowed. We defer everything | ||
1466 | * else to the "slow" path. | ||
1467 | */ | ||
1468 | |||
1469 | mfctl %cr19,%r9 /* Get iir */ | ||
1470 | |||
1471 | /* PA 2.0 Arch Ref. Book pg 382 has a good description of the insn bits. | ||
1472 | Checks for fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw */ | ||
1473 | |||
1474 | /* Checks for fdc,fdce,pdc,"fic,4f" only */ | ||
1475 | ldi 0x280,%r16 | ||
1476 | and %r9,%r16,%r17 | ||
1477 | cmpb,<>,n %r16,%r17,nadtlb_probe_check | ||
1478 | bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */ | ||
1479 | BL get_register,%r25 | ||
1480 | extrw,u %r9,15,5,%r8 /* Get index register # */ | ||
1481 | CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ | ||
1482 | copy %r1,%r24 | ||
1483 | BL get_register,%r25 | ||
1484 | extrw,u %r9,10,5,%r8 /* Get base register # */ | ||
1485 | CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ | ||
1486 | BL set_register,%r25 | ||
1487 | add,l %r1,%r24,%r1 /* doesn't affect c/b bits */ | ||
1488 | |||
1489 | nadtlb_nullify: | ||
1490 | mfctl %cr22,%r8 /* Get ipsw */ | ||
1491 | ldil L%PSW_N,%r9 | ||
1492 | or %r8,%r9,%r8 /* Set PSW_N */ | ||
1493 | mtctl %r8,%cr22 | ||
1494 | |||
1495 | rfir | ||
1496 | nop | ||
1497 | |||
1498 | /* | ||
1499 | When there is no translation for the probe address then we | ||
1500 | must nullify the insn and return zero in the target regsiter. | ||
1501 | This will indicate to the calling code that it does not have | ||
1502 | write/read privileges to this address. | ||
1503 | |||
1504 | This should technically work for prober and probew in PA 1.1, | ||
1505 | and also probe,r and probe,w in PA 2.0 | ||
1506 | |||
1507 | WARNING: USE ONLY NON-SHADOW REGISTERS WITH PROBE INSN! | ||
1508 | THE SLOW-PATH EMULATION HAS NOT BEEN WRITTEN YET. | ||
1509 | |||
1510 | */ | ||
1511 | nadtlb_probe_check: | ||
1512 | ldi 0x80,%r16 | ||
1513 | and %r9,%r16,%r17 | ||
1514 | cmpb,<>,n %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/ | ||
1515 | BL get_register,%r25 /* Find the target register */ | ||
1516 | extrw,u %r9,31,5,%r8 /* Get target register */ | ||
1517 | CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ | ||
1518 | BL set_register,%r25 | ||
1519 | copy %r0,%r1 /* Write zero to target register */ | ||
1520 | b nadtlb_nullify /* Nullify return insn */ | ||
1521 | nop | ||
1522 | |||
1523 | |||
1524 | #ifdef __LP64__ | ||
1525 | itlb_miss_20w: | ||
1526 | |||
1527 | /* | ||
1528 | * I miss is a little different, since we allow users to fault | ||
1529 | * on the gateway page which is in the kernel address space. | ||
1530 | */ | ||
1531 | |||
1532 | space_adjust spc,va,t0 | ||
1533 | get_pgd spc,ptp | ||
1534 | space_check spc,t0,itlb_fault | ||
1535 | |||
1536 | L3_ptep ptp,pte,t0,va,itlb_fault | ||
1537 | |||
1538 | update_ptep ptp,pte,t0,t1 | ||
1539 | |||
1540 | make_insert_tlb spc,pte,prot | ||
1541 | |||
1542 | iitlbt pte,prot | ||
1543 | |||
1544 | rfir | ||
1545 | nop | ||
1546 | |||
1547 | #else | ||
1548 | |||
1549 | itlb_miss_11: | ||
1550 | get_pgd spc,ptp | ||
1551 | |||
1552 | space_check spc,t0,itlb_fault | ||
1553 | |||
1554 | L2_ptep ptp,pte,t0,va,itlb_fault | ||
1555 | |||
1556 | update_ptep ptp,pte,t0,t1 | ||
1557 | |||
1558 | make_insert_tlb_11 spc,pte,prot | ||
1559 | |||
1560 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | ||
1561 | mtsp spc,%sr1 | ||
1562 | |||
1563 | iitlba pte,(%sr1,va) | ||
1564 | iitlbp prot,(%sr1,va) | ||
1565 | |||
1566 | mtsp t0, %sr1 /* Restore sr1 */ | ||
1567 | |||
1568 | rfir | ||
1569 | nop | ||
1570 | |||
1571 | itlb_miss_20: | ||
1572 | get_pgd spc,ptp | ||
1573 | |||
1574 | space_check spc,t0,itlb_fault | ||
1575 | |||
1576 | L2_ptep ptp,pte,t0,va,itlb_fault | ||
1577 | |||
1578 | update_ptep ptp,pte,t0,t1 | ||
1579 | |||
1580 | make_insert_tlb spc,pte,prot | ||
1581 | |||
1582 | f_extend pte,t0 | ||
1583 | |||
1584 | iitlbt pte,prot | ||
1585 | |||
1586 | rfir | ||
1587 | nop | ||
1588 | |||
1589 | #endif | ||
1590 | |||
1591 | #ifdef __LP64__ | ||
1592 | |||
1593 | dbit_trap_20w: | ||
1594 | space_adjust spc,va,t0 | ||
1595 | get_pgd spc,ptp | ||
1596 | space_check spc,t0,dbit_fault | ||
1597 | |||
1598 | L3_ptep ptp,pte,t0,va,dbit_fault | ||
1599 | |||
1600 | #ifdef CONFIG_SMP | ||
1601 | CMPIB=,n 0,spc,dbit_nolock_20w | ||
1602 | load32 PA(pa_dbit_lock),t0 | ||
1603 | |||
1604 | dbit_spin_20w: | ||
1605 | ldcw 0(t0),t1 | ||
1606 | cmpib,= 0,t1,dbit_spin_20w | ||
1607 | nop | ||
1608 | |||
1609 | dbit_nolock_20w: | ||
1610 | #endif | ||
1611 | update_dirty ptp,pte,t1 | ||
1612 | |||
1613 | make_insert_tlb spc,pte,prot | ||
1614 | |||
1615 | idtlbt pte,prot | ||
1616 | #ifdef CONFIG_SMP | ||
1617 | CMPIB=,n 0,spc,dbit_nounlock_20w | ||
1618 | ldi 1,t1 | ||
1619 | stw t1,0(t0) | ||
1620 | |||
1621 | dbit_nounlock_20w: | ||
1622 | #endif | ||
1623 | |||
1624 | rfir | ||
1625 | nop | ||
1626 | #else | ||
1627 | |||
1628 | dbit_trap_11: | ||
1629 | |||
1630 | get_pgd spc,ptp | ||
1631 | |||
1632 | space_check spc,t0,dbit_fault | ||
1633 | |||
1634 | L2_ptep ptp,pte,t0,va,dbit_fault | ||
1635 | |||
1636 | #ifdef CONFIG_SMP | ||
1637 | CMPIB=,n 0,spc,dbit_nolock_11 | ||
1638 | load32 PA(pa_dbit_lock),t0 | ||
1639 | |||
1640 | dbit_spin_11: | ||
1641 | ldcw 0(t0),t1 | ||
1642 | cmpib,= 0,t1,dbit_spin_11 | ||
1643 | nop | ||
1644 | |||
1645 | dbit_nolock_11: | ||
1646 | #endif | ||
1647 | update_dirty ptp,pte,t1 | ||
1648 | |||
1649 | make_insert_tlb_11 spc,pte,prot | ||
1650 | |||
1651 | mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ | ||
1652 | mtsp spc,%sr1 | ||
1653 | |||
1654 | idtlba pte,(%sr1,va) | ||
1655 | idtlbp prot,(%sr1,va) | ||
1656 | |||
1657 | mtsp t1, %sr1 /* Restore sr1 */ | ||
1658 | #ifdef CONFIG_SMP | ||
1659 | CMPIB=,n 0,spc,dbit_nounlock_11 | ||
1660 | ldi 1,t1 | ||
1661 | stw t1,0(t0) | ||
1662 | |||
1663 | dbit_nounlock_11: | ||
1664 | #endif | ||
1665 | |||
1666 | rfir | ||
1667 | nop | ||
1668 | |||
1669 | dbit_trap_20: | ||
1670 | get_pgd spc,ptp | ||
1671 | |||
1672 | space_check spc,t0,dbit_fault | ||
1673 | |||
1674 | L2_ptep ptp,pte,t0,va,dbit_fault | ||
1675 | |||
1676 | #ifdef CONFIG_SMP | ||
1677 | CMPIB=,n 0,spc,dbit_nolock_20 | ||
1678 | load32 PA(pa_dbit_lock),t0 | ||
1679 | |||
1680 | dbit_spin_20: | ||
1681 | ldcw 0(t0),t1 | ||
1682 | cmpib,= 0,t1,dbit_spin_20 | ||
1683 | nop | ||
1684 | |||
1685 | dbit_nolock_20: | ||
1686 | #endif | ||
1687 | update_dirty ptp,pte,t1 | ||
1688 | |||
1689 | make_insert_tlb spc,pte,prot | ||
1690 | |||
1691 | f_extend pte,t1 | ||
1692 | |||
1693 | idtlbt pte,prot | ||
1694 | |||
1695 | #ifdef CONFIG_SMP | ||
1696 | CMPIB=,n 0,spc,dbit_nounlock_20 | ||
1697 | ldi 1,t1 | ||
1698 | stw t1,0(t0) | ||
1699 | |||
1700 | dbit_nounlock_20: | ||
1701 | #endif | ||
1702 | |||
1703 | rfir | ||
1704 | nop | ||
1705 | #endif | ||
1706 | |||
1707 | .import handle_interruption,code | ||
1708 | |||
1709 | kernel_bad_space: | ||
1710 | b intr_save | ||
1711 | ldi 31,%r8 /* Use an unused code */ | ||
1712 | |||
1713 | dbit_fault: | ||
1714 | b intr_save | ||
1715 | ldi 20,%r8 | ||
1716 | |||
1717 | itlb_fault: | ||
1718 | b intr_save | ||
1719 | ldi 6,%r8 | ||
1720 | |||
1721 | nadtlb_fault: | ||
1722 | b intr_save | ||
1723 | ldi 17,%r8 | ||
1724 | |||
1725 | dtlb_fault: | ||
1726 | b intr_save | ||
1727 | ldi 15,%r8 | ||
1728 | |||
1729 | /* Register saving semantics for system calls: | ||
1730 | |||
1731 | %r1 clobbered by system call macro in userspace | ||
1732 | %r2 saved in PT_REGS by gateway page | ||
1733 | %r3 - %r18 preserved by C code (saved by signal code) | ||
1734 | %r19 - %r20 saved in PT_REGS by gateway page | ||
1735 | %r21 - %r22 non-standard syscall args | ||
1736 | stored in kernel stack by gateway page | ||
1737 | %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page | ||
1738 | %r27 - %r30 saved in PT_REGS by gateway page | ||
1739 | %r31 syscall return pointer | ||
1740 | */ | ||
1741 | |||
1742 | /* Floating point registers (FIXME: what do we do with these?) | ||
1743 | |||
1744 | %fr0 - %fr3 status/exception, not preserved | ||
1745 | %fr4 - %fr7 arguments | ||
1746 | %fr8 - %fr11 not preserved by C code | ||
1747 | %fr12 - %fr21 preserved by C code | ||
1748 | %fr22 - %fr31 not preserved by C code | ||
1749 | */ | ||
1750 | |||
1751 | .macro reg_save regs | ||
1752 | STREG %r3, PT_GR3(\regs) | ||
1753 | STREG %r4, PT_GR4(\regs) | ||
1754 | STREG %r5, PT_GR5(\regs) | ||
1755 | STREG %r6, PT_GR6(\regs) | ||
1756 | STREG %r7, PT_GR7(\regs) | ||
1757 | STREG %r8, PT_GR8(\regs) | ||
1758 | STREG %r9, PT_GR9(\regs) | ||
1759 | STREG %r10,PT_GR10(\regs) | ||
1760 | STREG %r11,PT_GR11(\regs) | ||
1761 | STREG %r12,PT_GR12(\regs) | ||
1762 | STREG %r13,PT_GR13(\regs) | ||
1763 | STREG %r14,PT_GR14(\regs) | ||
1764 | STREG %r15,PT_GR15(\regs) | ||
1765 | STREG %r16,PT_GR16(\regs) | ||
1766 | STREG %r17,PT_GR17(\regs) | ||
1767 | STREG %r18,PT_GR18(\regs) | ||
1768 | .endm | ||
1769 | |||
1770 | .macro reg_restore regs | ||
1771 | LDREG PT_GR3(\regs), %r3 | ||
1772 | LDREG PT_GR4(\regs), %r4 | ||
1773 | LDREG PT_GR5(\regs), %r5 | ||
1774 | LDREG PT_GR6(\regs), %r6 | ||
1775 | LDREG PT_GR7(\regs), %r7 | ||
1776 | LDREG PT_GR8(\regs), %r8 | ||
1777 | LDREG PT_GR9(\regs), %r9 | ||
1778 | LDREG PT_GR10(\regs),%r10 | ||
1779 | LDREG PT_GR11(\regs),%r11 | ||
1780 | LDREG PT_GR12(\regs),%r12 | ||
1781 | LDREG PT_GR13(\regs),%r13 | ||
1782 | LDREG PT_GR14(\regs),%r14 | ||
1783 | LDREG PT_GR15(\regs),%r15 | ||
1784 | LDREG PT_GR16(\regs),%r16 | ||
1785 | LDREG PT_GR17(\regs),%r17 | ||
1786 | LDREG PT_GR18(\regs),%r18 | ||
1787 | .endm | ||
1788 | |||
1789 | .export sys_fork_wrapper | ||
1790 | .export child_return | ||
1791 | sys_fork_wrapper: | ||
1792 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 | ||
1793 | ldo TASK_REGS(%r1),%r1 | ||
1794 | reg_save %r1 | ||
1795 | mfctl %cr27, %r3 | ||
1796 | STREG %r3, PT_CR27(%r1) | ||
1797 | |||
1798 | STREG %r2,-RP_OFFSET(%r30) | ||
1799 | ldo FRAME_SIZE(%r30),%r30 | ||
1800 | #ifdef __LP64__ | ||
1801 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1802 | #endif | ||
1803 | |||
1804 | /* These are call-clobbered registers and therefore | ||
1805 | also syscall-clobbered (we hope). */ | ||
1806 | STREG %r2,PT_GR19(%r1) /* save for child */ | ||
1807 | STREG %r30,PT_GR21(%r1) | ||
1808 | |||
1809 | LDREG PT_GR30(%r1),%r25 | ||
1810 | copy %r1,%r24 | ||
1811 | BL sys_clone,%r2 | ||
1812 | ldi SIGCHLD,%r26 | ||
1813 | |||
1814 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1815 | wrapper_exit: | ||
1816 | ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ | ||
1817 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1818 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1819 | |||
1820 | LDREG PT_CR27(%r1), %r3 | ||
1821 | mtctl %r3, %cr27 | ||
1822 | reg_restore %r1 | ||
1823 | |||
1824 | /* strace expects syscall # to be preserved in r20 */ | ||
1825 | ldi __NR_fork,%r20 | ||
1826 | bv %r0(%r2) | ||
1827 | STREG %r20,PT_GR20(%r1) | ||
1828 | |||
1829 | /* Set the return value for the child */ | ||
1830 | child_return: | ||
1831 | BL schedule_tail, %r2 | ||
1832 | nop | ||
1833 | |||
1834 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 | ||
1835 | LDREG TASK_PT_GR19(%r1),%r2 | ||
1836 | b wrapper_exit | ||
1837 | copy %r0,%r28 | ||
1838 | |||
1839 | |||
1840 | .export sys_clone_wrapper | ||
1841 | sys_clone_wrapper: | ||
1842 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1843 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1844 | reg_save %r1 | ||
1845 | mfctl %cr27, %r3 | ||
1846 | STREG %r3, PT_CR27(%r1) | ||
1847 | |||
1848 | STREG %r2,-RP_OFFSET(%r30) | ||
1849 | ldo FRAME_SIZE(%r30),%r30 | ||
1850 | #ifdef __LP64__ | ||
1851 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1852 | #endif | ||
1853 | |||
1854 | STREG %r2,PT_GR19(%r1) /* save for child */ | ||
1855 | STREG %r30,PT_GR21(%r1) | ||
1856 | BL sys_clone,%r2 | ||
1857 | copy %r1,%r24 | ||
1858 | |||
1859 | b wrapper_exit | ||
1860 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1861 | |||
1862 | .export sys_vfork_wrapper | ||
1863 | sys_vfork_wrapper: | ||
1864 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1865 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1866 | reg_save %r1 | ||
1867 | mfctl %cr27, %r3 | ||
1868 | STREG %r3, PT_CR27(%r1) | ||
1869 | |||
1870 | STREG %r2,-RP_OFFSET(%r30) | ||
1871 | ldo FRAME_SIZE(%r30),%r30 | ||
1872 | #ifdef __LP64__ | ||
1873 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1874 | #endif | ||
1875 | |||
1876 | STREG %r2,PT_GR19(%r1) /* save for child */ | ||
1877 | STREG %r30,PT_GR21(%r1) | ||
1878 | |||
1879 | BL sys_vfork,%r2 | ||
1880 | copy %r1,%r26 | ||
1881 | |||
1882 | b wrapper_exit | ||
1883 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1884 | |||
1885 | |||
1886 | .macro execve_wrapper execve | ||
1887 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1888 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1889 | |||
1890 | /* | ||
1891 | * Do we need to save/restore r3-r18 here? | ||
1892 | * I don't think so. why would new thread need old | ||
1893 | * threads registers? | ||
1894 | */ | ||
1895 | |||
1896 | /* %arg0 - %arg3 are already saved for us. */ | ||
1897 | |||
1898 | STREG %r2,-RP_OFFSET(%r30) | ||
1899 | ldo FRAME_SIZE(%r30),%r30 | ||
1900 | #ifdef __LP64__ | ||
1901 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1902 | #endif | ||
1903 | bl \execve,%r2 | ||
1904 | copy %r1,%arg0 | ||
1905 | |||
1906 | ldo -FRAME_SIZE(%r30),%r30 | ||
1907 | LDREG -RP_OFFSET(%r30),%r2 | ||
1908 | |||
1909 | /* If exec succeeded we need to load the args */ | ||
1910 | |||
1911 | ldo -1024(%r0),%r1 | ||
1912 | cmpb,>>= %r28,%r1,error_\execve | ||
1913 | copy %r2,%r19 | ||
1914 | |||
1915 | error_\execve: | ||
1916 | bv %r0(%r19) | ||
1917 | nop | ||
1918 | .endm | ||
1919 | |||
1920 | .export sys_execve_wrapper | ||
1921 | .import sys_execve | ||
1922 | |||
1923 | sys_execve_wrapper: | ||
1924 | execve_wrapper sys_execve | ||
1925 | |||
1926 | #ifdef __LP64__ | ||
1927 | .export sys32_execve_wrapper | ||
1928 | .import sys32_execve | ||
1929 | |||
1930 | sys32_execve_wrapper: | ||
1931 | execve_wrapper sys32_execve | ||
1932 | #endif | ||
1933 | |||
1934 | .export sys_rt_sigreturn_wrapper | ||
1935 | sys_rt_sigreturn_wrapper: | ||
1936 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 | ||
1937 | ldo TASK_REGS(%r26),%r26 /* get pt regs */ | ||
1938 | /* Don't save regs, we are going to restore them from sigcontext. */ | ||
1939 | STREG %r2, -RP_OFFSET(%r30) | ||
1940 | #ifdef __LP64__ | ||
1941 | ldo FRAME_SIZE(%r30), %r30 | ||
1942 | BL sys_rt_sigreturn,%r2 | ||
1943 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1944 | #else | ||
1945 | BL sys_rt_sigreturn,%r2 | ||
1946 | ldo FRAME_SIZE(%r30), %r30 | ||
1947 | #endif | ||
1948 | |||
1949 | ldo -FRAME_SIZE(%r30), %r30 | ||
1950 | LDREG -RP_OFFSET(%r30), %r2 | ||
1951 | |||
1952 | /* FIXME: I think we need to restore a few more things here. */ | ||
1953 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1954 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1955 | reg_restore %r1 | ||
1956 | |||
1957 | /* If the signal was received while the process was blocked on a | ||
1958 | * syscall, then r2 will take us to syscall_exit; otherwise r2 will | ||
1959 | * take us to syscall_exit_rfi and on to intr_return. | ||
1960 | */ | ||
1961 | bv %r0(%r2) | ||
1962 | LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */ | ||
1963 | |||
1964 | .export sys_sigaltstack_wrapper | ||
1965 | sys_sigaltstack_wrapper: | ||
1966 | /* Get the user stack pointer */ | ||
1967 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1968 | ldo TASK_REGS(%r1),%r24 /* get pt regs */ | ||
1969 | LDREG TASK_PT_GR30(%r24),%r24 | ||
1970 | STREG %r2, -RP_OFFSET(%r30) | ||
1971 | #ifdef __LP64__ | ||
1972 | ldo FRAME_SIZE(%r30), %r30 | ||
1973 | b,l do_sigaltstack,%r2 | ||
1974 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1975 | #else | ||
1976 | bl do_sigaltstack,%r2 | ||
1977 | ldo FRAME_SIZE(%r30), %r30 | ||
1978 | #endif | ||
1979 | |||
1980 | ldo -FRAME_SIZE(%r30), %r30 | ||
1981 | LDREG -RP_OFFSET(%r30), %r2 | ||
1982 | bv %r0(%r2) | ||
1983 | nop | ||
1984 | |||
1985 | #ifdef __LP64__ | ||
1986 | .export sys32_sigaltstack_wrapper | ||
1987 | sys32_sigaltstack_wrapper: | ||
1988 | /* Get the user stack pointer */ | ||
1989 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24 | ||
1990 | LDREG TASK_PT_GR30(%r24),%r24 | ||
1991 | STREG %r2, -RP_OFFSET(%r30) | ||
1992 | ldo FRAME_SIZE(%r30), %r30 | ||
1993 | b,l do_sigaltstack32,%r2 | ||
1994 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1995 | |||
1996 | ldo -FRAME_SIZE(%r30), %r30 | ||
1997 | LDREG -RP_OFFSET(%r30), %r2 | ||
1998 | bv %r0(%r2) | ||
1999 | nop | ||
2000 | #endif | ||
2001 | |||
2002 | .export sys_rt_sigsuspend_wrapper | ||
2003 | sys_rt_sigsuspend_wrapper: | ||
2004 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 | ||
2005 | ldo TASK_REGS(%r1),%r24 | ||
2006 | reg_save %r24 | ||
2007 | |||
2008 | STREG %r2, -RP_OFFSET(%r30) | ||
2009 | #ifdef __LP64__ | ||
2010 | ldo FRAME_SIZE(%r30), %r30 | ||
2011 | b,l sys_rt_sigsuspend,%r2 | ||
2012 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
2013 | #else | ||
2014 | bl sys_rt_sigsuspend,%r2 | ||
2015 | ldo FRAME_SIZE(%r30), %r30 | ||
2016 | #endif | ||
2017 | |||
2018 | ldo -FRAME_SIZE(%r30), %r30 | ||
2019 | LDREG -RP_OFFSET(%r30), %r2 | ||
2020 | |||
2021 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 | ||
2022 | ldo TASK_REGS(%r1),%r1 | ||
2023 | reg_restore %r1 | ||
2024 | |||
2025 | bv %r0(%r2) | ||
2026 | nop | ||
2027 | |||
2028 | .export syscall_exit | ||
2029 | syscall_exit: | ||
2030 | |||
2031 | /* NOTE: HP-UX syscalls also come through here | ||
2032 | * after hpux_syscall_exit fixes up return | ||
2033 | * values. */ | ||
2034 | |||
2035 | /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit | ||
2036 | * via syscall_exit_rfi if the signal was received while the process | ||
2037 | * was running. | ||
2038 | */ | ||
2039 | |||
2040 | /* save return value now */ | ||
2041 | |||
2042 | mfctl %cr30, %r1 | ||
2043 | LDREG TI_TASK(%r1),%r1 | ||
2044 | STREG %r28,TASK_PT_GR28(%r1) | ||
2045 | |||
2046 | #ifdef CONFIG_HPUX | ||
2047 | |||
2048 | /* <linux/personality.h> cannot be easily included */ | ||
2049 | #define PER_HPUX 0x10 | ||
2050 | LDREG TASK_PERSONALITY(%r1),%r19 | ||
2051 | |||
2052 | /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */ | ||
2053 | ldo -PER_HPUX(%r19), %r19 | ||
2054 | CMPIB<>,n 0,%r19,1f | ||
2055 | |||
2056 | /* Save other hpux returns if personality is PER_HPUX */ | ||
2057 | STREG %r22,TASK_PT_GR22(%r1) | ||
2058 | STREG %r29,TASK_PT_GR29(%r1) | ||
2059 | 1: | ||
2060 | |||
2061 | #endif /* CONFIG_HPUX */ | ||
2062 | |||
2063 | /* Seems to me that dp could be wrong here, if the syscall involved | ||
2064 | * calling a module, and nothing got round to restoring dp on return. | ||
2065 | */ | ||
2066 | loadgp | ||
2067 | |||
2068 | syscall_check_bh: | ||
2069 | |||
2070 | /* Check for software interrupts */ | ||
2071 | |||
2072 | .import irq_stat,data | ||
2073 | |||
2074 | load32 irq_stat,%r19 | ||
2075 | |||
2076 | #ifdef CONFIG_SMP | ||
2077 | /* sched.h: int processor */ | ||
2078 | /* %r26 is used as scratch register to index into irq_stat[] */ | ||
2079 | ldw TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */ | ||
2080 | |||
2081 | /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */ | ||
2082 | #ifdef __LP64__ | ||
2083 | shld %r26, 6, %r20 | ||
2084 | #else | ||
2085 | shlw %r26, 5, %r20 | ||
2086 | #endif | ||
2087 | add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */ | ||
2088 | #endif /* CONFIG_SMP */ | ||
2089 | |||
2090 | LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */ | ||
2091 | cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */ | ||
2092 | |||
2093 | syscall_check_resched: | ||
2094 | |||
2095 | /* check for reschedule */ | ||
2096 | |||
2097 | LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */ | ||
2098 | bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */ | ||
2099 | |||
2100 | syscall_check_sig: | ||
2101 | LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* get ti flags */ | ||
2102 | bb,<,n %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */ | ||
2103 | |||
2104 | syscall_restore: | ||
2105 | /* Are we being ptraced? */ | ||
2106 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
2107 | |||
2108 | LDREG TASK_PTRACE(%r1), %r19 | ||
2109 | bb,< %r19,31,syscall_restore_rfi | ||
2110 | nop | ||
2111 | |||
2112 | ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */ | ||
2113 | rest_fp %r19 | ||
2114 | |||
2115 | LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */ | ||
2116 | mtsar %r19 | ||
2117 | |||
2118 | LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */ | ||
2119 | LDREG TASK_PT_GR19(%r1),%r19 | ||
2120 | LDREG TASK_PT_GR20(%r1),%r20 | ||
2121 | LDREG TASK_PT_GR21(%r1),%r21 | ||
2122 | LDREG TASK_PT_GR22(%r1),%r22 | ||
2123 | LDREG TASK_PT_GR23(%r1),%r23 | ||
2124 | LDREG TASK_PT_GR24(%r1),%r24 | ||
2125 | LDREG TASK_PT_GR25(%r1),%r25 | ||
2126 | LDREG TASK_PT_GR26(%r1),%r26 | ||
2127 | LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */ | ||
2128 | LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */ | ||
2129 | LDREG TASK_PT_GR29(%r1),%r29 | ||
2130 | LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */ | ||
2131 | |||
2132 | /* NOTE: We use rsm/ssm pair to make this operation atomic */ | ||
2133 | rsm PSW_SM_I, %r0 | ||
2134 | LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */ | ||
2135 | mfsp %sr3,%r1 /* Get users space id */ | ||
2136 | mtsp %r1,%sr7 /* Restore sr7 */ | ||
2137 | ssm PSW_SM_I, %r0 | ||
2138 | |||
2139 | /* Set sr2 to zero for userspace syscalls to work. */ | ||
2140 | mtsp %r0,%sr2 | ||
2141 | mtsp %r1,%sr4 /* Restore sr4 */ | ||
2142 | mtsp %r1,%sr5 /* Restore sr5 */ | ||
2143 | mtsp %r1,%sr6 /* Restore sr6 */ | ||
2144 | |||
2145 | depi 3,31,2,%r31 /* ensure return to user mode. */ | ||
2146 | |||
2147 | #ifdef __LP64__ | ||
2148 | /* decide whether to reset the wide mode bit | ||
2149 | * | ||
2150 | * For a syscall, the W bit is stored in the lowest bit | ||
2151 | * of sp. Extract it and reset W if it is zero */ | ||
2152 | extrd,u,*<> %r30,63,1,%r1 | ||
2153 | rsm PSW_SM_W, %r0 | ||
2154 | /* now reset the lowest bit of sp if it was set */ | ||
2155 | xor %r30,%r1,%r30 | ||
2156 | #endif | ||
2157 | be,n 0(%sr3,%r31) /* return to user space */ | ||
2158 | |||
2159 | /* We have to return via an RFI, so that PSW T and R bits can be set | ||
2160 | * appropriately. | ||
2161 | * This sets up pt_regs so we can return via intr_restore, which is not | ||
2162 | * the most efficient way of doing things, but it works. | ||
2163 | */ | ||
2164 | syscall_restore_rfi: | ||
2165 | ldo -1(%r0),%r2 /* Set recovery cntr to -1 */ | ||
2166 | mtctl %r2,%cr0 /* for immediate trap */ | ||
2167 | LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */ | ||
2168 | ldi 0x0b,%r20 /* Create new PSW */ | ||
2169 | depi -1,13,1,%r20 /* C, Q, D, and I bits */ | ||
2170 | |||
2171 | /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are | ||
2172 | * set in include/linux/ptrace.h and converted to PA bitmap | ||
2173 | * numbers in asm-offsets.c */ | ||
2174 | |||
2175 | /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */ | ||
2176 | extru,= %r19,PA_SINGLESTEP_BIT,1,%r0 | ||
2177 | depi -1,27,1,%r20 /* R bit */ | ||
2178 | |||
2179 | /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */ | ||
2180 | extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0 | ||
2181 | depi -1,7,1,%r20 /* T bit */ | ||
2182 | |||
2183 | STREG %r20,TASK_PT_PSW(%r1) | ||
2184 | |||
2185 | /* Always store space registers, since sr3 can be changed (e.g. fork) */ | ||
2186 | |||
2187 | mfsp %sr3,%r25 | ||
2188 | STREG %r25,TASK_PT_SR3(%r1) | ||
2189 | STREG %r25,TASK_PT_SR4(%r1) | ||
2190 | STREG %r25,TASK_PT_SR5(%r1) | ||
2191 | STREG %r25,TASK_PT_SR6(%r1) | ||
2192 | STREG %r25,TASK_PT_SR7(%r1) | ||
2193 | STREG %r25,TASK_PT_IASQ0(%r1) | ||
2194 | STREG %r25,TASK_PT_IASQ1(%r1) | ||
2195 | |||
2196 | /* XXX W bit??? */ | ||
2197 | /* Now if old D bit is clear, it means we didn't save all registers | ||
2198 | * on syscall entry, so do that now. This only happens on TRACEME | ||
2199 | * calls, or if someone attached to us while we were on a syscall. | ||
2200 | * We could make this more efficient by not saving r3-r18, but | ||
2201 | * then we wouldn't be able to use the common intr_restore path. | ||
2202 | * It is only for traced processes anyway, so performance is not | ||
2203 | * an issue. | ||
2204 | */ | ||
2205 | bb,< %r2,30,pt_regs_ok /* Branch if D set */ | ||
2206 | ldo TASK_REGS(%r1),%r25 | ||
2207 | reg_save %r25 /* Save r3 to r18 */ | ||
2208 | |||
2209 | /* Save the current sr */ | ||
2210 | mfsp %sr0,%r2 | ||
2211 | STREG %r2,TASK_PT_SR0(%r1) | ||
2212 | |||
2213 | /* Save the scratch sr */ | ||
2214 | mfsp %sr1,%r2 | ||
2215 | STREG %r2,TASK_PT_SR1(%r1) | ||
2216 | |||
2217 | /* sr2 should be set to zero for userspace syscalls */ | ||
2218 | STREG %r0,TASK_PT_SR2(%r1) | ||
2219 | |||
2220 | pt_regs_ok: | ||
2221 | LDREG TASK_PT_GR31(%r1),%r2 | ||
2222 | depi 3,31,2,%r2 /* ensure return to user mode. */ | ||
2223 | STREG %r2,TASK_PT_IAOQ0(%r1) | ||
2224 | ldo 4(%r2),%r2 | ||
2225 | STREG %r2,TASK_PT_IAOQ1(%r1) | ||
2226 | copy %r25,%r16 | ||
2227 | b intr_restore | ||
2228 | nop | ||
2229 | |||
2230 | .import do_softirq,code | ||
2231 | syscall_do_softirq: | ||
2232 | bl do_softirq,%r2 | ||
2233 | nop | ||
2234 | /* NOTE: We enable I-bit incase we schedule later, | ||
2235 | * and we might be going back to userspace if we were | ||
2236 | * traced. */ | ||
2237 | b syscall_check_resched | ||
2238 | ssm PSW_SM_I, %r0 /* do_softirq returns with I bit off */ | ||
2239 | |||
2240 | .import schedule,code | ||
2241 | syscall_do_resched: | ||
2242 | BL schedule,%r2 | ||
2243 | #ifdef __LP64__ | ||
2244 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
2245 | #else | ||
2246 | nop | ||
2247 | #endif | ||
2248 | b syscall_check_bh /* if resched, we start over again */ | ||
2249 | nop | ||
2250 | |||
2251 | .import do_signal,code | ||
2252 | syscall_do_signal: | ||
2253 | /* Save callee-save registers (for sigcontext). | ||
2254 | FIXME: After this point the process structure should be | ||
2255 | consistent with all the relevant state of the process | ||
2256 | before the syscall. We need to verify this. */ | ||
2257 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
2258 | ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */ | ||
2259 | reg_save %r25 | ||
2260 | |||
2261 | ldi 1, %r24 /* unsigned long in_syscall */ | ||
2262 | |||
2263 | #ifdef __LP64__ | ||
2264 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
2265 | #endif | ||
2266 | BL do_signal,%r2 | ||
2267 | copy %r0, %r26 /* sigset_t *oldset = NULL */ | ||
2268 | |||
2269 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
2270 | ldo TASK_REGS(%r1), %r20 /* reload pt_regs */ | ||
2271 | reg_restore %r20 | ||
2272 | |||
2273 | b,n syscall_check_sig | ||
2274 | |||
2275 | /* | ||
2276 | * get_register is used by the non access tlb miss handlers to | ||
2277 | * copy the value of the general register specified in r8 into | ||
2278 | * r1. This routine can't be used for shadowed registers, since | ||
2279 | * the rfir will restore the original value. So, for the shadowed | ||
2280 | * registers we put a -1 into r1 to indicate that the register | ||
2281 | * should not be used (the register being copied could also have | ||
2282 | * a -1 in it, but that is OK, it just means that we will have | ||
2283 | * to use the slow path instead). | ||
2284 | */ | ||
2285 | |||
2286 | get_register: | ||
2287 | blr %r8,%r0 | ||
2288 | nop | ||
2289 | bv %r0(%r25) /* r0 */ | ||
2290 | copy %r0,%r1 | ||
2291 | bv %r0(%r25) /* r1 - shadowed */ | ||
2292 | ldi -1,%r1 | ||
2293 | bv %r0(%r25) /* r2 */ | ||
2294 | copy %r2,%r1 | ||
2295 | bv %r0(%r25) /* r3 */ | ||
2296 | copy %r3,%r1 | ||
2297 | bv %r0(%r25) /* r4 */ | ||
2298 | copy %r4,%r1 | ||
2299 | bv %r0(%r25) /* r5 */ | ||
2300 | copy %r5,%r1 | ||
2301 | bv %r0(%r25) /* r6 */ | ||
2302 | copy %r6,%r1 | ||
2303 | bv %r0(%r25) /* r7 */ | ||
2304 | copy %r7,%r1 | ||
2305 | bv %r0(%r25) /* r8 - shadowed */ | ||
2306 | ldi -1,%r1 | ||
2307 | bv %r0(%r25) /* r9 - shadowed */ | ||
2308 | ldi -1,%r1 | ||
2309 | bv %r0(%r25) /* r10 */ | ||
2310 | copy %r10,%r1 | ||
2311 | bv %r0(%r25) /* r11 */ | ||
2312 | copy %r11,%r1 | ||
2313 | bv %r0(%r25) /* r12 */ | ||
2314 | copy %r12,%r1 | ||
2315 | bv %r0(%r25) /* r13 */ | ||
2316 | copy %r13,%r1 | ||
2317 | bv %r0(%r25) /* r14 */ | ||
2318 | copy %r14,%r1 | ||
2319 | bv %r0(%r25) /* r15 */ | ||
2320 | copy %r15,%r1 | ||
2321 | bv %r0(%r25) /* r16 - shadowed */ | ||
2322 | ldi -1,%r1 | ||
2323 | bv %r0(%r25) /* r17 - shadowed */ | ||
2324 | ldi -1,%r1 | ||
2325 | bv %r0(%r25) /* r18 */ | ||
2326 | copy %r18,%r1 | ||
2327 | bv %r0(%r25) /* r19 */ | ||
2328 | copy %r19,%r1 | ||
2329 | bv %r0(%r25) /* r20 */ | ||
2330 | copy %r20,%r1 | ||
2331 | bv %r0(%r25) /* r21 */ | ||
2332 | copy %r21,%r1 | ||
2333 | bv %r0(%r25) /* r22 */ | ||
2334 | copy %r22,%r1 | ||
2335 | bv %r0(%r25) /* r23 */ | ||
2336 | copy %r23,%r1 | ||
2337 | bv %r0(%r25) /* r24 - shadowed */ | ||
2338 | ldi -1,%r1 | ||
2339 | bv %r0(%r25) /* r25 - shadowed */ | ||
2340 | ldi -1,%r1 | ||
2341 | bv %r0(%r25) /* r26 */ | ||
2342 | copy %r26,%r1 | ||
2343 | bv %r0(%r25) /* r27 */ | ||
2344 | copy %r27,%r1 | ||
2345 | bv %r0(%r25) /* r28 */ | ||
2346 | copy %r28,%r1 | ||
2347 | bv %r0(%r25) /* r29 */ | ||
2348 | copy %r29,%r1 | ||
2349 | bv %r0(%r25) /* r30 */ | ||
2350 | copy %r30,%r1 | ||
2351 | bv %r0(%r25) /* r31 */ | ||
2352 | copy %r31,%r1 | ||
2353 | |||
2354 | /* | ||
2355 | * set_register is used by the non access tlb miss handlers to | ||
2356 | * copy the value of r1 into the general register specified in | ||
2357 | * r8. | ||
2358 | */ | ||
2359 | |||
2360 | set_register: | ||
2361 | blr %r8,%r0 | ||
2362 | nop | ||
2363 | bv %r0(%r25) /* r0 (silly, but it is a place holder) */ | ||
2364 | copy %r1,%r0 | ||
2365 | bv %r0(%r25) /* r1 */ | ||
2366 | copy %r1,%r1 | ||
2367 | bv %r0(%r25) /* r2 */ | ||
2368 | copy %r1,%r2 | ||
2369 | bv %r0(%r25) /* r3 */ | ||
2370 | copy %r1,%r3 | ||
2371 | bv %r0(%r25) /* r4 */ | ||
2372 | copy %r1,%r4 | ||
2373 | bv %r0(%r25) /* r5 */ | ||
2374 | copy %r1,%r5 | ||
2375 | bv %r0(%r25) /* r6 */ | ||
2376 | copy %r1,%r6 | ||
2377 | bv %r0(%r25) /* r7 */ | ||
2378 | copy %r1,%r7 | ||
2379 | bv %r0(%r25) /* r8 */ | ||
2380 | copy %r1,%r8 | ||
2381 | bv %r0(%r25) /* r9 */ | ||
2382 | copy %r1,%r9 | ||
2383 | bv %r0(%r25) /* r10 */ | ||
2384 | copy %r1,%r10 | ||
2385 | bv %r0(%r25) /* r11 */ | ||
2386 | copy %r1,%r11 | ||
2387 | bv %r0(%r25) /* r12 */ | ||
2388 | copy %r1,%r12 | ||
2389 | bv %r0(%r25) /* r13 */ | ||
2390 | copy %r1,%r13 | ||
2391 | bv %r0(%r25) /* r14 */ | ||
2392 | copy %r1,%r14 | ||
2393 | bv %r0(%r25) /* r15 */ | ||
2394 | copy %r1,%r15 | ||
2395 | bv %r0(%r25) /* r16 */ | ||
2396 | copy %r1,%r16 | ||
2397 | bv %r0(%r25) /* r17 */ | ||
2398 | copy %r1,%r17 | ||
2399 | bv %r0(%r25) /* r18 */ | ||
2400 | copy %r1,%r18 | ||
2401 | bv %r0(%r25) /* r19 */ | ||
2402 | copy %r1,%r19 | ||
2403 | bv %r0(%r25) /* r20 */ | ||
2404 | copy %r1,%r20 | ||
2405 | bv %r0(%r25) /* r21 */ | ||
2406 | copy %r1,%r21 | ||
2407 | bv %r0(%r25) /* r22 */ | ||
2408 | copy %r1,%r22 | ||
2409 | bv %r0(%r25) /* r23 */ | ||
2410 | copy %r1,%r23 | ||
2411 | bv %r0(%r25) /* r24 */ | ||
2412 | copy %r1,%r24 | ||
2413 | bv %r0(%r25) /* r25 */ | ||
2414 | copy %r1,%r25 | ||
2415 | bv %r0(%r25) /* r26 */ | ||
2416 | copy %r1,%r26 | ||
2417 | bv %r0(%r25) /* r27 */ | ||
2418 | copy %r1,%r27 | ||
2419 | bv %r0(%r25) /* r28 */ | ||
2420 | copy %r1,%r28 | ||
2421 | bv %r0(%r25) /* r29 */ | ||
2422 | copy %r1,%r29 | ||
2423 | bv %r0(%r25) /* r30 */ | ||
2424 | copy %r1,%r30 | ||
2425 | bv %r0(%r25) /* r31 */ | ||
2426 | copy %r1,%r31 | ||
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c new file mode 100644 index 000000000000..f244fb200db1 --- /dev/null +++ b/arch/parisc/kernel/firmware.c | |||
@@ -0,0 +1,1405 @@ | |||
1 | /* | ||
2 | * arch/parisc/kernel/firmware.c - safe PDC access routines | ||
3 | * | ||
4 | * PDC == Processor Dependent Code | ||
5 | * | ||
6 | * See http://www.parisc-linux.org/documentation/index.html | ||
7 | * for documentation describing the entry points and calling | ||
8 | * conventions defined below. | ||
9 | * | ||
10 | * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org) | ||
11 | * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy) | ||
12 | * Copyright 2003 Grant Grundler <grundler parisc-linux org> | ||
13 | * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org> | ||
14 | * Copyright 2004 Thibaut VARENE <varenet@parisc-linux.org> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | /* I think it would be in everyone's best interest to follow this | ||
24 | * guidelines when writing PDC wrappers: | ||
25 | * | ||
26 | * - the name of the pdc wrapper should match one of the macros | ||
27 | * used for the first two arguments | ||
28 | * - don't use caps for random parts of the name | ||
29 | * - use the static PDC result buffers and "copyout" to structs | ||
30 | * supplied by the caller to encapsulate alignment restrictions | ||
31 | * - hold pdc_lock while in PDC or using static result buffers | ||
32 | * - use __pa() to convert virtual (kernel) pointers to physical | ||
33 | * ones. | ||
34 | * - the name of the struct used for pdc return values should equal | ||
35 | * one of the macros used for the first two arguments to the | ||
36 | * corresponding PDC call | ||
37 | * - keep the order of arguments | ||
38 | * - don't be smart (setting trailing NUL bytes for strings, return | ||
39 | * something useful even if the call failed) unless you are sure | ||
40 | * it's not going to affect functionality or performance | ||
41 | * | ||
42 | * Example: | ||
43 | * int pdc_cache_info(struct pdc_cache_info *cache_info ) | ||
44 | * { | ||
45 | * int retval; | ||
46 | * | ||
47 | * spin_lock_irq(&pdc_lock); | ||
48 | * retval = mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0); | ||
49 | * convert_to_wide(pdc_result); | ||
50 | * memcpy(cache_info, pdc_result, sizeof(*cache_info)); | ||
51 | * spin_unlock_irq(&pdc_lock); | ||
52 | * | ||
53 | * return retval; | ||
54 | * } | ||
55 | * prumpf 991016 | ||
56 | */ | ||
57 | |||
58 | #include <stdarg.h> | ||
59 | |||
60 | #include <linux/delay.h> | ||
61 | #include <linux/init.h> | ||
62 | #include <linux/kernel.h> | ||
63 | #include <linux/module.h> | ||
64 | #include <linux/string.h> | ||
65 | #include <linux/spinlock.h> | ||
66 | |||
67 | #include <asm/page.h> | ||
68 | #include <asm/pdc.h> | ||
69 | #include <asm/pdcpat.h> | ||
70 | #include <asm/system.h> | ||
71 | #include <asm/processor.h> /* for boot_cpu_data */ | ||
72 | |||
73 | static DEFINE_SPINLOCK(pdc_lock); | ||
74 | static unsigned long pdc_result[32] __attribute__ ((aligned (8))); | ||
75 | static unsigned long pdc_result2[32] __attribute__ ((aligned (8))); | ||
76 | |||
77 | #ifdef __LP64__ | ||
78 | #define WIDE_FIRMWARE 0x1 | ||
79 | #define NARROW_FIRMWARE 0x2 | ||
80 | |||
81 | /* Firmware needs to be initially set to narrow to determine the | ||
82 | * actual firmware width. */ | ||
83 | int parisc_narrow_firmware = 1; | ||
84 | #endif | ||
85 | |||
86 | /* on all currently-supported platforms, IODC I/O calls are always | ||
87 | * 32-bit calls, and MEM_PDC calls are always the same width as the OS. | ||
88 | * This means Cxxx boxes can't run wide kernels right now. -PB | ||
89 | * | ||
90 | * CONFIG_PDC_NARROW has been added to allow 64-bit kernels to run on | ||
91 | * systems with 32-bit MEM_PDC calls. This will allow wide kernels to | ||
92 | * run on Cxxx boxes now. -RB | ||
93 | * | ||
94 | * Note that some PAT boxes may have 64-bit IODC I/O... | ||
95 | */ | ||
96 | |||
97 | #ifdef __LP64__ | ||
98 | long real64_call(unsigned long function, ...); | ||
99 | #endif | ||
100 | long real32_call(unsigned long function, ...); | ||
101 | |||
102 | #ifdef __LP64__ | ||
103 | # define MEM_PDC (unsigned long)(PAGE0->mem_pdc_hi) << 32 | PAGE0->mem_pdc | ||
104 | # define mem_pdc_call(args...) unlikely(parisc_narrow_firmware) ? real32_call(MEM_PDC, args) : real64_call(MEM_PDC, args) | ||
105 | #else | ||
106 | # define MEM_PDC (unsigned long)PAGE0->mem_pdc | ||
107 | # define mem_pdc_call(args...) real32_call(MEM_PDC, args) | ||
108 | #endif | ||
109 | |||
110 | |||
111 | /** | ||
112 | * f_extend - Convert PDC addresses to kernel addresses. | ||
113 | * @address: Address returned from PDC. | ||
114 | * | ||
115 | * This function is used to convert PDC addresses into kernel addresses | ||
116 | * when the PDC address size and kernel address size are different. | ||
117 | */ | ||
118 | static unsigned long f_extend(unsigned long address) | ||
119 | { | ||
120 | #ifdef __LP64__ | ||
121 | if(unlikely(parisc_narrow_firmware)) { | ||
122 | if((address & 0xff000000) == 0xf0000000) | ||
123 | return 0xf0f0f0f000000000UL | (u32)address; | ||
124 | |||
125 | if((address & 0xf0000000) == 0xf0000000) | ||
126 | return 0xffffffff00000000UL | (u32)address; | ||
127 | } | ||
128 | #endif | ||
129 | return address; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * convert_to_wide - Convert the return buffer addresses into kernel addresses. | ||
134 | * @address: The return buffer from PDC. | ||
135 | * | ||
136 | * This function is used to convert the return buffer addresses retrieved from PDC | ||
137 | * into kernel addresses when the PDC address size and kernel address size are | ||
138 | * different. | ||
139 | */ | ||
140 | static void convert_to_wide(unsigned long *addr) | ||
141 | { | ||
142 | #ifdef __LP64__ | ||
143 | int i; | ||
144 | unsigned int *p = (unsigned int *)addr; | ||
145 | |||
146 | if(unlikely(parisc_narrow_firmware)) { | ||
147 | for(i = 31; i >= 0; --i) | ||
148 | addr[i] = p[i]; | ||
149 | } | ||
150 | #endif | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * set_firmware_width - Determine if the firmware is wide or narrow. | ||
155 | * | ||
156 | * This function must be called before any pdc_* function that uses the convert_to_wide | ||
157 | * function. | ||
158 | */ | ||
159 | void __init set_firmware_width(void) | ||
160 | { | ||
161 | #ifdef __LP64__ | ||
162 | int retval; | ||
163 | |||
164 | spin_lock_irq(&pdc_lock); | ||
165 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); | ||
166 | convert_to_wide(pdc_result); | ||
167 | if(pdc_result[0] != NARROW_FIRMWARE) | ||
168 | parisc_narrow_firmware = 0; | ||
169 | spin_unlock_irq(&pdc_lock); | ||
170 | #endif | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * pdc_emergency_unlock - Unlock the linux pdc lock | ||
175 | * | ||
176 | * This call unlocks the linux pdc lock in case we need some PDC functions | ||
177 | * (like pdc_add_valid) during kernel stack dump. | ||
178 | */ | ||
179 | void pdc_emergency_unlock(void) | ||
180 | { | ||
181 | /* Spinlock DEBUG code freaks out if we unconditionally unlock */ | ||
182 | if (spin_is_locked(&pdc_lock)) | ||
183 | spin_unlock(&pdc_lock); | ||
184 | } | ||
185 | |||
186 | |||
187 | /** | ||
188 | * pdc_add_valid - Verify address can be accessed without causing a HPMC. | ||
189 | * @address: Address to be verified. | ||
190 | * | ||
191 | * This PDC call attempts to read from the specified address and verifies | ||
192 | * if the address is valid. | ||
193 | * | ||
194 | * The return value is PDC_OK (0) in case accessing this address is valid. | ||
195 | */ | ||
196 | int pdc_add_valid(unsigned long address) | ||
197 | { | ||
198 | int retval; | ||
199 | |||
200 | spin_lock_irq(&pdc_lock); | ||
201 | retval = mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, address); | ||
202 | spin_unlock_irq(&pdc_lock); | ||
203 | |||
204 | return retval; | ||
205 | } | ||
206 | EXPORT_SYMBOL(pdc_add_valid); | ||
207 | |||
208 | /** | ||
209 | * pdc_chassis_info - Return chassis information. | ||
210 | * @result: The return buffer. | ||
211 | * @chassis_info: The memory buffer address. | ||
212 | * @len: The size of the memory buffer address. | ||
213 | * | ||
214 | * An HVERSION dependent call for returning the chassis information. | ||
215 | */ | ||
216 | int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len) | ||
217 | { | ||
218 | int retval; | ||
219 | |||
220 | spin_lock_irq(&pdc_lock); | ||
221 | memcpy(&pdc_result, chassis_info, sizeof(*chassis_info)); | ||
222 | memcpy(&pdc_result2, led_info, len); | ||
223 | retval = mem_pdc_call(PDC_CHASSIS, PDC_RETURN_CHASSIS_INFO, | ||
224 | __pa(pdc_result), __pa(pdc_result2), len); | ||
225 | memcpy(chassis_info, pdc_result, sizeof(*chassis_info)); | ||
226 | memcpy(led_info, pdc_result2, len); | ||
227 | spin_unlock_irq(&pdc_lock); | ||
228 | |||
229 | return retval; | ||
230 | } | ||
231 | |||
232 | /** | ||
233 | * pdc_pat_chassis_send_log - Sends a PDC PAT CHASSIS log message. | ||
234 | * @retval: -1 on error, 0 on success. Other value are PDC errors | ||
235 | * | ||
236 | * Must be correctly formatted or expect system crash | ||
237 | */ | ||
238 | #ifdef __LP64__ | ||
239 | int pdc_pat_chassis_send_log(unsigned long state, unsigned long data) | ||
240 | { | ||
241 | int retval = 0; | ||
242 | |||
243 | if (!is_pdc_pat()) | ||
244 | return -1; | ||
245 | |||
246 | spin_lock_irq(&pdc_lock); | ||
247 | retval = mem_pdc_call(PDC_PAT_CHASSIS_LOG, PDC_PAT_CHASSIS_WRITE_LOG, __pa(&state), __pa(&data)); | ||
248 | spin_unlock_irq(&pdc_lock); | ||
249 | |||
250 | return retval; | ||
251 | } | ||
252 | #endif | ||
253 | |||
254 | /** | ||
255 | * pdc_chassis_disp - Updates display | ||
256 | * @retval: -1 on error, 0 on success | ||
257 | * | ||
258 | * Works on old PDC only (E class, others?) | ||
259 | */ | ||
260 | int pdc_chassis_disp(unsigned long disp) | ||
261 | { | ||
262 | int retval = 0; | ||
263 | |||
264 | spin_lock_irq(&pdc_lock); | ||
265 | retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp); | ||
266 | spin_unlock_irq(&pdc_lock); | ||
267 | |||
268 | return retval; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * pdc_coproc_cfg - To identify coprocessors attached to the processor. | ||
273 | * @pdc_coproc_info: Return buffer address. | ||
274 | * | ||
275 | * This PDC call returns the presence and status of all the coprocessors | ||
276 | * attached to the processor. | ||
277 | */ | ||
278 | int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) | ||
279 | { | ||
280 | int retval; | ||
281 | |||
282 | spin_lock_irq(&pdc_lock); | ||
283 | retval = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result)); | ||
284 | convert_to_wide(pdc_result); | ||
285 | pdc_coproc_info->ccr_functional = pdc_result[0]; | ||
286 | pdc_coproc_info->ccr_present = pdc_result[1]; | ||
287 | pdc_coproc_info->revision = pdc_result[17]; | ||
288 | pdc_coproc_info->model = pdc_result[18]; | ||
289 | spin_unlock_irq(&pdc_lock); | ||
290 | |||
291 | return retval; | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * pdc_iodc_read - Read data from the modules IODC. | ||
296 | * @actcnt: The actual number of bytes. | ||
297 | * @hpa: The HPA of the module for the iodc read. | ||
298 | * @index: The iodc entry point. | ||
299 | * @iodc_data: A buffer memory for the iodc options. | ||
300 | * @iodc_data_size: Size of the memory buffer. | ||
301 | * | ||
302 | * This PDC call reads from the IODC of the module specified by the hpa | ||
303 | * argument. | ||
304 | */ | ||
305 | int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index, | ||
306 | void *iodc_data, unsigned int iodc_data_size) | ||
307 | { | ||
308 | int retval; | ||
309 | |||
310 | spin_lock_irq(&pdc_lock); | ||
311 | retval = mem_pdc_call(PDC_IODC, PDC_IODC_READ, __pa(pdc_result), hpa, | ||
312 | index, __pa(pdc_result2), iodc_data_size); | ||
313 | convert_to_wide(pdc_result); | ||
314 | *actcnt = pdc_result[0]; | ||
315 | memcpy(iodc_data, pdc_result2, iodc_data_size); | ||
316 | spin_unlock_irq(&pdc_lock); | ||
317 | |||
318 | return retval; | ||
319 | } | ||
320 | EXPORT_SYMBOL(pdc_iodc_read); | ||
321 | |||
322 | /** | ||
323 | * pdc_system_map_find_mods - Locate unarchitected modules. | ||
324 | * @pdc_mod_info: Return buffer address. | ||
325 | * @mod_path: pointer to dev path structure. | ||
326 | * @mod_index: fixed address module index. | ||
327 | * | ||
328 | * To locate and identify modules which reside at fixed I/O addresses, which | ||
329 | * do not self-identify via architected bus walks. | ||
330 | */ | ||
331 | int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info, | ||
332 | struct pdc_module_path *mod_path, long mod_index) | ||
333 | { | ||
334 | int retval; | ||
335 | |||
336 | spin_lock_irq(&pdc_lock); | ||
337 | retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result), | ||
338 | __pa(pdc_result2), mod_index); | ||
339 | convert_to_wide(pdc_result); | ||
340 | memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info)); | ||
341 | memcpy(mod_path, pdc_result2, sizeof(*mod_path)); | ||
342 | spin_unlock_irq(&pdc_lock); | ||
343 | |||
344 | pdc_mod_info->mod_addr = f_extend(pdc_mod_info->mod_addr); | ||
345 | return retval; | ||
346 | } | ||
347 | |||
348 | /** | ||
349 | * pdc_system_map_find_addrs - Retrieve additional address ranges. | ||
350 | * @pdc_addr_info: Return buffer address. | ||
351 | * @mod_index: Fixed address module index. | ||
352 | * @addr_index: Address range index. | ||
353 | * | ||
354 | * Retrieve additional information about subsequent address ranges for modules | ||
355 | * with multiple address ranges. | ||
356 | */ | ||
357 | int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info, | ||
358 | long mod_index, long addr_index) | ||
359 | { | ||
360 | int retval; | ||
361 | |||
362 | spin_lock_irq(&pdc_lock); | ||
363 | retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_ADDRESS, __pa(pdc_result), | ||
364 | mod_index, addr_index); | ||
365 | convert_to_wide(pdc_result); | ||
366 | memcpy(pdc_addr_info, pdc_result, sizeof(*pdc_addr_info)); | ||
367 | spin_unlock_irq(&pdc_lock); | ||
368 | |||
369 | pdc_addr_info->mod_addr = f_extend(pdc_addr_info->mod_addr); | ||
370 | return retval; | ||
371 | } | ||
372 | |||
373 | /** | ||
374 | * pdc_model_info - Return model information about the processor. | ||
375 | * @model: The return buffer. | ||
376 | * | ||
377 | * Returns the version numbers, identifiers, and capabilities from the processor module. | ||
378 | */ | ||
379 | int pdc_model_info(struct pdc_model *model) | ||
380 | { | ||
381 | int retval; | ||
382 | |||
383 | spin_lock_irq(&pdc_lock); | ||
384 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_INFO, __pa(pdc_result), 0); | ||
385 | convert_to_wide(pdc_result); | ||
386 | memcpy(model, pdc_result, sizeof(*model)); | ||
387 | spin_unlock_irq(&pdc_lock); | ||
388 | |||
389 | return retval; | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * pdc_model_sysmodel - Get the system model name. | ||
394 | * @name: A char array of at least 81 characters. | ||
395 | * | ||
396 | * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) | ||
397 | */ | ||
398 | int pdc_model_sysmodel(char *name) | ||
399 | { | ||
400 | int retval; | ||
401 | |||
402 | spin_lock_irq(&pdc_lock); | ||
403 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_SYSMODEL, __pa(pdc_result), | ||
404 | OS_ID_HPUX, __pa(name)); | ||
405 | convert_to_wide(pdc_result); | ||
406 | |||
407 | if (retval == PDC_OK) { | ||
408 | name[pdc_result[0]] = '\0'; /* add trailing '\0' */ | ||
409 | } else { | ||
410 | name[0] = 0; | ||
411 | } | ||
412 | spin_unlock_irq(&pdc_lock); | ||
413 | |||
414 | return retval; | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * pdc_model_versions - Identify the version number of each processor. | ||
419 | * @cpu_id: The return buffer. | ||
420 | * @id: The id of the processor to check. | ||
421 | * | ||
422 | * Returns the version number for each processor component. | ||
423 | * | ||
424 | * This comment was here before, but I do not know what it means :( -RB | ||
425 | * id: 0 = cpu revision, 1 = boot-rom-version | ||
426 | */ | ||
427 | int pdc_model_versions(unsigned long *versions, int id) | ||
428 | { | ||
429 | int retval; | ||
430 | |||
431 | spin_lock_irq(&pdc_lock); | ||
432 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_VERSIONS, __pa(pdc_result), id); | ||
433 | convert_to_wide(pdc_result); | ||
434 | *versions = pdc_result[0]; | ||
435 | spin_unlock_irq(&pdc_lock); | ||
436 | |||
437 | return retval; | ||
438 | } | ||
439 | |||
440 | /** | ||
441 | * pdc_model_cpuid - Returns the CPU_ID. | ||
442 | * @cpu_id: The return buffer. | ||
443 | * | ||
444 | * Returns the CPU_ID value which uniquely identifies the cpu portion of | ||
445 | * the processor module. | ||
446 | */ | ||
447 | int pdc_model_cpuid(unsigned long *cpu_id) | ||
448 | { | ||
449 | int retval; | ||
450 | |||
451 | spin_lock_irq(&pdc_lock); | ||
452 | pdc_result[0] = 0; /* preset zero (call may not be implemented!) */ | ||
453 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CPU_ID, __pa(pdc_result), 0); | ||
454 | convert_to_wide(pdc_result); | ||
455 | *cpu_id = pdc_result[0]; | ||
456 | spin_unlock_irq(&pdc_lock); | ||
457 | |||
458 | return retval; | ||
459 | } | ||
460 | |||
461 | /** | ||
462 | * pdc_model_capabilities - Returns the platform capabilities. | ||
463 | * @capabilities: The return buffer. | ||
464 | * | ||
465 | * Returns information about platform support for 32- and/or 64-bit | ||
466 | * OSes, IO-PDIR coherency, and virtual aliasing. | ||
467 | */ | ||
468 | int pdc_model_capabilities(unsigned long *capabilities) | ||
469 | { | ||
470 | int retval; | ||
471 | |||
472 | spin_lock_irq(&pdc_lock); | ||
473 | pdc_result[0] = 0; /* preset zero (call may not be implemented!) */ | ||
474 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); | ||
475 | convert_to_wide(pdc_result); | ||
476 | *capabilities = pdc_result[0]; | ||
477 | spin_unlock_irq(&pdc_lock); | ||
478 | |||
479 | return retval; | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * pdc_cache_info - Return cache and TLB information. | ||
484 | * @cache_info: The return buffer. | ||
485 | * | ||
486 | * Returns information about the processor's cache and TLB. | ||
487 | */ | ||
488 | int pdc_cache_info(struct pdc_cache_info *cache_info) | ||
489 | { | ||
490 | int retval; | ||
491 | |||
492 | spin_lock_irq(&pdc_lock); | ||
493 | retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_INFO, __pa(pdc_result), 0); | ||
494 | convert_to_wide(pdc_result); | ||
495 | memcpy(cache_info, pdc_result, sizeof(*cache_info)); | ||
496 | spin_unlock_irq(&pdc_lock); | ||
497 | |||
498 | return retval; | ||
499 | } | ||
500 | |||
501 | #ifndef CONFIG_PA20 | ||
502 | /** | ||
503 | * pdc_btlb_info - Return block TLB information. | ||
504 | * @btlb: The return buffer. | ||
505 | * | ||
506 | * Returns information about the hardware Block TLB. | ||
507 | */ | ||
508 | int pdc_btlb_info(struct pdc_btlb_info *btlb) | ||
509 | { | ||
510 | int retval; | ||
511 | |||
512 | spin_lock_irq(&pdc_lock); | ||
513 | retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0); | ||
514 | memcpy(btlb, pdc_result, sizeof(*btlb)); | ||
515 | spin_unlock_irq(&pdc_lock); | ||
516 | |||
517 | if(retval < 0) { | ||
518 | btlb->max_size = 0; | ||
519 | } | ||
520 | return retval; | ||
521 | } | ||
522 | |||
523 | /** | ||
524 | * pdc_mem_map_hpa - Find fixed module information. | ||
525 | * @address: The return buffer | ||
526 | * @mod_path: pointer to dev path structure. | ||
527 | * | ||
528 | * This call was developed for S700 workstations to allow the kernel to find | ||
529 | * the I/O devices (Core I/O). In the future (Kittyhawk and beyond) this | ||
530 | * call will be replaced (on workstations) by the architected PDC_SYSTEM_MAP | ||
531 | * call. | ||
532 | * | ||
533 | * This call is supported by all existing S700 workstations (up to Gecko). | ||
534 | */ | ||
535 | int pdc_mem_map_hpa(struct pdc_memory_map *address, | ||
536 | struct pdc_module_path *mod_path) | ||
537 | { | ||
538 | int retval; | ||
539 | |||
540 | spin_lock_irq(&pdc_lock); | ||
541 | memcpy(pdc_result2, mod_path, sizeof(*mod_path)); | ||
542 | retval = mem_pdc_call(PDC_MEM_MAP, PDC_MEM_MAP_HPA, __pa(pdc_result), | ||
543 | __pa(pdc_result2)); | ||
544 | memcpy(address, pdc_result, sizeof(*address)); | ||
545 | spin_unlock_irq(&pdc_lock); | ||
546 | |||
547 | return retval; | ||
548 | } | ||
549 | #endif /* !CONFIG_PA20 */ | ||
550 | |||
551 | /** | ||
552 | * pdc_lan_station_id - Get the LAN address. | ||
553 | * @lan_addr: The return buffer. | ||
554 | * @hpa: The network device HPA. | ||
555 | * | ||
556 | * Get the LAN station address when it is not directly available from the LAN hardware. | ||
557 | */ | ||
558 | int pdc_lan_station_id(char *lan_addr, unsigned long hpa) | ||
559 | { | ||
560 | int retval; | ||
561 | |||
562 | spin_lock_irq(&pdc_lock); | ||
563 | retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ, | ||
564 | __pa(pdc_result), hpa); | ||
565 | if (retval < 0) { | ||
566 | /* FIXME: else read MAC from NVRAM */ | ||
567 | memset(lan_addr, 0, PDC_LAN_STATION_ID_SIZE); | ||
568 | } else { | ||
569 | memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE); | ||
570 | } | ||
571 | spin_unlock_irq(&pdc_lock); | ||
572 | |||
573 | return retval; | ||
574 | } | ||
575 | EXPORT_SYMBOL(pdc_lan_station_id); | ||
576 | |||
577 | /** | ||
578 | * pdc_stable_read - Read data from Stable Storage. | ||
579 | * @staddr: Stable Storage address to access. | ||
580 | * @memaddr: The memory address where Stable Storage data shall be copied. | ||
581 | * @count: number of bytes to transfert. count is multiple of 4. | ||
582 | * | ||
583 | * This PDC call reads from the Stable Storage address supplied in staddr | ||
584 | * and copies count bytes to the memory address memaddr. | ||
585 | * The call will fail if staddr+count > PDC_STABLE size. | ||
586 | */ | ||
587 | int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count) | ||
588 | { | ||
589 | int retval; | ||
590 | |||
591 | spin_lock_irq(&pdc_lock); | ||
592 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_READ, staddr, | ||
593 | __pa(pdc_result), count); | ||
594 | convert_to_wide(pdc_result); | ||
595 | memcpy(memaddr, pdc_result, count); | ||
596 | spin_unlock_irq(&pdc_lock); | ||
597 | |||
598 | return retval; | ||
599 | } | ||
600 | EXPORT_SYMBOL(pdc_stable_read); | ||
601 | |||
602 | /** | ||
603 | * pdc_stable_write - Write data to Stable Storage. | ||
604 | * @staddr: Stable Storage address to access. | ||
605 | * @memaddr: The memory address where Stable Storage data shall be read from. | ||
606 | * @count: number of bytes to transfert. count is multiple of 4. | ||
607 | * | ||
608 | * This PDC call reads count bytes from the supplied memaddr address, | ||
609 | * and copies count bytes to the Stable Storage address staddr. | ||
610 | * The call will fail if staddr+count > PDC_STABLE size. | ||
611 | */ | ||
612 | int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count) | ||
613 | { | ||
614 | int retval; | ||
615 | |||
616 | spin_lock_irq(&pdc_lock); | ||
617 | memcpy(pdc_result, memaddr, count); | ||
618 | convert_to_wide(pdc_result); | ||
619 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_WRITE, staddr, | ||
620 | __pa(pdc_result), count); | ||
621 | spin_unlock_irq(&pdc_lock); | ||
622 | |||
623 | return retval; | ||
624 | } | ||
625 | EXPORT_SYMBOL(pdc_stable_write); | ||
626 | |||
627 | /** | ||
628 | * pdc_stable_get_size - Get Stable Storage size in bytes. | ||
629 | * @size: pointer where the size will be stored. | ||
630 | * | ||
631 | * This PDC call returns the number of bytes in the processor's Stable | ||
632 | * Storage, which is the number of contiguous bytes implemented in Stable | ||
633 | * Storage starting from staddr=0. size in an unsigned 64-bit integer | ||
634 | * which is a multiple of four. | ||
635 | */ | ||
636 | int pdc_stable_get_size(unsigned long *size) | ||
637 | { | ||
638 | int retval; | ||
639 | |||
640 | spin_lock_irq(&pdc_lock); | ||
641 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_RETURN_SIZE, __pa(pdc_result)); | ||
642 | *size = pdc_result[0]; | ||
643 | spin_unlock_irq(&pdc_lock); | ||
644 | |||
645 | return retval; | ||
646 | } | ||
647 | EXPORT_SYMBOL(pdc_stable_get_size); | ||
648 | |||
649 | /** | ||
650 | * pdc_stable_verify_contents - Checks that Stable Storage contents are valid. | ||
651 | * | ||
652 | * This PDC call is meant to be used to check the integrity of the current | ||
653 | * contents of Stable Storage. | ||
654 | */ | ||
655 | int pdc_stable_verify_contents(void) | ||
656 | { | ||
657 | int retval; | ||
658 | |||
659 | spin_lock_irq(&pdc_lock); | ||
660 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_VERIFY_CONTENTS); | ||
661 | spin_unlock_irq(&pdc_lock); | ||
662 | |||
663 | return retval; | ||
664 | } | ||
665 | EXPORT_SYMBOL(pdc_stable_verify_contents); | ||
666 | |||
667 | /** | ||
668 | * pdc_stable_initialize - Sets Stable Storage contents to zero and initialize | ||
669 | * the validity indicator. | ||
670 | * | ||
671 | * This PDC call will erase all contents of Stable Storage. Use with care! | ||
672 | */ | ||
673 | int pdc_stable_initialize(void) | ||
674 | { | ||
675 | int retval; | ||
676 | |||
677 | spin_lock_irq(&pdc_lock); | ||
678 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_INITIALIZE); | ||
679 | spin_unlock_irq(&pdc_lock); | ||
680 | |||
681 | return retval; | ||
682 | } | ||
683 | EXPORT_SYMBOL(pdc_stable_initialize); | ||
684 | |||
685 | /** | ||
686 | * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD) | ||
687 | * @hwpath: fully bc.mod style path to the device. | ||
688 | * @initiator: the array to return the result into | ||
689 | * | ||
690 | * Get the SCSI operational parameters from PDC. | ||
691 | * Needed since HPUX never used BIOS or symbios card NVRAM. | ||
692 | * Most ncr/sym cards won't have an entry and just use whatever | ||
693 | * capabilities of the card are (eg Ultra, LVD). But there are | ||
694 | * several cases where it's useful: | ||
695 | * o set SCSI id for Multi-initiator clusters, | ||
696 | * o cable too long (ie SE scsi 10Mhz won't support 6m length), | ||
697 | * o bus width exported is less than what the interface chip supports. | ||
698 | */ | ||
699 | int pdc_get_initiator(struct hardware_path *hwpath, struct pdc_initiator *initiator) | ||
700 | { | ||
701 | int retval; | ||
702 | |||
703 | spin_lock_irq(&pdc_lock); | ||
704 | |||
705 | /* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */ | ||
706 | #define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \ | ||
707 | strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 8) == 0) | ||
708 | |||
709 | retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR, | ||
710 | __pa(pdc_result), __pa(hwpath)); | ||
711 | if (retval < PDC_OK) | ||
712 | goto out; | ||
713 | |||
714 | if (pdc_result[0] < 16) { | ||
715 | initiator->host_id = pdc_result[0]; | ||
716 | } else { | ||
717 | initiator->host_id = -1; | ||
718 | } | ||
719 | |||
720 | /* | ||
721 | * Sprockets and Piranha return 20 or 40 (MT/s). Prelude returns | ||
722 | * 1, 2, 5 or 10 for 5, 10, 20 or 40 MT/s, respectively | ||
723 | */ | ||
724 | switch (pdc_result[1]) { | ||
725 | case 1: initiator->factor = 50; break; | ||
726 | case 2: initiator->factor = 25; break; | ||
727 | case 5: initiator->factor = 12; break; | ||
728 | case 25: initiator->factor = 10; break; | ||
729 | case 20: initiator->factor = 12; break; | ||
730 | case 40: initiator->factor = 10; break; | ||
731 | default: initiator->factor = -1; break; | ||
732 | } | ||
733 | |||
734 | if (IS_SPROCKETS()) { | ||
735 | initiator->width = pdc_result[4]; | ||
736 | initiator->mode = pdc_result[5]; | ||
737 | } else { | ||
738 | initiator->width = -1; | ||
739 | initiator->mode = -1; | ||
740 | } | ||
741 | |||
742 | out: | ||
743 | spin_unlock_irq(&pdc_lock); | ||
744 | return (retval >= PDC_OK); | ||
745 | } | ||
746 | EXPORT_SYMBOL(pdc_get_initiator); | ||
747 | |||
748 | |||
749 | /** | ||
750 | * pdc_pci_irt_size - Get the number of entries in the interrupt routing table. | ||
751 | * @num_entries: The return value. | ||
752 | * @hpa: The HPA for the device. | ||
753 | * | ||
754 | * This PDC function returns the number of entries in the specified cell's | ||
755 | * interrupt table. | ||
756 | * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes | ||
757 | */ | ||
758 | int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa) | ||
759 | { | ||
760 | int retval; | ||
761 | |||
762 | spin_lock_irq(&pdc_lock); | ||
763 | retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE, | ||
764 | __pa(pdc_result), hpa); | ||
765 | convert_to_wide(pdc_result); | ||
766 | *num_entries = pdc_result[0]; | ||
767 | spin_unlock_irq(&pdc_lock); | ||
768 | |||
769 | return retval; | ||
770 | } | ||
771 | |||
772 | /** | ||
773 | * pdc_pci_irt - Get the PCI interrupt routing table. | ||
774 | * @num_entries: The number of entries in the table. | ||
775 | * @hpa: The Hard Physical Address of the device. | ||
776 | * @tbl: | ||
777 | * | ||
778 | * Get the PCI interrupt routing table for the device at the given HPA. | ||
779 | * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes | ||
780 | */ | ||
781 | int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl) | ||
782 | { | ||
783 | int retval; | ||
784 | |||
785 | BUG_ON((unsigned long)tbl & 0x7); | ||
786 | |||
787 | spin_lock_irq(&pdc_lock); | ||
788 | pdc_result[0] = num_entries; | ||
789 | retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, | ||
790 | __pa(pdc_result), hpa, __pa(tbl)); | ||
791 | spin_unlock_irq(&pdc_lock); | ||
792 | |||
793 | return retval; | ||
794 | } | ||
795 | |||
796 | |||
797 | #if 0 /* UNTEST CODE - left here in case someone needs it */ | ||
798 | |||
799 | /** | ||
800 | * pdc_pci_config_read - read PCI config space. | ||
801 | * @hpa token from PDC to indicate which PCI device | ||
802 | * @pci_addr configuration space address to read from | ||
803 | * | ||
804 | * Read PCI Configuration space *before* linux PCI subsystem is running. | ||
805 | */ | ||
806 | unsigned int pdc_pci_config_read(void *hpa, unsigned long cfg_addr) | ||
807 | { | ||
808 | int retval; | ||
809 | spin_lock_irq(&pdc_lock); | ||
810 | pdc_result[0] = 0; | ||
811 | pdc_result[1] = 0; | ||
812 | retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_READ_CONFIG, | ||
813 | __pa(pdc_result), hpa, cfg_addr&~3UL, 4UL); | ||
814 | spin_unlock_irq(&pdc_lock); | ||
815 | return retval ? ~0 : (unsigned int) pdc_result[0]; | ||
816 | } | ||
817 | |||
818 | |||
819 | /** | ||
820 | * pdc_pci_config_write - read PCI config space. | ||
821 | * @hpa token from PDC to indicate which PCI device | ||
822 | * @pci_addr configuration space address to write | ||
823 | * @val value we want in the 32-bit register | ||
824 | * | ||
825 | * Write PCI Configuration space *before* linux PCI subsystem is running. | ||
826 | */ | ||
827 | void pdc_pci_config_write(void *hpa, unsigned long cfg_addr, unsigned int val) | ||
828 | { | ||
829 | int retval; | ||
830 | spin_lock_irq(&pdc_lock); | ||
831 | pdc_result[0] = 0; | ||
832 | retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_WRITE_CONFIG, | ||
833 | __pa(pdc_result), hpa, | ||
834 | cfg_addr&~3UL, 4UL, (unsigned long) val); | ||
835 | spin_unlock_irq(&pdc_lock); | ||
836 | return retval; | ||
837 | } | ||
838 | #endif /* UNTESTED CODE */ | ||
839 | |||
840 | /** | ||
841 | * pdc_tod_read - Read the Time-Of-Day clock. | ||
842 | * @tod: The return buffer: | ||
843 | * | ||
844 | * Read the Time-Of-Day clock | ||
845 | */ | ||
846 | int pdc_tod_read(struct pdc_tod *tod) | ||
847 | { | ||
848 | int retval; | ||
849 | |||
850 | spin_lock_irq(&pdc_lock); | ||
851 | retval = mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(pdc_result), 0); | ||
852 | convert_to_wide(pdc_result); | ||
853 | memcpy(tod, pdc_result, sizeof(*tod)); | ||
854 | spin_unlock_irq(&pdc_lock); | ||
855 | |||
856 | return retval; | ||
857 | } | ||
858 | EXPORT_SYMBOL(pdc_tod_read); | ||
859 | |||
860 | /** | ||
861 | * pdc_tod_set - Set the Time-Of-Day clock. | ||
862 | * @sec: The number of seconds since epoch. | ||
863 | * @usec: The number of micro seconds. | ||
864 | * | ||
865 | * Set the Time-Of-Day clock. | ||
866 | */ | ||
867 | int pdc_tod_set(unsigned long sec, unsigned long usec) | ||
868 | { | ||
869 | int retval; | ||
870 | |||
871 | spin_lock_irq(&pdc_lock); | ||
872 | retval = mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec); | ||
873 | spin_unlock_irq(&pdc_lock); | ||
874 | |||
875 | return retval; | ||
876 | } | ||
877 | EXPORT_SYMBOL(pdc_tod_set); | ||
878 | |||
879 | #ifdef __LP64__ | ||
880 | int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr, | ||
881 | struct pdc_memory_table *tbl, unsigned long entries) | ||
882 | { | ||
883 | int retval; | ||
884 | |||
885 | spin_lock_irq(&pdc_lock); | ||
886 | retval = mem_pdc_call(PDC_MEM, PDC_MEM_TABLE, __pa(pdc_result), __pa(pdc_result2), entries); | ||
887 | convert_to_wide(pdc_result); | ||
888 | memcpy(r_addr, pdc_result, sizeof(*r_addr)); | ||
889 | memcpy(tbl, pdc_result2, entries * sizeof(*tbl)); | ||
890 | spin_unlock_irq(&pdc_lock); | ||
891 | |||
892 | return retval; | ||
893 | } | ||
894 | #endif /* __LP64__ */ | ||
895 | |||
896 | /* FIXME: Is this pdc used? I could not find type reference to ftc_bitmap | ||
897 | * so I guessed at unsigned long. Someone who knows what this does, can fix | ||
898 | * it later. :) | ||
899 | */ | ||
900 | int pdc_do_firm_test_reset(unsigned long ftc_bitmap) | ||
901 | { | ||
902 | int retval; | ||
903 | |||
904 | spin_lock_irq(&pdc_lock); | ||
905 | retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_FIRM_TEST_RESET, | ||
906 | PDC_FIRM_TEST_MAGIC, ftc_bitmap); | ||
907 | spin_unlock_irq(&pdc_lock); | ||
908 | |||
909 | return retval; | ||
910 | } | ||
911 | |||
912 | /* | ||
913 | * pdc_do_reset - Reset the system. | ||
914 | * | ||
915 | * Reset the system. | ||
916 | */ | ||
917 | int pdc_do_reset(void) | ||
918 | { | ||
919 | int retval; | ||
920 | |||
921 | spin_lock_irq(&pdc_lock); | ||
922 | retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET); | ||
923 | spin_unlock_irq(&pdc_lock); | ||
924 | |||
925 | return retval; | ||
926 | } | ||
927 | |||
928 | /* | ||
929 | * pdc_soft_power_info - Enable soft power switch. | ||
930 | * @power_reg: address of soft power register | ||
931 | * | ||
932 | * Return the absolute address of the soft power switch register | ||
933 | */ | ||
934 | int __init pdc_soft_power_info(unsigned long *power_reg) | ||
935 | { | ||
936 | int retval; | ||
937 | |||
938 | *power_reg = (unsigned long) (-1); | ||
939 | |||
940 | spin_lock_irq(&pdc_lock); | ||
941 | retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0); | ||
942 | if (retval == PDC_OK) { | ||
943 | convert_to_wide(pdc_result); | ||
944 | *power_reg = f_extend(pdc_result[0]); | ||
945 | } | ||
946 | spin_unlock_irq(&pdc_lock); | ||
947 | |||
948 | return retval; | ||
949 | } | ||
950 | |||
951 | /* | ||
952 | * pdc_soft_power_button - Control the soft power button behaviour | ||
953 | * @sw_control: 0 for hardware control, 1 for software control | ||
954 | * | ||
955 | * | ||
956 | * This PDC function places the soft power button under software or | ||
957 | * hardware control. | ||
958 | * Under software control the OS may control to when to allow to shut | ||
959 | * down the system. Under hardware control pressing the power button | ||
960 | * powers off the system immediately. | ||
961 | */ | ||
962 | int pdc_soft_power_button(int sw_control) | ||
963 | { | ||
964 | int retval; | ||
965 | spin_lock_irq(&pdc_lock); | ||
966 | retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control); | ||
967 | spin_unlock_irq(&pdc_lock); | ||
968 | return retval; | ||
969 | } | ||
970 | |||
971 | /* | ||
972 | * pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices. | ||
973 | * Primarily a problem on T600 (which parisc-linux doesn't support) but | ||
974 | * who knows what other platform firmware might do with this OS "hook". | ||
975 | */ | ||
976 | void pdc_io_reset(void) | ||
977 | { | ||
978 | spin_lock_irq(&pdc_lock); | ||
979 | mem_pdc_call(PDC_IO, PDC_IO_RESET, 0); | ||
980 | spin_unlock_irq(&pdc_lock); | ||
981 | } | ||
982 | |||
983 | /* | ||
984 | * pdc_io_reset_devices - Hack to Stop USB controller | ||
985 | * | ||
986 | * If PDC used the usb controller, the usb controller | ||
987 | * is still running and will crash the machines during iommu | ||
988 | * setup, because of still running DMA. This PDC call | ||
989 | * stops the USB controller. | ||
990 | * Normally called after calling pdc_io_reset(). | ||
991 | */ | ||
992 | void pdc_io_reset_devices(void) | ||
993 | { | ||
994 | spin_lock_irq(&pdc_lock); | ||
995 | mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0); | ||
996 | spin_unlock_irq(&pdc_lock); | ||
997 | } | ||
998 | |||
999 | |||
1000 | /** | ||
1001 | * pdc_iodc_putc - Console character print using IODC. | ||
1002 | * @c: the character to output. | ||
1003 | * | ||
1004 | * Note that only these special chars are architected for console IODC io: | ||
1005 | * BEL, BS, CR, and LF. Others are passed through. | ||
1006 | * Since the HP console requires CR+LF to perform a 'newline', we translate | ||
1007 | * "\n" to "\r\n". | ||
1008 | */ | ||
1009 | void pdc_iodc_putc(unsigned char c) | ||
1010 | { | ||
1011 | /* XXX Should we spinlock posx usage */ | ||
1012 | static int posx; /* for simple TAB-Simulation... */ | ||
1013 | static int __attribute__((aligned(8))) iodc_retbuf[32]; | ||
1014 | static char __attribute__((aligned(64))) iodc_dbuf[4096]; | ||
1015 | unsigned int n; | ||
1016 | unsigned int flags; | ||
1017 | |||
1018 | switch (c) { | ||
1019 | case '\n': | ||
1020 | iodc_dbuf[0] = '\r'; | ||
1021 | iodc_dbuf[1] = '\n'; | ||
1022 | n = 2; | ||
1023 | posx = 0; | ||
1024 | break; | ||
1025 | case '\t': | ||
1026 | pdc_iodc_putc(' '); | ||
1027 | while (posx & 7) /* expand TAB */ | ||
1028 | pdc_iodc_putc(' '); | ||
1029 | return; /* return since IODC can't handle this */ | ||
1030 | case '\b': | ||
1031 | posx-=2; /* BS */ | ||
1032 | default: | ||
1033 | iodc_dbuf[0] = c; | ||
1034 | n = 1; | ||
1035 | posx++; | ||
1036 | break; | ||
1037 | } | ||
1038 | |||
1039 | spin_lock_irqsave(&pdc_lock, flags); | ||
1040 | real32_call(PAGE0->mem_cons.iodc_io, | ||
1041 | (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, | ||
1042 | PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), | ||
1043 | __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); | ||
1044 | spin_unlock_irqrestore(&pdc_lock, flags); | ||
1045 | } | ||
1046 | |||
1047 | /** | ||
1048 | * pdc_iodc_outc - Console character print using IODC (without conversions). | ||
1049 | * @c: the character to output. | ||
1050 | * | ||
1051 | * Write the character directly to the IODC console. | ||
1052 | */ | ||
1053 | void pdc_iodc_outc(unsigned char c) | ||
1054 | { | ||
1055 | unsigned int n, flags; | ||
1056 | |||
1057 | /* fill buffer with one caracter and print it */ | ||
1058 | static int __attribute__((aligned(8))) iodc_retbuf[32]; | ||
1059 | static char __attribute__((aligned(64))) iodc_dbuf[4096]; | ||
1060 | |||
1061 | n = 1; | ||
1062 | iodc_dbuf[0] = c; | ||
1063 | |||
1064 | spin_lock_irqsave(&pdc_lock, flags); | ||
1065 | real32_call(PAGE0->mem_cons.iodc_io, | ||
1066 | (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, | ||
1067 | PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), | ||
1068 | __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); | ||
1069 | spin_unlock_irqrestore(&pdc_lock, flags); | ||
1070 | } | ||
1071 | |||
1072 | /** | ||
1073 | * pdc_iodc_getc - Read a character (non-blocking) from the PDC console. | ||
1074 | * | ||
1075 | * Read a character (non-blocking) from the PDC console, returns -1 if | ||
1076 | * key is not present. | ||
1077 | */ | ||
1078 | int pdc_iodc_getc(void) | ||
1079 | { | ||
1080 | unsigned int flags; | ||
1081 | static int __attribute__((aligned(8))) iodc_retbuf[32]; | ||
1082 | static char __attribute__((aligned(64))) iodc_dbuf[4096]; | ||
1083 | int ch; | ||
1084 | int status; | ||
1085 | |||
1086 | /* Bail if no console input device. */ | ||
1087 | if (!PAGE0->mem_kbd.iodc_io) | ||
1088 | return 0; | ||
1089 | |||
1090 | /* wait for a keyboard (rs232)-input */ | ||
1091 | spin_lock_irqsave(&pdc_lock, flags); | ||
1092 | real32_call(PAGE0->mem_kbd.iodc_io, | ||
1093 | (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN, | ||
1094 | PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers), | ||
1095 | __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0); | ||
1096 | |||
1097 | ch = *iodc_dbuf; | ||
1098 | status = *iodc_retbuf; | ||
1099 | spin_unlock_irqrestore(&pdc_lock, flags); | ||
1100 | |||
1101 | if (status == 0) | ||
1102 | return -1; | ||
1103 | |||
1104 | return ch; | ||
1105 | } | ||
1106 | |||
1107 | int pdc_sti_call(unsigned long func, unsigned long flags, | ||
1108 | unsigned long inptr, unsigned long outputr, | ||
1109 | unsigned long glob_cfg) | ||
1110 | { | ||
1111 | int retval; | ||
1112 | |||
1113 | spin_lock_irq(&pdc_lock); | ||
1114 | retval = real32_call(func, flags, inptr, outputr, glob_cfg); | ||
1115 | spin_unlock_irq(&pdc_lock); | ||
1116 | |||
1117 | return retval; | ||
1118 | } | ||
1119 | EXPORT_SYMBOL(pdc_sti_call); | ||
1120 | |||
1121 | #ifdef __LP64__ | ||
1122 | /** | ||
1123 | * pdc_pat_cell_get_number - Returns the cell number. | ||
1124 | * @cell_info: The return buffer. | ||
1125 | * | ||
1126 | * This PDC call returns the cell number of the cell from which the call | ||
1127 | * is made. | ||
1128 | */ | ||
1129 | int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info) | ||
1130 | { | ||
1131 | int retval; | ||
1132 | |||
1133 | spin_lock_irq(&pdc_lock); | ||
1134 | retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_NUMBER, __pa(pdc_result)); | ||
1135 | memcpy(cell_info, pdc_result, sizeof(*cell_info)); | ||
1136 | spin_unlock_irq(&pdc_lock); | ||
1137 | |||
1138 | return retval; | ||
1139 | } | ||
1140 | |||
1141 | /** | ||
1142 | * pdc_pat_cell_module - Retrieve the cell's module information. | ||
1143 | * @actcnt: The number of bytes written to mem_addr. | ||
1144 | * @ploc: The physical location. | ||
1145 | * @mod: The module index. | ||
1146 | * @view_type: The view of the address type. | ||
1147 | * @mem_addr: The return buffer. | ||
1148 | * | ||
1149 | * This PDC call returns information about each module attached to the cell | ||
1150 | * at the specified location. | ||
1151 | */ | ||
1152 | int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, | ||
1153 | unsigned long view_type, void *mem_addr) | ||
1154 | { | ||
1155 | int retval; | ||
1156 | static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8))); | ||
1157 | |||
1158 | spin_lock_irq(&pdc_lock); | ||
1159 | retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result), | ||
1160 | ploc, mod, view_type, __pa(&result)); | ||
1161 | if(!retval) { | ||
1162 | *actcnt = pdc_result[0]; | ||
1163 | memcpy(mem_addr, &result, *actcnt); | ||
1164 | } | ||
1165 | spin_unlock_irq(&pdc_lock); | ||
1166 | |||
1167 | return retval; | ||
1168 | } | ||
1169 | |||
1170 | /** | ||
1171 | * pdc_pat_cpu_get_number - Retrieve the cpu number. | ||
1172 | * @cpu_info: The return buffer. | ||
1173 | * @hpa: The Hard Physical Address of the CPU. | ||
1174 | * | ||
1175 | * Retrieve the cpu number for the cpu at the specified HPA. | ||
1176 | */ | ||
1177 | int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa) | ||
1178 | { | ||
1179 | int retval; | ||
1180 | |||
1181 | spin_lock_irq(&pdc_lock); | ||
1182 | retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER, | ||
1183 | __pa(&pdc_result), hpa); | ||
1184 | memcpy(cpu_info, pdc_result, sizeof(*cpu_info)); | ||
1185 | spin_unlock_irq(&pdc_lock); | ||
1186 | |||
1187 | return retval; | ||
1188 | } | ||
1189 | |||
1190 | /** | ||
1191 | * pdc_pat_get_irt_size - Retrieve the number of entries in the cell's interrupt table. | ||
1192 | * @num_entries: The return value. | ||
1193 | * @cell_num: The target cell. | ||
1194 | * | ||
1195 | * This PDC function returns the number of entries in the specified cell's | ||
1196 | * interrupt table. | ||
1197 | */ | ||
1198 | int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num) | ||
1199 | { | ||
1200 | int retval; | ||
1201 | |||
1202 | spin_lock_irq(&pdc_lock); | ||
1203 | retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE, | ||
1204 | __pa(pdc_result), cell_num); | ||
1205 | *num_entries = pdc_result[0]; | ||
1206 | spin_unlock_irq(&pdc_lock); | ||
1207 | |||
1208 | return retval; | ||
1209 | } | ||
1210 | |||
1211 | /** | ||
1212 | * pdc_pat_get_irt - Retrieve the cell's interrupt table. | ||
1213 | * @r_addr: The return buffer. | ||
1214 | * @cell_num: The target cell. | ||
1215 | * | ||
1216 | * This PDC function returns the actual interrupt table for the specified cell. | ||
1217 | */ | ||
1218 | int pdc_pat_get_irt(void *r_addr, unsigned long cell_num) | ||
1219 | { | ||
1220 | int retval; | ||
1221 | |||
1222 | spin_lock_irq(&pdc_lock); | ||
1223 | retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE, | ||
1224 | __pa(r_addr), cell_num); | ||
1225 | spin_unlock_irq(&pdc_lock); | ||
1226 | |||
1227 | return retval; | ||
1228 | } | ||
1229 | |||
1230 | /** | ||
1231 | * pdc_pat_pd_get_addr_map - Retrieve information about memory address ranges. | ||
1232 | * @actlen: The return buffer. | ||
1233 | * @mem_addr: Pointer to the memory buffer. | ||
1234 | * @count: The number of bytes to read from the buffer. | ||
1235 | * @offset: The offset with respect to the beginning of the buffer. | ||
1236 | * | ||
1237 | */ | ||
1238 | int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, | ||
1239 | unsigned long count, unsigned long offset) | ||
1240 | { | ||
1241 | int retval; | ||
1242 | |||
1243 | spin_lock_irq(&pdc_lock); | ||
1244 | retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_ADDR_MAP, __pa(pdc_result), | ||
1245 | __pa(pdc_result2), count, offset); | ||
1246 | *actual_len = pdc_result[0]; | ||
1247 | memcpy(mem_addr, pdc_result2, *actual_len); | ||
1248 | spin_unlock_irq(&pdc_lock); | ||
1249 | |||
1250 | return retval; | ||
1251 | } | ||
1252 | |||
1253 | /** | ||
1254 | * pdc_pat_io_pci_cfg_read - Read PCI configuration space. | ||
1255 | * @pci_addr: PCI configuration space address for which the read request is being made. | ||
1256 | * @pci_size: Size of read in bytes. Valid values are 1, 2, and 4. | ||
1257 | * @mem_addr: Pointer to return memory buffer. | ||
1258 | * | ||
1259 | */ | ||
1260 | int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr) | ||
1261 | { | ||
1262 | int retval; | ||
1263 | spin_lock_irq(&pdc_lock); | ||
1264 | retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ, | ||
1265 | __pa(pdc_result), pci_addr, pci_size); | ||
1266 | switch(pci_size) { | ||
1267 | case 1: *(u8 *) mem_addr = (u8) pdc_result[0]; | ||
1268 | case 2: *(u16 *)mem_addr = (u16) pdc_result[0]; | ||
1269 | case 4: *(u32 *)mem_addr = (u32) pdc_result[0]; | ||
1270 | } | ||
1271 | spin_unlock_irq(&pdc_lock); | ||
1272 | |||
1273 | return retval; | ||
1274 | } | ||
1275 | |||
1276 | /** | ||
1277 | * pdc_pat_io_pci_cfg_write - Retrieve information about memory address ranges. | ||
1278 | * @pci_addr: PCI configuration space address for which the write request is being made. | ||
1279 | * @pci_size: Size of write in bytes. Valid values are 1, 2, and 4. | ||
1280 | * @value: Pointer to 1, 2, or 4 byte value in low order end of argument to be | ||
1281 | * written to PCI Config space. | ||
1282 | * | ||
1283 | */ | ||
1284 | int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val) | ||
1285 | { | ||
1286 | int retval; | ||
1287 | |||
1288 | spin_lock_irq(&pdc_lock); | ||
1289 | retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_WRITE, | ||
1290 | pci_addr, pci_size, val); | ||
1291 | spin_unlock_irq(&pdc_lock); | ||
1292 | |||
1293 | return retval; | ||
1294 | } | ||
1295 | #endif /* __LP64__ */ | ||
1296 | |||
1297 | |||
1298 | /***************** 32-bit real-mode calls ***********/ | ||
1299 | /* The struct below is used | ||
1300 | * to overlay real_stack (real2.S), preparing a 32-bit call frame. | ||
1301 | * real32_call_asm() then uses this stack in narrow real mode | ||
1302 | */ | ||
1303 | |||
1304 | struct narrow_stack { | ||
1305 | /* use int, not long which is 64 bits */ | ||
1306 | unsigned int arg13; | ||
1307 | unsigned int arg12; | ||
1308 | unsigned int arg11; | ||
1309 | unsigned int arg10; | ||
1310 | unsigned int arg9; | ||
1311 | unsigned int arg8; | ||
1312 | unsigned int arg7; | ||
1313 | unsigned int arg6; | ||
1314 | unsigned int arg5; | ||
1315 | unsigned int arg4; | ||
1316 | unsigned int arg3; | ||
1317 | unsigned int arg2; | ||
1318 | unsigned int arg1; | ||
1319 | unsigned int arg0; | ||
1320 | unsigned int frame_marker[8]; | ||
1321 | unsigned int sp; | ||
1322 | /* in reality, there's nearly 8k of stack after this */ | ||
1323 | }; | ||
1324 | |||
1325 | long real32_call(unsigned long fn, ...) | ||
1326 | { | ||
1327 | va_list args; | ||
1328 | extern struct narrow_stack real_stack; | ||
1329 | extern unsigned long real32_call_asm(unsigned int *, | ||
1330 | unsigned int *, | ||
1331 | unsigned int); | ||
1332 | |||
1333 | va_start(args, fn); | ||
1334 | real_stack.arg0 = va_arg(args, unsigned int); | ||
1335 | real_stack.arg1 = va_arg(args, unsigned int); | ||
1336 | real_stack.arg2 = va_arg(args, unsigned int); | ||
1337 | real_stack.arg3 = va_arg(args, unsigned int); | ||
1338 | real_stack.arg4 = va_arg(args, unsigned int); | ||
1339 | real_stack.arg5 = va_arg(args, unsigned int); | ||
1340 | real_stack.arg6 = va_arg(args, unsigned int); | ||
1341 | real_stack.arg7 = va_arg(args, unsigned int); | ||
1342 | real_stack.arg8 = va_arg(args, unsigned int); | ||
1343 | real_stack.arg9 = va_arg(args, unsigned int); | ||
1344 | real_stack.arg10 = va_arg(args, unsigned int); | ||
1345 | real_stack.arg11 = va_arg(args, unsigned int); | ||
1346 | real_stack.arg12 = va_arg(args, unsigned int); | ||
1347 | real_stack.arg13 = va_arg(args, unsigned int); | ||
1348 | va_end(args); | ||
1349 | |||
1350 | return real32_call_asm(&real_stack.sp, &real_stack.arg0, fn); | ||
1351 | } | ||
1352 | |||
1353 | #ifdef __LP64__ | ||
1354 | /***************** 64-bit real-mode calls ***********/ | ||
1355 | |||
1356 | struct wide_stack { | ||
1357 | unsigned long arg0; | ||
1358 | unsigned long arg1; | ||
1359 | unsigned long arg2; | ||
1360 | unsigned long arg3; | ||
1361 | unsigned long arg4; | ||
1362 | unsigned long arg5; | ||
1363 | unsigned long arg6; | ||
1364 | unsigned long arg7; | ||
1365 | unsigned long arg8; | ||
1366 | unsigned long arg9; | ||
1367 | unsigned long arg10; | ||
1368 | unsigned long arg11; | ||
1369 | unsigned long arg12; | ||
1370 | unsigned long arg13; | ||
1371 | unsigned long frame_marker[2]; /* rp, previous sp */ | ||
1372 | unsigned long sp; | ||
1373 | /* in reality, there's nearly 8k of stack after this */ | ||
1374 | }; | ||
1375 | |||
1376 | long real64_call(unsigned long fn, ...) | ||
1377 | { | ||
1378 | va_list args; | ||
1379 | extern struct wide_stack real64_stack; | ||
1380 | extern unsigned long real64_call_asm(unsigned long *, | ||
1381 | unsigned long *, | ||
1382 | unsigned long); | ||
1383 | |||
1384 | va_start(args, fn); | ||
1385 | real64_stack.arg0 = va_arg(args, unsigned long); | ||
1386 | real64_stack.arg1 = va_arg(args, unsigned long); | ||
1387 | real64_stack.arg2 = va_arg(args, unsigned long); | ||
1388 | real64_stack.arg3 = va_arg(args, unsigned long); | ||
1389 | real64_stack.arg4 = va_arg(args, unsigned long); | ||
1390 | real64_stack.arg5 = va_arg(args, unsigned long); | ||
1391 | real64_stack.arg6 = va_arg(args, unsigned long); | ||
1392 | real64_stack.arg7 = va_arg(args, unsigned long); | ||
1393 | real64_stack.arg8 = va_arg(args, unsigned long); | ||
1394 | real64_stack.arg9 = va_arg(args, unsigned long); | ||
1395 | real64_stack.arg10 = va_arg(args, unsigned long); | ||
1396 | real64_stack.arg11 = va_arg(args, unsigned long); | ||
1397 | real64_stack.arg12 = va_arg(args, unsigned long); | ||
1398 | real64_stack.arg13 = va_arg(args, unsigned long); | ||
1399 | va_end(args); | ||
1400 | |||
1401 | return real64_call_asm(&real64_stack.sp, &real64_stack.arg0, fn); | ||
1402 | } | ||
1403 | |||
1404 | #endif /* __LP64__ */ | ||
1405 | |||
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c new file mode 100644 index 000000000000..2071b5bba15c --- /dev/null +++ b/arch/parisc/kernel/hardware.c | |||
@@ -0,0 +1,1366 @@ | |||
1 | /* | ||
2 | * Hardware descriptions for HP 9000 based hardware, including | ||
3 | * system types, SCSI controllers, DMA controllers, HPPB controllers | ||
4 | * and lots more. | ||
5 | * | ||
6 | * Based on the document "PA-RISC 1.1 I/O Firmware Architecture | ||
7 | * Reference Specification", March 7, 1999, version 0.96. This | ||
8 | * is available at http://parisc-linux.org/documentation/ | ||
9 | * | ||
10 | * Copyright 1999 by Alex deVries <alex@onefishtwo.ca> | ||
11 | * and copyright 1999 The Puffin Group Inc. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2, or (at your option) | ||
16 | * any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | |||
30 | #include <asm/hardware.h> | ||
31 | #include <linux/stddef.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | /* | ||
36 | * HP PARISC Hardware Database | ||
37 | * Access to this database is only possible during bootup | ||
38 | * so don't reference this table after starting the init process | ||
39 | */ | ||
40 | |||
41 | static struct hp_hardware hp_hardware_list[] __initdata = { | ||
42 | {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"}, | ||
43 | {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"}, | ||
44 | {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"}, | ||
45 | {HPHW_NPROC,0xB,0x4,0x01,"Technical Shogun (845, 645)"}, | ||
46 | {HPHW_NPROC,0xF,0x4,0x01,"Commercial Shogun (949)"}, | ||
47 | {HPHW_NPROC,0xC,0x4,0x01,"Cheetah (850, 950)"}, | ||
48 | {HPHW_NPROC,0x80,0x4,0x01,"Cheetah (950S)"}, | ||
49 | {HPHW_NPROC,0x81,0x4,0x01,"Jaguar (855, 955)"}, | ||
50 | {HPHW_NPROC,0x82,0x4,0x01,"Cougar (860, 960)"}, | ||
51 | {HPHW_NPROC,0x83,0x4,0x13,"Panther (865, 870, 980)"}, | ||
52 | {HPHW_NPROC,0x100,0x4,0x01,"Burgundy (810)"}, | ||
53 | {HPHW_NPROC,0x101,0x4,0x01,"SilverFox Low (822, 922)"}, | ||
54 | {HPHW_NPROC,0x102,0x4,0x01,"SilverFox High (832, 932)"}, | ||
55 | {HPHW_NPROC,0x103,0x4,0x01,"Lego, SilverLite (815, 808, 920)"}, | ||
56 | {HPHW_NPROC,0x104,0x4,0x03,"SilverBullet Low (842, 948)"}, | ||
57 | {HPHW_NPROC,0x105,0x4,0x03,"SilverBullet High (852, 958)"}, | ||
58 | {HPHW_NPROC,0x106,0x4,0x81,"Oboe"}, | ||
59 | {HPHW_NPROC,0x180,0x4,0x12,"Dragon"}, | ||
60 | {HPHW_NPROC,0x181,0x4,0x13,"Chimera (890, 990, 992)"}, | ||
61 | {HPHW_NPROC,0x182,0x4,0x91,"TNT 100 (891,T500)"}, | ||
62 | {HPHW_NPROC,0x183,0x4,0x91,"TNT 120 (892,T520)"}, | ||
63 | {HPHW_NPROC,0x184,0x4,0x91,"Jade 180 U (893,T540)"}, | ||
64 | {HPHW_NPROC,0x1FF,0x4,0x91,"Hitachi X Processor"}, | ||
65 | {HPHW_NPROC,0x200,0x4,0x81,"Cobra (720)"}, | ||
66 | {HPHW_NPROC,0x201,0x4,0x81,"Coral (750)"}, | ||
67 | {HPHW_NPROC,0x202,0x4,0x81,"King Cobra (730)"}, | ||
68 | {HPHW_NPROC,0x203,0x4,0x81,"Hardball (735/99)"}, | ||
69 | {HPHW_NPROC,0x204,0x4,0x81,"Coral II (755/99)"}, | ||
70 | {HPHW_NPROC,0x205,0x4,0x81,"Coral II (755/125)"}, | ||
71 | {HPHW_NPROC,0x205,0x4,0x91,"Snake Eagle "}, | ||
72 | {HPHW_NPROC,0x206,0x4,0x81,"Snake Cheetah (735/130)"}, | ||
73 | {HPHW_NPROC,0x280,0x4,0x81,"Nova Low (817, 827, 957, 957LX)"}, | ||
74 | {HPHW_NPROC,0x281,0x4,0x81,"Nova High (837, 847, 857, 967, 967LX)"}, | ||
75 | {HPHW_NPROC,0x282,0x4,0x81,"Nova8 (807, 917, 917LX, 927,927LX, 937, 937LX, 947,947LX)"}, | ||
76 | {HPHW_NPROC,0x283,0x4,0x81,"Nova64 (867, 877, 977)"}, | ||
77 | {HPHW_NPROC,0x284,0x4,0x81,"TNova (887, 897, 987)"}, | ||
78 | {HPHW_NPROC,0x285,0x4,0x81,"TNova64"}, | ||
79 | {HPHW_NPROC,0x286,0x4,0x91,"Hydra64 (Nova)"}, | ||
80 | {HPHW_NPROC,0x287,0x4,0x91,"Hydra96 (Nova)"}, | ||
81 | {HPHW_NPROC,0x288,0x4,0x81,"TNova96"}, | ||
82 | {HPHW_NPROC,0x300,0x4,0x81,"Bushmaster (710)"}, | ||
83 | {HPHW_NPROC,0x302,0x4,0x81,"Flounder (705)"}, | ||
84 | {HPHW_NPROC,0x310,0x4,0x81,"Scorpio (715/50)"}, | ||
85 | {HPHW_NPROC,0x311,0x4,0x81,"Scorpio Jr.(715/33)"}, | ||
86 | {HPHW_NPROC,0x312,0x4,0x81,"Strider-50 (715S/50)"}, | ||
87 | {HPHW_NPROC,0x313,0x4,0x81,"Strider-33 (715S/33)"}, | ||
88 | {HPHW_NPROC,0x314,0x4,0x81,"Trailways-50 (715T/50)"}, | ||
89 | {HPHW_NPROC,0x315,0x4,0x81,"Trailways-33 (715T/33)"}, | ||
90 | {HPHW_NPROC,0x316,0x4,0x81,"Scorpio Sr.(715/75)"}, | ||
91 | {HPHW_NPROC,0x317,0x4,0x81,"Scorpio 100 (715/100)"}, | ||
92 | {HPHW_NPROC,0x318,0x4,0x81,"Spectra (725/50)"}, | ||
93 | {HPHW_NPROC,0x319,0x4,0x81,"Spectra (725/75)"}, | ||
94 | {HPHW_NPROC,0x320,0x4,0x81,"Spectra (725/100)"}, | ||
95 | {HPHW_NPROC,0x401,0x4,0x81,"Pace (745i, 747i)"}, | ||
96 | {HPHW_NPROC,0x402,0x4,0x81,"Sidewinder (742i)"}, | ||
97 | {HPHW_NPROC,0x403,0x4,0x81,"Fast Pace"}, | ||
98 | {HPHW_NPROC,0x480,0x4,0x81,"Orville (E23)"}, | ||
99 | {HPHW_NPROC,0x481,0x4,0x81,"Wilbur (E25)"}, | ||
100 | {HPHW_NPROC,0x482,0x4,0x81,"WB-80 (E35)"}, | ||
101 | {HPHW_NPROC,0x483,0x4,0x81,"WB-96 (E45)"}, | ||
102 | {HPHW_NPROC,0x484,0x4,0x81,"UL Proc L-100 (811/D210,D310)"}, | ||
103 | {HPHW_NPROC,0x485,0x4,0x81,"UL Proc L-75 (801/D200)"}, | ||
104 | {HPHW_NPROC,0x501,0x4,0x81,"Merlin L2 132 (9000/778/B132L)"}, | ||
105 | {HPHW_NPROC,0x502,0x4,0x81,"Merlin L2 160 (9000/778/B160L)"}, | ||
106 | {HPHW_NPROC,0x503,0x4,0x81,"Merlin L2+ 132 (9000/778/B132L)"}, | ||
107 | {HPHW_NPROC,0x504,0x4,0x81,"Merlin L2+ 180 (9000/778/B180L)"}, | ||
108 | {HPHW_NPROC,0x505,0x4,0x81,"Raven L2 132 (9000/778/C132L)"}, | ||
109 | {HPHW_NPROC,0x506,0x4,0x81,"Raven L2 160 (9000/779/C160L)"}, | ||
110 | {HPHW_NPROC,0x507,0x4,0x81,"Raven L2 180 (9000/779/C180L)"}, | ||
111 | {HPHW_NPROC,0x508,0x4,0x81,"Raven L2 160 (9000/779/C160L)"}, | ||
112 | {HPHW_NPROC,0x509,0x4,0x81,"712/132 L2 Upgrade"}, | ||
113 | {HPHW_NPROC,0x50A,0x4,0x81,"712/160 L2 Upgrade"}, | ||
114 | {HPHW_NPROC,0x50B,0x4,0x81,"715/132 L2 Upgrade"}, | ||
115 | {HPHW_NPROC,0x50C,0x4,0x81,"715/160 L2 Upgrade"}, | ||
116 | {HPHW_NPROC,0x50D,0x4,0x81,"Rocky2 L2 120"}, | ||
117 | {HPHW_NPROC,0x50E,0x4,0x81,"Rocky2 L2 150"}, | ||
118 | {HPHW_NPROC,0x50F,0x4,0x81,"Anole L2 132 (744)"}, | ||
119 | {HPHW_NPROC,0x510,0x4,0x81,"Anole L2 165 (744)"}, | ||
120 | {HPHW_NPROC,0x511,0x4,0x81,"Kiji L2 132"}, | ||
121 | {HPHW_NPROC,0x512,0x4,0x81,"UL L2 132 (803/D220,D320)"}, | ||
122 | {HPHW_NPROC,0x513,0x4,0x81,"UL L2 160 (813/D220,D320)"}, | ||
123 | {HPHW_NPROC,0x514,0x4,0x81,"Merlin Jr L2 132"}, | ||
124 | {HPHW_NPROC,0x515,0x4,0x81,"Staccato L2 132"}, | ||
125 | {HPHW_NPROC,0x516,0x4,0x81,"Staccato L2 180 (A Class 180)"}, | ||
126 | {HPHW_NPROC,0x580,0x4,0x81,"KittyHawk DC2-100 (K100)"}, | ||
127 | {HPHW_NPROC,0x581,0x4,0x91,"KittyHawk DC3-120 (K210)"}, | ||
128 | {HPHW_NPROC,0x582,0x4,0x91,"KittyHawk DC3 100 (K400)"}, | ||
129 | {HPHW_NPROC,0x583,0x4,0x91,"KittyHawk DC3 120 (K410)"}, | ||
130 | {HPHW_NPROC,0x584,0x4,0x91,"LighteningHawk T120"}, | ||
131 | {HPHW_NPROC,0x585,0x4,0x91,"SkyHawk 100"}, | ||
132 | {HPHW_NPROC,0x586,0x4,0x91,"SkyHawk 120"}, | ||
133 | {HPHW_NPROC,0x587,0x4,0x81,"UL Proc 1-way T'120"}, | ||
134 | {HPHW_NPROC,0x588,0x4,0x91,"UL Proc 2-way T'120"}, | ||
135 | {HPHW_NPROC,0x589,0x4,0x81,"UL Proc 1-way T'100 (821/D250,D350)"}, | ||
136 | {HPHW_NPROC,0x58A,0x4,0x91,"UL Proc 2-way T'100 (831/D250,D350)"}, | ||
137 | {HPHW_NPROC,0x58B,0x4,0x91,"KittyHawk DC2 100 (K200)"}, | ||
138 | {HPHW_NPROC,0x58C,0x4,0x91,"ThunderHawk DC3- 120 1M (K220)"}, | ||
139 | {HPHW_NPROC,0x58D,0x4,0x91,"ThunderHawk DC3 120 1M (K420)"}, | ||
140 | {HPHW_NPROC,0x58E,0x4,0x81,"Raven 120 T'"}, | ||
141 | {HPHW_NPROC,0x58F,0x4,0x91,"Mohawk 160 U 1M DC3 (K450)"}, | ||
142 | {HPHW_NPROC,0x590,0x4,0x91,"Mohawk 180 U 1M DC3 (K460)"}, | ||
143 | {HPHW_NPROC,0x591,0x4,0x91,"Mohawk 200 U 1M DC3"}, | ||
144 | {HPHW_NPROC,0x592,0x4,0x81,"Raven 100 T'"}, | ||
145 | {HPHW_NPROC,0x593,0x4,0x91,"FireHawk 160 U"}, | ||
146 | {HPHW_NPROC,0x594,0x4,0x91,"FireHawk 180 U"}, | ||
147 | {HPHW_NPROC,0x595,0x4,0x91,"FireHawk 220 U"}, | ||
148 | {HPHW_NPROC,0x596,0x4,0x91,"FireHawk 240 U"}, | ||
149 | {HPHW_NPROC,0x597,0x4,0x91,"SPP2000 processor"}, | ||
150 | {HPHW_NPROC,0x598,0x4,0x81,"Raven U 230 (9000/780/C230)"}, | ||
151 | {HPHW_NPROC,0x599,0x4,0x81,"Raven U 240 (9000/780/C240)"}, | ||
152 | {HPHW_NPROC,0x59A,0x4,0x91,"Unlisted but reserved"}, | ||
153 | {HPHW_NPROC,0x59A,0x4,0x81,"Unlisted but reserved"}, | ||
154 | {HPHW_NPROC,0x59B,0x4,0x81,"Raven U 160 (9000/780/C160)"}, | ||
155 | {HPHW_NPROC,0x59C,0x4,0x81,"Raven U 180 (9000/780/C180)"}, | ||
156 | {HPHW_NPROC,0x59D,0x4,0x81,"Raven U 200 (9000/780/C200)"}, | ||
157 | {HPHW_NPROC,0x59E,0x4,0x91,"ThunderHawk T' 120"}, | ||
158 | {HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780)"}, | ||
159 | {HPHW_NPROC,0x5A0,0x4,0x81,"UL 1w T120 1MB/1MB (841/D260,D360)"}, | ||
160 | {HPHW_NPROC,0x5A1,0x4,0x91,"UL 2w T120 1MB/1MB (851/D260,D360)"}, | ||
161 | {HPHW_NPROC,0x5A2,0x4,0x81,"UL 1w U160 512K/512K (861/D270,D370)"}, | ||
162 | {HPHW_NPROC,0x5A3,0x4,0x91,"UL 2w U160 512K/512K (871/D270,D370)"}, | ||
163 | {HPHW_NPROC,0x5A4,0x4,0x91,"Mohawk 160 U 1M DC3- (K250)"}, | ||
164 | {HPHW_NPROC,0x5A5,0x4,0x91,"Mohawk 180 U 1M DC3- (K260)"}, | ||
165 | {HPHW_NPROC,0x5A6,0x4,0x91,"Mohawk 200 U 1M DC3-"}, | ||
166 | {HPHW_NPROC,0x5A7,0x4,0x81,"UL proc 1-way U160 1M/1M"}, | ||
167 | {HPHW_NPROC,0x5A8,0x4,0x91,"UL proc 2-way U160 1M/1M"}, | ||
168 | {HPHW_NPROC,0x5A9,0x4,0x81,"UL proc 1-way U180 1M/1M"}, | ||
169 | {HPHW_NPROC,0x5AA,0x4,0x91,"UL proc 2-way U180 1M/1M"}, | ||
170 | {HPHW_NPROC,0x5AB,0x4,0x91,"Obsolete"}, | ||
171 | {HPHW_NPROC,0x5AB,0x4,0x81,"Obsolete"}, | ||
172 | {HPHW_NPROC,0x5AC,0x4,0x91,"Obsolete"}, | ||
173 | {HPHW_NPROC,0x5AC,0x4,0x81,"Obsolete"}, | ||
174 | {HPHW_NPROC,0x5AD,0x4,0x91,"BraveHawk 180MHz DC3-"}, | ||
175 | {HPHW_NPROC,0x5AE,0x4,0x91,"BraveHawk 200MHz DC3- (898/K370)"}, | ||
176 | {HPHW_NPROC,0x5AF,0x4,0x91,"BraveHawk 220MHz DC3-"}, | ||
177 | {HPHW_NPROC,0x5B0,0x4,0x91,"BraveHawk 180MHz DC3"}, | ||
178 | {HPHW_NPROC,0x5B1,0x4,0x91,"BraveHawk 200MHz DC3 (899/K570)"}, | ||
179 | {HPHW_NPROC,0x5B2,0x4,0x91,"BraveHawk 220MHz DC3"}, | ||
180 | {HPHW_NPROC,0x5B3,0x4,0x91,"FireHawk 200"}, | ||
181 | {HPHW_NPROC,0x5B4,0x4,0x91,"SPP2500"}, | ||
182 | {HPHW_NPROC,0x5B5,0x4,0x91,"SummitHawk U+"}, | ||
183 | {HPHW_NPROC,0x5B6,0x4,0x91,"DragonHawk U+ 240 DC3"}, | ||
184 | {HPHW_NPROC,0x5B7,0x4,0x91,"DragonHawk U+ 240 DC3-"}, | ||
185 | {HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"}, | ||
186 | {HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"}, | ||
187 | {HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"}, | ||
188 | {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W"}, | ||
189 | {HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"}, | ||
190 | {HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"}, | ||
191 | {HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"}, | ||
192 | {HPHW_NPROC,0x5BF,0x4,0x91,"Forte W 4-way"}, | ||
193 | {HPHW_NPROC,0x5C0,0x4,0x91,"M2250"}, | ||
194 | {HPHW_NPROC,0x5C1,0x4,0x91,"M2500"}, | ||
195 | {HPHW_NPROC,0x5C2,0x4,0x91,"Sonata 440"}, | ||
196 | {HPHW_NPROC,0x5C3,0x4,0x91,"Sonata 360"}, | ||
197 | {HPHW_NPROC,0x5C4,0x4,0x91,"Rhapsody 440"}, | ||
198 | {HPHW_NPROC,0x5C5,0x4,0x91,"Rhapsody 360"}, | ||
199 | {HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780)"}, | ||
200 | {HPHW_NPROC,0x5C7,0x4,0x91,"Halfdome W 440"}, | ||
201 | {HPHW_NPROC,0x5C8,0x4,0x81,"Lego 360 processor"}, | ||
202 | {HPHW_NPROC,0x5C9,0x4,0x91,"Rhapsody DC- 440"}, | ||
203 | {HPHW_NPROC,0x5CA,0x4,0x91,"Rhapsody DC- 360"}, | ||
204 | {HPHW_NPROC,0x5CB,0x4,0x91,"Crescendo 440"}, | ||
205 | {HPHW_NPROC,0x5CC,0x4,0x91,"Prelude W 440"}, | ||
206 | {HPHW_NPROC,0x5CD,0x4,0x91,"SPP2600"}, | ||
207 | {HPHW_NPROC,0x5CE,0x4,0x91,"M2600"}, | ||
208 | {HPHW_NPROC,0x5CF,0x4,0x81,"Allegro W+"}, | ||
209 | {HPHW_NPROC,0x5D0,0x4,0x81,"Kazoo W+"}, | ||
210 | {HPHW_NPROC,0x5D1,0x4,0x91,"Forte W+ 2w"}, | ||
211 | {HPHW_NPROC,0x5D2,0x4,0x91,"Forte W+ 4w"}, | ||
212 | {HPHW_NPROC,0x5D3,0x4,0x91,"Prelude W+ 540"}, | ||
213 | {HPHW_NPROC,0x5D4,0x4,0x91,"Duet W+"}, | ||
214 | {HPHW_NPROC,0x5D5,0x4,0x91,"Crescendo 550"}, | ||
215 | {HPHW_NPROC,0x5D6,0x4,0x81,"Crescendo DC- 440"}, | ||
216 | {HPHW_NPROC,0x5D7,0x4,0x91,"Keystone W+"}, | ||
217 | {HPHW_NPROC,0x5D8,0x4,0x91,"Rhapsody wave 2 W+ DC-"}, | ||
218 | {HPHW_NPROC,0x5D9,0x4,0x91,"Rhapsody wave 2 W+"}, | ||
219 | {HPHW_NPROC,0x5DA,0x4,0x91,"Marcato W+ DC-"}, | ||
220 | {HPHW_NPROC,0x5DB,0x4,0x91,"Marcato W+"}, | ||
221 | {HPHW_NPROC,0x5DC,0x4,0x91,"Allegro W2"}, | ||
222 | {HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"}, | ||
223 | {HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"}, | ||
224 | {HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"}, | ||
225 | {HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"}, | ||
226 | {HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"}, | ||
227 | {HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"}, | ||
228 | {HPHW_NPROC,0x5E3,0x4,0x91,"Crescendo 750 W2"}, | ||
229 | {HPHW_NPROC,0x5E4,0x4,0x91,"Keystone/Matterhorn W2 750"}, | ||
230 | {HPHW_NPROC,0x5E5,0x4,0x91,"PowerBar W+"}, | ||
231 | {HPHW_NPROC,0x5E6,0x4,0x91,"Keystone/Matterhorn W2 650"}, | ||
232 | {HPHW_NPROC,0x5E7,0x4,0x91,"Caribe W2 800"}, | ||
233 | {HPHW_NPROC,0x5E8,0x4,0x91,"Pikes Peak W2"}, | ||
234 | {HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"}, | ||
235 | {HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"}, | ||
236 | {HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"}, | ||
237 | {HPHW_NPROC,0x602,0x4,0x81,"Gecko 100 (712/100)"}, | ||
238 | {HPHW_NPROC,0x603,0x4,0x81,"Anole 64 (743/64)"}, | ||
239 | {HPHW_NPROC,0x604,0x4,0x81,"Anole 100 (743/100)"}, | ||
240 | {HPHW_NPROC,0x605,0x4,0x81,"Gecko 120 (712/120)"}, | ||
241 | {HPHW_NPROC,0x606,0x4,0x81,"Gila 80"}, | ||
242 | {HPHW_NPROC,0x607,0x4,0x81,"Gila 100"}, | ||
243 | {HPHW_NPROC,0x608,0x4,0x81,"Gila 120"}, | ||
244 | {HPHW_NPROC,0x609,0x4,0x81,"Scorpio-L 80"}, | ||
245 | {HPHW_NPROC,0x60A,0x4,0x81,"Mirage Jr (715/64)"}, | ||
246 | {HPHW_NPROC,0x60B,0x4,0x81,"Mirage 100"}, | ||
247 | {HPHW_NPROC,0x60C,0x4,0x81,"Mirage 100+"}, | ||
248 | {HPHW_NPROC,0x60D,0x4,0x81,"Electra 100"}, | ||
249 | {HPHW_NPROC,0x60E,0x4,0x81,"Electra 120"}, | ||
250 | {HPHW_NPROC,0x610,0x4,0x81,"Scorpio-L 100"}, | ||
251 | {HPHW_NPROC,0x611,0x4,0x81,"Scorpio-L 120"}, | ||
252 | {HPHW_NPROC,0x612,0x4,0x81,"Spectra-L 80"}, | ||
253 | {HPHW_NPROC,0x613,0x4,0x81,"Spectra-L 100"}, | ||
254 | {HPHW_NPROC,0x614,0x4,0x81,"Spectra-L 120"}, | ||
255 | {HPHW_NPROC,0x615,0x4,0x81,"Piranha 100"}, | ||
256 | {HPHW_NPROC,0x616,0x4,0x81,"Piranha 120"}, | ||
257 | {HPHW_NPROC,0x617,0x4,0x81,"Jason 50"}, | ||
258 | {HPHW_NPROC,0x618,0x4,0x81,"Jason 100"}, | ||
259 | {HPHW_NPROC,0x619,0x4,0x81,"Mirage 80"}, | ||
260 | {HPHW_NPROC,0x61A,0x4,0x81,"SAIC L-80"}, | ||
261 | {HPHW_NPROC,0x61B,0x4,0x81,"Rocky1 L-60"}, | ||
262 | {HPHW_NPROC,0x61C,0x4,0x81,"Anole T (743/T)"}, | ||
263 | {HPHW_NPROC,0x67E,0x4,0x81,"Hitachi Tiny 80"}, | ||
264 | {HPHW_NPROC,0x67F,0x4,0x81,"Hitachi Tiny 64"}, | ||
265 | {HPHW_NPROC,0x700,0x4,0x91,"NEC Aska Processor"}, | ||
266 | {HPHW_NPROC,0x880,0x4,0x91,"Orca Mako"}, | ||
267 | {HPHW_NPROC,0x881,0x4,0x91,"Everest Mako"}, | ||
268 | {HPHW_NPROC,0x882,0x4,0x91,"Rainier/Medel Mako Slow"}, | ||
269 | {HPHW_NPROC,0x883,0x4,0x91,"Rainier/Medel Mako Fast"}, | ||
270 | {HPHW_NPROC,0x884,0x4,0x91,"Mt. Hamilton"}, | ||
271 | {HPHW_NPROC,0x885,0x4,0x91,"Mt. Hamilton DC-"}, | ||
272 | {HPHW_NPROC,0x886,0x4,0x91,"Storm Peak Slow DC-"}, | ||
273 | {HPHW_NPROC,0x887,0x4,0x91,"Storm Peak Slow"}, | ||
274 | {HPHW_NPROC,0x888,0x4,0x91,"Storm Peak Fast DC-"}, | ||
275 | {HPHW_NPROC,0x889,0x4,0x91,"Storm Peak Fast"}, | ||
276 | {HPHW_NPROC,0x88A,0x4,0x91,"Crestone Peak"}, | ||
277 | {HPHW_A_DIRECT, 0x004, 0x0000D, 0x00, "Arrakis MUX"}, | ||
278 | {HPHW_A_DIRECT, 0x005, 0x0000D, 0x00, "Dyun Kiuh MUX"}, | ||
279 | {HPHW_A_DIRECT, 0x006, 0x0000D, 0x00, "Baat Kiuh AP/MUX (40299B)"}, | ||
280 | {HPHW_A_DIRECT, 0x007, 0x0000D, 0x00, "Dino AP"}, | ||
281 | {HPHW_A_DIRECT, 0x009, 0x0000D, 0x00, "Solaris Direct Connect MUX (J2092A)"}, | ||
282 | {HPHW_A_DIRECT, 0x00A, 0x0000D, 0x00, "Solaris RS-422/423 MUX (J2093A)"}, | ||
283 | {HPHW_A_DIRECT, 0x00B, 0x0000D, 0x00, "Solaris RS-422/423 Quadriloops MUX"}, | ||
284 | {HPHW_A_DIRECT, 0x00C, 0x0000D, 0x00, "Solaris Modem MUX (J2094A)"}, | ||
285 | {HPHW_A_DIRECT, 0x00D, 0x0000D, 0x00, "Twins Direct Connect MUX"}, | ||
286 | {HPHW_A_DIRECT, 0x00E, 0x0000D, 0x00, "Twins Modem MUX"}, | ||
287 | {HPHW_A_DIRECT, 0x00F, 0x0000D, 0x00, "Nautilus RS-485"}, | ||
288 | {HPHW_A_DIRECT, 0x010, 0x0000D, 0x00, "UltraLight CAP/MUX"}, | ||
289 | {HPHW_A_DIRECT, 0x015, 0x0000D, 0x00, "Eole CAP/MUX"}, | ||
290 | {HPHW_A_DIRECT, 0x024, 0x0000D, 0x00, "Sahp Kiuh AP/MUX"}, | ||
291 | {HPHW_A_DIRECT, 0x034, 0x0000D, 0x00, "Sahp Kiuh Low AP/MUX"}, | ||
292 | {HPHW_A_DIRECT, 0x044, 0x0000D, 0x00, "Sahp Baat Kiuh AP/MUX"}, | ||
293 | {HPHW_A_DIRECT, 0x004, 0x0000E, 0x80, "Burgundy RS-232"}, | ||
294 | {HPHW_A_DIRECT, 0x005, 0x0000E, 0x80, "Silverfox RS-232"}, | ||
295 | {HPHW_A_DIRECT, 0x006, 0x0000E, 0x80, "Lego RS-232"}, | ||
296 | {HPHW_A_DIRECT, 0x004, 0x0000F, 0x00, "Peacock Graphics"}, | ||
297 | {HPHW_A_DIRECT, 0x004, 0x00014, 0x80, "Burgundy HIL"}, | ||
298 | {HPHW_A_DIRECT, 0x005, 0x00014, 0x80, "Peacock HIL"}, | ||
299 | {HPHW_A_DIRECT, 0x004, 0x00015, 0x80, "Leonardo"}, | ||
300 | {HPHW_A_DIRECT, 0x004, 0x00016, 0x80, "HP-PB HRM"}, | ||
301 | {HPHW_A_DIRECT, 0x004, 0x00017, 0x80, "HP-PB HRC"}, | ||
302 | {HPHW_A_DIRECT, 0x004, 0x0003A, 0x80, "Skunk Centronics (28655A)"}, | ||
303 | {HPHW_A_DIRECT, 0x024, 0x0003A, 0x80, "Sahp Kiuh Centronics"}, | ||
304 | {HPHW_A_DIRECT, 0x044, 0x0003A, 0x80, "Sahp Baat Kiuh Centronics"}, | ||
305 | {HPHW_A_DIRECT, 0x004, 0x0004E, 0x80, "AT&T DataKit (AMSO)"}, | ||
306 | {HPHW_A_DIRECT, 0x004, 0x0009B, 0x80, "Test&Meas GSC HPIB"}, | ||
307 | {HPHW_A_DIRECT, 0x004, 0x000A8, 0x00, "Rocky2-120 Front Keyboard"}, | ||
308 | {HPHW_A_DIRECT, 0x005, 0x000A8, 0x00, "Rocky2-150 Front Keyboard"}, | ||
309 | {HPHW_A_DIRECT, 0x004, 0x00101, 0x80, "Hitachi Console Module"}, | ||
310 | {HPHW_A_DIRECT, 0x004, 0x00102, 0x80, "Hitachi Boot Module"}, | ||
311 | {HPHW_A_DIRECT, 0x004, 0x00203, 0x80, "MELCO HBMLA MLAIT"}, | ||
312 | {HPHW_A_DIRECT, 0x004, 0x00208, 0x80, "MELCO HBDPC"}, | ||
313 | {HPHW_A_DIRECT, 0x004, 0x00300, 0x00, "DCI TWINAX TERM IO MUX"}, | ||
314 | {HPHW_A_DMA, 0x004, 0x00039, 0x80, "Skunk SCSI (28655A)"}, | ||
315 | {HPHW_A_DMA, 0x005, 0x00039, 0x80, "KittyHawk CSY Core SCSI"}, | ||
316 | {HPHW_A_DMA, 0x014, 0x00039, 0x80, "Diablo SCSI"}, | ||
317 | {HPHW_A_DMA, 0x024, 0x00039, 0x80, "Sahp Kiuh SCSI"}, | ||
318 | {HPHW_A_DMA, 0x034, 0x00039, 0x80, "Sahp Kiuh Low SCSI"}, | ||
319 | {HPHW_A_DMA, 0x044, 0x00039, 0x80, "Sahp Baat Kiuh SCSI"}, | ||
320 | {HPHW_A_DMA, 0x004, 0x0003B, 0x80, "Wizard SCSI"}, | ||
321 | {HPHW_A_DMA, 0x005, 0x0003B, 0x80, "KittyHawk CSY Core FW-SCSI"}, | ||
322 | {HPHW_A_DMA, 0x006, 0x0003B, 0x80, "Symbios EPIC FW-SCSI"}, | ||
323 | {HPHW_A_DMA, 0x004, 0x00040, 0x80, "HP-PB Shazam HPIB (28650A)"}, | ||
324 | {HPHW_A_DMA, 0x005, 0x00040, 0x80, "Burgundy HPIB"}, | ||
325 | {HPHW_A_DMA, 0x004, 0x00041, 0x80, "HP-PB HP-FL"}, | ||
326 | {HPHW_A_DMA, 0x004, 0x00042, 0x80, "HP-PB LoQuix HPIB (28650B)"}, | ||
327 | {HPHW_A_DMA, 0x004, 0x00043, 0x80, "HP-PB Crypt LoQuix"}, | ||
328 | {HPHW_A_DMA, 0x004, 0x00044, 0x80, "HP-PB Shazam GPIO (28651A)"}, | ||
329 | {HPHW_A_DMA, 0x004, 0x00045, 0x80, "HP-PB LoQuix GPIO"}, | ||
330 | {HPHW_A_DMA, 0x004, 0x00046, 0x80, "2-Port X.25 NIO_ACC (AMSO)"}, | ||
331 | {HPHW_A_DMA, 0x004, 0x00047, 0x80, "4-Port X.25 NIO_ACC (AMSO)"}, | ||
332 | {HPHW_A_DMA, 0x004, 0x0004B, 0x80, "LGB Control"}, | ||
333 | {HPHW_A_DMA, 0x004, 0x0004C, 0x80, "Martian RTI (AMSO)"}, | ||
334 | {HPHW_A_DMA, 0x004, 0x0004D, 0x80, "ACC Mux (AMSO)"}, | ||
335 | {HPHW_A_DMA, 0x004, 0x00050, 0x80, "Lanbrusca 802.3 (36967A)"}, | ||
336 | {HPHW_A_DMA, 0x004, 0x00056, 0x80, "HP-PB LoQuix FDDI"}, | ||
337 | {HPHW_A_DMA, 0x004, 0x00057, 0x80, "HP-PB LoQuix FDDI (28670A)"}, | ||
338 | {HPHW_A_DMA, 0x004, 0x0005E, 0x00, "Gecko Add-on Token Ring"}, | ||
339 | {HPHW_A_DMA, 0x012, 0x00089, 0x80, "Barracuda Add-on FW-SCSI"}, | ||
340 | {HPHW_A_DMA, 0x013, 0x00089, 0x80, "Bluefish Add-on FW-SCSI"}, | ||
341 | {HPHW_A_DMA, 0x014, 0x00089, 0x80, "Shrike Add-on FW-SCSI"}, | ||
342 | {HPHW_A_DMA, 0x015, 0x00089, 0x80, "KittyHawk GSY Core FW-SCSI"}, | ||
343 | {HPHW_A_DMA, 0x017, 0x00089, 0x80, "Shrike Jade Add-on FW-SCSI (A3644A)"}, | ||
344 | {HPHW_A_DMA, 0x01F, 0x00089, 0x80, "SkyHawk 100/120 FW-SCSI"}, | ||
345 | {HPHW_A_DMA, 0x027, 0x00089, 0x80, "Piranha 100 FW-SCSI"}, | ||
346 | {HPHW_A_DMA, 0x032, 0x00089, 0x80, "Raven T' Core FW-SCSI"}, | ||
347 | {HPHW_A_DMA, 0x03B, 0x00089, 0x80, "Raven U/L2 Core FW-SCSI"}, | ||
348 | {HPHW_A_DMA, 0x03C, 0x00089, 0x80, "Merlin 132 Core FW-SCSI"}, | ||
349 | {HPHW_A_DMA, 0x03D, 0x00089, 0x80, "Merlin 160 Core FW-SCSI"}, | ||
350 | {HPHW_A_DMA, 0x044, 0x00089, 0x80, "Mohawk Core FW-SCSI"}, | ||
351 | {HPHW_A_DMA, 0x051, 0x00089, 0x80, "Firehawk FW-SCSI"}, | ||
352 | {HPHW_A_DMA, 0x058, 0x00089, 0x80, "FireHawk 200 FW-SCSI"}, | ||
353 | {HPHW_A_DMA, 0x05C, 0x00089, 0x80, "SummitHawk 230 Ultra-SCSI"}, | ||
354 | {HPHW_A_DMA, 0x014, 0x00091, 0x80, "Baby Hugo Add-on Net FC (A3406A)"}, | ||
355 | {HPHW_A_DMA, 0x020, 0x00091, 0x80, "Baby Jade Add-on Net FC (A3638A)"}, | ||
356 | {HPHW_A_DMA, 0x004, 0x00092, 0x80, "GSC+ YLIASTER ATM"}, | ||
357 | {HPHW_A_DMA, 0x004, 0x00095, 0x80, "Hamlyn GSC+ Network Card"}, | ||
358 | {HPHW_A_DMA, 0x004, 0x00098, 0x80, "Lo-fat Emulator"}, | ||
359 | {HPHW_A_DMA, 0x004, 0x0009A, 0x80, "GSC+ Venus ATM"}, | ||
360 | {HPHW_A_DMA, 0x005, 0x0009A, 0x80, "GSC+ Samorobrive ATM"}, | ||
361 | {HPHW_A_DMA, 0x004, 0x0009D, 0x80, "HP HSC-PCI Cards"}, | ||
362 | {HPHW_A_DMA, 0x004, 0x0009E, 0x80, "Alaxis GSC+ 155Mb ATM"}, | ||
363 | {HPHW_A_DMA, 0x005, 0x0009E, 0x80, "Alaxis GSC+ 622Mb ATM"}, | ||
364 | {HPHW_A_DMA, 0x05C, 0x0009F, 0x80, "SummitHawk 230 USB"}, | ||
365 | {HPHW_A_DMA, 0x05C, 0x000A0, 0x80, "SummitHawk 230 100BaseT"}, | ||
366 | {HPHW_A_DMA, 0x015, 0x000A7, 0x80, "Baby Hugo Add-on mass FC (A3404A)"}, | ||
367 | {HPHW_A_DMA, 0x018, 0x000A7, 0x80, "Mombasa GS Add-on mass FC (A3591)"}, | ||
368 | {HPHW_A_DMA, 0x021, 0x000A7, 0x80, "Baby Jade Add-on mass FC (A3636A)"}, | ||
369 | {HPHW_A_DMA, 0x004, 0x00201, 0x80, "MELCO HCMAP"}, | ||
370 | {HPHW_A_DMA, 0x004, 0x00202, 0x80, "MELCO HBMLA MLAMA"}, | ||
371 | {HPHW_A_DMA, 0x004, 0x00205, 0x80, "MELCO HBRFU"}, | ||
372 | {HPHW_A_DMA, 0x004, 0x00380, 0x80, "Interphase NIO-FC"}, | ||
373 | {HPHW_A_DMA, 0x004, 0x00381, 0x80, "Interphase NIO-ATM"}, | ||
374 | {HPHW_A_DMA, 0x004, 0x00382, 0x80, "Interphase NIO-100BaseTX"}, | ||
375 | {HPHW_BA, 0x004, 0x00070, 0x0, "Cobra Core BA"}, | ||
376 | {HPHW_BA, 0x005, 0x00070, 0x0, "Coral Core BA"}, | ||
377 | {HPHW_BA, 0x006, 0x00070, 0x0, "Bushmaster Core BA"}, | ||
378 | {HPHW_BA, 0x007, 0x00070, 0x0, "Scorpio Core BA"}, | ||
379 | {HPHW_BA, 0x008, 0x00070, 0x0, "Flounder Core BA"}, | ||
380 | {HPHW_BA, 0x009, 0x00070, 0x0, "Outfield Core BA"}, | ||
381 | {HPHW_BA, 0x00A, 0x00070, 0x0, "CoralII Core BA"}, | ||
382 | {HPHW_BA, 0x00B, 0x00070, 0x0, "Scorpio Jr. Core BA"}, | ||
383 | {HPHW_BA, 0x00C, 0x00070, 0x0, "Strider-50 Core BA"}, | ||
384 | {HPHW_BA, 0x00D, 0x00070, 0x0, "Strider-33 Core BA"}, | ||
385 | {HPHW_BA, 0x00E, 0x00070, 0x0, "Trailways-50 Core BA"}, | ||
386 | {HPHW_BA, 0x00F, 0x00070, 0x0, "Trailways-33 Core BA"}, | ||
387 | {HPHW_BA, 0x010, 0x00070, 0x0, "Pace Core BA"}, | ||
388 | {HPHW_BA, 0x011, 0x00070, 0x0, "Sidewinder Core BA"}, | ||
389 | {HPHW_BA, 0x019, 0x00070, 0x0, "Scorpio Sr. Core BA"}, | ||
390 | {HPHW_BA, 0x020, 0x00070, 0x0, "Scorpio 100 Core BA"}, | ||
391 | {HPHW_BA, 0x021, 0x00070, 0x0, "Spectra 50 Core BA"}, | ||
392 | {HPHW_BA, 0x022, 0x00070, 0x0, "Spectra 75 Core BA"}, | ||
393 | {HPHW_BA, 0x023, 0x00070, 0x0, "Spectra 100 Core BA"}, | ||
394 | {HPHW_BA, 0x024, 0x00070, 0x0, "Fast Pace Core BA"}, | ||
395 | {HPHW_BA, 0x026, 0x00070, 0x0, "CoralII Jaguar Core BA"}, | ||
396 | {HPHW_BA, 0x004, 0x00076, 0x0, "Cobra EISA BA"}, | ||
397 | {HPHW_BA, 0x005, 0x00076, 0x0, "Coral EISA BA"}, | ||
398 | {HPHW_BA, 0x007, 0x00076, 0x0, "Scorpio EISA BA"}, | ||
399 | {HPHW_BA, 0x00A, 0x00076, 0x0, "CoralII EISA BA"}, | ||
400 | {HPHW_BA, 0x00B, 0x00076, 0x0, "Scorpio Jr. EISA BA"}, | ||
401 | {HPHW_BA, 0x00C, 0x00076, 0x0, "Strider-50 Core EISA"}, | ||
402 | {HPHW_BA, 0x00D, 0x00076, 0x0, "Strider-33 Core EISA"}, | ||
403 | {HPHW_BA, 0x00E, 0x00076, 0x0, "Trailways-50 Core EISA"}, | ||
404 | {HPHW_BA, 0x00F, 0x00076, 0x0, "Trailways-33 Core EISA"}, | ||
405 | {HPHW_BA, 0x010, 0x00076, 0x0, "Pace Core EISA"}, | ||
406 | {HPHW_BA, 0x019, 0x00076, 0x0, "Scorpio Sr. EISA BA"}, | ||
407 | {HPHW_BA, 0x020, 0x00076, 0x0, "Scorpio 100 EISA BA"}, | ||
408 | {HPHW_BA, 0x021, 0x00076, 0x0, "Spectra 50 EISA BA"}, | ||
409 | {HPHW_BA, 0x022, 0x00076, 0x0, "Spectra 75 EISA BA"}, | ||
410 | {HPHW_BA, 0x023, 0x00076, 0x0, "Spectra 100 EISA BA"}, | ||
411 | {HPHW_BA, 0x026, 0x00076, 0x0, "CoralII Jaguar EISA BA"}, | ||
412 | {HPHW_BA, 0x010, 0x00078, 0x0, "Pace VME BA"}, | ||
413 | {HPHW_BA, 0x011, 0x00078, 0x0, "Sidewinder VME BA"}, | ||
414 | {HPHW_BA, 0x01A, 0x00078, 0x0, "Anole 64 VME BA"}, | ||
415 | {HPHW_BA, 0x01B, 0x00078, 0x0, "Anole 100 VME BA"}, | ||
416 | {HPHW_BA, 0x024, 0x00078, 0x0, "Fast Pace VME BA"}, | ||
417 | {HPHW_BA, 0x034, 0x00078, 0x0, "Anole T VME BA"}, | ||
418 | {HPHW_BA, 0x04A, 0x00078, 0x0, "Anole L2 132 VME BA"}, | ||
419 | {HPHW_BA, 0x04C, 0x00078, 0x0, "Anole L2 165 VME BA"}, | ||
420 | {HPHW_BA, 0x011, 0x00081, 0x0, "WB-96 Core BA"}, | ||
421 | {HPHW_BA, 0x012, 0x00081, 0x0, "Orville UX Core BA"}, | ||
422 | {HPHW_BA, 0x013, 0x00081, 0x0, "Wilbur UX Core BA"}, | ||
423 | {HPHW_BA, 0x014, 0x00081, 0x0, "WB-80 Core BA"}, | ||
424 | {HPHW_BA, 0x015, 0x00081, 0x0, "KittyHawk GSY Core BA"}, | ||
425 | {HPHW_BA, 0x016, 0x00081, 0x0, "Gecko Core BA"}, | ||
426 | {HPHW_BA, 0x018, 0x00081, 0x0, "Gecko Optional BA"}, | ||
427 | {HPHW_BA, 0x01A, 0x00081, 0x0, "Anole 64 Core BA"}, | ||
428 | {HPHW_BA, 0x01B, 0x00081, 0x0, "Anole 100 Core BA"}, | ||
429 | {HPHW_BA, 0x01C, 0x00081, 0x0, "Gecko 80 Core BA"}, | ||
430 | {HPHW_BA, 0x01D, 0x00081, 0x0, "Gecko 100 Core BA"}, | ||
431 | {HPHW_BA, 0x01F, 0x00081, 0x0, "SkyHawk 100/120 Core BA"}, | ||
432 | {HPHW_BA, 0x027, 0x00081, 0x0, "Piranha 100 Core BA"}, | ||
433 | {HPHW_BA, 0x028, 0x00081, 0x0, "Mirage Jr Core BA"}, | ||
434 | {HPHW_BA, 0x029, 0x00081, 0x0, "Mirage Core BA"}, | ||
435 | {HPHW_BA, 0x02A, 0x00081, 0x0, "Electra Core BA"}, | ||
436 | {HPHW_BA, 0x02B, 0x00081, 0x0, "Mirage 80 Core BA"}, | ||
437 | {HPHW_BA, 0x02C, 0x00081, 0x0, "Mirage 100+ Core BA"}, | ||
438 | {HPHW_BA, 0x02E, 0x00081, 0x0, "UL 350 Lasi Core BA"}, | ||
439 | {HPHW_BA, 0x02F, 0x00081, 0x0, "UL 550 Lasi Core BA"}, | ||
440 | {HPHW_BA, 0x032, 0x00081, 0x0, "Raven T' Core BA"}, | ||
441 | {HPHW_BA, 0x033, 0x00081, 0x0, "Anole T Core BA"}, | ||
442 | {HPHW_BA, 0x034, 0x00081, 0x0, "SAIC L-80 Core BA"}, | ||
443 | {HPHW_BA, 0x035, 0x00081, 0x0, "PCX-L2 712/132 Core BA"}, | ||
444 | {HPHW_BA, 0x036, 0x00081, 0x0, "PCX-L2 712/160 Core BA"}, | ||
445 | {HPHW_BA, 0x03B, 0x00081, 0x0, "Raven U/L2 Core BA"}, | ||
446 | {HPHW_BA, 0x03C, 0x00081, 0x0, "Merlin 132 Core BA"}, | ||
447 | {HPHW_BA, 0x03D, 0x00081, 0x0, "Merlin 160 Core BA"}, | ||
448 | {HPHW_BA, 0x03E, 0x00081, 0x0, "Merlin+ 132 Core BA"}, | ||
449 | {HPHW_BA, 0x03F, 0x00081, 0x0, "Merlin+ 180 Core BA"}, | ||
450 | {HPHW_BA, 0x044, 0x00081, 0x0, "Mohawk Core BA"}, | ||
451 | {HPHW_BA, 0x045, 0x00081, 0x0, "Rocky1 Core BA"}, | ||
452 | {HPHW_BA, 0x046, 0x00081, 0x0, "Rocky2 120 Core BA"}, | ||
453 | {HPHW_BA, 0x047, 0x00081, 0x0, "Rocky2 150 Core BA"}, | ||
454 | {HPHW_BA, 0x04B, 0x00081, 0x0, "Anole L2 132 Core BA"}, | ||
455 | {HPHW_BA, 0x04D, 0x00081, 0x0, "Anole L2 165 Core BA"}, | ||
456 | {HPHW_BA, 0x04E, 0x00081, 0x0, "Kiji L2 132 Core BA"}, | ||
457 | {HPHW_BA, 0x050, 0x00081, 0x0, "Merlin Jr 132 Core BA"}, | ||
458 | {HPHW_BA, 0x051, 0x00081, 0x0, "Firehawk Core BA"}, | ||
459 | {HPHW_BA, 0x056, 0x00081, 0x0, "Raven+ w SE FWSCSI Core BA"}, | ||
460 | {HPHW_BA, 0x057, 0x00081, 0x0, "Raven+ w Diff FWSCSI Core BA"}, | ||
461 | {HPHW_BA, 0x058, 0x00081, 0x0, "FireHawk 200 Core BA"}, | ||
462 | {HPHW_BA, 0x05C, 0x00081, 0x0, "SummitHawk 230 Core BA"}, | ||
463 | {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 132 Core BA"}, | ||
464 | {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 180 Core BA"}, | ||
465 | {HPHW_BA, 0x05F, 0x00081, 0x0, "Staccato 180 Lasi"}, | ||
466 | {HPHW_BA, 0x800, 0x00081, 0x0, "Hitachi Tiny 64 Core BA"}, | ||
467 | {HPHW_BA, 0x801, 0x00081, 0x0, "Hitachi Tiny 80 Core BA"}, | ||
468 | {HPHW_BA, 0x004, 0x0008B, 0x0, "Anole Optional PCMCIA BA"}, | ||
469 | {HPHW_BA, 0x004, 0x0008E, 0x0, "GSC ITR Wax BA"}, | ||
470 | {HPHW_BA, 0x00C, 0x0008E, 0x0, "Gecko Optional Wax BA"}, | ||
471 | {HPHW_BA, 0x010, 0x0008E, 0x0, "Pace Wax BA"}, | ||
472 | {HPHW_BA, 0x011, 0x0008E, 0x0, "SuperPace Wax BA"}, | ||
473 | {HPHW_BA, 0x012, 0x0008E, 0x0, "Mirage Jr Wax BA"}, | ||
474 | {HPHW_BA, 0x013, 0x0008E, 0x0, "Mirage Wax BA"}, | ||
475 | {HPHW_BA, 0x014, 0x0008E, 0x0, "Electra Wax BA"}, | ||
476 | {HPHW_BA, 0x017, 0x0008E, 0x0, "Raven Backplane Wax BA"}, | ||
477 | {HPHW_BA, 0x01E, 0x0008E, 0x0, "Raven T' Wax BA"}, | ||
478 | {HPHW_BA, 0x01F, 0x0008E, 0x0, "SkyHawk Wax BA"}, | ||
479 | {HPHW_BA, 0x023, 0x0008E, 0x0, "Rocky1 Wax BA"}, | ||
480 | {HPHW_BA, 0x02B, 0x0008E, 0x0, "Mirage 80 Wax BA"}, | ||
481 | {HPHW_BA, 0x02C, 0x0008E, 0x0, "Mirage 100+ Wax BA"}, | ||
482 | {HPHW_BA, 0x030, 0x0008E, 0x0, "UL 350 Core Wax BA"}, | ||
483 | {HPHW_BA, 0x031, 0x0008E, 0x0, "UL 550 Core Wax BA"}, | ||
484 | {HPHW_BA, 0x034, 0x0008E, 0x0, "SAIC L-80 Wax BA"}, | ||
485 | {HPHW_BA, 0x03A, 0x0008E, 0x0, "Merlin+ Wax BA"}, | ||
486 | {HPHW_BA, 0x040, 0x0008E, 0x0, "Merlin 132 Wax BA"}, | ||
487 | {HPHW_BA, 0x041, 0x0008E, 0x0, "Merlin 160 Wax BA"}, | ||
488 | {HPHW_BA, 0x043, 0x0008E, 0x0, "Merlin 132/160 Wax BA"}, | ||
489 | {HPHW_BA, 0x052, 0x0008E, 0x0, "Raven+ Hi Power Backplane w/EISA Wax BA"}, | ||
490 | {HPHW_BA, 0x054, 0x0008E, 0x0, "Raven+ Lo Power Backplane w/EISA Wax BA"}, | ||
491 | {HPHW_BA, 0x059, 0x0008E, 0x0, "FireHawk 200 Wax BA"}, | ||
492 | {HPHW_BA, 0x05A, 0x0008E, 0x0, "Raven+ L2 Backplane w/EISA Wax BA"}, | ||
493 | {HPHW_BA, 0x05D, 0x0008E, 0x0, "SummitHawk Wax BA"}, | ||
494 | {HPHW_BA, 0x800, 0x0008E, 0x0, "Hitachi Tiny 64 Wax BA"}, | ||
495 | {HPHW_BA, 0x801, 0x0008E, 0x0, "Hitachi Tiny 80 Wax BA"}, | ||
496 | {HPHW_BA, 0x011, 0x00090, 0x0, "SuperPace Wax EISA BA"}, | ||
497 | {HPHW_BA, 0x017, 0x00090, 0x0, "Raven Backplane Wax EISA BA"}, | ||
498 | {HPHW_BA, 0x01E, 0x00090, 0x0, "Raven T' Wax EISA BA"}, | ||
499 | {HPHW_BA, 0x01F, 0x00090, 0x0, "SkyHawk 100/120 Wax EISA BA"}, | ||
500 | {HPHW_BA, 0x027, 0x00090, 0x0, "Piranha 100 Wax EISA BA"}, | ||
501 | {HPHW_BA, 0x028, 0x00090, 0x0, "Mirage Jr Wax EISA BA"}, | ||
502 | {HPHW_BA, 0x029, 0x00090, 0x0, "Mirage Wax EISA BA"}, | ||
503 | {HPHW_BA, 0x02A, 0x00090, 0x0, "Electra Wax EISA BA"}, | ||
504 | {HPHW_BA, 0x02B, 0x00090, 0x0, "Mirage 80 Wax EISA BA"}, | ||
505 | {HPHW_BA, 0x02C, 0x00090, 0x0, "Mirage 100+ Wax EISA BA"}, | ||
506 | {HPHW_BA, 0x030, 0x00090, 0x0, "UL 350 Wax EISA BA"}, | ||
507 | {HPHW_BA, 0x031, 0x00090, 0x0, "UL 550 Wax EISA BA"}, | ||
508 | {HPHW_BA, 0x034, 0x00090, 0x0, "SAIC L-80 Wax EISA BA"}, | ||
509 | {HPHW_BA, 0x03A, 0x00090, 0x0, "Merlin+ Wax EISA BA"}, | ||
510 | {HPHW_BA, 0x040, 0x00090, 0x0, "Merlin 132 Wax EISA BA"}, | ||
511 | {HPHW_BA, 0x041, 0x00090, 0x0, "Merlin 160 Wax EISA BA"}, | ||
512 | {HPHW_BA, 0x043, 0x00090, 0x0, "Merlin 132/160 Wax EISA BA"}, | ||
513 | {HPHW_BA, 0x052, 0x00090, 0x0, "Raven Hi Power Backplane Wax EISA BA"}, | ||
514 | {HPHW_BA, 0x054, 0x00090, 0x0, "Raven Lo Power Backplane Wax EISA BA"}, | ||
515 | {HPHW_BA, 0x059, 0x00090, 0x0, "FireHawk 200 Wax EISA BA"}, | ||
516 | {HPHW_BA, 0x05A, 0x00090, 0x0, "Raven L2 Backplane Wax EISA BA"}, | ||
517 | {HPHW_BA, 0x05D, 0x00090, 0x0, "SummitHawk Wax EISA BA"}, | ||
518 | {HPHW_BA, 0x800, 0x00090, 0x0, "Hitachi Tiny 64 Wax EISA BA"}, | ||
519 | {HPHW_BA, 0x801, 0x00090, 0x0, "Hitachi Tiny 80 Wax EISA BA"}, | ||
520 | {HPHW_BA, 0x01A, 0x00093, 0x0, "Anole 64 TIMI BA"}, | ||
521 | {HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 100 TIMI BA"}, | ||
522 | {HPHW_BA, 0x034, 0x00093, 0x0, "Anole T TIMI BA"}, | ||
523 | {HPHW_BA, 0x04A, 0x00093, 0x0, "Anole L2 132 TIMI BA"}, | ||
524 | {HPHW_BA, 0x04C, 0x00093, 0x0, "Anole L2 165 TIMI BA"}, | ||
525 | {HPHW_BA, 0x582, 0x000A5, 0x00, "Epic PCI Bridge"}, | ||
526 | {HPHW_BCPORT, 0x504, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"}, | ||
527 | {HPHW_BCPORT, 0x505, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"}, | ||
528 | {HPHW_BCPORT, 0x503, 0x0000C, 0x00, "Java BC GSC+ Port"}, | ||
529 | {HPHW_BCPORT, 0x57F, 0x0000C, 0x00, "Hitachi Ghostview GSC+ Port"}, | ||
530 | {HPHW_BCPORT, 0x501, 0x0000C, 0x00, "U2-IOA BC GSC+ Port"}, | ||
531 | {HPHW_BCPORT, 0x502, 0x0000C, 0x00, "Uturn-IOA BC GSC+ Port"}, | ||
532 | {HPHW_BCPORT, 0x780, 0x0000C, 0x00, "Astro BC Ropes Port"}, | ||
533 | {HPHW_BCPORT, 0x506, 0x0000C, 0x00, "NEC-IOS BC HSC Port"}, | ||
534 | {HPHW_BCPORT, 0x004, 0x0000C, 0x00, "Cheetah BC SMB Port"}, | ||
535 | {HPHW_BCPORT, 0x006, 0x0000C, 0x00, "Cheetah BC MID_BUS Port"}, | ||
536 | {HPHW_BCPORT, 0x005, 0x0000C, 0x00, "Condor BC MID_BUS Port"}, | ||
537 | {HPHW_BCPORT, 0x100, 0x0000C, 0x00, "Condor BC HP-PB Port"}, | ||
538 | {HPHW_BCPORT, 0x184, 0x0000C, 0x00, "Summit BC Port"}, | ||
539 | {HPHW_BCPORT, 0x101, 0x0000C, 0x00, "Summit BC HP-PB Port"}, | ||
540 | {HPHW_BCPORT, 0x102, 0x0000C, 0x00, "HP-PB Port (prefetch)"}, | ||
541 | {HPHW_BCPORT, 0x500, 0x0000C, 0x00, "Gecko BOA BC GSC+ Port"}, | ||
542 | {HPHW_BCPORT, 0x103, 0x0000C, 0x00, "Gecko BOA BC HP-PB Port"}, | ||
543 | {HPHW_BCPORT, 0x507, 0x0000C, 0x00, "Keyaki BC GSC+ Port"}, | ||
544 | {HPHW_BCPORT, 0x508, 0x0000C, 0x00, "Keyaki-DX BC GSC+ Port"}, | ||
545 | {HPHW_BCPORT, 0x584, 0x0000C, 0x10, "DEW BC Runway Port"}, | ||
546 | {HPHW_BCPORT, 0x800, 0x0000C, 0x10, "DEW BC Merced Port"}, | ||
547 | {HPHW_BCPORT, 0x801, 0x0000C, 0x10, "SMC Bus Interface Merced Bus0"}, | ||
548 | {HPHW_BCPORT, 0x802, 0x0000C, 0x10, "SMC Bus INterface Merced Bus1"}, | ||
549 | {HPHW_BCPORT, 0x803, 0x0000C, 0x10, "IKE I/O BC Merced Port"}, | ||
550 | {HPHW_BCPORT, 0x781, 0x0000C, 0x00, "IKE I/O BC Ropes Port"}, | ||
551 | {HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O BC Merced Port"}, | ||
552 | {HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O BC Ropes Port"}, | ||
553 | {HPHW_BCPORT, 0x784, 0x0000C, 0x00, "Pluto I/O BC Ropes Port"}, | ||
554 | {HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"}, | ||
555 | {HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"}, | ||
556 | {HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"}, | ||
557 | {HPHW_BRIDGE, 0x583, 0x000A5, 0x00, "Saga PCI Bridge"}, | ||
558 | {HPHW_BRIDGE, 0x783, 0x0000A, 0x00, "Mercury PCI Bridge"}, | ||
559 | {HPHW_BRIDGE, 0x784, 0x0000A, 0x00, "Quicksilver AGP Bridge"}, | ||
560 | {HPHW_B_DMA, 0x004, 0x00018, 0x00, "Parallel I/O"}, | ||
561 | {HPHW_B_DMA, 0x004, 0x00019, 0x00, "Parallel RDB"}, | ||
562 | {HPHW_B_DMA, 0x004, 0x00020, 0x80, "MID_BUS PSI"}, | ||
563 | {HPHW_B_DMA, 0x004, 0x0002F, 0x80, "HP-PB Transit PSI (36960A)"}, | ||
564 | {HPHW_B_DMA, 0x008, 0x00051, 0x80, "HP-PB Transit 802.3"}, | ||
565 | {HPHW_B_DMA, 0x004, 0x00052, 0x80, "Miura LAN/Console (J2146A)"}, | ||
566 | {HPHW_B_DMA, 0x008, 0x00058, 0x80, "HP-PB Transit 802.4"}, | ||
567 | {HPHW_B_DMA, 0x005, 0x00060, 0x80, "KittyHawk CSY Core LAN/Console"}, | ||
568 | {HPHW_B_DMA, 0x014, 0x00060, 0x80, "Diablo LAN/Console"}, | ||
569 | {HPHW_B_DMA, 0x054, 0x00060, 0x80, "Countach LAN/Console"}, | ||
570 | {HPHW_B_DMA, 0x004, 0x00094, 0x80, "KittyHawk GSC+ Exerciser"}, | ||
571 | {HPHW_B_DMA, 0x004, 0x00100, 0x80, "HP-PB HF Interface"}, | ||
572 | {HPHW_B_DMA, 0x000, 0x00206, 0x80, "MELCO HMPHA"}, | ||
573 | {HPHW_B_DMA, 0x005, 0x00206, 0x80, "MELCO HMPHA_10"}, | ||
574 | {HPHW_B_DMA, 0x006, 0x00206, 0x80, "MELCO HMQHA"}, | ||
575 | {HPHW_B_DMA, 0x007, 0x00206, 0x80, "MELCO HMQHA_10"}, | ||
576 | {HPHW_B_DMA, 0x004, 0x207, 0x80, "MELCO HNDWA MDWS-70"}, | ||
577 | {HPHW_CIO, 0x004, 0x00010, 0x00, "VLSI CIO"}, | ||
578 | {HPHW_CIO, 0x005, 0x00010, 0x00, "Silverfox CIO"}, | ||
579 | {HPHW_CIO, 0x006, 0x00010, 0x00, "Emerald CIO"}, | ||
580 | {HPHW_CIO, 0x008, 0x00010, 0x00, "Discrete CIO"}, | ||
581 | {HPHW_CONSOLE, 0x004, 0x0001C, 0x00, "Cheetah console"}, | ||
582 | {HPHW_CONSOLE, 0x005, 0x0001C, 0x00, "Emerald console"}, | ||
583 | {HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"}, | ||
584 | {HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"}, | ||
585 | {HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"}, | ||
586 | {HPHW_FABRIC, 0x007, 0x000AA, 0x80, "Caribe DNA Central Agent"}, | ||
587 | {HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"}, | ||
588 | {HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"}, | ||
589 | {HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"}, | ||
590 | {HPHW_FIO, 0x004, 0x0004F, 0x0, "8-Port X.25 EISA-ACC (AMSO)"}, | ||
591 | {HPHW_FIO, 0x004, 0x00071, 0x0, "Cobra Core SCSI"}, | ||
592 | {HPHW_FIO, 0x005, 0x00071, 0x0, "Coral Core SCSI"}, | ||
593 | {HPHW_FIO, 0x006, 0x00071, 0x0, "Bushmaster Core SCSI"}, | ||
594 | {HPHW_FIO, 0x007, 0x00071, 0x0, "Scorpio Core SCSI"}, | ||
595 | {HPHW_FIO, 0x008, 0x00071, 0x0, "Flounder Core SCSI"}, | ||
596 | {HPHW_FIO, 0x009, 0x00071, 0x0, "Outfield Core SCSI"}, | ||
597 | {HPHW_FIO, 0x00A, 0x00071, 0x0, "CoralII Core SCSI"}, | ||
598 | {HPHW_FIO, 0x00B, 0x00071, 0x0, "Scorpio Jr. Core SCSI"}, | ||
599 | {HPHW_FIO, 0x00C, 0x00071, 0x0, "Strider-50 Core SCSI"}, | ||
600 | {HPHW_FIO, 0x00D, 0x00071, 0x0, "Strider-33 Core SCSI"}, | ||
601 | {HPHW_FIO, 0x00E, 0x00071, 0x0, "Trailways-50 Core SCSI"}, | ||
602 | {HPHW_FIO, 0x00F, 0x00071, 0x0, "Trailways-33 Core SCSI"}, | ||
603 | {HPHW_FIO, 0x010, 0x00071, 0x0, "Pace Core SCSI"}, | ||
604 | {HPHW_FIO, 0x011, 0x00071, 0x0, "Sidewinder Core SCSI"}, | ||
605 | {HPHW_FIO, 0x019, 0x00071, 0x0, "Scorpio Sr. Core SCSI"}, | ||
606 | {HPHW_FIO, 0x020, 0x00071, 0x0, "Scorpio 100 Core SCSI"}, | ||
607 | {HPHW_FIO, 0x021, 0x00071, 0x0, "Spectra 50 Core SCSI"}, | ||
608 | {HPHW_FIO, 0x022, 0x00071, 0x0, "Spectra 75 Core SCSI"}, | ||
609 | {HPHW_FIO, 0x023, 0x00071, 0x0, "Spectra 100 Core SCSI"}, | ||
610 | {HPHW_FIO, 0x024, 0x00071, 0x0, "Fast Pace Core SCSI"}, | ||
611 | {HPHW_FIO, 0x026, 0x00071, 0x0, "CoralII Jaguar Core SCSI"}, | ||
612 | {HPHW_FIO, 0x004, 0x00072, 0x0, "Cobra Core LAN (802.3)"}, | ||
613 | {HPHW_FIO, 0x005, 0x00072, 0x0, "Coral Core LAN (802.3)"}, | ||
614 | {HPHW_FIO, 0x006, 0x00072, 0x0, "Bushmaster Core LAN (802.3)"}, | ||
615 | {HPHW_FIO, 0x007, 0x00072, 0x0, "Scorpio Core LAN (802.3)"}, | ||
616 | {HPHW_FIO, 0x008, 0x00072, 0x0, "Flounder Core LAN (802.3)"}, | ||
617 | {HPHW_FIO, 0x009, 0x00072, 0x0, "Outfield Core LAN (802.3)"}, | ||
618 | {HPHW_FIO, 0x00A, 0x00072, 0x0, "CoralII Core LAN (802.3)"}, | ||
619 | {HPHW_FIO, 0x00B, 0x00072, 0x0, "Scorpio Jr. Core LAN (802.3)"}, | ||
620 | {HPHW_FIO, 0x00C, 0x00072, 0x0, "Strider-50 Core LAN (802.3)"}, | ||
621 | {HPHW_FIO, 0x00D, 0x00072, 0x0, "Strider-33 Core LAN (802.3)"}, | ||
622 | {HPHW_FIO, 0x00E, 0x00072, 0x0, "Trailways-50 Core LAN (802.3)"}, | ||
623 | {HPHW_FIO, 0x00F, 0x00072, 0x0, "Trailways-33 Core LAN (802.3)"}, | ||
624 | {HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core LAN (802.3)"}, | ||
625 | {HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core LAN (802.3)"}, | ||
626 | {HPHW_FIO, 0x019, 0x00072, 0x0, "Scorpio Sr. Core LAN (802.3)"}, | ||
627 | {HPHW_FIO, 0x020, 0x00072, 0x0, "Scorpio 100 Core LAN (802.3)"}, | ||
628 | {HPHW_FIO, 0x021, 0x00072, 0x0, "Spectra 50 Core LAN (802.3)"}, | ||
629 | {HPHW_FIO, 0x022, 0x00072, 0x0, "Spectra 75 Core LAN (802.3)"}, | ||
630 | {HPHW_FIO, 0x023, 0x00072, 0x0, "Spectra 100 Core LAN (802.3)"}, | ||
631 | {HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core LAN (802.3)"}, | ||
632 | {HPHW_FIO, 0x026, 0x00072, 0x0, "CoralII Jaguar Core LAN (802.3)"}, | ||
633 | {HPHW_FIO, 0x004, 0x00073, 0x0, "Cobra Core HIL"}, | ||
634 | {HPHW_FIO, 0x005, 0x00073, 0x0, "Coral Core HIL"}, | ||
635 | {HPHW_FIO, 0x006, 0x00073, 0x0, "Bushmaster Core HIL"}, | ||
636 | {HPHW_FIO, 0x007, 0x00073, 0x0, "Scorpio Core HIL"}, | ||
637 | {HPHW_FIO, 0x008, 0x00073, 0x0, "Flounder Core HIL"}, | ||
638 | {HPHW_FIO, 0x009, 0x00073, 0x0, "Outfield Core HIL"}, | ||
639 | {HPHW_FIO, 0x00A, 0x00073, 0x0, "CoralII Core HIL"}, | ||
640 | {HPHW_FIO, 0x00B, 0x00073, 0x0, "Scorpio Jr. Core HIL"}, | ||
641 | {HPHW_FIO, 0x00C, 0x00073, 0x0, "Strider-50 Core HIL"}, | ||
642 | {HPHW_FIO, 0x00D, 0x00073, 0x0, "Strider-33 Core HIL"}, | ||
643 | {HPHW_FIO, 0x00E, 0x00073, 0x0, "Trailways-50 Core HIL"}, | ||
644 | {HPHW_FIO, 0x00F, 0x00073, 0x0, "Trailways-33 Core HIL"}, | ||
645 | {HPHW_FIO, 0x010, 0x00073, 0x0, "Pace Core HIL"}, | ||
646 | {HPHW_FIO, 0x011, 0x00073, 0xcc, "SuperPace Wax HIL"}, | ||
647 | {HPHW_FIO, 0x012, 0x00073, 0x0, "Mirage Jr Wax HIL"}, | ||
648 | {HPHW_FIO, 0x013, 0x00073, 0x0, "Mirage 100 Wax HIL"}, | ||
649 | {HPHW_FIO, 0x014, 0x00073, 0x0, "Electra Wax HIL"}, | ||
650 | {HPHW_FIO, 0x017, 0x00073, 0x0, "Raven Backplane Wax HIL"}, | ||
651 | {HPHW_FIO, 0x019, 0x00073, 0x0, "Scorpio Sr. Core HIL"}, | ||
652 | {HPHW_FIO, 0x01E, 0x00073, 0x0, "Raven T' Wax HIL"}, | ||
653 | {HPHW_FIO, 0x01F, 0x00073, 0x0, "SkyHawk 100/120 Wax HIL"}, | ||
654 | {HPHW_FIO, 0x020, 0x00073, 0x0, "Scorpio 100 Core HIL"}, | ||
655 | {HPHW_FIO, 0x021, 0x00073, 0x0, "Spectra 50 Core HIL"}, | ||
656 | {HPHW_FIO, 0x022, 0x00073, 0x0, "Spectra 75 Core HIL"}, | ||
657 | {HPHW_FIO, 0x023, 0x00073, 0x0, "Spectra 100 Core HIL"}, | ||
658 | {HPHW_FIO, 0x024, 0x00073, 0x0, "Fast Pace Core HIL"}, | ||
659 | {HPHW_FIO, 0x026, 0x00073, 0x0, "CoralII Jaguar Core HIL"}, | ||
660 | {HPHW_FIO, 0x02B, 0x00073, 0x0, "Mirage 80 Wax HIL"}, | ||
661 | {HPHW_FIO, 0x02C, 0x00073, 0x0, "Mirage 100+ Wax HIL"}, | ||
662 | {HPHW_FIO, 0x03A, 0x00073, 0x0, "Merlin+ Wax HIL"}, | ||
663 | {HPHW_FIO, 0x040, 0x00073, 0x0, "Merlin 132 Wax HIL"}, | ||
664 | {HPHW_FIO, 0x041, 0x00073, 0x0, "Merlin 160 Wax HIL"}, | ||
665 | {HPHW_FIO, 0x043, 0x00073, 0x0, "Merlin 132/160 Wax HIL"}, | ||
666 | {HPHW_FIO, 0x052, 0x00073, 0x0, "Raven+ Hi Power Backplane w/EISA Wax HIL"}, | ||
667 | {HPHW_FIO, 0x053, 0x00073, 0x0, "Raven+ Hi Power Backplane wo/EISA Wax HIL"}, | ||
668 | {HPHW_FIO, 0x054, 0x00073, 0x0, "Raven+ Lo Power Backplane w/EISA Wax HIL"}, | ||
669 | {HPHW_FIO, 0x055, 0x00073, 0x0, "Raven+ Lo Power Backplane wo/EISA Wax HIL"}, | ||
670 | {HPHW_FIO, 0x059, 0x00073, 0x0, "FireHawk 200 Wax HIL"}, | ||
671 | {HPHW_FIO, 0x05A, 0x00073, 0x0, "Raven+ L2 Backplane w/EISA Wax HIL"}, | ||
672 | {HPHW_FIO, 0x05B, 0x00073, 0x0, "Raven+ L2 Backplane wo/EISA Wax HIL"}, | ||
673 | {HPHW_FIO, 0x05D, 0x00073, 0x0, "SummitHawk Wax HIL"}, | ||
674 | {HPHW_FIO, 0x800, 0x00073, 0x0, "Hitachi Tiny 64 Wax HIL"}, | ||
675 | {HPHW_FIO, 0x801, 0x00073, 0x0, "Hitachi Tiny 80 Wax HIL"}, | ||
676 | {HPHW_FIO, 0x004, 0x00074, 0x0, "Cobra Core Centronics"}, | ||
677 | {HPHW_FIO, 0x005, 0x00074, 0x0, "Coral Core Centronics"}, | ||
678 | {HPHW_FIO, 0x006, 0x00074, 0x0, "Bushmaster Core Centronics"}, | ||
679 | {HPHW_FIO, 0x007, 0x00074, 0x0, "Scorpio Core Centronics"}, | ||
680 | {HPHW_FIO, 0x008, 0x00074, 0x0, "Flounder Core Centronics"}, | ||
681 | {HPHW_FIO, 0x009, 0x00074, 0x0, "Outfield Core Centronics"}, | ||
682 | {HPHW_FIO, 0x00A, 0x00074, 0x0, "CoralII Core Centronics"}, | ||
683 | {HPHW_FIO, 0x00B, 0x00074, 0x0, "Scorpio Jr. Core Centronics"}, | ||
684 | {HPHW_FIO, 0x00C, 0x00074, 0x0, "Strider-50 Core Centronics"}, | ||
685 | {HPHW_FIO, 0x00D, 0x00074, 0x0, "Strider-33 Core Centronics"}, | ||
686 | {HPHW_FIO, 0x00E, 0x00074, 0x0, "Trailways-50 Core Centronics"}, | ||
687 | {HPHW_FIO, 0x00F, 0x00074, 0x0, "Trailways-33 Core Centronics"}, | ||
688 | {HPHW_FIO, 0x010, 0x00074, 0x0, "Pace Core Centronics"}, | ||
689 | {HPHW_FIO, 0x011, 0x00074, 0x0, "Sidewinder Core Centronics"}, | ||
690 | {HPHW_FIO, 0x015, 0x00074, 0x0, "KittyHawk GSY Core Centronics"}, | ||
691 | {HPHW_FIO, 0x016, 0x00074, 0x0, "Gecko Core Centronics"}, | ||
692 | {HPHW_FIO, 0x019, 0x00074, 0x0, "Scorpio Sr. Core Centronics"}, | ||
693 | {HPHW_FIO, 0x01A, 0x00074, 0x0, "Anole 64 Core Centronics"}, | ||
694 | {HPHW_FIO, 0x01B, 0x00074, 0x0, "Anole 100 Core Centronics"}, | ||
695 | {HPHW_FIO, 0x01C, 0x00074, 0x0, "Gecko 80 Core Centronics"}, | ||
696 | {HPHW_FIO, 0x01D, 0x00074, 0x0, "Gecko 100 Core Centronics"}, | ||
697 | {HPHW_FIO, 0x01F, 0x00074, 0x0, "SkyHawk 100/120 Core Centronics"}, | ||
698 | {HPHW_FIO, 0x020, 0x00074, 0x0, "Scorpio 100 Core Centronics"}, | ||
699 | {HPHW_FIO, 0x021, 0x00074, 0x0, "Spectra 50 Core Centronics"}, | ||
700 | {HPHW_FIO, 0x022, 0x00074, 0x0, "Spectra 75 Core Centronics"}, | ||
701 | {HPHW_FIO, 0x023, 0x00074, 0x0, "Spectra 100 Core Centronics"}, | ||
702 | {HPHW_FIO, 0x024, 0x00074, 0x0, "Fast Pace Core Centronics"}, | ||
703 | {HPHW_FIO, 0x026, 0x00074, 0x0, "CoralII Jaguar Core Centronics"}, | ||
704 | {HPHW_FIO, 0x027, 0x00074, 0x0, "Piranha 100 Core Centronics"}, | ||
705 | {HPHW_FIO, 0x028, 0x00074, 0x0, "Mirage Jr Core Centronics"}, | ||
706 | {HPHW_FIO, 0x029, 0x00074, 0x0, "Mirage Core Centronics"}, | ||
707 | {HPHW_FIO, 0x02A, 0x00074, 0x0, "Electra Core Centronics"}, | ||
708 | {HPHW_FIO, 0x02B, 0x00074, 0x0, "Mirage 80 Core Centronics"}, | ||
709 | {HPHW_FIO, 0x02C, 0x00074, 0x0, "Mirage 100+ Core Centronics"}, | ||
710 | {HPHW_FIO, 0x02E, 0x00074, 0x0, "UL 350 Core Centronics"}, | ||
711 | {HPHW_FIO, 0x02F, 0x00074, 0x0, "UL 550 Core Centronics"}, | ||
712 | {HPHW_FIO, 0x032, 0x00074, 0x0, "Raven T' Core Centronics"}, | ||
713 | {HPHW_FIO, 0x033, 0x00074, 0x0, "Anole T Core Centronics"}, | ||
714 | {HPHW_FIO, 0x034, 0x00074, 0x0, "SAIC L-80 Core Centronics"}, | ||
715 | {HPHW_FIO, 0x035, 0x00074, 0x0, "PCX-L2 712/132 Core Centronics"}, | ||
716 | {HPHW_FIO, 0x036, 0x00074, 0x0, "PCX-L2 712/160 Core Centronics"}, | ||
717 | {HPHW_FIO, 0x03B, 0x00074, 0x0, "Raven U/L2 Core Centronics"}, | ||
718 | {HPHW_FIO, 0x03C, 0x00074, 0x0, "Merlin 132 Core Centronics"}, | ||
719 | {HPHW_FIO, 0x03D, 0x00074, 0x0, "Merlin 160 Core Centronics"}, | ||
720 | {HPHW_FIO, 0x03E, 0x00074, 0x0, "Merlin+ 132 Core Centronics"}, | ||
721 | {HPHW_FIO, 0x03F, 0x00074, 0x0, "Merlin+ 180 Core Centronics"}, | ||
722 | {HPHW_FIO, 0x044, 0x00074, 0x0, "Mohawk Core Centronics"}, | ||
723 | {HPHW_FIO, 0x045, 0x00074, 0x0, "Rocky1 Core Centronics"}, | ||
724 | {HPHW_FIO, 0x046, 0x00074, 0x0, "Rocky2 120 Core Centronics"}, | ||
725 | {HPHW_FIO, 0x047, 0x00074, 0x0, "Rocky2 150 Core Centronics"}, | ||
726 | {HPHW_FIO, 0x04B, 0x00074, 0x0, "Anole L2 132 Core Centronics"}, | ||
727 | {HPHW_FIO, 0x04D, 0x00074, 0x0, "Anole L2 165 Core Centronics"}, | ||
728 | {HPHW_FIO, 0x050, 0x00074, 0x0, "Merlin Jr 132 Core Centronics"}, | ||
729 | {HPHW_FIO, 0x051, 0x00074, 0x0, "Firehawk Core Centronics"}, | ||
730 | {HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ w SE FWSCSI Core Centronics"}, | ||
731 | {HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ w Diff FWSCSI Core Centronics"}, | ||
732 | {HPHW_FIO, 0x058, 0x00074, 0x0, "FireHawk 200 Core Centronics"}, | ||
733 | {HPHW_FIO, 0x05C, 0x00074, 0x0, "SummitHawk 230 Core Centronics"}, | ||
734 | {HPHW_FIO, 0x800, 0x00074, 0x0, "Hitachi Tiny 64 Core Centronics"}, | ||
735 | {HPHW_FIO, 0x801, 0x00074, 0x0, "Hitachi Tiny 80 Core Centronics"}, | ||
736 | {HPHW_FIO, 0x004, 0x00075, 0x0, "Cobra Core RS-232"}, | ||
737 | {HPHW_FIO, 0x005, 0x00075, 0x0, "Coral Core RS-232"}, | ||
738 | {HPHW_FIO, 0x006, 0x00075, 0x0, "Bushmaster Core RS-232"}, | ||
739 | {HPHW_FIO, 0x007, 0x00075, 0x0, "Scorpio Core RS-232"}, | ||
740 | {HPHW_FIO, 0x008, 0x00075, 0x0, "Flounder Core RS-232"}, | ||
741 | {HPHW_FIO, 0x009, 0x00075, 0x0, "Outfield Core RS-232"}, | ||
742 | {HPHW_FIO, 0x00A, 0x00075, 0x0, "CoralII Core RS-232"}, | ||
743 | {HPHW_FIO, 0x00B, 0x00075, 0x0, "Scorpio Jr. Core RS-232"}, | ||
744 | {HPHW_FIO, 0x00C, 0x00075, 0x0, "Strider-50 Core RS-232"}, | ||
745 | {HPHW_FIO, 0x00D, 0x00075, 0x0, "Strider-33 Core RS-232"}, | ||
746 | {HPHW_FIO, 0x00E, 0x00075, 0x0, "Trailways-50 Core RS-232"}, | ||
747 | {HPHW_FIO, 0x00F, 0x00075, 0x0, "Trailways-33 Core RS-232"}, | ||
748 | {HPHW_FIO, 0x010, 0x00075, 0x0, "Pace Core RS-232"}, | ||
749 | {HPHW_FIO, 0x011, 0x00075, 0x0, "Sidewinder Core RS-232"}, | ||
750 | {HPHW_FIO, 0x019, 0x00075, 0x0, "Scorpio Sr. Core RS-232"}, | ||
751 | {HPHW_FIO, 0x020, 0x00075, 0x0, "Scorpio 100 Core RS-232"}, | ||
752 | {HPHW_FIO, 0x021, 0x00075, 0x0, "Spectra 50 Core RS-232"}, | ||
753 | {HPHW_FIO, 0x022, 0x00075, 0x0, "Spectra 75 Core RS-232"}, | ||
754 | {HPHW_FIO, 0x023, 0x00075, 0x0, "Spectra 100 Core RS-232"}, | ||
755 | {HPHW_FIO, 0x024, 0x00075, 0x0, "Fast Pace Core RS-232"}, | ||
756 | {HPHW_FIO, 0x026, 0x00075, 0x0, "CoralII Jaguar Core RS-232"}, | ||
757 | {HPHW_FIO, 0x004, 0x00077, 0x0, "Coral SGC Graphics"}, | ||
758 | {HPHW_FIO, 0x005, 0x00077, 0x0, "Hyperdrive Optional Graphics"}, | ||
759 | {HPHW_FIO, 0x006, 0x00077, 0x0, "Stinger Optional Graphics"}, | ||
760 | {HPHW_FIO, 0x007, 0x00077, 0x0, "Scorpio Builtin Graphics"}, | ||
761 | {HPHW_FIO, 0x008, 0x00077, 0x0, "Anole Hyperdrive Optional Graphics"}, | ||
762 | {HPHW_FIO, 0x009, 0x00077, 0x0, "Thunder II graphics EISA form"}, | ||
763 | {HPHW_FIO, 0x00A, 0x00077, 0x0, "Thunder II graphics GSA form"}, | ||
764 | {HPHW_FIO, 0x00B, 0x00077, 0x0, "Scorpio Jr Builtin Graphics"}, | ||
765 | {HPHW_FIO, 0x00C, 0x00077, 0x0, "Strider-50 SSC Graphics"}, | ||
766 | {HPHW_FIO, 0x00D, 0x00077, 0x0, "Strider-33 SSC Graphics"}, | ||
767 | {HPHW_FIO, 0x00E, 0x00077, 0x0, "Trailways-50 SSC Graphics"}, | ||
768 | {HPHW_FIO, 0x00F, 0x00077, 0x0, "Trailways-33 SSC Graphics"}, | ||
769 | {HPHW_FIO, 0x010, 0x00077, 0x0, "Pace SGC Graphics"}, | ||
770 | {HPHW_FIO, 0x011, 0x00077, 0x0, "Mohawk Opt. 2D Graphics (Kid)"}, | ||
771 | {HPHW_FIO, 0x012, 0x00077, 0x0, "Raven Opt. 2D Graphics (Goat)"}, | ||
772 | {HPHW_FIO, 0x016, 0x00077, 0x0, "Lego 24 SCG Graphics"}, | ||
773 | {HPHW_FIO, 0x017, 0x00077, 0x0, "Lego 24Z SCG Graphics"}, | ||
774 | {HPHW_FIO, 0x018, 0x00077, 0x0, "Lego 48Z SCG Graphics"}, | ||
775 | {HPHW_FIO, 0x019, 0x00077, 0x0, "Scorpio Sr Builtin Graphics"}, | ||
776 | {HPHW_FIO, 0x020, 0x00077, 0x0, "Scorpio 100 Builtin Graphics"}, | ||
777 | {HPHW_FIO, 0x021, 0x00077, 0x0, "Spectra 50 Builtin Graphics"}, | ||
778 | {HPHW_FIO, 0x022, 0x00077, 0x0, "Spectra 75 Builtin Graphics"}, | ||
779 | {HPHW_FIO, 0x023, 0x00077, 0x0, "Spectra 100 Builtin Graphics"}, | ||
780 | {HPHW_FIO, 0x024, 0x00077, 0x0, "Fast Pace SGC Graphics"}, | ||
781 | {HPHW_FIO, 0x006, 0x0007A, 0x0, "Bushmaster Audio"}, | ||
782 | {HPHW_FIO, 0x008, 0x0007A, 0x0, "Flounder Audio"}, | ||
783 | {HPHW_FIO, 0x004, 0x0007B, 0x0, "UL Optional Audio"}, | ||
784 | {HPHW_FIO, 0x007, 0x0007B, 0x0, "Scorpio Audio"}, | ||
785 | {HPHW_FIO, 0x00B, 0x0007B, 0x0, "Scorpio Jr. Audio"}, | ||
786 | {HPHW_FIO, 0x00C, 0x0007B, 0x0, "Strider-50 Audio"}, | ||
787 | {HPHW_FIO, 0x00D, 0x0007B, 0x0, "Strider-33 Audio"}, | ||
788 | {HPHW_FIO, 0x00E, 0x0007B, 0x0, "Trailways-50 Audio"}, | ||
789 | {HPHW_FIO, 0x00F, 0x0007B, 0x0, "Trailways-33 Audio"}, | ||
790 | {HPHW_FIO, 0x015, 0x0007B, 0x0, "KittyHawk GSY Core Audio"}, | ||
791 | {HPHW_FIO, 0x016, 0x0007B, 0x0, "Gecko Audio"}, | ||
792 | {HPHW_FIO, 0x019, 0x0007B, 0x0, "Scorpio Sr. Audio"}, | ||
793 | {HPHW_FIO, 0x01A, 0x0007B, 0x0, "Anole 64 Audio"}, | ||
794 | {HPHW_FIO, 0x01B, 0x0007B, 0x0, "Anole 100 Audio"}, | ||
795 | {HPHW_FIO, 0x01C, 0x0007B, 0x0, "Gecko 80 Audio"}, | ||
796 | {HPHW_FIO, 0x01D, 0x0007B, 0x0, "Gecko 100 Audio"}, | ||
797 | {HPHW_FIO, 0x01F, 0x0007B, 0x0, "SkyHawk 100/120 Audio"}, | ||
798 | {HPHW_FIO, 0x020, 0x0007B, 0x0, "Scorpio 100 Audio"}, | ||
799 | {HPHW_FIO, 0x021, 0x0007B, 0x0, "Spectra 50 Audio"}, | ||
800 | {HPHW_FIO, 0x022, 0x0007B, 0x0, "Spectra 75 Audio"}, | ||
801 | {HPHW_FIO, 0x023, 0x0007B, 0x0, "Spectra 100 Audio"}, | ||
802 | {HPHW_FIO, 0x028, 0x0007B, 0x0, "Mirage Jr Audio"}, | ||
803 | {HPHW_FIO, 0x029, 0x0007B, 0x0, "Mirage Audio"}, | ||
804 | {HPHW_FIO, 0x02A, 0x0007B, 0x0, "Electra Audio"}, | ||
805 | {HPHW_FIO, 0x02B, 0x0007B, 0x0, "Mirage 80 Audio"}, | ||
806 | {HPHW_FIO, 0x02C, 0x0007B, 0x0, "Mirage 100+ Audio"}, | ||
807 | {HPHW_FIO, 0x032, 0x0007B, 0x0, "Raven T' Audio"}, | ||
808 | {HPHW_FIO, 0x034, 0x0007B, 0x0, "SAIC L-80 Audio"}, | ||
809 | {HPHW_FIO, 0x035, 0x0007B, 0x0, "PCX-L2 712/132 Core Audio"}, | ||
810 | {HPHW_FIO, 0x036, 0x0007B, 0x0, "PCX-L2 712/160 Core Audio"}, | ||
811 | {HPHW_FIO, 0x03B, 0x0007B, 0x0, "Raven U/L2 Core Audio"}, | ||
812 | {HPHW_FIO, 0x03C, 0x0007B, 0x0, "Merlin 132 Core Audio"}, | ||
813 | {HPHW_FIO, 0x03D, 0x0007B, 0x0, "Merlin 160 Core Audio"}, | ||
814 | {HPHW_FIO, 0x03E, 0x0007B, 0x0, "Merlin+ 132 Core Audio"}, | ||
815 | {HPHW_FIO, 0x03F, 0x0007B, 0x0, "Merlin+ 180 Core Audio"}, | ||
816 | {HPHW_FIO, 0x044, 0x0007B, 0x0, "Mohawk Core Audio"}, | ||
817 | {HPHW_FIO, 0x046, 0x0007B, 0x0, "Rocky2 120 Core Audio"}, | ||
818 | {HPHW_FIO, 0x047, 0x0007B, 0x0, "Rocky2 150 Core Audio"}, | ||
819 | {HPHW_FIO, 0x04B, 0x0007B, 0x0, "Anole L2 132 Core Audio"}, | ||
820 | {HPHW_FIO, 0x04D, 0x0007B, 0x0, "Anole L2 165 Core Audio"}, | ||
821 | {HPHW_FIO, 0x04E, 0x0007B, 0x0, "Kiji L2 132 Core Audio"}, | ||
822 | {HPHW_FIO, 0x050, 0x0007B, 0x0, "Merlin Jr 132 Core Audio"}, | ||
823 | {HPHW_FIO, 0x051, 0x0007B, 0x0, "Firehawk Audio"}, | ||
824 | {HPHW_FIO, 0x056, 0x0007B, 0x0, "Raven+ w SE FWSCSI Core Audio"}, | ||
825 | {HPHW_FIO, 0x057, 0x0007B, 0x0, "Raven+ w Diff FWSCSI Core Audio"}, | ||
826 | {HPHW_FIO, 0x058, 0x0007B, 0x0, "FireHawk 200 Audio"}, | ||
827 | {HPHW_FIO, 0x05C, 0x0007B, 0x0, "SummitHawk 230 Core Audio"}, | ||
828 | {HPHW_FIO, 0x800, 0x0007B, 0x0, "Hitachi Tiny 64 Audio"}, | ||
829 | {HPHW_FIO, 0x801, 0x0007B, 0x0, "Hitachi Tiny 80 Audio"}, | ||
830 | {HPHW_FIO, 0x009, 0x0007C, 0x0, "Outfield FW SCSI"}, | ||
831 | {HPHW_FIO, 0x00A, 0x0007C, 0x0, "CoralII FW SCSI"}, | ||
832 | {HPHW_FIO, 0x026, 0x0007C, 0x0, "CoralII Jaguar FW SCSI"}, | ||
833 | {HPHW_FIO, 0x009, 0x0007D, 0x0, "Outfield FDDI"}, | ||
834 | {HPHW_FIO, 0x00A, 0x0007D, 0x0, "CoralII FDDI"}, | ||
835 | {HPHW_FIO, 0x026, 0x0007D, 0x0, "CoralII Jaguar FDDI"}, | ||
836 | {HPHW_FIO, 0x010, 0x0007E, 0x0, "Pace Audio"}, | ||
837 | {HPHW_FIO, 0x024, 0x0007E, 0x0, "Fast Pace Audio"}, | ||
838 | {HPHW_FIO, 0x009, 0x0007F, 0x0, "Outfield Audio"}, | ||
839 | {HPHW_FIO, 0x00A, 0x0007F, 0x0, "CoralII Audio"}, | ||
840 | {HPHW_FIO, 0x026, 0x0007F, 0x0, "CoralII Jaguar Audio"}, | ||
841 | {HPHW_FIO, 0x010, 0x00080, 0x0, "Pace Core HPIB"}, | ||
842 | {HPHW_FIO, 0x024, 0x00080, 0x0, "Fast Pace Core HPIB"}, | ||
843 | {HPHW_FIO, 0x015, 0x00082, 0x0, "KittyHawk GSY Core SCSI"}, | ||
844 | {HPHW_FIO, 0x016, 0x00082, 0x0, "Gecko Core SCSI"}, | ||
845 | {HPHW_FIO, 0x01A, 0x00082, 0x0, "Anole 64 Core SCSI"}, | ||
846 | {HPHW_FIO, 0x01B, 0x00082, 0x0, "Anole 100 Core SCSI"}, | ||
847 | {HPHW_FIO, 0x01C, 0x00082, 0x0, "Gecko 80 Core SCSI"}, | ||
848 | {HPHW_FIO, 0x01D, 0x00082, 0x0, "Gecko 100 Core SCSI"}, | ||
849 | {HPHW_FIO, 0x01F, 0x00082, 0x0, "SkyHawk 100/120 Core SCSI"}, | ||
850 | {HPHW_FIO, 0x027, 0x00082, 0x0, "Piranha 100 Core SCSI"}, | ||
851 | {HPHW_FIO, 0x028, 0x00082, 0x0, "Mirage Jr Core SCSI"}, | ||
852 | {HPHW_FIO, 0x029, 0x00082, 0x0, "Mirage Core SCSI"}, | ||
853 | {HPHW_FIO, 0x02A, 0x00082, 0x0, "Electra Core SCSI"}, | ||
854 | {HPHW_FIO, 0x02B, 0x00082, 0x0, "Mirage 80 Core SCSI"}, | ||
855 | {HPHW_FIO, 0x02C, 0x00082, 0x0, "Mirage 100+ Core SCSI"}, | ||
856 | {HPHW_FIO, 0x02E, 0x00082, 0x0, "UL 350 Core SCSI"}, | ||
857 | {HPHW_FIO, 0x02F, 0x00082, 0x0, "UL 550 Core SCSI"}, | ||
858 | {HPHW_FIO, 0x032, 0x00082, 0x0, "Raven T' Core SCSI"}, | ||
859 | {HPHW_FIO, 0x033, 0x00082, 0x0, "Anole T Core SCSI"}, | ||
860 | {HPHW_FIO, 0x034, 0x00082, 0x0, "SAIC L-80 Core SCSI"}, | ||
861 | {HPHW_FIO, 0x035, 0x00082, 0x0, "PCX-L2 712/132 Core SCSI"}, | ||
862 | {HPHW_FIO, 0x036, 0x00082, 0x0, "PCX-L2 712/160 Core SCSI"}, | ||
863 | {HPHW_FIO, 0x03B, 0x00082, 0x0, "Raven U/L2 Core SCSI"}, | ||
864 | {HPHW_FIO, 0x03C, 0x00082, 0x0, "Merlin 132 Core SCSI"}, | ||
865 | {HPHW_FIO, 0x03D, 0x00082, 0x0, "Merlin 160 Core SCSI"}, | ||
866 | {HPHW_FIO, 0x03E, 0x00082, 0x0, "Merlin+ 132 Core SCSI"}, | ||
867 | {HPHW_FIO, 0x03F, 0x00082, 0x0, "Merlin+ 180 Core SCSI"}, | ||
868 | {HPHW_FIO, 0x044, 0x00082, 0x0, "Mohawk Core SCSI"}, | ||
869 | {HPHW_FIO, 0x045, 0x00082, 0x0, "Rocky1 Core SCSI"}, | ||
870 | {HPHW_FIO, 0x046, 0x00082, 0x0, "Rocky2 120 Core SCSI"}, | ||
871 | {HPHW_FIO, 0x047, 0x00082, 0x0, "Rocky2 150 Core SCSI"}, | ||
872 | {HPHW_FIO, 0x04B, 0x00082, 0x0, "Anole L2 132 Core SCSI"}, | ||
873 | {HPHW_FIO, 0x04D, 0x00082, 0x0, "Anole L2 165 Core SCSI"}, | ||
874 | {HPHW_FIO, 0x04E, 0x00082, 0x0, "Kiji L2 132 Core SCSI"}, | ||
875 | {HPHW_FIO, 0x050, 0x00082, 0x0, "Merlin Jr 132 Core SCSI"}, | ||
876 | {HPHW_FIO, 0x051, 0x00082, 0x0, "Firehawk Core SCSI"}, | ||
877 | {HPHW_FIO, 0x056, 0x00082, 0x0, "Raven+ w SE FWSCSI Core SCSI"}, | ||
878 | {HPHW_FIO, 0x057, 0x00082, 0x0, "Raven+ w Diff FWSCSI Core SCSI"}, | ||
879 | {HPHW_FIO, 0x058, 0x00082, 0x0, "FireHawk 200 Core SCSI"}, | ||
880 | {HPHW_FIO, 0x05C, 0x00082, 0x0, "SummitHawk 230 Core SCSI"}, | ||
881 | {HPHW_FIO, 0x05E, 0x00082, 0x0, "Staccato 132 Core SCSI"}, | ||
882 | {HPHW_FIO, 0x05F, 0x00082, 0x0, "Staccato 180 Core SCSI"}, | ||
883 | {HPHW_FIO, 0x800, 0x00082, 0x0, "Hitachi Tiny 64 Core SCSI"}, | ||
884 | {HPHW_FIO, 0x801, 0x00082, 0x0, "Hitachi Tiny 80 Core SCSI"}, | ||
885 | {HPHW_FIO, 0x016, 0x00083, 0x0, "Gecko Core PC Floppy"}, | ||
886 | {HPHW_FIO, 0x01C, 0x00083, 0x0, "Gecko 80 Core PC Floppy"}, | ||
887 | {HPHW_FIO, 0x01D, 0x00083, 0x0, "Gecko 100 Core PC Floppy"}, | ||
888 | {HPHW_FIO, 0x051, 0x00083, 0x0, "Firehawk Core PC Floppy"}, | ||
889 | {HPHW_FIO, 0x058, 0x00083, 0x0, "FireHawk 200 Core PC Floppy"}, | ||
890 | {HPHW_FIO, 0x027, 0x00083, 0x0, "Piranha 100 Core PC Floppy"}, | ||
891 | {HPHW_FIO, 0x028, 0x00083, 0x0, "Mirage Jr Core PC Floppy"}, | ||
892 | {HPHW_FIO, 0x029, 0x00083, 0x0, "Mirage Core PC Floppy"}, | ||
893 | {HPHW_FIO, 0x02A, 0x00083, 0x0, "Electra Core PC Floppy"}, | ||
894 | {HPHW_FIO, 0x02B, 0x00083, 0x0, "Mirage 80 Core PC Floppy"}, | ||
895 | {HPHW_FIO, 0x02C, 0x00083, 0x0, "Mirage 100+ Core PC Floppy"}, | ||
896 | {HPHW_FIO, 0x02E, 0x00083, 0x0, "UL 350 Core PC Floppy"}, | ||
897 | {HPHW_FIO, 0x02F, 0x00083, 0x0, "UL 550 Core PC Floppy"}, | ||
898 | {HPHW_FIO, 0x032, 0x00083, 0x0, "Raven T' Core PC Floppy"}, | ||
899 | {HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floppy"}, | ||
900 | {HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floppy"}, | ||
901 | {HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floppy"}, | ||
902 | {HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floppy"}, | ||
903 | {HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floppy"}, | ||
904 | {HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floppy"}, | ||
905 | {HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floppy"}, | ||
906 | {HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floppy"}, | ||
907 | {HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floppy"}, | ||
908 | {HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floppy"}, | ||
909 | {HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floppy"}, | ||
910 | {HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floppy"}, | ||
911 | {HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floppy"}, | ||
912 | {HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floppy"}, | ||
913 | {HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floppy"}, | ||
914 | {HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floppy"}, | ||
915 | {HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floppy"}, | ||
916 | {HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PS/2 Port"}, | ||
917 | {HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PS/2 Port"}, | ||
918 | {HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PS/2 Port"}, | ||
919 | {HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PS/2 Port"}, | ||
920 | {HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PS/2 Port"}, | ||
921 | {HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PS/2 Port"}, | ||
922 | {HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PS/2 Port"}, | ||
923 | {HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PS/2 Port"}, | ||
924 | {HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PS/2 Port"}, | ||
925 | {HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PS/2 Port"}, | ||
926 | {HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PS/2 Port"}, | ||
927 | {HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PS/2 Port"}, | ||
928 | {HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PS/2 Port"}, | ||
929 | {HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PS/2 Port"}, | ||
930 | {HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PS/2 Port"}, | ||
931 | {HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PS/2 Port"}, | ||
932 | {HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PS/2 Port"}, | ||
933 | {HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PS/2 Port"}, | ||
934 | {HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PS/2 Port"}, | ||
935 | {HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core PS/2 Port"}, | ||
936 | {HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core PS/2 Port"}, | ||
937 | {HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PS/2 Port"}, | ||
938 | {HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PS/2 Port"}, | ||
939 | {HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PS/2 Port"}, | ||
940 | {HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PS/2 Port"}, | ||
941 | {HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PS/2 Port"}, | ||
942 | {HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PS/2 Port"}, | ||
943 | {HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PS/2 Port"}, | ||
944 | {HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PS/2 Port"}, | ||
945 | {HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PS/2 Port"}, | ||
946 | {HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PS/2 Port"}, | ||
947 | {HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PS/2 Port"}, | ||
948 | {HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PS/2 Port"}, | ||
949 | {HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PS/2 Port"}, | ||
950 | {HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PS/2 Port"}, | ||
951 | {HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PS/2 Port"}, | ||
952 | {HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PS/2 Port"}, | ||
953 | {HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PS/2 Port"}, | ||
954 | {HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PS/2 Port"}, | ||
955 | {HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PS/2 Port"}, | ||
956 | {HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PS/2 Port"}, | ||
957 | {HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PS/2 Port"}, | ||
958 | {HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PS/2 Port"}, | ||
959 | {HPHW_FIO, 0x004, 0x00085, 0x0, "Solo GSC Optional Graphics"}, | ||
960 | {HPHW_FIO, 0x005, 0x00085, 0x0, "Duet GSC Optional Graphics"}, | ||
961 | {HPHW_FIO, 0x008, 0x00085, 0x0, "Anole Artist Optional Graphics"}, | ||
962 | {HPHW_FIO, 0x010, 0x00085, 0x0, "Mirage 80 GSC Builtin Graphics"}, | ||
963 | {HPHW_FIO, 0x011, 0x00085, 0x0, "Mirage 100+ GSC Builtin Graphics"}, | ||
964 | {HPHW_FIO, 0x012, 0x00085, 0x0, "Mirage Jr GSC Builtin Graphics"}, | ||
965 | {HPHW_FIO, 0x013, 0x00085, 0x0, "Mirage GSC Builtin Graphics"}, | ||
966 | {HPHW_FIO, 0x014, 0x00085, 0x0, "Electra GSC Builtin Graphics"}, | ||
967 | {HPHW_FIO, 0x016, 0x00085, 0x0, "Gecko GSC Core Graphics"}, | ||
968 | {HPHW_FIO, 0x017, 0x00085, 0x0, "Gecko GSC Optional Graphics"}, | ||
969 | {HPHW_FIO, 0x01A, 0x00085, 0x0, "Anole 64 Artist Builtin Graphics"}, | ||
970 | {HPHW_FIO, 0x01B, 0x00085, 0x0, "Anole 100 Artist Builtin Graphics"}, | ||
971 | {HPHW_FIO, 0x01C, 0x00085, 0x0, "Gecko 80 GSC Core Graphics"}, | ||
972 | {HPHW_FIO, 0x01D, 0x00085, 0x0, "Gecko 100 GSC Core Graphics"}, | ||
973 | {HPHW_FIO, 0x032, 0x00085, 0x0, "Raven T' GSC Core Graphics"}, | ||
974 | {HPHW_FIO, 0x033, 0x00085, 0x0, "Anole T Artist Builtin Graphics"}, | ||
975 | {HPHW_FIO, 0x034, 0x00085, 0x0, "SAIC L-80 GSC Core Graphics"}, | ||
976 | {HPHW_FIO, 0x035, 0x00085, 0x0, "PCX-L2 712/132 Core Graphics"}, | ||
977 | {HPHW_FIO, 0x036, 0x00085, 0x0, "PCX-L2 712/160 Core Graphics"}, | ||
978 | {HPHW_FIO, 0x03B, 0x00085, 0x0, "Raven U/L2 Core Graphics"}, | ||
979 | {HPHW_FIO, 0x03C, 0x00085, 0x0, "Merlin 132 Core Graphics"}, | ||
980 | {HPHW_FIO, 0x03D, 0x00085, 0x0, "Merlin 160 Core Graphics"}, | ||
981 | {HPHW_FIO, 0x03E, 0x00085, 0x0, "Merlin+ 132 Core Graphics"}, | ||
982 | {HPHW_FIO, 0x03F, 0x00085, 0x0, "Merlin+ 180 Core Graphics"}, | ||
983 | {HPHW_FIO, 0x045, 0x00085, 0x0, "Rocky1 Core Graphics"}, | ||
984 | {HPHW_FIO, 0x046, 0x00085, 0x0, "Rocky2 120 Core Graphics"}, | ||
985 | {HPHW_FIO, 0x047, 0x00085, 0x0, "Rocky2 150 Core Graphics"}, | ||
986 | {HPHW_FIO, 0x04B, 0x00085, 0x0, "Anole L2 132 Core Graphics"}, | ||
987 | {HPHW_FIO, 0x04D, 0x00085, 0x0, "Anole L2 165 Core Graphics"}, | ||
988 | {HPHW_FIO, 0x04E, 0x00085, 0x0, "Kiji L2 132 Core Graphics"}, | ||
989 | {HPHW_FIO, 0x050, 0x00085, 0x0, "Merlin Jr 132 Core Graphics"}, | ||
990 | {HPHW_FIO, 0x056, 0x00085, 0x0, "Raven+ w SE FWSCSI Core Graphics"}, | ||
991 | {HPHW_FIO, 0x057, 0x00085, 0x0, "Raven+ w Diff FWSCSI Core Graphics"}, | ||
992 | {HPHW_FIO, 0x800, 0x00085, 0x0, "Hitachi Tiny 64 Core Graphics"}, | ||
993 | {HPHW_FIO, 0x801, 0x00085, 0x0, "Hitachi Tiny 80 Core Graphics"}, | ||
994 | {HPHW_FIO, 0x004, 0x00086, 0x0, "GSC IBM Token Ring"}, | ||
995 | {HPHW_FIO, 0x015, 0x00087, 0x0, "Gecko Optional ISDN"}, | ||
996 | {HPHW_FIO, 0x016, 0x00087, 0x0, "Gecko Core ISDN"}, | ||
997 | {HPHW_FIO, 0x01C, 0x00087, 0x0, "Gecko 80 Core ISDN"}, | ||
998 | {HPHW_FIO, 0x01D, 0x00087, 0x0, "Gecko 100 Core ISDN"}, | ||
999 | {HPHW_FIO, 0x010, 0x00088, 0x0, "Pace VME Networking"}, | ||
1000 | {HPHW_FIO, 0x011, 0x00088, 0x0, "Sidewinder VME Networking"}, | ||
1001 | {HPHW_FIO, 0x01A, 0x00088, 0x0, "Anole 64 VME Networking"}, | ||
1002 | {HPHW_FIO, 0x01B, 0x00088, 0x0, "Anole 100 VME Networking"}, | ||
1003 | {HPHW_FIO, 0x024, 0x00088, 0x0, "Fast Pace VME Networking"}, | ||
1004 | {HPHW_FIO, 0x034, 0x00088, 0x0, "Anole T VME Networking"}, | ||
1005 | {HPHW_FIO, 0x04A, 0x00088, 0x0, "Anole L2 132 VME Networking"}, | ||
1006 | {HPHW_FIO, 0x04C, 0x00088, 0x0, "Anole L2 165 VME Networking"}, | ||
1007 | {HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core LAN (802.3)"}, | ||
1008 | {HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core LAN (802.3)"}, | ||
1009 | {HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core LAN (802.3)"}, | ||
1010 | {HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core LAN (802.3)"}, | ||
1011 | {HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core LAN (802.3)"}, | ||
1012 | {HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core LAN (802.3)"}, | ||
1013 | {HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional LAN (802.3)"}, | ||
1014 | {HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core LAN (802.3)"}, | ||
1015 | {HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core LAN (802.3)"}, | ||
1016 | {HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core LAN (802.3)"}, | ||
1017 | {HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core LAN (802.3)"}, | ||
1018 | {HPHW_FIO, 0x01F, 0x0008A, 0x0, "SkyHawk 100/120 Core LAN (802.3)"}, | ||
1019 | {HPHW_FIO, 0x027, 0x0008A, 0x0, "Piranha 100 Core LAN (802.3)"}, | ||
1020 | {HPHW_FIO, 0x028, 0x0008A, 0x0, "Mirage Jr Core LAN (802.3)"}, | ||
1021 | {HPHW_FIO, 0x029, 0x0008A, 0x0, "Mirage Core LAN (802.3)"}, | ||
1022 | {HPHW_FIO, 0x02A, 0x0008A, 0x0, "Electra Core LAN (802.3)"}, | ||
1023 | {HPHW_FIO, 0x02B, 0x0008A, 0x0, "Mirage 80 Core LAN (802.3)"}, | ||
1024 | {HPHW_FIO, 0x02C, 0x0008A, 0x0, "Mirage 100+ Core LAN (802.3)"}, | ||
1025 | {HPHW_FIO, 0x02E, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"}, | ||
1026 | {HPHW_FIO, 0x02F, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"}, | ||
1027 | {HPHW_FIO, 0x032, 0x0008A, 0x0, "Raven T' Core LAN (802.3)"}, | ||
1028 | {HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core LAN (802.3)"}, | ||
1029 | {HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core LAN (802.3)"}, | ||
1030 | {HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core LAN (802.3)"}, | ||
1031 | {HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core LAN (802.3)"}, | ||
1032 | {HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core LAN (802.3)"}, | ||
1033 | {HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core LAN (802.3)"}, | ||
1034 | {HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core LAN (802.3)"}, | ||
1035 | {HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core LAN (802.3)"}, | ||
1036 | {HPHW_FIO, 0x045, 0x0008A, 0x0, "Rocky1 Core LAN (802.3)"}, | ||
1037 | {HPHW_FIO, 0x046, 0x0008A, 0x0, "Rocky2 120 Core LAN (802.3)"}, | ||
1038 | {HPHW_FIO, 0x047, 0x0008A, 0x0, "Rocky2 150 Core LAN (802.3)"}, | ||
1039 | {HPHW_FIO, 0x04B, 0x0008A, 0x0, "Anole L2 132 Core LAN (802.3)"}, | ||
1040 | {HPHW_FIO, 0x04D, 0x0008A, 0x0, "Anole L2 165 Core LAN (802.3)"}, | ||
1041 | {HPHW_FIO, 0x04E, 0x0008A, 0x0, "Kiji L2 132 Core LAN (802.3)"}, | ||
1042 | {HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core LAN (802.3)"}, | ||
1043 | {HPHW_FIO, 0x058, 0x0008A, 0x0, "FireHawk 200 Core LAN (802.3)"}, | ||
1044 | {HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core LAN (802.3)"}, | ||
1045 | {HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core LAN (802.3)"}, | ||
1046 | {HPHW_FIO, 0x004, 0x0008C, 0x0, "SkyHawk 100/120 Wax RS-232"}, | ||
1047 | {HPHW_FIO, 0x005, 0x0008C, 0x0, "SAIC L-80 Wax RS-232"}, | ||
1048 | {HPHW_FIO, 0x006, 0x0008C, 0x0, "Raven U/L2 Dino RS-232"}, | ||
1049 | {HPHW_FIO, 0x007, 0x0008C, 0x0, "Dino RS-232"}, | ||
1050 | {HPHW_FIO, 0x008, 0x0008C, 0x0, "Merlin 132 Dino RS-232"}, | ||
1051 | {HPHW_FIO, 0x009, 0x0008C, 0x0, "Merlin 160 Dino RS-232"}, | ||
1052 | {HPHW_FIO, 0x00A, 0x0008C, 0x0, "Merlin Jr 132 Dino RS-232"}, | ||
1053 | {HPHW_FIO, 0x010, 0x0008C, 0x0, "Mirage 80 Wax RS-232"}, | ||
1054 | {HPHW_FIO, 0x011, 0x0008C, 0x0, "Mirage 100+ Wax RS-232"}, | ||
1055 | {HPHW_FIO, 0x012, 0x0008C, 0x0, "Mirage Jr Wax RS-232"}, | ||
1056 | {HPHW_FIO, 0x013, 0x0008C, 0x0, "Mirage Wax RS-232"}, | ||
1057 | {HPHW_FIO, 0x014, 0x0008C, 0x0, "Electra Wax RS-232"}, | ||
1058 | {HPHW_FIO, 0x015, 0x0008C, 0x0, "KittyHawk GSY Core RS-232"}, | ||
1059 | {HPHW_FIO, 0x016, 0x0008C, 0x0, "Gecko Core RS-232"}, | ||
1060 | {HPHW_FIO, 0x017, 0x0008C, 0x0, "Raven Backplane RS-232"}, | ||
1061 | {HPHW_FIO, 0x018, 0x0008C, 0x0, "Gecko Optional RS-232"}, | ||
1062 | {HPHW_FIO, 0x019, 0x0008C, 0x0, "Merlin+ 180 Dino RS-232"}, | ||
1063 | {HPHW_FIO, 0x01A, 0x0008C, 0x0, "Anole 64 Core RS-232"}, | ||
1064 | {HPHW_FIO, 0x01B, 0x0008C, 0x0, "Anole 100 Core RS-232"}, | ||
1065 | {HPHW_FIO, 0x01C, 0x0008C, 0x0, "Gecko 80 Core RS-232"}, | ||
1066 | {HPHW_FIO, 0x01D, 0x0008C, 0x0, "Gecko 100 Core RS-232"}, | ||
1067 | {HPHW_FIO, 0x01E, 0x0008C, 0x0, "Raven T' Wax RS-232"}, | ||
1068 | {HPHW_FIO, 0x01F, 0x0008C, 0x0, "SkyHawk 100/120 Core RS-232"}, | ||
1069 | {HPHW_FIO, 0x020, 0x0008C, 0x0, "Anole 64 Timi RS-232"}, | ||
1070 | {HPHW_FIO, 0x021, 0x0008C, 0x0, "Anole 100 Timi RS-232"}, | ||
1071 | {HPHW_FIO, 0x022, 0x0008C, 0x0, "Merlin+ 132 Dino RS-232"}, | ||
1072 | {HPHW_FIO, 0x023, 0x0008C, 0x0, "Rocky1 Wax RS-232"}, | ||
1073 | {HPHW_FIO, 0x025, 0x0008C, 0x0, "Armyknife Optional RS-232"}, | ||
1074 | {HPHW_FIO, 0x026, 0x0008C, 0x0, "Piranha 100 Wax RS-232"}, | ||
1075 | {HPHW_FIO, 0x027, 0x0008C, 0x0, "Piranha 100 Core RS-232"}, | ||
1076 | {HPHW_FIO, 0x028, 0x0008C, 0x0, "Mirage Jr Core RS-232"}, | ||
1077 | {HPHW_FIO, 0x029, 0x0008C, 0x0, "Mirage Core RS-232"}, | ||
1078 | {HPHW_FIO, 0x02A, 0x0008C, 0x0, "Electra Core RS-232"}, | ||
1079 | {HPHW_FIO, 0x02B, 0x0008C, 0x0, "Mirage 80 Core RS-232"}, | ||
1080 | {HPHW_FIO, 0x02C, 0x0008C, 0x0, "Mirage 100+ Core RS-232"}, | ||
1081 | {HPHW_FIO, 0x02E, 0x0008C, 0x0, "UL 350 Lasi Core RS-232"}, | ||
1082 | {HPHW_FIO, 0x02F, 0x0008C, 0x0, "UL 550 Lasi Core RS-232"}, | ||
1083 | {HPHW_FIO, 0x030, 0x0008C, 0x0, "UL 350 Wax Core RS-232"}, | ||
1084 | {HPHW_FIO, 0x031, 0x0008C, 0x0, "UL 550 Wax Core RS-232"}, | ||
1085 | {HPHW_FIO, 0x032, 0x0008C, 0x0, "Raven T' Lasi Core RS-232"}, | ||
1086 | {HPHW_FIO, 0x033, 0x0008C, 0x0, "Anole T Core RS-232"}, | ||
1087 | {HPHW_FIO, 0x034, 0x0008C, 0x0, "SAIC L-80 Core RS-232"}, | ||
1088 | {HPHW_FIO, 0x035, 0x0008C, 0x0, "PCX-L2 712/132 Core RS-232"}, | ||
1089 | {HPHW_FIO, 0x036, 0x0008C, 0x0, "PCX-L2 712/160 Core RS-232"}, | ||
1090 | {HPHW_FIO, 0x03A, 0x0008C, 0x0, "Merlin+ Wax RS-232"}, | ||
1091 | {HPHW_FIO, 0x03B, 0x0008C, 0x0, "Raven U/L2 Core RS-232"}, | ||
1092 | {HPHW_FIO, 0x03C, 0x0008C, 0x0, "Merlin 132 Core RS-232"}, | ||
1093 | {HPHW_FIO, 0x03D, 0x0008C, 0x0, "Merlin 160 Core RS-232"}, | ||
1094 | {HPHW_FIO, 0x03E, 0x0008C, 0x0, "Merlin+ 132 Core RS-232"}, | ||
1095 | {HPHW_FIO, 0x03F, 0x0008C, 0x0, "Merlin+ 180 Core RS-232"}, | ||
1096 | {HPHW_FIO, 0x040, 0x0008C, 0x0, "Merlin 132 Wax RS-232"}, | ||
1097 | {HPHW_FIO, 0x041, 0x0008C, 0x0, "Merlin 160 Wax RS-232"}, | ||
1098 | {HPHW_FIO, 0x043, 0x0008C, 0x0, "Merlin 132/160 Wax RS-232"}, | ||
1099 | {HPHW_FIO, 0x044, 0x0008C, 0x0, "Mohawk Core RS-232"}, | ||
1100 | {HPHW_FIO, 0x045, 0x0008C, 0x0, "Rocky1 Core RS-232"}, | ||
1101 | {HPHW_FIO, 0x046, 0x0008C, 0x0, "Rocky2 120 Core RS-232"}, | ||
1102 | {HPHW_FIO, 0x047, 0x0008C, 0x0, "Rocky2 150 Core RS-232"}, | ||
1103 | {HPHW_FIO, 0x048, 0x0008C, 0x0, "Rocky2 120 Dino RS-232"}, | ||
1104 | {HPHW_FIO, 0x049, 0x0008C, 0x0, "Rocky2 150 Dino RS-232"}, | ||
1105 | {HPHW_FIO, 0x04A, 0x0008C, 0x0, "Anole L2 132 TIMI RS-232"}, | ||
1106 | {HPHW_FIO, 0x04B, 0x0008C, 0x0, "Anole L2 l32 Core RS-232"}, | ||
1107 | {HPHW_FIO, 0x04C, 0x0008D, 0x0, "Anole L2 165 TIMI RS-232"}, | ||
1108 | {HPHW_FIO, 0x04D, 0x0008C, 0x0, "Anole L2 165 Core RS-232"}, | ||
1109 | {HPHW_FIO, 0x04E, 0x0008C, 0x0, "Kiji L2 132 Core RS-232"}, | ||
1110 | {HPHW_FIO, 0x04F, 0x0008C, 0x0, "Kiji L2 132 Dino RS-232"}, | ||
1111 | {HPHW_FIO, 0x050, 0x0008C, 0x0, "Merlin Jr 132 Core RS-232"}, | ||
1112 | {HPHW_FIO, 0x051, 0x0008C, 0x0, "Firehawk Core RS-232"}, | ||
1113 | {HPHW_FIO, 0x052, 0x0008C, 0x0, "Raven+ Hi Power Backplane w EISA RS-232"}, | ||
1114 | {HPHW_FIO, 0x053, 0x0008C, 0x0, "Raven+ Hi Power Backplane w/o EISA RS-232"}, | ||
1115 | {HPHW_FIO, 0x054, 0x0008C, 0x0, "Raven+ Lo Power Backplane w EISA RS-232"}, | ||
1116 | {HPHW_FIO, 0x055, 0x0008C, 0x0, "Raven+ Lo Power Backplane w/o EISA RS-232"}, | ||
1117 | {HPHW_FIO, 0x056, 0x0008C, 0x0, "Raven+ w SE FWSCSI Core RS-232"}, | ||
1118 | {HPHW_FIO, 0x057, 0x0008C, 0x0, "Raven+ w Diff FWSCSI Core RS-232"}, | ||
1119 | {HPHW_FIO, 0x058, 0x0008C, 0x0, "FireHawk 200 Core RS-232"}, | ||
1120 | {HPHW_FIO, 0x059, 0x0008C, 0x0, "FireHawk 200 Wax RS-232"}, | ||
1121 | {HPHW_FIO, 0x05A, 0x0008C, 0x0, "Raven+ L2 Backplane w EISA RS-232"}, | ||
1122 | {HPHW_FIO, 0x05B, 0x0008C, 0x0, "Raven+ L2 Backplane w/o EISA RS-232"}, | ||
1123 | {HPHW_FIO, 0x05D, 0x0008C, 0x0, "SummitHawk Dino RS-232"}, | ||
1124 | {HPHW_FIO, 0x05E, 0x0008C, 0x0, "Staccato 132 Core LAN RS-232"}, | ||
1125 | {HPHW_FIO, 0x05F, 0x0008C, 0x0, "Staccato 180 Core LAN RS-232"}, | ||
1126 | {HPHW_FIO, 0x800, 0x0008C, 0x0, "Hitachi Tiny 64 Core RS-232"}, | ||
1127 | {HPHW_FIO, 0x801, 0x0008C, 0x0, "Hitachi Tiny 80 Core RS-232"}, | ||
1128 | {HPHW_FIO, 0x015, 0x0008D, 0x0, "Gecko Optional RJ-16"}, | ||
1129 | {HPHW_FIO, 0x016, 0x0008D, 0x0, "Gecko Core RJ-16"}, | ||
1130 | {HPHW_FIO, 0x01C, 0x0008D, 0x0, "Gecko 80 Core RJ-16"}, | ||
1131 | {HPHW_FIO, 0x01D, 0x0008D, 0x0, "Gecko 100 Core RJ-16"}, | ||
1132 | {HPHW_FIO, 0x004, 0x0008F, 0x0, "Anole Boot Rom"}, | ||
1133 | {HPHW_FIO, 0x005, 0x0008F, 0x0, "Rocky1 Boot Rom"}, | ||
1134 | {HPHW_FIO, 0x006, 0x0008F, 0x0, "Rocky2 120 Boot Rom"}, | ||
1135 | {HPHW_FIO, 0x007, 0x0008F, 0x0, "Rocky2 150 Boot Rom"}, | ||
1136 | {HPHW_FIO, 0x01B, 0x0008F, 0x0, "Anole 100 Boot Rom"}, | ||
1137 | {HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS/2 Port"}, | ||
1138 | {HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS/2 Port"}, | ||
1139 | {HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS/2 Port"}, | ||
1140 | {HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS/2 Port"}, | ||
1141 | {HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS/2 Port"}, | ||
1142 | {HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS/2 Port"}, | ||
1143 | {HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS/2 Port"}, | ||
1144 | {HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG LAN"}, | ||
1145 | {HPHW_FIO, 0x023, 0x00099, 0x0, "Rocky1 Wax HPIB"}, | ||
1146 | {HPHW_FIO, 0x048, 0x00099, 0x0, "Rocky2 120 Clark/Dino HPIB"}, | ||
1147 | {HPHW_FIO, 0x049, 0x00099, 0x0, "Rocky2 150 Clark/Dino HPIB"}, | ||
1148 | {HPHW_FIO, 0x004, 0x000A1, 0x0, "SPP2000 Console TTY"}, | ||
1149 | {HPHW_FIO, 0x004, 0x000A2, 0x0, "Forte Core PCI 10/100BT LAN"}, | ||
1150 | {HPHW_FIO, 0x005, 0x000A2, 0x0, "AllegroLow PCI 10/100BT LAN"}, | ||
1151 | {HPHW_FIO, 0x006, 0x000A2, 0x0, "AllegroHIgh Core PCI 10/100BT LAN"}, | ||
1152 | {HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in LAN"}, | ||
1153 | {HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT LAN"}, | ||
1154 | {HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI LAN"}, | ||
1155 | {HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI LAN"}, | ||
1156 | {HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI LAN"}, | ||
1157 | {HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI LAN"}, | ||
1158 | {HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI LAN"}, | ||
1159 | {HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI LAN"}, | ||
1160 | {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI LVD Ultra2 SCSI"}, | ||
1161 | {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI SE UltraSCSI"}, | ||
1162 | {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI IDE/ATAPI CD-ROM"}, | ||
1163 | {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI LVD Ultra2 SCSI"}, | ||
1164 | {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI IDE/ATAPI CD-ROM"}, | ||
1165 | {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI LVD Ultra2 SCSI"}, | ||
1166 | {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI IDE/ATAPI CD-ROM"}, | ||
1167 | {HPHW_FIO, 0x007, 0x000A3, 0x0, "PCI Plug-in Disk"}, | ||
1168 | {HPHW_FIO, 0x008, 0x000A3, 0x0, "A5158A S FC Tachlite HBA"}, | ||
1169 | {HPHW_FIO, 0x009, 0x000A3, 0x0, "A5157A D FC HBA"}, | ||
1170 | {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI LVD Ultra2 SCSI"}, | ||
1171 | {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI NSE UltraSCSI"}, | ||
1172 | {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI WSE UltraSCSI"}, | ||
1173 | {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI IDE/ATAPI CD-ROM"}, | ||
1174 | {HPHW_FIO, 0x03E, 0x000A3, 0x0, "Merlin+ 132 Core SE FWSCSI PCI Disk"}, | ||
1175 | {HPHW_FIO, 0x03F, 0x000A3, 0x0, "Merlin+ 180 Core SE FWSCSI PCI Disk"}, | ||
1176 | {HPHW_FIO, 0x056, 0x000A3, 0x0, "Raven+ w SE FWSCSI Core PCI Disk"}, | ||
1177 | {HPHW_FIO, 0x057, 0x000A3, 0x0, "Raven+ w Diff FWSCSI Core PCI Disk"}, | ||
1178 | {HPHW_FIO, 0x004, 0x000A4, 0x0, "SPP2000 Core BA"}, | ||
1179 | {HPHW_FIO, 0x004, 0x000A6, 0x0, "Sonic Ethernet 802.3 Card"}, | ||
1180 | {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI SuperIO RS-232"}, | ||
1181 | {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI USB KB"}, | ||
1182 | {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI SuperIO RS-232"}, | ||
1183 | {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI USB KB"}, | ||
1184 | {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI SuperIO RS-232"}, | ||
1185 | {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI USB KB"}, | ||
1186 | {HPHW_FIO, 0x007, 0x000A9, 0x0, "Miscelaneous PCI Plug-in"}, | ||
1187 | {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI SuperIO RS-232"}, | ||
1188 | {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI USB KB"}, | ||
1189 | {HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"}, | ||
1190 | {HPHW_FIO, 0x004, 0x00340, 0x0, "BARCO CX4500 VME Grphx Cnsl"}, | ||
1191 | {HPHW_FIO, 0x004, 0x00360, 0x0, "Hughes TOG VME FDDI"}, | ||
1192 | {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"}, | ||
1193 | {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"}, | ||
1194 | {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"}, | ||
1195 | {HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"}, | ||
1196 | {HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"}, | ||
1197 | {HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"}, | ||
1198 | {HPHW_IOA, 0x880, 0x0000C, 0x10, "Pluto BC McKinley Port"}, | ||
1199 | {HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"}, | ||
1200 | {HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"}, | ||
1201 | {HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"}, | ||
1202 | {HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"}, | ||
1203 | {HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"}, | ||
1204 | {HPHW_MEMORY, 0x0AF, 0x00009, 0x00, "Everest Mako Memory"}, | ||
1205 | {HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"}, | ||
1206 | {HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"}, | ||
1207 | {HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"}, | ||
1208 | {HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"}, | ||
1209 | {HPHW_MC, 0x004, 0x000C0, 0x00, "BMC IPMI Mgmt Ctlr"}, | ||
1210 | {HPHW_FAULTY, 0, } /* Special Marker for last entry */ | ||
1211 | }; | ||
1212 | |||
1213 | |||
1214 | static struct hp_cpu_type_mask { | ||
1215 | unsigned short model; | ||
1216 | unsigned short mask; | ||
1217 | enum cpu_type cpu; | ||
1218 | } hp_cpu_type_mask_list[] __initdata = { | ||
1219 | |||
1220 | { 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */ | ||
1221 | { 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */ | ||
1222 | { 0x0080, 0x0ff0, pcx }, /* 0x0080 - 0x008f */ | ||
1223 | { 0x0100, 0x0ff0, pcx }, /* 0x0100 - 0x010f */ | ||
1224 | { 0x0182, 0x0ffe, pcx }, /* 0x0182 - 0x0183 */ | ||
1225 | { 0x0182, 0x0ffe, pcxt }, /* 0x0182 - 0x0183 */ | ||
1226 | { 0x0184, 0x0fff, pcxu }, /* 0x0184 - 0x0184 */ | ||
1227 | { 0x0200, 0x0ffe, pcxs }, /* 0x0200 - 0x0201 */ | ||
1228 | { 0x0202, 0x0fff, pcxs }, /* 0x0202 - 0x0202 */ | ||
1229 | { 0x0203, 0x0fff, pcxt }, /* 0x0203 - 0x0203 */ | ||
1230 | { 0x0204, 0x0ffc, pcxt }, /* 0x0204 - 0x0207 */ | ||
1231 | { 0x0280, 0x0ffc, pcxs }, /* 0x0280 - 0x0283 */ | ||
1232 | { 0x0284, 0x0ffc, pcxt }, /* 0x0284 - 0x0287 */ | ||
1233 | { 0x0288, 0x0fff, pcxt }, /* 0x0288 - 0x0288 */ | ||
1234 | { 0x0300, 0x0ffc, pcxs }, /* 0x0300 - 0x0303 */ | ||
1235 | { 0x0310, 0x0ff0, pcxt }, /* 0x0310 - 0x031f */ | ||
1236 | { 0x0320, 0x0ff0, pcxt }, /* 0x0320 - 0x032f */ | ||
1237 | { 0x0400, 0x0ff0, pcxt }, /* 0x0400 - 0x040f */ | ||
1238 | { 0x0480, 0x0ff0, pcxl }, /* 0x0480 - 0x048f */ | ||
1239 | { 0x0500, 0x0ff0, pcxl2 }, /* 0x0500 - 0x050f */ | ||
1240 | { 0x0510, 0x0ff0, pcxl2 }, /* 0x0510 - 0x051f */ | ||
1241 | { 0x0580, 0x0ff8, pcxt_ }, /* 0x0580 - 0x0587 */ | ||
1242 | { 0x0588, 0x0ffc, pcxt_ }, /* 0x0588 - 0x058b */ | ||
1243 | { 0x058c, 0x0ffe, pcxt_ }, /* 0x058c - 0x058d */ | ||
1244 | { 0x058e, 0x0fff, pcxt_ }, /* 0x058e - 0x058e */ | ||
1245 | { 0x058f, 0x0fff, pcxu }, /* 0x058f - 0x058f */ | ||
1246 | { 0x0590, 0x0ffe, pcxu }, /* 0x0590 - 0x0591 */ | ||
1247 | { 0x0592, 0x0fff, pcxt_ }, /* 0x0592 - 0x0592 */ | ||
1248 | { 0x0593, 0x0fff, pcxu }, /* 0x0593 - 0x0593 */ | ||
1249 | { 0x0594, 0x0ffc, pcxu }, /* 0x0594 - 0x0597 */ | ||
1250 | { 0x0598, 0x0ffe, pcxu_ }, /* 0x0598 - 0x0599 */ | ||
1251 | { 0x059a, 0x0ffe, pcxu }, /* 0x059a - 0x059b */ | ||
1252 | { 0x059c, 0x0fff, pcxu }, /* 0x059c - 0x059c */ | ||
1253 | { 0x059d, 0x0fff, pcxu_ }, /* 0x059d - 0x059d */ | ||
1254 | { 0x059e, 0x0fff, pcxt_ }, /* 0x059e - 0x059e */ | ||
1255 | { 0x059f, 0x0fff, pcxu }, /* 0x059f - 0x059f */ | ||
1256 | { 0x05a0, 0x0ffe, pcxt_ }, /* 0x05a0 - 0x05a1 */ | ||
1257 | { 0x05a2, 0x0ffe, pcxu }, /* 0x05a2 - 0x05a3 */ | ||
1258 | { 0x05a4, 0x0ffc, pcxu }, /* 0x05a4 - 0x05a7 */ | ||
1259 | { 0x05a8, 0x0ffc, pcxu }, /* 0x05a8 - 0x05ab */ | ||
1260 | { 0x05ad, 0x0fff, pcxu_ }, /* 0x05ad - 0x05ad */ | ||
1261 | { 0x05ae, 0x0ffe, pcxu_ }, /* 0x05ae - 0x05af */ | ||
1262 | { 0x05b0, 0x0ffe, pcxu_ }, /* 0x05b0 - 0x05b1 */ | ||
1263 | { 0x05b2, 0x0fff, pcxu_ }, /* 0x05b2 - 0x05b2 */ | ||
1264 | { 0x05b3, 0x0fff, pcxu }, /* 0x05b3 - 0x05b3 */ | ||
1265 | { 0x05b4, 0x0fff, pcxw }, /* 0x05b4 - 0x05b4 */ | ||
1266 | { 0x05b5, 0x0fff, pcxu_ }, /* 0x05b5 - 0x05b5 */ | ||
1267 | { 0x05b6, 0x0ffe, pcxu_ }, /* 0x05b6 - 0x05b7 */ | ||
1268 | { 0x05b8, 0x0ffe, pcxu_ }, /* 0x05b8 - 0x05b9 */ | ||
1269 | { 0x05ba, 0x0fff, pcxu_ }, /* 0x05ba - 0x05ba */ | ||
1270 | { 0x05bb, 0x0fff, pcxw }, /* 0x05bb - 0x05bb */ | ||
1271 | { 0x05bc, 0x0ffc, pcxw }, /* 0x05bc - 0x05bf */ | ||
1272 | { 0x05c0, 0x0ffc, pcxw }, /* 0x05c0 - 0x05c3 */ | ||
1273 | { 0x05c4, 0x0ffe, pcxw }, /* 0x05c4 - 0x05c5 */ | ||
1274 | { 0x05c6, 0x0fff, pcxw }, /* 0x05c6 - 0x05c6 */ | ||
1275 | { 0x05c7, 0x0fff, pcxw_ }, /* 0x05c7 - 0x05c7 */ | ||
1276 | { 0x05c8, 0x0ffc, pcxw }, /* 0x05c8 - 0x05cb */ | ||
1277 | { 0x05cc, 0x0ffe, pcxw }, /* 0x05cc - 0x05cd */ | ||
1278 | { 0x05ce, 0x0ffe, pcxw_ }, /* 0x05ce - 0x05cf */ | ||
1279 | { 0x05d0, 0x0ffc, pcxw_ }, /* 0x05d0 - 0x05d3 */ | ||
1280 | { 0x05d4, 0x0ffe, pcxw_ }, /* 0x05d4 - 0x05d5 */ | ||
1281 | { 0x05d6, 0x0fff, pcxw }, /* 0x05d6 - 0x05d6 */ | ||
1282 | { 0x05d7, 0x0fff, pcxw_ }, /* 0x05d7 - 0x05d7 */ | ||
1283 | { 0x05d8, 0x0ffc, pcxw_ }, /* 0x05d8 - 0x05db */ | ||
1284 | { 0x05dc, 0x0ffe, pcxw2 }, /* 0x05dc - 0x05dd */ | ||
1285 | { 0x05de, 0x0fff, pcxw_ }, /* 0x05de - 0x05de */ | ||
1286 | { 0x05df, 0x0fff, pcxw2 }, /* 0x05df - 0x05df */ | ||
1287 | { 0x05e0, 0x0ffc, pcxw2 }, /* 0x05e0 - 0x05e3 */ | ||
1288 | { 0x05e4, 0x0fff, pcxw2 }, /* 0x05e4 - 0x05e4 */ | ||
1289 | { 0x05e5, 0x0fff, pcxw_ }, /* 0x05e5 - 0x05e5 */ | ||
1290 | { 0x05e6, 0x0ffe, pcxw2 }, /* 0x05e6 - 0x05e7 */ | ||
1291 | { 0x05e8, 0x0ff8, pcxw2 }, /* 0x05e8 - 0x05ef */ | ||
1292 | { 0x05f0, 0x0ff0, pcxw2 }, /* 0x05f0 - 0x05ff */ | ||
1293 | { 0x0600, 0x0fe0, pcxl }, /* 0x0600 - 0x061f */ | ||
1294 | { 0x0880, 0x0ff0, mako }, /* 0x0880 - 0x088f */ | ||
1295 | { 0x0000, 0x0000, pcx } /* terminate table */ | ||
1296 | }; | ||
1297 | |||
1298 | char *cpu_name_version[][2] = { | ||
1299 | [pcx] = { "PA7000 (PCX)", "1.0" }, | ||
1300 | [pcxs] = { "PA7000 (PCX-S)", "1.1a" }, | ||
1301 | [pcxt] = { "PA7100 (PCX-T)", "1.1b" }, | ||
1302 | [pcxt_] = { "PA7200 (PCX-T')", "1.1c" }, | ||
1303 | [pcxl] = { "PA7100LC (PCX-L)", "1.1d" }, | ||
1304 | [pcxl2] = { "PA7300LC (PCX-L2)", "1.1e" }, | ||
1305 | [pcxu] = { "PA8000 (PCX-U)", "2.0" }, | ||
1306 | [pcxu_] = { "PA8200 (PCX-U+)", "2.0" }, | ||
1307 | [pcxw] = { "PA8500 (PCX-W)", "2.0" }, | ||
1308 | [pcxw_] = { "PA8600 (PCX-W+)", "2.0" }, | ||
1309 | [pcxw2] = { "PA8700 (PCX-W2)", "2.0" }, | ||
1310 | [mako] = { "PA8800 (Mako)", "2.0" } | ||
1311 | }; | ||
1312 | |||
1313 | const char * __init | ||
1314 | parisc_hardware_description(struct parisc_device_id *id) | ||
1315 | { | ||
1316 | struct hp_hardware *listptr; | ||
1317 | |||
1318 | for (listptr = hp_hardware_list; listptr->hw_type != HPHW_FAULTY; listptr++) { | ||
1319 | if ((listptr->hw_type == id->hw_type) && | ||
1320 | (listptr->hversion == id->hversion) && | ||
1321 | (listptr->sversion == id->sversion)){ | ||
1322 | return listptr->name; | ||
1323 | } | ||
1324 | } | ||
1325 | |||
1326 | /* | ||
1327 | * ok, the above hardware table isn't complete, and we haven't found | ||
1328 | * our device in this table. So let's now try to find a generic name | ||
1329 | * to describe the given hardware... | ||
1330 | */ | ||
1331 | switch (id->hw_type) { | ||
1332 | case HPHW_NPROC: | ||
1333 | return "Unknown machine"; | ||
1334 | |||
1335 | case HPHW_A_DIRECT: | ||
1336 | switch (id->sversion) { | ||
1337 | case 0x0D: return "MUX port"; | ||
1338 | case 0x0E: return "RS-232 port"; | ||
1339 | } | ||
1340 | break; | ||
1341 | |||
1342 | case HPHW_MEMORY: | ||
1343 | return "Memory"; | ||
1344 | |||
1345 | } | ||
1346 | |||
1347 | return "unknown device"; | ||
1348 | } | ||
1349 | |||
1350 | |||
1351 | /* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */ | ||
1352 | enum cpu_type __init | ||
1353 | parisc_get_cpu_type(unsigned long hversion) | ||
1354 | { | ||
1355 | struct hp_cpu_type_mask *ptr; | ||
1356 | unsigned short model = ((unsigned short) (hversion)) >> 4; | ||
1357 | |||
1358 | for (ptr = hp_cpu_type_mask_list; 0 != ptr->mask; ptr++) { | ||
1359 | if (ptr->model == (model & ptr->mask)) | ||
1360 | return ptr->cpu; | ||
1361 | } | ||
1362 | panic("could not identify CPU type\n"); | ||
1363 | |||
1364 | return pcx; /* not reached: */ | ||
1365 | } | ||
1366 | |||
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S new file mode 100644 index 000000000000..ddf7e914f15e --- /dev/null +++ b/arch/parisc/kernel/head.S | |||
@@ -0,0 +1,386 @@ | |||
1 | /* This file is subject to the terms and conditions of the GNU General Public | ||
2 | * License. See the file "COPYING" in the main directory of this archive | ||
3 | * for more details. | ||
4 | * | ||
5 | * Copyright (C) 1999 by Helge Deller | ||
6 | * Copyright 1999 SuSE GmbH (Philipp Rumpf) | ||
7 | * Copyright 1999 Philipp Rumpf (prumpf@tux.org) | ||
8 | * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com) | ||
9 | * Copyright (C) 2001 Grant Grundler (Hewlett Packard) | ||
10 | * Copyright (C) 2004 Kyle McMartin <kyle@debian.org> | ||
11 | * | ||
12 | * Initial Version 04-23-1999 by Helge Deller <deller@gmx.de> | ||
13 | */ | ||
14 | |||
15 | #include <linux/autoconf.h> /* for CONFIG_SMP */ | ||
16 | |||
17 | #include <asm/offsets.h> | ||
18 | #include <asm/psw.h> | ||
19 | #include <asm/pdc.h> | ||
20 | |||
21 | #include <asm/assembly.h> | ||
22 | #include <asm/pgtable.h> | ||
23 | |||
24 | .level LEVEL | ||
25 | |||
26 | .data | ||
27 | |||
28 | .export boot_args | ||
29 | boot_args: | ||
30 | .word 0 /* arg0 */ | ||
31 | .word 0 /* arg1 */ | ||
32 | .word 0 /* arg2 */ | ||
33 | .word 0 /* arg3 */ | ||
34 | |||
35 | .text | ||
36 | .align 4 | ||
37 | .import init_thread_union,data | ||
38 | .import fault_vector_20,code /* IVA parisc 2.0 32 bit */ | ||
39 | #ifndef __LP64__ | ||
40 | .import fault_vector_11,code /* IVA parisc 1.1 32 bit */ | ||
41 | .import $global$ /* forward declaration */ | ||
42 | #endif /*!LP64*/ | ||
43 | .export stext | ||
44 | .export _stext,data /* Kernel want it this way! */ | ||
45 | _stext: | ||
46 | stext: | ||
47 | .proc | ||
48 | .callinfo | ||
49 | |||
50 | /* Make sure sr4-sr7 are set to zero for the kernel address space */ | ||
51 | mtsp %r0,%sr4 | ||
52 | mtsp %r0,%sr5 | ||
53 | mtsp %r0,%sr6 | ||
54 | mtsp %r0,%sr7 | ||
55 | |||
56 | /* Clear BSS (shouldn't the boot loader do this?) */ | ||
57 | |||
58 | .import __bss_start,data | ||
59 | .import __bss_stop,data | ||
60 | |||
61 | load32 PA(__bss_start),%r3 | ||
62 | load32 PA(__bss_stop),%r4 | ||
63 | $bss_loop: | ||
64 | cmpb,<<,n %r3,%r4,$bss_loop | ||
65 | stw,ma %r0,4(%r3) | ||
66 | |||
67 | /* Save away the arguments the boot loader passed in (32 bit args) */ | ||
68 | load32 PA(boot_args),%r1 | ||
69 | stw,ma %arg0,4(%r1) | ||
70 | stw,ma %arg1,4(%r1) | ||
71 | stw,ma %arg2,4(%r1) | ||
72 | stw,ma %arg3,4(%r1) | ||
73 | |||
74 | /* Initialize startup VM. Just map first 8/16 MB of memory */ | ||
75 | load32 PA(swapper_pg_dir),%r4 | ||
76 | mtctl %r4,%cr24 /* Initialize kernel root pointer */ | ||
77 | mtctl %r4,%cr25 /* Initialize user root pointer */ | ||
78 | |||
79 | #ifdef __LP64__ | ||
80 | /* Set pmd in pgd */ | ||
81 | load32 PA(pmd0),%r5 | ||
82 | shrd %r5,PxD_VALUE_SHIFT,%r3 | ||
83 | ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3 | ||
84 | stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4) | ||
85 | ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4 | ||
86 | #else | ||
87 | /* 2-level page table, so pmd == pgd */ | ||
88 | ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4 | ||
89 | #endif | ||
90 | |||
91 | /* Fill in pmd with enough pte directories */ | ||
92 | load32 PA(pg0),%r1 | ||
93 | SHRREG %r1,PxD_VALUE_SHIFT,%r3 | ||
94 | ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3 | ||
95 | |||
96 | ldi ASM_PT_INITIAL,%r1 | ||
97 | |||
98 | 1: | ||
99 | stw %r3,0(%r4) | ||
100 | ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3 | ||
101 | addib,> -1,%r1,1b | ||
102 | #ifdef __LP64__ | ||
103 | ldo ASM_PMD_ENTRY_SIZE(%r4),%r4 | ||
104 | #else | ||
105 | ldo ASM_PGD_ENTRY_SIZE(%r4),%r4 | ||
106 | #endif | ||
107 | |||
108 | |||
109 | /* Now initialize the PTEs themselves */ | ||
110 | ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */ | ||
111 | load32 PA(pg0),%r1 | ||
112 | |||
113 | $pgt_fill_loop: | ||
114 | STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1) | ||
115 | ldo ASM_PAGE_SIZE(%r3),%r3 | ||
116 | bb,>= %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop | ||
117 | nop | ||
118 | |||
119 | /* Load the return address...er...crash 'n burn */ | ||
120 | copy %r0,%r2 | ||
121 | |||
122 | /* And the RFI Target address too */ | ||
123 | load32 start_kernel,%r11 | ||
124 | |||
125 | /* And the initial task pointer */ | ||
126 | load32 init_thread_union,%r6 | ||
127 | mtctl %r6,%cr30 | ||
128 | |||
129 | /* And the stack pointer too */ | ||
130 | ldo THREAD_SZ_ALGN(%r6),%sp | ||
131 | |||
132 | /* And the interrupt stack */ | ||
133 | load32 interrupt_stack,%r6 | ||
134 | mtctl %r6,%cr31 | ||
135 | |||
136 | #ifdef CONFIG_SMP | ||
137 | /* Set the smp rendevous address into page zero. | ||
138 | ** It would be safer to do this in init_smp_config() but | ||
139 | ** it's just way easier to deal with here because | ||
140 | ** of 64-bit function ptrs and the address is local to this file. | ||
141 | */ | ||
142 | load32 PA(smp_slave_stext),%r10 | ||
143 | stw %r10,0x10(%r0) /* MEM_RENDEZ */ | ||
144 | stw %r0,0x28(%r0) /* MEM_RENDEZ_HI - assume addr < 4GB */ | ||
145 | |||
146 | /* FALLTHROUGH */ | ||
147 | .procend | ||
148 | |||
149 | /* | ||
150 | ** Code Common to both Monarch and Slave processors. | ||
151 | ** Entry: | ||
152 | ** | ||
153 | ** 1.1: | ||
154 | ** %r11 must contain RFI target address. | ||
155 | ** %r25/%r26 args to pass to target function | ||
156 | ** %r2 in case rfi target decides it didn't like something | ||
157 | ** | ||
158 | ** 2.0w: | ||
159 | ** %r3 PDCE_PROC address | ||
160 | ** %r11 RFI target address | ||
161 | ** | ||
162 | ** Caller must init: SR4-7, %sp, %r10, %cr24/25, | ||
163 | */ | ||
164 | common_stext: | ||
165 | .proc | ||
166 | .callinfo | ||
167 | #else | ||
168 | /* Clear PDC entry point - we won't use it */ | ||
169 | stw %r0,0x10(%r0) /* MEM_RENDEZ */ | ||
170 | stw %r0,0x28(%r0) /* MEM_RENDEZ_HI */ | ||
171 | #endif /*CONFIG_SMP*/ | ||
172 | |||
173 | #ifdef __LP64__ | ||
174 | tophys_r1 %sp | ||
175 | |||
176 | /* Save the rfi target address */ | ||
177 | ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 | ||
178 | tophys_r1 %r10 | ||
179 | std %r11, TASK_PT_GR11(%r10) | ||
180 | /* Switch to wide mode Superdome doesn't support narrow PDC | ||
181 | ** calls. | ||
182 | */ | ||
183 | 1: mfia %rp /* clear upper part of pcoq */ | ||
184 | ldo 2f-1b(%rp),%rp | ||
185 | depdi 0,31,32,%rp | ||
186 | bv (%rp) | ||
187 | ssm PSW_SM_W,%r0 | ||
188 | |||
189 | /* Set Wide mode as the "Default" (eg for traps) | ||
190 | ** First trap occurs *right* after (or part of) rfi for slave CPUs. | ||
191 | ** Someday, palo might not do this for the Monarch either. | ||
192 | */ | ||
193 | 2: | ||
194 | #define MEM_PDC_LO 0x388 | ||
195 | #define MEM_PDC_HI 0x35C | ||
196 | ldw MEM_PDC_LO(%r0),%r3 | ||
197 | ldw MEM_PDC_HI(%r0),%r6 | ||
198 | depd %r6, 31, 32, %r3 /* move to upper word */ | ||
199 | |||
200 | ldo PDC_PSW(%r0),%arg0 /* 21 */ | ||
201 | ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */ | ||
202 | ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */ | ||
203 | load32 PA(stext_pdc_ret), %rp | ||
204 | bv (%r3) | ||
205 | copy %r0,%arg3 | ||
206 | |||
207 | stext_pdc_ret: | ||
208 | /* restore rfi target address*/ | ||
209 | ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 | ||
210 | tophys_r1 %r10 | ||
211 | ldd TASK_PT_GR11(%r10), %r11 | ||
212 | tovirt_r1 %sp | ||
213 | #endif | ||
214 | |||
215 | /* PARANOID: clear user scratch/user space SR's */ | ||
216 | mtsp %r0,%sr0 | ||
217 | mtsp %r0,%sr1 | ||
218 | mtsp %r0,%sr2 | ||
219 | mtsp %r0,%sr3 | ||
220 | |||
221 | /* Initialize Protection Registers */ | ||
222 | mtctl %r0,%cr8 | ||
223 | mtctl %r0,%cr9 | ||
224 | mtctl %r0,%cr12 | ||
225 | mtctl %r0,%cr13 | ||
226 | |||
227 | /* Prepare to RFI! Man all the cannons! */ | ||
228 | |||
229 | /* Initialize the global data pointer */ | ||
230 | loadgp | ||
231 | |||
232 | /* Set up our interrupt table. HPMCs might not work after this! | ||
233 | * | ||
234 | * We need to install the correct iva for PA1.1 or PA2.0. The | ||
235 | * following short sequence of instructions can determine this | ||
236 | * (without being illegal on a PA1.1 machine). | ||
237 | */ | ||
238 | #ifndef __LP64__ | ||
239 | ldi 32,%r10 | ||
240 | mtctl %r10,%cr11 | ||
241 | .level 2.0 | ||
242 | mfctl,w %cr11,%r10 | ||
243 | .level 1.1 | ||
244 | comib,<>,n 0,%r10,$is_pa20 | ||
245 | ldil L%PA(fault_vector_11),%r10 | ||
246 | b $install_iva | ||
247 | ldo R%PA(fault_vector_11)(%r10),%r10 | ||
248 | |||
249 | $is_pa20: | ||
250 | .level LEVEL /* restore 1.1 || 2.0w */ | ||
251 | #endif /*!LP64*/ | ||
252 | load32 PA(fault_vector_20),%r10 | ||
253 | |||
254 | $install_iva: | ||
255 | mtctl %r10,%cr14 | ||
256 | |||
257 | #ifdef __LP64__ | ||
258 | b aligned_rfi | ||
259 | nop | ||
260 | |||
261 | .align 256 | ||
262 | aligned_rfi: | ||
263 | ssm 0,0 | ||
264 | nop /* 1 */ | ||
265 | nop /* 2 */ | ||
266 | nop /* 3 */ | ||
267 | nop /* 4 */ | ||
268 | nop /* 5 */ | ||
269 | nop /* 6 */ | ||
270 | nop /* 7 */ | ||
271 | nop /* 8 */ | ||
272 | #endif | ||
273 | |||
274 | #ifdef __LP64__ /* move to psw.h? */ | ||
275 | #define PSW_BITS PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R | ||
276 | #else | ||
277 | #define PSW_BITS PSW_SM_Q | ||
278 | #endif | ||
279 | |||
280 | $rfi: | ||
281 | /* turn off troublesome PSW bits */ | ||
282 | rsm PSW_BITS,%r0 | ||
283 | |||
284 | /* kernel PSW: | ||
285 | * - no interruptions except HPMC and TOC (which are handled by PDC) | ||
286 | * - Q bit set (IODC / PDC interruptions) | ||
287 | * - big-endian | ||
288 | * - virtually mapped | ||
289 | */ | ||
290 | load32 KERNEL_PSW,%r10 | ||
291 | mtctl %r10,%ipsw | ||
292 | |||
293 | /* Set the space pointers for the post-RFI world | ||
294 | ** Clear the two-level IIA Space Queue, effectively setting | ||
295 | ** Kernel space. | ||
296 | */ | ||
297 | mtctl %r0,%cr17 /* Clear IIASQ tail */ | ||
298 | mtctl %r0,%cr17 /* Clear IIASQ head */ | ||
299 | |||
300 | /* Load RFI target into PC queue */ | ||
301 | mtctl %r11,%cr18 /* IIAOQ head */ | ||
302 | ldo 4(%r11),%r11 | ||
303 | mtctl %r11,%cr18 /* IIAOQ tail */ | ||
304 | |||
305 | /* Jump to hyperspace */ | ||
306 | rfi | ||
307 | nop | ||
308 | |||
309 | .procend | ||
310 | |||
311 | #ifdef CONFIG_SMP | ||
312 | |||
313 | .import smp_init_current_idle_task,data | ||
314 | .import smp_callin,code | ||
315 | |||
316 | #ifndef __LP64__ | ||
317 | smp_callin_rtn: | ||
318 | .proc | ||
319 | .callinfo | ||
320 | break 1,1 /* Break if returned from start_secondary */ | ||
321 | nop | ||
322 | nop | ||
323 | .procend | ||
324 | #endif /*!LP64*/ | ||
325 | |||
326 | /*************************************************************************** | ||
327 | * smp_slave_stext is executed by all non-monarch Processors when the Monarch | ||
328 | * pokes the slave CPUs in smp.c:smp_boot_cpus(). | ||
329 | * | ||
330 | * Once here, registers values are initialized in order to branch to virtual | ||
331 | * mode. Once all available/eligible CPUs are in virtual mode, all are | ||
332 | * released and start out by executing their own idle task. | ||
333 | *****************************************************************************/ | ||
334 | smp_slave_stext: | ||
335 | .proc | ||
336 | .callinfo | ||
337 | |||
338 | /* | ||
339 | ** Initialize Space registers | ||
340 | */ | ||
341 | mtsp %r0,%sr4 | ||
342 | mtsp %r0,%sr5 | ||
343 | mtsp %r0,%sr6 | ||
344 | mtsp %r0,%sr7 | ||
345 | |||
346 | /* Initialize the SP - monarch sets up smp_init_current_idle_task */ | ||
347 | load32 PA(smp_init_current_idle_task),%sp | ||
348 | LDREG 0(%sp),%sp /* load task address */ | ||
349 | tophys_r1 %sp | ||
350 | LDREG TASK_THREAD_INFO(%sp),%sp | ||
351 | mtctl %sp,%cr30 /* store in cr30 */ | ||
352 | ldo THREAD_SZ_ALGN(%sp),%sp | ||
353 | |||
354 | /* point CPU to kernel page tables */ | ||
355 | load32 PA(swapper_pg_dir),%r4 | ||
356 | mtctl %r4,%cr24 /* Initialize kernel root pointer */ | ||
357 | mtctl %r4,%cr25 /* Initialize user root pointer */ | ||
358 | |||
359 | #ifdef __LP64__ | ||
360 | /* Setup PDCE_PROC entry */ | ||
361 | copy %arg0,%r3 | ||
362 | #else | ||
363 | /* Load RFI *return* address in case smp_callin bails */ | ||
364 | load32 smp_callin_rtn,%r2 | ||
365 | #endif | ||
366 | |||
367 | /* Load RFI target address. */ | ||
368 | load32 smp_callin,%r11 | ||
369 | |||
370 | /* ok...common code can handle the rest */ | ||
371 | b common_stext | ||
372 | nop | ||
373 | |||
374 | .procend | ||
375 | #endif /* CONFIG_SMP */ | ||
376 | #ifndef __LP64__ | ||
377 | .data | ||
378 | |||
379 | .align 4 | ||
380 | .export $global$,data | ||
381 | |||
382 | .type $global$,@object | ||
383 | .size $global$,4 | ||
384 | $global$: | ||
385 | .word 0 | ||
386 | #endif /*!LP64*/ | ||
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S new file mode 100644 index 000000000000..c412c0adc4a9 --- /dev/null +++ b/arch/parisc/kernel/hpmc.S | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * HPMC (High Priority Machine Check) handler. | ||
3 | * | ||
4 | * Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org> | ||
5 | * Copyright (C) 1999 Hewlett-Packard (Frank Rowand) | ||
6 | * Copyright (C) 2000 Hewlett-Packard (John Marvin) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | * This HPMC handler retrieves the HPMC pim data, resets IO and | ||
26 | * returns to the default trap handler with code set to 1 (HPMC). | ||
27 | * The default trap handler calls handle interruption, which | ||
28 | * does a stack and register dump. This at least allows kernel | ||
29 | * developers to get back to C code in virtual mode, where they | ||
30 | * have the option to examine and print values from memory that | ||
31 | * would help in debugging an HPMC caused by a software bug. | ||
32 | * | ||
33 | * There is more to do here: | ||
34 | * | ||
35 | * 1) On MP systems we need to synchronize processors | ||
36 | * before calling pdc/iodc. | ||
37 | * 2) We should be checking the system state and not | ||
38 | * returning to the fault handler if things are really | ||
39 | * bad. | ||
40 | * | ||
41 | */ | ||
42 | |||
43 | .level 1.1 | ||
44 | .data | ||
45 | |||
46 | #include <asm/assembly.h> | ||
47 | #include <asm/pdc.h> | ||
48 | |||
49 | /* | ||
50 | * stack for os_hpmc, the HPMC handler. | ||
51 | * buffer for IODC procedures (for the HPMC handler). | ||
52 | * | ||
53 | * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc. | ||
54 | */ | ||
55 | |||
56 | .align 4096 | ||
57 | hpmc_stack: | ||
58 | .block 16384 | ||
59 | |||
60 | #define HPMC_IODC_BUF_SIZE 0x8000 | ||
61 | |||
62 | .align 4096 | ||
63 | hpmc_iodc_buf: | ||
64 | .block HPMC_IODC_BUF_SIZE | ||
65 | |||
66 | .align 8 | ||
67 | hpmc_raddr: | ||
68 | .block 128 | ||
69 | |||
70 | #define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */ | ||
71 | |||
72 | .export hpmc_pim_data, data | ||
73 | .align 8 | ||
74 | hpmc_pim_data: | ||
75 | .block HPMC_PIM_DATA_SIZE | ||
76 | |||
77 | .text | ||
78 | |||
79 | .export os_hpmc, code | ||
80 | .import intr_save, code | ||
81 | |||
82 | os_hpmc: | ||
83 | |||
84 | /* | ||
85 | * registers modified: | ||
86 | * | ||
87 | * Using callee saves registers without saving them. The | ||
88 | * original values are in the pim dump if we need them. | ||
89 | * | ||
90 | * r2 (rp) return pointer | ||
91 | * r3 address of PDCE_PROC | ||
92 | * r4 scratch | ||
93 | * r5 scratch | ||
94 | * r23 (arg3) procedure arg | ||
95 | * r24 (arg2) procedure arg | ||
96 | * r25 (arg1) procedure arg | ||
97 | * r26 (arg0) procedure arg | ||
98 | * r30 (sp) stack pointer | ||
99 | * | ||
100 | * registers read: | ||
101 | * | ||
102 | * r26 contains address of PDCE_PROC on entry | ||
103 | * r28 (ret0) return value from procedure | ||
104 | */ | ||
105 | |||
106 | copy arg0, %r3 /* save address of PDCE_PROC */ | ||
107 | |||
108 | /* | ||
109 | * disable nested HPMCs | ||
110 | * | ||
111 | * Increment os_hpmc checksum to invalidate it. | ||
112 | * Do this before turning the PSW M bit off. | ||
113 | */ | ||
114 | |||
115 | mfctl %cr14, %r4 | ||
116 | ldw 52(%r4),%r5 | ||
117 | addi 1,%r5,%r5 | ||
118 | stw %r5,52(%r4) | ||
119 | |||
120 | /* MP_FIXME: synchronize all processors. */ | ||
121 | |||
122 | /* Setup stack pointer. */ | ||
123 | |||
124 | load32 PA(hpmc_stack),sp | ||
125 | |||
126 | ldo 128(sp),sp /* leave room for arguments */ | ||
127 | |||
128 | /* | ||
129 | * Most PDC routines require that the M bit be off. | ||
130 | * So turn on the Q bit and turn off the M bit. | ||
131 | */ | ||
132 | |||
133 | ldo 8(%r0),%r4 /* PSW Q on, PSW M off */ | ||
134 | mtctl %r4,ipsw | ||
135 | mtctl %r0,pcsq | ||
136 | mtctl %r0,pcsq | ||
137 | load32 PA(os_hpmc_1),%r4 | ||
138 | mtctl %r4,pcoq | ||
139 | ldo 4(%r4),%r4 | ||
140 | mtctl %r4,pcoq | ||
141 | rfi | ||
142 | nop | ||
143 | |||
144 | os_hpmc_1: | ||
145 | |||
146 | /* Call PDC_PIM to get HPMC pim info */ | ||
147 | |||
148 | /* | ||
149 | * Note that on some newer boxes, PDC_PIM must be called | ||
150 | * before PDC_IO if you want IO to be reset. PDC_PIM sets | ||
151 | * a flag that PDC_IO examines. | ||
152 | */ | ||
153 | |||
154 | ldo PDC_PIM(%r0), arg0 | ||
155 | ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */ | ||
156 | load32 PA(hpmc_raddr),arg2 | ||
157 | load32 PA(hpmc_pim_data),arg3 | ||
158 | load32 HPMC_PIM_DATA_SIZE,%r4 | ||
159 | stw %r4,-52(sp) | ||
160 | |||
161 | ldil L%PA(os_hpmc_2), rp | ||
162 | bv (r3) /* call pdce_proc */ | ||
163 | ldo R%PA(os_hpmc_2)(rp), rp | ||
164 | |||
165 | os_hpmc_2: | ||
166 | comib,<> 0,ret0, os_hpmc_fail | ||
167 | |||
168 | /* Reset IO by calling the hversion dependent PDC_IO routine */ | ||
169 | |||
170 | ldo PDC_IO(%r0),arg0 | ||
171 | ldo 0(%r0),arg1 /* log IO errors */ | ||
172 | ldo 0(%r0),arg2 /* reserved */ | ||
173 | ldo 0(%r0),arg3 /* reserved */ | ||
174 | stw %r0,-52(sp) /* reserved */ | ||
175 | |||
176 | ldil L%PA(os_hpmc_3),rp | ||
177 | bv (%r3) /* call pdce_proc */ | ||
178 | ldo R%PA(os_hpmc_3)(rp),rp | ||
179 | |||
180 | os_hpmc_3: | ||
181 | |||
182 | /* FIXME? Check for errors from PDC_IO (-1 might be OK) */ | ||
183 | |||
184 | /* | ||
185 | * Initialize the IODC console device (HPA,SPA, path etc. | ||
186 | * are stored on page 0. | ||
187 | */ | ||
188 | |||
189 | /* | ||
190 | * Load IODC into hpmc_iodc_buf by calling PDC_IODC. | ||
191 | * Note that PDC_IODC handles flushing the appropriate | ||
192 | * data and instruction cache lines. | ||
193 | */ | ||
194 | |||
195 | ldo PDC_IODC(%r0),arg0 | ||
196 | ldo PDC_IODC_READ(%r0),arg1 | ||
197 | load32 PA(hpmc_raddr),arg2 | ||
198 | ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */ | ||
199 | ldo PDC_IODC_RI_INIT(%r0),%r4 | ||
200 | stw %r4,-52(sp) | ||
201 | load32 PA(hpmc_iodc_buf),%r4 | ||
202 | stw %r4,-56(sp) | ||
203 | load32 HPMC_IODC_BUF_SIZE,%r4 | ||
204 | stw %r4,-60(sp) | ||
205 | |||
206 | ldil L%PA(os_hpmc_4),rp | ||
207 | bv (%r3) /* call pdce_proc */ | ||
208 | ldo R%PA(os_hpmc_4)(rp),rp | ||
209 | |||
210 | os_hpmc_4: | ||
211 | comib,<> 0,ret0,os_hpmc_fail | ||
212 | |||
213 | /* Call the entry init (just loaded by PDC_IODC) */ | ||
214 | |||
215 | ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg0 /* console hpa */ | ||
216 | ldo ENTRY_INIT_MOD_DEV(%r0), arg1 | ||
217 | ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */ | ||
218 | depi 0,31,11,arg2 /* clear bits 21-31 */ | ||
219 | ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */ | ||
220 | load32 PA(hpmc_raddr),%r4 | ||
221 | stw %r4, -52(sp) | ||
222 | stw %r0, -56(sp) /* HV */ | ||
223 | stw %r0, -60(sp) /* HV */ | ||
224 | stw %r0, -64(sp) /* HV */ | ||
225 | stw %r0, -68(sp) /* lang, must be zero */ | ||
226 | |||
227 | load32 PA(hpmc_iodc_buf),%r5 | ||
228 | ldil L%PA(os_hpmc_5),rp | ||
229 | bv (%r5) | ||
230 | ldo R%PA(os_hpmc_5)(rp),rp | ||
231 | |||
232 | os_hpmc_5: | ||
233 | comib,<> 0,ret0,os_hpmc_fail | ||
234 | |||
235 | /* Prepare to call intr_save */ | ||
236 | |||
237 | /* | ||
238 | * Load kernel page directory (load into user also, since | ||
239 | * we don't intend to ever return to user land anyway) | ||
240 | */ | ||
241 | |||
242 | load32 PA(swapper_pg_dir),%r4 | ||
243 | mtctl %r4,%cr24 /* Initialize kernel root pointer */ | ||
244 | mtctl %r4,%cr25 /* Initialize user root pointer */ | ||
245 | |||
246 | /* Clear sr4-sr7 */ | ||
247 | |||
248 | mtsp %r0, %sr4 | ||
249 | mtsp %r0, %sr5 | ||
250 | mtsp %r0, %sr6 | ||
251 | mtsp %r0, %sr7 | ||
252 | |||
253 | tovirt_r1 %r30 /* make sp virtual */ | ||
254 | |||
255 | rsm 8,%r0 /* Clear Q bit */ | ||
256 | ldi 1,%r8 /* Set trap code to "1" for HPMC */ | ||
257 | load32 PA(intr_save),%r1 | ||
258 | be 0(%sr7,%r1) | ||
259 | nop | ||
260 | |||
261 | os_hpmc_fail: | ||
262 | |||
263 | /* | ||
264 | * Reset the system | ||
265 | * | ||
266 | * Some systems may lockup from a broadcast reset, so try the | ||
267 | * hversion PDC_BROADCAST_RESET() first. | ||
268 | * MP_FIXME: reset all processors if more than one central bus. | ||
269 | */ | ||
270 | |||
271 | /* PDC_BROADCAST_RESET() */ | ||
272 | |||
273 | ldo PDC_BROADCAST_RESET(%r0),arg0 | ||
274 | ldo 0(%r0),arg1 /* do reset */ | ||
275 | |||
276 | ldil L%PA(os_hpmc_6),rp | ||
277 | bv (%r3) /* call pdce_proc */ | ||
278 | ldo R%PA(os_hpmc_6)(rp),rp | ||
279 | |||
280 | os_hpmc_6: | ||
281 | |||
282 | /* | ||
283 | * possible return values: | ||
284 | * -1 non-existent procedure | ||
285 | * -2 non-existent option | ||
286 | * -16 unaligned stack | ||
287 | * | ||
288 | * If call returned, do a broadcast reset. | ||
289 | */ | ||
290 | |||
291 | ldil L%0xfffc0000,%r4 /* IO_BROADCAST */ | ||
292 | ldo 5(%r0),%r5 | ||
293 | stw %r5,48(%r4) /* CMD_RESET to IO_COMMAND offset */ | ||
294 | |||
295 | b . | ||
296 | nop | ||
297 | |||
298 | /* this label used to compute os_hpmc checksum */ | ||
299 | |||
300 | .export os_hpmc_end, code | ||
301 | |||
302 | os_hpmc_end: | ||
303 | |||
304 | nop | ||
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c new file mode 100644 index 000000000000..7e898fd64415 --- /dev/null +++ b/arch/parisc/kernel/init_task.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Static declaration of "init" task data structure. | ||
3 | * | ||
4 | * Copyright (C) 2000 Paul Bame <bame at parisc-linux.org> | ||
5 | * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org> | ||
6 | * Copyright (C) 2001 Helge Deller <deller @ parisc-linux.org> | ||
7 | * Copyright (C) 2002 Matthew Wilcox <willy with parisc-linux.org> | ||
8 | * | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/mm.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/init_task.h> | ||
30 | #include <linux/mqueue.h> | ||
31 | |||
32 | #include <asm/uaccess.h> | ||
33 | #include <asm/pgtable.h> | ||
34 | #include <asm/pgalloc.h> | ||
35 | |||
36 | static struct fs_struct init_fs = INIT_FS; | ||
37 | static struct files_struct init_files = INIT_FILES; | ||
38 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | ||
39 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | ||
40 | struct mm_struct init_mm = INIT_MM(init_mm); | ||
41 | |||
42 | EXPORT_SYMBOL(init_mm); | ||
43 | |||
44 | /* | ||
45 | * Initial task structure. | ||
46 | * | ||
47 | * We need to make sure that this is 16384-byte aligned due to the | ||
48 | * way process stacks are handled. This is done by having a special | ||
49 | * "init_task" linker map entry.. | ||
50 | */ | ||
51 | unsigned char interrupt_stack[ISTACK_SIZE] __attribute__ ((section("init_istack"), aligned(4096))); | ||
52 | union thread_union init_thread_union | ||
53 | __attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) = | ||
54 | { INIT_THREAD_INFO(init_task) }; | ||
55 | |||
56 | #ifdef __LP64__ | ||
57 | /* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout | ||
58 | * with the first pmd adjacent to the pgd and below it. gcc doesn't actually | ||
59 | * guarantee that global objects will be laid out in memory in the same order | ||
60 | * as the order of declaration, so put these in different sections and use | ||
61 | * the linker script to order them. */ | ||
62 | pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pmd"))) = { {0}, }; | ||
63 | |||
64 | #endif | ||
65 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pgd"))) = { {0}, }; | ||
66 | pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pte"))) = { {0}, }; | ||
67 | |||
68 | /* | ||
69 | * Initial task structure. | ||
70 | * | ||
71 | * All other task structs will be allocated on slabs in fork.c | ||
72 | */ | ||
73 | EXPORT_SYMBOL(init_task); | ||
74 | |||
75 | __asm__(".data"); | ||
76 | struct task_struct init_task = INIT_TASK(init_task); | ||
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c new file mode 100644 index 000000000000..1a1c66422736 --- /dev/null +++ b/arch/parisc/kernel/inventory.c | |||
@@ -0,0 +1,612 @@ | |||
1 | /* | ||
2 | * inventory.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Copyright (c) 1999 The Puffin Group (David Kennedy and Alex deVries) | ||
10 | * Copyright (c) 2001 Matthew Wilcox for Hewlett-Packard | ||
11 | * | ||
12 | * These are the routines to discover what hardware exists in this box. | ||
13 | * This task is complicated by there being 3 different ways of | ||
14 | * performing an inventory, depending largely on the age of the box. | ||
15 | * The recommended way to do this is to check to see whether the machine | ||
16 | * is a `Snake' first, then try System Map, then try PAT. We try System | ||
17 | * Map before checking for a Snake -- this probably doesn't cause any | ||
18 | * problems, but... | ||
19 | */ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/mmzone.h> | ||
29 | #include <asm/pdc.h> | ||
30 | #include <asm/pdcpat.h> | ||
31 | #include <asm/processor.h> | ||
32 | #include <asm/page.h> | ||
33 | #include <asm/parisc-device.h> | ||
34 | |||
35 | /* | ||
36 | ** Debug options | ||
37 | ** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices. | ||
38 | */ | ||
39 | #undef DEBUG_PAT | ||
40 | |||
41 | int pdc_type = PDC_TYPE_ILLEGAL; | ||
42 | |||
43 | void __init setup_pdc(void) | ||
44 | { | ||
45 | long status; | ||
46 | unsigned int bus_id; | ||
47 | struct pdc_system_map_mod_info module_result; | ||
48 | struct pdc_module_path module_path; | ||
49 | struct pdc_model model; | ||
50 | #ifdef __LP64__ | ||
51 | struct pdc_pat_cell_num cell_info; | ||
52 | #endif | ||
53 | |||
54 | /* Determine the pdc "type" used on this machine */ | ||
55 | |||
56 | printk(KERN_INFO "Determining PDC firmware type: "); | ||
57 | |||
58 | status = pdc_system_map_find_mods(&module_result, &module_path, 0); | ||
59 | if (status == PDC_OK) { | ||
60 | pdc_type = PDC_TYPE_SYSTEM_MAP; | ||
61 | printk("System Map.\n"); | ||
62 | return; | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * If the machine doesn't support PDC_SYSTEM_MAP then either it | ||
67 | * is a pdc pat box, or it is an older box. All 64 bit capable | ||
68 | * machines are either pdc pat boxes or they support PDC_SYSTEM_MAP. | ||
69 | */ | ||
70 | |||
71 | /* | ||
72 | * TODO: We should test for 64 bit capability and give a | ||
73 | * clearer message. | ||
74 | */ | ||
75 | |||
76 | #ifdef __LP64__ | ||
77 | status = pdc_pat_cell_get_number(&cell_info); | ||
78 | if (status == PDC_OK) { | ||
79 | pdc_type = PDC_TYPE_PAT; | ||
80 | printk("64 bit PAT.\n"); | ||
81 | return; | ||
82 | } | ||
83 | #endif | ||
84 | |||
85 | /* Check the CPU's bus ID. There's probably a better test. */ | ||
86 | |||
87 | status = pdc_model_info(&model); | ||
88 | |||
89 | bus_id = (model.hversion >> (4 + 7)) & 0x1f; | ||
90 | |||
91 | switch (bus_id) { | ||
92 | case 0x4: /* 720, 730, 750, 735, 755 */ | ||
93 | case 0x6: /* 705, 710 */ | ||
94 | case 0x7: /* 715, 725 */ | ||
95 | case 0x8: /* 745, 747, 742 */ | ||
96 | case 0xA: /* 712 and similiar */ | ||
97 | case 0xC: /* 715/64, at least */ | ||
98 | |||
99 | pdc_type = PDC_TYPE_SNAKE; | ||
100 | printk("Snake.\n"); | ||
101 | return; | ||
102 | |||
103 | default: /* Everything else */ | ||
104 | |||
105 | printk("Unsupported.\n"); | ||
106 | panic("If this is a 64-bit machine, please try a 64-bit kernel.\n"); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | #define PDC_PAGE_ADJ_SHIFT (PAGE_SHIFT - 12) /* pdc pages are always 4k */ | ||
111 | |||
112 | static void __init | ||
113 | set_pmem_entry(physmem_range_t *pmem_ptr, unsigned long start, | ||
114 | unsigned long pages4k) | ||
115 | { | ||
116 | /* Rather than aligning and potentially throwing away | ||
117 | * memory, we'll assume that any ranges are already | ||
118 | * nicely aligned with any reasonable page size, and | ||
119 | * panic if they are not (it's more likely that the | ||
120 | * pdc info is bad in this case). | ||
121 | */ | ||
122 | |||
123 | if ( ((start & (PAGE_SIZE - 1)) != 0) | ||
124 | || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) ) { | ||
125 | |||
126 | panic("Memory range doesn't align with page size!\n"); | ||
127 | } | ||
128 | |||
129 | pmem_ptr->start_pfn = (start >> PAGE_SHIFT); | ||
130 | pmem_ptr->pages = (pages4k >> PDC_PAGE_ADJ_SHIFT); | ||
131 | } | ||
132 | |||
133 | static void __init pagezero_memconfig(void) | ||
134 | { | ||
135 | unsigned long npages; | ||
136 | |||
137 | /* Use the 32 bit information from page zero to create a single | ||
138 | * entry in the pmem_ranges[] table. | ||
139 | * | ||
140 | * We currently don't support machines with contiguous memory | ||
141 | * >= 4 Gb, who report that memory using 64 bit only fields | ||
142 | * on page zero. It's not worth doing until it can be tested, | ||
143 | * and it is not clear we can support those machines for other | ||
144 | * reasons. | ||
145 | * | ||
146 | * If that support is done in the future, this is where it | ||
147 | * should be done. | ||
148 | */ | ||
149 | |||
150 | npages = (PAGE_ALIGN(PAGE0->imm_max_mem) >> PAGE_SHIFT); | ||
151 | set_pmem_entry(pmem_ranges,0UL,npages); | ||
152 | npmem_ranges = 1; | ||
153 | } | ||
154 | |||
155 | #ifdef __LP64__ | ||
156 | |||
157 | /* All of the PDC PAT specific code is 64-bit only */ | ||
158 | |||
159 | /* | ||
160 | ** The module object is filled via PDC_PAT_CELL[Return Cell Module]. | ||
161 | ** If a module is found, register module will get the IODC bytes via | ||
162 | ** pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter. | ||
163 | ** | ||
164 | ** The IO view can be used by PDC_PAT_CELL[Return Cell Module] | ||
165 | ** only for SBAs and LBAs. This view will cause an invalid | ||
166 | ** argument error for all other cell module types. | ||
167 | ** | ||
168 | */ | ||
169 | |||
170 | static int __init | ||
171 | pat_query_module(ulong pcell_loc, ulong mod_index) | ||
172 | { | ||
173 | pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; | ||
174 | unsigned long bytecnt; | ||
175 | unsigned long temp; /* 64-bit scratch value */ | ||
176 | long status; /* PDC return value status */ | ||
177 | struct parisc_device *dev; | ||
178 | |||
179 | /* return cell module (PA or Processor view) */ | ||
180 | status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index, | ||
181 | PA_VIEW, &pa_pdc_cell); | ||
182 | |||
183 | if (status != PDC_OK) { | ||
184 | /* no more cell modules or error */ | ||
185 | return status; | ||
186 | } | ||
187 | |||
188 | temp = pa_pdc_cell.cba; | ||
189 | dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path); | ||
190 | if (!dev) { | ||
191 | return PDC_NE_MOD; | ||
192 | } | ||
193 | |||
194 | /* alloc_pa_dev sets dev->hpa */ | ||
195 | |||
196 | /* | ||
197 | ** save parameters in the parisc_device | ||
198 | ** (The idea being the device driver will call pdc_pat_cell_module() | ||
199 | ** and store the results in its own data structure.) | ||
200 | */ | ||
201 | dev->pcell_loc = pcell_loc; | ||
202 | dev->mod_index = mod_index; | ||
203 | |||
204 | /* save generic info returned from the call */ | ||
205 | /* REVISIT: who is the consumer of this? not sure yet... */ | ||
206 | dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */ | ||
207 | dev->pmod_loc = pa_pdc_cell.mod_location; | ||
208 | |||
209 | register_parisc_device(dev); /* advertise device */ | ||
210 | |||
211 | #ifdef DEBUG_PAT | ||
212 | pdc_pat_cell_mod_maddr_block_t io_pdc_cell; | ||
213 | /* dump what we see so far... */ | ||
214 | switch (PAT_GET_ENTITY(dev->mod_info)) { | ||
215 | unsigned long i; | ||
216 | |||
217 | case PAT_ENTITY_PROC: | ||
218 | printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n", | ||
219 | pa_pdc_cell.mod[0]); | ||
220 | break; | ||
221 | |||
222 | case PAT_ENTITY_MEM: | ||
223 | printk(KERN_DEBUG | ||
224 | "PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n", | ||
225 | pa_pdc_cell.mod[0], pa_pdc_cell.mod[1], | ||
226 | pa_pdc_cell.mod[2]); | ||
227 | break; | ||
228 | case PAT_ENTITY_CA: | ||
229 | printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc); | ||
230 | break; | ||
231 | |||
232 | case PAT_ENTITY_PBC: | ||
233 | printk(KERN_DEBUG "PAT_ENTITY_PBC: "); | ||
234 | goto print_ranges; | ||
235 | |||
236 | case PAT_ENTITY_SBA: | ||
237 | printk(KERN_DEBUG "PAT_ENTITY_SBA: "); | ||
238 | goto print_ranges; | ||
239 | |||
240 | case PAT_ENTITY_LBA: | ||
241 | printk(KERN_DEBUG "PAT_ENTITY_LBA: "); | ||
242 | |||
243 | print_ranges: | ||
244 | pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index, | ||
245 | IO_VIEW, &io_pdc_cell); | ||
246 | printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]); | ||
247 | for (i = 0; i < pa_pdc_cell.mod[1]; i++) { | ||
248 | printk(KERN_DEBUG | ||
249 | " PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", | ||
250 | i, pa_pdc_cell.mod[2 + i * 3], /* type */ | ||
251 | pa_pdc_cell.mod[3 + i * 3], /* start */ | ||
252 | pa_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */ | ||
253 | printk(KERN_DEBUG | ||
254 | " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", | ||
255 | i, io_pdc_cell.mod[2 + i * 3], /* type */ | ||
256 | io_pdc_cell.mod[3 + i * 3], /* start */ | ||
257 | io_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */ | ||
258 | } | ||
259 | printk(KERN_DEBUG "\n"); | ||
260 | break; | ||
261 | } | ||
262 | #endif /* DEBUG_PAT */ | ||
263 | return PDC_OK; | ||
264 | } | ||
265 | |||
266 | |||
267 | /* pat pdc can return information about a variety of different | ||
268 | * types of memory (e.g. firmware,i/o, etc) but we only care about | ||
269 | * the usable physical ram right now. Since the firmware specific | ||
270 | * information is allocated on the stack, we'll be generous, in | ||
271 | * case there is a lot of other information we don't care about. | ||
272 | */ | ||
273 | |||
274 | #define PAT_MAX_RANGES (4 * MAX_PHYSMEM_RANGES) | ||
275 | |||
276 | static void __init pat_memconfig(void) | ||
277 | { | ||
278 | unsigned long actual_len; | ||
279 | struct pdc_pat_pd_addr_map_entry mem_table[PAT_MAX_RANGES+1]; | ||
280 | struct pdc_pat_pd_addr_map_entry *mtbl_ptr; | ||
281 | physmem_range_t *pmem_ptr; | ||
282 | long status; | ||
283 | int entries; | ||
284 | unsigned long length; | ||
285 | int i; | ||
286 | |||
287 | length = (PAT_MAX_RANGES + 1) * sizeof(struct pdc_pat_pd_addr_map_entry); | ||
288 | |||
289 | status = pdc_pat_pd_get_addr_map(&actual_len, mem_table, length, 0L); | ||
290 | |||
291 | if ((status != PDC_OK) | ||
292 | || ((actual_len % sizeof(struct pdc_pat_pd_addr_map_entry)) != 0)) { | ||
293 | |||
294 | /* The above pdc call shouldn't fail, but, just in | ||
295 | * case, just use the PAGE0 info. | ||
296 | */ | ||
297 | |||
298 | printk("\n\n\n"); | ||
299 | printk(KERN_WARNING "WARNING! Could not get full memory configuration. " | ||
300 | "All memory may not be used!\n\n\n"); | ||
301 | pagezero_memconfig(); | ||
302 | return; | ||
303 | } | ||
304 | |||
305 | entries = actual_len / sizeof(struct pdc_pat_pd_addr_map_entry); | ||
306 | |||
307 | if (entries > PAT_MAX_RANGES) { | ||
308 | printk(KERN_WARNING "This Machine has more memory ranges than we support!\n"); | ||
309 | printk(KERN_WARNING "Some memory may not be used!\n"); | ||
310 | } | ||
311 | |||
312 | /* Copy information into the firmware independent pmem_ranges | ||
313 | * array, skipping types we don't care about. Notice we said | ||
314 | * "may" above. We'll use all the entries that were returned. | ||
315 | */ | ||
316 | |||
317 | npmem_ranges = 0; | ||
318 | mtbl_ptr = mem_table; | ||
319 | pmem_ptr = pmem_ranges; /* Global firmware independent table */ | ||
320 | for (i = 0; i < entries; i++,mtbl_ptr++) { | ||
321 | if ( (mtbl_ptr->entry_type != PAT_MEMORY_DESCRIPTOR) | ||
322 | || (mtbl_ptr->memory_type != PAT_MEMTYPE_MEMORY) | ||
323 | || (mtbl_ptr->pages == 0) | ||
324 | || ( (mtbl_ptr->memory_usage != PAT_MEMUSE_GENERAL) | ||
325 | && (mtbl_ptr->memory_usage != PAT_MEMUSE_GI) | ||
326 | && (mtbl_ptr->memory_usage != PAT_MEMUSE_GNI) ) ) { | ||
327 | |||
328 | continue; | ||
329 | } | ||
330 | |||
331 | if (npmem_ranges == MAX_PHYSMEM_RANGES) { | ||
332 | printk(KERN_WARNING "This Machine has more memory ranges than we support!\n"); | ||
333 | printk(KERN_WARNING "Some memory will not be used!\n"); | ||
334 | break; | ||
335 | } | ||
336 | |||
337 | set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages); | ||
338 | npmem_ranges++; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | static int __init pat_inventory(void) | ||
343 | { | ||
344 | int status; | ||
345 | ulong mod_index = 0; | ||
346 | struct pdc_pat_cell_num cell_info; | ||
347 | |||
348 | /* | ||
349 | ** Note: Prelude (and it's successors: Lclass, A400/500) only | ||
350 | ** implement PDC_PAT_CELL sub-options 0 and 2. | ||
351 | */ | ||
352 | status = pdc_pat_cell_get_number(&cell_info); | ||
353 | if (status != PDC_OK) { | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | #ifdef DEBUG_PAT | ||
358 | printk(KERN_DEBUG "CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_info.cell_num, | ||
359 | cell_info.cell_loc); | ||
360 | #endif | ||
361 | |||
362 | while (PDC_OK == pat_query_module(cell_info.cell_loc, mod_index)) { | ||
363 | mod_index++; | ||
364 | } | ||
365 | |||
366 | return mod_index; | ||
367 | } | ||
368 | |||
369 | /* We only look for extended memory ranges on a 64 bit capable box */ | ||
370 | static void __init sprockets_memconfig(void) | ||
371 | { | ||
372 | struct pdc_memory_table_raddr r_addr; | ||
373 | struct pdc_memory_table mem_table[MAX_PHYSMEM_RANGES]; | ||
374 | struct pdc_memory_table *mtbl_ptr; | ||
375 | physmem_range_t *pmem_ptr; | ||
376 | long status; | ||
377 | int entries; | ||
378 | int i; | ||
379 | |||
380 | status = pdc_mem_mem_table(&r_addr,mem_table, | ||
381 | (unsigned long)MAX_PHYSMEM_RANGES); | ||
382 | |||
383 | if (status != PDC_OK) { | ||
384 | |||
385 | /* The above pdc call only works on boxes with sprockets | ||
386 | * firmware (newer B,C,J class). Other non PAT PDC machines | ||
387 | * do support more than 3.75 Gb of memory, but we don't | ||
388 | * support them yet. | ||
389 | */ | ||
390 | |||
391 | pagezero_memconfig(); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | if (r_addr.entries_total > MAX_PHYSMEM_RANGES) { | ||
396 | printk(KERN_WARNING "This Machine has more memory ranges than we support!\n"); | ||
397 | printk(KERN_WARNING "Some memory will not be used!\n"); | ||
398 | } | ||
399 | |||
400 | entries = (int)r_addr.entries_returned; | ||
401 | |||
402 | npmem_ranges = 0; | ||
403 | mtbl_ptr = mem_table; | ||
404 | pmem_ptr = pmem_ranges; /* Global firmware independent table */ | ||
405 | for (i = 0; i < entries; i++,mtbl_ptr++) { | ||
406 | set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages); | ||
407 | npmem_ranges++; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | #else /* !__LP64__ */ | ||
412 | |||
413 | #define pat_inventory() do { } while (0) | ||
414 | #define pat_memconfig() do { } while (0) | ||
415 | #define sprockets_memconfig() pagezero_memconfig() | ||
416 | |||
417 | #endif /* !__LP64__ */ | ||
418 | |||
419 | |||
420 | #ifndef CONFIG_PA20 | ||
421 | |||
422 | /* Code to support Snake machines (7[2350], 7[235]5, 715/Scorpio) */ | ||
423 | |||
424 | static struct parisc_device * __init | ||
425 | legacy_create_device(struct pdc_memory_map *r_addr, | ||
426 | struct pdc_module_path *module_path) | ||
427 | { | ||
428 | struct parisc_device *dev; | ||
429 | int status = pdc_mem_map_hpa(r_addr, module_path); | ||
430 | if (status != PDC_OK) | ||
431 | return NULL; | ||
432 | |||
433 | dev = alloc_pa_dev(r_addr->hpa, &module_path->path); | ||
434 | if (dev == NULL) | ||
435 | return NULL; | ||
436 | |||
437 | register_parisc_device(dev); | ||
438 | return dev; | ||
439 | } | ||
440 | |||
441 | /** | ||
442 | * snake_inventory | ||
443 | * | ||
444 | * Before PDC_SYSTEM_MAP was invented, the PDC_MEM_MAP call was used. | ||
445 | * To use it, we initialise the mod_path.bc to 0xff and try all values of | ||
446 | * mod to get the HPA for the top-level devices. Bus adapters may have | ||
447 | * sub-devices which are discovered by setting bc[5] to 0 and bc[4] to the | ||
448 | * module, then trying all possible functions. | ||
449 | */ | ||
450 | static void __init snake_inventory(void) | ||
451 | { | ||
452 | int mod; | ||
453 | for (mod = 0; mod < 16; mod++) { | ||
454 | struct parisc_device *dev; | ||
455 | struct pdc_module_path module_path; | ||
456 | struct pdc_memory_map r_addr; | ||
457 | unsigned int func; | ||
458 | |||
459 | memset(module_path.path.bc, 0xff, 6); | ||
460 | module_path.path.mod = mod; | ||
461 | dev = legacy_create_device(&r_addr, &module_path); | ||
462 | if ((!dev) || (dev->id.hw_type != HPHW_BA)) | ||
463 | continue; | ||
464 | |||
465 | memset(module_path.path.bc, 0xff, 4); | ||
466 | module_path.path.bc[4] = mod; | ||
467 | |||
468 | for (func = 0; func < 16; func++) { | ||
469 | module_path.path.bc[5] = 0; | ||
470 | module_path.path.mod = func; | ||
471 | legacy_create_device(&r_addr, &module_path); | ||
472 | } | ||
473 | } | ||
474 | } | ||
475 | |||
476 | #else /* CONFIG_PA20 */ | ||
477 | #define snake_inventory() do { } while (0) | ||
478 | #endif /* CONFIG_PA20 */ | ||
479 | |||
480 | /* Common 32/64 bit based code goes here */ | ||
481 | |||
482 | /** | ||
483 | * add_system_map_addresses - Add additional addresses to the parisc device. | ||
484 | * @dev: The parisc device. | ||
485 | * @num_addrs: Then number of addresses to add; | ||
486 | * @module_instance: The system_map module instance. | ||
487 | * | ||
488 | * This function adds any additional addresses reported by the system_map | ||
489 | * firmware to the parisc device. | ||
490 | */ | ||
491 | static void __init | ||
492 | add_system_map_addresses(struct parisc_device *dev, int num_addrs, | ||
493 | int module_instance) | ||
494 | { | ||
495 | int i; | ||
496 | long status; | ||
497 | struct pdc_system_map_addr_info addr_result; | ||
498 | |||
499 | dev->addr = kmalloc(num_addrs * sizeof(unsigned long), GFP_KERNEL); | ||
500 | if(!dev->addr) { | ||
501 | printk(KERN_ERR "%s %s(): memory allocation failure\n", | ||
502 | __FILE__, __FUNCTION__); | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | for(i = 1; i <= num_addrs; ++i) { | ||
507 | status = pdc_system_map_find_addrs(&addr_result, | ||
508 | module_instance, i); | ||
509 | if(PDC_OK == status) { | ||
510 | dev->addr[dev->num_addrs] = (unsigned long)addr_result.mod_addr; | ||
511 | dev->num_addrs++; | ||
512 | } else { | ||
513 | printk(KERN_WARNING | ||
514 | "Bad PDC_FIND_ADDRESS status return (%ld) for index %d\n", | ||
515 | status, i); | ||
516 | } | ||
517 | } | ||
518 | } | ||
519 | |||
520 | /** | ||
521 | * system_map_inventory - Retrieve firmware devices via SYSTEM_MAP. | ||
522 | * | ||
523 | * This function attempts to retrieve and register all the devices firmware | ||
524 | * knows about via the SYSTEM_MAP PDC call. | ||
525 | */ | ||
526 | static void __init system_map_inventory(void) | ||
527 | { | ||
528 | int i; | ||
529 | long status = PDC_OK; | ||
530 | |||
531 | for (i = 0; i < 256; i++) { | ||
532 | struct parisc_device *dev; | ||
533 | struct pdc_system_map_mod_info module_result; | ||
534 | struct pdc_module_path module_path; | ||
535 | |||
536 | status = pdc_system_map_find_mods(&module_result, | ||
537 | &module_path, i); | ||
538 | if ((status == PDC_BAD_PROC) || (status == PDC_NE_MOD)) | ||
539 | break; | ||
540 | if (status != PDC_OK) | ||
541 | continue; | ||
542 | |||
543 | dev = alloc_pa_dev(module_result.mod_addr, &module_path.path); | ||
544 | if (!dev) | ||
545 | continue; | ||
546 | |||
547 | register_parisc_device(dev); | ||
548 | |||
549 | /* if available, get the additional addresses for a module */ | ||
550 | if (!module_result.add_addrs) | ||
551 | continue; | ||
552 | |||
553 | add_system_map_addresses(dev, module_result.add_addrs, i); | ||
554 | } | ||
555 | |||
556 | walk_central_bus(); | ||
557 | return; | ||
558 | } | ||
559 | |||
560 | void __init do_memory_inventory(void) | ||
561 | { | ||
562 | switch (pdc_type) { | ||
563 | |||
564 | case PDC_TYPE_PAT: | ||
565 | pat_memconfig(); | ||
566 | break; | ||
567 | |||
568 | case PDC_TYPE_SYSTEM_MAP: | ||
569 | sprockets_memconfig(); | ||
570 | break; | ||
571 | |||
572 | case PDC_TYPE_SNAKE: | ||
573 | pagezero_memconfig(); | ||
574 | return; | ||
575 | |||
576 | default: | ||
577 | panic("Unknown PDC type!\n"); | ||
578 | } | ||
579 | |||
580 | if (npmem_ranges == 0 || pmem_ranges[0].start_pfn != 0) { | ||
581 | printk(KERN_WARNING "Bad memory configuration returned!\n"); | ||
582 | printk(KERN_WARNING "Some memory may not be used!\n"); | ||
583 | pagezero_memconfig(); | ||
584 | } | ||
585 | } | ||
586 | |||
587 | void __init do_device_inventory(void) | ||
588 | { | ||
589 | printk(KERN_INFO "Searching for devices...\n"); | ||
590 | |||
591 | init_parisc_bus(); | ||
592 | |||
593 | switch (pdc_type) { | ||
594 | |||
595 | case PDC_TYPE_PAT: | ||
596 | pat_inventory(); | ||
597 | break; | ||
598 | |||
599 | case PDC_TYPE_SYSTEM_MAP: | ||
600 | system_map_inventory(); | ||
601 | break; | ||
602 | |||
603 | case PDC_TYPE_SNAKE: | ||
604 | snake_inventory(); | ||
605 | break; | ||
606 | |||
607 | default: | ||
608 | panic("Unknown PDC type!\n"); | ||
609 | } | ||
610 | printk(KERN_INFO "Found devices:\n"); | ||
611 | print_parisc_devices(); | ||
612 | } | ||
diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c new file mode 100644 index 000000000000..1d3824b670d1 --- /dev/null +++ b/arch/parisc/kernel/ioctl32.c | |||
@@ -0,0 +1,625 @@ | |||
1 | /* $Id: ioctl32.c,v 1.5 2002/10/18 00:21:43 varenet Exp $ | ||
2 | * ioctl32.c: Conversion between 32bit and 64bit native ioctls. | ||
3 | * | ||
4 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) | ||
5 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) | ||
6 | * | ||
7 | * These routines maintain argument size conversion between 32bit and 64bit | ||
8 | * ioctls. | ||
9 | */ | ||
10 | |||
11 | #include <linux/syscalls.h> | ||
12 | |||
13 | #define INCLUDES | ||
14 | #include "compat_ioctl.c" | ||
15 | |||
16 | #include <asm/perf.h> | ||
17 | #include <asm/ioctls.h> | ||
18 | |||
19 | #define CODE | ||
20 | #include "compat_ioctl.c" | ||
21 | |||
22 | /* Use this to get at 32-bit user passed pointers. | ||
23 | See sys_sparc32.c for description about these. */ | ||
24 | #define A(__x) ((unsigned long)(__x)) | ||
25 | /* The same for use with copy_from_user() and copy_to_user(). */ | ||
26 | #define B(__x) ((void *)(unsigned long)(__x)) | ||
27 | |||
28 | #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) | ||
29 | /* This really belongs in include/linux/drm.h -DaveM */ | ||
30 | #include "../../../drivers/char/drm/drm.h" | ||
31 | |||
32 | typedef struct drm32_version { | ||
33 | int version_major; /* Major version */ | ||
34 | int version_minor; /* Minor version */ | ||
35 | int version_patchlevel;/* Patch level */ | ||
36 | int name_len; /* Length of name buffer */ | ||
37 | u32 name; /* Name of driver */ | ||
38 | int date_len; /* Length of date buffer */ | ||
39 | u32 date; /* User-space buffer to hold date */ | ||
40 | int desc_len; /* Length of desc buffer */ | ||
41 | u32 desc; /* User-space buffer to hold desc */ | ||
42 | } drm32_version_t; | ||
43 | #define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t) | ||
44 | |||
45 | static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
46 | { | ||
47 | drm32_version_t *uversion = (drm32_version_t *)arg; | ||
48 | char *name_ptr, *date_ptr, *desc_ptr; | ||
49 | u32 tmp1, tmp2, tmp3; | ||
50 | drm_version_t kversion; | ||
51 | mm_segment_t old_fs; | ||
52 | int ret; | ||
53 | |||
54 | memset(&kversion, 0, sizeof(kversion)); | ||
55 | if (get_user(kversion.name_len, &uversion->name_len) || | ||
56 | get_user(kversion.date_len, &uversion->date_len) || | ||
57 | get_user(kversion.desc_len, &uversion->desc_len) || | ||
58 | get_user(tmp1, &uversion->name) || | ||
59 | get_user(tmp2, &uversion->date) || | ||
60 | get_user(tmp3, &uversion->desc)) | ||
61 | return -EFAULT; | ||
62 | |||
63 | name_ptr = (char *) A(tmp1); | ||
64 | date_ptr = (char *) A(tmp2); | ||
65 | desc_ptr = (char *) A(tmp3); | ||
66 | |||
67 | ret = -ENOMEM; | ||
68 | if (kversion.name_len && name_ptr) { | ||
69 | kversion.name = kmalloc(kversion.name_len, GFP_KERNEL); | ||
70 | if (!kversion.name) | ||
71 | goto out; | ||
72 | } | ||
73 | if (kversion.date_len && date_ptr) { | ||
74 | kversion.date = kmalloc(kversion.date_len, GFP_KERNEL); | ||
75 | if (!kversion.date) | ||
76 | goto out; | ||
77 | } | ||
78 | if (kversion.desc_len && desc_ptr) { | ||
79 | kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL); | ||
80 | if (!kversion.desc) | ||
81 | goto out; | ||
82 | } | ||
83 | |||
84 | old_fs = get_fs(); | ||
85 | set_fs(KERNEL_DS); | ||
86 | ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion); | ||
87 | set_fs(old_fs); | ||
88 | |||
89 | if (!ret) { | ||
90 | if ((kversion.name && | ||
91 | copy_to_user(name_ptr, kversion.name, kversion.name_len)) || | ||
92 | (kversion.date && | ||
93 | copy_to_user(date_ptr, kversion.date, kversion.date_len)) || | ||
94 | (kversion.desc && | ||
95 | copy_to_user(desc_ptr, kversion.desc, kversion.desc_len))) | ||
96 | ret = -EFAULT; | ||
97 | if (put_user(kversion.version_major, &uversion->version_major) || | ||
98 | put_user(kversion.version_minor, &uversion->version_minor) || | ||
99 | put_user(kversion.version_patchlevel, &uversion->version_patchlevel) || | ||
100 | put_user(kversion.name_len, &uversion->name_len) || | ||
101 | put_user(kversion.date_len, &uversion->date_len) || | ||
102 | put_user(kversion.desc_len, &uversion->desc_len)) | ||
103 | ret = -EFAULT; | ||
104 | } | ||
105 | |||
106 | out: | ||
107 | if (kversion.name) | ||
108 | kfree(kversion.name); | ||
109 | if (kversion.date) | ||
110 | kfree(kversion.date); | ||
111 | if (kversion.desc) | ||
112 | kfree(kversion.desc); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | typedef struct drm32_unique { | ||
117 | int unique_len; /* Length of unique */ | ||
118 | u32 unique; /* Unique name for driver instantiation */ | ||
119 | } drm32_unique_t; | ||
120 | #define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) | ||
121 | #define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) | ||
122 | |||
123 | static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
124 | { | ||
125 | drm32_unique_t *uarg = (drm32_unique_t *)arg; | ||
126 | drm_unique_t karg; | ||
127 | mm_segment_t old_fs; | ||
128 | char *uptr; | ||
129 | u32 tmp; | ||
130 | int ret; | ||
131 | |||
132 | if (get_user(karg.unique_len, &uarg->unique_len)) | ||
133 | return -EFAULT; | ||
134 | karg.unique = NULL; | ||
135 | |||
136 | if (get_user(tmp, &uarg->unique)) | ||
137 | return -EFAULT; | ||
138 | |||
139 | uptr = (char *) A(tmp); | ||
140 | |||
141 | if (uptr) { | ||
142 | karg.unique = kmalloc(karg.unique_len, GFP_KERNEL); | ||
143 | if (!karg.unique) | ||
144 | return -ENOMEM; | ||
145 | if (cmd == DRM32_IOCTL_SET_UNIQUE && | ||
146 | copy_from_user(karg.unique, uptr, karg.unique_len)) { | ||
147 | kfree(karg.unique); | ||
148 | return -EFAULT; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | old_fs = get_fs(); | ||
153 | set_fs(KERNEL_DS); | ||
154 | if (cmd == DRM32_IOCTL_GET_UNIQUE) | ||
155 | ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg); | ||
156 | else | ||
157 | ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg); | ||
158 | set_fs(old_fs); | ||
159 | |||
160 | if (!ret) { | ||
161 | if (cmd == DRM32_IOCTL_GET_UNIQUE && | ||
162 | uptr != NULL && | ||
163 | copy_to_user(uptr, karg.unique, karg.unique_len)) | ||
164 | ret = -EFAULT; | ||
165 | if (put_user(karg.unique_len, &uarg->unique_len)) | ||
166 | ret = -EFAULT; | ||
167 | } | ||
168 | |||
169 | if (karg.unique != NULL) | ||
170 | kfree(karg.unique); | ||
171 | |||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | typedef struct drm32_map { | ||
176 | u32 offset; /* Requested physical address (0 for SAREA)*/ | ||
177 | u32 size; /* Requested physical size (bytes) */ | ||
178 | drm_map_type_t type; /* Type of memory to map */ | ||
179 | drm_map_flags_t flags; /* Flags */ | ||
180 | u32 handle; /* User-space: "Handle" to pass to mmap */ | ||
181 | /* Kernel-space: kernel-virtual address */ | ||
182 | int mtrr; /* MTRR slot used */ | ||
183 | /* Private data */ | ||
184 | } drm32_map_t; | ||
185 | #define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t) | ||
186 | |||
187 | static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
188 | { | ||
189 | drm32_map_t *uarg = (drm32_map_t *) arg; | ||
190 | drm_map_t karg; | ||
191 | mm_segment_t old_fs; | ||
192 | u32 tmp; | ||
193 | int ret; | ||
194 | |||
195 | ret = get_user(karg.offset, &uarg->offset); | ||
196 | ret |= get_user(karg.size, &uarg->size); | ||
197 | ret |= get_user(karg.type, &uarg->type); | ||
198 | ret |= get_user(karg.flags, &uarg->flags); | ||
199 | ret |= get_user(tmp, &uarg->handle); | ||
200 | ret |= get_user(karg.mtrr, &uarg->mtrr); | ||
201 | if (ret) | ||
202 | return -EFAULT; | ||
203 | |||
204 | karg.handle = (void *) A(tmp); | ||
205 | |||
206 | old_fs = get_fs(); | ||
207 | set_fs(KERNEL_DS); | ||
208 | ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); | ||
209 | set_fs(old_fs); | ||
210 | |||
211 | if (!ret) { | ||
212 | ret = put_user(karg.offset, &uarg->offset); | ||
213 | ret |= put_user(karg.size, &uarg->size); | ||
214 | ret |= put_user(karg.type, &uarg->type); | ||
215 | ret |= put_user(karg.flags, &uarg->flags); | ||
216 | tmp = (u32) (long)karg.handle; | ||
217 | ret |= put_user(tmp, &uarg->handle); | ||
218 | ret |= put_user(karg.mtrr, &uarg->mtrr); | ||
219 | if (ret) | ||
220 | ret = -EFAULT; | ||
221 | } | ||
222 | |||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | typedef struct drm32_buf_info { | ||
227 | int count; /* Entries in list */ | ||
228 | u32 list; /* (drm_buf_desc_t *) */ | ||
229 | } drm32_buf_info_t; | ||
230 | #define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t) | ||
231 | |||
232 | static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
233 | { | ||
234 | drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg; | ||
235 | drm_buf_desc_t *ulist; | ||
236 | drm_buf_info_t karg; | ||
237 | mm_segment_t old_fs; | ||
238 | int orig_count, ret; | ||
239 | u32 tmp; | ||
240 | |||
241 | if (get_user(karg.count, &uarg->count) || | ||
242 | get_user(tmp, &uarg->list)) | ||
243 | return -EFAULT; | ||
244 | |||
245 | ulist = (drm_buf_desc_t *) A(tmp); | ||
246 | |||
247 | orig_count = karg.count; | ||
248 | |||
249 | karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL); | ||
250 | if (!karg.list) | ||
251 | return -EFAULT; | ||
252 | |||
253 | old_fs = get_fs(); | ||
254 | set_fs(KERNEL_DS); | ||
255 | ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg); | ||
256 | set_fs(old_fs); | ||
257 | |||
258 | if (!ret) { | ||
259 | if (karg.count <= orig_count && | ||
260 | (copy_to_user(ulist, karg.list, | ||
261 | karg.count * sizeof(drm_buf_desc_t)))) | ||
262 | ret = -EFAULT; | ||
263 | if (put_user(karg.count, &uarg->count)) | ||
264 | ret = -EFAULT; | ||
265 | } | ||
266 | |||
267 | kfree(karg.list); | ||
268 | |||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | typedef struct drm32_buf_free { | ||
273 | int count; | ||
274 | u32 list; /* (int *) */ | ||
275 | } drm32_buf_free_t; | ||
276 | #define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t) | ||
277 | |||
278 | static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
279 | { | ||
280 | drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg; | ||
281 | drm_buf_free_t karg; | ||
282 | mm_segment_t old_fs; | ||
283 | int *ulist; | ||
284 | int ret; | ||
285 | u32 tmp; | ||
286 | |||
287 | if (get_user(karg.count, &uarg->count) || | ||
288 | get_user(tmp, &uarg->list)) | ||
289 | return -EFAULT; | ||
290 | |||
291 | ulist = (int *) A(tmp); | ||
292 | |||
293 | karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL); | ||
294 | if (!karg.list) | ||
295 | return -ENOMEM; | ||
296 | |||
297 | ret = -EFAULT; | ||
298 | if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int)))) | ||
299 | goto out; | ||
300 | |||
301 | old_fs = get_fs(); | ||
302 | set_fs(KERNEL_DS); | ||
303 | ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg); | ||
304 | set_fs(old_fs); | ||
305 | |||
306 | out: | ||
307 | kfree(karg.list); | ||
308 | |||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | typedef struct drm32_buf_pub { | ||
313 | int idx; /* Index into master buflist */ | ||
314 | int total; /* Buffer size */ | ||
315 | int used; /* Amount of buffer in use (for DMA) */ | ||
316 | u32 address; /* Address of buffer (void *) */ | ||
317 | } drm32_buf_pub_t; | ||
318 | |||
319 | typedef struct drm32_buf_map { | ||
320 | int count; /* Length of buflist */ | ||
321 | u32 virtual; /* Mmaped area in user-virtual (void *) */ | ||
322 | u32 list; /* Buffer information (drm_buf_pub_t *) */ | ||
323 | } drm32_buf_map_t; | ||
324 | #define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t) | ||
325 | |||
326 | static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
327 | { | ||
328 | drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg; | ||
329 | drm32_buf_pub_t *ulist; | ||
330 | drm_buf_map_t karg; | ||
331 | mm_segment_t old_fs; | ||
332 | int orig_count, ret, i; | ||
333 | u32 tmp1, tmp2; | ||
334 | |||
335 | if (get_user(karg.count, &uarg->count) || | ||
336 | get_user(tmp1, &uarg->virtual) || | ||
337 | get_user(tmp2, &uarg->list)) | ||
338 | return -EFAULT; | ||
339 | |||
340 | karg.virtual = (void *) A(tmp1); | ||
341 | ulist = (drm32_buf_pub_t *) A(tmp2); | ||
342 | |||
343 | orig_count = karg.count; | ||
344 | |||
345 | karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL); | ||
346 | if (!karg.list) | ||
347 | return -ENOMEM; | ||
348 | |||
349 | ret = -EFAULT; | ||
350 | for (i = 0; i < karg.count; i++) { | ||
351 | if (get_user(karg.list[i].idx, &ulist[i].idx) || | ||
352 | get_user(karg.list[i].total, &ulist[i].total) || | ||
353 | get_user(karg.list[i].used, &ulist[i].used) || | ||
354 | get_user(tmp1, &ulist[i].address)) | ||
355 | goto out; | ||
356 | |||
357 | karg.list[i].address = (void *) A(tmp1); | ||
358 | } | ||
359 | |||
360 | old_fs = get_fs(); | ||
361 | set_fs(KERNEL_DS); | ||
362 | ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg); | ||
363 | set_fs(old_fs); | ||
364 | |||
365 | if (!ret) { | ||
366 | for (i = 0; i < orig_count; i++) { | ||
367 | tmp1 = (u32) (long) karg.list[i].address; | ||
368 | if (put_user(karg.list[i].idx, &ulist[i].idx) || | ||
369 | put_user(karg.list[i].total, &ulist[i].total) || | ||
370 | put_user(karg.list[i].used, &ulist[i].used) || | ||
371 | put_user(tmp1, &ulist[i].address)) { | ||
372 | ret = -EFAULT; | ||
373 | goto out; | ||
374 | } | ||
375 | } | ||
376 | if (put_user(karg.count, &uarg->count)) | ||
377 | ret = -EFAULT; | ||
378 | } | ||
379 | |||
380 | out: | ||
381 | kfree(karg.list); | ||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | typedef struct drm32_dma { | ||
386 | /* Indices here refer to the offset into | ||
387 | buflist in drm_buf_get_t. */ | ||
388 | int context; /* Context handle */ | ||
389 | int send_count; /* Number of buffers to send */ | ||
390 | u32 send_indices; /* List of handles to buffers (int *) */ | ||
391 | u32 send_sizes; /* Lengths of data to send (int *) */ | ||
392 | drm_dma_flags_t flags; /* Flags */ | ||
393 | int request_count; /* Number of buffers requested */ | ||
394 | int request_size; /* Desired size for buffers */ | ||
395 | u32 request_indices; /* Buffer information (int *) */ | ||
396 | u32 request_sizes; /* (int *) */ | ||
397 | int granted_count; /* Number of buffers granted */ | ||
398 | } drm32_dma_t; | ||
399 | #define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t) | ||
400 | |||
401 | /* RED PEN The DRM layer blindly dereferences the send/request | ||
402 | * indice/size arrays even though they are userland | ||
403 | * pointers. -DaveM | ||
404 | */ | ||
405 | static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
406 | { | ||
407 | drm32_dma_t *uarg = (drm32_dma_t *) arg; | ||
408 | int *u_si, *u_ss, *u_ri, *u_rs; | ||
409 | drm_dma_t karg; | ||
410 | mm_segment_t old_fs; | ||
411 | int ret; | ||
412 | u32 tmp1, tmp2, tmp3, tmp4; | ||
413 | |||
414 | karg.send_indices = karg.send_sizes = NULL; | ||
415 | karg.request_indices = karg.request_sizes = NULL; | ||
416 | |||
417 | if (get_user(karg.context, &uarg->context) || | ||
418 | get_user(karg.send_count, &uarg->send_count) || | ||
419 | get_user(tmp1, &uarg->send_indices) || | ||
420 | get_user(tmp2, &uarg->send_sizes) || | ||
421 | get_user(karg.flags, &uarg->flags) || | ||
422 | get_user(karg.request_count, &uarg->request_count) || | ||
423 | get_user(karg.request_size, &uarg->request_size) || | ||
424 | get_user(tmp3, &uarg->request_indices) || | ||
425 | get_user(tmp4, &uarg->request_sizes) || | ||
426 | get_user(karg.granted_count, &uarg->granted_count)) | ||
427 | return -EFAULT; | ||
428 | |||
429 | u_si = (int *) A(tmp1); | ||
430 | u_ss = (int *) A(tmp2); | ||
431 | u_ri = (int *) A(tmp3); | ||
432 | u_rs = (int *) A(tmp4); | ||
433 | |||
434 | if (karg.send_count) { | ||
435 | karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); | ||
436 | karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); | ||
437 | |||
438 | ret = -ENOMEM; | ||
439 | if (!karg.send_indices || !karg.send_sizes) | ||
440 | goto out; | ||
441 | |||
442 | ret = -EFAULT; | ||
443 | if (copy_from_user(karg.send_indices, u_si, | ||
444 | (karg.send_count * sizeof(int))) || | ||
445 | copy_from_user(karg.send_sizes, u_ss, | ||
446 | (karg.send_count * sizeof(int)))) | ||
447 | goto out; | ||
448 | } | ||
449 | |||
450 | if (karg.request_count) { | ||
451 | karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); | ||
452 | karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); | ||
453 | |||
454 | ret = -ENOMEM; | ||
455 | if (!karg.request_indices || !karg.request_sizes) | ||
456 | goto out; | ||
457 | |||
458 | ret = -EFAULT; | ||
459 | if (copy_from_user(karg.request_indices, u_ri, | ||
460 | (karg.request_count * sizeof(int))) || | ||
461 | copy_from_user(karg.request_sizes, u_rs, | ||
462 | (karg.request_count * sizeof(int)))) | ||
463 | goto out; | ||
464 | } | ||
465 | |||
466 | old_fs = get_fs(); | ||
467 | set_fs(KERNEL_DS); | ||
468 | ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg); | ||
469 | set_fs(old_fs); | ||
470 | |||
471 | if (!ret) { | ||
472 | if (put_user(karg.context, &uarg->context) || | ||
473 | put_user(karg.send_count, &uarg->send_count) || | ||
474 | put_user(karg.flags, &uarg->flags) || | ||
475 | put_user(karg.request_count, &uarg->request_count) || | ||
476 | put_user(karg.request_size, &uarg->request_size) || | ||
477 | put_user(karg.granted_count, &uarg->granted_count)) | ||
478 | ret = -EFAULT; | ||
479 | |||
480 | if (karg.send_count) { | ||
481 | if (copy_to_user(u_si, karg.send_indices, | ||
482 | (karg.send_count * sizeof(int))) || | ||
483 | copy_to_user(u_ss, karg.send_sizes, | ||
484 | (karg.send_count * sizeof(int)))) | ||
485 | ret = -EFAULT; | ||
486 | } | ||
487 | if (karg.request_count) { | ||
488 | if (copy_to_user(u_ri, karg.request_indices, | ||
489 | (karg.request_count * sizeof(int))) || | ||
490 | copy_to_user(u_rs, karg.request_sizes, | ||
491 | (karg.request_count * sizeof(int)))) | ||
492 | ret = -EFAULT; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | out: | ||
497 | if (karg.send_indices) | ||
498 | kfree(karg.send_indices); | ||
499 | if (karg.send_sizes) | ||
500 | kfree(karg.send_sizes); | ||
501 | if (karg.request_indices) | ||
502 | kfree(karg.request_indices); | ||
503 | if (karg.request_sizes) | ||
504 | kfree(karg.request_sizes); | ||
505 | |||
506 | return ret; | ||
507 | } | ||
508 | |||
509 | typedef struct drm32_ctx_res { | ||
510 | int count; | ||
511 | u32 contexts; /* (drm_ctx_t *) */ | ||
512 | } drm32_ctx_res_t; | ||
513 | #define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t) | ||
514 | |||
515 | static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
516 | { | ||
517 | drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg; | ||
518 | drm_ctx_t *ulist; | ||
519 | drm_ctx_res_t karg; | ||
520 | mm_segment_t old_fs; | ||
521 | int orig_count, ret; | ||
522 | u32 tmp; | ||
523 | |||
524 | karg.contexts = NULL; | ||
525 | if (get_user(karg.count, &uarg->count) || | ||
526 | get_user(tmp, &uarg->contexts)) | ||
527 | return -EFAULT; | ||
528 | |||
529 | ulist = (drm_ctx_t *) A(tmp); | ||
530 | |||
531 | orig_count = karg.count; | ||
532 | if (karg.count && ulist) { | ||
533 | karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL); | ||
534 | if (!karg.contexts) | ||
535 | return -ENOMEM; | ||
536 | if (copy_from_user(karg.contexts, ulist, | ||
537 | (karg.count * sizeof(drm_ctx_t)))) { | ||
538 | kfree(karg.contexts); | ||
539 | return -EFAULT; | ||
540 | } | ||
541 | } | ||
542 | |||
543 | old_fs = get_fs(); | ||
544 | set_fs(KERNEL_DS); | ||
545 | ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg); | ||
546 | set_fs(old_fs); | ||
547 | |||
548 | if (!ret) { | ||
549 | if (orig_count) { | ||
550 | if (copy_to_user(ulist, karg.contexts, | ||
551 | (orig_count * sizeof(drm_ctx_t)))) | ||
552 | ret = -EFAULT; | ||
553 | } | ||
554 | if (put_user(karg.count, &uarg->count)) | ||
555 | ret = -EFAULT; | ||
556 | } | ||
557 | |||
558 | if (karg.contexts) | ||
559 | kfree(karg.contexts); | ||
560 | |||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | #endif | ||
565 | |||
566 | #define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL }, | ||
567 | #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) | ||
568 | |||
569 | #define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = { | ||
570 | #define IOCTL_TABLE_END }; | ||
571 | |||
572 | IOCTL_TABLE_START | ||
573 | #include <linux/compat_ioctl.h> | ||
574 | |||
575 | #define DECLARES | ||
576 | #include "compat_ioctl.c" | ||
577 | |||
578 | /* Might be moved to compat_ioctl.h with some ifdefs... */ | ||
579 | COMPATIBLE_IOCTL(TIOCSTART) | ||
580 | COMPATIBLE_IOCTL(TIOCSTOP) | ||
581 | COMPATIBLE_IOCTL(TIOCSLTC) | ||
582 | |||
583 | /* PA-specific ioctls */ | ||
584 | COMPATIBLE_IOCTL(PA_PERF_ON) | ||
585 | COMPATIBLE_IOCTL(PA_PERF_OFF) | ||
586 | COMPATIBLE_IOCTL(PA_PERF_VERSION) | ||
587 | |||
588 | /* And these ioctls need translation */ | ||
589 | HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc) | ||
590 | HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc) | ||
591 | HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc) | ||
592 | |||
593 | #if defined(CONFIG_GEN_RTC) | ||
594 | COMPATIBLE_IOCTL(RTC_AIE_ON) | ||
595 | COMPATIBLE_IOCTL(RTC_AIE_OFF) | ||
596 | COMPATIBLE_IOCTL(RTC_UIE_ON) | ||
597 | COMPATIBLE_IOCTL(RTC_UIE_OFF) | ||
598 | COMPATIBLE_IOCTL(RTC_PIE_ON) | ||
599 | COMPATIBLE_IOCTL(RTC_PIE_OFF) | ||
600 | COMPATIBLE_IOCTL(RTC_WIE_ON) | ||
601 | COMPATIBLE_IOCTL(RTC_WIE_OFF) | ||
602 | COMPATIBLE_IOCTL(RTC_ALM_SET) /* struct rtc_time only has ints */ | ||
603 | COMPATIBLE_IOCTL(RTC_ALM_READ) /* struct rtc_time only has ints */ | ||
604 | COMPATIBLE_IOCTL(RTC_RD_TIME) /* struct rtc_time only has ints */ | ||
605 | COMPATIBLE_IOCTL(RTC_SET_TIME) /* struct rtc_time only has ints */ | ||
606 | HANDLE_IOCTL(RTC_IRQP_READ, w_long) | ||
607 | COMPATIBLE_IOCTL(RTC_IRQP_SET) | ||
608 | HANDLE_IOCTL(RTC_EPOCH_READ, w_long) | ||
609 | COMPATIBLE_IOCTL(RTC_EPOCH_SET) | ||
610 | #endif | ||
611 | |||
612 | #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) | ||
613 | HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version); | ||
614 | HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique); | ||
615 | HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique); | ||
616 | HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap); | ||
617 | HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs); | ||
618 | HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs); | ||
619 | HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs); | ||
620 | HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma); | ||
621 | HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx); | ||
622 | #endif /* DRM */ | ||
623 | IOCTL_TABLE_END | ||
624 | |||
625 | int ioctl_table_size = ARRAY_SIZE(ioctl_start); | ||
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c new file mode 100644 index 000000000000..006385dbee66 --- /dev/null +++ b/arch/parisc/kernel/irq.c | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * Code to handle x86 style IRQs plus some generic interrupt stuff. | ||
3 | * | ||
4 | * Copyright (C) 1992 Linus Torvalds | ||
5 | * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle | ||
6 | * Copyright (C) 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org) | ||
7 | * Copyright (C) 1999-2000 Grant Grundler | ||
8 | * Copyright (c) 2005 Matthew Wilcox | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2, or (at your option) | ||
13 | * any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | #include <linux/bitops.h> | ||
25 | #include <linux/config.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/kernel_stat.h> | ||
30 | #include <linux/seq_file.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/types.h> | ||
33 | |||
34 | #undef PARISC_IRQ_CR16_COUNTS | ||
35 | |||
36 | extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *); | ||
37 | extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *); | ||
38 | |||
39 | #define EIEM_MASK(irq) (1UL<<(CPU_IRQ_MAX - irq)) | ||
40 | |||
41 | /* Bits in EIEM correlate with cpu_irq_action[]. | ||
42 | ** Numbered *Big Endian*! (ie bit 0 is MSB) | ||
43 | */ | ||
44 | static volatile unsigned long cpu_eiem = 0; | ||
45 | |||
46 | static void cpu_set_eiem(void *info) | ||
47 | { | ||
48 | set_eiem((unsigned long) info); | ||
49 | } | ||
50 | |||
51 | static inline void cpu_disable_irq(unsigned int irq) | ||
52 | { | ||
53 | unsigned long eirr_bit = EIEM_MASK(irq); | ||
54 | |||
55 | cpu_eiem &= ~eirr_bit; | ||
56 | on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1); | ||
57 | } | ||
58 | |||
59 | static void cpu_enable_irq(unsigned int irq) | ||
60 | { | ||
61 | unsigned long eirr_bit = EIEM_MASK(irq); | ||
62 | |||
63 | mtctl(eirr_bit, 23); /* clear EIRR bit before unmasking */ | ||
64 | cpu_eiem |= eirr_bit; | ||
65 | on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1); | ||
66 | } | ||
67 | |||
68 | static unsigned int cpu_startup_irq(unsigned int irq) | ||
69 | { | ||
70 | cpu_enable_irq(irq); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | void no_ack_irq(unsigned int irq) { } | ||
75 | void no_end_irq(unsigned int irq) { } | ||
76 | |||
77 | static struct hw_interrupt_type cpu_interrupt_type = { | ||
78 | .typename = "CPU", | ||
79 | .startup = cpu_startup_irq, | ||
80 | .shutdown = cpu_disable_irq, | ||
81 | .enable = cpu_enable_irq, | ||
82 | .disable = cpu_disable_irq, | ||
83 | .ack = no_ack_irq, | ||
84 | .end = no_end_irq, | ||
85 | // .set_affinity = cpu_set_affinity_irq, | ||
86 | }; | ||
87 | |||
88 | int show_interrupts(struct seq_file *p, void *v) | ||
89 | { | ||
90 | int i = *(loff_t *) v, j; | ||
91 | unsigned long flags; | ||
92 | |||
93 | if (i == 0) { | ||
94 | seq_puts(p, " "); | ||
95 | for_each_online_cpu(j) | ||
96 | seq_printf(p, " CPU%d", j); | ||
97 | |||
98 | #ifdef PARISC_IRQ_CR16_COUNTS | ||
99 | seq_printf(p, " [min/avg/max] (CPU cycle counts)"); | ||
100 | #endif | ||
101 | seq_putc(p, '\n'); | ||
102 | } | ||
103 | |||
104 | if (i < NR_IRQS) { | ||
105 | struct irqaction *action; | ||
106 | |||
107 | spin_lock_irqsave(&irq_desc[i].lock, flags); | ||
108 | action = irq_desc[i].action; | ||
109 | if (!action) | ||
110 | goto skip; | ||
111 | seq_printf(p, "%3d: ", i); | ||
112 | #ifdef CONFIG_SMP | ||
113 | for_each_online_cpu(j) | ||
114 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | ||
115 | #else | ||
116 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
117 | #endif | ||
118 | |||
119 | seq_printf(p, " %14s", irq_desc[i].handler->typename); | ||
120 | #ifndef PARISC_IRQ_CR16_COUNTS | ||
121 | seq_printf(p, " %s", action->name); | ||
122 | |||
123 | while ((action = action->next)) | ||
124 | seq_printf(p, ", %s", action->name); | ||
125 | #else | ||
126 | for ( ;action; action = action->next) { | ||
127 | unsigned int k, avg, min, max; | ||
128 | |||
129 | min = max = action->cr16_hist[0]; | ||
130 | |||
131 | for (avg = k = 0; k < PARISC_CR16_HIST_SIZE; k++) { | ||
132 | int hist = action->cr16_hist[k]; | ||
133 | |||
134 | if (hist) { | ||
135 | avg += hist; | ||
136 | } else | ||
137 | break; | ||
138 | |||
139 | if (hist > max) max = hist; | ||
140 | if (hist < min) min = hist; | ||
141 | } | ||
142 | |||
143 | avg /= k; | ||
144 | seq_printf(p, " %s[%d/%d/%d]", action->name, | ||
145 | min,avg,max); | ||
146 | } | ||
147 | #endif | ||
148 | |||
149 | seq_putc(p, '\n'); | ||
150 | skip: | ||
151 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | ||
152 | } | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
158 | |||
159 | /* | ||
160 | ** The following form a "set": Virtual IRQ, Transaction Address, Trans Data. | ||
161 | ** Respectively, these map to IRQ region+EIRR, Processor HPA, EIRR bit. | ||
162 | ** | ||
163 | ** To use txn_XXX() interfaces, get a Virtual IRQ first. | ||
164 | ** Then use that to get the Transaction address and data. | ||
165 | */ | ||
166 | |||
167 | int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *type, void *data) | ||
168 | { | ||
169 | if (irq_desc[irq].action) | ||
170 | return -EBUSY; | ||
171 | if (irq_desc[irq].handler != &cpu_interrupt_type) | ||
172 | return -EBUSY; | ||
173 | |||
174 | if (type) { | ||
175 | irq_desc[irq].handler = type; | ||
176 | irq_desc[irq].handler_data = data; | ||
177 | cpu_interrupt_type.enable(irq); | ||
178 | } | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | int txn_claim_irq(int irq) | ||
183 | { | ||
184 | return cpu_claim_irq(irq, NULL, NULL) ? -1 : irq; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * The bits_wide parameter accommodates the limitations of the HW/SW which | ||
189 | * use these bits: | ||
190 | * Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register) | ||
191 | * V-class (EPIC): 6 bits | ||
192 | * N/L/A-class (iosapic): 8 bits | ||
193 | * PCI 2.2 MSI: 16 bits | ||
194 | * Some PCI devices: 32 bits (Symbios SCSI/ATM/HyperFabric) | ||
195 | * | ||
196 | * On the service provider side: | ||
197 | * o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register) | ||
198 | * o PA 2.0 wide mode 6-bits (per processor) | ||
199 | * o IA64 8-bits (0-256 total) | ||
200 | * | ||
201 | * So a Legacy PA I/O device on a PA 2.0 box can't use all the bits supported | ||
202 | * by the processor...and the N/L-class I/O subsystem supports more bits than | ||
203 | * PA2.0 has. The first case is the problem. | ||
204 | */ | ||
205 | int txn_alloc_irq(unsigned int bits_wide) | ||
206 | { | ||
207 | int irq; | ||
208 | |||
209 | /* never return irq 0 cause that's the interval timer */ | ||
210 | for (irq = CPU_IRQ_BASE + 1; irq <= CPU_IRQ_MAX; irq++) { | ||
211 | if (cpu_claim_irq(irq, NULL, NULL) < 0) | ||
212 | continue; | ||
213 | if ((irq - CPU_IRQ_BASE) >= (1 << bits_wide)) | ||
214 | continue; | ||
215 | return irq; | ||
216 | } | ||
217 | |||
218 | /* unlikely, but be prepared */ | ||
219 | return -1; | ||
220 | } | ||
221 | |||
222 | unsigned long txn_alloc_addr(unsigned int virt_irq) | ||
223 | { | ||
224 | static int next_cpu = -1; | ||
225 | |||
226 | next_cpu++; /* assign to "next" CPU we want this bugger on */ | ||
227 | |||
228 | /* validate entry */ | ||
229 | while ((next_cpu < NR_CPUS) && (!cpu_data[next_cpu].txn_addr || | ||
230 | !cpu_online(next_cpu))) | ||
231 | next_cpu++; | ||
232 | |||
233 | if (next_cpu >= NR_CPUS) | ||
234 | next_cpu = 0; /* nothing else, assign monarch */ | ||
235 | |||
236 | return cpu_data[next_cpu].txn_addr; | ||
237 | } | ||
238 | |||
239 | |||
240 | unsigned int txn_alloc_data(unsigned int virt_irq) | ||
241 | { | ||
242 | return virt_irq - CPU_IRQ_BASE; | ||
243 | } | ||
244 | |||
245 | /* ONLY called from entry.S:intr_extint() */ | ||
246 | void do_cpu_irq_mask(struct pt_regs *regs) | ||
247 | { | ||
248 | unsigned long eirr_val; | ||
249 | |||
250 | irq_enter(); | ||
251 | |||
252 | /* | ||
253 | * Only allow interrupt processing to be interrupted by the | ||
254 | * timer tick | ||
255 | */ | ||
256 | set_eiem(EIEM_MASK(TIMER_IRQ)); | ||
257 | |||
258 | /* 1) only process IRQs that are enabled/unmasked (cpu_eiem) | ||
259 | * 2) We loop here on EIRR contents in order to avoid | ||
260 | * nested interrupts or having to take another interrupt | ||
261 | * when we could have just handled it right away. | ||
262 | */ | ||
263 | for (;;) { | ||
264 | unsigned long bit = (1UL << (BITS_PER_LONG - 1)); | ||
265 | unsigned int irq; | ||
266 | eirr_val = mfctl(23) & cpu_eiem; | ||
267 | if (!eirr_val) | ||
268 | break; | ||
269 | |||
270 | if (eirr_val & EIEM_MASK(TIMER_IRQ)) | ||
271 | set_eiem(0); | ||
272 | |||
273 | mtctl(eirr_val, 23); /* reset bits we are going to process */ | ||
274 | |||
275 | /* Work our way from MSb to LSb...same order we alloc EIRs */ | ||
276 | for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) { | ||
277 | if (!(bit & eirr_val)) | ||
278 | continue; | ||
279 | |||
280 | /* clear bit in mask - can exit loop sooner */ | ||
281 | eirr_val &= ~bit; | ||
282 | |||
283 | __do_IRQ(irq, regs); | ||
284 | } | ||
285 | } | ||
286 | set_eiem(cpu_eiem); | ||
287 | irq_exit(); | ||
288 | } | ||
289 | |||
290 | |||
291 | static struct irqaction timer_action = { | ||
292 | .handler = timer_interrupt, | ||
293 | .name = "timer", | ||
294 | }; | ||
295 | |||
296 | #ifdef CONFIG_SMP | ||
297 | static struct irqaction ipi_action = { | ||
298 | .handler = ipi_interrupt, | ||
299 | .name = "IPI", | ||
300 | }; | ||
301 | #endif | ||
302 | |||
303 | static void claim_cpu_irqs(void) | ||
304 | { | ||
305 | int i; | ||
306 | for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) { | ||
307 | irq_desc[i].handler = &cpu_interrupt_type; | ||
308 | } | ||
309 | |||
310 | irq_desc[TIMER_IRQ].action = &timer_action; | ||
311 | irq_desc[TIMER_IRQ].status |= IRQ_PER_CPU; | ||
312 | #ifdef CONFIG_SMP | ||
313 | irq_desc[IPI_IRQ].action = &ipi_action; | ||
314 | irq_desc[IPI_IRQ].status = IRQ_PER_CPU; | ||
315 | #endif | ||
316 | } | ||
317 | |||
318 | void __init init_IRQ(void) | ||
319 | { | ||
320 | local_irq_disable(); /* PARANOID - should already be disabled */ | ||
321 | mtctl(~0UL, 23); /* EIRR : clear all pending external intr */ | ||
322 | claim_cpu_irqs(); | ||
323 | #ifdef CONFIG_SMP | ||
324 | if (!cpu_eiem) | ||
325 | cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ); | ||
326 | #else | ||
327 | cpu_eiem = EIEM_MASK(TIMER_IRQ); | ||
328 | #endif | ||
329 | set_eiem(cpu_eiem); /* EIEM : enable all external intr */ | ||
330 | |||
331 | } | ||
332 | |||
333 | void hw_resend_irq(struct hw_interrupt_type *type, unsigned int irq) | ||
334 | { | ||
335 | /* XXX: Needs to be written. We managed without it so far, but | ||
336 | * we really ought to write it. | ||
337 | */ | ||
338 | } | ||
339 | |||
340 | void ack_bad_irq(unsigned int irq) | ||
341 | { | ||
342 | printk("unexpected IRQ %d\n", irq); | ||
343 | } | ||
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c new file mode 100644 index 000000000000..f27cfe4771b8 --- /dev/null +++ b/arch/parisc/kernel/module.c | |||
@@ -0,0 +1,822 @@ | |||
1 | /* Kernel dynamically loadable module help for PARISC. | ||
2 | * | ||
3 | * The best reference for this stuff is probably the Processor- | ||
4 | * Specific ELF Supplement for PA-RISC: | ||
5 | * http://ftp.parisc-linux.org/docs/arch/elf-pa-hp.pdf | ||
6 | * | ||
7 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
8 | * Copyright (C) 2003 Randolph Chung <tausq at debian . org> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | * | ||
26 | * Notes: | ||
27 | * - SEGREL32 handling | ||
28 | * We are not doing SEGREL32 handling correctly. According to the ABI, we | ||
29 | * should do a value offset, like this: | ||
30 | * if (is_init(me, (void *)val)) | ||
31 | * val -= (uint32_t)me->module_init; | ||
32 | * else | ||
33 | * val -= (uint32_t)me->module_core; | ||
34 | * However, SEGREL32 is used only for PARISC unwind entries, and we want | ||
35 | * those entries to have an absolute address, and not just an offset. | ||
36 | * | ||
37 | * The unwind table mechanism has the ability to specify an offset for | ||
38 | * the unwind table; however, because we split off the init functions into | ||
39 | * a different piece of memory, it is not possible to do this using a | ||
40 | * single offset. Instead, we use the above hack for now. | ||
41 | */ | ||
42 | |||
43 | #include <linux/moduleloader.h> | ||
44 | #include <linux/elf.h> | ||
45 | #include <linux/vmalloc.h> | ||
46 | #include <linux/fs.h> | ||
47 | #include <linux/string.h> | ||
48 | #include <linux/kernel.h> | ||
49 | |||
50 | #include <asm/unwind.h> | ||
51 | |||
52 | #if 0 | ||
53 | #define DEBUGP printk | ||
54 | #else | ||
55 | #define DEBUGP(fmt...) | ||
56 | #endif | ||
57 | |||
58 | #define CHECK_RELOC(val, bits) \ | ||
59 | if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ | ||
60 | ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \ | ||
61 | printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ | ||
62 | me->name, strtab + sym->st_name, (unsigned long)val, bits); \ | ||
63 | return -ENOEXEC; \ | ||
64 | } | ||
65 | |||
66 | /* Maximum number of GOT entries. We use a long displacement ldd from | ||
67 | * the bottom of the table, which has a maximum signed displacement of | ||
68 | * 0x3fff; however, since we're only going forward, this becomes | ||
69 | * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have | ||
70 | * at most 1023 entries */ | ||
71 | #define MAX_GOTS 1023 | ||
72 | |||
73 | /* three functions to determine where in the module core | ||
74 | * or init pieces the location is */ | ||
75 | static inline int is_init(struct module *me, void *loc) | ||
76 | { | ||
77 | return (loc >= me->module_init && | ||
78 | loc <= (me->module_init + me->init_size)); | ||
79 | } | ||
80 | |||
81 | static inline int is_core(struct module *me, void *loc) | ||
82 | { | ||
83 | return (loc >= me->module_core && | ||
84 | loc <= (me->module_core + me->core_size)); | ||
85 | } | ||
86 | |||
87 | static inline int is_local(struct module *me, void *loc) | ||
88 | { | ||
89 | return is_init(me, loc) || is_core(me, loc); | ||
90 | } | ||
91 | |||
92 | |||
93 | #ifndef __LP64__ | ||
94 | struct got_entry { | ||
95 | Elf32_Addr addr; | ||
96 | }; | ||
97 | |||
98 | #define Elf_Fdesc Elf32_Fdesc | ||
99 | |||
100 | struct stub_entry { | ||
101 | Elf32_Word insns[2]; /* each stub entry has two insns */ | ||
102 | }; | ||
103 | #else | ||
104 | struct got_entry { | ||
105 | Elf64_Addr addr; | ||
106 | }; | ||
107 | |||
108 | #define Elf_Fdesc Elf64_Fdesc | ||
109 | |||
110 | struct stub_entry { | ||
111 | Elf64_Word insns[4]; /* each stub entry has four insns */ | ||
112 | }; | ||
113 | #endif | ||
114 | |||
115 | /* Field selection types defined by hppa */ | ||
116 | #define rnd(x) (((x)+0x1000)&~0x1fff) | ||
117 | /* fsel: full 32 bits */ | ||
118 | #define fsel(v,a) ((v)+(a)) | ||
119 | /* lsel: select left 21 bits */ | ||
120 | #define lsel(v,a) (((v)+(a))>>11) | ||
121 | /* rsel: select right 11 bits */ | ||
122 | #define rsel(v,a) (((v)+(a))&0x7ff) | ||
123 | /* lrsel with rounding of addend to nearest 8k */ | ||
124 | #define lrsel(v,a) (((v)+rnd(a))>>11) | ||
125 | /* rrsel with rounding of addend to nearest 8k */ | ||
126 | #define rrsel(v,a) ((((v)+rnd(a))&0x7ff)+((a)-rnd(a))) | ||
127 | |||
128 | #define mask(x,sz) ((x) & ~((1<<(sz))-1)) | ||
129 | |||
130 | |||
131 | /* The reassemble_* functions prepare an immediate value for | ||
132 | insertion into an opcode. pa-risc uses all sorts of weird bitfields | ||
133 | in the instruction to hold the value. */ | ||
134 | static inline int reassemble_14(int as14) | ||
135 | { | ||
136 | return (((as14 & 0x1fff) << 1) | | ||
137 | ((as14 & 0x2000) >> 13)); | ||
138 | } | ||
139 | |||
140 | static inline int reassemble_17(int as17) | ||
141 | { | ||
142 | return (((as17 & 0x10000) >> 16) | | ||
143 | ((as17 & 0x0f800) << 5) | | ||
144 | ((as17 & 0x00400) >> 8) | | ||
145 | ((as17 & 0x003ff) << 3)); | ||
146 | } | ||
147 | |||
148 | static inline int reassemble_21(int as21) | ||
149 | { | ||
150 | return (((as21 & 0x100000) >> 20) | | ||
151 | ((as21 & 0x0ffe00) >> 8) | | ||
152 | ((as21 & 0x000180) << 7) | | ||
153 | ((as21 & 0x00007c) << 14) | | ||
154 | ((as21 & 0x000003) << 12)); | ||
155 | } | ||
156 | |||
157 | static inline int reassemble_22(int as22) | ||
158 | { | ||
159 | return (((as22 & 0x200000) >> 21) | | ||
160 | ((as22 & 0x1f0000) << 5) | | ||
161 | ((as22 & 0x00f800) << 5) | | ||
162 | ((as22 & 0x000400) >> 8) | | ||
163 | ((as22 & 0x0003ff) << 3)); | ||
164 | } | ||
165 | |||
166 | void *module_alloc(unsigned long size) | ||
167 | { | ||
168 | if (size == 0) | ||
169 | return NULL; | ||
170 | return vmalloc(size); | ||
171 | } | ||
172 | |||
173 | #ifndef __LP64__ | ||
174 | static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n) | ||
175 | { | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n) | ||
180 | { | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) | ||
185 | { | ||
186 | unsigned long cnt = 0; | ||
187 | |||
188 | for (; n > 0; n--, rela++) | ||
189 | { | ||
190 | switch (ELF32_R_TYPE(rela->r_info)) { | ||
191 | case R_PARISC_PCREL17F: | ||
192 | case R_PARISC_PCREL22F: | ||
193 | cnt++; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | return cnt; | ||
198 | } | ||
199 | #else | ||
200 | static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n) | ||
201 | { | ||
202 | unsigned long cnt = 0; | ||
203 | |||
204 | for (; n > 0; n--, rela++) | ||
205 | { | ||
206 | switch (ELF64_R_TYPE(rela->r_info)) { | ||
207 | case R_PARISC_LTOFF21L: | ||
208 | case R_PARISC_LTOFF14R: | ||
209 | case R_PARISC_PCREL22F: | ||
210 | cnt++; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | return cnt; | ||
215 | } | ||
216 | |||
217 | static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n) | ||
218 | { | ||
219 | unsigned long cnt = 0; | ||
220 | |||
221 | for (; n > 0; n--, rela++) | ||
222 | { | ||
223 | switch (ELF64_R_TYPE(rela->r_info)) { | ||
224 | case R_PARISC_FPTR64: | ||
225 | cnt++; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | return cnt; | ||
230 | } | ||
231 | |||
232 | static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) | ||
233 | { | ||
234 | unsigned long cnt = 0; | ||
235 | |||
236 | for (; n > 0; n--, rela++) | ||
237 | { | ||
238 | switch (ELF64_R_TYPE(rela->r_info)) { | ||
239 | case R_PARISC_PCREL22F: | ||
240 | cnt++; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | return cnt; | ||
245 | } | ||
246 | #endif | ||
247 | |||
248 | |||
249 | /* Free memory returned from module_alloc */ | ||
250 | void module_free(struct module *mod, void *module_region) | ||
251 | { | ||
252 | vfree(module_region); | ||
253 | /* FIXME: If module_region == mod->init_region, trim exception | ||
254 | table entries. */ | ||
255 | } | ||
256 | |||
257 | #define CONST | ||
258 | int module_frob_arch_sections(CONST Elf_Ehdr *hdr, | ||
259 | CONST Elf_Shdr *sechdrs, | ||
260 | CONST char *secstrings, | ||
261 | struct module *me) | ||
262 | { | ||
263 | unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0; | ||
264 | unsigned int i; | ||
265 | |||
266 | for (i = 1; i < hdr->e_shnum; i++) { | ||
267 | const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset; | ||
268 | unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); | ||
269 | |||
270 | if (strncmp(secstrings + sechdrs[i].sh_name, | ||
271 | ".PARISC.unwind", 14) == 0) | ||
272 | me->arch.unwind_section = i; | ||
273 | |||
274 | if (sechdrs[i].sh_type != SHT_RELA) | ||
275 | continue; | ||
276 | |||
277 | /* some of these are not relevant for 32-bit/64-bit | ||
278 | * we leave them here to make the code common. the | ||
279 | * compiler will do its thing and optimize out the | ||
280 | * stuff we don't need | ||
281 | */ | ||
282 | gots += count_gots(rels, nrels); | ||
283 | fdescs += count_fdescs(rels, nrels); | ||
284 | if(strncmp(secstrings + sechdrs[i].sh_name, | ||
285 | ".rela.init", 10) == 0) | ||
286 | init_stubs += count_stubs(rels, nrels); | ||
287 | else | ||
288 | stubs += count_stubs(rels, nrels); | ||
289 | } | ||
290 | |||
291 | /* align things a bit */ | ||
292 | me->core_size = ALIGN(me->core_size, 16); | ||
293 | me->arch.got_offset = me->core_size; | ||
294 | me->core_size += gots * sizeof(struct got_entry); | ||
295 | |||
296 | me->core_size = ALIGN(me->core_size, 16); | ||
297 | me->arch.fdesc_offset = me->core_size; | ||
298 | me->core_size += fdescs * sizeof(Elf_Fdesc); | ||
299 | |||
300 | me->core_size = ALIGN(me->core_size, 16); | ||
301 | me->arch.stub_offset = me->core_size; | ||
302 | me->core_size += stubs * sizeof(struct stub_entry); | ||
303 | |||
304 | me->init_size = ALIGN(me->init_size, 16); | ||
305 | me->arch.init_stub_offset = me->init_size; | ||
306 | me->init_size += init_stubs * sizeof(struct stub_entry); | ||
307 | |||
308 | me->arch.got_max = gots; | ||
309 | me->arch.fdesc_max = fdescs; | ||
310 | me->arch.stub_max = stubs; | ||
311 | me->arch.init_stub_max = init_stubs; | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | #ifdef __LP64__ | ||
317 | static Elf64_Word get_got(struct module *me, unsigned long value, long addend) | ||
318 | { | ||
319 | unsigned int i; | ||
320 | struct got_entry *got; | ||
321 | |||
322 | value += addend; | ||
323 | |||
324 | BUG_ON(value == 0); | ||
325 | |||
326 | got = me->module_core + me->arch.got_offset; | ||
327 | for (i = 0; got[i].addr; i++) | ||
328 | if (got[i].addr == value) | ||
329 | goto out; | ||
330 | |||
331 | BUG_ON(++me->arch.got_count > me->arch.got_max); | ||
332 | |||
333 | got[i].addr = value; | ||
334 | out: | ||
335 | DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry), | ||
336 | value); | ||
337 | return i * sizeof(struct got_entry); | ||
338 | } | ||
339 | #endif /* __LP64__ */ | ||
340 | |||
341 | #ifdef __LP64__ | ||
342 | static Elf_Addr get_fdesc(struct module *me, unsigned long value) | ||
343 | { | ||
344 | Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset; | ||
345 | |||
346 | if (!value) { | ||
347 | printk(KERN_ERR "%s: zero OPD requested!\n", me->name); | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | /* Look for existing fdesc entry. */ | ||
352 | while (fdesc->addr) { | ||
353 | if (fdesc->addr == value) | ||
354 | return (Elf_Addr)fdesc; | ||
355 | fdesc++; | ||
356 | } | ||
357 | |||
358 | BUG_ON(++me->arch.fdesc_count > me->arch.fdesc_max); | ||
359 | |||
360 | /* Create new one */ | ||
361 | fdesc->addr = value; | ||
362 | fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset; | ||
363 | return (Elf_Addr)fdesc; | ||
364 | } | ||
365 | #endif /* __LP64__ */ | ||
366 | |||
367 | static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, | ||
368 | int millicode, int init_section) | ||
369 | { | ||
370 | unsigned long i; | ||
371 | struct stub_entry *stub; | ||
372 | |||
373 | if(init_section) { | ||
374 | i = me->arch.init_stub_count++; | ||
375 | BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max); | ||
376 | stub = me->module_init + me->arch.init_stub_offset + | ||
377 | i * sizeof(struct stub_entry); | ||
378 | } else { | ||
379 | i = me->arch.stub_count++; | ||
380 | BUG_ON(me->arch.stub_count > me->arch.stub_max); | ||
381 | stub = me->module_core + me->arch.stub_offset + | ||
382 | i * sizeof(struct stub_entry); | ||
383 | } | ||
384 | |||
385 | #ifndef __LP64__ | ||
386 | /* for 32-bit the stub looks like this: | ||
387 | * ldil L'XXX,%r1 | ||
388 | * be,n R'XXX(%sr4,%r1) | ||
389 | */ | ||
390 | //value = *(unsigned long *)((value + addend) & ~3); /* why? */ | ||
391 | |||
392 | stub->insns[0] = 0x20200000; /* ldil L'XXX,%r1 */ | ||
393 | stub->insns[1] = 0xe0202002; /* be,n R'XXX(%sr4,%r1) */ | ||
394 | |||
395 | stub->insns[0] |= reassemble_21(lrsel(value, addend)); | ||
396 | stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4); | ||
397 | |||
398 | #else | ||
399 | /* for 64-bit we have two kinds of stubs: | ||
400 | * for normal function calls: | ||
401 | * ldd 0(%dp),%dp | ||
402 | * ldd 10(%dp), %r1 | ||
403 | * bve (%r1) | ||
404 | * ldd 18(%dp), %dp | ||
405 | * | ||
406 | * for millicode: | ||
407 | * ldil 0, %r1 | ||
408 | * ldo 0(%r1), %r1 | ||
409 | * ldd 10(%r1), %r1 | ||
410 | * bve,n (%r1) | ||
411 | */ | ||
412 | if (!millicode) | ||
413 | { | ||
414 | stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ | ||
415 | stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */ | ||
416 | stub->insns[2] = 0xe820d000; /* bve (%r1) */ | ||
417 | stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ | ||
418 | |||
419 | stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); | ||
420 | } | ||
421 | else | ||
422 | { | ||
423 | stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ | ||
424 | stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */ | ||
425 | stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */ | ||
426 | stub->insns[3] = 0xe820d002; /* bve,n (%r1) */ | ||
427 | |||
428 | stub->insns[0] |= reassemble_21(lrsel(value, addend)); | ||
429 | stub->insns[1] |= reassemble_14(rrsel(value, addend)); | ||
430 | } | ||
431 | #endif | ||
432 | |||
433 | return (Elf_Addr)stub; | ||
434 | } | ||
435 | |||
436 | int apply_relocate(Elf_Shdr *sechdrs, | ||
437 | const char *strtab, | ||
438 | unsigned int symindex, | ||
439 | unsigned int relsec, | ||
440 | struct module *me) | ||
441 | { | ||
442 | /* parisc should not need this ... */ | ||
443 | printk(KERN_ERR "module %s: RELOCATION unsupported\n", | ||
444 | me->name); | ||
445 | return -ENOEXEC; | ||
446 | } | ||
447 | |||
448 | #ifndef __LP64__ | ||
449 | int apply_relocate_add(Elf_Shdr *sechdrs, | ||
450 | const char *strtab, | ||
451 | unsigned int symindex, | ||
452 | unsigned int relsec, | ||
453 | struct module *me) | ||
454 | { | ||
455 | int i; | ||
456 | Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; | ||
457 | Elf32_Sym *sym; | ||
458 | Elf32_Word *loc; | ||
459 | Elf32_Addr val; | ||
460 | Elf32_Sword addend; | ||
461 | Elf32_Addr dot; | ||
462 | //unsigned long dp = (unsigned long)$global$; | ||
463 | register unsigned long dp asm ("r27"); | ||
464 | |||
465 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
466 | sechdrs[relsec].sh_info); | ||
467 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
468 | /* This is where to make the change */ | ||
469 | loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
470 | + rel[i].r_offset; | ||
471 | /* This is the symbol it is referring to */ | ||
472 | sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
473 | + ELF32_R_SYM(rel[i].r_info); | ||
474 | if (!sym->st_value) { | ||
475 | printk(KERN_WARNING "%s: Unknown symbol %s\n", | ||
476 | me->name, strtab + sym->st_name); | ||
477 | return -ENOENT; | ||
478 | } | ||
479 | //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03; | ||
480 | dot = (Elf32_Addr)loc & ~0x03; | ||
481 | |||
482 | val = sym->st_value; | ||
483 | addend = rel[i].r_addend; | ||
484 | |||
485 | #if 0 | ||
486 | #define r(t) ELF32_R_TYPE(rel[i].r_info)==t ? #t : | ||
487 | DEBUGP("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n", | ||
488 | strtab + sym->st_name, | ||
489 | (uint32_t)loc, val, addend, | ||
490 | r(R_PARISC_PLABEL32) | ||
491 | r(R_PARISC_DIR32) | ||
492 | r(R_PARISC_DIR21L) | ||
493 | r(R_PARISC_DIR14R) | ||
494 | r(R_PARISC_SEGREL32) | ||
495 | r(R_PARISC_DPREL21L) | ||
496 | r(R_PARISC_DPREL14R) | ||
497 | r(R_PARISC_PCREL17F) | ||
498 | r(R_PARISC_PCREL22F) | ||
499 | "UNKNOWN"); | ||
500 | #undef r | ||
501 | #endif | ||
502 | |||
503 | switch (ELF32_R_TYPE(rel[i].r_info)) { | ||
504 | case R_PARISC_PLABEL32: | ||
505 | /* 32-bit function address */ | ||
506 | /* no function descriptors... */ | ||
507 | *loc = fsel(val, addend); | ||
508 | break; | ||
509 | case R_PARISC_DIR32: | ||
510 | /* direct 32-bit ref */ | ||
511 | *loc = fsel(val, addend); | ||
512 | break; | ||
513 | case R_PARISC_DIR21L: | ||
514 | /* left 21 bits of effective address */ | ||
515 | val = lrsel(val, addend); | ||
516 | *loc = mask(*loc, 21) | reassemble_21(val); | ||
517 | break; | ||
518 | case R_PARISC_DIR14R: | ||
519 | /* right 14 bits of effective address */ | ||
520 | val = rrsel(val, addend); | ||
521 | *loc = mask(*loc, 14) | reassemble_14(val); | ||
522 | break; | ||
523 | case R_PARISC_SEGREL32: | ||
524 | /* 32-bit segment relative address */ | ||
525 | /* See note about special handling of SEGREL32 at | ||
526 | * the beginning of this file. | ||
527 | */ | ||
528 | *loc = fsel(val, addend); | ||
529 | break; | ||
530 | case R_PARISC_DPREL21L: | ||
531 | /* left 21 bit of relative address */ | ||
532 | val = lrsel(val - dp, addend); | ||
533 | *loc = mask(*loc, 21) | reassemble_21(val); | ||
534 | break; | ||
535 | case R_PARISC_DPREL14R: | ||
536 | /* right 14 bit of relative address */ | ||
537 | val = rrsel(val - dp, addend); | ||
538 | *loc = mask(*loc, 14) | reassemble_14(val); | ||
539 | break; | ||
540 | case R_PARISC_PCREL17F: | ||
541 | /* 17-bit PC relative address */ | ||
542 | val = get_stub(me, val, addend, 0, is_init(me, loc)); | ||
543 | val = (val - dot - 8)/4; | ||
544 | CHECK_RELOC(val, 17) | ||
545 | *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); | ||
546 | break; | ||
547 | case R_PARISC_PCREL22F: | ||
548 | /* 22-bit PC relative address; only defined for pa20 */ | ||
549 | val = get_stub(me, val, addend, 0, is_init(me, loc)); | ||
550 | DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", | ||
551 | strtab + sym->st_name, (unsigned long)loc, addend, | ||
552 | val) | ||
553 | val = (val - dot - 8)/4; | ||
554 | CHECK_RELOC(val, 22); | ||
555 | *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); | ||
556 | break; | ||
557 | |||
558 | default: | ||
559 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
560 | me->name, ELF32_R_TYPE(rel[i].r_info)); | ||
561 | return -ENOEXEC; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | #else | ||
569 | int apply_relocate_add(Elf_Shdr *sechdrs, | ||
570 | const char *strtab, | ||
571 | unsigned int symindex, | ||
572 | unsigned int relsec, | ||
573 | struct module *me) | ||
574 | { | ||
575 | int i; | ||
576 | Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; | ||
577 | Elf64_Sym *sym; | ||
578 | Elf64_Word *loc; | ||
579 | Elf64_Xword *loc64; | ||
580 | Elf64_Addr val; | ||
581 | Elf64_Sxword addend; | ||
582 | Elf64_Addr dot; | ||
583 | |||
584 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
585 | sechdrs[relsec].sh_info); | ||
586 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
587 | /* This is where to make the change */ | ||
588 | loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
589 | + rel[i].r_offset; | ||
590 | /* This is the symbol it is referring to */ | ||
591 | sym = (Elf64_Sym *)sechdrs[symindex].sh_addr | ||
592 | + ELF64_R_SYM(rel[i].r_info); | ||
593 | if (!sym->st_value) { | ||
594 | printk(KERN_WARNING "%s: Unknown symbol %s\n", | ||
595 | me->name, strtab + sym->st_name); | ||
596 | return -ENOENT; | ||
597 | } | ||
598 | //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03; | ||
599 | dot = (Elf64_Addr)loc & ~0x03; | ||
600 | loc64 = (Elf64_Xword *)loc; | ||
601 | |||
602 | val = sym->st_value; | ||
603 | addend = rel[i].r_addend; | ||
604 | |||
605 | #if 0 | ||
606 | #define r(t) ELF64_R_TYPE(rel[i].r_info)==t ? #t : | ||
607 | printk("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n", | ||
608 | strtab + sym->st_name, | ||
609 | loc, val, addend, | ||
610 | r(R_PARISC_LTOFF14R) | ||
611 | r(R_PARISC_LTOFF21L) | ||
612 | r(R_PARISC_PCREL22F) | ||
613 | r(R_PARISC_DIR64) | ||
614 | r(R_PARISC_SEGREL32) | ||
615 | r(R_PARISC_FPTR64) | ||
616 | "UNKNOWN"); | ||
617 | #undef r | ||
618 | #endif | ||
619 | |||
620 | switch (ELF64_R_TYPE(rel[i].r_info)) { | ||
621 | case R_PARISC_LTOFF21L: | ||
622 | /* LT-relative; left 21 bits */ | ||
623 | val = get_got(me, val, addend); | ||
624 | DEBUGP("LTOFF21L Symbol %s loc %p val %lx\n", | ||
625 | strtab + sym->st_name, | ||
626 | loc, val); | ||
627 | val = lrsel(val, 0); | ||
628 | *loc = mask(*loc, 21) | reassemble_21(val); | ||
629 | break; | ||
630 | case R_PARISC_LTOFF14R: | ||
631 | /* L(ltoff(val+addend)) */ | ||
632 | /* LT-relative; right 14 bits */ | ||
633 | val = get_got(me, val, addend); | ||
634 | val = rrsel(val, 0); | ||
635 | DEBUGP("LTOFF14R Symbol %s loc %p val %lx\n", | ||
636 | strtab + sym->st_name, | ||
637 | loc, val); | ||
638 | *loc = mask(*loc, 14) | reassemble_14(val); | ||
639 | break; | ||
640 | case R_PARISC_PCREL22F: | ||
641 | /* PC-relative; 22 bits */ | ||
642 | DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", | ||
643 | strtab + sym->st_name, | ||
644 | loc, val); | ||
645 | /* can we reach it locally? */ | ||
646 | if(!is_local(me, (void *)val)) { | ||
647 | if (strncmp(strtab + sym->st_name, "$$", 2) | ||
648 | == 0) | ||
649 | val = get_stub(me, val, addend, 1, | ||
650 | is_init(me, loc)); | ||
651 | else | ||
652 | val = get_stub(me, val, addend, 0, | ||
653 | is_init(me, loc)); | ||
654 | } | ||
655 | DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", | ||
656 | strtab + sym->st_name, loc, sym->st_value, | ||
657 | addend, val); | ||
658 | /* FIXME: local symbols work as long as the | ||
659 | * core and init pieces aren't separated too | ||
660 | * far. If this is ever broken, you will trip | ||
661 | * the check below. The way to fix it would | ||
662 | * be to generate local stubs to go between init | ||
663 | * and core */ | ||
664 | if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 || | ||
665 | (Elf64_Sxword)(val - dot - 8) < -0x800000) { | ||
666 | printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n", | ||
667 | me->name, strtab + sym->st_name); | ||
668 | return -ENOEXEC; | ||
669 | } | ||
670 | val = (val - dot - 8)/4; | ||
671 | *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); | ||
672 | break; | ||
673 | case R_PARISC_DIR64: | ||
674 | /* 64-bit effective address */ | ||
675 | *loc64 = val + addend; | ||
676 | break; | ||
677 | case R_PARISC_SEGREL32: | ||
678 | /* 32-bit segment relative address */ | ||
679 | /* See note about special handling of SEGREL32 at | ||
680 | * the beginning of this file. | ||
681 | */ | ||
682 | *loc = fsel(val, addend); | ||
683 | break; | ||
684 | case R_PARISC_FPTR64: | ||
685 | /* 64-bit function address */ | ||
686 | if(is_local(me, (void *)(val + addend))) { | ||
687 | *loc64 = get_fdesc(me, val+addend); | ||
688 | DEBUGP("FDESC for %s at %p points to %lx\n", | ||
689 | strtab + sym->st_name, *loc64, | ||
690 | ((Elf_Fdesc *)*loc64)->addr); | ||
691 | } else { | ||
692 | /* if the symbol is not local to this | ||
693 | * module then val+addend is a pointer | ||
694 | * to the function descriptor */ | ||
695 | DEBUGP("Non local FPTR64 Symbol %s loc %p val %lx\n", | ||
696 | strtab + sym->st_name, | ||
697 | loc, val); | ||
698 | *loc64 = val + addend; | ||
699 | } | ||
700 | break; | ||
701 | |||
702 | default: | ||
703 | printk(KERN_ERR "module %s: Unknown relocation: %Lu\n", | ||
704 | me->name, ELF64_R_TYPE(rel[i].r_info)); | ||
705 | return -ENOEXEC; | ||
706 | } | ||
707 | } | ||
708 | return 0; | ||
709 | } | ||
710 | #endif | ||
711 | |||
712 | static void | ||
713 | register_unwind_table(struct module *me, | ||
714 | const Elf_Shdr *sechdrs) | ||
715 | { | ||
716 | unsigned char *table, *end; | ||
717 | unsigned long gp; | ||
718 | |||
719 | if (!me->arch.unwind_section) | ||
720 | return; | ||
721 | |||
722 | table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr; | ||
723 | end = table + sechdrs[me->arch.unwind_section].sh_size; | ||
724 | gp = (Elf_Addr)me->module_core + me->arch.got_offset; | ||
725 | |||
726 | DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", | ||
727 | me->arch.unwind_section, table, end, gp); | ||
728 | me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end); | ||
729 | } | ||
730 | |||
731 | static void | ||
732 | deregister_unwind_table(struct module *me) | ||
733 | { | ||
734 | if (me->arch.unwind) | ||
735 | unwind_table_remove(me->arch.unwind); | ||
736 | } | ||
737 | |||
738 | int module_finalize(const Elf_Ehdr *hdr, | ||
739 | const Elf_Shdr *sechdrs, | ||
740 | struct module *me) | ||
741 | { | ||
742 | int i; | ||
743 | unsigned long nsyms; | ||
744 | const char *strtab = NULL; | ||
745 | Elf_Sym *newptr, *oldptr; | ||
746 | Elf_Shdr *symhdr = NULL; | ||
747 | #ifdef DEBUG | ||
748 | Elf_Fdesc *entry; | ||
749 | u32 *addr; | ||
750 | |||
751 | entry = (Elf_Fdesc *)me->init; | ||
752 | printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry, | ||
753 | entry->gp, entry->addr); | ||
754 | addr = (u32 *)entry->addr; | ||
755 | printk("INSNS: %x %x %x %x\n", | ||
756 | addr[0], addr[1], addr[2], addr[3]); | ||
757 | printk("stubs used %ld, stubs max %ld\n" | ||
758 | "init_stubs used %ld, init stubs max %ld\n" | ||
759 | "got entries used %ld, gots max %ld\n" | ||
760 | "fdescs used %ld, fdescs max %ld\n", | ||
761 | me->arch.stub_count, me->arch.stub_max, | ||
762 | me->arch.init_stub_count, me->arch.init_stub_max, | ||
763 | me->arch.got_count, me->arch.got_max, | ||
764 | me->arch.fdesc_count, me->arch.fdesc_max); | ||
765 | #endif | ||
766 | |||
767 | register_unwind_table(me, sechdrs); | ||
768 | |||
769 | /* haven't filled in me->symtab yet, so have to find it | ||
770 | * ourselves */ | ||
771 | for (i = 1; i < hdr->e_shnum; i++) { | ||
772 | if(sechdrs[i].sh_type == SHT_SYMTAB | ||
773 | && (sechdrs[i].sh_type & SHF_ALLOC)) { | ||
774 | int strindex = sechdrs[i].sh_link; | ||
775 | /* FIXME: AWFUL HACK | ||
776 | * The cast is to drop the const from | ||
777 | * the sechdrs pointer */ | ||
778 | symhdr = (Elf_Shdr *)&sechdrs[i]; | ||
779 | strtab = (char *)sechdrs[strindex].sh_addr; | ||
780 | break; | ||
781 | } | ||
782 | } | ||
783 | |||
784 | DEBUGP("module %s: strtab %p, symhdr %p\n", | ||
785 | me->name, strtab, symhdr); | ||
786 | |||
787 | if(me->arch.got_count > MAX_GOTS) { | ||
788 | printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d\n", me->name, me->arch.got_count, MAX_GOTS); | ||
789 | return -EINVAL; | ||
790 | } | ||
791 | |||
792 | /* no symbol table */ | ||
793 | if(symhdr == NULL) | ||
794 | return 0; | ||
795 | |||
796 | oldptr = (void *)symhdr->sh_addr; | ||
797 | newptr = oldptr + 1; /* we start counting at 1 */ | ||
798 | nsyms = symhdr->sh_size / sizeof(Elf_Sym); | ||
799 | DEBUGP("OLD num_symtab %lu\n", nsyms); | ||
800 | |||
801 | for (i = 1; i < nsyms; i++) { | ||
802 | oldptr++; /* note, count starts at 1 so preincrement */ | ||
803 | if(strncmp(strtab + oldptr->st_name, | ||
804 | ".L", 2) == 0) | ||
805 | continue; | ||
806 | |||
807 | if(newptr != oldptr) | ||
808 | *newptr++ = *oldptr; | ||
809 | else | ||
810 | newptr++; | ||
811 | |||
812 | } | ||
813 | nsyms = newptr - (Elf_Sym *)symhdr->sh_addr; | ||
814 | DEBUGP("NEW num_symtab %lu\n", nsyms); | ||
815 | symhdr->sh_size = nsyms * sizeof(Elf_Sym); | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | void module_arch_cleanup(struct module *mod) | ||
820 | { | ||
821 | deregister_unwind_table(mod); | ||
822 | } | ||
diff --git a/arch/parisc/kernel/pa7300lc.c b/arch/parisc/kernel/pa7300lc.c new file mode 100644 index 000000000000..8a89780223aa --- /dev/null +++ b/arch/parisc/kernel/pa7300lc.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * linux/arch/parisc/kernel/pa7300lc.c | ||
3 | * - PA7300LC-specific functions | ||
4 | * | ||
5 | * Copyright (C) 2000 Philipp Rumpf */ | ||
6 | |||
7 | #include <linux/sched.h> | ||
8 | #include <linux/smp.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <asm/io.h> | ||
11 | #include <asm/ptrace.h> | ||
12 | #include <asm/machdep.h> | ||
13 | |||
14 | /* CPU register indices */ | ||
15 | |||
16 | #define MIOC_STATUS 0xf040 | ||
17 | #define MIOC_CONTROL 0xf080 | ||
18 | #define MDERRADD 0xf0e0 | ||
19 | #define DMAERR 0xf0e8 | ||
20 | #define DIOERR 0xf0ec | ||
21 | #define HIDMAMEM 0xf0f4 | ||
22 | |||
23 | /* this returns the HPA of the CPU it was called on */ | ||
24 | static u32 cpu_hpa(void) | ||
25 | { | ||
26 | return 0xfffb0000; | ||
27 | } | ||
28 | |||
29 | static void pa7300lc_lpmc(int code, struct pt_regs *regs) | ||
30 | { | ||
31 | u32 hpa; | ||
32 | printk(KERN_WARNING "LPMC on CPU %d\n", smp_processor_id()); | ||
33 | |||
34 | show_regs(regs); | ||
35 | |||
36 | hpa = cpu_hpa(); | ||
37 | printk(KERN_WARNING | ||
38 | "MIOC_CONTROL %08x\n" "MIOC_STATUS %08x\n" | ||
39 | "MDERRADD %08x\n" "DMAERR %08x\n" | ||
40 | "DIOERR %08x\n" "HIDMAMEM %08x\n", | ||
41 | gsc_readl(hpa+MIOC_CONTROL), gsc_readl(hpa+MIOC_STATUS), | ||
42 | gsc_readl(hpa+MDERRADD), gsc_readl(hpa+DMAERR), | ||
43 | gsc_readl(hpa+DIOERR), gsc_readl(hpa+HIDMAMEM)); | ||
44 | } | ||
45 | |||
46 | void pa7300lc_init(void) | ||
47 | { | ||
48 | cpu_lpmc = pa7300lc_lpmc; | ||
49 | } | ||
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S new file mode 100644 index 000000000000..77e03bc0f935 --- /dev/null +++ b/arch/parisc/kernel/pacache.S | |||
@@ -0,0 +1,1086 @@ | |||
1 | /* | ||
2 | * PARISC TLB and cache flushing support | ||
3 | * Copyright (C) 2000-2001 Hewlett-Packard (John Marvin) | ||
4 | * Copyright (C) 2001 Matthew Wilcox (willy at parisc-linux.org) | ||
5 | * Copyright (C) 2002 Richard Hirst (rhirst with parisc-linux.org) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * NOTE: fdc,fic, and pdc instructions that use base register modification | ||
24 | * should only use index and base registers that are not shadowed, | ||
25 | * so that the fast path emulation in the non access miss handler | ||
26 | * can be used. | ||
27 | */ | ||
28 | |||
29 | #ifdef __LP64__ | ||
30 | #define ADDIB addib,* | ||
31 | #define CMPB cmpb,* | ||
32 | #define ANDCM andcm,* | ||
33 | |||
34 | .level 2.0w | ||
35 | #else | ||
36 | #define ADDIB addib, | ||
37 | #define CMPB cmpb, | ||
38 | #define ANDCM andcm | ||
39 | |||
40 | .level 2.0 | ||
41 | #endif | ||
42 | |||
43 | #include <asm/assembly.h> | ||
44 | #include <asm/psw.h> | ||
45 | #include <asm/pgtable.h> | ||
46 | #include <asm/cache.h> | ||
47 | |||
48 | .text | ||
49 | .align 128 | ||
50 | |||
51 | .export flush_tlb_all_local,code | ||
52 | |||
53 | flush_tlb_all_local: | ||
54 | .proc | ||
55 | .callinfo NO_CALLS | ||
56 | .entry | ||
57 | |||
58 | /* | ||
59 | * The pitlbe and pdtlbe instructions should only be used to | ||
60 | * flush the entire tlb. Also, there needs to be no intervening | ||
61 | * tlb operations, e.g. tlb misses, so the operation needs | ||
62 | * to happen in real mode with all interruptions disabled. | ||
63 | */ | ||
64 | |||
65 | /* | ||
66 | * Once again, we do the rfi dance ... some day we need examine | ||
67 | * all of our uses of this type of code and see what can be | ||
68 | * consolidated. | ||
69 | */ | ||
70 | |||
71 | rsm PSW_SM_I, %r19 /* relied upon translation! PA 2.0 Arch. F-5 */ | ||
72 | nop | ||
73 | nop | ||
74 | nop | ||
75 | nop | ||
76 | nop | ||
77 | nop | ||
78 | nop | ||
79 | |||
80 | rsm PSW_SM_Q, %r0 /* Turn off Q bit to load iia queue */ | ||
81 | ldil L%REAL_MODE_PSW, %r1 | ||
82 | ldo R%REAL_MODE_PSW(%r1), %r1 | ||
83 | mtctl %r1, %cr22 | ||
84 | mtctl %r0, %cr17 /* Clear IIASQ tail */ | ||
85 | mtctl %r0, %cr17 /* Clear IIASQ head */ | ||
86 | ldil L%PA(1f), %r1 | ||
87 | ldo R%PA(1f)(%r1), %r1 | ||
88 | mtctl %r1, %cr18 /* IIAOQ head */ | ||
89 | ldo 4(%r1), %r1 | ||
90 | mtctl %r1, %cr18 /* IIAOQ tail */ | ||
91 | rfi | ||
92 | nop | ||
93 | |||
94 | 1: ldil L%PA(cache_info), %r1 | ||
95 | ldo R%PA(cache_info)(%r1), %r1 | ||
96 | |||
97 | /* Flush Instruction Tlb */ | ||
98 | |||
99 | LDREG ITLB_SID_BASE(%r1), %r20 | ||
100 | LDREG ITLB_SID_STRIDE(%r1), %r21 | ||
101 | LDREG ITLB_SID_COUNT(%r1), %r22 | ||
102 | LDREG ITLB_OFF_BASE(%r1), %arg0 | ||
103 | LDREG ITLB_OFF_STRIDE(%r1), %arg1 | ||
104 | LDREG ITLB_OFF_COUNT(%r1), %arg2 | ||
105 | LDREG ITLB_LOOP(%r1), %arg3 | ||
106 | |||
107 | ADDIB= -1, %arg3, fitoneloop /* Preadjust and test */ | ||
108 | movb,<,n %arg3, %r31, fitdone /* If loop < 0, skip */ | ||
109 | copy %arg0, %r28 /* Init base addr */ | ||
110 | |||
111 | fitmanyloop: /* Loop if LOOP >= 2 */ | ||
112 | mtsp %r20, %sr1 | ||
113 | add %r21, %r20, %r20 /* increment space */ | ||
114 | copy %arg2, %r29 /* Init middle loop count */ | ||
115 | |||
116 | fitmanymiddle: /* Loop if LOOP >= 2 */ | ||
117 | ADDIB> -1, %r31, fitmanymiddle /* Adjusted inner loop decr */ | ||
118 | pitlbe 0(%sr1, %r28) | ||
119 | pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */ | ||
120 | ADDIB> -1, %r29, fitmanymiddle /* Middle loop decr */ | ||
121 | copy %arg3, %r31 /* Re-init inner loop count */ | ||
122 | |||
123 | movb,tr %arg0, %r28, fitmanyloop /* Re-init base addr */ | ||
124 | ADDIB<=,n -1, %r22, fitdone /* Outer loop count decr */ | ||
125 | |||
126 | fitoneloop: /* Loop if LOOP = 1 */ | ||
127 | mtsp %r20, %sr1 | ||
128 | copy %arg0, %r28 /* init base addr */ | ||
129 | copy %arg2, %r29 /* init middle loop count */ | ||
130 | |||
131 | fitonemiddle: /* Loop if LOOP = 1 */ | ||
132 | ADDIB> -1, %r29, fitonemiddle /* Middle loop count decr */ | ||
133 | pitlbe,m %arg1(%sr1, %r28) /* pitlbe for one loop */ | ||
134 | |||
135 | ADDIB> -1, %r22, fitoneloop /* Outer loop count decr */ | ||
136 | add %r21, %r20, %r20 /* increment space */ | ||
137 | |||
138 | fitdone: | ||
139 | |||
140 | /* Flush Data Tlb */ | ||
141 | |||
142 | LDREG DTLB_SID_BASE(%r1), %r20 | ||
143 | LDREG DTLB_SID_STRIDE(%r1), %r21 | ||
144 | LDREG DTLB_SID_COUNT(%r1), %r22 | ||
145 | LDREG DTLB_OFF_BASE(%r1), %arg0 | ||
146 | LDREG DTLB_OFF_STRIDE(%r1), %arg1 | ||
147 | LDREG DTLB_OFF_COUNT(%r1), %arg2 | ||
148 | LDREG DTLB_LOOP(%r1), %arg3 | ||
149 | |||
150 | ADDIB= -1, %arg3, fdtoneloop /* Preadjust and test */ | ||
151 | movb,<,n %arg3, %r31, fdtdone /* If loop < 0, skip */ | ||
152 | copy %arg0, %r28 /* Init base addr */ | ||
153 | |||
154 | fdtmanyloop: /* Loop if LOOP >= 2 */ | ||
155 | mtsp %r20, %sr1 | ||
156 | add %r21, %r20, %r20 /* increment space */ | ||
157 | copy %arg2, %r29 /* Init middle loop count */ | ||
158 | |||
159 | fdtmanymiddle: /* Loop if LOOP >= 2 */ | ||
160 | ADDIB> -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */ | ||
161 | pdtlbe 0(%sr1, %r28) | ||
162 | pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */ | ||
163 | ADDIB> -1, %r29, fdtmanymiddle /* Middle loop decr */ | ||
164 | copy %arg3, %r31 /* Re-init inner loop count */ | ||
165 | |||
166 | movb,tr %arg0, %r28, fdtmanyloop /* Re-init base addr */ | ||
167 | ADDIB<=,n -1, %r22,fdtdone /* Outer loop count decr */ | ||
168 | |||
169 | fdtoneloop: /* Loop if LOOP = 1 */ | ||
170 | mtsp %r20, %sr1 | ||
171 | copy %arg0, %r28 /* init base addr */ | ||
172 | copy %arg2, %r29 /* init middle loop count */ | ||
173 | |||
174 | fdtonemiddle: /* Loop if LOOP = 1 */ | ||
175 | ADDIB> -1, %r29, fdtonemiddle /* Middle loop count decr */ | ||
176 | pdtlbe,m %arg1(%sr1, %r28) /* pdtlbe for one loop */ | ||
177 | |||
178 | ADDIB> -1, %r22, fdtoneloop /* Outer loop count decr */ | ||
179 | add %r21, %r20, %r20 /* increment space */ | ||
180 | |||
181 | fdtdone: | ||
182 | |||
183 | /* Switch back to virtual mode */ | ||
184 | |||
185 | rsm PSW_SM_Q, %r0 /* clear Q bit to load iia queue */ | ||
186 | ldil L%KERNEL_PSW, %r1 | ||
187 | ldo R%KERNEL_PSW(%r1), %r1 | ||
188 | or %r1, %r19, %r1 /* Set I bit if set on entry */ | ||
189 | mtctl %r1, %cr22 | ||
190 | mtctl %r0, %cr17 /* Clear IIASQ tail */ | ||
191 | mtctl %r0, %cr17 /* Clear IIASQ head */ | ||
192 | ldil L%(2f), %r1 | ||
193 | ldo R%(2f)(%r1), %r1 | ||
194 | mtctl %r1, %cr18 /* IIAOQ head */ | ||
195 | ldo 4(%r1), %r1 | ||
196 | mtctl %r1, %cr18 /* IIAOQ tail */ | ||
197 | rfi | ||
198 | nop | ||
199 | |||
200 | 2: bv %r0(%r2) | ||
201 | nop | ||
202 | .exit | ||
203 | |||
204 | .procend | ||
205 | |||
206 | .export flush_instruction_cache_local,code | ||
207 | .import cache_info,data | ||
208 | |||
209 | flush_instruction_cache_local: | ||
210 | .proc | ||
211 | .callinfo NO_CALLS | ||
212 | .entry | ||
213 | |||
214 | mtsp %r0, %sr1 | ||
215 | ldil L%cache_info, %r1 | ||
216 | ldo R%cache_info(%r1), %r1 | ||
217 | |||
218 | /* Flush Instruction Cache */ | ||
219 | |||
220 | LDREG ICACHE_BASE(%r1), %arg0 | ||
221 | LDREG ICACHE_STRIDE(%r1), %arg1 | ||
222 | LDREG ICACHE_COUNT(%r1), %arg2 | ||
223 | LDREG ICACHE_LOOP(%r1), %arg3 | ||
224 | rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/ | ||
225 | ADDIB= -1, %arg3, fioneloop /* Preadjust and test */ | ||
226 | movb,<,n %arg3, %r31, fisync /* If loop < 0, do sync */ | ||
227 | |||
228 | fimanyloop: /* Loop if LOOP >= 2 */ | ||
229 | ADDIB> -1, %r31, fimanyloop /* Adjusted inner loop decr */ | ||
230 | fice 0(%sr1, %arg0) | ||
231 | fice,m %arg1(%sr1, %arg0) /* Last fice and addr adjust */ | ||
232 | movb,tr %arg3, %r31, fimanyloop /* Re-init inner loop count */ | ||
233 | ADDIB<=,n -1, %arg2, fisync /* Outer loop decr */ | ||
234 | |||
235 | fioneloop: /* Loop if LOOP = 1 */ | ||
236 | ADDIB> -1, %arg2, fioneloop /* Outer loop count decr */ | ||
237 | fice,m %arg1(%sr1, %arg0) /* Fice for one loop */ | ||
238 | |||
239 | fisync: | ||
240 | sync | ||
241 | mtsm %r22 | ||
242 | bv %r0(%r2) | ||
243 | nop | ||
244 | .exit | ||
245 | |||
246 | .procend | ||
247 | |||
248 | .export flush_data_cache_local, code | ||
249 | .import cache_info, data | ||
250 | |||
251 | flush_data_cache_local: | ||
252 | .proc | ||
253 | .callinfo NO_CALLS | ||
254 | .entry | ||
255 | |||
256 | mtsp %r0, %sr1 | ||
257 | ldil L%cache_info, %r1 | ||
258 | ldo R%cache_info(%r1), %r1 | ||
259 | |||
260 | /* Flush Data Cache */ | ||
261 | |||
262 | LDREG DCACHE_BASE(%r1), %arg0 | ||
263 | LDREG DCACHE_STRIDE(%r1), %arg1 | ||
264 | LDREG DCACHE_COUNT(%r1), %arg2 | ||
265 | LDREG DCACHE_LOOP(%r1), %arg3 | ||
266 | rsm PSW_SM_I, %r22 | ||
267 | ADDIB= -1, %arg3, fdoneloop /* Preadjust and test */ | ||
268 | movb,<,n %arg3, %r31, fdsync /* If loop < 0, do sync */ | ||
269 | |||
270 | fdmanyloop: /* Loop if LOOP >= 2 */ | ||
271 | ADDIB> -1, %r31, fdmanyloop /* Adjusted inner loop decr */ | ||
272 | fdce 0(%sr1, %arg0) | ||
273 | fdce,m %arg1(%sr1, %arg0) /* Last fdce and addr adjust */ | ||
274 | movb,tr %arg3, %r31, fdmanyloop /* Re-init inner loop count */ | ||
275 | ADDIB<=,n -1, %arg2, fdsync /* Outer loop decr */ | ||
276 | |||
277 | fdoneloop: /* Loop if LOOP = 1 */ | ||
278 | ADDIB> -1, %arg2, fdoneloop /* Outer loop count decr */ | ||
279 | fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */ | ||
280 | |||
281 | fdsync: | ||
282 | syncdma | ||
283 | sync | ||
284 | mtsm %r22 | ||
285 | bv %r0(%r2) | ||
286 | nop | ||
287 | .exit | ||
288 | |||
289 | .procend | ||
290 | |||
291 | .export copy_user_page_asm,code | ||
292 | .align 16 | ||
293 | |||
294 | copy_user_page_asm: | ||
295 | .proc | ||
296 | .callinfo NO_CALLS | ||
297 | .entry | ||
298 | |||
299 | #ifdef __LP64__ | ||
300 | /* PA8x00 CPUs can consume 2 loads or 1 store per cycle. | ||
301 | * Unroll the loop by hand and arrange insn appropriately. | ||
302 | * GCC probably can do this just as well. | ||
303 | */ | ||
304 | |||
305 | ldd 0(%r25), %r19 | ||
306 | ldi 32, %r1 /* PAGE_SIZE/128 == 32 */ | ||
307 | ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */ | ||
308 | ldw 128(%r25), %r0 /* prefetch 2 */ | ||
309 | |||
310 | 1: ldd 8(%r25), %r20 | ||
311 | ldw 192(%r25), %r0 /* prefetch 3 */ | ||
312 | ldw 256(%r25), %r0 /* prefetch 4 */ | ||
313 | |||
314 | ldd 16(%r25), %r21 | ||
315 | ldd 24(%r25), %r22 | ||
316 | std %r19, 0(%r26) | ||
317 | std %r20, 8(%r26) | ||
318 | |||
319 | ldd 32(%r25), %r19 | ||
320 | ldd 40(%r25), %r20 | ||
321 | std %r21, 16(%r26) | ||
322 | std %r22, 24(%r26) | ||
323 | |||
324 | ldd 48(%r25), %r21 | ||
325 | ldd 56(%r25), %r22 | ||
326 | std %r19, 32(%r26) | ||
327 | std %r20, 40(%r26) | ||
328 | |||
329 | ldd 64(%r25), %r19 | ||
330 | ldd 72(%r25), %r20 | ||
331 | std %r21, 48(%r26) | ||
332 | std %r22, 56(%r26) | ||
333 | |||
334 | ldd 80(%r25), %r21 | ||
335 | ldd 88(%r25), %r22 | ||
336 | std %r19, 64(%r26) | ||
337 | std %r20, 72(%r26) | ||
338 | |||
339 | ldd 96(%r25), %r19 | ||
340 | ldd 104(%r25), %r20 | ||
341 | std %r21, 80(%r26) | ||
342 | std %r22, 88(%r26) | ||
343 | |||
344 | ldd 112(%r25), %r21 | ||
345 | ldd 120(%r25), %r22 | ||
346 | std %r19, 96(%r26) | ||
347 | std %r20, 104(%r26) | ||
348 | |||
349 | ldo 128(%r25), %r25 | ||
350 | std %r21, 112(%r26) | ||
351 | std %r22, 120(%r26) | ||
352 | ldo 128(%r26), %r26 | ||
353 | |||
354 | ADDIB> -1, %r1, 1b /* bundle 10 */ | ||
355 | ldd 0(%r25), %r19 /* start next loads */ | ||
356 | |||
357 | #else | ||
358 | |||
359 | /* | ||
360 | * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw | ||
361 | * bundles (very restricted rules for bundling). | ||
362 | * Note that until (if) we start saving | ||
363 | * the full 64 bit register values on interrupt, we can't | ||
364 | * use ldd/std on a 32 bit kernel. | ||
365 | */ | ||
366 | ldi 64, %r1 /* PAGE_SIZE/64 == 64 */ | ||
367 | |||
368 | 1: | ||
369 | ldw 0(%r25), %r19 | ||
370 | ldw 4(%r25), %r20 | ||
371 | ldw 8(%r25), %r21 | ||
372 | ldw 12(%r25), %r22 | ||
373 | stw %r19, 0(%r26) | ||
374 | stw %r20, 4(%r26) | ||
375 | stw %r21, 8(%r26) | ||
376 | stw %r22, 12(%r26) | ||
377 | ldw 16(%r25), %r19 | ||
378 | ldw 20(%r25), %r20 | ||
379 | ldw 24(%r25), %r21 | ||
380 | ldw 28(%r25), %r22 | ||
381 | stw %r19, 16(%r26) | ||
382 | stw %r20, 20(%r26) | ||
383 | stw %r21, 24(%r26) | ||
384 | stw %r22, 28(%r26) | ||
385 | ldw 32(%r25), %r19 | ||
386 | ldw 36(%r25), %r20 | ||
387 | ldw 40(%r25), %r21 | ||
388 | ldw 44(%r25), %r22 | ||
389 | stw %r19, 32(%r26) | ||
390 | stw %r20, 36(%r26) | ||
391 | stw %r21, 40(%r26) | ||
392 | stw %r22, 44(%r26) | ||
393 | ldw 48(%r25), %r19 | ||
394 | ldw 52(%r25), %r20 | ||
395 | ldw 56(%r25), %r21 | ||
396 | ldw 60(%r25), %r22 | ||
397 | stw %r19, 48(%r26) | ||
398 | stw %r20, 52(%r26) | ||
399 | stw %r21, 56(%r26) | ||
400 | stw %r22, 60(%r26) | ||
401 | ldo 64(%r26), %r26 | ||
402 | ADDIB> -1, %r1, 1b | ||
403 | ldo 64(%r25), %r25 | ||
404 | #endif | ||
405 | bv %r0(%r2) | ||
406 | nop | ||
407 | .exit | ||
408 | |||
409 | .procend | ||
410 | |||
411 | /* | ||
412 | * NOTE: Code in clear_user_page has a hard coded dependency on the | ||
413 | * maximum alias boundary being 4 Mb. We've been assured by the | ||
414 | * parisc chip designers that there will not ever be a parisc | ||
415 | * chip with a larger alias boundary (Never say never :-) ). | ||
416 | * | ||
417 | * Subtle: the dtlb miss handlers support the temp alias region by | ||
418 | * "knowing" that if a dtlb miss happens within the temp alias | ||
419 | * region it must have occurred while in clear_user_page. Since | ||
420 | * this routine makes use of processor local translations, we | ||
421 | * don't want to insert them into the kernel page table. Instead, | ||
422 | * we load up some general registers (they need to be registers | ||
423 | * which aren't shadowed) with the physical page numbers (preshifted | ||
424 | * for tlb insertion) needed to insert the translations. When we | ||
425 | * miss on the translation, the dtlb miss handler inserts the | ||
426 | * translation into the tlb using these values: | ||
427 | * | ||
428 | * %r26 physical page (shifted for tlb insert) of "to" translation | ||
429 | * %r23 physical page (shifted for tlb insert) of "from" translation | ||
430 | */ | ||
431 | |||
432 | #if 0 | ||
433 | |||
434 | /* | ||
435 | * We can't do this since copy_user_page is used to bring in | ||
436 | * file data that might have instructions. Since the data would | ||
437 | * then need to be flushed out so the i-fetch can see it, it | ||
438 | * makes more sense to just copy through the kernel translation | ||
439 | * and flush it. | ||
440 | * | ||
441 | * I'm still keeping this around because it may be possible to | ||
442 | * use it if more information is passed into copy_user_page(). | ||
443 | * Have to do some measurements to see if it is worthwhile to | ||
444 | * lobby for such a change. | ||
445 | */ | ||
446 | |||
447 | .export copy_user_page_asm,code | ||
448 | |||
449 | copy_user_page_asm: | ||
450 | .proc | ||
451 | .callinfo NO_CALLS | ||
452 | .entry | ||
453 | |||
454 | ldil L%(__PAGE_OFFSET), %r1 | ||
455 | sub %r26, %r1, %r26 | ||
456 | sub %r25, %r1, %r23 /* move physical addr into non shadowed reg */ | ||
457 | |||
458 | ldil L%(TMPALIAS_MAP_START), %r28 | ||
459 | #ifdef __LP64__ | ||
460 | extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */ | ||
461 | extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */ | ||
462 | depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */ | ||
463 | depdi 0, 63,12, %r28 /* Clear any offset bits */ | ||
464 | copy %r28, %r29 | ||
465 | depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */ | ||
466 | #else | ||
467 | extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ | ||
468 | extrw,u %r23, 24,25, %r23 /* convert phys addr to tlb insert format */ | ||
469 | depw %r24, 31,22, %r28 /* Form aliased virtual address 'to' */ | ||
470 | depwi 0, 31,12, %r28 /* Clear any offset bits */ | ||
471 | copy %r28, %r29 | ||
472 | depwi 1, 9,1, %r29 /* Form aliased virtual address 'from' */ | ||
473 | #endif | ||
474 | |||
475 | /* Purge any old translations */ | ||
476 | |||
477 | pdtlb 0(%r28) | ||
478 | pdtlb 0(%r29) | ||
479 | |||
480 | ldi 64, %r1 | ||
481 | |||
482 | /* | ||
483 | * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw | ||
484 | * bundles (very restricted rules for bundling). It probably | ||
485 | * does OK on PCXU and better, but we could do better with | ||
486 | * ldd/std instructions. Note that until (if) we start saving | ||
487 | * the full 64 bit register values on interrupt, we can't | ||
488 | * use ldd/std on a 32 bit kernel. | ||
489 | */ | ||
490 | |||
491 | |||
492 | 1: | ||
493 | ldw 0(%r29), %r19 | ||
494 | ldw 4(%r29), %r20 | ||
495 | ldw 8(%r29), %r21 | ||
496 | ldw 12(%r29), %r22 | ||
497 | stw %r19, 0(%r28) | ||
498 | stw %r20, 4(%r28) | ||
499 | stw %r21, 8(%r28) | ||
500 | stw %r22, 12(%r28) | ||
501 | ldw 16(%r29), %r19 | ||
502 | ldw 20(%r29), %r20 | ||
503 | ldw 24(%r29), %r21 | ||
504 | ldw 28(%r29), %r22 | ||
505 | stw %r19, 16(%r28) | ||
506 | stw %r20, 20(%r28) | ||
507 | stw %r21, 24(%r28) | ||
508 | stw %r22, 28(%r28) | ||
509 | ldw 32(%r29), %r19 | ||
510 | ldw 36(%r29), %r20 | ||
511 | ldw 40(%r29), %r21 | ||
512 | ldw 44(%r29), %r22 | ||
513 | stw %r19, 32(%r28) | ||
514 | stw %r20, 36(%r28) | ||
515 | stw %r21, 40(%r28) | ||
516 | stw %r22, 44(%r28) | ||
517 | ldw 48(%r29), %r19 | ||
518 | ldw 52(%r29), %r20 | ||
519 | ldw 56(%r29), %r21 | ||
520 | ldw 60(%r29), %r22 | ||
521 | stw %r19, 48(%r28) | ||
522 | stw %r20, 52(%r28) | ||
523 | stw %r21, 56(%r28) | ||
524 | stw %r22, 60(%r28) | ||
525 | ldo 64(%r28), %r28 | ||
526 | ADDIB> -1, %r1,1b | ||
527 | ldo 64(%r29), %r29 | ||
528 | |||
529 | bv %r0(%r2) | ||
530 | nop | ||
531 | .exit | ||
532 | |||
533 | .procend | ||
534 | #endif | ||
535 | |||
536 | .export __clear_user_page_asm,code | ||
537 | |||
538 | __clear_user_page_asm: | ||
539 | .proc | ||
540 | .callinfo NO_CALLS | ||
541 | .entry | ||
542 | |||
543 | tophys_r1 %r26 | ||
544 | |||
545 | ldil L%(TMPALIAS_MAP_START), %r28 | ||
546 | #ifdef __LP64__ | ||
547 | #if (TMPALIAS_MAP_START >= 0x80000000) | ||
548 | depdi 0, 31,32, %r28 /* clear any sign extension */ | ||
549 | #endif | ||
550 | extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ | ||
551 | depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ | ||
552 | depdi 0, 63,12, %r28 /* Clear any offset bits */ | ||
553 | #else | ||
554 | extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ | ||
555 | depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ | ||
556 | depwi 0, 31,12, %r28 /* Clear any offset bits */ | ||
557 | #endif | ||
558 | |||
559 | /* Purge any old translation */ | ||
560 | |||
561 | pdtlb 0(%r28) | ||
562 | |||
563 | #ifdef __LP64__ | ||
564 | ldi 32, %r1 /* PAGE_SIZE/128 == 32 */ | ||
565 | |||
566 | /* PREFETCH (Write) has not (yet) been proven to help here */ | ||
567 | /* #define PREFETCHW_OP ldd 256(%0), %r0 */ | ||
568 | |||
569 | 1: std %r0, 0(%r28) | ||
570 | std %r0, 8(%r28) | ||
571 | std %r0, 16(%r28) | ||
572 | std %r0, 24(%r28) | ||
573 | std %r0, 32(%r28) | ||
574 | std %r0, 40(%r28) | ||
575 | std %r0, 48(%r28) | ||
576 | std %r0, 56(%r28) | ||
577 | std %r0, 64(%r28) | ||
578 | std %r0, 72(%r28) | ||
579 | std %r0, 80(%r28) | ||
580 | std %r0, 88(%r28) | ||
581 | std %r0, 96(%r28) | ||
582 | std %r0, 104(%r28) | ||
583 | std %r0, 112(%r28) | ||
584 | std %r0, 120(%r28) | ||
585 | ADDIB> -1, %r1, 1b | ||
586 | ldo 128(%r28), %r28 | ||
587 | |||
588 | #else /* ! __LP64 */ | ||
589 | |||
590 | ldi 64, %r1 /* PAGE_SIZE/64 == 64 */ | ||
591 | |||
592 | 1: | ||
593 | stw %r0, 0(%r28) | ||
594 | stw %r0, 4(%r28) | ||
595 | stw %r0, 8(%r28) | ||
596 | stw %r0, 12(%r28) | ||
597 | stw %r0, 16(%r28) | ||
598 | stw %r0, 20(%r28) | ||
599 | stw %r0, 24(%r28) | ||
600 | stw %r0, 28(%r28) | ||
601 | stw %r0, 32(%r28) | ||
602 | stw %r0, 36(%r28) | ||
603 | stw %r0, 40(%r28) | ||
604 | stw %r0, 44(%r28) | ||
605 | stw %r0, 48(%r28) | ||
606 | stw %r0, 52(%r28) | ||
607 | stw %r0, 56(%r28) | ||
608 | stw %r0, 60(%r28) | ||
609 | ADDIB> -1, %r1, 1b | ||
610 | ldo 64(%r28), %r28 | ||
611 | #endif /* __LP64 */ | ||
612 | |||
613 | bv %r0(%r2) | ||
614 | nop | ||
615 | .exit | ||
616 | |||
617 | .procend | ||
618 | |||
619 | .export flush_kernel_dcache_page | ||
620 | |||
621 | flush_kernel_dcache_page: | ||
622 | .proc | ||
623 | .callinfo NO_CALLS | ||
624 | .entry | ||
625 | |||
626 | ldil L%dcache_stride, %r1 | ||
627 | ldw R%dcache_stride(%r1), %r23 | ||
628 | |||
629 | #ifdef __LP64__ | ||
630 | depdi,z 1, 63-PAGE_SHIFT,1, %r25 | ||
631 | #else | ||
632 | depwi,z 1, 31-PAGE_SHIFT,1, %r25 | ||
633 | #endif | ||
634 | add %r26, %r25, %r25 | ||
635 | sub %r25, %r23, %r25 | ||
636 | |||
637 | |||
638 | 1: fdc,m %r23(%r26) | ||
639 | fdc,m %r23(%r26) | ||
640 | fdc,m %r23(%r26) | ||
641 | fdc,m %r23(%r26) | ||
642 | fdc,m %r23(%r26) | ||
643 | fdc,m %r23(%r26) | ||
644 | fdc,m %r23(%r26) | ||
645 | fdc,m %r23(%r26) | ||
646 | fdc,m %r23(%r26) | ||
647 | fdc,m %r23(%r26) | ||
648 | fdc,m %r23(%r26) | ||
649 | fdc,m %r23(%r26) | ||
650 | fdc,m %r23(%r26) | ||
651 | fdc,m %r23(%r26) | ||
652 | fdc,m %r23(%r26) | ||
653 | CMPB<< %r26, %r25,1b | ||
654 | fdc,m %r23(%r26) | ||
655 | |||
656 | sync | ||
657 | bv %r0(%r2) | ||
658 | nop | ||
659 | .exit | ||
660 | |||
661 | .procend | ||
662 | |||
663 | .export flush_user_dcache_page | ||
664 | |||
665 | flush_user_dcache_page: | ||
666 | .proc | ||
667 | .callinfo NO_CALLS | ||
668 | .entry | ||
669 | |||
670 | ldil L%dcache_stride, %r1 | ||
671 | ldw R%dcache_stride(%r1), %r23 | ||
672 | |||
673 | #ifdef __LP64__ | ||
674 | depdi,z 1,63-PAGE_SHIFT,1, %r25 | ||
675 | #else | ||
676 | depwi,z 1,31-PAGE_SHIFT,1, %r25 | ||
677 | #endif | ||
678 | add %r26, %r25, %r25 | ||
679 | sub %r25, %r23, %r25 | ||
680 | |||
681 | |||
682 | 1: fdc,m %r23(%sr3, %r26) | ||
683 | fdc,m %r23(%sr3, %r26) | ||
684 | fdc,m %r23(%sr3, %r26) | ||
685 | fdc,m %r23(%sr3, %r26) | ||
686 | fdc,m %r23(%sr3, %r26) | ||
687 | fdc,m %r23(%sr3, %r26) | ||
688 | fdc,m %r23(%sr3, %r26) | ||
689 | fdc,m %r23(%sr3, %r26) | ||
690 | fdc,m %r23(%sr3, %r26) | ||
691 | fdc,m %r23(%sr3, %r26) | ||
692 | fdc,m %r23(%sr3, %r26) | ||
693 | fdc,m %r23(%sr3, %r26) | ||
694 | fdc,m %r23(%sr3, %r26) | ||
695 | fdc,m %r23(%sr3, %r26) | ||
696 | fdc,m %r23(%sr3, %r26) | ||
697 | CMPB<< %r26, %r25,1b | ||
698 | fdc,m %r23(%sr3, %r26) | ||
699 | |||
700 | sync | ||
701 | bv %r0(%r2) | ||
702 | nop | ||
703 | .exit | ||
704 | |||
705 | .procend | ||
706 | |||
707 | .export flush_user_icache_page | ||
708 | |||
709 | flush_user_icache_page: | ||
710 | .proc | ||
711 | .callinfo NO_CALLS | ||
712 | .entry | ||
713 | |||
714 | ldil L%dcache_stride, %r1 | ||
715 | ldw R%dcache_stride(%r1), %r23 | ||
716 | |||
717 | #ifdef __LP64__ | ||
718 | depdi,z 1, 63-PAGE_SHIFT,1, %r25 | ||
719 | #else | ||
720 | depwi,z 1, 31-PAGE_SHIFT,1, %r25 | ||
721 | #endif | ||
722 | add %r26, %r25, %r25 | ||
723 | sub %r25, %r23, %r25 | ||
724 | |||
725 | |||
726 | 1: fic,m %r23(%sr3, %r26) | ||
727 | fic,m %r23(%sr3, %r26) | ||
728 | fic,m %r23(%sr3, %r26) | ||
729 | fic,m %r23(%sr3, %r26) | ||
730 | fic,m %r23(%sr3, %r26) | ||
731 | fic,m %r23(%sr3, %r26) | ||
732 | fic,m %r23(%sr3, %r26) | ||
733 | fic,m %r23(%sr3, %r26) | ||
734 | fic,m %r23(%sr3, %r26) | ||
735 | fic,m %r23(%sr3, %r26) | ||
736 | fic,m %r23(%sr3, %r26) | ||
737 | fic,m %r23(%sr3, %r26) | ||
738 | fic,m %r23(%sr3, %r26) | ||
739 | fic,m %r23(%sr3, %r26) | ||
740 | fic,m %r23(%sr3, %r26) | ||
741 | CMPB<< %r26, %r25,1b | ||
742 | fic,m %r23(%sr3, %r26) | ||
743 | |||
744 | sync | ||
745 | bv %r0(%r2) | ||
746 | nop | ||
747 | .exit | ||
748 | |||
749 | .procend | ||
750 | |||
751 | |||
752 | .export purge_kernel_dcache_page | ||
753 | |||
754 | purge_kernel_dcache_page: | ||
755 | .proc | ||
756 | .callinfo NO_CALLS | ||
757 | .entry | ||
758 | |||
759 | ldil L%dcache_stride, %r1 | ||
760 | ldw R%dcache_stride(%r1), %r23 | ||
761 | |||
762 | #ifdef __LP64__ | ||
763 | depdi,z 1, 63-PAGE_SHIFT,1, %r25 | ||
764 | #else | ||
765 | depwi,z 1, 31-PAGE_SHIFT,1, %r25 | ||
766 | #endif | ||
767 | add %r26, %r25, %r25 | ||
768 | sub %r25, %r23, %r25 | ||
769 | |||
770 | 1: pdc,m %r23(%r26) | ||
771 | pdc,m %r23(%r26) | ||
772 | pdc,m %r23(%r26) | ||
773 | pdc,m %r23(%r26) | ||
774 | pdc,m %r23(%r26) | ||
775 | pdc,m %r23(%r26) | ||
776 | pdc,m %r23(%r26) | ||
777 | pdc,m %r23(%r26) | ||
778 | pdc,m %r23(%r26) | ||
779 | pdc,m %r23(%r26) | ||
780 | pdc,m %r23(%r26) | ||
781 | pdc,m %r23(%r26) | ||
782 | pdc,m %r23(%r26) | ||
783 | pdc,m %r23(%r26) | ||
784 | pdc,m %r23(%r26) | ||
785 | CMPB<< %r26, %r25, 1b | ||
786 | pdc,m %r23(%r26) | ||
787 | |||
788 | sync | ||
789 | bv %r0(%r2) | ||
790 | nop | ||
791 | .exit | ||
792 | |||
793 | .procend | ||
794 | |||
795 | #if 0 | ||
796 | /* Currently not used, but it still is a possible alternate | ||
797 | * solution. | ||
798 | */ | ||
799 | |||
800 | .export flush_alias_page | ||
801 | |||
802 | flush_alias_page: | ||
803 | .proc | ||
804 | .callinfo NO_CALLS | ||
805 | .entry | ||
806 | |||
807 | tophys_r1 %r26 | ||
808 | |||
809 | ldil L%(TMPALIAS_MAP_START), %r28 | ||
810 | #ifdef __LP64__ | ||
811 | extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ | ||
812 | depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ | ||
813 | depdi 0, 63,12, %r28 /* Clear any offset bits */ | ||
814 | #else | ||
815 | extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ | ||
816 | depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ | ||
817 | depwi 0, 31,12, %r28 /* Clear any offset bits */ | ||
818 | #endif | ||
819 | |||
820 | /* Purge any old translation */ | ||
821 | |||
822 | pdtlb 0(%r28) | ||
823 | |||
824 | ldil L%dcache_stride, %r1 | ||
825 | ldw R%dcache_stride(%r1), %r23 | ||
826 | |||
827 | #ifdef __LP64__ | ||
828 | depdi,z 1, 63-PAGE_SHIFT,1, %r29 | ||
829 | #else | ||
830 | depwi,z 1, 31-PAGE_SHIFT,1, %r29 | ||
831 | #endif | ||
832 | add %r28, %r29, %r29 | ||
833 | sub %r29, %r23, %r29 | ||
834 | |||
835 | 1: fdc,m %r23(%r28) | ||
836 | fdc,m %r23(%r28) | ||
837 | fdc,m %r23(%r28) | ||
838 | fdc,m %r23(%r28) | ||
839 | fdc,m %r23(%r28) | ||
840 | fdc,m %r23(%r28) | ||
841 | fdc,m %r23(%r28) | ||
842 | fdc,m %r23(%r28) | ||
843 | fdc,m %r23(%r28) | ||
844 | fdc,m %r23(%r28) | ||
845 | fdc,m %r23(%r28) | ||
846 | fdc,m %r23(%r28) | ||
847 | fdc,m %r23(%r28) | ||
848 | fdc,m %r23(%r28) | ||
849 | fdc,m %r23(%r28) | ||
850 | CMPB<< %r28, %r29, 1b | ||
851 | fdc,m %r23(%r28) | ||
852 | |||
853 | sync | ||
854 | bv %r0(%r2) | ||
855 | nop | ||
856 | .exit | ||
857 | |||
858 | .procend | ||
859 | #endif | ||
860 | |||
861 | .export flush_user_dcache_range_asm | ||
862 | |||
863 | flush_user_dcache_range_asm: | ||
864 | .proc | ||
865 | .callinfo NO_CALLS | ||
866 | .entry | ||
867 | |||
868 | ldil L%dcache_stride, %r1 | ||
869 | ldw R%dcache_stride(%r1), %r23 | ||
870 | ldo -1(%r23), %r21 | ||
871 | ANDCM %r26, %r21, %r26 | ||
872 | |||
873 | 1: CMPB<<,n %r26, %r25, 1b | ||
874 | fdc,m %r23(%sr3, %r26) | ||
875 | |||
876 | sync | ||
877 | bv %r0(%r2) | ||
878 | nop | ||
879 | .exit | ||
880 | |||
881 | .procend | ||
882 | |||
883 | .export flush_kernel_dcache_range_asm | ||
884 | |||
885 | flush_kernel_dcache_range_asm: | ||
886 | .proc | ||
887 | .callinfo NO_CALLS | ||
888 | .entry | ||
889 | |||
890 | ldil L%dcache_stride, %r1 | ||
891 | ldw R%dcache_stride(%r1), %r23 | ||
892 | ldo -1(%r23), %r21 | ||
893 | ANDCM %r26, %r21, %r26 | ||
894 | |||
895 | 1: CMPB<<,n %r26, %r25,1b | ||
896 | fdc,m %r23(%r26) | ||
897 | |||
898 | sync | ||
899 | syncdma | ||
900 | bv %r0(%r2) | ||
901 | nop | ||
902 | .exit | ||
903 | |||
904 | .procend | ||
905 | |||
906 | .export flush_user_icache_range_asm | ||
907 | |||
908 | flush_user_icache_range_asm: | ||
909 | .proc | ||
910 | .callinfo NO_CALLS | ||
911 | .entry | ||
912 | |||
913 | ldil L%icache_stride, %r1 | ||
914 | ldw R%icache_stride(%r1), %r23 | ||
915 | ldo -1(%r23), %r21 | ||
916 | ANDCM %r26, %r21, %r26 | ||
917 | |||
918 | 1: CMPB<<,n %r26, %r25,1b | ||
919 | fic,m %r23(%sr3, %r26) | ||
920 | |||
921 | sync | ||
922 | bv %r0(%r2) | ||
923 | nop | ||
924 | .exit | ||
925 | |||
926 | .procend | ||
927 | |||
928 | .export flush_kernel_icache_page | ||
929 | |||
930 | flush_kernel_icache_page: | ||
931 | .proc | ||
932 | .callinfo NO_CALLS | ||
933 | .entry | ||
934 | |||
935 | ldil L%icache_stride, %r1 | ||
936 | ldw R%icache_stride(%r1), %r23 | ||
937 | |||
938 | #ifdef __LP64__ | ||
939 | depdi,z 1, 63-PAGE_SHIFT,1, %r25 | ||
940 | #else | ||
941 | depwi,z 1, 31-PAGE_SHIFT,1, %r25 | ||
942 | #endif | ||
943 | add %r26, %r25, %r25 | ||
944 | sub %r25, %r23, %r25 | ||
945 | |||
946 | |||
947 | 1: fic,m %r23(%r26) | ||
948 | fic,m %r23(%r26) | ||
949 | fic,m %r23(%r26) | ||
950 | fic,m %r23(%r26) | ||
951 | fic,m %r23(%r26) | ||
952 | fic,m %r23(%r26) | ||
953 | fic,m %r23(%r26) | ||
954 | fic,m %r23(%r26) | ||
955 | fic,m %r23(%r26) | ||
956 | fic,m %r23(%r26) | ||
957 | fic,m %r23(%r26) | ||
958 | fic,m %r23(%r26) | ||
959 | fic,m %r23(%r26) | ||
960 | fic,m %r23(%r26) | ||
961 | fic,m %r23(%r26) | ||
962 | CMPB<< %r26, %r25, 1b | ||
963 | fic,m %r23(%r26) | ||
964 | |||
965 | sync | ||
966 | bv %r0(%r2) | ||
967 | nop | ||
968 | .exit | ||
969 | |||
970 | .procend | ||
971 | |||
972 | .export flush_kernel_icache_range_asm | ||
973 | |||
974 | flush_kernel_icache_range_asm: | ||
975 | .proc | ||
976 | .callinfo NO_CALLS | ||
977 | .entry | ||
978 | |||
979 | ldil L%icache_stride, %r1 | ||
980 | ldw R%icache_stride(%r1), %r23 | ||
981 | ldo -1(%r23), %r21 | ||
982 | ANDCM %r26, %r21, %r26 | ||
983 | |||
984 | 1: CMPB<<,n %r26, %r25, 1b | ||
985 | fic,m %r23(%r26) | ||
986 | |||
987 | sync | ||
988 | bv %r0(%r2) | ||
989 | nop | ||
990 | .exit | ||
991 | |||
992 | .procend | ||
993 | |||
994 | .align 128 | ||
995 | |||
996 | .export disable_sr_hashing_asm,code | ||
997 | |||
998 | disable_sr_hashing_asm: | ||
999 | .proc | ||
1000 | .callinfo NO_CALLS | ||
1001 | .entry | ||
1002 | |||
1003 | /* Switch to real mode */ | ||
1004 | |||
1005 | ssm 0, %r0 /* relied upon translation! */ | ||
1006 | nop | ||
1007 | nop | ||
1008 | nop | ||
1009 | nop | ||
1010 | nop | ||
1011 | nop | ||
1012 | nop | ||
1013 | |||
1014 | rsm (PSW_SM_Q|PSW_SM_I), %r0 /* disable Q&I to load the iia queue */ | ||
1015 | ldil L%REAL_MODE_PSW, %r1 | ||
1016 | ldo R%REAL_MODE_PSW(%r1), %r1 | ||
1017 | mtctl %r1, %cr22 | ||
1018 | mtctl %r0, %cr17 /* Clear IIASQ tail */ | ||
1019 | mtctl %r0, %cr17 /* Clear IIASQ head */ | ||
1020 | ldil L%PA(1f), %r1 | ||
1021 | ldo R%PA(1f)(%r1), %r1 | ||
1022 | mtctl %r1, %cr18 /* IIAOQ head */ | ||
1023 | ldo 4(%r1), %r1 | ||
1024 | mtctl %r1, %cr18 /* IIAOQ tail */ | ||
1025 | rfi | ||
1026 | nop | ||
1027 | |||
1028 | 1: cmpib,=,n SRHASH_PCXST, %r26,srdis_pcxs | ||
1029 | cmpib,=,n SRHASH_PCXL, %r26,srdis_pcxl | ||
1030 | cmpib,=,n SRHASH_PA20, %r26,srdis_pa20 | ||
1031 | b,n srdis_done | ||
1032 | |||
1033 | srdis_pcxs: | ||
1034 | |||
1035 | /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */ | ||
1036 | |||
1037 | .word 0x141c1a00 /* mfdiag %dr0, %r28 */ | ||
1038 | .word 0x141c1a00 /* must issue twice */ | ||
1039 | depwi 0,18,1, %r28 /* Clear DHE (dcache hash enable) */ | ||
1040 | depwi 0,20,1, %r28 /* Clear IHE (icache hash enable) */ | ||
1041 | .word 0x141c1600 /* mtdiag %r28, %dr0 */ | ||
1042 | .word 0x141c1600 /* must issue twice */ | ||
1043 | b,n srdis_done | ||
1044 | |||
1045 | srdis_pcxl: | ||
1046 | |||
1047 | /* Disable Space Register Hashing for PCXL */ | ||
1048 | |||
1049 | .word 0x141c0600 /* mfdiag %dr0, %r28 */ | ||
1050 | depwi 0,28,2, %r28 /* Clear DHASH_EN & IHASH_EN */ | ||
1051 | .word 0x141c0240 /* mtdiag %r28, %dr0 */ | ||
1052 | b,n srdis_done | ||
1053 | |||
1054 | srdis_pa20: | ||
1055 | |||
1056 | /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */ | ||
1057 | |||
1058 | .word 0x144008bc /* mfdiag %dr2, %r28 */ | ||
1059 | depdi 0, 54,1, %r28 /* clear DIAG_SPHASH_ENAB (bit 54) */ | ||
1060 | .word 0x145c1840 /* mtdiag %r28, %dr2 */ | ||
1061 | |||
1062 | srdis_done: | ||
1063 | |||
1064 | /* Switch back to virtual mode */ | ||
1065 | |||
1066 | rsm PSW_SM_Q, %r0 /* clear Q bit to load iia queue */ | ||
1067 | ldil L%KERNEL_PSW, %r1 | ||
1068 | ldo R%KERNEL_PSW(%r1), %r1 | ||
1069 | mtctl %r1, %cr22 | ||
1070 | mtctl %r0, %cr17 /* Clear IIASQ tail */ | ||
1071 | mtctl %r0, %cr17 /* Clear IIASQ head */ | ||
1072 | ldil L%(2f), %r1 | ||
1073 | ldo R%(2f)(%r1), %r1 | ||
1074 | mtctl %r1, %cr18 /* IIAOQ head */ | ||
1075 | ldo 4(%r1), %r1 | ||
1076 | mtctl %r1, %cr18 /* IIAOQ tail */ | ||
1077 | rfi | ||
1078 | nop | ||
1079 | |||
1080 | 2: bv %r0(%r2) | ||
1081 | nop | ||
1082 | .exit | ||
1083 | |||
1084 | .procend | ||
1085 | |||
1086 | .end | ||
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c new file mode 100644 index 000000000000..f40a777dd388 --- /dev/null +++ b/arch/parisc/kernel/parisc_ksyms.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Architecture-specific kernel symbols | ||
3 | * | ||
4 | * Copyright (C) 2000-2001 Richard Hirst <rhirst with parisc-linux.org> | ||
5 | * Copyright (C) 2001 Dave Kennedy | ||
6 | * Copyright (C) 2001 Paul Bame <bame at parisc-linux.org> | ||
7 | * Copyright (C) 2001-2003 Grant Grundler <grundler with parisc-linux.org> | ||
8 | * Copyright (C) 2002-2003 Matthew Wilcox <willy at parisc-linux.org> | ||
9 | * Copyright (C) 2002 Randolph Chung <tausq at parisc-linux.org> | ||
10 | * Copyright (C) 2002-2003 Helge Deller <deller with parisc-linux.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/syscalls.h> | ||
31 | |||
32 | #include <linux/string.h> | ||
33 | EXPORT_SYMBOL(memchr); | ||
34 | EXPORT_SYMBOL(memcmp); | ||
35 | EXPORT_SYMBOL(memmove); | ||
36 | EXPORT_SYMBOL(memscan); | ||
37 | EXPORT_SYMBOL(memset); | ||
38 | EXPORT_SYMBOL(strcat); | ||
39 | EXPORT_SYMBOL(strchr); | ||
40 | EXPORT_SYMBOL(strcmp); | ||
41 | EXPORT_SYMBOL(strcpy); | ||
42 | EXPORT_SYMBOL(strlen); | ||
43 | EXPORT_SYMBOL(strncat); | ||
44 | EXPORT_SYMBOL(strncmp); | ||
45 | EXPORT_SYMBOL(strncpy); | ||
46 | EXPORT_SYMBOL(strnlen); | ||
47 | EXPORT_SYMBOL(strrchr); | ||
48 | EXPORT_SYMBOL(strstr); | ||
49 | EXPORT_SYMBOL(strpbrk); | ||
50 | |||
51 | #include <linux/pm.h> | ||
52 | EXPORT_SYMBOL(pm_power_off); | ||
53 | |||
54 | #include <asm/atomic.h> | ||
55 | EXPORT_SYMBOL(__xchg8); | ||
56 | EXPORT_SYMBOL(__xchg32); | ||
57 | EXPORT_SYMBOL(__cmpxchg_u32); | ||
58 | #ifdef CONFIG_SMP | ||
59 | EXPORT_SYMBOL(__atomic_hash); | ||
60 | #endif | ||
61 | #ifdef __LP64__ | ||
62 | EXPORT_SYMBOL(__xchg64); | ||
63 | EXPORT_SYMBOL(__cmpxchg_u64); | ||
64 | #endif | ||
65 | |||
66 | #include <asm/uaccess.h> | ||
67 | EXPORT_SYMBOL(lstrncpy_from_user); | ||
68 | EXPORT_SYMBOL(lclear_user); | ||
69 | EXPORT_SYMBOL(lstrnlen_user); | ||
70 | |||
71 | /* Global fixups */ | ||
72 | extern void fixup_get_user_skip_1(void); | ||
73 | extern void fixup_get_user_skip_2(void); | ||
74 | extern void fixup_put_user_skip_1(void); | ||
75 | extern void fixup_put_user_skip_2(void); | ||
76 | EXPORT_SYMBOL(fixup_get_user_skip_1); | ||
77 | EXPORT_SYMBOL(fixup_get_user_skip_2); | ||
78 | EXPORT_SYMBOL(fixup_put_user_skip_1); | ||
79 | EXPORT_SYMBOL(fixup_put_user_skip_2); | ||
80 | |||
81 | #ifndef __LP64__ | ||
82 | /* Needed so insmod can set dp value */ | ||
83 | extern int $global$; | ||
84 | EXPORT_SYMBOL($global$); | ||
85 | #endif | ||
86 | |||
87 | #include <asm/io.h> | ||
88 | EXPORT_SYMBOL(__ioremap); | ||
89 | EXPORT_SYMBOL(iounmap); | ||
90 | EXPORT_SYMBOL(memcpy_toio); | ||
91 | EXPORT_SYMBOL(memcpy_fromio); | ||
92 | EXPORT_SYMBOL(memset_io); | ||
93 | |||
94 | #include <asm/unistd.h> | ||
95 | EXPORT_SYMBOL(sys_open); | ||
96 | EXPORT_SYMBOL(sys_lseek); | ||
97 | EXPORT_SYMBOL(sys_read); | ||
98 | EXPORT_SYMBOL(sys_write); | ||
99 | |||
100 | #include <asm/semaphore.h> | ||
101 | EXPORT_SYMBOL(__up); | ||
102 | EXPORT_SYMBOL(__down_interruptible); | ||
103 | EXPORT_SYMBOL(__down); | ||
104 | |||
105 | extern void $$divI(void); | ||
106 | extern void $$divU(void); | ||
107 | extern void $$remI(void); | ||
108 | extern void $$remU(void); | ||
109 | extern void $$mulI(void); | ||
110 | extern void $$divU_3(void); | ||
111 | extern void $$divU_5(void); | ||
112 | extern void $$divU_6(void); | ||
113 | extern void $$divU_9(void); | ||
114 | extern void $$divU_10(void); | ||
115 | extern void $$divU_12(void); | ||
116 | extern void $$divU_7(void); | ||
117 | extern void $$divU_14(void); | ||
118 | extern void $$divU_15(void); | ||
119 | extern void $$divI_3(void); | ||
120 | extern void $$divI_5(void); | ||
121 | extern void $$divI_6(void); | ||
122 | extern void $$divI_7(void); | ||
123 | extern void $$divI_9(void); | ||
124 | extern void $$divI_10(void); | ||
125 | extern void $$divI_12(void); | ||
126 | extern void $$divI_14(void); | ||
127 | extern void $$divI_15(void); | ||
128 | |||
129 | EXPORT_SYMBOL($$divI); | ||
130 | EXPORT_SYMBOL($$divU); | ||
131 | EXPORT_SYMBOL($$remI); | ||
132 | EXPORT_SYMBOL($$remU); | ||
133 | EXPORT_SYMBOL($$mulI); | ||
134 | EXPORT_SYMBOL($$divU_3); | ||
135 | EXPORT_SYMBOL($$divU_5); | ||
136 | EXPORT_SYMBOL($$divU_6); | ||
137 | EXPORT_SYMBOL($$divU_9); | ||
138 | EXPORT_SYMBOL($$divU_10); | ||
139 | EXPORT_SYMBOL($$divU_12); | ||
140 | EXPORT_SYMBOL($$divU_7); | ||
141 | EXPORT_SYMBOL($$divU_14); | ||
142 | EXPORT_SYMBOL($$divU_15); | ||
143 | EXPORT_SYMBOL($$divI_3); | ||
144 | EXPORT_SYMBOL($$divI_5); | ||
145 | EXPORT_SYMBOL($$divI_6); | ||
146 | EXPORT_SYMBOL($$divI_7); | ||
147 | EXPORT_SYMBOL($$divI_9); | ||
148 | EXPORT_SYMBOL($$divI_10); | ||
149 | EXPORT_SYMBOL($$divI_12); | ||
150 | EXPORT_SYMBOL($$divI_14); | ||
151 | EXPORT_SYMBOL($$divI_15); | ||
152 | |||
153 | extern void __ashrdi3(void); | ||
154 | extern void __ashldi3(void); | ||
155 | extern void __lshrdi3(void); | ||
156 | extern void __muldi3(void); | ||
157 | |||
158 | EXPORT_SYMBOL(__ashrdi3); | ||
159 | EXPORT_SYMBOL(__ashldi3); | ||
160 | EXPORT_SYMBOL(__lshrdi3); | ||
161 | EXPORT_SYMBOL(__muldi3); | ||
162 | |||
163 | asmlinkage void * __canonicalize_funcptr_for_compare(void *); | ||
164 | EXPORT_SYMBOL(__canonicalize_funcptr_for_compare); | ||
165 | |||
166 | #ifdef __LP64__ | ||
167 | extern void __divdi3(void); | ||
168 | extern void __udivdi3(void); | ||
169 | extern void __umoddi3(void); | ||
170 | extern void __moddi3(void); | ||
171 | |||
172 | EXPORT_SYMBOL(__divdi3); | ||
173 | EXPORT_SYMBOL(__udivdi3); | ||
174 | EXPORT_SYMBOL(__umoddi3); | ||
175 | EXPORT_SYMBOL(__moddi3); | ||
176 | #endif | ||
177 | |||
178 | #ifndef __LP64__ | ||
179 | extern void $$dyncall(void); | ||
180 | EXPORT_SYMBOL($$dyncall); | ||
181 | #endif | ||
182 | |||
183 | #ifdef CONFIG_DISCONTIGMEM | ||
184 | #include <asm/mmzone.h> | ||
185 | EXPORT_SYMBOL(node_data); | ||
186 | EXPORT_SYMBOL(pfnnid_map); | ||
187 | #endif | ||
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c new file mode 100644 index 000000000000..368cc095c99f --- /dev/null +++ b/arch/parisc/kernel/pci-dma.c | |||
@@ -0,0 +1,578 @@ | |||
1 | /* | ||
2 | ** PARISC 1.1 Dynamic DMA mapping support. | ||
3 | ** This implementation is for PA-RISC platforms that do not support | ||
4 | ** I/O TLBs (aka DMA address translation hardware). | ||
5 | ** See Documentation/DMA-mapping.txt for interface definitions. | ||
6 | ** | ||
7 | ** (c) Copyright 1999,2000 Hewlett-Packard Company | ||
8 | ** (c) Copyright 2000 Grant Grundler | ||
9 | ** (c) Copyright 2000 Philipp Rumpf <prumpf@tux.org> | ||
10 | ** (c) Copyright 2000 John Marvin | ||
11 | ** | ||
12 | ** "leveraged" from 2.3.47: arch/ia64/kernel/pci-dma.c. | ||
13 | ** (I assume it's from David Mosberger-Tang but there was no Copyright) | ||
14 | ** | ||
15 | ** AFAIK, all PA7100LC and PA7300LC platforms can use this code. | ||
16 | ** | ||
17 | ** - ggg | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/proc_fs.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/types.h> | ||
27 | |||
28 | #include <asm/cacheflush.h> | ||
29 | #include <asm/dma.h> /* for DMA_CHUNK_SIZE */ | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/page.h> /* get_order */ | ||
32 | #include <asm/pgalloc.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | |||
35 | |||
36 | static struct proc_dir_entry * proc_gsc_root = NULL; | ||
37 | static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length); | ||
38 | static unsigned long pcxl_used_bytes = 0; | ||
39 | static unsigned long pcxl_used_pages = 0; | ||
40 | |||
41 | extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */ | ||
42 | static spinlock_t pcxl_res_lock; | ||
43 | static char *pcxl_res_map; | ||
44 | static int pcxl_res_hint; | ||
45 | static int pcxl_res_size; | ||
46 | |||
47 | #ifdef DEBUG_PCXL_RESOURCE | ||
48 | #define DBG_RES(x...) printk(x) | ||
49 | #else | ||
50 | #define DBG_RES(x...) | ||
51 | #endif | ||
52 | |||
53 | |||
54 | /* | ||
55 | ** Dump a hex representation of the resource map. | ||
56 | */ | ||
57 | |||
58 | #ifdef DUMP_RESMAP | ||
59 | static | ||
60 | void dump_resmap(void) | ||
61 | { | ||
62 | u_long *res_ptr = (unsigned long *)pcxl_res_map; | ||
63 | u_long i = 0; | ||
64 | |||
65 | printk("res_map: "); | ||
66 | for(; i < (pcxl_res_size / sizeof(unsigned long)); ++i, ++res_ptr) | ||
67 | printk("%08lx ", *res_ptr); | ||
68 | |||
69 | printk("\n"); | ||
70 | } | ||
71 | #else | ||
72 | static inline void dump_resmap(void) {;} | ||
73 | #endif | ||
74 | |||
75 | static int pa11_dma_supported( struct device *dev, u64 mask) | ||
76 | { | ||
77 | return 1; | ||
78 | } | ||
79 | |||
80 | static inline int map_pte_uncached(pte_t * pte, | ||
81 | unsigned long vaddr, | ||
82 | unsigned long size, unsigned long *paddr_ptr) | ||
83 | { | ||
84 | unsigned long end; | ||
85 | unsigned long orig_vaddr = vaddr; | ||
86 | |||
87 | vaddr &= ~PMD_MASK; | ||
88 | end = vaddr + size; | ||
89 | if (end > PMD_SIZE) | ||
90 | end = PMD_SIZE; | ||
91 | do { | ||
92 | if (!pte_none(*pte)) | ||
93 | printk(KERN_ERR "map_pte_uncached: page already exists\n"); | ||
94 | set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC)); | ||
95 | purge_tlb_start(); | ||
96 | pdtlb_kernel(orig_vaddr); | ||
97 | purge_tlb_end(); | ||
98 | vaddr += PAGE_SIZE; | ||
99 | orig_vaddr += PAGE_SIZE; | ||
100 | (*paddr_ptr) += PAGE_SIZE; | ||
101 | pte++; | ||
102 | } while (vaddr < end); | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static inline int map_pmd_uncached(pmd_t * pmd, unsigned long vaddr, | ||
107 | unsigned long size, unsigned long *paddr_ptr) | ||
108 | { | ||
109 | unsigned long end; | ||
110 | unsigned long orig_vaddr = vaddr; | ||
111 | |||
112 | vaddr &= ~PGDIR_MASK; | ||
113 | end = vaddr + size; | ||
114 | if (end > PGDIR_SIZE) | ||
115 | end = PGDIR_SIZE; | ||
116 | do { | ||
117 | pte_t * pte = pte_alloc_kernel(&init_mm, pmd, vaddr); | ||
118 | if (!pte) | ||
119 | return -ENOMEM; | ||
120 | if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr)) | ||
121 | return -ENOMEM; | ||
122 | vaddr = (vaddr + PMD_SIZE) & PMD_MASK; | ||
123 | orig_vaddr += PMD_SIZE; | ||
124 | pmd++; | ||
125 | } while (vaddr < end); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static inline int map_uncached_pages(unsigned long vaddr, unsigned long size, | ||
130 | unsigned long paddr) | ||
131 | { | ||
132 | pgd_t * dir; | ||
133 | unsigned long end = vaddr + size; | ||
134 | |||
135 | dir = pgd_offset_k(vaddr); | ||
136 | do { | ||
137 | pmd_t *pmd; | ||
138 | |||
139 | pmd = pmd_alloc(NULL, dir, vaddr); | ||
140 | if (!pmd) | ||
141 | return -ENOMEM; | ||
142 | if (map_pmd_uncached(pmd, vaddr, end - vaddr, &paddr)) | ||
143 | return -ENOMEM; | ||
144 | vaddr = vaddr + PGDIR_SIZE; | ||
145 | dir++; | ||
146 | } while (vaddr && (vaddr < end)); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr, | ||
151 | unsigned long size) | ||
152 | { | ||
153 | pte_t * pte; | ||
154 | unsigned long end; | ||
155 | unsigned long orig_vaddr = vaddr; | ||
156 | |||
157 | if (pmd_none(*pmd)) | ||
158 | return; | ||
159 | if (pmd_bad(*pmd)) { | ||
160 | pmd_ERROR(*pmd); | ||
161 | pmd_clear(pmd); | ||
162 | return; | ||
163 | } | ||
164 | pte = pte_offset_map(pmd, vaddr); | ||
165 | vaddr &= ~PMD_MASK; | ||
166 | end = vaddr + size; | ||
167 | if (end > PMD_SIZE) | ||
168 | end = PMD_SIZE; | ||
169 | do { | ||
170 | pte_t page = *pte; | ||
171 | pte_clear(&init_mm, vaddr, pte); | ||
172 | purge_tlb_start(); | ||
173 | pdtlb_kernel(orig_vaddr); | ||
174 | purge_tlb_end(); | ||
175 | vaddr += PAGE_SIZE; | ||
176 | orig_vaddr += PAGE_SIZE; | ||
177 | pte++; | ||
178 | if (pte_none(page) || pte_present(page)) | ||
179 | continue; | ||
180 | printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n"); | ||
181 | } while (vaddr < end); | ||
182 | } | ||
183 | |||
184 | static inline void unmap_uncached_pmd(pgd_t * dir, unsigned long vaddr, | ||
185 | unsigned long size) | ||
186 | { | ||
187 | pmd_t * pmd; | ||
188 | unsigned long end; | ||
189 | unsigned long orig_vaddr = vaddr; | ||
190 | |||
191 | if (pgd_none(*dir)) | ||
192 | return; | ||
193 | if (pgd_bad(*dir)) { | ||
194 | pgd_ERROR(*dir); | ||
195 | pgd_clear(dir); | ||
196 | return; | ||
197 | } | ||
198 | pmd = pmd_offset(dir, vaddr); | ||
199 | vaddr &= ~PGDIR_MASK; | ||
200 | end = vaddr + size; | ||
201 | if (end > PGDIR_SIZE) | ||
202 | end = PGDIR_SIZE; | ||
203 | do { | ||
204 | unmap_uncached_pte(pmd, orig_vaddr, end - vaddr); | ||
205 | vaddr = (vaddr + PMD_SIZE) & PMD_MASK; | ||
206 | orig_vaddr += PMD_SIZE; | ||
207 | pmd++; | ||
208 | } while (vaddr < end); | ||
209 | } | ||
210 | |||
211 | static void unmap_uncached_pages(unsigned long vaddr, unsigned long size) | ||
212 | { | ||
213 | pgd_t * dir; | ||
214 | unsigned long end = vaddr + size; | ||
215 | |||
216 | dir = pgd_offset_k(vaddr); | ||
217 | do { | ||
218 | unmap_uncached_pmd(dir, vaddr, end - vaddr); | ||
219 | vaddr = vaddr + PGDIR_SIZE; | ||
220 | dir++; | ||
221 | } while (vaddr && (vaddr < end)); | ||
222 | } | ||
223 | |||
224 | #define PCXL_SEARCH_LOOP(idx, mask, size) \ | ||
225 | for(; res_ptr < res_end; ++res_ptr) \ | ||
226 | { \ | ||
227 | if(0 == ((*res_ptr) & mask)) { \ | ||
228 | *res_ptr |= mask; \ | ||
229 | idx = (int)((u_long)res_ptr - (u_long)pcxl_res_map); \ | ||
230 | pcxl_res_hint = idx + (size >> 3); \ | ||
231 | goto resource_found; \ | ||
232 | } \ | ||
233 | } | ||
234 | |||
235 | #define PCXL_FIND_FREE_MAPPING(idx, mask, size) { \ | ||
236 | u##size *res_ptr = (u##size *)&(pcxl_res_map[pcxl_res_hint & ~((size >> 3) - 1)]); \ | ||
237 | u##size *res_end = (u##size *)&pcxl_res_map[pcxl_res_size]; \ | ||
238 | PCXL_SEARCH_LOOP(idx, mask, size); \ | ||
239 | res_ptr = (u##size *)&pcxl_res_map[0]; \ | ||
240 | PCXL_SEARCH_LOOP(idx, mask, size); \ | ||
241 | } | ||
242 | |||
243 | unsigned long | ||
244 | pcxl_alloc_range(size_t size) | ||
245 | { | ||
246 | int res_idx; | ||
247 | u_long mask, flags; | ||
248 | unsigned int pages_needed = size >> PAGE_SHIFT; | ||
249 | |||
250 | mask = (u_long) -1L; | ||
251 | mask >>= BITS_PER_LONG - pages_needed; | ||
252 | |||
253 | DBG_RES("pcxl_alloc_range() size: %d pages_needed %d pages_mask 0x%08lx\n", | ||
254 | size, pages_needed, mask); | ||
255 | |||
256 | spin_lock_irqsave(&pcxl_res_lock, flags); | ||
257 | |||
258 | if(pages_needed <= 8) { | ||
259 | PCXL_FIND_FREE_MAPPING(res_idx, mask, 8); | ||
260 | } else if(pages_needed <= 16) { | ||
261 | PCXL_FIND_FREE_MAPPING(res_idx, mask, 16); | ||
262 | } else if(pages_needed <= 32) { | ||
263 | PCXL_FIND_FREE_MAPPING(res_idx, mask, 32); | ||
264 | } else { | ||
265 | panic("%s: pcxl_alloc_range() Too many pages to map.\n", | ||
266 | __FILE__); | ||
267 | } | ||
268 | |||
269 | dump_resmap(); | ||
270 | panic("%s: pcxl_alloc_range() out of dma mapping resources\n", | ||
271 | __FILE__); | ||
272 | |||
273 | resource_found: | ||
274 | |||
275 | DBG_RES("pcxl_alloc_range() res_idx %d mask 0x%08lx res_hint: %d\n", | ||
276 | res_idx, mask, pcxl_res_hint); | ||
277 | |||
278 | pcxl_used_pages += pages_needed; | ||
279 | pcxl_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1); | ||
280 | |||
281 | spin_unlock_irqrestore(&pcxl_res_lock, flags); | ||
282 | |||
283 | dump_resmap(); | ||
284 | |||
285 | /* | ||
286 | ** return the corresponding vaddr in the pcxl dma map | ||
287 | */ | ||
288 | return (pcxl_dma_start + (res_idx << (PAGE_SHIFT + 3))); | ||
289 | } | ||
290 | |||
291 | #define PCXL_FREE_MAPPINGS(idx, m, size) \ | ||
292 | u##size *res_ptr = (u##size *)&(pcxl_res_map[(idx) + (((size >> 3) - 1) & (~((size >> 3) - 1)))]); \ | ||
293 | /* BUG_ON((*res_ptr & m) != m); */ \ | ||
294 | *res_ptr &= ~m; | ||
295 | |||
296 | /* | ||
297 | ** clear bits in the pcxl resource map | ||
298 | */ | ||
299 | static void | ||
300 | pcxl_free_range(unsigned long vaddr, size_t size) | ||
301 | { | ||
302 | u_long mask, flags; | ||
303 | unsigned int res_idx = (vaddr - pcxl_dma_start) >> (PAGE_SHIFT + 3); | ||
304 | unsigned int pages_mapped = size >> PAGE_SHIFT; | ||
305 | |||
306 | mask = (u_long) -1L; | ||
307 | mask >>= BITS_PER_LONG - pages_mapped; | ||
308 | |||
309 | DBG_RES("pcxl_free_range() res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n", | ||
310 | res_idx, size, pages_mapped, mask); | ||
311 | |||
312 | spin_lock_irqsave(&pcxl_res_lock, flags); | ||
313 | |||
314 | if(pages_mapped <= 8) { | ||
315 | PCXL_FREE_MAPPINGS(res_idx, mask, 8); | ||
316 | } else if(pages_mapped <= 16) { | ||
317 | PCXL_FREE_MAPPINGS(res_idx, mask, 16); | ||
318 | } else if(pages_mapped <= 32) { | ||
319 | PCXL_FREE_MAPPINGS(res_idx, mask, 32); | ||
320 | } else { | ||
321 | panic("%s: pcxl_free_range() Too many pages to unmap.\n", | ||
322 | __FILE__); | ||
323 | } | ||
324 | |||
325 | pcxl_used_pages -= (pages_mapped ? pages_mapped : 1); | ||
326 | pcxl_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1); | ||
327 | |||
328 | spin_unlock_irqrestore(&pcxl_res_lock, flags); | ||
329 | |||
330 | dump_resmap(); | ||
331 | } | ||
332 | |||
333 | static int __init | ||
334 | pcxl_dma_init(void) | ||
335 | { | ||
336 | if (pcxl_dma_start == 0) | ||
337 | return 0; | ||
338 | |||
339 | spin_lock_init(&pcxl_res_lock); | ||
340 | pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3); | ||
341 | pcxl_res_hint = 0; | ||
342 | pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL, | ||
343 | get_order(pcxl_res_size)); | ||
344 | memset(pcxl_res_map, 0, pcxl_res_size); | ||
345 | proc_gsc_root = proc_mkdir("gsc", 0); | ||
346 | create_proc_info_entry("dino", 0, proc_gsc_root, pcxl_proc_info); | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | __initcall(pcxl_dma_init); | ||
351 | |||
352 | static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flag) | ||
353 | { | ||
354 | unsigned long vaddr; | ||
355 | unsigned long paddr; | ||
356 | int order; | ||
357 | |||
358 | order = get_order(size); | ||
359 | size = 1 << (order + PAGE_SHIFT); | ||
360 | vaddr = pcxl_alloc_range(size); | ||
361 | paddr = __get_free_pages(flag, order); | ||
362 | flush_kernel_dcache_range(paddr, size); | ||
363 | paddr = __pa(paddr); | ||
364 | map_uncached_pages(vaddr, size, paddr); | ||
365 | *dma_handle = (dma_addr_t) paddr; | ||
366 | |||
367 | #if 0 | ||
368 | /* This probably isn't needed to support EISA cards. | ||
369 | ** ISA cards will certainly only support 24-bit DMA addressing. | ||
370 | ** Not clear if we can, want, or need to support ISA. | ||
371 | */ | ||
372 | if (!dev || *dev->coherent_dma_mask < 0xffffffff) | ||
373 | gfp |= GFP_DMA; | ||
374 | #endif | ||
375 | return (void *)vaddr; | ||
376 | } | ||
377 | |||
378 | static void pa11_dma_free_consistent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) | ||
379 | { | ||
380 | int order; | ||
381 | |||
382 | order = get_order(size); | ||
383 | size = 1 << (order + PAGE_SHIFT); | ||
384 | unmap_uncached_pages((unsigned long)vaddr, size); | ||
385 | pcxl_free_range((unsigned long)vaddr, size); | ||
386 | free_pages((unsigned long)__va(dma_handle), order); | ||
387 | } | ||
388 | |||
389 | static dma_addr_t pa11_dma_map_single(struct device *dev, void *addr, size_t size, enum dma_data_direction direction) | ||
390 | { | ||
391 | if (direction == DMA_NONE) { | ||
392 | printk(KERN_ERR "pa11_dma_map_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0)); | ||
393 | BUG(); | ||
394 | } | ||
395 | |||
396 | flush_kernel_dcache_range((unsigned long) addr, size); | ||
397 | return virt_to_phys(addr); | ||
398 | } | ||
399 | |||
400 | static void pa11_dma_unmap_single(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) | ||
401 | { | ||
402 | if (direction == DMA_NONE) { | ||
403 | printk(KERN_ERR "pa11_dma_unmap_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0)); | ||
404 | BUG(); | ||
405 | } | ||
406 | |||
407 | if (direction == DMA_TO_DEVICE) | ||
408 | return; | ||
409 | |||
410 | /* | ||
411 | * For PCI_DMA_FROMDEVICE this flush is not necessary for the | ||
412 | * simple map/unmap case. However, it IS necessary if if | ||
413 | * pci_dma_sync_single_* has been called and the buffer reused. | ||
414 | */ | ||
415 | |||
416 | flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size); | ||
417 | return; | ||
418 | } | ||
419 | |||
420 | static int pa11_dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction) | ||
421 | { | ||
422 | int i; | ||
423 | |||
424 | if (direction == DMA_NONE) | ||
425 | BUG(); | ||
426 | |||
427 | for (i = 0; i < nents; i++, sglist++ ) { | ||
428 | unsigned long vaddr = sg_virt_addr(sglist); | ||
429 | sg_dma_address(sglist) = (dma_addr_t) virt_to_phys(vaddr); | ||
430 | sg_dma_len(sglist) = sglist->length; | ||
431 | flush_kernel_dcache_range(vaddr, sglist->length); | ||
432 | } | ||
433 | return nents; | ||
434 | } | ||
435 | |||
436 | static void pa11_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction) | ||
437 | { | ||
438 | int i; | ||
439 | |||
440 | if (direction == DMA_NONE) | ||
441 | BUG(); | ||
442 | |||
443 | if (direction == DMA_TO_DEVICE) | ||
444 | return; | ||
445 | |||
446 | /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */ | ||
447 | |||
448 | for (i = 0; i < nents; i++, sglist++ ) | ||
449 | flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length); | ||
450 | return; | ||
451 | } | ||
452 | |||
453 | static void pa11_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction) | ||
454 | { | ||
455 | if (direction == DMA_NONE) | ||
456 | BUG(); | ||
457 | |||
458 | flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size); | ||
459 | } | ||
460 | |||
461 | static void pa11_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size, enum dma_data_direction direction) | ||
462 | { | ||
463 | if (direction == DMA_NONE) | ||
464 | BUG(); | ||
465 | |||
466 | flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle) + offset, size); | ||
467 | } | ||
468 | |||
469 | static void pa11_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction) | ||
470 | { | ||
471 | int i; | ||
472 | |||
473 | /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */ | ||
474 | |||
475 | for (i = 0; i < nents; i++, sglist++ ) | ||
476 | flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length); | ||
477 | } | ||
478 | |||
479 | static void pa11_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction) | ||
480 | { | ||
481 | int i; | ||
482 | |||
483 | /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */ | ||
484 | |||
485 | for (i = 0; i < nents; i++, sglist++ ) | ||
486 | flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length); | ||
487 | } | ||
488 | |||
489 | struct hppa_dma_ops pcxl_dma_ops = { | ||
490 | .dma_supported = pa11_dma_supported, | ||
491 | .alloc_consistent = pa11_dma_alloc_consistent, | ||
492 | .alloc_noncoherent = pa11_dma_alloc_consistent, | ||
493 | .free_consistent = pa11_dma_free_consistent, | ||
494 | .map_single = pa11_dma_map_single, | ||
495 | .unmap_single = pa11_dma_unmap_single, | ||
496 | .map_sg = pa11_dma_map_sg, | ||
497 | .unmap_sg = pa11_dma_unmap_sg, | ||
498 | .dma_sync_single_for_cpu = pa11_dma_sync_single_for_cpu, | ||
499 | .dma_sync_single_for_device = pa11_dma_sync_single_for_device, | ||
500 | .dma_sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu, | ||
501 | .dma_sync_sg_for_device = pa11_dma_sync_sg_for_device, | ||
502 | }; | ||
503 | |||
504 | static void *fail_alloc_consistent(struct device *dev, size_t size, | ||
505 | dma_addr_t *dma_handle, int flag) | ||
506 | { | ||
507 | return NULL; | ||
508 | } | ||
509 | |||
510 | static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size, | ||
511 | dma_addr_t *dma_handle, int flag) | ||
512 | { | ||
513 | void *addr = NULL; | ||
514 | |||
515 | /* rely on kmalloc to be cacheline aligned */ | ||
516 | addr = kmalloc(size, flag); | ||
517 | if(addr) | ||
518 | *dma_handle = (dma_addr_t)virt_to_phys(addr); | ||
519 | |||
520 | return addr; | ||
521 | } | ||
522 | |||
523 | static void pa11_dma_free_noncoherent(struct device *dev, size_t size, | ||
524 | void *vaddr, dma_addr_t iova) | ||
525 | { | ||
526 | kfree(vaddr); | ||
527 | return; | ||
528 | } | ||
529 | |||
530 | struct hppa_dma_ops pcx_dma_ops = { | ||
531 | .dma_supported = pa11_dma_supported, | ||
532 | .alloc_consistent = fail_alloc_consistent, | ||
533 | .alloc_noncoherent = pa11_dma_alloc_noncoherent, | ||
534 | .free_consistent = pa11_dma_free_noncoherent, | ||
535 | .map_single = pa11_dma_map_single, | ||
536 | .unmap_single = pa11_dma_unmap_single, | ||
537 | .map_sg = pa11_dma_map_sg, | ||
538 | .unmap_sg = pa11_dma_unmap_sg, | ||
539 | .dma_sync_single_for_cpu = pa11_dma_sync_single_for_cpu, | ||
540 | .dma_sync_single_for_device = pa11_dma_sync_single_for_device, | ||
541 | .dma_sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu, | ||
542 | .dma_sync_sg_for_device = pa11_dma_sync_sg_for_device, | ||
543 | }; | ||
544 | |||
545 | |||
546 | static int pcxl_proc_info(char *buf, char **start, off_t offset, int len) | ||
547 | { | ||
548 | u_long i = 0; | ||
549 | unsigned long *res_ptr = (u_long *)pcxl_res_map; | ||
550 | unsigned long total_pages = pcxl_res_size << 3; /* 8 bits per byte */ | ||
551 | |||
552 | sprintf(buf, "\nDMA Mapping Area size : %d bytes (%d pages)\n", | ||
553 | PCXL_DMA_MAP_SIZE, | ||
554 | (pcxl_res_size << 3) ); /* 1 bit per page */ | ||
555 | |||
556 | sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", | ||
557 | buf, pcxl_res_size, pcxl_res_size << 3); /* 8 bits per byte */ | ||
558 | |||
559 | strcat(buf, " total: free: used: % used:\n"); | ||
560 | sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size, | ||
561 | pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes, | ||
562 | (pcxl_used_bytes * 100) / pcxl_res_size); | ||
563 | |||
564 | sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages, | ||
565 | total_pages - pcxl_used_pages, pcxl_used_pages, | ||
566 | (pcxl_used_pages * 100 / total_pages)); | ||
567 | |||
568 | strcat(buf, "\nResource bitmap:"); | ||
569 | |||
570 | for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) { | ||
571 | if ((i & 7) == 0) | ||
572 | strcat(buf,"\n "); | ||
573 | sprintf(buf, "%s %08lx", buf, *res_ptr); | ||
574 | } | ||
575 | strcat(buf, "\n"); | ||
576 | return strlen(buf); | ||
577 | } | ||
578 | |||
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c new file mode 100644 index 000000000000..3cb08a4a513a --- /dev/null +++ b/arch/parisc/kernel/pci.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $ | ||
2 | * | ||
3 | * This file is subject to the terms and conditions of the GNU General Public | ||
4 | * License. See the file "COPYING" in the main directory of this archive | ||
5 | * for more details. | ||
6 | * | ||
7 | * Copyright (C) 1997, 1998 Ralf Baechle | ||
8 | * Copyright (C) 1999 SuSE GmbH | ||
9 | * Copyright (C) 1999-2001 Hewlett-Packard Company | ||
10 | * Copyright (C) 1999-2001 Grant Grundler | ||
11 | */ | ||
12 | #include <linux/config.h> | ||
13 | #include <linux/eisa.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/types.h> | ||
20 | |||
21 | #include <asm/io.h> | ||
22 | #include <asm/system.h> | ||
23 | #include <asm/cache.h> /* for L1_CACHE_BYTES */ | ||
24 | #include <asm/superio.h> | ||
25 | |||
26 | #define DEBUG_RESOURCES 0 | ||
27 | #define DEBUG_CONFIG 0 | ||
28 | |||
29 | #if DEBUG_CONFIG | ||
30 | # define DBGC(x...) printk(KERN_DEBUG x) | ||
31 | #else | ||
32 | # define DBGC(x...) | ||
33 | #endif | ||
34 | |||
35 | |||
36 | #if DEBUG_RESOURCES | ||
37 | #define DBG_RES(x...) printk(KERN_DEBUG x) | ||
38 | #else | ||
39 | #define DBG_RES(x...) | ||
40 | #endif | ||
41 | |||
42 | /* To be used as: mdelay(pci_post_reset_delay); | ||
43 | * | ||
44 | * post_reset is the time the kernel should stall to prevent anyone from | ||
45 | * accessing the PCI bus once #RESET is de-asserted. | ||
46 | * PCI spec somewhere says 1 second but with multi-PCI bus systems, | ||
47 | * this makes the boot time much longer than necessary. | ||
48 | * 20ms seems to work for all the HP PCI implementations to date. | ||
49 | * | ||
50 | * XXX: turn into a #defined constant in <asm/pci.h> ? | ||
51 | */ | ||
52 | int pci_post_reset_delay = 50; | ||
53 | |||
54 | struct pci_port_ops *pci_port; | ||
55 | struct pci_bios_ops *pci_bios; | ||
56 | |||
57 | int pci_hba_count = 0; | ||
58 | |||
59 | /* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. */ | ||
60 | #define PCI_HBA_MAX 32 | ||
61 | struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX]; | ||
62 | |||
63 | |||
64 | /******************************************************************** | ||
65 | ** | ||
66 | ** I/O port space support | ||
67 | ** | ||
68 | *********************************************************************/ | ||
69 | |||
70 | /* EISA port numbers and PCI port numbers share the same interface. Some | ||
71 | * machines have both EISA and PCI adapters installed. Rather than turn | ||
72 | * pci_port into an array, we reserve bus 0 for EISA and call the EISA | ||
73 | * routines if the access is to a port on bus 0. We don't want to fix | ||
74 | * EISA and ISA drivers which assume port space is <= 0xffff. | ||
75 | */ | ||
76 | |||
77 | #ifdef CONFIG_EISA | ||
78 | #define EISA_IN(size) if (EISA_bus && (b == 0)) return eisa_in##size(addr) | ||
79 | #define EISA_OUT(size) if (EISA_bus && (b == 0)) return eisa_out##size(d, addr) | ||
80 | #else | ||
81 | #define EISA_IN(size) | ||
82 | #define EISA_OUT(size) | ||
83 | #endif | ||
84 | |||
85 | #define PCI_PORT_IN(type, size) \ | ||
86 | u##size in##type (int addr) \ | ||
87 | { \ | ||
88 | int b = PCI_PORT_HBA(addr); \ | ||
89 | EISA_IN(size); \ | ||
90 | if (!parisc_pci_hba[b]) return (u##size) -1; \ | ||
91 | return pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \ | ||
92 | } \ | ||
93 | EXPORT_SYMBOL(in##type); | ||
94 | |||
95 | PCI_PORT_IN(b, 8) | ||
96 | PCI_PORT_IN(w, 16) | ||
97 | PCI_PORT_IN(l, 32) | ||
98 | |||
99 | |||
100 | #define PCI_PORT_OUT(type, size) \ | ||
101 | void out##type (u##size d, int addr) \ | ||
102 | { \ | ||
103 | int b = PCI_PORT_HBA(addr); \ | ||
104 | EISA_OUT(size); \ | ||
105 | if (!parisc_pci_hba[b]) return; \ | ||
106 | pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \ | ||
107 | } \ | ||
108 | EXPORT_SYMBOL(out##type); | ||
109 | |||
110 | PCI_PORT_OUT(b, 8) | ||
111 | PCI_PORT_OUT(w, 16) | ||
112 | PCI_PORT_OUT(l, 32) | ||
113 | |||
114 | |||
115 | |||
116 | /* | ||
117 | * BIOS32 replacement. | ||
118 | */ | ||
119 | static int __init pcibios_init(void) | ||
120 | { | ||
121 | if (!pci_bios) | ||
122 | return -1; | ||
123 | |||
124 | if (pci_bios->init) { | ||
125 | pci_bios->init(); | ||
126 | } else { | ||
127 | printk(KERN_WARNING "pci_bios != NULL but init() is!\n"); | ||
128 | } | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | |||
133 | /* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */ | ||
134 | void pcibios_fixup_bus(struct pci_bus *bus) | ||
135 | { | ||
136 | if (pci_bios->fixup_bus) { | ||
137 | pci_bios->fixup_bus(bus); | ||
138 | } else { | ||
139 | printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n"); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | |||
144 | char *pcibios_setup(char *str) | ||
145 | { | ||
146 | return str; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Called by pci_set_master() - a driver interface. | ||
151 | * | ||
152 | * Legacy PDC guarantees to set: | ||
153 | * Map Memory BAR's into PA IO space. | ||
154 | * Map Expansion ROM BAR into one common PA IO space per bus. | ||
155 | * Map IO BAR's into PCI IO space. | ||
156 | * Command (see below) | ||
157 | * Cache Line Size | ||
158 | * Latency Timer | ||
159 | * Interrupt Line | ||
160 | * PPB: secondary latency timer, io/mmio base/limit, | ||
161 | * bus numbers, bridge control | ||
162 | * | ||
163 | */ | ||
164 | void pcibios_set_master(struct pci_dev *dev) | ||
165 | { | ||
166 | u8 lat; | ||
167 | |||
168 | /* If someone already mucked with this, don't touch it. */ | ||
169 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); | ||
170 | if (lat >= 16) return; | ||
171 | |||
172 | /* | ||
173 | ** HP generally has fewer devices on the bus than other architectures. | ||
174 | ** upper byte is PCI_LATENCY_TIMER. | ||
175 | */ | ||
176 | pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, | ||
177 | (0x80 << 8) | (L1_CACHE_BYTES / sizeof(u32))); | ||
178 | } | ||
179 | |||
180 | |||
181 | void __init pcibios_init_bus(struct pci_bus *bus) | ||
182 | { | ||
183 | struct pci_dev *dev = bus->self; | ||
184 | unsigned short bridge_ctl; | ||
185 | |||
186 | /* We deal only with pci controllers and pci-pci bridges. */ | ||
187 | if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
188 | return; | ||
189 | |||
190 | /* PCI-PCI bridge - set the cache line and default latency | ||
191 | (32) for primary and secondary buses. */ | ||
192 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32); | ||
193 | |||
194 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl); | ||
195 | bridge_ctl |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; | ||
196 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl); | ||
197 | } | ||
198 | |||
199 | |||
200 | /* KLUGE: Link the child and parent resources - generic PCI didn't */ | ||
201 | static void | ||
202 | pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) | ||
203 | { | ||
204 | if (!r->parent) { | ||
205 | printk(KERN_EMERG "PCI: Tell willy he's wrong\n"); | ||
206 | r->parent = hba_res; | ||
207 | |||
208 | /* reverse link is harder *sigh* */ | ||
209 | if (r->parent->child) { | ||
210 | if (r->parent->sibling) { | ||
211 | struct resource *next = r->parent->sibling; | ||
212 | while (next->sibling) | ||
213 | next = next->sibling; | ||
214 | next->sibling = r; | ||
215 | } else { | ||
216 | r->parent->sibling = r; | ||
217 | } | ||
218 | } else | ||
219 | r->parent->child = r; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | /* called by drivers/pci/setup-bus.c:pci_setup_bridge(). */ | ||
224 | void __devinit pcibios_resource_to_bus(struct pci_dev *dev, | ||
225 | struct pci_bus_region *region, struct resource *res) | ||
226 | { | ||
227 | struct pci_bus *bus = dev->bus; | ||
228 | struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data); | ||
229 | |||
230 | if (res->flags & IORESOURCE_IO) { | ||
231 | /* | ||
232 | ** I/O space may see busnumbers here. Something | ||
233 | ** in the form of 0xbbxxxx where bb is the bus num | ||
234 | ** and xxxx is the I/O port space address. | ||
235 | ** Remaining address translation are done in the | ||
236 | ** PCI Host adapter specific code - ie dino_out8. | ||
237 | */ | ||
238 | region->start = PCI_PORT_ADDR(res->start); | ||
239 | region->end = PCI_PORT_ADDR(res->end); | ||
240 | } else if (res->flags & IORESOURCE_MEM) { | ||
241 | /* Convert MMIO addr to PCI addr (undo global virtualization) */ | ||
242 | region->start = PCI_BUS_ADDR(hba, res->start); | ||
243 | region->end = PCI_BUS_ADDR(hba, res->end); | ||
244 | } | ||
245 | |||
246 | DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n", | ||
247 | bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM", | ||
248 | region->start, region->end); | ||
249 | |||
250 | /* KLUGE ALERT | ||
251 | ** if this resource isn't linked to a "parent", then it seems | ||
252 | ** to be a child of the HBA - lets link it in. | ||
253 | */ | ||
254 | pcibios_link_hba_resources(&hba->io_space, bus->resource[0]); | ||
255 | pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]); | ||
256 | } | ||
257 | |||
258 | #ifdef CONFIG_HOTPLUG | ||
259 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
260 | #endif | ||
261 | |||
262 | /* | ||
263 | * pcibios align resources() is called every time generic PCI code | ||
264 | * wants to generate a new address. The process of looking for | ||
265 | * an available address, each candidate is first "aligned" and | ||
266 | * then checked if the resource is available until a match is found. | ||
267 | * | ||
268 | * Since we are just checking candidates, don't use any fields other | ||
269 | * than res->start. | ||
270 | */ | ||
271 | void pcibios_align_resource(void *data, struct resource *res, | ||
272 | unsigned long size, unsigned long alignment) | ||
273 | { | ||
274 | unsigned long mask, align; | ||
275 | |||
276 | DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n", | ||
277 | pci_name(((struct pci_dev *) data)), | ||
278 | res->parent, res->start, res->end, | ||
279 | (int) res->flags, size, alignment); | ||
280 | |||
281 | /* If it's not IO, then it's gotta be MEM */ | ||
282 | align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; | ||
283 | |||
284 | /* Align to largest of MIN or input size */ | ||
285 | mask = max(alignment, align) - 1; | ||
286 | res->start += mask; | ||
287 | res->start &= ~mask; | ||
288 | |||
289 | /* The caller updates the end field, we don't. */ | ||
290 | } | ||
291 | |||
292 | |||
293 | /* | ||
294 | * A driver is enabling the device. We make sure that all the appropriate | ||
295 | * bits are set to allow the device to operate as the driver is expecting. | ||
296 | * We enable the port IO and memory IO bits if the device has any BARs of | ||
297 | * that type, and we enable the PERR and SERR bits unconditionally. | ||
298 | * Drivers that do not need parity (eg graphics and possibly networking) | ||
299 | * can clear these bits if they want. | ||
300 | */ | ||
301 | int pcibios_enable_device(struct pci_dev *dev, int mask) | ||
302 | { | ||
303 | u16 cmd; | ||
304 | int idx; | ||
305 | |||
306 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
307 | |||
308 | for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) { | ||
309 | struct resource *r = &dev->resource[idx]; | ||
310 | |||
311 | /* only setup requested resources */ | ||
312 | if (!(mask & (1<<idx))) | ||
313 | continue; | ||
314 | |||
315 | if (r->flags & IORESOURCE_IO) | ||
316 | cmd |= PCI_COMMAND_IO; | ||
317 | if (r->flags & IORESOURCE_MEM) | ||
318 | cmd |= PCI_COMMAND_MEMORY; | ||
319 | } | ||
320 | |||
321 | cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY); | ||
322 | |||
323 | #if 0 | ||
324 | /* If bridge/bus controller has FBB enabled, child must too. */ | ||
325 | if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK) | ||
326 | cmd |= PCI_COMMAND_FAST_BACK; | ||
327 | #endif | ||
328 | DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", pci_name(dev), cmd); | ||
329 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | |||
334 | /* PA-RISC specific */ | ||
335 | void pcibios_register_hba(struct pci_hba_data *hba) | ||
336 | { | ||
337 | if (pci_hba_count >= PCI_HBA_MAX) { | ||
338 | printk(KERN_ERR "PCI: Too many Host Bus Adapters\n"); | ||
339 | return; | ||
340 | } | ||
341 | |||
342 | parisc_pci_hba[pci_hba_count] = hba; | ||
343 | hba->hba_num = pci_hba_count++; | ||
344 | } | ||
345 | |||
346 | subsys_initcall(pcibios_init); | ||
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c new file mode 100644 index 000000000000..52004ae28d20 --- /dev/null +++ b/arch/parisc/kernel/pdc_chassis.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /* | ||
2 | * interfaces to log Chassis Codes via PDC (firmware) | ||
3 | * | ||
4 | * Copyright (C) 2002 Laurent Canet <canetl@esiee.fr> | ||
5 | * Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #undef PDC_CHASSIS_DEBUG | ||
23 | #ifdef PDC_CHASSIS_DEBUG | ||
24 | #define DPRINTK(fmt, args...) printk(fmt, ## args) | ||
25 | #else | ||
26 | #define DPRINTK(fmt, args...) | ||
27 | #endif | ||
28 | |||
29 | #include <linux/init.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/reboot.h> | ||
32 | #include <linux/notifier.h> | ||
33 | |||
34 | #include <asm/pdc_chassis.h> | ||
35 | #include <asm/processor.h> | ||
36 | #include <asm/pdc.h> | ||
37 | #include <asm/pdcpat.h> | ||
38 | |||
39 | |||
40 | #ifdef CONFIG_PDC_CHASSIS | ||
41 | static int pdc_chassis_old = 0; | ||
42 | static unsigned int pdc_chassis_enabled = 1; | ||
43 | |||
44 | |||
45 | /** | ||
46 | * pdc_chassis_setup() - Enable/disable pdc_chassis code at boot time. | ||
47 | * @str configuration param: 0 to disable chassis log | ||
48 | * @return 1 | ||
49 | */ | ||
50 | |||
51 | static int __init pdc_chassis_setup(char *str) | ||
52 | { | ||
53 | /*panic_timeout = simple_strtoul(str, NULL, 0);*/ | ||
54 | get_option(&str, &pdc_chassis_enabled); | ||
55 | return 1; | ||
56 | } | ||
57 | __setup("pdcchassis=", pdc_chassis_setup); | ||
58 | |||
59 | |||
60 | /** | ||
61 | * pdc_chassis_checkold() - Checks for old PDC_CHASSIS compatibility | ||
62 | * @pdc_chassis_old: 1 if old pdc chassis style | ||
63 | * | ||
64 | * Currently, only E class and A180 are known to work with this. | ||
65 | * Inspired by Christoph Plattner | ||
66 | */ | ||
67 | |||
68 | static void __init pdc_chassis_checkold(void) | ||
69 | { | ||
70 | switch(CPU_HVERSION) { | ||
71 | case 0x480: /* E25 */ | ||
72 | case 0x481: /* E35 */ | ||
73 | case 0x482: /* E45 */ | ||
74 | case 0x483: /* E55 */ | ||
75 | case 0x516: /* A180 */ | ||
76 | pdc_chassis_old = 1; | ||
77 | break; | ||
78 | |||
79 | default: | ||
80 | break; | ||
81 | } | ||
82 | DPRINTK(KERN_DEBUG "%s: pdc_chassis_checkold(); pdc_chassis_old = %d\n", __FILE__, pdc_chassis_old); | ||
83 | } | ||
84 | |||
85 | |||
86 | /** | ||
87 | * pdc_chassis_panic_event() - Called by the panic handler. | ||
88 | * | ||
89 | * As soon as a panic occurs, we should inform the PDC. | ||
90 | */ | ||
91 | |||
92 | static int pdc_chassis_panic_event(struct notifier_block *this, | ||
93 | unsigned long event, void *ptr) | ||
94 | { | ||
95 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); | ||
96 | return NOTIFY_DONE; | ||
97 | } | ||
98 | |||
99 | |||
100 | static struct notifier_block pdc_chassis_panic_block = { | ||
101 | .notifier_call = pdc_chassis_panic_event, | ||
102 | .priority = INT_MAX, | ||
103 | }; | ||
104 | |||
105 | |||
106 | /** | ||
107 | * parisc_reboot_event() - Called by the reboot handler. | ||
108 | * | ||
109 | * As soon as a reboot occurs, we should inform the PDC. | ||
110 | */ | ||
111 | |||
112 | static int pdc_chassis_reboot_event(struct notifier_block *this, | ||
113 | unsigned long event, void *ptr) | ||
114 | { | ||
115 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); | ||
116 | return NOTIFY_DONE; | ||
117 | } | ||
118 | |||
119 | |||
120 | static struct notifier_block pdc_chassis_reboot_block = { | ||
121 | .notifier_call = pdc_chassis_reboot_event, | ||
122 | .priority = INT_MAX, | ||
123 | }; | ||
124 | #endif /* CONFIG_PDC_CHASSIS */ | ||
125 | |||
126 | |||
127 | /** | ||
128 | * parisc_pdc_chassis_init() - Called at boot time. | ||
129 | */ | ||
130 | |||
131 | void __init parisc_pdc_chassis_init(void) | ||
132 | { | ||
133 | #ifdef CONFIG_PDC_CHASSIS | ||
134 | int handle = 0; | ||
135 | if (pdc_chassis_enabled) { | ||
136 | DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__); | ||
137 | |||
138 | /* Let see if we have something to handle... */ | ||
139 | /* Check for PDC_PAT or old LED Panel */ | ||
140 | pdc_chassis_checkold(); | ||
141 | if (is_pdc_pat()) { | ||
142 | printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n"); | ||
143 | handle = 1; | ||
144 | } | ||
145 | else if (pdc_chassis_old) { | ||
146 | printk(KERN_INFO "Enabling old style chassis LED panel support.\n"); | ||
147 | handle = 1; | ||
148 | } | ||
149 | |||
150 | if (handle) { | ||
151 | /* initialize panic notifier chain */ | ||
152 | notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block); | ||
153 | |||
154 | /* initialize reboot notifier chain */ | ||
155 | register_reboot_notifier(&pdc_chassis_reboot_block); | ||
156 | } | ||
157 | } | ||
158 | #endif /* CONFIG_PDC_CHASSIS */ | ||
159 | } | ||
160 | |||
161 | |||
162 | /** | ||
163 | * pdc_chassis_send_status() - Sends a predefined message to the chassis, | ||
164 | * and changes the front panel LEDs according to the new system state | ||
165 | * @retval: PDC call return value. | ||
166 | * | ||
167 | * Only machines with 64 bits PDC PAT and those reported in | ||
168 | * pdc_chassis_checkold() are supported atm. | ||
169 | * | ||
170 | * returns 0 if no error, -1 if no supported PDC is present or invalid message, | ||
171 | * else returns the appropriate PDC error code. | ||
172 | * | ||
173 | * For a list of predefined messages, see asm-parisc/pdc_chassis.h | ||
174 | */ | ||
175 | |||
176 | int pdc_chassis_send_status(int message) | ||
177 | { | ||
178 | /* Maybe we should do that in an other way ? */ | ||
179 | int retval = 0; | ||
180 | #ifdef CONFIG_PDC_CHASSIS | ||
181 | if (pdc_chassis_enabled) { | ||
182 | |||
183 | DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message); | ||
184 | |||
185 | #ifdef CONFIG_64BIT | ||
186 | if (is_pdc_pat()) { | ||
187 | switch(message) { | ||
188 | case PDC_CHASSIS_DIRECT_BSTART: | ||
189 | retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_BSTART, PDC_CHASSIS_LSTATE_RUN_NORMAL); | ||
190 | break; | ||
191 | |||
192 | case PDC_CHASSIS_DIRECT_BCOMPLETE: | ||
193 | retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_BCOMPLETE, PDC_CHASSIS_LSTATE_RUN_NORMAL); | ||
194 | break; | ||
195 | |||
196 | case PDC_CHASSIS_DIRECT_SHUTDOWN: | ||
197 | retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_SHUTDOWN, PDC_CHASSIS_LSTATE_NONOS); | ||
198 | break; | ||
199 | |||
200 | case PDC_CHASSIS_DIRECT_PANIC: | ||
201 | retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_PANIC, PDC_CHASSIS_LSTATE_RUN_CRASHREC); | ||
202 | break; | ||
203 | |||
204 | case PDC_CHASSIS_DIRECT_LPMC: | ||
205 | retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_LPMC, PDC_CHASSIS_LSTATE_RUN_SYSINT); | ||
206 | break; | ||
207 | |||
208 | case PDC_CHASSIS_DIRECT_HPMC: | ||
209 | retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_HPMC, PDC_CHASSIS_LSTATE_RUN_NCRIT); | ||
210 | break; | ||
211 | |||
212 | default: | ||
213 | retval = -1; | ||
214 | } | ||
215 | } else retval = -1; | ||
216 | #else | ||
217 | if (pdc_chassis_old) { | ||
218 | switch (message) { | ||
219 | case PDC_CHASSIS_DIRECT_BSTART: | ||
220 | case PDC_CHASSIS_DIRECT_BCOMPLETE: | ||
221 | retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_RUN)); | ||
222 | break; | ||
223 | |||
224 | case PDC_CHASSIS_DIRECT_SHUTDOWN: | ||
225 | retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_SHUT)); | ||
226 | break; | ||
227 | |||
228 | case PDC_CHASSIS_DIRECT_HPMC: | ||
229 | case PDC_CHASSIS_DIRECT_PANIC: | ||
230 | retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_FLT)); | ||
231 | break; | ||
232 | |||
233 | case PDC_CHASSIS_DIRECT_LPMC: | ||
234 | retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_WARN)); | ||
235 | break; | ||
236 | |||
237 | default: | ||
238 | retval = -1; | ||
239 | } | ||
240 | } else retval = -1; | ||
241 | #endif /* CONFIG_64BIT */ | ||
242 | } /* if (pdc_chassis_enabled) */ | ||
243 | #endif /* CONFIG_PDC_CHASSIS */ | ||
244 | return retval; | ||
245 | } | ||
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c new file mode 100644 index 000000000000..01f676d1673b --- /dev/null +++ b/arch/parisc/kernel/pdc_cons.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * PDC Console support - ie use firmware to dump text via boot console | ||
3 | * | ||
4 | * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org> | ||
5 | * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net> | ||
6 | * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org> | ||
7 | * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org> | ||
8 | * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org> | ||
9 | * Copyright (C) 2000 Michael Ang <mang with subcarrier.org> | ||
10 | * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org> | ||
11 | * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org> | ||
12 | * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org> | ||
13 | * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org> | ||
14 | * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> | ||
15 | * | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License as published by | ||
19 | * the Free Software Foundation; either version 2 of the License, or | ||
20 | * (at your option) any later version. | ||
21 | * | ||
22 | * This program is distributed in the hope that it will be useful, | ||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | * GNU General Public License for more details. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License | ||
28 | * along with this program; if not, write to the Free Software | ||
29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * The PDC console is a simple console, which can be used for debugging | ||
34 | * boot related problems on HP PA-RISC machines. | ||
35 | * | ||
36 | * This code uses the ROM (=PDC) based functions to read and write characters | ||
37 | * from and to PDC's boot path. | ||
38 | * Since all character read from that path must be polled, this code never | ||
39 | * can or will be a fully functional linux console. | ||
40 | */ | ||
41 | |||
42 | /* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems. | ||
43 | * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */ | ||
44 | #undef EARLY_BOOTUP_DEBUG | ||
45 | |||
46 | |||
47 | #include <linux/config.h> | ||
48 | #include <linux/kernel.h> | ||
49 | #include <linux/console.h> | ||
50 | #include <linux/string.h> | ||
51 | #include <linux/init.h> | ||
52 | #include <linux/delay.h> | ||
53 | #include <linux/sched.h> | ||
54 | #include <linux/interrupt.h> | ||
55 | #include <linux/major.h> | ||
56 | #include <linux/tty.h> | ||
57 | #include <asm/page.h> | ||
58 | #include <asm/types.h> | ||
59 | #include <asm/system.h> | ||
60 | #include <asm/pdc.h> /* for iodc_call() proto and friends */ | ||
61 | |||
62 | |||
63 | static void pdc_console_write(struct console *co, const char *s, unsigned count) | ||
64 | { | ||
65 | while(count--) | ||
66 | pdc_iodc_putc(*s++); | ||
67 | } | ||
68 | |||
69 | void pdc_outc(unsigned char c) | ||
70 | { | ||
71 | pdc_iodc_outc(c); | ||
72 | } | ||
73 | |||
74 | void pdc_printf(const char *fmt, ...) | ||
75 | { | ||
76 | va_list args; | ||
77 | char buf[1024]; | ||
78 | int i, len; | ||
79 | |||
80 | va_start(args, fmt); | ||
81 | len = vscnprintf(buf, sizeof(buf), fmt, args); | ||
82 | va_end(args); | ||
83 | |||
84 | for (i = 0; i < len; i++) | ||
85 | pdc_iodc_outc(buf[i]); | ||
86 | } | ||
87 | |||
88 | int pdc_console_poll_key(struct console *co) | ||
89 | { | ||
90 | return pdc_iodc_getc(); | ||
91 | } | ||
92 | |||
93 | static int pdc_console_setup(struct console *co, char *options) | ||
94 | { | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | #if defined(CONFIG_PDC_CONSOLE) | ||
99 | #define PDC_CONSOLE_DEVICE pdc_console_device | ||
100 | static struct tty_driver * pdc_console_device (struct console *c, int *index) | ||
101 | { | ||
102 | extern struct tty_driver console_driver; | ||
103 | *index = c->index ? c->index-1 : fg_console; | ||
104 | return &console_driver; | ||
105 | } | ||
106 | #else | ||
107 | #define PDC_CONSOLE_DEVICE NULL | ||
108 | #endif | ||
109 | |||
110 | static struct console pdc_cons = { | ||
111 | .name = "ttyB", | ||
112 | .write = pdc_console_write, | ||
113 | .device = PDC_CONSOLE_DEVICE, | ||
114 | .setup = pdc_console_setup, | ||
115 | .flags = CON_BOOT|CON_PRINTBUFFER|CON_ENABLED, | ||
116 | .index = -1, | ||
117 | }; | ||
118 | |||
119 | static int pdc_console_initialized; | ||
120 | extern unsigned long con_start; /* kernel/printk.c */ | ||
121 | extern unsigned long log_end; /* kernel/printk.c */ | ||
122 | |||
123 | |||
124 | static void pdc_console_init_force(void) | ||
125 | { | ||
126 | if (pdc_console_initialized) | ||
127 | return; | ||
128 | ++pdc_console_initialized; | ||
129 | |||
130 | /* If the console is duplex then copy the COUT parameters to CIN. */ | ||
131 | if (PAGE0->mem_cons.cl_class == CL_DUPLEX) | ||
132 | memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons)); | ||
133 | |||
134 | /* register the pdc console */ | ||
135 | register_console(&pdc_cons); | ||
136 | } | ||
137 | |||
138 | void __init pdc_console_init(void) | ||
139 | { | ||
140 | #if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE) | ||
141 | pdc_console_init_force(); | ||
142 | #endif | ||
143 | #ifdef EARLY_BOOTUP_DEBUG | ||
144 | printk(KERN_INFO "Initialized PDC Console for debugging.\n"); | ||
145 | #endif | ||
146 | } | ||
147 | |||
148 | |||
149 | /* Unregister the pdc console with the printk console layer */ | ||
150 | void pdc_console_die(void) | ||
151 | { | ||
152 | if (!pdc_console_initialized) | ||
153 | return; | ||
154 | --pdc_console_initialized; | ||
155 | |||
156 | printk(KERN_INFO "Switching from PDC console\n"); | ||
157 | |||
158 | /* Don't repeat what we've already printed */ | ||
159 | con_start = log_end; | ||
160 | |||
161 | unregister_console(&pdc_cons); | ||
162 | } | ||
163 | |||
164 | |||
165 | /* | ||
166 | * Used for emergencies. Currently only used if an HPMC occurs. If an | ||
167 | * HPMC occurs, it is possible that the current console may not be | ||
168 | * properly initialed after the PDC IO reset. This routine unregisters all | ||
169 | * of the current consoles, reinitializes the pdc console and | ||
170 | * registers it. | ||
171 | */ | ||
172 | |||
173 | void pdc_console_restart(void) | ||
174 | { | ||
175 | struct console *console; | ||
176 | |||
177 | if (pdc_console_initialized) | ||
178 | return; | ||
179 | |||
180 | while ((console = console_drivers) != NULL) | ||
181 | unregister_console(console_drivers); | ||
182 | |||
183 | /* Don't repeat what we've already printed */ | ||
184 | con_start = log_end; | ||
185 | |||
186 | /* force registering the pdc console */ | ||
187 | pdc_console_init_force(); | ||
188 | } | ||
189 | |||
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c new file mode 100644 index 000000000000..b3ad0a505b87 --- /dev/null +++ b/arch/parisc/kernel/perf.c | |||
@@ -0,0 +1,841 @@ | |||
1 | /* | ||
2 | * Parisc performance counters | ||
3 | * Copyright (C) 2001 Randolph Chung <tausq@debian.org> | ||
4 | * | ||
5 | * This code is derived, with permission, from HP/UX sources. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * Edited comment from original sources: | ||
24 | * | ||
25 | * This driver programs the PCX-U/PCX-W performance counters | ||
26 | * on the PA-RISC 2.0 chips. The driver keeps all images now | ||
27 | * internally to the kernel to hopefully eliminate the possiblity | ||
28 | * of a bad image halting the CPU. Also, there are different | ||
29 | * images for the PCX-W and later chips vs the PCX-U chips. | ||
30 | * | ||
31 | * Only 1 process is allowed to access the driver at any time, | ||
32 | * so the only protection that is needed is at open and close. | ||
33 | * A variable "perf_enabled" is used to hold the state of the | ||
34 | * driver. The spinlock "perf_lock" is used to protect the | ||
35 | * modification of the state during open/close operations so | ||
36 | * multiple processes don't get into the driver simultaneously. | ||
37 | * | ||
38 | * This driver accesses the processor directly vs going through | ||
39 | * the PDC INTRIGUE calls. This is done to eliminate bugs introduced | ||
40 | * in various PDC revisions. The code is much more maintainable | ||
41 | * and reliable this way vs having to debug on every version of PDC | ||
42 | * on every box. | ||
43 | */ | ||
44 | |||
45 | #include <linux/init.h> | ||
46 | #include <linux/proc_fs.h> | ||
47 | #include <linux/miscdevice.h> | ||
48 | #include <linux/spinlock.h> | ||
49 | |||
50 | #include <asm/uaccess.h> | ||
51 | #include <asm/perf.h> | ||
52 | #include <asm/parisc-device.h> | ||
53 | #include <asm/processor.h> | ||
54 | #include <asm/runway.h> | ||
55 | #include <asm/io.h> /* for __raw_read() */ | ||
56 | |||
57 | #include "perf_images.h" | ||
58 | |||
59 | #define MAX_RDR_WORDS 24 | ||
60 | #define PERF_VERSION 2 /* derived from hpux's PI v2 interface */ | ||
61 | |||
62 | /* definition of RDR regs */ | ||
63 | struct rdr_tbl_ent { | ||
64 | uint16_t width; | ||
65 | uint8_t num_words; | ||
66 | uint8_t write_control; | ||
67 | }; | ||
68 | |||
69 | static int perf_processor_interface = UNKNOWN_INTF; | ||
70 | static int perf_enabled = 0; | ||
71 | static spinlock_t perf_lock; | ||
72 | struct parisc_device *cpu_device = NULL; | ||
73 | |||
74 | /* RDRs to write for PCX-W */ | ||
75 | static int perf_rdrs_W[] = | ||
76 | { 0, 1, 4, 5, 6, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 }; | ||
77 | |||
78 | /* RDRs to write for PCX-U */ | ||
79 | static int perf_rdrs_U[] = | ||
80 | { 0, 1, 4, 5, 6, 7, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 }; | ||
81 | |||
82 | /* RDR register descriptions for PCX-W */ | ||
83 | static struct rdr_tbl_ent perf_rdr_tbl_W[] = { | ||
84 | { 19, 1, 8 }, /* RDR 0 */ | ||
85 | { 16, 1, 16 }, /* RDR 1 */ | ||
86 | { 72, 2, 0 }, /* RDR 2 */ | ||
87 | { 81, 2, 0 }, /* RDR 3 */ | ||
88 | { 328, 6, 0 }, /* RDR 4 */ | ||
89 | { 160, 3, 0 }, /* RDR 5 */ | ||
90 | { 336, 6, 0 }, /* RDR 6 */ | ||
91 | { 164, 3, 0 }, /* RDR 7 */ | ||
92 | { 0, 0, 0 }, /* RDR 8 */ | ||
93 | { 35, 1, 0 }, /* RDR 9 */ | ||
94 | { 6, 1, 0 }, /* RDR 10 */ | ||
95 | { 18, 1, 0 }, /* RDR 11 */ | ||
96 | { 13, 1, 0 }, /* RDR 12 */ | ||
97 | { 8, 1, 0 }, /* RDR 13 */ | ||
98 | { 8, 1, 0 }, /* RDR 14 */ | ||
99 | { 8, 1, 0 }, /* RDR 15 */ | ||
100 | { 1530, 24, 0 }, /* RDR 16 */ | ||
101 | { 16, 1, 0 }, /* RDR 17 */ | ||
102 | { 4, 1, 0 }, /* RDR 18 */ | ||
103 | { 0, 0, 0 }, /* RDR 19 */ | ||
104 | { 152, 3, 24 }, /* RDR 20 */ | ||
105 | { 152, 3, 24 }, /* RDR 21 */ | ||
106 | { 233, 4, 48 }, /* RDR 22 */ | ||
107 | { 233, 4, 48 }, /* RDR 23 */ | ||
108 | { 71, 2, 0 }, /* RDR 24 */ | ||
109 | { 71, 2, 0 }, /* RDR 25 */ | ||
110 | { 11, 1, 0 }, /* RDR 26 */ | ||
111 | { 18, 1, 0 }, /* RDR 27 */ | ||
112 | { 128, 2, 0 }, /* RDR 28 */ | ||
113 | { 0, 0, 0 }, /* RDR 29 */ | ||
114 | { 16, 1, 0 }, /* RDR 30 */ | ||
115 | { 16, 1, 0 }, /* RDR 31 */ | ||
116 | }; | ||
117 | |||
118 | /* RDR register descriptions for PCX-U */ | ||
119 | static struct rdr_tbl_ent perf_rdr_tbl_U[] = { | ||
120 | { 19, 1, 8 }, /* RDR 0 */ | ||
121 | { 32, 1, 16 }, /* RDR 1 */ | ||
122 | { 20, 1, 0 }, /* RDR 2 */ | ||
123 | { 0, 0, 0 }, /* RDR 3 */ | ||
124 | { 344, 6, 0 }, /* RDR 4 */ | ||
125 | { 176, 3, 0 }, /* RDR 5 */ | ||
126 | { 336, 6, 0 }, /* RDR 6 */ | ||
127 | { 0, 0, 0 }, /* RDR 7 */ | ||
128 | { 0, 0, 0 }, /* RDR 8 */ | ||
129 | { 0, 0, 0 }, /* RDR 9 */ | ||
130 | { 28, 1, 0 }, /* RDR 10 */ | ||
131 | { 33, 1, 0 }, /* RDR 11 */ | ||
132 | { 0, 0, 0 }, /* RDR 12 */ | ||
133 | { 230, 4, 0 }, /* RDR 13 */ | ||
134 | { 32, 1, 0 }, /* RDR 14 */ | ||
135 | { 128, 2, 0 }, /* RDR 15 */ | ||
136 | { 1494, 24, 0 }, /* RDR 16 */ | ||
137 | { 18, 1, 0 }, /* RDR 17 */ | ||
138 | { 4, 1, 0 }, /* RDR 18 */ | ||
139 | { 0, 0, 0 }, /* RDR 19 */ | ||
140 | { 158, 3, 24 }, /* RDR 20 */ | ||
141 | { 158, 3, 24 }, /* RDR 21 */ | ||
142 | { 194, 4, 48 }, /* RDR 22 */ | ||
143 | { 194, 4, 48 }, /* RDR 23 */ | ||
144 | { 71, 2, 0 }, /* RDR 24 */ | ||
145 | { 71, 2, 0 }, /* RDR 25 */ | ||
146 | { 28, 1, 0 }, /* RDR 26 */ | ||
147 | { 33, 1, 0 }, /* RDR 27 */ | ||
148 | { 88, 2, 0 }, /* RDR 28 */ | ||
149 | { 32, 1, 0 }, /* RDR 29 */ | ||
150 | { 24, 1, 0 }, /* RDR 30 */ | ||
151 | { 16, 1, 0 }, /* RDR 31 */ | ||
152 | }; | ||
153 | |||
154 | /* | ||
155 | * A non-zero write_control in the above tables is a byte offset into | ||
156 | * this array. | ||
157 | */ | ||
158 | static uint64_t perf_bitmasks[] = { | ||
159 | 0x0000000000000000ul, /* first dbl word must be zero */ | ||
160 | 0xfdffe00000000000ul, /* RDR0 bitmask */ | ||
161 | 0x003f000000000000ul, /* RDR1 bitmask */ | ||
162 | 0x00fffffffffffffful, /* RDR20-RDR21 bitmask (152 bits) */ | ||
163 | 0xfffffffffffffffful, | ||
164 | 0xfffffffc00000000ul, | ||
165 | 0xfffffffffffffffful, /* RDR22-RDR23 bitmask (233 bits) */ | ||
166 | 0xfffffffffffffffful, | ||
167 | 0xfffffffffffffffcul, | ||
168 | 0xff00000000000000ul | ||
169 | }; | ||
170 | |||
171 | /* | ||
172 | * Write control bitmasks for Pa-8700 processor given | ||
173 | * somethings have changed slightly. | ||
174 | */ | ||
175 | static uint64_t perf_bitmasks_piranha[] = { | ||
176 | 0x0000000000000000ul, /* first dbl word must be zero */ | ||
177 | 0xfdffe00000000000ul, /* RDR0 bitmask */ | ||
178 | 0x003f000000000000ul, /* RDR1 bitmask */ | ||
179 | 0x00fffffffffffffful, /* RDR20-RDR21 bitmask (158 bits) */ | ||
180 | 0xfffffffffffffffful, | ||
181 | 0xfffffffc00000000ul, | ||
182 | 0xfffffffffffffffful, /* RDR22-RDR23 bitmask (210 bits) */ | ||
183 | 0xfffffffffffffffful, | ||
184 | 0xfffffffffffffffful, | ||
185 | 0xfffc000000000000ul | ||
186 | }; | ||
187 | |||
188 | static uint64_t *bitmask_array; /* array of bitmasks to use */ | ||
189 | |||
190 | /****************************************************************************** | ||
191 | * Function Prototypes | ||
192 | *****************************************************************************/ | ||
193 | static int perf_config(uint32_t *image_ptr); | ||
194 | static int perf_release(struct inode *inode, struct file *file); | ||
195 | static int perf_open(struct inode *inode, struct file *file); | ||
196 | static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos); | ||
197 | static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, | ||
198 | loff_t *ppos); | ||
199 | static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
200 | unsigned long arg); | ||
201 | static void perf_start_counters(void); | ||
202 | static int perf_stop_counters(uint32_t *raddr); | ||
203 | static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num); | ||
204 | static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer); | ||
205 | static int perf_rdr_clear(uint32_t rdr_num); | ||
206 | static int perf_write_image(uint64_t *memaddr); | ||
207 | static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer); | ||
208 | |||
209 | /* External Assembly Routines */ | ||
210 | extern uint64_t perf_rdr_shift_in_W (uint32_t rdr_num, uint16_t width); | ||
211 | extern uint64_t perf_rdr_shift_in_U (uint32_t rdr_num, uint16_t width); | ||
212 | extern void perf_rdr_shift_out_W (uint32_t rdr_num, uint64_t buffer); | ||
213 | extern void perf_rdr_shift_out_U (uint32_t rdr_num, uint64_t buffer); | ||
214 | extern void perf_intrigue_enable_perf_counters (void); | ||
215 | extern void perf_intrigue_disable_perf_counters (void); | ||
216 | |||
217 | /****************************************************************************** | ||
218 | * Function Definitions | ||
219 | *****************************************************************************/ | ||
220 | |||
221 | |||
222 | /* | ||
223 | * configure: | ||
224 | * | ||
225 | * Configure the cpu with a given data image. First turn off the counters, | ||
226 | * then download the image, then turn the counters back on. | ||
227 | */ | ||
228 | static int perf_config(uint32_t *image_ptr) | ||
229 | { | ||
230 | long error; | ||
231 | uint32_t raddr[4]; | ||
232 | |||
233 | /* Stop the counters*/ | ||
234 | error = perf_stop_counters(raddr); | ||
235 | if (error != 0) { | ||
236 | printk("perf_config: perf_stop_counters = %ld\n", error); | ||
237 | return -EINVAL; | ||
238 | } | ||
239 | |||
240 | printk("Preparing to write image\n"); | ||
241 | /* Write the image to the chip */ | ||
242 | error = perf_write_image((uint64_t *)image_ptr); | ||
243 | if (error != 0) { | ||
244 | printk("perf_config: DOWNLOAD = %ld\n", error); | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | |||
248 | printk("Preparing to start counters\n"); | ||
249 | |||
250 | /* Start the counters */ | ||
251 | perf_start_counters(); | ||
252 | |||
253 | return sizeof(uint32_t); | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * Open the device and initialize all of its memory. The device is only | ||
258 | * opened once, but can be "queried" by multiple processes that know its | ||
259 | * file descriptor. | ||
260 | */ | ||
261 | static int perf_open(struct inode *inode, struct file *file) | ||
262 | { | ||
263 | spin_lock(&perf_lock); | ||
264 | if (perf_enabled) { | ||
265 | spin_unlock(&perf_lock); | ||
266 | return -EBUSY; | ||
267 | } | ||
268 | perf_enabled = 1; | ||
269 | spin_unlock(&perf_lock); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Close the device. | ||
276 | */ | ||
277 | static int perf_release(struct inode *inode, struct file *file) | ||
278 | { | ||
279 | spin_lock(&perf_lock); | ||
280 | perf_enabled = 0; | ||
281 | spin_unlock(&perf_lock); | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * Read does nothing for this driver | ||
288 | */ | ||
289 | static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos) | ||
290 | { | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * write: | ||
296 | * | ||
297 | * This routine downloads the image to the chip. It must be | ||
298 | * called on the processor that the download should happen | ||
299 | * on. | ||
300 | */ | ||
301 | static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, | ||
302 | loff_t *ppos) | ||
303 | { | ||
304 | int err; | ||
305 | size_t image_size; | ||
306 | uint32_t image_type; | ||
307 | uint32_t interface_type; | ||
308 | uint32_t test; | ||
309 | |||
310 | if (perf_processor_interface == ONYX_INTF) | ||
311 | image_size = PCXU_IMAGE_SIZE; | ||
312 | else if (perf_processor_interface == CUDA_INTF) | ||
313 | image_size = PCXW_IMAGE_SIZE; | ||
314 | else | ||
315 | return -EFAULT; | ||
316 | |||
317 | if (!capable(CAP_SYS_ADMIN)) | ||
318 | return -EACCES; | ||
319 | |||
320 | if (count != sizeof(uint32_t)) | ||
321 | return -EIO; | ||
322 | |||
323 | if ((err = copy_from_user(&image_type, buf, sizeof(uint32_t))) != 0) | ||
324 | return err; | ||
325 | |||
326 | /* Get the interface type and test type */ | ||
327 | interface_type = (image_type >> 16) & 0xffff; | ||
328 | test = (image_type & 0xffff); | ||
329 | |||
330 | /* Make sure everything makes sense */ | ||
331 | |||
332 | /* First check the machine type is correct for | ||
333 | the requested image */ | ||
334 | if (((perf_processor_interface == CUDA_INTF) && | ||
335 | (interface_type != CUDA_INTF)) || | ||
336 | ((perf_processor_interface == ONYX_INTF) && | ||
337 | (interface_type != ONYX_INTF))) | ||
338 | return -EINVAL; | ||
339 | |||
340 | /* Next check to make sure the requested image | ||
341 | is valid */ | ||
342 | if (((interface_type == CUDA_INTF) && | ||
343 | (test >= MAX_CUDA_IMAGES)) || | ||
344 | ((interface_type == ONYX_INTF) && | ||
345 | (test >= MAX_ONYX_IMAGES))) | ||
346 | return -EINVAL; | ||
347 | |||
348 | /* Copy the image into the processor */ | ||
349 | if (interface_type == CUDA_INTF) | ||
350 | return perf_config(cuda_images[test]); | ||
351 | else | ||
352 | return perf_config(onyx_images[test]); | ||
353 | |||
354 | return count; | ||
355 | } | ||
356 | |||
357 | /* | ||
358 | * Patch the images that need to know the IVA addresses. | ||
359 | */ | ||
360 | static void perf_patch_images(void) | ||
361 | { | ||
362 | #if 0 /* FIXME!! */ | ||
363 | /* | ||
364 | * NOTE: this routine is VERY specific to the current TLB image. | ||
365 | * If the image is changed, this routine might also need to be changed. | ||
366 | */ | ||
367 | extern void $i_itlb_miss_2_0(); | ||
368 | extern void $i_dtlb_miss_2_0(); | ||
369 | extern void PA2_0_iva(); | ||
370 | |||
371 | /* | ||
372 | * We can only use the lower 32-bits, the upper 32-bits should be 0 | ||
373 | * anyway given this is in the kernel | ||
374 | */ | ||
375 | uint32_t itlb_addr = (uint32_t)&($i_itlb_miss_2_0); | ||
376 | uint32_t dtlb_addr = (uint32_t)&($i_dtlb_miss_2_0); | ||
377 | uint32_t IVAaddress = (uint32_t)&PA2_0_iva; | ||
378 | |||
379 | if (perf_processor_interface == ONYX_INTF) { | ||
380 | /* clear last 2 bytes */ | ||
381 | onyx_images[TLBMISS][15] &= 0xffffff00; | ||
382 | /* set 2 bytes */ | ||
383 | onyx_images[TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24)); | ||
384 | onyx_images[TLBMISS][16] = (dtlb_addr << 8)&0xffffff00; | ||
385 | onyx_images[TLBMISS][17] = itlb_addr; | ||
386 | |||
387 | /* clear last 2 bytes */ | ||
388 | onyx_images[TLBHANDMISS][15] &= 0xffffff00; | ||
389 | /* set 2 bytes */ | ||
390 | onyx_images[TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24)); | ||
391 | onyx_images[TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00; | ||
392 | onyx_images[TLBHANDMISS][17] = itlb_addr; | ||
393 | |||
394 | /* clear last 2 bytes */ | ||
395 | onyx_images[BIG_CPI][15] &= 0xffffff00; | ||
396 | /* set 2 bytes */ | ||
397 | onyx_images[BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24)); | ||
398 | onyx_images[BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00; | ||
399 | onyx_images[BIG_CPI][17] = itlb_addr; | ||
400 | |||
401 | onyx_images[PANIC][15] &= 0xffffff00; /* clear last 2 bytes */ | ||
402 | onyx_images[PANIC][15] |= (0x000000ff&((IVAaddress) >> 24)); /* set 2 bytes */ | ||
403 | onyx_images[PANIC][16] = (IVAaddress << 8)&0xffffff00; | ||
404 | |||
405 | |||
406 | } else if (perf_processor_interface == CUDA_INTF) { | ||
407 | /* Cuda interface */ | ||
408 | cuda_images[TLBMISS][16] = | ||
409 | (cuda_images[TLBMISS][16]&0xffff0000) | | ||
410 | ((dtlb_addr >> 8)&0x0000ffff); | ||
411 | cuda_images[TLBMISS][17] = | ||
412 | ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); | ||
413 | cuda_images[TLBMISS][18] = (itlb_addr << 16)&0xffff0000; | ||
414 | |||
415 | cuda_images[TLBHANDMISS][16] = | ||
416 | (cuda_images[TLBHANDMISS][16]&0xffff0000) | | ||
417 | ((dtlb_addr >> 8)&0x0000ffff); | ||
418 | cuda_images[TLBHANDMISS][17] = | ||
419 | ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); | ||
420 | cuda_images[TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000; | ||
421 | |||
422 | cuda_images[BIG_CPI][16] = | ||
423 | (cuda_images[BIG_CPI][16]&0xffff0000) | | ||
424 | ((dtlb_addr >> 8)&0x0000ffff); | ||
425 | cuda_images[BIG_CPI][17] = | ||
426 | ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); | ||
427 | cuda_images[BIG_CPI][18] = (itlb_addr << 16)&0xffff0000; | ||
428 | } else { | ||
429 | /* Unknown type */ | ||
430 | } | ||
431 | #endif | ||
432 | } | ||
433 | |||
434 | |||
435 | /* | ||
436 | * ioctl routine | ||
437 | * All routines effect the processor that they are executed on. Thus you | ||
438 | * must be running on the processor that you wish to change. | ||
439 | */ | ||
440 | |||
441 | static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
442 | unsigned long arg) | ||
443 | { | ||
444 | long error_start; | ||
445 | uint32_t raddr[4]; | ||
446 | |||
447 | switch (cmd) { | ||
448 | |||
449 | case PA_PERF_ON: | ||
450 | /* Start the counters */ | ||
451 | perf_start_counters(); | ||
452 | return 0; | ||
453 | |||
454 | case PA_PERF_OFF: | ||
455 | error_start = perf_stop_counters(raddr); | ||
456 | if (error_start != 0) { | ||
457 | printk(KERN_ERR "perf_off: perf_stop_counters = %ld\n", error_start); | ||
458 | return -EFAULT; | ||
459 | } | ||
460 | |||
461 | /* copy out the Counters */ | ||
462 | if (copy_to_user((void __user *)arg, raddr, | ||
463 | sizeof (raddr)) != 0) { | ||
464 | return -EFAULT; | ||
465 | } | ||
466 | return 0; | ||
467 | |||
468 | case PA_PERF_VERSION: | ||
469 | /* Return the version # */ | ||
470 | return put_user(PERF_VERSION, (int *)arg); | ||
471 | |||
472 | default: | ||
473 | break; | ||
474 | } | ||
475 | return -ENOTTY; | ||
476 | } | ||
477 | |||
478 | static struct file_operations perf_fops = { | ||
479 | .llseek = no_llseek, | ||
480 | .read = perf_read, | ||
481 | .write = perf_write, | ||
482 | .ioctl = perf_ioctl, | ||
483 | .open = perf_open, | ||
484 | .release = perf_release | ||
485 | }; | ||
486 | |||
487 | static struct miscdevice perf_dev = { | ||
488 | MISC_DYNAMIC_MINOR, | ||
489 | PA_PERF_DEV, | ||
490 | &perf_fops | ||
491 | }; | ||
492 | |||
493 | /* | ||
494 | * Initialize the module | ||
495 | */ | ||
496 | static int __init perf_init(void) | ||
497 | { | ||
498 | int ret; | ||
499 | |||
500 | /* Determine correct processor interface to use */ | ||
501 | bitmask_array = perf_bitmasks; | ||
502 | |||
503 | if (boot_cpu_data.cpu_type == pcxu || | ||
504 | boot_cpu_data.cpu_type == pcxu_) { | ||
505 | perf_processor_interface = ONYX_INTF; | ||
506 | } else if (boot_cpu_data.cpu_type == pcxw || | ||
507 | boot_cpu_data.cpu_type == pcxw_ || | ||
508 | boot_cpu_data.cpu_type == pcxw2 || | ||
509 | boot_cpu_data.cpu_type == mako) { | ||
510 | perf_processor_interface = CUDA_INTF; | ||
511 | if (boot_cpu_data.cpu_type == pcxw2 || | ||
512 | boot_cpu_data.cpu_type == mako) | ||
513 | bitmask_array = perf_bitmasks_piranha; | ||
514 | } else { | ||
515 | perf_processor_interface = UNKNOWN_INTF; | ||
516 | printk("Performance monitoring counters not supported on this processor\n"); | ||
517 | return -ENODEV; | ||
518 | } | ||
519 | |||
520 | ret = misc_register(&perf_dev); | ||
521 | if (ret) { | ||
522 | printk(KERN_ERR "Performance monitoring counters: " | ||
523 | "cannot register misc device.\n"); | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | /* Patch the images to match the system */ | ||
528 | perf_patch_images(); | ||
529 | |||
530 | spin_lock_init(&perf_lock); | ||
531 | |||
532 | /* TODO: this only lets us access the first cpu.. what to do for SMP? */ | ||
533 | cpu_device = cpu_data[0].dev; | ||
534 | printk("Performance monitoring counters enabled for %s\n", | ||
535 | cpu_data[0].dev->name); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | /* | ||
541 | * perf_start_counters(void) | ||
542 | * | ||
543 | * Start the counters. | ||
544 | */ | ||
545 | static void perf_start_counters(void) | ||
546 | { | ||
547 | /* Enable performance monitor counters */ | ||
548 | perf_intrigue_enable_perf_counters(); | ||
549 | } | ||
550 | |||
551 | /* | ||
552 | * perf_stop_counters | ||
553 | * | ||
554 | * Stop the performance counters and save counts | ||
555 | * in a per_processor array. | ||
556 | */ | ||
557 | static int perf_stop_counters(uint32_t *raddr) | ||
558 | { | ||
559 | uint64_t userbuf[MAX_RDR_WORDS]; | ||
560 | |||
561 | /* Disable performance counters */ | ||
562 | perf_intrigue_disable_perf_counters(); | ||
563 | |||
564 | if (perf_processor_interface == ONYX_INTF) { | ||
565 | uint64_t tmp64; | ||
566 | /* | ||
567 | * Read the counters | ||
568 | */ | ||
569 | if (!perf_rdr_read_ubuf(16, userbuf)) | ||
570 | return -13; | ||
571 | |||
572 | /* Counter0 is bits 1398 thru 1429 */ | ||
573 | tmp64 = (userbuf[21] << 22) & 0x00000000ffc00000; | ||
574 | tmp64 |= (userbuf[22] >> 42) & 0x00000000003fffff; | ||
575 | /* OR sticky0 (bit 1430) to counter0 bit 32 */ | ||
576 | tmp64 |= (userbuf[22] >> 10) & 0x0000000080000000; | ||
577 | raddr[0] = (uint32_t)tmp64; | ||
578 | |||
579 | /* Counter1 is bits 1431 thru 1462 */ | ||
580 | tmp64 = (userbuf[22] >> 9) & 0x00000000ffffffff; | ||
581 | /* OR sticky1 (bit 1463) to counter1 bit 32 */ | ||
582 | tmp64 |= (userbuf[22] << 23) & 0x0000000080000000; | ||
583 | raddr[1] = (uint32_t)tmp64; | ||
584 | |||
585 | /* Counter2 is bits 1464 thru 1495 */ | ||
586 | tmp64 = (userbuf[22] << 24) & 0x00000000ff000000; | ||
587 | tmp64 |= (userbuf[23] >> 40) & 0x0000000000ffffff; | ||
588 | /* OR sticky2 (bit 1496) to counter2 bit 32 */ | ||
589 | tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000; | ||
590 | raddr[2] = (uint32_t)tmp64; | ||
591 | |||
592 | /* Counter3 is bits 1497 thru 1528 */ | ||
593 | tmp64 = (userbuf[23] >> 7) & 0x00000000ffffffff; | ||
594 | /* OR sticky3 (bit 1529) to counter3 bit 32 */ | ||
595 | tmp64 |= (userbuf[23] << 25) & 0x0000000080000000; | ||
596 | raddr[3] = (uint32_t)tmp64; | ||
597 | |||
598 | /* | ||
599 | * Zero out the counters | ||
600 | */ | ||
601 | |||
602 | /* | ||
603 | * The counters and sticky-bits comprise the last 132 bits | ||
604 | * (1398 - 1529) of RDR16 on a U chip. We'll zero these | ||
605 | * out the easy way: zero out last 10 bits of dword 21, | ||
606 | * all of dword 22 and 58 bits (plus 6 don't care bits) of | ||
607 | * dword 23. | ||
608 | */ | ||
609 | userbuf[21] &= 0xfffffffffffffc00ul; /* 0 to last 10 bits */ | ||
610 | userbuf[22] = 0; | ||
611 | userbuf[23] = 0; | ||
612 | |||
613 | /* | ||
614 | * Write back the zero'ed bytes + the image given | ||
615 | * the read was destructive. | ||
616 | */ | ||
617 | perf_rdr_write(16, userbuf); | ||
618 | } else { | ||
619 | |||
620 | /* | ||
621 | * Read RDR-15 which contains the counters and sticky bits | ||
622 | */ | ||
623 | if (!perf_rdr_read_ubuf(15, userbuf)) { | ||
624 | return -13; | ||
625 | } | ||
626 | |||
627 | /* | ||
628 | * Clear out the counters | ||
629 | */ | ||
630 | perf_rdr_clear(15); | ||
631 | |||
632 | /* | ||
633 | * Copy the counters | ||
634 | */ | ||
635 | raddr[0] = (uint32_t)((userbuf[0] >> 32) & 0x00000000ffffffffUL); | ||
636 | raddr[1] = (uint32_t)(userbuf[0] & 0x00000000ffffffffUL); | ||
637 | raddr[2] = (uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffffUL); | ||
638 | raddr[3] = (uint32_t)(userbuf[1] & 0x00000000ffffffffUL); | ||
639 | } | ||
640 | |||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | /* | ||
645 | * perf_rdr_get_entry | ||
646 | * | ||
647 | * Retrieve a pointer to the description of what this | ||
648 | * RDR contains. | ||
649 | */ | ||
650 | static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num) | ||
651 | { | ||
652 | if (perf_processor_interface == ONYX_INTF) { | ||
653 | return &perf_rdr_tbl_U[rdr_num]; | ||
654 | } else { | ||
655 | return &perf_rdr_tbl_W[rdr_num]; | ||
656 | } | ||
657 | } | ||
658 | |||
659 | /* | ||
660 | * perf_rdr_read_ubuf | ||
661 | * | ||
662 | * Read the RDR value into the buffer specified. | ||
663 | */ | ||
664 | static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer) | ||
665 | { | ||
666 | uint64_t data, data_mask = 0; | ||
667 | uint32_t width, xbits, i; | ||
668 | struct rdr_tbl_ent *tentry; | ||
669 | |||
670 | tentry = perf_rdr_get_entry(rdr_num); | ||
671 | if ((width = tentry->width) == 0) | ||
672 | return 0; | ||
673 | |||
674 | /* Clear out buffer */ | ||
675 | i = tentry->num_words; | ||
676 | while (i--) { | ||
677 | buffer[i] = 0; | ||
678 | } | ||
679 | |||
680 | /* Check for bits an even number of 64 */ | ||
681 | if ((xbits = width & 0x03f) != 0) { | ||
682 | data_mask = 1; | ||
683 | data_mask <<= (64 - xbits); | ||
684 | data_mask--; | ||
685 | } | ||
686 | |||
687 | /* Grab all of the data */ | ||
688 | i = tentry->num_words; | ||
689 | while (i--) { | ||
690 | |||
691 | if (perf_processor_interface == ONYX_INTF) { | ||
692 | data = perf_rdr_shift_in_U(rdr_num, width); | ||
693 | } else { | ||
694 | data = perf_rdr_shift_in_W(rdr_num, width); | ||
695 | } | ||
696 | if (xbits) { | ||
697 | buffer[i] |= (data << (64 - xbits)); | ||
698 | if (i) { | ||
699 | buffer[i-1] |= ((data >> xbits) & data_mask); | ||
700 | } | ||
701 | } else { | ||
702 | buffer[i] = data; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | return 1; | ||
707 | } | ||
708 | |||
709 | /* | ||
710 | * perf_rdr_clear | ||
711 | * | ||
712 | * Zero out the given RDR register | ||
713 | */ | ||
714 | static int perf_rdr_clear(uint32_t rdr_num) | ||
715 | { | ||
716 | struct rdr_tbl_ent *tentry; | ||
717 | int32_t i; | ||
718 | |||
719 | tentry = perf_rdr_get_entry(rdr_num); | ||
720 | |||
721 | if (tentry->width == 0) { | ||
722 | return -1; | ||
723 | } | ||
724 | |||
725 | i = tentry->num_words; | ||
726 | while (i--) { | ||
727 | if (perf_processor_interface == ONYX_INTF) { | ||
728 | perf_rdr_shift_out_U(rdr_num, 0UL); | ||
729 | } else { | ||
730 | perf_rdr_shift_out_W(rdr_num, 0UL); | ||
731 | } | ||
732 | } | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | |||
738 | /* | ||
739 | * perf_write_image | ||
740 | * | ||
741 | * Write the given image out to the processor | ||
742 | */ | ||
743 | static int perf_write_image(uint64_t *memaddr) | ||
744 | { | ||
745 | uint64_t buffer[MAX_RDR_WORDS]; | ||
746 | uint64_t *bptr; | ||
747 | uint32_t dwords; | ||
748 | uint32_t *intrigue_rdr; | ||
749 | uint64_t *intrigue_bitmask, tmp64, proc_hpa; | ||
750 | struct rdr_tbl_ent *tentry; | ||
751 | int i; | ||
752 | |||
753 | /* Clear out counters */ | ||
754 | if (perf_processor_interface == ONYX_INTF) { | ||
755 | |||
756 | perf_rdr_clear(16); | ||
757 | |||
758 | /* Toggle performance monitor */ | ||
759 | perf_intrigue_enable_perf_counters(); | ||
760 | perf_intrigue_disable_perf_counters(); | ||
761 | |||
762 | intrigue_rdr = perf_rdrs_U; | ||
763 | } else { | ||
764 | perf_rdr_clear(15); | ||
765 | intrigue_rdr = perf_rdrs_W; | ||
766 | } | ||
767 | |||
768 | /* Write all RDRs */ | ||
769 | while (*intrigue_rdr != -1) { | ||
770 | tentry = perf_rdr_get_entry(*intrigue_rdr); | ||
771 | perf_rdr_read_ubuf(*intrigue_rdr, buffer); | ||
772 | bptr = &buffer[0]; | ||
773 | dwords = tentry->num_words; | ||
774 | if (tentry->write_control) { | ||
775 | intrigue_bitmask = &bitmask_array[tentry->write_control >> 3]; | ||
776 | while (dwords--) { | ||
777 | tmp64 = *intrigue_bitmask & *memaddr++; | ||
778 | tmp64 |= (~(*intrigue_bitmask++)) & *bptr; | ||
779 | *bptr++ = tmp64; | ||
780 | } | ||
781 | } else { | ||
782 | while (dwords--) { | ||
783 | *bptr++ = *memaddr++; | ||
784 | } | ||
785 | } | ||
786 | |||
787 | perf_rdr_write(*intrigue_rdr, buffer); | ||
788 | intrigue_rdr++; | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * Now copy out the Runway stuff which is not in RDRs | ||
793 | */ | ||
794 | |||
795 | if (cpu_device == NULL) | ||
796 | { | ||
797 | printk(KERN_ERR "write_image: cpu_device not yet initialized!\n"); | ||
798 | return -1; | ||
799 | } | ||
800 | |||
801 | proc_hpa = cpu_device->hpa; | ||
802 | |||
803 | /* Merge intrigue bits into Runway STATUS 0 */ | ||
804 | tmp64 = __raw_readq(proc_hpa + RUNWAY_STATUS) & 0xffecfffffffffffful; | ||
805 | __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), proc_hpa + RUNWAY_STATUS); | ||
806 | |||
807 | /* Write RUNWAY DEBUG registers */ | ||
808 | for (i = 0; i < 8; i++) { | ||
809 | __raw_writeq(*memaddr++, proc_hpa + RUNWAY_DEBUG + i); | ||
810 | } | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | /* | ||
816 | * perf_rdr_write | ||
817 | * | ||
818 | * Write the given RDR register with the contents | ||
819 | * of the given buffer. | ||
820 | */ | ||
821 | static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer) | ||
822 | { | ||
823 | struct rdr_tbl_ent *tentry; | ||
824 | int32_t i; | ||
825 | |||
826 | printk("perf_rdr_write\n"); | ||
827 | tentry = perf_rdr_get_entry(rdr_num); | ||
828 | if (tentry->width == 0) { return; } | ||
829 | |||
830 | i = tentry->num_words; | ||
831 | while (i--) { | ||
832 | if (perf_processor_interface == ONYX_INTF) { | ||
833 | perf_rdr_shift_out_U(rdr_num, buffer[i]); | ||
834 | } else { | ||
835 | perf_rdr_shift_out_W(rdr_num, buffer[i]); | ||
836 | } | ||
837 | } | ||
838 | printk("perf_rdr_write done\n"); | ||
839 | } | ||
840 | |||
841 | module_init(perf_init); | ||
diff --git a/arch/parisc/kernel/perf_asm.S b/arch/parisc/kernel/perf_asm.S new file mode 100644 index 000000000000..adb3c6444910 --- /dev/null +++ b/arch/parisc/kernel/perf_asm.S | |||
@@ -0,0 +1,1691 @@ | |||
1 | |||
2 | /* low-level asm for "intrigue" (PA8500-8700 CPU perf counters) | ||
3 | * | ||
4 | * Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org> | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Grant Grundler) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | #include <asm/assembly.h> | ||
24 | |||
25 | #ifdef CONFIG_64BIT | ||
26 | .level 2.0w | ||
27 | #endif /* CONFIG_64BIT */ | ||
28 | |||
29 | #define MTDIAG_1(gr) .word 0x14201840 + gr*0x10000 | ||
30 | #define MTDIAG_2(gr) .word 0x14401840 + gr*0x10000 | ||
31 | #define MFDIAG_1(gr) .word 0x142008A0 + gr | ||
32 | #define MFDIAG_2(gr) .word 0x144008A0 + gr | ||
33 | #define STDIAG(dr) .word 0x14000AA0 + dr*0x200000 | ||
34 | #define SFDIAG(dr) .word 0x14000BA0 + dr*0x200000 | ||
35 | #define DR2_SLOW_RET 53 | ||
36 | |||
37 | |||
38 | ; | ||
39 | ; Enable the performance counters | ||
40 | ; | ||
41 | ; The coprocessor only needs to be enabled when | ||
42 | ; starting/stopping the coprocessor with the pmenb/pmdis. | ||
43 | ; | ||
44 | .text | ||
45 | .align 32 | ||
46 | |||
47 | .export perf_intrigue_enable_perf_counters,code | ||
48 | perf_intrigue_enable_perf_counters: | ||
49 | .proc | ||
50 | .callinfo frame=0,NO_CALLS | ||
51 | .entry | ||
52 | |||
53 | ldi 0x20,%r25 ; load up perfmon bit | ||
54 | mfctl ccr,%r26 ; get coprocessor register | ||
55 | or %r25,%r26,%r26 ; set bit | ||
56 | mtctl %r26,ccr ; turn on performance coprocessor | ||
57 | pmenb ; enable performance monitor | ||
58 | ssm 0,0 ; dummy op to ensure completion | ||
59 | sync ; follow ERS | ||
60 | andcm %r26,%r25,%r26 ; clear bit now | ||
61 | mtctl %r26,ccr ; turn off performance coprocessor | ||
62 | nop ; NOPs as specified in ERS | ||
63 | nop | ||
64 | nop | ||
65 | nop | ||
66 | nop | ||
67 | nop | ||
68 | nop | ||
69 | bve (%r2) | ||
70 | nop | ||
71 | .exit | ||
72 | .procend | ||
73 | |||
74 | .export perf_intrigue_disable_perf_counters,code | ||
75 | perf_intrigue_disable_perf_counters: | ||
76 | .proc | ||
77 | .callinfo frame=0,NO_CALLS | ||
78 | .entry | ||
79 | ldi 0x20,%r25 ; load up perfmon bit | ||
80 | mfctl ccr,%r26 ; get coprocessor register | ||
81 | or %r25,%r26,%r26 ; set bit | ||
82 | mtctl %r26,ccr ; turn on performance coprocessor | ||
83 | pmdis ; disable performance monitor | ||
84 | ssm 0,0 ; dummy op to ensure completion | ||
85 | andcm %r26,%r25,%r26 ; clear bit now | ||
86 | bve (%r2) | ||
87 | mtctl %r26,ccr ; turn off performance coprocessor | ||
88 | .exit | ||
89 | .procend | ||
90 | |||
91 | ;*********************************************************************** | ||
92 | ;* | ||
93 | ;* Name: perf_rdr_shift_in_W | ||
94 | ;* | ||
95 | ;* Description: | ||
96 | ;* This routine shifts data in from the RDR in arg0 and returns | ||
97 | ;* the result in ret0. If the RDR is <= 64 bits in length, it | ||
98 | ;* is shifted shifted backup immediately. This is to compensate | ||
99 | ;* for RDR10 which has bits that preclude PDC stack operations | ||
100 | ;* when they are in the wrong state. | ||
101 | ;* | ||
102 | ;* Arguments: | ||
103 | ;* arg0 : rdr to be read | ||
104 | ;* arg1 : bit length of rdr | ||
105 | ;* | ||
106 | ;* Returns: | ||
107 | ;* ret0 = next 64 bits of rdr data from staging register | ||
108 | ;* | ||
109 | ;* Register usage: | ||
110 | ;* arg0 : rdr to be read | ||
111 | ;* arg1 : bit length of rdr | ||
112 | ;* %r24 - original DR2 value | ||
113 | ;* %r1 - scratch | ||
114 | ;* %r29 - scratch | ||
115 | ;* | ||
116 | ;* Returns: | ||
117 | ;* ret0 = RDR data (right justified) | ||
118 | ;* | ||
119 | ;*********************************************************************** | ||
120 | |||
121 | .export perf_rdr_shift_in_W,code | ||
122 | perf_rdr_shift_in_W: | ||
123 | .proc | ||
124 | .callinfo frame=0,NO_CALLS | ||
125 | .entry | ||
126 | ; | ||
127 | ; read(shift in) the RDR. | ||
128 | ; | ||
129 | |||
130 | ; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any | ||
131 | ; shifting is done, from or to, remote diagnose registers. | ||
132 | ; | ||
133 | |||
134 | depdi,z 1,DR2_SLOW_RET,1,%r29 | ||
135 | MFDIAG_2 (24) | ||
136 | or %r24,%r29,%r29 | ||
137 | MTDIAG_2 (29) ; set DR2_SLOW_RET | ||
138 | |||
139 | nop | ||
140 | nop | ||
141 | nop | ||
142 | nop | ||
143 | |||
144 | ; | ||
145 | ; Cacheline start (32-byte cacheline) | ||
146 | ; | ||
147 | nop | ||
148 | nop | ||
149 | nop | ||
150 | extrd,u arg1,63,6,%r1 ; setup shift amount by bits to move | ||
151 | |||
152 | mtsar %r1 | ||
153 | shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number | ||
154 | blr %r1,%r0 ; branch to 8-instruction sequence | ||
155 | nop | ||
156 | |||
157 | ; | ||
158 | ; Cacheline start (32-byte cacheline) | ||
159 | ; | ||
160 | |||
161 | ; | ||
162 | ; RDR 0 sequence | ||
163 | ; | ||
164 | SFDIAG (0) | ||
165 | ssm 0,0 | ||
166 | MFDIAG_1 (28) | ||
167 | shrpd ret0,%r0,%sar,%r1 | ||
168 | MTDIAG_1 (1) ; mtdiag %dr1, %r1 | ||
169 | STDIAG (0) | ||
170 | ssm 0,0 | ||
171 | b,n perf_rdr_shift_in_W_leave | ||
172 | |||
173 | ; | ||
174 | ; RDR 1 sequence | ||
175 | ; | ||
176 | sync | ||
177 | ssm 0,0 | ||
178 | SFDIAG (1) | ||
179 | ssm 0,0 | ||
180 | MFDIAG_1 (28) | ||
181 | ssm 0,0 | ||
182 | b,n perf_rdr_shift_in_W_leave | ||
183 | nop | ||
184 | |||
185 | ; | ||
186 | ; RDR 2 read sequence | ||
187 | ; | ||
188 | SFDIAG (2) | ||
189 | ssm 0,0 | ||
190 | MFDIAG_1 (28) | ||
191 | shrpd ret0,%r0,%sar,%r1 | ||
192 | MTDIAG_1 (1) | ||
193 | STDIAG (2) | ||
194 | ssm 0,0 | ||
195 | b,n perf_rdr_shift_in_W_leave | ||
196 | |||
197 | ; | ||
198 | ; RDR 3 read sequence | ||
199 | ; | ||
200 | b,n perf_rdr_shift_in_W_leave | ||
201 | nop | ||
202 | nop | ||
203 | nop | ||
204 | nop | ||
205 | nop | ||
206 | nop | ||
207 | nop | ||
208 | |||
209 | ; | ||
210 | ; RDR 4 read sequence | ||
211 | ; | ||
212 | sync | ||
213 | ssm 0,0 | ||
214 | SFDIAG (4) | ||
215 | ssm 0,0 | ||
216 | MFDIAG_1 (28) | ||
217 | b,n perf_rdr_shift_in_W_leave | ||
218 | ssm 0,0 | ||
219 | nop | ||
220 | |||
221 | ; | ||
222 | ; RDR 5 read sequence | ||
223 | ; | ||
224 | sync | ||
225 | ssm 0,0 | ||
226 | SFDIAG (5) | ||
227 | ssm 0,0 | ||
228 | MFDIAG_1 (28) | ||
229 | b,n perf_rdr_shift_in_W_leave | ||
230 | ssm 0,0 | ||
231 | nop | ||
232 | |||
233 | ; | ||
234 | ; RDR 6 read sequence | ||
235 | ; | ||
236 | sync | ||
237 | ssm 0,0 | ||
238 | SFDIAG (6) | ||
239 | ssm 0,0 | ||
240 | MFDIAG_1 (28) | ||
241 | b,n perf_rdr_shift_in_W_leave | ||
242 | ssm 0,0 | ||
243 | nop | ||
244 | |||
245 | ; | ||
246 | ; RDR 7 read sequence | ||
247 | ; | ||
248 | b,n perf_rdr_shift_in_W_leave | ||
249 | nop | ||
250 | nop | ||
251 | nop | ||
252 | nop | ||
253 | nop | ||
254 | nop | ||
255 | nop | ||
256 | |||
257 | ; | ||
258 | ; RDR 8 read sequence | ||
259 | ; | ||
260 | b,n perf_rdr_shift_in_W_leave | ||
261 | nop | ||
262 | nop | ||
263 | nop | ||
264 | nop | ||
265 | nop | ||
266 | nop | ||
267 | nop | ||
268 | |||
269 | ; | ||
270 | ; RDR 9 read sequence | ||
271 | ; | ||
272 | b,n perf_rdr_shift_in_W_leave | ||
273 | nop | ||
274 | nop | ||
275 | nop | ||
276 | nop | ||
277 | nop | ||
278 | nop | ||
279 | nop | ||
280 | |||
281 | ; | ||
282 | ; RDR 10 read sequence | ||
283 | ; | ||
284 | SFDIAG (10) | ||
285 | ssm 0,0 | ||
286 | MFDIAG_1 (28) | ||
287 | shrpd ret0,%r0,%sar,%r1 | ||
288 | MTDIAG_1 (1) | ||
289 | STDIAG (10) | ||
290 | ssm 0,0 | ||
291 | b,n perf_rdr_shift_in_W_leave | ||
292 | |||
293 | ; | ||
294 | ; RDR 11 read sequence | ||
295 | ; | ||
296 | SFDIAG (11) | ||
297 | ssm 0,0 | ||
298 | MFDIAG_1 (28) | ||
299 | shrpd ret0,%r0,%sar,%r1 | ||
300 | MTDIAG_1 (1) | ||
301 | STDIAG (11) | ||
302 | ssm 0,0 | ||
303 | b,n perf_rdr_shift_in_W_leave | ||
304 | |||
305 | ; | ||
306 | ; RDR 12 read sequence | ||
307 | ; | ||
308 | b,n perf_rdr_shift_in_W_leave | ||
309 | nop | ||
310 | nop | ||
311 | nop | ||
312 | nop | ||
313 | nop | ||
314 | nop | ||
315 | nop | ||
316 | |||
317 | ; | ||
318 | ; RDR 13 read sequence | ||
319 | ; | ||
320 | sync | ||
321 | ssm 0,0 | ||
322 | SFDIAG (13) | ||
323 | ssm 0,0 | ||
324 | MFDIAG_1 (28) | ||
325 | b,n perf_rdr_shift_in_W_leave | ||
326 | ssm 0,0 | ||
327 | nop | ||
328 | |||
329 | ; | ||
330 | ; RDR 14 read sequence | ||
331 | ; | ||
332 | SFDIAG (14) | ||
333 | ssm 0,0 | ||
334 | MFDIAG_1 (28) | ||
335 | shrpd ret0,%r0,%sar,%r1 | ||
336 | MTDIAG_1 (1) | ||
337 | STDIAG (14) | ||
338 | ssm 0,0 | ||
339 | b,n perf_rdr_shift_in_W_leave | ||
340 | |||
341 | ; | ||
342 | ; RDR 15 read sequence | ||
343 | ; | ||
344 | sync | ||
345 | ssm 0,0 | ||
346 | SFDIAG (15) | ||
347 | ssm 0,0 | ||
348 | MFDIAG_1 (28) | ||
349 | ssm 0,0 | ||
350 | b,n perf_rdr_shift_in_W_leave | ||
351 | nop | ||
352 | |||
353 | ; | ||
354 | ; RDR 16 read sequence | ||
355 | ; | ||
356 | sync | ||
357 | ssm 0,0 | ||
358 | SFDIAG (16) | ||
359 | ssm 0,0 | ||
360 | MFDIAG_1 (28) | ||
361 | b,n perf_rdr_shift_in_W_leave | ||
362 | ssm 0,0 | ||
363 | nop | ||
364 | |||
365 | ; | ||
366 | ; RDR 17 read sequence | ||
367 | ; | ||
368 | SFDIAG (17) | ||
369 | ssm 0,0 | ||
370 | MFDIAG_1 (28) | ||
371 | shrpd ret0,%r0,%sar,%r1 | ||
372 | MTDIAG_1 (1) | ||
373 | STDIAG (17) | ||
374 | ssm 0,0 | ||
375 | b,n perf_rdr_shift_in_W_leave | ||
376 | |||
377 | ; | ||
378 | ; RDR 18 read sequence | ||
379 | ; | ||
380 | SFDIAG (18) | ||
381 | ssm 0,0 | ||
382 | MFDIAG_1 (28) | ||
383 | shrpd ret0,%r0,%sar,%r1 | ||
384 | MTDIAG_1 (1) | ||
385 | STDIAG (18) | ||
386 | ssm 0,0 | ||
387 | b,n perf_rdr_shift_in_W_leave | ||
388 | |||
389 | ; | ||
390 | ; RDR 19 read sequence | ||
391 | ; | ||
392 | b,n perf_rdr_shift_in_W_leave | ||
393 | nop | ||
394 | nop | ||
395 | nop | ||
396 | nop | ||
397 | nop | ||
398 | nop | ||
399 | nop | ||
400 | |||
401 | ; | ||
402 | ; RDR 20 read sequence | ||
403 | ; | ||
404 | sync | ||
405 | ssm 0,0 | ||
406 | SFDIAG (20) | ||
407 | ssm 0,0 | ||
408 | MFDIAG_1 (28) | ||
409 | b,n perf_rdr_shift_in_W_leave | ||
410 | ssm 0,0 | ||
411 | nop | ||
412 | |||
413 | ; | ||
414 | ; RDR 21 read sequence | ||
415 | ; | ||
416 | sync | ||
417 | ssm 0,0 | ||
418 | SFDIAG (21) | ||
419 | ssm 0,0 | ||
420 | MFDIAG_1 (28) | ||
421 | b,n perf_rdr_shift_in_W_leave | ||
422 | ssm 0,0 | ||
423 | nop | ||
424 | |||
425 | ; | ||
426 | ; RDR 22 read sequence | ||
427 | ; | ||
428 | sync | ||
429 | ssm 0,0 | ||
430 | SFDIAG (22) | ||
431 | ssm 0,0 | ||
432 | MFDIAG_1 (28) | ||
433 | b,n perf_rdr_shift_in_W_leave | ||
434 | ssm 0,0 | ||
435 | nop | ||
436 | |||
437 | ; | ||
438 | ; RDR 23 read sequence | ||
439 | ; | ||
440 | sync | ||
441 | ssm 0,0 | ||
442 | SFDIAG (23) | ||
443 | ssm 0,0 | ||
444 | MFDIAG_1 (28) | ||
445 | b,n perf_rdr_shift_in_W_leave | ||
446 | ssm 0,0 | ||
447 | nop | ||
448 | |||
449 | ; | ||
450 | ; RDR 24 read sequence | ||
451 | ; | ||
452 | sync | ||
453 | ssm 0,0 | ||
454 | SFDIAG (24) | ||
455 | ssm 0,0 | ||
456 | MFDIAG_1 (28) | ||
457 | b,n perf_rdr_shift_in_W_leave | ||
458 | ssm 0,0 | ||
459 | nop | ||
460 | |||
461 | ; | ||
462 | ; RDR 25 read sequence | ||
463 | ; | ||
464 | sync | ||
465 | ssm 0,0 | ||
466 | SFDIAG (25) | ||
467 | ssm 0,0 | ||
468 | MFDIAG_1 (28) | ||
469 | b,n perf_rdr_shift_in_W_leave | ||
470 | ssm 0,0 | ||
471 | nop | ||
472 | |||
473 | ; | ||
474 | ; RDR 26 read sequence | ||
475 | ; | ||
476 | SFDIAG (26) | ||
477 | ssm 0,0 | ||
478 | MFDIAG_1 (28) | ||
479 | shrpd ret0,%r0,%sar,%r1 | ||
480 | MTDIAG_1 (1) | ||
481 | STDIAG (26) | ||
482 | ssm 0,0 | ||
483 | b,n perf_rdr_shift_in_W_leave | ||
484 | |||
485 | ; | ||
486 | ; RDR 27 read sequence | ||
487 | ; | ||
488 | SFDIAG (27) | ||
489 | ssm 0,0 | ||
490 | MFDIAG_1 (28) | ||
491 | shrpd ret0,%r0,%sar,%r1 | ||
492 | MTDIAG_1 (1) | ||
493 | STDIAG (27) | ||
494 | ssm 0,0 | ||
495 | b,n perf_rdr_shift_in_W_leave | ||
496 | |||
497 | ; | ||
498 | ; RDR 28 read sequence | ||
499 | ; | ||
500 | sync | ||
501 | ssm 0,0 | ||
502 | SFDIAG (28) | ||
503 | ssm 0,0 | ||
504 | MFDIAG_1 (28) | ||
505 | b,n perf_rdr_shift_in_W_leave | ||
506 | ssm 0,0 | ||
507 | nop | ||
508 | |||
509 | ; | ||
510 | ; RDR 29 read sequence | ||
511 | ; | ||
512 | sync | ||
513 | ssm 0,0 | ||
514 | SFDIAG (29) | ||
515 | ssm 0,0 | ||
516 | MFDIAG_1 (28) | ||
517 | b,n perf_rdr_shift_in_W_leave | ||
518 | ssm 0,0 | ||
519 | nop | ||
520 | |||
521 | ; | ||
522 | ; RDR 30 read sequence | ||
523 | ; | ||
524 | SFDIAG (30) | ||
525 | ssm 0,0 | ||
526 | MFDIAG_1 (28) | ||
527 | shrpd ret0,%r0,%sar,%r1 | ||
528 | MTDIAG_1 (1) | ||
529 | STDIAG (30) | ||
530 | ssm 0,0 | ||
531 | b,n perf_rdr_shift_in_W_leave | ||
532 | |||
533 | ; | ||
534 | ; RDR 31 read sequence | ||
535 | ; | ||
536 | sync | ||
537 | ssm 0,0 | ||
538 | SFDIAG (31) | ||
539 | ssm 0,0 | ||
540 | MFDIAG_1 (28) | ||
541 | nop | ||
542 | ssm 0,0 | ||
543 | nop | ||
544 | |||
545 | ; | ||
546 | ; Fallthrough | ||
547 | ; | ||
548 | |||
549 | perf_rdr_shift_in_W_leave: | ||
550 | bve (%r2) | ||
551 | .exit | ||
552 | MTDIAG_2 (24) ; restore DR2 | ||
553 | .procend | ||
554 | |||
555 | |||
556 | ;*********************************************************************** | ||
557 | ;* | ||
558 | ;* Name: perf_rdr_shift_out_W | ||
559 | ;* | ||
560 | ;* Description: | ||
561 | ;* This routine moves data to the RDR's. The double-word that | ||
562 | ;* arg1 points to is loaded and moved into the staging register. | ||
563 | ;* Then the STDIAG instruction for the RDR # in arg0 is called | ||
564 | ;* to move the data to the RDR. | ||
565 | ;* | ||
566 | ;* Arguments: | ||
567 | ;* arg0 = rdr number | ||
568 | ;* arg1 = 64-bit value to write | ||
569 | ;* %r24 - DR2 | DR2_SLOW_RET | ||
570 | ;* %r23 - original DR2 value | ||
571 | ;* | ||
572 | ;* Returns: | ||
573 | ;* None | ||
574 | ;* | ||
575 | ;* Register usage: | ||
576 | ;* | ||
577 | ;*********************************************************************** | ||
578 | |||
579 | .export perf_rdr_shift_out_W,code | ||
580 | perf_rdr_shift_out_W: | ||
581 | .proc | ||
582 | .callinfo frame=0,NO_CALLS | ||
583 | .entry | ||
584 | ; | ||
585 | ; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any | ||
586 | ; shifting is done, from or to, the remote diagnose registers. | ||
587 | ; | ||
588 | |||
589 | depdi,z 1,DR2_SLOW_RET,1,%r24 | ||
590 | MFDIAG_2 (23) | ||
591 | or %r24,%r23,%r24 | ||
592 | MTDIAG_2 (24) ; set DR2_SLOW_RET | ||
593 | MTDIAG_1 (25) ; data to the staging register | ||
594 | shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number | ||
595 | blr %r1,%r0 ; branch to 8-instruction sequence | ||
596 | nop | ||
597 | |||
598 | ; | ||
599 | ; RDR 0 write sequence | ||
600 | ; | ||
601 | sync ; RDR 0 write sequence | ||
602 | ssm 0,0 | ||
603 | STDIAG (0) | ||
604 | ssm 0,0 | ||
605 | b,n perf_rdr_shift_out_W_leave | ||
606 | nop | ||
607 | ssm 0,0 | ||
608 | nop | ||
609 | |||
610 | ; | ||
611 | ; RDR 1 write sequence | ||
612 | ; | ||
613 | sync | ||
614 | ssm 0,0 | ||
615 | STDIAG (1) | ||
616 | ssm 0,0 | ||
617 | b,n perf_rdr_shift_out_W_leave | ||
618 | nop | ||
619 | ssm 0,0 | ||
620 | nop | ||
621 | |||
622 | ; | ||
623 | ; RDR 2 write sequence | ||
624 | ; | ||
625 | sync | ||
626 | ssm 0,0 | ||
627 | STDIAG (2) | ||
628 | ssm 0,0 | ||
629 | b,n perf_rdr_shift_out_W_leave | ||
630 | nop | ||
631 | ssm 0,0 | ||
632 | nop | ||
633 | |||
634 | ; | ||
635 | ; RDR 3 write sequence | ||
636 | ; | ||
637 | sync | ||
638 | ssm 0,0 | ||
639 | STDIAG (3) | ||
640 | ssm 0,0 | ||
641 | b,n perf_rdr_shift_out_W_leave | ||
642 | nop | ||
643 | ssm 0,0 | ||
644 | nop | ||
645 | |||
646 | ; | ||
647 | ; RDR 4 write sequence | ||
648 | ; | ||
649 | sync | ||
650 | ssm 0,0 | ||
651 | STDIAG (4) | ||
652 | ssm 0,0 | ||
653 | b,n perf_rdr_shift_out_W_leave | ||
654 | nop | ||
655 | ssm 0,0 | ||
656 | nop | ||
657 | |||
658 | ; | ||
659 | ; RDR 5 write sequence | ||
660 | ; | ||
661 | sync | ||
662 | ssm 0,0 | ||
663 | STDIAG (5) | ||
664 | ssm 0,0 | ||
665 | b,n perf_rdr_shift_out_W_leave | ||
666 | nop | ||
667 | ssm 0,0 | ||
668 | nop | ||
669 | |||
670 | ; | ||
671 | ; RDR 6 write sequence | ||
672 | ; | ||
673 | sync | ||
674 | ssm 0,0 | ||
675 | STDIAG (6) | ||
676 | ssm 0,0 | ||
677 | b,n perf_rdr_shift_out_W_leave | ||
678 | nop | ||
679 | ssm 0,0 | ||
680 | nop | ||
681 | |||
682 | ; | ||
683 | ; RDR 7 write sequence | ||
684 | ; | ||
685 | sync | ||
686 | ssm 0,0 | ||
687 | STDIAG (7) | ||
688 | ssm 0,0 | ||
689 | b,n perf_rdr_shift_out_W_leave | ||
690 | nop | ||
691 | ssm 0,0 | ||
692 | nop | ||
693 | |||
694 | ; | ||
695 | ; RDR 8 write sequence | ||
696 | ; | ||
697 | sync | ||
698 | ssm 0,0 | ||
699 | STDIAG (8) | ||
700 | ssm 0,0 | ||
701 | b,n perf_rdr_shift_out_W_leave | ||
702 | nop | ||
703 | ssm 0,0 | ||
704 | nop | ||
705 | |||
706 | ; | ||
707 | ; RDR 9 write sequence | ||
708 | ; | ||
709 | sync | ||
710 | ssm 0,0 | ||
711 | STDIAG (9) | ||
712 | ssm 0,0 | ||
713 | b,n perf_rdr_shift_out_W_leave | ||
714 | nop | ||
715 | ssm 0,0 | ||
716 | nop | ||
717 | |||
718 | ; | ||
719 | ; RDR 10 write sequence | ||
720 | ; | ||
721 | sync | ||
722 | ssm 0,0 | ||
723 | STDIAG (10) | ||
724 | STDIAG (26) | ||
725 | ssm 0,0 | ||
726 | b,n perf_rdr_shift_out_W_leave | ||
727 | ssm 0,0 | ||
728 | nop | ||
729 | |||
730 | ; | ||
731 | ; RDR 11 write sequence | ||
732 | ; | ||
733 | sync | ||
734 | ssm 0,0 | ||
735 | STDIAG (11) | ||
736 | STDIAG (27) | ||
737 | ssm 0,0 | ||
738 | b,n perf_rdr_shift_out_W_leave | ||
739 | ssm 0,0 | ||
740 | nop | ||
741 | |||
742 | ; | ||
743 | ; RDR 12 write sequence | ||
744 | ; | ||
745 | sync | ||
746 | ssm 0,0 | ||
747 | STDIAG (12) | ||
748 | ssm 0,0 | ||
749 | b,n perf_rdr_shift_out_W_leave | ||
750 | nop | ||
751 | ssm 0,0 | ||
752 | nop | ||
753 | |||
754 | ; | ||
755 | ; RDR 13 write sequence | ||
756 | ; | ||
757 | sync | ||
758 | ssm 0,0 | ||
759 | STDIAG (13) | ||
760 | ssm 0,0 | ||
761 | b,n perf_rdr_shift_out_W_leave | ||
762 | nop | ||
763 | ssm 0,0 | ||
764 | nop | ||
765 | |||
766 | ; | ||
767 | ; RDR 14 write sequence | ||
768 | ; | ||
769 | sync | ||
770 | ssm 0,0 | ||
771 | STDIAG (14) | ||
772 | ssm 0,0 | ||
773 | b,n perf_rdr_shift_out_W_leave | ||
774 | nop | ||
775 | ssm 0,0 | ||
776 | nop | ||
777 | |||
778 | ; | ||
779 | ; RDR 15 write sequence | ||
780 | ; | ||
781 | sync | ||
782 | ssm 0,0 | ||
783 | STDIAG (15) | ||
784 | ssm 0,0 | ||
785 | b,n perf_rdr_shift_out_W_leave | ||
786 | nop | ||
787 | ssm 0,0 | ||
788 | nop | ||
789 | |||
790 | ; | ||
791 | ; RDR 16 write sequence | ||
792 | ; | ||
793 | sync | ||
794 | ssm 0,0 | ||
795 | STDIAG (16) | ||
796 | ssm 0,0 | ||
797 | b,n perf_rdr_shift_out_W_leave | ||
798 | nop | ||
799 | ssm 0,0 | ||
800 | nop | ||
801 | |||
802 | ; | ||
803 | ; RDR 17 write sequence | ||
804 | ; | ||
805 | sync | ||
806 | ssm 0,0 | ||
807 | STDIAG (17) | ||
808 | ssm 0,0 | ||
809 | b,n perf_rdr_shift_out_W_leave | ||
810 | nop | ||
811 | ssm 0,0 | ||
812 | nop | ||
813 | |||
814 | ; | ||
815 | ; RDR 18 write sequence | ||
816 | ; | ||
817 | sync | ||
818 | ssm 0,0 | ||
819 | STDIAG (18) | ||
820 | ssm 0,0 | ||
821 | b,n perf_rdr_shift_out_W_leave | ||
822 | nop | ||
823 | ssm 0,0 | ||
824 | nop | ||
825 | |||
826 | ; | ||
827 | ; RDR 19 write sequence | ||
828 | ; | ||
829 | sync | ||
830 | ssm 0,0 | ||
831 | STDIAG (19) | ||
832 | ssm 0,0 | ||
833 | b,n perf_rdr_shift_out_W_leave | ||
834 | nop | ||
835 | ssm 0,0 | ||
836 | nop | ||
837 | |||
838 | ; | ||
839 | ; RDR 20 write sequence | ||
840 | ; | ||
841 | sync | ||
842 | ssm 0,0 | ||
843 | STDIAG (20) | ||
844 | ssm 0,0 | ||
845 | b,n perf_rdr_shift_out_W_leave | ||
846 | nop | ||
847 | ssm 0,0 | ||
848 | nop | ||
849 | |||
850 | ; | ||
851 | ; RDR 21 write sequence | ||
852 | ; | ||
853 | sync | ||
854 | ssm 0,0 | ||
855 | STDIAG (21) | ||
856 | ssm 0,0 | ||
857 | b,n perf_rdr_shift_out_W_leave | ||
858 | nop | ||
859 | ssm 0,0 | ||
860 | nop | ||
861 | |||
862 | ; | ||
863 | ; RDR 22 write sequence | ||
864 | ; | ||
865 | sync | ||
866 | ssm 0,0 | ||
867 | STDIAG (22) | ||
868 | ssm 0,0 | ||
869 | b,n perf_rdr_shift_out_W_leave | ||
870 | nop | ||
871 | ssm 0,0 | ||
872 | nop | ||
873 | |||
874 | ; | ||
875 | ; RDR 23 write sequence | ||
876 | ; | ||
877 | sync | ||
878 | ssm 0,0 | ||
879 | STDIAG (23) | ||
880 | ssm 0,0 | ||
881 | b,n perf_rdr_shift_out_W_leave | ||
882 | nop | ||
883 | ssm 0,0 | ||
884 | nop | ||
885 | |||
886 | ; | ||
887 | ; RDR 24 write sequence | ||
888 | ; | ||
889 | sync | ||
890 | ssm 0,0 | ||
891 | STDIAG (24) | ||
892 | ssm 0,0 | ||
893 | b,n perf_rdr_shift_out_W_leave | ||
894 | nop | ||
895 | ssm 0,0 | ||
896 | nop | ||
897 | |||
898 | ; | ||
899 | ; RDR 25 write sequence | ||
900 | ; | ||
901 | sync | ||
902 | ssm 0,0 | ||
903 | STDIAG (25) | ||
904 | ssm 0,0 | ||
905 | b,n perf_rdr_shift_out_W_leave | ||
906 | nop | ||
907 | ssm 0,0 | ||
908 | nop | ||
909 | |||
910 | ; | ||
911 | ; RDR 26 write sequence | ||
912 | ; | ||
913 | sync | ||
914 | ssm 0,0 | ||
915 | STDIAG (10) | ||
916 | STDIAG (26) | ||
917 | ssm 0,0 | ||
918 | b,n perf_rdr_shift_out_W_leave | ||
919 | ssm 0,0 | ||
920 | nop | ||
921 | |||
922 | ; | ||
923 | ; RDR 27 write sequence | ||
924 | ; | ||
925 | sync | ||
926 | ssm 0,0 | ||
927 | STDIAG (11) | ||
928 | STDIAG (27) | ||
929 | ssm 0,0 | ||
930 | b,n perf_rdr_shift_out_W_leave | ||
931 | ssm 0,0 | ||
932 | nop | ||
933 | |||
934 | ; | ||
935 | ; RDR 28 write sequence | ||
936 | ; | ||
937 | sync | ||
938 | ssm 0,0 | ||
939 | STDIAG (28) | ||
940 | ssm 0,0 | ||
941 | b,n perf_rdr_shift_out_W_leave | ||
942 | nop | ||
943 | ssm 0,0 | ||
944 | nop | ||
945 | |||
946 | ; | ||
947 | ; RDR 29 write sequence | ||
948 | ; | ||
949 | sync | ||
950 | ssm 0,0 | ||
951 | STDIAG (29) | ||
952 | ssm 0,0 | ||
953 | b,n perf_rdr_shift_out_W_leave | ||
954 | nop | ||
955 | ssm 0,0 | ||
956 | nop | ||
957 | |||
958 | ; | ||
959 | ; RDR 30 write sequence | ||
960 | ; | ||
961 | sync | ||
962 | ssm 0,0 | ||
963 | STDIAG (30) | ||
964 | ssm 0,0 | ||
965 | b,n perf_rdr_shift_out_W_leave | ||
966 | nop | ||
967 | ssm 0,0 | ||
968 | nop | ||
969 | |||
970 | ; | ||
971 | ; RDR 31 write sequence | ||
972 | ; | ||
973 | sync | ||
974 | ssm 0,0 | ||
975 | STDIAG (31) | ||
976 | ssm 0,0 | ||
977 | b,n perf_rdr_shift_out_W_leave | ||
978 | nop | ||
979 | ssm 0,0 | ||
980 | nop | ||
981 | |||
982 | perf_rdr_shift_out_W_leave: | ||
983 | bve (%r2) | ||
984 | .exit | ||
985 | MTDIAG_2 (23) ; restore DR2 | ||
986 | .procend | ||
987 | |||
988 | |||
989 | ;*********************************************************************** | ||
990 | ;* | ||
991 | ;* Name: rdr_shift_in_U | ||
992 | ;* | ||
993 | ;* Description: | ||
994 | ;* This routine shifts data in from the RDR in arg0 and returns | ||
995 | ;* the result in ret0. If the RDR is <= 64 bits in length, it | ||
996 | ;* is shifted shifted backup immediately. This is to compensate | ||
997 | ;* for RDR10 which has bits that preclude PDC stack operations | ||
998 | ;* when they are in the wrong state. | ||
999 | ;* | ||
1000 | ;* Arguments: | ||
1001 | ;* arg0 : rdr to be read | ||
1002 | ;* arg1 : bit length of rdr | ||
1003 | ;* | ||
1004 | ;* Returns: | ||
1005 | ;* ret0 = next 64 bits of rdr data from staging register | ||
1006 | ;* | ||
1007 | ;* Register usage: | ||
1008 | ;* arg0 : rdr to be read | ||
1009 | ;* arg1 : bit length of rdr | ||
1010 | ;* %r24 - original DR2 value | ||
1011 | ;* %r23 - DR2 | DR2_SLOW_RET | ||
1012 | ;* %r1 - scratch | ||
1013 | ;* | ||
1014 | ;*********************************************************************** | ||
1015 | |||
1016 | .export perf_rdr_shift_in_U,code | ||
1017 | perf_rdr_shift_in_U: | ||
1018 | .proc | ||
1019 | .callinfo frame=0,NO_CALLS | ||
1020 | .entry | ||
1021 | |||
1022 | ; read(shift in) the RDR. | ||
1023 | ; | ||
1024 | ; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any | ||
1025 | ; shifting is done, from or to, remote diagnose registers. | ||
1026 | |||
1027 | depdi,z 1,DR2_SLOW_RET,1,%r29 | ||
1028 | MFDIAG_2 (24) | ||
1029 | or %r24,%r29,%r29 | ||
1030 | MTDIAG_2 (29) ; set DR2_SLOW_RET | ||
1031 | |||
1032 | nop | ||
1033 | nop | ||
1034 | nop | ||
1035 | nop | ||
1036 | |||
1037 | ; | ||
1038 | ; Start of next 32-byte cacheline | ||
1039 | ; | ||
1040 | nop | ||
1041 | nop | ||
1042 | nop | ||
1043 | extrd,u arg1,63,6,%r1 | ||
1044 | |||
1045 | mtsar %r1 | ||
1046 | shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number | ||
1047 | blr %r1,%r0 ; branch to 8-instruction sequence | ||
1048 | nop | ||
1049 | |||
1050 | ; | ||
1051 | ; Start of next 32-byte cacheline | ||
1052 | ; | ||
1053 | SFDIAG (0) ; RDR 0 read sequence | ||
1054 | ssm 0,0 | ||
1055 | MFDIAG_1 (28) | ||
1056 | shrpd ret0,%r0,%sar,%r1 | ||
1057 | MTDIAG_1 (1) | ||
1058 | STDIAG (0) | ||
1059 | ssm 0,0 | ||
1060 | b,n perf_rdr_shift_in_U_leave | ||
1061 | |||
1062 | SFDIAG (1) ; RDR 1 read sequence | ||
1063 | ssm 0,0 | ||
1064 | MFDIAG_1 (28) | ||
1065 | shrpd ret0,%r0,%sar,%r1 | ||
1066 | MTDIAG_1 (1) | ||
1067 | STDIAG (1) | ||
1068 | ssm 0,0 | ||
1069 | b,n perf_rdr_shift_in_U_leave | ||
1070 | |||
1071 | sync ; RDR 2 read sequence | ||
1072 | ssm 0,0 | ||
1073 | SFDIAG (4) | ||
1074 | ssm 0,0 | ||
1075 | MFDIAG_1 (28) | ||
1076 | b,n perf_rdr_shift_in_U_leave | ||
1077 | ssm 0,0 | ||
1078 | nop | ||
1079 | |||
1080 | sync ; RDR 3 read sequence | ||
1081 | ssm 0,0 | ||
1082 | SFDIAG (3) | ||
1083 | ssm 0,0 | ||
1084 | MFDIAG_1 (28) | ||
1085 | b,n perf_rdr_shift_in_U_leave | ||
1086 | ssm 0,0 | ||
1087 | nop | ||
1088 | |||
1089 | sync ; RDR 4 read sequence | ||
1090 | ssm 0,0 | ||
1091 | SFDIAG (4) | ||
1092 | ssm 0,0 | ||
1093 | MFDIAG_1 (28) | ||
1094 | b,n perf_rdr_shift_in_U_leave | ||
1095 | ssm 0,0 | ||
1096 | nop | ||
1097 | |||
1098 | sync ; RDR 5 read sequence | ||
1099 | ssm 0,0 | ||
1100 | SFDIAG (5) | ||
1101 | ssm 0,0 | ||
1102 | MFDIAG_1 (28) | ||
1103 | b,n perf_rdr_shift_in_U_leave | ||
1104 | ssm 0,0 | ||
1105 | nop | ||
1106 | |||
1107 | sync ; RDR 6 read sequence | ||
1108 | ssm 0,0 | ||
1109 | SFDIAG (6) | ||
1110 | ssm 0,0 | ||
1111 | MFDIAG_1 (28) | ||
1112 | b,n perf_rdr_shift_in_U_leave | ||
1113 | ssm 0,0 | ||
1114 | nop | ||
1115 | |||
1116 | sync ; RDR 7 read sequence | ||
1117 | ssm 0,0 | ||
1118 | SFDIAG (7) | ||
1119 | ssm 0,0 | ||
1120 | MFDIAG_1 (28) | ||
1121 | b,n perf_rdr_shift_in_U_leave | ||
1122 | ssm 0,0 | ||
1123 | nop | ||
1124 | |||
1125 | b,n perf_rdr_shift_in_U_leave | ||
1126 | nop | ||
1127 | nop | ||
1128 | nop | ||
1129 | nop | ||
1130 | nop | ||
1131 | nop | ||
1132 | nop | ||
1133 | |||
1134 | SFDIAG (9) ; RDR 9 read sequence | ||
1135 | ssm 0,0 | ||
1136 | MFDIAG_1 (28) | ||
1137 | shrpd ret0,%r0,%sar,%r1 | ||
1138 | MTDIAG_1 (1) | ||
1139 | STDIAG (9) | ||
1140 | ssm 0,0 | ||
1141 | b,n perf_rdr_shift_in_U_leave | ||
1142 | |||
1143 | SFDIAG (10) ; RDR 10 read sequence | ||
1144 | ssm 0,0 | ||
1145 | MFDIAG_1 (28) | ||
1146 | shrpd ret0,%r0,%sar,%r1 | ||
1147 | MTDIAG_1 (1) | ||
1148 | STDIAG (10) | ||
1149 | ssm 0,0 | ||
1150 | b,n perf_rdr_shift_in_U_leave | ||
1151 | |||
1152 | SFDIAG (11) ; RDR 11 read sequence | ||
1153 | ssm 0,0 | ||
1154 | MFDIAG_1 (28) | ||
1155 | shrpd ret0,%r0,%sar,%r1 | ||
1156 | MTDIAG_1 (1) | ||
1157 | STDIAG (11) | ||
1158 | ssm 0,0 | ||
1159 | b,n perf_rdr_shift_in_U_leave | ||
1160 | |||
1161 | SFDIAG (12) ; RDR 12 read sequence | ||
1162 | ssm 0,0 | ||
1163 | MFDIAG_1 (28) | ||
1164 | shrpd ret0,%r0,%sar,%r1 | ||
1165 | MTDIAG_1 (1) | ||
1166 | STDIAG (12) | ||
1167 | ssm 0,0 | ||
1168 | b,n perf_rdr_shift_in_U_leave | ||
1169 | |||
1170 | SFDIAG (13) ; RDR 13 read sequence | ||
1171 | ssm 0,0 | ||
1172 | MFDIAG_1 (28) | ||
1173 | shrpd ret0,%r0,%sar,%r1 | ||
1174 | MTDIAG_1 (1) | ||
1175 | STDIAG (13) | ||
1176 | ssm 0,0 | ||
1177 | b,n perf_rdr_shift_in_U_leave | ||
1178 | |||
1179 | SFDIAG (14) ; RDR 14 read sequence | ||
1180 | ssm 0,0 | ||
1181 | MFDIAG_1 (28) | ||
1182 | shrpd ret0,%r0,%sar,%r1 | ||
1183 | MTDIAG_1 (1) | ||
1184 | STDIAG (14) | ||
1185 | ssm 0,0 | ||
1186 | b,n perf_rdr_shift_in_U_leave | ||
1187 | |||
1188 | SFDIAG (15) ; RDR 15 read sequence | ||
1189 | ssm 0,0 | ||
1190 | MFDIAG_1 (28) | ||
1191 | shrpd ret0,%r0,%sar,%r1 | ||
1192 | MTDIAG_1 (1) | ||
1193 | STDIAG (15) | ||
1194 | ssm 0,0 | ||
1195 | b,n perf_rdr_shift_in_U_leave | ||
1196 | |||
1197 | sync ; RDR 16 read sequence | ||
1198 | ssm 0,0 | ||
1199 | SFDIAG (16) | ||
1200 | ssm 0,0 | ||
1201 | MFDIAG_1 (28) | ||
1202 | b,n perf_rdr_shift_in_U_leave | ||
1203 | ssm 0,0 | ||
1204 | nop | ||
1205 | |||
1206 | SFDIAG (17) ; RDR 17 read sequence | ||
1207 | ssm 0,0 | ||
1208 | MFDIAG_1 (28) | ||
1209 | shrpd ret0,%r0,%sar,%r1 | ||
1210 | MTDIAG_1 (1) | ||
1211 | STDIAG (17) | ||
1212 | ssm 0,0 | ||
1213 | b,n perf_rdr_shift_in_U_leave | ||
1214 | |||
1215 | SFDIAG (18) ; RDR 18 read sequence | ||
1216 | ssm 0,0 | ||
1217 | MFDIAG_1 (28) | ||
1218 | shrpd ret0,%r0,%sar,%r1 | ||
1219 | MTDIAG_1 (1) | ||
1220 | STDIAG (18) | ||
1221 | ssm 0,0 | ||
1222 | b,n perf_rdr_shift_in_U_leave | ||
1223 | |||
1224 | b,n perf_rdr_shift_in_U_leave | ||
1225 | nop | ||
1226 | nop | ||
1227 | nop | ||
1228 | nop | ||
1229 | nop | ||
1230 | nop | ||
1231 | nop | ||
1232 | |||
1233 | sync ; RDR 20 read sequence | ||
1234 | ssm 0,0 | ||
1235 | SFDIAG (20) | ||
1236 | ssm 0,0 | ||
1237 | MFDIAG_1 (28) | ||
1238 | b,n perf_rdr_shift_in_U_leave | ||
1239 | ssm 0,0 | ||
1240 | nop | ||
1241 | |||
1242 | sync ; RDR 21 read sequence | ||
1243 | ssm 0,0 | ||
1244 | SFDIAG (21) | ||
1245 | ssm 0,0 | ||
1246 | MFDIAG_1 (28) | ||
1247 | b,n perf_rdr_shift_in_U_leave | ||
1248 | ssm 0,0 | ||
1249 | nop | ||
1250 | |||
1251 | sync ; RDR 22 read sequence | ||
1252 | ssm 0,0 | ||
1253 | SFDIAG (22) | ||
1254 | ssm 0,0 | ||
1255 | MFDIAG_1 (28) | ||
1256 | b,n perf_rdr_shift_in_U_leave | ||
1257 | ssm 0,0 | ||
1258 | nop | ||
1259 | |||
1260 | sync ; RDR 23 read sequence | ||
1261 | ssm 0,0 | ||
1262 | SFDIAG (23) | ||
1263 | ssm 0,0 | ||
1264 | MFDIAG_1 (28) | ||
1265 | b,n perf_rdr_shift_in_U_leave | ||
1266 | ssm 0,0 | ||
1267 | nop | ||
1268 | |||
1269 | sync ; RDR 24 read sequence | ||
1270 | ssm 0,0 | ||
1271 | SFDIAG (24) | ||
1272 | ssm 0,0 | ||
1273 | MFDIAG_1 (28) | ||
1274 | b,n perf_rdr_shift_in_U_leave | ||
1275 | ssm 0,0 | ||
1276 | nop | ||
1277 | |||
1278 | sync ; RDR 25 read sequence | ||
1279 | ssm 0,0 | ||
1280 | SFDIAG (25) | ||
1281 | ssm 0,0 | ||
1282 | MFDIAG_1 (28) | ||
1283 | b,n perf_rdr_shift_in_U_leave | ||
1284 | ssm 0,0 | ||
1285 | nop | ||
1286 | |||
1287 | SFDIAG (26) ; RDR 26 read sequence | ||
1288 | ssm 0,0 | ||
1289 | MFDIAG_1 (28) | ||
1290 | shrpd ret0,%r0,%sar,%r1 | ||
1291 | MTDIAG_1 (1) | ||
1292 | STDIAG (26) | ||
1293 | ssm 0,0 | ||
1294 | b,n perf_rdr_shift_in_U_leave | ||
1295 | |||
1296 | SFDIAG (27) ; RDR 27 read sequence | ||
1297 | ssm 0,0 | ||
1298 | MFDIAG_1 (28) | ||
1299 | shrpd ret0,%r0,%sar,%r1 | ||
1300 | MTDIAG_1 (1) | ||
1301 | STDIAG (27) | ||
1302 | ssm 0,0 | ||
1303 | b,n perf_rdr_shift_in_U_leave | ||
1304 | |||
1305 | sync ; RDR 28 read sequence | ||
1306 | ssm 0,0 | ||
1307 | SFDIAG (28) | ||
1308 | ssm 0,0 | ||
1309 | MFDIAG_1 (28) | ||
1310 | b,n perf_rdr_shift_in_U_leave | ||
1311 | ssm 0,0 | ||
1312 | nop | ||
1313 | |||
1314 | b,n perf_rdr_shift_in_U_leave | ||
1315 | nop | ||
1316 | nop | ||
1317 | nop | ||
1318 | nop | ||
1319 | nop | ||
1320 | nop | ||
1321 | nop | ||
1322 | |||
1323 | SFDIAG (30) ; RDR 30 read sequence | ||
1324 | ssm 0,0 | ||
1325 | MFDIAG_1 (28) | ||
1326 | shrpd ret0,%r0,%sar,%r1 | ||
1327 | MTDIAG_1 (1) | ||
1328 | STDIAG (30) | ||
1329 | ssm 0,0 | ||
1330 | b,n perf_rdr_shift_in_U_leave | ||
1331 | |||
1332 | SFDIAG (31) ; RDR 31 read sequence | ||
1333 | ssm 0,0 | ||
1334 | MFDIAG_1 (28) | ||
1335 | shrpd ret0,%r0,%sar,%r1 | ||
1336 | MTDIAG_1 (1) | ||
1337 | STDIAG (31) | ||
1338 | ssm 0,0 | ||
1339 | b,n perf_rdr_shift_in_U_leave | ||
1340 | nop | ||
1341 | |||
1342 | perf_rdr_shift_in_U_leave: | ||
1343 | bve (%r2) | ||
1344 | .exit | ||
1345 | MTDIAG_2 (24) ; restore DR2 | ||
1346 | .procend | ||
1347 | |||
1348 | ;*********************************************************************** | ||
1349 | ;* | ||
1350 | ;* Name: rdr_shift_out_U | ||
1351 | ;* | ||
1352 | ;* Description: | ||
1353 | ;* This routine moves data to the RDR's. The double-word that | ||
1354 | ;* arg1 points to is loaded and moved into the staging register. | ||
1355 | ;* Then the STDIAG instruction for the RDR # in arg0 is called | ||
1356 | ;* to move the data to the RDR. | ||
1357 | ;* | ||
1358 | ;* Arguments: | ||
1359 | ;* arg0 = rdr target | ||
1360 | ;* arg1 = buffer pointer | ||
1361 | ;* | ||
1362 | ;* Returns: | ||
1363 | ;* None | ||
1364 | ;* | ||
1365 | ;* Register usage: | ||
1366 | ;* arg0 = rdr target | ||
1367 | ;* arg1 = buffer pointer | ||
1368 | ;* %r24 - DR2 | DR2_SLOW_RET | ||
1369 | ;* %r23 - original DR2 value | ||
1370 | ;* | ||
1371 | ;*********************************************************************** | ||
1372 | |||
1373 | .export perf_rdr_shift_out_U,code | ||
1374 | perf_rdr_shift_out_U: | ||
1375 | .proc | ||
1376 | .callinfo frame=0,NO_CALLS | ||
1377 | .entry | ||
1378 | |||
1379 | ; | ||
1380 | ; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any | ||
1381 | ; shifting is done, from or to, the remote diagnose registers. | ||
1382 | ; | ||
1383 | |||
1384 | depdi,z 1,DR2_SLOW_RET,1,%r24 | ||
1385 | MFDIAG_2 (23) | ||
1386 | or %r24,%r23,%r24 | ||
1387 | MTDIAG_2 (24) ; set DR2_SLOW_RET | ||
1388 | |||
1389 | MTDIAG_1 (25) ; data to the staging register | ||
1390 | shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number | ||
1391 | blr %r1,%r0 ; branch to 8-instruction sequence | ||
1392 | nop | ||
1393 | |||
1394 | ; | ||
1395 | ; 32-byte cachline aligned | ||
1396 | ; | ||
1397 | |||
1398 | sync ; RDR 0 write sequence | ||
1399 | ssm 0,0 | ||
1400 | STDIAG (0) | ||
1401 | ssm 0,0 | ||
1402 | b,n perf_rdr_shift_out_U_leave | ||
1403 | nop | ||
1404 | ssm 0,0 | ||
1405 | nop | ||
1406 | |||
1407 | sync ; RDR 1 write sequence | ||
1408 | ssm 0,0 | ||
1409 | STDIAG (1) | ||
1410 | ssm 0,0 | ||
1411 | b,n perf_rdr_shift_out_U_leave | ||
1412 | nop | ||
1413 | ssm 0,0 | ||
1414 | nop | ||
1415 | |||
1416 | sync ; RDR 2 write sequence | ||
1417 | ssm 0,0 | ||
1418 | STDIAG (2) | ||
1419 | ssm 0,0 | ||
1420 | b,n perf_rdr_shift_out_U_leave | ||
1421 | nop | ||
1422 | ssm 0,0 | ||
1423 | nop | ||
1424 | |||
1425 | sync ; RDR 3 write sequence | ||
1426 | ssm 0,0 | ||
1427 | STDIAG (3) | ||
1428 | ssm 0,0 | ||
1429 | b,n perf_rdr_shift_out_U_leave | ||
1430 | nop | ||
1431 | ssm 0,0 | ||
1432 | nop | ||
1433 | |||
1434 | sync ; RDR 4 write sequence | ||
1435 | ssm 0,0 | ||
1436 | STDIAG (4) | ||
1437 | ssm 0,0 | ||
1438 | b,n perf_rdr_shift_out_U_leave | ||
1439 | nop | ||
1440 | ssm 0,0 | ||
1441 | nop | ||
1442 | |||
1443 | sync ; RDR 5 write sequence | ||
1444 | ssm 0,0 | ||
1445 | STDIAG (5) | ||
1446 | ssm 0,0 | ||
1447 | b,n perf_rdr_shift_out_U_leave | ||
1448 | nop | ||
1449 | ssm 0,0 | ||
1450 | nop | ||
1451 | |||
1452 | sync ; RDR 6 write sequence | ||
1453 | ssm 0,0 | ||
1454 | STDIAG (6) | ||
1455 | ssm 0,0 | ||
1456 | b,n perf_rdr_shift_out_U_leave | ||
1457 | nop | ||
1458 | ssm 0,0 | ||
1459 | nop | ||
1460 | |||
1461 | sync ; RDR 7 write sequence | ||
1462 | ssm 0,0 | ||
1463 | STDIAG (7) | ||
1464 | ssm 0,0 | ||
1465 | b,n perf_rdr_shift_out_U_leave | ||
1466 | nop | ||
1467 | ssm 0,0 | ||
1468 | nop | ||
1469 | |||
1470 | sync ; RDR 8 write sequence | ||
1471 | ssm 0,0 | ||
1472 | STDIAG (8) | ||
1473 | ssm 0,0 | ||
1474 | b,n perf_rdr_shift_out_U_leave | ||
1475 | nop | ||
1476 | ssm 0,0 | ||
1477 | nop | ||
1478 | |||
1479 | sync ; RDR 9 write sequence | ||
1480 | ssm 0,0 | ||
1481 | STDIAG (9) | ||
1482 | ssm 0,0 | ||
1483 | b,n perf_rdr_shift_out_U_leave | ||
1484 | nop | ||
1485 | ssm 0,0 | ||
1486 | nop | ||
1487 | |||
1488 | sync ; RDR 10 write sequence | ||
1489 | ssm 0,0 | ||
1490 | STDIAG (10) | ||
1491 | ssm 0,0 | ||
1492 | b,n perf_rdr_shift_out_U_leave | ||
1493 | nop | ||
1494 | ssm 0,0 | ||
1495 | nop | ||
1496 | |||
1497 | sync ; RDR 11 write sequence | ||
1498 | ssm 0,0 | ||
1499 | STDIAG (11) | ||
1500 | ssm 0,0 | ||
1501 | b,n perf_rdr_shift_out_U_leave | ||
1502 | nop | ||
1503 | ssm 0,0 | ||
1504 | nop | ||
1505 | |||
1506 | sync ; RDR 12 write sequence | ||
1507 | ssm 0,0 | ||
1508 | STDIAG (12) | ||
1509 | ssm 0,0 | ||
1510 | b,n perf_rdr_shift_out_U_leave | ||
1511 | nop | ||
1512 | ssm 0,0 | ||
1513 | nop | ||
1514 | |||
1515 | sync ; RDR 13 write sequence | ||
1516 | ssm 0,0 | ||
1517 | STDIAG (13) | ||
1518 | ssm 0,0 | ||
1519 | b,n perf_rdr_shift_out_U_leave | ||
1520 | nop | ||
1521 | ssm 0,0 | ||
1522 | nop | ||
1523 | |||
1524 | sync ; RDR 14 write sequence | ||
1525 | ssm 0,0 | ||
1526 | STDIAG (14) | ||
1527 | ssm 0,0 | ||
1528 | b,n perf_rdr_shift_out_U_leave | ||
1529 | nop | ||
1530 | ssm 0,0 | ||
1531 | nop | ||
1532 | |||
1533 | sync ; RDR 15 write sequence | ||
1534 | ssm 0,0 | ||
1535 | STDIAG (15) | ||
1536 | ssm 0,0 | ||
1537 | b,n perf_rdr_shift_out_U_leave | ||
1538 | nop | ||
1539 | ssm 0,0 | ||
1540 | nop | ||
1541 | |||
1542 | sync ; RDR 16 write sequence | ||
1543 | ssm 0,0 | ||
1544 | STDIAG (16) | ||
1545 | ssm 0,0 | ||
1546 | b,n perf_rdr_shift_out_U_leave | ||
1547 | nop | ||
1548 | ssm 0,0 | ||
1549 | nop | ||
1550 | |||
1551 | sync ; RDR 17 write sequence | ||
1552 | ssm 0,0 | ||
1553 | STDIAG (17) | ||
1554 | ssm 0,0 | ||
1555 | b,n perf_rdr_shift_out_U_leave | ||
1556 | nop | ||
1557 | ssm 0,0 | ||
1558 | nop | ||
1559 | |||
1560 | sync ; RDR 18 write sequence | ||
1561 | ssm 0,0 | ||
1562 | STDIAG (18) | ||
1563 | ssm 0,0 | ||
1564 | b,n perf_rdr_shift_out_U_leave | ||
1565 | nop | ||
1566 | ssm 0,0 | ||
1567 | nop | ||
1568 | |||
1569 | sync ; RDR 19 write sequence | ||
1570 | ssm 0,0 | ||
1571 | STDIAG (19) | ||
1572 | ssm 0,0 | ||
1573 | b,n perf_rdr_shift_out_U_leave | ||
1574 | nop | ||
1575 | ssm 0,0 | ||
1576 | nop | ||
1577 | |||
1578 | sync ; RDR 20 write sequence | ||
1579 | ssm 0,0 | ||
1580 | STDIAG (20) | ||
1581 | ssm 0,0 | ||
1582 | b,n perf_rdr_shift_out_U_leave | ||
1583 | nop | ||
1584 | ssm 0,0 | ||
1585 | nop | ||
1586 | |||
1587 | sync ; RDR 21 write sequence | ||
1588 | ssm 0,0 | ||
1589 | STDIAG (21) | ||
1590 | ssm 0,0 | ||
1591 | b,n perf_rdr_shift_out_U_leave | ||
1592 | nop | ||
1593 | ssm 0,0 | ||
1594 | nop | ||
1595 | |||
1596 | sync ; RDR 22 write sequence | ||
1597 | ssm 0,0 | ||
1598 | STDIAG (22) | ||
1599 | ssm 0,0 | ||
1600 | b,n perf_rdr_shift_out_U_leave | ||
1601 | nop | ||
1602 | ssm 0,0 | ||
1603 | nop | ||
1604 | |||
1605 | sync ; RDR 23 write sequence | ||
1606 | ssm 0,0 | ||
1607 | STDIAG (23) | ||
1608 | ssm 0,0 | ||
1609 | b,n perf_rdr_shift_out_U_leave | ||
1610 | nop | ||
1611 | ssm 0,0 | ||
1612 | nop | ||
1613 | |||
1614 | sync ; RDR 24 write sequence | ||
1615 | ssm 0,0 | ||
1616 | STDIAG (24) | ||
1617 | ssm 0,0 | ||
1618 | b,n perf_rdr_shift_out_U_leave | ||
1619 | nop | ||
1620 | ssm 0,0 | ||
1621 | nop | ||
1622 | |||
1623 | sync ; RDR 25 write sequence | ||
1624 | ssm 0,0 | ||
1625 | STDIAG (25) | ||
1626 | ssm 0,0 | ||
1627 | b,n perf_rdr_shift_out_U_leave | ||
1628 | nop | ||
1629 | ssm 0,0 | ||
1630 | nop | ||
1631 | |||
1632 | sync ; RDR 26 write sequence | ||
1633 | ssm 0,0 | ||
1634 | STDIAG (26) | ||
1635 | ssm 0,0 | ||
1636 | b,n perf_rdr_shift_out_U_leave | ||
1637 | nop | ||
1638 | ssm 0,0 | ||
1639 | nop | ||
1640 | |||
1641 | sync ; RDR 27 write sequence | ||
1642 | ssm 0,0 | ||
1643 | STDIAG (27) | ||
1644 | ssm 0,0 | ||
1645 | b,n perf_rdr_shift_out_U_leave | ||
1646 | nop | ||
1647 | ssm 0,0 | ||
1648 | nop | ||
1649 | |||
1650 | sync ; RDR 28 write sequence | ||
1651 | ssm 0,0 | ||
1652 | STDIAG (28) | ||
1653 | ssm 0,0 | ||
1654 | b,n perf_rdr_shift_out_U_leave | ||
1655 | nop | ||
1656 | ssm 0,0 | ||
1657 | nop | ||
1658 | |||
1659 | sync ; RDR 29 write sequence | ||
1660 | ssm 0,0 | ||
1661 | STDIAG (29) | ||
1662 | ssm 0,0 | ||
1663 | b,n perf_rdr_shift_out_U_leave | ||
1664 | nop | ||
1665 | ssm 0,0 | ||
1666 | nop | ||
1667 | |||
1668 | sync ; RDR 30 write sequence | ||
1669 | ssm 0,0 | ||
1670 | STDIAG (30) | ||
1671 | ssm 0,0 | ||
1672 | b,n perf_rdr_shift_out_U_leave | ||
1673 | nop | ||
1674 | ssm 0,0 | ||
1675 | nop | ||
1676 | |||
1677 | sync ; RDR 31 write sequence | ||
1678 | ssm 0,0 | ||
1679 | STDIAG (31) | ||
1680 | ssm 0,0 | ||
1681 | b,n perf_rdr_shift_out_U_leave | ||
1682 | nop | ||
1683 | ssm 0,0 | ||
1684 | nop | ||
1685 | |||
1686 | perf_rdr_shift_out_U_leave: | ||
1687 | bve (%r2) | ||
1688 | .exit | ||
1689 | MTDIAG_2 (23) ; restore DR2 | ||
1690 | .procend | ||
1691 | |||
diff --git a/arch/parisc/kernel/perf_images.h b/arch/parisc/kernel/perf_images.h new file mode 100644 index 000000000000..d9562fe3f75c --- /dev/null +++ b/arch/parisc/kernel/perf_images.h | |||
@@ -0,0 +1,3138 @@ | |||
1 | /* | ||
2 | * Imagine for use with the Onyx (PCX-U) CPU interface | ||
3 | * | ||
4 | * Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org> | ||
5 | * Copyright (C) 2001 Hewlett-Packard (Grant Grundler) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #ifndef PERF_IMAGES_H | ||
22 | #define PERF_IMAGES_H | ||
23 | |||
24 | /* Magic numbers taken without modification from HPUX stuff */ | ||
25 | |||
26 | #define PCXU_IMAGE_SIZE 584 | ||
27 | |||
28 | static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] = { | ||
29 | /* | ||
30 | * CPI: | ||
31 | * | ||
32 | * Counts the following: | ||
33 | * | ||
34 | * ctr0 : total cycles | ||
35 | * ctr1 : total cycles where nothing retired | ||
36 | * ctr2 : total instructions retired, including nullified | ||
37 | * ctr3 : total instructions retired, less nullified instructions | ||
38 | */ | ||
39 | { | ||
40 | 0x4c00c000, 0x00000000, 0x00060000, 0x00000000, | ||
41 | 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380, | ||
42 | 0x0101ffff, 0xfffff104, 0xe000c07f, 0xfffffffc, | ||
43 | 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, | ||
44 | 0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00, | ||
45 | 0x000fffff, 0x00000000, 0x00000000, 0x00ffffff, | ||
46 | 0xfffff000, 0x0000000f, 0xffffffff, 0xff000000, | ||
47 | 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, | ||
48 | 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff, | ||
49 | 0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000, | ||
50 | 0xf0000030, 0x00003c00, 0x067f080c, 0x02019fc0, | ||
51 | 0x02804067, 0xf0009030, 0x19fc002c, 0x40067f08, | ||
52 | 0x0c12019f, 0xc0028440, 0x67f00091, 0x3019fc00, | ||
53 | 0x2fc007ff, 0xf800f001, 0xfffe003c, 0x007fff80, | ||
54 | 0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00, | ||
55 | 0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800, | ||
56 | 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003, | ||
57 | 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f, | ||
58 | 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c, | ||
59 | 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0, | ||
60 | 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000, | ||
61 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
62 | 0x6fff0000, 0x00000000, 0x60000000, 0x00000000, | ||
63 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
64 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
65 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
66 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
67 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
68 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
69 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
70 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
71 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
72 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
73 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
74 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
75 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
76 | 0xffffffff, 0xffffffff}, | ||
77 | |||
78 | /* Bus utilization image (bus_util) | ||
79 | * | ||
80 | * ctr0 : counts address valid cycles | ||
81 | * ctr1 : counts data valid cycles | ||
82 | * ctr2 : counts overflow from counter 0 | ||
83 | * ctr3 : counts overflow from counter 1 | ||
84 | */ | ||
85 | { | ||
86 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
87 | 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, | ||
88 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
89 | 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, | ||
90 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
91 | 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, | ||
92 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
93 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
94 | 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff, | ||
95 | 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, | ||
96 | 0x0000000c, 0x00003c00, 0x07930000, 0x0041e4c0, | ||
97 | 0x01002079, 0x3000800c, 0x1e4c0030, 0x00279300, | ||
98 | 0x010049e4, 0xc0014022, 0x79300090, 0x0c9e4c00, | ||
99 | 0x34004793, 0x00020051, 0xe4c00180, 0x24793000, | ||
100 | 0xa00d1e4c, 0x00380067, 0x93000300, 0x59e4c001, | ||
101 | 0xc0267930, 0x00b00d9e, 0x4c003fff, 0xffffffff, | ||
102 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
103 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
104 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
105 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
106 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00, | ||
107 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
108 | 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, | ||
109 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
110 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
111 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
112 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
113 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
114 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
115 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
116 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
117 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
118 | 0x00100000, 0x00000000, 0xffffffff, 0xffffffff, | ||
119 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
120 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
121 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
122 | 0xffffffff, 0xffffffff }, | ||
123 | |||
124 | /* | ||
125 | * TLB counts (same as tlbStats image): | ||
126 | * | ||
127 | * Counts the following: | ||
128 | * | ||
129 | * ctr0: DTLB misses | ||
130 | * ctr1: ITLB misses | ||
131 | * ctr2: total cycles in the miss handlers | ||
132 | * ctr3: total cycles | ||
133 | */ | ||
134 | |||
135 | { | ||
136 | 0x0c00c000, 0x00000000, 0x00060000, 0x00000000, | ||
137 | 0xe7e7e0e0, 0x004e0004, 0x07ffffff, 0xffc01380, | ||
138 | 0x0101ffff, 0xfffff104, 0xe000c06a, 0xafffc85c, | ||
139 | 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, | ||
140 | 0x01b9e000, 0x0001b8c0, 0x00000000, 0x0fffff00, | ||
141 | 0x000fffff, 0x00000000, 0x00000000, 0x00400000, | ||
142 | 0x00001000, 0x00000004, 0x00000000, 0x01000000, | ||
143 | 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, | ||
144 | 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff, | ||
145 | 0xfff55ff5, 0xffffffff, 0xffffffff, 0xf0000000, | ||
146 | 0xf0000000, 0x00003c00, 0x01ff0001, 0x08007fc2, | ||
147 | 0x02c1001f, 0xf0807100, 0x1bfc200c, 0x4806ff00, | ||
148 | 0x03f001ff, 0xfe003c00, 0x7fff800f, 0x001fffe0, | ||
149 | 0x03c007ff, 0xf800f001, 0xfffe003c, 0x007fff80, | ||
150 | 0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00, | ||
151 | 0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800, | ||
152 | 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003, | ||
153 | 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f, | ||
154 | 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c, | ||
155 | 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0, | ||
156 | 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000, | ||
157 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
158 | 0x6fff0000, 0x00000000, 0x60000000, 0x00000000, | ||
159 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
160 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
161 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
162 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
163 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
164 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
165 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
166 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
167 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
168 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
169 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
170 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
171 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
172 | 0xffffffff, 0xffffffff }, | ||
173 | |||
174 | /* tlbHandMiss | ||
175 | * | ||
176 | * ctr0: counts TLB misses | ||
177 | * ctr1: counts dmisses inside tlb miss handlers | ||
178 | * ctr2: counts cycles in the tlb miss handlers | ||
179 | * ctr3: counts overflows of ctr2 | ||
180 | */ | ||
181 | { | ||
182 | 0x1c00c000,00000000,0x00060000,00000000, | ||
183 | 0xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380, | ||
184 | 0x0101ffff,0xfffff104,0xe000c06a,0xafffc85c, | ||
185 | 0x01380010,0x1fffffff,0xff000000,00000000, | ||
186 | 0x01b9e000,0x0001b8c0,00000000,0x0fffff00, | ||
187 | 0x000fffff,00000000,00000000,0x00400000, | ||
188 | 0x00001000,0x00000004,00000000,0x01000000, | ||
189 | 0x0000ffff,0xfffffff0,00000000,0x0fffffff, | ||
190 | 0xffff0000,00000000,0x6fffffff,0xffffffff, | ||
191 | 0xfff55ff5,0xffffffff,0xffffffff,0xf0000000, | ||
192 | 0xf0000000,0x00003c00,0x01fd0000,0x08007f42, | ||
193 | 0x0281001f,0xd080a100,0x19f42008,0x44067d08, | ||
194 | 0x0612019f,0x400084c0,0x67d00060,0x0047f400, | ||
195 | 0x042011fd,0x080b0404,0x7f4202c4,0x0167d080, | ||
196 | 0x311059f4,0x201c4816,0x7d000313,0x059f4001, | ||
197 | 0xfc007fff,0x800f001f,0xffe003c0,0x07fff800, | ||
198 | 0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, | ||
199 | 0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, | ||
200 | 0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, | ||
201 | 0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, | ||
202 | 0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, | ||
203 | 00000000,00000000,00000000,00000000, | ||
204 | 0x6fff0000,00000000,0x60000000,00000000, | ||
205 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
206 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
207 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
208 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
209 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
210 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
211 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
212 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
213 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
214 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
215 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
216 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
217 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
218 | 0xffffffff,0xffffffff}, | ||
219 | |||
220 | /* branch_taken image (ptkn image) | ||
221 | * | ||
222 | * ctr0: overflow for ctr1 | ||
223 | * ctr1: predicted taken branches, actually taken | ||
224 | * ctr2: all predicted taken branches (nullfied or not) | ||
225 | * ctr3: overflow for ctr2 | ||
226 | */ | ||
227 | |||
228 | { | ||
229 | 0xcc01e000, 0x00000000, 0x00060000, 0x00000000, | ||
230 | 0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff, | ||
231 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
232 | 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, | ||
233 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
234 | 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, | ||
235 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
236 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
237 | 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff, | ||
238 | 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, | ||
239 | 0xf0000000, 0x00003c00, 0x04f90000, 0x02013e40, | ||
240 | 0x0081004f, 0x90004060, 0x13e40018, 0x0024f900, | ||
241 | 0x0802093e, 0x40028102, 0x4f9000c0, 0x6093e400, | ||
242 | 0x380014f9, 0x00010205, 0x3e4000c1, 0x014f9000, | ||
243 | 0x506053e4, 0x001c0034, 0xf9000902, 0x0d3e4002, | ||
244 | 0xc1034f90, 0x00d060d3, 0xe4003fff, 0xffffffff, | ||
245 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
246 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
247 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
248 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
249 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00, | ||
250 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
251 | 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, | ||
252 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
253 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
254 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
255 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
256 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
257 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
258 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
259 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
260 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
261 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
262 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
263 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
264 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
265 | 0xffffffff, 0xffffffff }, | ||
266 | |||
267 | /* branch_nottaken (pntkn image) | ||
268 | * | ||
269 | * ctr0: overflow for ctr1 | ||
270 | * ctr1: counts branches predicted not-taken, but actually taken | ||
271 | * ctr2: counts all predictable branches predicted not-taken | ||
272 | * ctr3: overflow for ctr2 | ||
273 | */ | ||
274 | { | ||
275 | 0xcc01e000,00000000,0x00060000,00000000, | ||
276 | 0xc0c0c0e0,0xffb1fffb,0xfff7ffff,0xffffffff, | ||
277 | 0xffffffff,0xfffffffb,0x1fffbfff,0x7fffffff, | ||
278 | 0xfcc7ffff,0xffdffffa,0x5f000000,00000000, | ||
279 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
280 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
281 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
282 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
283 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
284 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
285 | 0xf0000060,0x00003c00,0x04f90000,0x02013e40, | ||
286 | 0x0081004f,0x90004060,0x13e40018,0x0024f900, | ||
287 | 0x0802093e,0x40028102,0x4f9000c0,0x6093e400, | ||
288 | 0x380014f9,0x00010205,0x3e4000c1,0x014f9000, | ||
289 | 0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, | ||
290 | 0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, | ||
291 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
292 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
293 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
294 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
295 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
296 | 00000000,00000000,00000000,00000000, | ||
297 | 0xffff0000,00000000,0xf0000000,00000000, | ||
298 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
299 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
300 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
301 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
302 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
303 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
304 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
305 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
306 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
307 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
308 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
309 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
310 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
311 | 0xffffffff,0xffffffff}, | ||
312 | |||
313 | |||
314 | /* imiss image | ||
315 | * | ||
316 | * ctr0 : counts imiss aligned on 0 | ||
317 | * ctr1 : counts imiss aligned on 4 | ||
318 | * ctr2 : counts imiss aligned on 8 | ||
319 | * ctr3 : counts imiss aligned on C | ||
320 | */ | ||
321 | { | ||
322 | 0x0c00c000, 0x00000000, 0x00010000, 0x00000000, | ||
323 | 0xe7ebedee, 0xffffffff, 0xffffffff, 0xffffffff, | ||
324 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
325 | 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, | ||
326 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
327 | 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, | ||
328 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
329 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
330 | 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff, | ||
331 | 0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000, | ||
332 | 0xf0000000, 0x00003c00, 0x007f0000, 0x01001fc0, | ||
333 | 0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00, | ||
334 | 0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00, | ||
335 | 0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000, | ||
336 | 0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003, | ||
337 | 0x438007f0, 0x00e0f001, 0xfc003fff, 0xfffff800, | ||
338 | 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003, | ||
339 | 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f, | ||
340 | 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f, | ||
341 | 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff, | ||
342 | 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000, | ||
343 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
344 | 0x6fff0000, 0x00000000, 0x60000000, 0x00000000, | ||
345 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
346 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
347 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
348 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
349 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
350 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
351 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
352 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
353 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
354 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
355 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
356 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
357 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
358 | 0xffffffff, 0xffffffff}, | ||
359 | |||
360 | /* dmiss image | ||
361 | * | ||
362 | * ctr0 : counts cycles | ||
363 | * ctr1 : counts cycles where something retired | ||
364 | * ctr2 : counts dmisses | ||
365 | * ctr3 : (same as ctr2) | ||
366 | */ | ||
367 | { | ||
368 | 0x3c00c000, 0x00000000, 0x00060000, 0x00000000, | ||
369 | 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff, | ||
370 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
371 | 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, | ||
372 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
373 | 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, | ||
374 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
375 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
376 | 0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff, | ||
377 | 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, | ||
378 | 0xf0000000, 0x00003c04, 0x007f0009, 0x02001fc0, | ||
379 | 0x0280c007, 0xf000b040, 0x01fc0030, 0x14007f00, | ||
380 | 0x0d06001f, 0xc00381c0, 0x07f000f0, 0x8001fc00, | ||
381 | 0x2024007f, 0x00090a00, 0x1fc00282, 0xc007f000, | ||
382 | 0xb0c001fc, 0x00303400, 0x7f000d0e, 0x001fc003, | ||
383 | 0x83c007f0, 0x00f00001, 0xfc0023ff, 0xfffff800, | ||
384 | 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003, | ||
385 | 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f, | ||
386 | 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f, | ||
387 | 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff, | ||
388 | 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000, | ||
389 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
390 | 0x6fff0000, 0x00000000, 0x60000000, 0x00000000, | ||
391 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
392 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
393 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
394 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
395 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
396 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
397 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
398 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
399 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
400 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
401 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
402 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
403 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
404 | 0xffffffff, 0xffffffff }, | ||
405 | |||
406 | /* dcmiss | ||
407 | * | ||
408 | * ctr0: counts store instructions retired | ||
409 | * ctr1: counts load instructions retired | ||
410 | * ctr2: counts dmisses | ||
411 | * ctr3: counts READ_SHARED_OR_PRIV and READ_PRIVATE transactions on Runway | ||
412 | */ | ||
413 | { | ||
414 | 0x2c90c000,00000000,0x00060000,00000000, | ||
415 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
416 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
417 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
418 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
419 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
420 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
421 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
422 | 0xffff0000,00000000,0x6fffffff,0xffffffff, | ||
423 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
424 | 0xf00000e8,0x00003c02,0x00bf0001,0x02002fc0, | ||
425 | 0x0080a00b,0xf0003040,0x02fc0010,0x1200bf00, | ||
426 | 0x0506002f,0xc00181a0,0x0bf00070,0x8002fc00, | ||
427 | 0x202200bf,0x00090a00,0x2fc00282,0xa00bf000, | ||
428 | 0xb0c002fc,0x00303200,0xbf000d0e,0x002fc003, | ||
429 | 0x83a00bf0,0x00ffffff,0xffffffff,0xffffffff, | ||
430 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
431 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
432 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
433 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
434 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
435 | 00000000,00000000,00000000,00000000, | ||
436 | 0x6fff0000,00000000,0x60000000,00000000, | ||
437 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
438 | 0xfffffc00,00000000,0x55555555,0xd5555555, | ||
439 | 0x55555555,0x75555555,0x5e1ffc00,00000000, | ||
440 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
441 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
442 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
443 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
444 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
445 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
446 | 0x00100000,00000000,0xf8000000,00000000, | ||
447 | 00000000,00000000,0xf4000000,00000000, | ||
448 | 0xffffffff,0xffffffff,0x00ffffff,0xffffffff, | ||
449 | 00000000,00000000,0x00ffffff,0xffffffff, | ||
450 | 0xffffffff,0xffffffff }, | ||
451 | |||
452 | /* big_cpi | ||
453 | * | ||
454 | * ctr0: counts total cycles | ||
455 | * ctr1: counts overflows of ctr0 (for greater than 32-bit values) | ||
456 | * ctr2: counts overflows of ctr3 (for greater than 32-bit values) | ||
457 | * ctr3: counts unnullified instructions retired | ||
458 | */ | ||
459 | { | ||
460 | 0x0c00c000,00000000,0x00060000,00000000, | ||
461 | 0xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380, | ||
462 | 0x0101ffff,0xfffff104,0xe000c06a,0xafffc85c, | ||
463 | 0x01380010,0x1fffffff,0xff000000,00000000, | ||
464 | 0x01b9e000,0x0001b8c0,00000000,0x0fffff00, | ||
465 | 0x000fffff,00000000,00000000,0x00400000, | ||
466 | 0x00001000,0x00000004,00000000,0x01000000, | ||
467 | 0x0000ffff,0xfffffff0,00000000,0x0fffffff, | ||
468 | 0xffff0000,00000000,0x6fffffff,0xffffffff, | ||
469 | 0xfff55ff5,0xffffffff,0xffffffff,0xf0000000, | ||
470 | 0xf0000010,0x00003c00,0x01760008,0x00025d80, | ||
471 | 0x02800417,0x6000c001,0x25d80038,0x04017600, | ||
472 | 0x0901025d,0x8002c044,0x176000d0,0x1125d800, | ||
473 | 0x3c2001f6,0x08080400,0x7d820203,0x001f6080, | ||
474 | 0x804027d8,0x20282009,0xf6080a0c,0x027d8202, | ||
475 | 0x81041f60,0x80c08107,0xd8203030,0x41f6080c, | ||
476 | 0x04127d82,0x0382049f,0x6080e0c1,0x27d82038, | ||
477 | 0x4006f608,0x081011bd,0x82030400,0xef6080a1, | ||
478 | 0x013bd820,0x384806f6,0x00081211,0xbd800304, | ||
479 | 0x80ef6000,0xa1213bd8,0x003bc007,0xfff800f0, | ||
480 | 0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, | ||
481 | 00000000,00000000,00000000,00000000, | ||
482 | 0x6fff0000,00000000,0x60000000,00000000, | ||
483 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
484 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
485 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
486 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
487 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
488 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
489 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
490 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
491 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
492 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
493 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
494 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
495 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
496 | 0xffffffff,0xffffffff }, | ||
497 | |||
498 | /* big_ls | ||
499 | * | ||
500 | * ctr0:counts the total number of cycles for which local_stall_A1 is asserted. | ||
501 | * ctr1: is the overflow for counter 0. | ||
502 | * ctr2: counts IFLUSH_AV | ||
503 | * ctr3: is the overflow for counter 2. | ||
504 | */ | ||
505 | { | ||
506 | 0x0c000000,00000000,0x00060000,00000000, | ||
507 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
508 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
509 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
510 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
511 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
512 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
513 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
514 | 0xffff0000,00000000,0x0fffffff,0xffffffff, | ||
515 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
516 | 00000000,0x00029408,0x02f50002,0x0800bd40, | ||
517 | 0x0202802f,0x5000a000,0x4bd40004,0x0812f500, | ||
518 | 0x030804bd,0x40024281,0x2f5000b0,0x010bd400, | ||
519 | 0x100842f5,0x00060810,0xbd400302,0x842f5000, | ||
520 | 0xe0014bd4,0x00140852,0xf5000708,0x14bd4003, | ||
521 | 0x42852f50,0x00ff001f,0xffe003c0,0x07fff800, | ||
522 | 0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, | ||
523 | 0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, | ||
524 | 0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, | ||
525 | 0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, | ||
526 | 0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, | ||
527 | 00000000,00000000,00000000,00000000, | ||
528 | 0x0df70000,00000000,00000000,00000000, | ||
529 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
530 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
531 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
532 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
533 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
534 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
535 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
536 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
537 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
538 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
539 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
540 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
541 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
542 | 0xffffffff,0xffffffff }, | ||
543 | |||
544 | /* br_abort | ||
545 | * | ||
546 | * ctr0: counts BRAD_STALLH | ||
547 | * ctr1: counts ONE_QUAD | ||
548 | * ctr2: counts BR0_ABRT | ||
549 | * ctr3: counts BR1_ABRT | ||
550 | */ | ||
551 | { | ||
552 | 0x0c002000,00000000,0x00060000,00000000, | ||
553 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
554 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
555 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
556 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
557 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
558 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
559 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
560 | 0xffff0000,00000000,0x1fffffff,0xffffffff, | ||
561 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
562 | 00000000,0x0003f800,0x007f000e,0x01001fc0, | ||
563 | 0x03c08007,0xf000c030,0x01fc0034,0x10007f00, | ||
564 | 0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, | ||
565 | 0x2420007f,0x00060900,0x1fc001c2,0x8007f000, | ||
566 | 0x40b001fc,0x00143000,0x7f00020d,0x001fc000, | ||
567 | 0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, | ||
568 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
569 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
570 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
571 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
572 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
573 | 00000000,00000000,00000000,00000000, | ||
574 | 0x1a250000,00000000,0x10000000,00000000, | ||
575 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
576 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
577 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
578 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
579 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
580 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
581 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
582 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
583 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
584 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
585 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
586 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
587 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
588 | 0xffffffff,0xffffffff}, | ||
589 | |||
590 | /* isnt | ||
591 | * | ||
592 | * ctr0: counts the total number of cycles for which iside_notrans is asserted | ||
593 | * ctr1: counts the number of times iside_notrans is asserted for 1-4 cycles | ||
594 | * ctr2: counts the number of times iside_notrans is asserted for 5-7 cycles | ||
595 | * ctr3: counts the number of times iside_notrans is asserted for > 7 cycles | ||
596 | */ | ||
597 | { | ||
598 | 0x0c018000,00000000,0x00060000,00000000, | ||
599 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
600 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
601 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
602 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
603 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
604 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
605 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
606 | 0xffff0000,00000000,0xcfffffff,0xffffffff, | ||
607 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
608 | 00000000,0x00021c20,0x03ff0808,0x1800ffc4, | ||
609 | 0x0204003f,0xf0004280,0x0ffc6020,0x8003ff00, | ||
610 | 0x043800ff,0xc8020c00,0x3ff00044,0x800ffca0, | ||
611 | 0x210003ff,0x00045800,0xffcc0214,0x003ff000, | ||
612 | 0x26800ffc,0xe0218003,0xff000278,0x00ffd002, | ||
613 | 0x1c003ff0,0x0028800f,0xfd002200,0x03ff0001, | ||
614 | 0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, | ||
615 | 0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, | ||
616 | 0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, | ||
617 | 0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, | ||
618 | 0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, | ||
619 | 00000000,00000000,00000000,00000000, | ||
620 | 0xcdff0000,00000000,0xc0000000,00000000, | ||
621 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
622 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
623 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
624 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
625 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
626 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
627 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
628 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
629 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
630 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
631 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
632 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
633 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
634 | 0xffffffff,0xffffffff}, | ||
635 | |||
636 | /* quadrant | ||
637 | * | ||
638 | * ctr0: Total number of instructions in quadrant 0 | ||
639 | * ctr1: Total number of instructions in quadrant 1 | ||
640 | * ctr2: Total number of instructions in quadrant 2 | ||
641 | * ctr3: Total number of instructions in quadrant 3 | ||
642 | * Works only with 32-bit | ||
643 | */ | ||
644 | |||
645 | { | ||
646 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
647 | 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380, | ||
648 | 0x0101ffff, 0xfffff004, 0xe000407f, 0xfffffffc, | ||
649 | 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, | ||
650 | 0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00, | ||
651 | 0x000fffff, 0x00000000, 0x00000000, 0x00ffffff, | ||
652 | 0xffcff000, 0x0000040f, 0xfffffffc, 0xff000000, | ||
653 | 0x0080ffff, 0xffffcff0, 0x0000000c, 0x0fffffff, | ||
654 | 0xfcff0000, 0x00000000, 0xffffffff, 0xffffffff, | ||
655 | 0xfff55ff5, 0x5fffffff, 0xffffffff, 0xf0000000, | ||
656 | 0xf00000f0, 0x00003c00, 0x007f0000, 0x01001fc0, | ||
657 | 0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00, | ||
658 | 0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00, | ||
659 | 0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000, | ||
660 | 0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003, | ||
661 | 0x438007f0, 0x00e0f001, 0xfc003fff, 0xffffffff, | ||
662 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
663 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
664 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
665 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
666 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00, | ||
667 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
668 | 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, | ||
669 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
670 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
671 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
672 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
673 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
674 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
675 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
676 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
677 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
678 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
679 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
680 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
681 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
682 | 0xffffffff, 0xffffffff}, | ||
683 | |||
684 | /* rw_pdfet (READ_PRIV transactions) | ||
685 | * | ||
686 | * ctr0: counts address valid cycles | ||
687 | * ctr1: counts *all* data valid cycles | ||
688 | * ctr2: is the overflow from counter 0 | ||
689 | * ctr3: is the overflow from counter 1 | ||
690 | */ | ||
691 | { | ||
692 | 0x0c01e000,00000000,0x00060000,00000000, | ||
693 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
694 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
695 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
696 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
697 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
698 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
699 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
700 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
701 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
702 | 0x0000000c,0x00003c00,0x07930000,0x0041e4c0, | ||
703 | 0x01002079,0x3000800c,0x1e4c0030,0x00279300, | ||
704 | 0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, | ||
705 | 0x34004793,0x00020051,0xe4c00180,0x24793000, | ||
706 | 0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, | ||
707 | 0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, | ||
708 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
709 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
710 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
711 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
712 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
713 | 00000000,00000000,00000000,00000000, | ||
714 | 0xffff0000,00000000,0xf0000000,00000000, | ||
715 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
716 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
717 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
718 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
719 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
720 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
721 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
722 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
723 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
724 | 0x00100000,00000000,0xf8000000,00000000, | ||
725 | 00000000,00000000,00000000,00000000, | ||
726 | 0xffffffff,0xffffffff,0x00ffffff,0xffffffff, | ||
727 | 00000000,00000000,00000000,00000000, | ||
728 | 0xffffffff,0xffffffff}, | ||
729 | |||
730 | /* rw_wdfet (WRITEBACKS) | ||
731 | * | ||
732 | * ctr0: counts address valid cycles | ||
733 | * ctr1: counts *all* data valid cycles | ||
734 | * ctr2: is the overflow from counter 0 | ||
735 | * ctr3: is the overflow from counter 1 | ||
736 | */ | ||
737 | { | ||
738 | 0x0c01e000,00000000,0x00060000,00000000, | ||
739 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
740 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
741 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
742 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
743 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
744 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
745 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
746 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
747 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
748 | 0x0000000c,0x00003c00,0x07930000,0x0041e4c0, | ||
749 | 0x01002079,0x3000800c,0x1e4c0030,0x00279300, | ||
750 | 0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, | ||
751 | 0x34004793,0x00020051,0xe4c00180,0x24793000, | ||
752 | 0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, | ||
753 | 0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, | ||
754 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
755 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
756 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
757 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
758 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
759 | 00000000,00000000,00000000,00000000, | ||
760 | 0xffff0000,00000000,0xf0000000,00000000, | ||
761 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
762 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
763 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
764 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
765 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
766 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
767 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
768 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
769 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
770 | 0x00100000,00000000,0x98000000,00000000, | ||
771 | 00000000,00000000,00000000,00000000, | ||
772 | 0xffffffff,0xffffffff,0x00ffffff,0xffffffff, | ||
773 | 00000000,00000000,00000000,00000000, | ||
774 | 0xffffffff,0xffffffff}, | ||
775 | |||
776 | /* shlib_cpi | ||
777 | * | ||
778 | * ctr0: Total number of instructions in quad 0 | ||
779 | * ctr1: Total number of CPU clock cycles in quad 0 | ||
780 | * ctr2: total instructions without nullified | ||
781 | * ctr3: total number of CPU clock cycles | ||
782 | */ | ||
783 | { | ||
784 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
785 | 0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380, | ||
786 | 0x0101ffff, 0xfffff004, 0xe000407f, 0xfffffffc, | ||
787 | 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, | ||
788 | 0x00000fff, 0xff00000f, 0xffffffff, 0xffffffff, | ||
789 | 0xffffffff, 0x00000000, 0x00000000, 0x00ffffff, | ||
790 | 0xffcff000, 0x0000000f, 0xfffffffc, 0xffffffff, | ||
791 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
792 | 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff, | ||
793 | 0xfff77ff5, 0x7fffffff, 0xffffffff, 0xf0000000, | ||
794 | 0xf00000a0, 0x00003c00, 0x01ff0005, 0x08007fc0, | ||
795 | 0x03c1001f, 0xf08030c0, 0x07fc203c, 0x4001ff08, | ||
796 | 0x0118007f, 0xc003c500, 0x1ff08031, 0xc007fc00, | ||
797 | 0x3fffffff, 0xf800ffff, 0xfffe003f, 0xffffff80, | ||
798 | 0x0fffffff, 0xe003ffff, 0xfff800ff, 0xfffffe00, | ||
799 | 0x3fffffff, 0x800fffff, 0xffe003ff, 0xfffff800, | ||
800 | 0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003, | ||
801 | 0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f, | ||
802 | 0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f, | ||
803 | 0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff, | ||
804 | 0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000, | ||
805 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
806 | 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, | ||
807 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
808 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
809 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
810 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
811 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
812 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
813 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
814 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
815 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
816 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
817 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
818 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
819 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
820 | 0xffffffff, 0xffffffff}, | ||
821 | |||
822 | |||
823 | /* addr_inv_abort_alu | ||
824 | * | ||
825 | * ctr0: counts ABORT_ALU0L | ||
826 | * ctr1: counts ABORT_ALU1L | ||
827 | * ctr2: counts ADDR0_INVALID | ||
828 | * ctr3: counts ADDR1_INVALID | ||
829 | */ | ||
830 | |||
831 | { | ||
832 | 0x0c00c000,00000000,0x00060000,00000000, | ||
833 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
834 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
835 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
836 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
837 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
838 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
839 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
840 | 0xffff0000,00000000,0x6fffffff,0xffffffff, | ||
841 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
842 | 00000000,0x0003f800,0x007f000d,0x01001fc0, | ||
843 | 0x03008007,0xf000f030,0x01fc0038,0x10007f00, | ||
844 | 0x0905001f,0xc0020180,0x07f000b0,0x7001fc00, | ||
845 | 0x2820007f,0x00050900,0x1fc00102,0x8007f000, | ||
846 | 0x70b001fc,0x00183000,0x7f00010d,0x001fc000, | ||
847 | 0x038007f0,0x0030f001,0xfc000bff,0xfffff800, | ||
848 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
849 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
850 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
851 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
852 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
853 | 00000000,00000000,00000000,00000000, | ||
854 | 0x65380000,00000000,0x60000000,00000000, | ||
855 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
856 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
857 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
858 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
859 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
860 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
861 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
862 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
863 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
864 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
865 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
866 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
867 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
868 | 0xffffffff,0xffffffff }, | ||
869 | |||
870 | |||
871 | |||
872 | /* brad_stall | ||
873 | * | ||
874 | * ctr0: counts the total number of cycles for which brad_stall is asserted | ||
875 | * ctr1: counts the number of times brad_stall is asserted for 1-4 cycles | ||
876 | * ctr2: counts the number of times brad_stall is asserted for 5-7 cycles | ||
877 | * ctr3: counts the number of times brad_stall is asserted for > 7 cycles | ||
878 | */ | ||
879 | { | ||
880 | 0x0c002000,00000000,0x00060000,00000000, | ||
881 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
882 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
883 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
884 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
885 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
886 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
887 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
888 | 0xffff0000,00000000,0x1fffffff,0xffffffff, | ||
889 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
890 | 00000000,0x00021c20,0x03ff0808,0x1800ffc4, | ||
891 | 0x0204003f,0xf0004280,0x0ffc6020,0x8003ff00, | ||
892 | 0x043800ff,0xc8020c00,0x3ff00044,0x800ffca0, | ||
893 | 0x210003ff,0x00045800,0xffcc0214,0x003ff000, | ||
894 | 0x26800ffc,0xe0218003,0xff000278,0x00ffd002, | ||
895 | 0x1c003ff0,0x0028800f,0xfd002200,0x03ff0001, | ||
896 | 0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, | ||
897 | 0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, | ||
898 | 0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, | ||
899 | 0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, | ||
900 | 0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, | ||
901 | 00000000,00000000,00000000,00000000, | ||
902 | 0x1bff0000,00000000,0x10000000,00000000, | ||
903 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
904 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
905 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
906 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
907 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
908 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
909 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
910 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
911 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
912 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
913 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
914 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
915 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
916 | 0xffffffff,0xffffffff}, | ||
917 | |||
918 | /* cntl_in_pipel | ||
919 | * | ||
920 | * ctr0: counts the total number of cycles for which cntl_in_pipel is asserted | ||
921 | * ctr1: counts the number of times cntl_in_pipel is asserted for 1-4 cycles | ||
922 | * ctr2: counts the number of times cntl_in_pipel is asserted for 5-7 cycles | ||
923 | * ctr3: counts the number of times cntl_in_pipel is asserted for > 7 cycles | ||
924 | */ | ||
925 | { | ||
926 | 0x0c006000,00000000,0x00060000,00000000, | ||
927 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
928 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
929 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
930 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
931 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
932 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
933 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
934 | 0xffff0000,00000000,0x3fffffff,0xffffffff, | ||
935 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
936 | 00000000,0x00021c00,0x03ff0808,0x1000ffc4, | ||
937 | 0x0206003f,0xf0004200,0x0ffc6020,0xa003ff00, | ||
938 | 0x043000ff,0xc8020e00,0x3ff00044,0x000ffca0, | ||
939 | 0x212003ff,0x00045000,0xffcc0216,0x003ff000, | ||
940 | 0x26000ffc,0xe021a003,0xff000270,0x00ffd002, | ||
941 | 0x1e003ff0,0x0028000f,0xfd002220,0x03ff0001, | ||
942 | 0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, | ||
943 | 0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, | ||
944 | 0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, | ||
945 | 0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, | ||
946 | 0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, | ||
947 | 00000000,00000000,00000000,00000000, | ||
948 | 0x3fff0000,00000000,0x30000000,00000000, | ||
949 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
950 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
951 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
952 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
953 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
954 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
955 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
956 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
957 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
958 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
959 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
960 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
961 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
962 | 0xffffffff,0xffffffff }, | ||
963 | |||
964 | |||
965 | /* dsnt_xfh | ||
966 | * | ||
967 | * ctr0: counts dside_notrans | ||
968 | * ctr1: counts xfhang | ||
969 | * ctr2: is the overflow for ctr0 | ||
970 | * ctr3: is the overflow for ctr1 | ||
971 | */ | ||
972 | { | ||
973 | 0x0c018000,00000000,0x00060000,00000000, | ||
974 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
975 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
976 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
977 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
978 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
979 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
980 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
981 | 0xffff0000,00000000,0xcfffffff,0xffffffff, | ||
982 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
983 | 00000000,0x00030000,0x01f30000,0x00087cc0, | ||
984 | 0x0040041f,0x30002001,0x87cc000c,0x1001f300, | ||
985 | 0x0404087c,0xc0014104,0x1f300060,0x4187cc00, | ||
986 | 0x1c2001f3,0x00080808,0x7cc00242,0x041f3000, | ||
987 | 0xa08187cc,0x002c3001,0xf3000c0c,0x087cc003, | ||
988 | 0x43041f30,0x00e0c187,0xcc003fc0,0x07fff800, | ||
989 | 0xf001fffe,0x003c007f,0xff800f00,0x1fffe003, | ||
990 | 0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f, | ||
991 | 0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c, | ||
992 | 0x007fff80,0x0f001fff,0xe003c007,0xfff800f0, | ||
993 | 0x01fffe00,0x3c007fff,0x800f001f,0xffe00000, | ||
994 | 00000000,00000000,00000000,00000000, | ||
995 | 0xcb3f0000,00000000,0xc0000000,00000000, | ||
996 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
997 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
998 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
999 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1000 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1001 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1002 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1003 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1004 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1005 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1006 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1007 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1008 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1009 | 0xffffffff,0xffffffff }, | ||
1010 | |||
1011 | /* fet_sig1 | ||
1012 | * | ||
1013 | * ctr0: counts ICORE_AV | ||
1014 | * ctr1: counts ITRANS_STALL | ||
1015 | * ctr2: counts SEL_PCQH | ||
1016 | * ctr3: counts OUT_OF_CONTEXT | ||
1017 | */ | ||
1018 | { | ||
1019 | 0x0c000000,00000000,0x00060000,00000000, | ||
1020 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
1021 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
1022 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1023 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1024 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1025 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1026 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1027 | 0xffff0000,00000000,0x0fffffff,0xffffffff, | ||
1028 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
1029 | 00000000,0x0003f800,0x007f000e,0x01001fc0, | ||
1030 | 0x03c08007,0xf000c030,0x01fc0034,0x10007f00, | ||
1031 | 0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, | ||
1032 | 0x2420007f,0x00060900,0x1fc001c2,0x8007f000, | ||
1033 | 0x40b001fc,0x00143000,0x7f00020d,0x001fc000, | ||
1034 | 0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, | ||
1035 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
1036 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
1037 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
1038 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
1039 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
1040 | 00000000,00000000,00000000,00000000, | ||
1041 | 0x07c10000,00000000,00000000,00000000, | ||
1042 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1043 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1044 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1045 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1046 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1047 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1048 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1049 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1050 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1051 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1052 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1053 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1054 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1055 | 0xffffffff,0xffffffff}, | ||
1056 | |||
1057 | /* fet_sig2 | ||
1058 | * | ||
1059 | * ctr0: counts ICORE_AV | ||
1060 | * ctr1: counts IRTN_AV | ||
1061 | * ctr2: counts ADDRESS_INC | ||
1062 | * ctr3: counts ADDRESS_DEC | ||
1063 | */ | ||
1064 | { | ||
1065 | 0x0c000000,00000000,0x00060000,00000000, | ||
1066 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
1067 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
1068 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1069 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1070 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1071 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1072 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1073 | 0xffff0000,00000000,0x0fffffff,0xffffffff, | ||
1074 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
1075 | 00000000,0x0003f800,0x007f000e,0x01001fc0, | ||
1076 | 0x03c08007,0xf000c030,0x01fc0034,0x10007f00, | ||
1077 | 0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, | ||
1078 | 0x2420007f,0x00060900,0x1fc001c2,0x8007f000, | ||
1079 | 0x40b001fc,0x00143000,0x7f00020d,0x001fc000, | ||
1080 | 0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, | ||
1081 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
1082 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
1083 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
1084 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
1085 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
1086 | 00000000,00000000,00000000,00000000, | ||
1087 | 0x06930000,00000000,00000000,00000000, | ||
1088 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1089 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1090 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1091 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1092 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1093 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1094 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1095 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1096 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1097 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1098 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1099 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1100 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1101 | 0xffffffff,0xffffffff }, | ||
1102 | |||
1103 | /* g7_1 | ||
1104 | * | ||
1105 | * ctr0: counts HIT_RETRY0 | ||
1106 | * ctr1: counts HIT_RETRY1 | ||
1107 | * ctr2: counts GO_TAG_E | ||
1108 | * ctr3: counts GO_TAG_O | ||
1109 | */ | ||
1110 | { | ||
1111 | 0x0c00e000,00000000,0x00060000,00000000, | ||
1112 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
1113 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
1114 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1115 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1116 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1117 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1118 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1119 | 0xffff0000,00000000,0x7fffffff,0xffffffff, | ||
1120 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
1121 | 00000000,0x0003f800,0x007f000e,0x01001fc0, | ||
1122 | 0x03c08007,0xf000c030,0x01fc0034,0x10007f00, | ||
1123 | 0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, | ||
1124 | 0x2420007f,0x00060900,0x1fc001c2,0x8007f000, | ||
1125 | 0x40b001fc,0x00143000,0x7f00020d,0x001fc000, | ||
1126 | 0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, | ||
1127 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
1128 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
1129 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
1130 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
1131 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
1132 | 00000000,00000000,00000000,00000000, | ||
1133 | 0x71c10000,00000000,0x70000000,00000000, | ||
1134 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1135 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1136 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1137 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1138 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1139 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1140 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1141 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1142 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1143 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1144 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1145 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1146 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1147 | 0xffffffff,0xffffffff }, | ||
1148 | |||
1149 | /* g7_2 | ||
1150 | * | ||
1151 | * ctr0: counts HIT_DM0 | ||
1152 | * ctr1: counts HIT_DM1 | ||
1153 | * ctr2: counts GO_STORE_E | ||
1154 | * ctr3: counts GO_STORE_O | ||
1155 | */ | ||
1156 | { | ||
1157 | 0x0c00e000,00000000,0x00060000,00000000, | ||
1158 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
1159 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
1160 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1161 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1162 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1163 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1164 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1165 | 0xffff0000,00000000,0x7fffffff,0xffffffff, | ||
1166 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
1167 | 00000000,0x0003f800,0x007f000e,0x01001fc0, | ||
1168 | 0x03c08007,0xf000c030,0x01fc0034,0x10007f00, | ||
1169 | 0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, | ||
1170 | 0x2420007f,0x00060900,0x1fc001c2,0x8007f000, | ||
1171 | 0x40b001fc,0x00143000,0x7f00020d,0x001fc000, | ||
1172 | 0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, | ||
1173 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
1174 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
1175 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
1176 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
1177 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
1178 | 00000000,00000000,00000000,00000000, | ||
1179 | 0x72930000,00000000,0x70000000,00000000, | ||
1180 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1181 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1182 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1183 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1184 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1185 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1186 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1187 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1188 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1189 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1190 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1191 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1192 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1193 | 0xffffffff,0xffffffff }, | ||
1194 | |||
1195 | /* g7_3 | ||
1196 | * | ||
1197 | * ctr0: counts HIT_DV0 | ||
1198 | * ctr1: counts HIT_DV1 | ||
1199 | * ctr2: counts STBYPT_E (load bypasses from store queue) | ||
1200 | * ctr3: counts STBYPT_O | ||
1201 | */ | ||
1202 | { | ||
1203 | 0x0c00e000,00000000,0x00060000,00000000, | ||
1204 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
1205 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
1206 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1207 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1208 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1209 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1210 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1211 | 0xffff0000,00000000,0x7fffffff,0xffffffff, | ||
1212 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
1213 | 00000000,0x0003f800,0x007f0002,0x01001fc0, | ||
1214 | 0x00c08007,0xf0000030,0x01fc0004,0x10007f00, | ||
1215 | 0x0605001f,0xc001c180,0x07f00040,0x7001fc00, | ||
1216 | 0x1420007f,0x000a0900,0x1fc002c2,0x8007f000, | ||
1217 | 0x80b001fc,0x00243000,0x7f000e0d,0x001fc003, | ||
1218 | 0xc38007f0,0x00c0f001,0xfc0037ff,0xfffff800, | ||
1219 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
1220 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
1221 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
1222 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
1223 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
1224 | 00000000,00000000,00000000,00000000, | ||
1225 | 0x77250000,00000000,0x70000000,00000000, | ||
1226 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1227 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1228 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1229 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1230 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1231 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1232 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1233 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1234 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1235 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1236 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1237 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1238 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1239 | 0xffffffff,0xffffffff }, | ||
1240 | |||
1241 | /* g7_4 | ||
1242 | * | ||
1243 | * ctr0: counts HIT_DIRTY0 | ||
1244 | * ctr1: counts HIT_DIRTY1 | ||
1245 | * ctr2: counts CA_BYP_E (quick launch) | ||
1246 | * ctr3: counts CA_BYP_O | ||
1247 | */ | ||
1248 | { | ||
1249 | 0x0c00e000,00000000,0x00060000,00000000, | ||
1250 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
1251 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
1252 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1253 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1254 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1255 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1256 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1257 | 0xffff0000,00000000,0x7fffffff,0xffffffff, | ||
1258 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
1259 | 00000000,0x0003f800,0x007f000e,0x01001fc0, | ||
1260 | 0x03c08007,0xf000c030,0x01fc0034,0x10007f00, | ||
1261 | 0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, | ||
1262 | 0x2420007f,0x00060900,0x1fc001c2,0x8007f000, | ||
1263 | 0x40b001fc,0x00143000,0x7f00020d,0x001fc000, | ||
1264 | 0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, | ||
1265 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
1266 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
1267 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
1268 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
1269 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
1270 | 00000000,00000000,00000000,00000000, | ||
1271 | 0x7bb70000,00000000,0x70000000,00000000, | ||
1272 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1273 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1274 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1275 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1276 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1277 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1278 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1279 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1280 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1281 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1282 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1283 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1284 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1285 | 0xffffffff,0xffffffff }, | ||
1286 | |||
1287 | |||
1288 | /* mpb_labort | ||
1289 | * | ||
1290 | * ctr0: counts L_ABORT_ALU0L | ||
1291 | * ctr1: counts L_ABORT_ALU1L | ||
1292 | * ctr2: counts MPB0H | ||
1293 | * ctr3: counts MPB1H | ||
1294 | */ | ||
1295 | { | ||
1296 | 0x0c00c000,00000000,0x00060000,00000000, | ||
1297 | 0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff, | ||
1298 | 0xffffffff,0xffa5ffff,0xffffffff,0xffffffff, | ||
1299 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1300 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1301 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1302 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1303 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1304 | 0xffff0000,00000000,0x6fffffff,0xffffffff, | ||
1305 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
1306 | 00000000,0x0003f800,0x007f000e,0x01001fc0, | ||
1307 | 0x03c08007,0xf000c030,0x01fc0034,0x10007f00, | ||
1308 | 0x0a05001f,0xc002c180,0x07f00080,0x7001fc00, | ||
1309 | 0x2420007f,0x00060900,0x1fc001c2,0x8007f000, | ||
1310 | 0x40b001fc,0x00143000,0x7f00020d,0x001fc000, | ||
1311 | 0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800, | ||
1312 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
1313 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
1314 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
1315 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
1316 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
1317 | 00000000,00000000,00000000,00000000, | ||
1318 | 0x605c0000,00000000,0x60000000,00000000, | ||
1319 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1320 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1321 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1322 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1323 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1324 | 0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff, | ||
1325 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1326 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1327 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1328 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1329 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1330 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1331 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1332 | 0xffffffff,0xffffffff }, | ||
1333 | |||
1334 | /* panic | ||
1335 | * | ||
1336 | * ctr0: is the overflow for counter 1 | ||
1337 | * ctr1: counts traps and RFI's | ||
1338 | * ctr2: counts panic traps | ||
1339 | * ctr3: is the overflow for counter 2 | ||
1340 | */ | ||
1341 | { | ||
1342 | 0x0c002000,00000000,0x00060000,00000000, | ||
1343 | 0xe7efe0e0,0xffffffff,0xffffffff,0xffffffff, | ||
1344 | 0xffffffff,0xffffffff,0xffffffff,0xfffffffc, | ||
1345 | 0x41380030,0x1aabfff2,0x17000000,00000000, | ||
1346 | 0x01b80000,0x3effffff,0xffffffff,0xffffffff, | ||
1347 | 0xffffffff,00000000,00000000,0x00400000, | ||
1348 | 0x00001fff,0xffffffff,0xffffffff,0xffffffff, | ||
1349 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1350 | 0xffff0000,00000000,0x1fffffff,0xffffffff, | ||
1351 | 0xfff7fff7,0xffffffff,0xffffffff,0xf0000000, | ||
1352 | 0xb0000000,0x00012c04,0x05790804,0x14013e44, | ||
1353 | 0x0008004f,0x90000040,0x15e46000,0xc0047920, | ||
1354 | 0x004a003e,0x40011080,0x0f900024,0x4003e460, | ||
1355 | 0x00c80479,0x00023301,0x1e400100,0x4157d080, | ||
1356 | 0x514053f4,0x40048014,0xfd000104,0x055f4600, | ||
1357 | 0x4c0147d2,0x0014a043,0xf4001508,0x10fd0003, | ||
1358 | 0x44043f46,0x004c8147,0xd0003330,0x51f40014, | ||
1359 | 0x04257908,0x0c14093e,0x44020802,0x4f900080, | ||
1360 | 0x4095e460,0x20c02479,0x20084a08,0x3e400310, | ||
1361 | 0x820f9000,0xa44083e4,0x6020c824,0x79000a33, | ||
1362 | 0x091e4003,0x3c007fff,0x800f001f,0xffe00000, | ||
1363 | 00000000,00000000,00000000,00000000, | ||
1364 | 0x10400000,00000000,0x10000000,00000000, | ||
1365 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1366 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1367 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1368 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1369 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1370 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1371 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1372 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1373 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1374 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1375 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1376 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1377 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1378 | 0xffffffff,0xffffffff }, | ||
1379 | |||
1380 | /* rare_inst | ||
1381 | * | ||
1382 | * ctr0: counts sync and syncdma instructions | ||
1383 | * ctr1: counts pxtlbx,x instructions | ||
1384 | * ctr2: counts ixtlbt instructions | ||
1385 | * ctr3: counts cycles | ||
1386 | */ | ||
1387 | { | ||
1388 | 0x0c01e000,00000000,0x00060000,00000000, | ||
1389 | 0xe0e0e0e0,0x004e000c,0x000843fc,0x85c09380, | ||
1390 | 0x0121ebfd,0xff217124,0xe0004000,0x943fc85f, | ||
1391 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1392 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1393 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1394 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1395 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1396 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1397 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1398 | 0xe00000e0,0x00003c00,0x007f0001,0x01001fc0, | ||
1399 | 0x00408007,0xf0003030,0x01fc000c,0x10007f00, | ||
1400 | 0x0505001f,0xc0014180,0x07f00070,0x7001fc00, | ||
1401 | 0x1c20007f,0x00090900,0x1fc00242,0x8007f000, | ||
1402 | 0xb0b001fc,0x002c3000,0x7f000d0d,0x001fc003, | ||
1403 | 0x438007f0,0x00f0f001,0xfc003fff,0xfffff800, | ||
1404 | 0xfffffffe,0x003fffff,0xff800fff,0xffffe003, | ||
1405 | 0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f, | ||
1406 | 0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f, | ||
1407 | 0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff, | ||
1408 | 0xfffffe00,0x3fffffff,0x800fffff,0xffe00000, | ||
1409 | 00000000,00000000,00000000,00000000, | ||
1410 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1411 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1412 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1413 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1414 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1415 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1416 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1417 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1418 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1419 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1420 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1421 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1422 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1423 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1424 | 0xffffffff,0xffffffff }, | ||
1425 | |||
1426 | /* rw_dfet (for D-cache misses and writebacks) | ||
1427 | * | ||
1428 | * ctr0: counts address valid cycles | ||
1429 | * ctr1: counts *all* data valid cycles | ||
1430 | * ctr2: is the overflow from counter 0 | ||
1431 | * ctr3: is the overflow from counter 1 | ||
1432 | */ | ||
1433 | { | ||
1434 | 0x0c01e000,00000000,0x00060000,00000000, | ||
1435 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
1436 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1437 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1438 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1439 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1440 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1441 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1442 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1443 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1444 | 0x0000000c,0x00003c00,0x07930000,0x0041e4c0, | ||
1445 | 0x01002079,0x3000800c,0x1e4c0030,0x00279300, | ||
1446 | 0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, | ||
1447 | 0x34004793,0x00020051,0xe4c00180,0x24793000, | ||
1448 | 0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, | ||
1449 | 0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, | ||
1450 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1451 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1452 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1453 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1454 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1455 | 00000000,00000000,00000000,00000000, | ||
1456 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1457 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1458 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1459 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1460 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1461 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1462 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1463 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1464 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1465 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1466 | 0x00100000,00000000,0xf0000000,00000000, | ||
1467 | 00000000,00000000,0x98000000,00000000, | ||
1468 | 0xffffffff,0xffffffff,0x0fffffff,0xffffffff, | ||
1469 | 00000000,00000000,0x00ffffff,0xffffffff, | ||
1470 | 0xffffffff,0xffffffff }, | ||
1471 | |||
1472 | /* rw_ifet (I-cache misses -- actually dumb READ transactions) | ||
1473 | * | ||
1474 | * ctr0: counts address valid cycles | ||
1475 | * ctr1: counts *all* data valid cycles | ||
1476 | * ctr2: is the overflow from counter 0 | ||
1477 | * ctr3: is the overflow from counter 1 | ||
1478 | */ | ||
1479 | { | ||
1480 | 0x0c01e000,00000000,0x00060000,00000000, | ||
1481 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
1482 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1483 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1484 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1485 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1486 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1487 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1488 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1489 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1490 | 0x0000000c,0x00003c00,0x07930000,0x0041e4c0, | ||
1491 | 0x01002079,0x3000800c,0x1e4c0030,0x00279300, | ||
1492 | 0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, | ||
1493 | 0x34004793,0x00020051,0xe4c00180,0x24793000, | ||
1494 | 0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, | ||
1495 | 0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, | ||
1496 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1497 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1498 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1499 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1500 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1501 | 00000000,00000000,00000000,00000000, | ||
1502 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1503 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1504 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1505 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1506 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1507 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1508 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1509 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1510 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1511 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1512 | 0x00100000,00000000,0xd0000000,00000000, | ||
1513 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1514 | 0xffffffff,0xffffffff,0x00ffffff,0xffffffff, | ||
1515 | 0xffffffff,0xffffffff,00000000,00000000, | ||
1516 | 0xffffffff,0xffffffff }, | ||
1517 | |||
1518 | |||
1519 | /* rw_sdfet (READ_SHARED_OR_PRIVATE transactions) | ||
1520 | * | ||
1521 | * ctr0: counts address valid cycles | ||
1522 | * ctr1: counts *all* data valid cycles | ||
1523 | * ctr2: is the overflow from counter 0 | ||
1524 | * ctr3: is the overflow from counter 1 | ||
1525 | */ | ||
1526 | { | ||
1527 | 0x0c01e000,00000000,0x00060000,00000000, | ||
1528 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
1529 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1530 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1531 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1532 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1533 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1534 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1535 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1536 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1537 | 0x0000000c,0x00003c00,0x07930000,0x0041e4c0, | ||
1538 | 0x01002079,0x3000800c,0x1e4c0030,0x00279300, | ||
1539 | 0x010049e4,0xc0014022,0x79300090,0x0c9e4c00, | ||
1540 | 0x34004793,0x00020051,0xe4c00180,0x24793000, | ||
1541 | 0xa00d1e4c,0x00380067,0x93000300,0x59e4c001, | ||
1542 | 0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff, | ||
1543 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1544 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1545 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1546 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1547 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1548 | 00000000,00000000,00000000,00000000, | ||
1549 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1550 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1551 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1552 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1553 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1554 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1555 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1556 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1557 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1558 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1559 | 0x00100000,00000000,0xf4000000,00000000, | ||
1560 | 00000000,00000000,00000000,00000000, | ||
1561 | 0xffffffff,0xffffffff,0x00ffffff,0xffffffff, | ||
1562 | 00000000,00000000,00000000,00000000, | ||
1563 | 0xffffffff,0xffffffff }, | ||
1564 | |||
1565 | |||
1566 | /* spec_ifet | ||
1567 | * | ||
1568 | * ICORE_AV fires for every request which the Instruction Fetch Unit sends | ||
1569 | * to the Runway Interface Block. Hence, this counts all I-misses, speculative | ||
1570 | * or not, but does *not* include I-cache prefetches, which are generated by | ||
1571 | * RIB. | ||
1572 | * IRTN_AV fires twice for every I-cache miss returning from RIB to the IFU. | ||
1573 | * It will not fire if a second I-cache miss is issued from the IFU to RIB | ||
1574 | * before the first returns. Therefore, if the IRTN_AV count is much less | ||
1575 | * than 2x the ICORE_AV count, many speculative I-cache misses are occurring | ||
1576 | * which are "discovered" to be incorrect fairly quickly. | ||
1577 | * The ratio of I-cache miss transactions on Runway to the ICORE_AV count is | ||
1578 | * a measure of the effectiveness of instruction prefetching. This ratio | ||
1579 | * should be between 1 and 2. If it is close to 1, most prefetches are | ||
1580 | * eventually called for by the IFU; if it is close to 2, almost no prefetches | ||
1581 | * are useful and they are wasted bus traffic. | ||
1582 | * | ||
1583 | * ctr0: counts ICORE_AV | ||
1584 | * ctr1: counts IRTN_AV | ||
1585 | * ctr2: counts all non-coherent READ transactions on Runway. (TTYPE D0) | ||
1586 | * This should be just I-cache miss and I-prefetch transactions. | ||
1587 | * ctr3: counts total processor cycles | ||
1588 | */ | ||
1589 | { | ||
1590 | 0x0c000000,00000000,0x00060000,00000000, | ||
1591 | 0xefefefef,0xffffffff,0xffffffff,0xffffffff, | ||
1592 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1593 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1594 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1595 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1596 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1597 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1598 | 0xffff0000,00000000,0x0fffffff,0xffffffff, | ||
1599 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1600 | 0x00000008,0x00030c00,0x01bf0001,0x00806fc0, | ||
1601 | 0x00c1001b,0xf0005048,0x06fc001c,0x2001bf00, | ||
1602 | 0x0908806f,0xc002c300,0x1bf000d0,0xc806fc00, | ||
1603 | 0x3fffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1604 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1605 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1606 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1607 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1608 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1609 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1610 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1611 | 00000000,00000000,00000000,00000000, | ||
1612 | 0x06bf0000,00000000,00000000,00000000, | ||
1613 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1614 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1615 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1616 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1617 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1618 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1619 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1620 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1621 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1622 | 0x00110000,00000000,0xd0ffffff,0xffffffff, | ||
1623 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1624 | 0xffffffff,0xffffffff,0x00ffffff,0xffffffff, | ||
1625 | 0xffffffff,0xffffffff,00000000,00000000, | ||
1626 | 0xffffffff,0xffffffff }, | ||
1627 | |||
1628 | /* st_cond0 | ||
1629 | * | ||
1630 | * ctr0: is the overflow for ctr1 | ||
1631 | * ctr1: counts major ops 0C and 0E (fp ops, not fmac or fmpyadd) | ||
1632 | * ctr2: counts B,L (including long and push) and GATE (including nullified), | ||
1633 | * predicted not-taken | ||
1634 | * ctr3: is the overflow for ctr2 | ||
1635 | */ | ||
1636 | { | ||
1637 | 0x4c01e000,00000000,0x00060000,00000000, | ||
1638 | 0xe0e0c0e0,0xffffffff,0xffffffff,0xffc13380, | ||
1639 | 0x0101ffff,0xffa1f057,0xe000407f,0xdfffc87f, | ||
1640 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1641 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1642 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1643 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1644 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1645 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1646 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1647 | 0xf0000060,0x00003c00,0x04f90000,0x02013e40, | ||
1648 | 0x0081004f,0x90004060,0x13e40018,0x0024f900, | ||
1649 | 0x0802093e,0x40028102,0x4f9000c0,0x6093e400, | ||
1650 | 0x380014f9,0x00010205,0x3e4000c1,0x014f9000, | ||
1651 | 0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, | ||
1652 | 0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, | ||
1653 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1654 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1655 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1656 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1657 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1658 | 00000000,00000000,00000000,00000000, | ||
1659 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1660 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1661 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1662 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1663 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1664 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1665 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1666 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1667 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1668 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1669 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1670 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1671 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1672 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1673 | 0xffffffff,0xffffffff }, | ||
1674 | |||
1675 | /* st_cond1 | ||
1676 | * | ||
1677 | * ctr0: is the overflow for ctr1 | ||
1678 | * ctr1: counts major ops 1x (most of the load/stores) | ||
1679 | * ctr2: counts CMPB (dw) predicted not-taken | ||
1680 | * ctr3: is the overflow for ctr2 | ||
1681 | */ | ||
1682 | { | ||
1683 | 0x4c01e000,00000000,0x00060000,00000000, | ||
1684 | 0xe0e0c0e0,0xffffffff,0xffffffff,0xffc01b80, | ||
1685 | 0x0101ffff,0xffb7f03d,0xe000407f,0xffffc8ff, | ||
1686 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1687 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1688 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1689 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1690 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1691 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1692 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1693 | 0xf0000060,0x00003c00,0x04f90000,0x02013e40, | ||
1694 | 0x0081004f,0x90004060,0x13e40018,0x0024f900, | ||
1695 | 0x0802093e,0x40028102,0x4f9000c0,0x6093e400, | ||
1696 | 0x380014f9,0x00010205,0x3e4000c1,0x014f9000, | ||
1697 | 0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, | ||
1698 | 0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, | ||
1699 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1700 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1701 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1702 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1703 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1704 | 00000000,00000000,00000000,00000000, | ||
1705 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1706 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1707 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1708 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1709 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1710 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1711 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1712 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1713 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1714 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1715 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1716 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1717 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1718 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1719 | 0xffffffff,0xffffffff }, | ||
1720 | |||
1721 | /* st_cond2 | ||
1722 | * | ||
1723 | * ctr0: is the overflow for ctr1 | ||
1724 | * ctr1: counts major op 03 | ||
1725 | * ctr2: counts CMPIB (dw) predicted not taken. | ||
1726 | * ctr3: is the overflow for ctr2 | ||
1727 | */ | ||
1728 | { | ||
1729 | 0x4c01e000,00000000,0x00060000,00000000, | ||
1730 | 0xe0e0c0e0,0xffffffff,0xffffffff,0xffc09780, | ||
1731 | 0x0101ffff,0xff21f077,0xe000407f,0xffffc87f, | ||
1732 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1733 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1734 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1735 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1736 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1737 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1738 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1739 | 0xf0000060,0x00003c00,0x04f90000,0x02013e40, | ||
1740 | 0x0081004f,0x90004060,0x13e40018,0x0024f900, | ||
1741 | 0x0802093e,0x40028102,0x4f9000c0,0x6093e400, | ||
1742 | 0x380014f9,0x00010205,0x3e4000c1,0x014f9000, | ||
1743 | 0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, | ||
1744 | 0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, | ||
1745 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1746 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1747 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1748 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1749 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1750 | 00000000,00000000,00000000,00000000, | ||
1751 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1752 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1753 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1754 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1755 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1756 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1757 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1758 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1759 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1760 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1761 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1762 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1763 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1764 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1765 | 0xffffffff,0xffffffff }, | ||
1766 | |||
1767 | /* st_cond3 | ||
1768 | * | ||
1769 | * ctr0: is the overflow for ctr1 | ||
1770 | * ctr1: counts major ops 06 & 26 | ||
1771 | * ctr2: counts BB, BVB, MOVB, MOVIB (incl. nullified) predicted not-taken | ||
1772 | * ctr3: is the overflow for ctr2 | ||
1773 | */ | ||
1774 | { | ||
1775 | 0x4c01e000,00000000,0x00060000,00000000, | ||
1776 | 0xe0e0c0e0,0xffffffff,0xffffffff,0xffc03780, | ||
1777 | 0x0101ffff,0xff29f016,0xe000407f,0xffffe97f, | ||
1778 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1779 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1780 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1781 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1782 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1783 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1784 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1785 | 0xf0000060,0x00003c00,0x04f90000,0x02013e40, | ||
1786 | 0x0081004f,0x90004060,0x13e40018,0x0024f900, | ||
1787 | 0x0802093e,0x40028102,0x4f9000c0,0x6093e400, | ||
1788 | 0x380014f9,0x00010205,0x3e4000c1,0x014f9000, | ||
1789 | 0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, | ||
1790 | 0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, | ||
1791 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1792 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1793 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1794 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1795 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1796 | 00000000,00000000,00000000,00000000, | ||
1797 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1798 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1799 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1800 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1801 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1802 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1803 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1804 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1805 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1806 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1807 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1808 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1809 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1810 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1811 | 0xffffffff,0xffffffff }, | ||
1812 | |||
1813 | /* st_cond4 | ||
1814 | * | ||
1815 | * ctr0: is the overflow for ctr1 | ||
1816 | * ctr1: counts major op 2E | ||
1817 | * ctr2: counts CMPB, CMPIB, ADDB, ADDIB (incl. nullified) predicted not-taken | ||
1818 | * ctr3: is the overflow for ctr2 | ||
1819 | */ | ||
1820 | { | ||
1821 | 0x4c01e000,00000000,0x00060000,00000000, | ||
1822 | 0xe0e0c0e0,0xffffffff,0xffffffff,0xffc17780, | ||
1823 | 0x0101ffff,0xff21f014,0xe000407f,0xffffe9ff, | ||
1824 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1825 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1826 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1827 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1828 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1829 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1830 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1831 | 0xf0000060,0x00003c00,0x04f90000,0x02013e40, | ||
1832 | 0x0081004f,0x90004060,0x13e40018,0x0024f900, | ||
1833 | 0x0802093e,0x40028102,0x4f9000c0,0x6093e400, | ||
1834 | 0x380014f9,0x00010205,0x3e4000c1,0x014f9000, | ||
1835 | 0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, | ||
1836 | 0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, | ||
1837 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1838 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1839 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1840 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1841 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1842 | 00000000,00000000,00000000,00000000, | ||
1843 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1844 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1845 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1846 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1847 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1848 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1849 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1850 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1851 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1852 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1853 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1854 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1855 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1856 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1857 | 0xffffffff,0xffffffff }, | ||
1858 | |||
1859 | /* st_unpred0 | ||
1860 | * | ||
1861 | * ctr0: is the overflow for ctr1 | ||
1862 | * ctr1: counts BE and BE,L | ||
1863 | * ctr2: counts BE and BE,L including nullified | ||
1864 | * ctr3: is the overflow for ctr2 | ||
1865 | */ | ||
1866 | { | ||
1867 | 0x4c01e000,00000000,0x00060000,00000000, | ||
1868 | 0xe0c0c0e0,0xffffffff,0xffffffff,0xffdf5bbf, | ||
1869 | 0xffffffff,0xff25f7d6,0xefffffff,0xffffc97f, | ||
1870 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1871 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1872 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1873 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1874 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1875 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1876 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1877 | 0xf0000060,0x00003c00,0x04f90000,0x02013e40, | ||
1878 | 0x0081004f,0x90004060,0x13e40018,0x0024f900, | ||
1879 | 0x0802093e,0x40028102,0x4f9000c0,0x6093e400, | ||
1880 | 0x380014f9,0x00010205,0x3e4000c1,0x014f9000, | ||
1881 | 0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, | ||
1882 | 0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, | ||
1883 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1884 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1885 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1886 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1887 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1888 | 00000000,00000000,00000000,00000000, | ||
1889 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1890 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1891 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1892 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1893 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1894 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1895 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1896 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1897 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1898 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1899 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1900 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1901 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1902 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1903 | 0xffffffff,0xffffffff }, | ||
1904 | |||
1905 | /* st_unpred1 | ||
1906 | * | ||
1907 | * ctr0: is the overflow for ctr1 | ||
1908 | * ctr1: counts BLR, BV, BVE, BVE,L | ||
1909 | * ctr2: counts BLR, BV, BVE, BVE,L including nullified | ||
1910 | * ctr3: is the overflow for ctr2 | ||
1911 | */ | ||
1912 | { | ||
1913 | 0x4c01e000,00000000,0x00060000,00000000, | ||
1914 | 0xe0c0c0e0,0xffffffff,0xffffffff,0xffc15f80, | ||
1915 | 0x0501ff7f,0xff21f057,0xe001407f,0xdfffc87f, | ||
1916 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1917 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1918 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1919 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1920 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1921 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1922 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1923 | 0xf0000060,0x00003c00,0x04f90000,0x02013e40, | ||
1924 | 0x0081004f,0x90004060,0x13e40018,0x0024f900, | ||
1925 | 0x0802093e,0x40028102,0x4f9000c0,0x6093e400, | ||
1926 | 0x380014f9,0x00010205,0x3e4000c1,0x014f9000, | ||
1927 | 0x506053e4,0x001c0034,0xf9000902,0x0d3e4002, | ||
1928 | 0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff, | ||
1929 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1930 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1931 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1932 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1933 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1934 | 00000000,00000000,00000000,00000000, | ||
1935 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1936 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1937 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1938 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1939 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1940 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1941 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1942 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1943 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1944 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1945 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1946 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1947 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1948 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1949 | 0xffffffff,0xffffffff }, | ||
1950 | |||
1951 | /* unpred | ||
1952 | * | ||
1953 | * ctr0: counts non-nullified unpredictable branches | ||
1954 | * ctr1: is the overflow for ctr0 | ||
1955 | * ctr2: counts all unpredictable branches (nullified or not) | ||
1956 | * ctr3: is the overflow for ctr2 | ||
1957 | */ | ||
1958 | { | ||
1959 | 0xcc01e000,00000000,0x00060000,00000000, | ||
1960 | 0x20202020,0xff31ffff,0xfff7fffe,0x97ffcc7f, | ||
1961 | 0xfffffdff,0xffa5fff3,0x1fffffff,0x7fffe97f, | ||
1962 | 0xffffffff,0xffffffff,0xff000000,00000000, | ||
1963 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1964 | 0xffffffff,00000000,0xffffffff,0xffffffff, | ||
1965 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1966 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1967 | 0xffff0000,00000000,0xffffffff,0xffffffff, | ||
1968 | 0xffffffff,0xffffffff,0xffffffff,0xf0000000, | ||
1969 | 0xf00000a0,0x00003c00,0x02f50000,0x0004bd40, | ||
1970 | 0x0040802f,0x50002020,0x4bd4000c,0x0042f500, | ||
1971 | 0x040014bd,0x40014084,0x2f500060,0x214bd400, | ||
1972 | 0x1c2002f5,0x00080804,0xbd400242,0x802f5000, | ||
1973 | 0xa0a04bd4,0x002c2042,0xf5000c08,0x14bd4003, | ||
1974 | 0x42842f50,0x00e0a14b,0xd4003fff,0xffffffff, | ||
1975 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1976 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1977 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1978 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1979 | 0xffffffff,0xffffffff,0xffffffff,0xfffffc00, | ||
1980 | 00000000,00000000,00000000,00000000, | ||
1981 | 0xffff0000,00000000,0xf0000000,00000000, | ||
1982 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1983 | 0xfffffc00,00000000,0xffffffff,0xffffffff, | ||
1984 | 0xffffffff,0xffffffff,0xfffffc00,00000000, | ||
1985 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1986 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1987 | 0xffffffff,0xffffffff,0xf3ffffff,0xffffffff, | ||
1988 | 0xfdffffff,0xffffffff,0xfe000000,00000000, | ||
1989 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1990 | 0xffffffff,0xfffff9ff,0xfe000000,00000000, | ||
1991 | 0x00030000,00000000,0xffffffff,0xffffffff, | ||
1992 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1993 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1994 | 0xffffffff,0xffffffff,0xffffffff,0xffffffff, | ||
1995 | 0xffffffff,0xffffffff }, | ||
1996 | |||
1997 | |||
1998 | /* go_store | ||
1999 | * | ||
2000 | * ctr0: Overflow for counter 2 | ||
2001 | * ctr1: Overflow for counter 3 | ||
2002 | * ctr2: count of GO_STORE_E signal | ||
2003 | * ctr3: count of GO_STORE_O signal | ||
2004 | */ | ||
2005 | |||
2006 | { | ||
2007 | 0x0c00e000, 0x00000000, 0x00060000, 0x00000000, | ||
2008 | 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2009 | 0xffffffff, 0xffa5ffff, 0xffffffff, 0xffffffff, | ||
2010 | 0xffffffff, 0xffffffff, 0xff000000, 0x00000000, | ||
2011 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2012 | 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, | ||
2013 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2014 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2015 | 0xffff0000, 0x00000000, 0x7fffffff, 0xffffffff, | ||
2016 | 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, | ||
2017 | 0x00000000, 0x0000c000, 0x067c0000, 0x01019f00, | ||
2018 | 0x00408067, 0xc0002030, 0x19f0000c, 0x000e7c00, | ||
2019 | 0x0401039f, 0x00014080, 0xe7c00060, 0x3039f000, | ||
2020 | 0x1c00167c, 0x00080105, 0x9f000240, 0x8167c000, | ||
2021 | 0xa03059f0, 0x002c001e, 0x7c000c01, 0x079f0003, | ||
2022 | 0x4081e7c0, 0x00e03079, 0xf0003fc0, 0x07fff800, | ||
2023 | 0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003, | ||
2024 | 0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f, | ||
2025 | 0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c, | ||
2026 | 0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0, | ||
2027 | 0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000, | ||
2028 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
2029 | 0x70130000, 0x00000000, 0x70000000, 0x00000000, | ||
2030 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2031 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
2032 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
2033 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
2034 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
2035 | 0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
2036 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
2037 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
2038 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
2039 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
2040 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2041 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2042 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2043 | 0xffffffff, 0xffffffff | ||
2044 | }, | ||
2045 | |||
2046 | |||
2047 | /* shlib_call | ||
2048 | * | ||
2049 | * ctr0: SharedLib call Depth1 | ||
2050 | * ctr1: SharedLib call Depth2 | ||
2051 | * ctr2: SharedLib call Depth3 | ||
2052 | * ctr3: SharedLib call Depth>3 | ||
2053 | */ | ||
2054 | { | ||
2055 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
2056 | 0xe0e0e0e0, 0xc76fa005, 0x07dd7e9c, 0x87115b80, | ||
2057 | 0x01100200, 0x07200004, 0xe000407f, 0xfffffffc, | ||
2058 | 0x01380010, 0x1fffffff, 0xff000000, 0x00000000, | ||
2059 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2060 | 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, | ||
2061 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2062 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2063 | 0xffff0000, 0x00000000, 0xffffffff, 0xffffffff, | ||
2064 | 0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000, | ||
2065 | 0xf0000000, 0x00003c20, 0x01ff0808, 0x04007fc0, | ||
2066 | 0x0003001f, 0xf0000180, 0x07fc4010, 0x5001ff00, | ||
2067 | 0x001c007f, 0xc2000a00, 0x1ff18022, 0x4007fc20, | ||
2068 | 0x00b001ff, 0x10003800, 0x7fc8004d, 0x001ff100, | ||
2069 | 0x03c007fc, 0x60012001, 0xff280144, 0x007fc600, | ||
2070 | 0x13001ff2, 0x00058007, 0xfcc00550, 0x01ff2000, | ||
2071 | 0x5c007fca, 0x001a001f, 0xf3801640, 0x07fca001, | ||
2072 | 0xb001ff30, 0x0078007f, 0xd0005d00, 0x1ff30007, | ||
2073 | 0xc007fce0, 0x022001ff, 0x48018400, 0x7fce0023, | ||
2074 | 0x001ff400, 0x098007fd, 0x20065001, 0xff40009c, | ||
2075 | 0x007fd200, 0x3fffffff, 0x800fffff, 0xffe00000, | ||
2076 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
2077 | 0xffff0000, 0x00000000, 0xf0000000, 0x00000000, | ||
2078 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2079 | 0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff, | ||
2080 | 0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000, | ||
2081 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
2082 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
2083 | 0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff, | ||
2084 | 0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000, | ||
2085 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
2086 | 0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000, | ||
2087 | 0x00030000, 0x00000000, 0xffffffff, 0xffffffff, | ||
2088 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2089 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2090 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2091 | 0xffffffff, 0xffffffff | ||
2092 | } | ||
2093 | }; | ||
2094 | #define PCXW_IMAGE_SIZE 576 | ||
2095 | |||
2096 | static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] = { | ||
2097 | /* | ||
2098 | * CPI: FROM CPI.IDF (Image 0) | ||
2099 | * | ||
2100 | * Counts the following: | ||
2101 | * | ||
2102 | * ctr0 : total cycles | ||
2103 | * ctr1 : total cycles where nothing retired | ||
2104 | * ctr2 : total instructions retired, including nullified | ||
2105 | * ctr3 : total instructions retired, less nullified instructions | ||
2106 | */ | ||
2107 | { | ||
2108 | 0x4c00c000, 0x00000000, 0x00060000, 0x00000000, | ||
2109 | 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, | ||
2110 | 0xffffc000, 0x07ffff00, 0x07ffffff, 0x6007ffff, | ||
2111 | 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000, | ||
2112 | 0x60f00000, 0x0fffff00, 0x000fffff, 0x00000fff, | ||
2113 | 0xff00000f, 0xffff0000, 0x00000000, 0x00ffffff, | ||
2114 | 0xfffff000, 0x0000000f, 0xffffffff, 0xff000000, | ||
2115 | 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, | ||
2116 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2117 | 0x00000000, 0x00000000, 0x00270000, 0x00000055, | ||
2118 | 0x0200000e, 0x4d300000, 0x00000000, 0x0ff00002, | ||
2119 | 0x70000000, 0x00000020, 0x0000e400, 0x00000ff0, | ||
2120 | 0x00000000, 0x00000000, 0x00000055, 0xffffff00, | ||
2121 | 0x00000000, 0x0000ff00, 0x00000000, 0x0f000000, | ||
2122 | 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, | ||
2123 | 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, | ||
2124 | 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000, | ||
2125 | 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, | ||
2126 | 0x00000000, 0x00000000, 0x00055fff, 0xfff00000, | ||
2127 | 0x00000000, 0x0ff00000, 0x00000030, 0x00000000, | ||
2128 | 0x00157fff, 0xffc00000, 0x034c0000, 0x00000000, | ||
2129 | 0x03fc0000, 0x00000000, 0x6fff0000, 0x00000000, | ||
2130 | 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2131 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2132 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2133 | 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2134 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2135 | 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2136 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2137 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2138 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2139 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2140 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2141 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2142 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2143 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2144 | }, | ||
2145 | |||
2146 | /* Bus utilization image FROM BUS_UTIL.IDF (Image 1) | ||
2147 | * | ||
2148 | * ctr0 : counts address valid cycles | ||
2149 | * ctr1 : counts data valid cycles | ||
2150 | * ctr2 : counts overflow from counter 0 | ||
2151 | * ctr3 : counts overflow from counter 1 | ||
2152 | */ | ||
2153 | { | ||
2154 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
2155 | 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2156 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2157 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2158 | 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2159 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2160 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2161 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2162 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2163 | 0x00000000, 0x00000000, 0x00001b00, 0xaa000000, | ||
2164 | 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000, | ||
2165 | 0x01b00000, 0x00000000, 0x00001037, 0x00000000, | ||
2166 | 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000, | ||
2167 | 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff, | ||
2168 | 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000, | ||
2169 | 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3, | ||
2170 | 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff, | ||
2171 | 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000, | ||
2172 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30, | ||
2173 | 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5, | ||
2174 | 0x40000000, 0x00000000, 0x731c0000, 0x000156ab, | ||
2175 | 0xfc000000, 0x00000000, 0xffff0000, 0x00000000, | ||
2176 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2177 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2178 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2179 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2180 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2181 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2182 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2183 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2184 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2185 | 0xfe000000, 0x00000000, 0x00100000, 0x00000000, | ||
2186 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2187 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2188 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2189 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2190 | }, | ||
2191 | |||
2192 | /* | ||
2193 | * TLB counts: FROM TLBSTATS.IDF (Image 2) | ||
2194 | * | ||
2195 | * Counts the following: | ||
2196 | * | ||
2197 | * ctr0: DTLB misses | ||
2198 | * ctr1: ITLB misses | ||
2199 | * ctr2: total cycles in the miss handlers | ||
2200 | * ctr3: total cycles | ||
2201 | */ | ||
2202 | |||
2203 | { | ||
2204 | 0x0c00c000, 0x00000000, 0x00060000, 0x00000000, | ||
2205 | 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, | ||
2206 | 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff, | ||
2207 | 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000, | ||
2208 | 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff, | ||
2209 | 0xff00000f, 0xffff0000, 0x00000000, 0x00400000, | ||
2210 | 0x00001000, 0x00000004, 0x00000000, 0x01000000, | ||
2211 | 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, | ||
2212 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2213 | 0x00000000, 0x00000000, 0x00800000, 0x00153f7f, | ||
2214 | 0x55000000, 0xaf800000, 0xc0000000, 0x0403f240, | ||
2215 | 0x00000000, 0x00001010, 0x00004700, 0x00000ff0, | ||
2216 | 0x00000000, 0x00000000, 0x00000055, 0xffffff00, | ||
2217 | 0x00000000, 0x0000ff00, 0x00000000, 0x0f000000, | ||
2218 | 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, | ||
2219 | 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, | ||
2220 | 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000, | ||
2221 | 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, | ||
2222 | 0x00000000, 0x00000000, 0x00055fff, 0xfff00000, | ||
2223 | 0x00000000, 0x0ff00000, 0x00000000, 0x00000000, | ||
2224 | 0x00157fff, 0xffc00000, 0x00000000, 0x3fc00000, | ||
2225 | 0x00040000, 0x00000000, 0x6fff0000, 0x00000000, | ||
2226 | 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2227 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2228 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2229 | 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2230 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2231 | 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2232 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2233 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2234 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2235 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2236 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2237 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2238 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2239 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2240 | }, | ||
2241 | |||
2242 | /* tlbhandler FROM tlbHandMiss.idf (Image 3) | ||
2243 | * | ||
2244 | * ctr0: TLB misses | ||
2245 | * ctr1: dmisses inside the TLB miss handler | ||
2246 | * ctr2: cycles in the TLB miss handler | ||
2247 | * ctr3: overflow of ctr2 | ||
2248 | */ | ||
2249 | { | ||
2250 | 0x1c00c000, 0x00000000, 0x00060000, 0x00000000, | ||
2251 | 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, | ||
2252 | 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff, | ||
2253 | 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000, | ||
2254 | 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff, | ||
2255 | 0xff00000f, 0xffff0000, 0x00000000, 0x00400000, | ||
2256 | 0x00001000, 0x00000004, 0x00000000, 0x01000000, | ||
2257 | 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, | ||
2258 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2259 | 0x00000000, 0x00000000, 0x006c0000, 0x01000054, | ||
2260 | 0x02000002, 0xc3200000, 0xc00aa000, 0x0c03f240, | ||
2261 | 0x00000000, 0x00001010, 0x000044f4, 0x00000c00, | ||
2262 | 0xaa0000f0, 0x0f0000b0, 0x00005005, 0x0f5f0000, | ||
2263 | 0x0001f000, 0x0000ff00, 0x00000000, 0x0f000000, | ||
2264 | 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, | ||
2265 | 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, | ||
2266 | 0x00000000, 0x00ff0000, 0x00000000, 0xf0000000, | ||
2267 | 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, | ||
2268 | 0x00000000, 0x00000000, 0x00055fff, 0xfff00000, | ||
2269 | 0x00000000, 0x0ff00a00, 0x000f0000, 0x24004000, | ||
2270 | 0x15400001, 0x40c00003, 0x3da00000, 0x0002a800, | ||
2271 | 0x00ff0000, 0x00000000, 0x6fff0000, 0x00000000, | ||
2272 | 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2273 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2274 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2275 | 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2276 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2277 | 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2278 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2279 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2280 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2281 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2282 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2283 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2284 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2285 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2286 | }, | ||
2287 | |||
2288 | /* branch_taken image FROM PTKN.IDF (Image 4) | ||
2289 | * | ||
2290 | * ctr0: mispredicted branches | ||
2291 | * ctr1: predicted taken branches, actually taken | ||
2292 | * ctr2: predicted taken branches (includes nullfied) | ||
2293 | * ctr3: all branches | ||
2294 | */ | ||
2295 | |||
2296 | { | ||
2297 | 0xcc01e000, 0x00000000, 0x00000000, 0x00000000, | ||
2298 | 0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2299 | 0xffffffff, 0xfffffeff, 0xfffeffff, 0xffffffff, | ||
2300 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2301 | 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2302 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2303 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2304 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2305 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2306 | 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, | ||
2307 | 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, | ||
2308 | 0x90000000, 0x00000000, 0x0000907e, 0x00000000, | ||
2309 | 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, | ||
2310 | 0x000dbfff, 0xffffff00, 0x00000000, 0x0f0fffff, | ||
2311 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
2312 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
2313 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
2314 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
2315 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
2316 | 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, | ||
2317 | 0x00000000, 0x00000002, 0x67840000, 0x00000000, | ||
2318 | 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, | ||
2319 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2320 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2321 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2322 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2323 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2324 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2325 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2326 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2327 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2328 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2329 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2330 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2331 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2332 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2333 | }, | ||
2334 | |||
2335 | /* branch_nottaken FROM PNTKN.IDF (Image 5) | ||
2336 | * | ||
2337 | * ctr0: mispredicted branches | ||
2338 | * ctr1: branches predicted not-taken, but actually taken | ||
2339 | * ctr2: branches predicted not-taken (includes nullified) | ||
2340 | * ctr3: all branches | ||
2341 | */ | ||
2342 | { | ||
2343 | 0xcc01e000, 0x00000000, 0x00000000, 0x00000000, | ||
2344 | 0xe0c0c0e0, 0xffffffff, 0xffffffff, 0xffefffff, | ||
2345 | 0xffffbfff, 0xfffffeff, 0xfffeffff, 0xfffffeff, | ||
2346 | 0xfffffffe, 0xffffffff, 0xffffff00, 0x00000000, | ||
2347 | 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2348 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2349 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2350 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2351 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2352 | 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, | ||
2353 | 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, | ||
2354 | 0x90000000, 0x00000000, 0x0000907e, 0x00000000, | ||
2355 | 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, | ||
2356 | 0x000dbfff, 0xffffff00, 0x00000000, 0x0f0fffff, | ||
2357 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
2358 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
2359 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
2360 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
2361 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
2362 | 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, | ||
2363 | 0x00000000, 0x00000002, 0x67840000, 0x00000000, | ||
2364 | 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, | ||
2365 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2366 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2367 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2368 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2369 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2370 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2371 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2372 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2373 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2374 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2375 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2376 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2377 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2378 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2379 | }, | ||
2380 | |||
2381 | /* IMISS image (Image 6) | ||
2382 | * | ||
2383 | * ctr0 : icache misses for retired instructions | ||
2384 | * ctr1 : total cycles | ||
2385 | * ctr2 : dcache misses for retired instructions | ||
2386 | * ctr3 : number of retired instructions | ||
2387 | */ | ||
2388 | { | ||
2389 | 0x2801e000, 0x00000000, 0x00010000, 0x00000000, | ||
2390 | 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff, | ||
2391 | 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2392 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2393 | 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2394 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2395 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2396 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2397 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2398 | 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0, | ||
2399 | 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800, | ||
2400 | 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0, | ||
2401 | 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555, | ||
2402 | 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff, | ||
2403 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
2404 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
2405 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
2406 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
2407 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
2408 | 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf, | ||
2409 | 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000, | ||
2410 | 0x03c14000, 0x00000000, 0xffff0000, 0x00000000, | ||
2411 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2412 | 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, | ||
2413 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2414 | 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2415 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2416 | 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2417 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2418 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2419 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2420 | 0xfe000000, 0x00000000, 0x00130000, 0x00000000, | ||
2421 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2422 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2423 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2424 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2425 | }, | ||
2426 | |||
2427 | /* DMISS image (Image 7) | ||
2428 | * | ||
2429 | * ctr0 : icache misses for retired instructions | ||
2430 | * ctr1 : total cycles | ||
2431 | * ctr2 : dcache misses for retired instructions | ||
2432 | * ctr3 : number of retired instructions | ||
2433 | */ | ||
2434 | { | ||
2435 | 0x2801e000, 0x00000000, 0x00010000, 0x00000000, | ||
2436 | 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff, | ||
2437 | 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2438 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2439 | 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2440 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2441 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2442 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2443 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2444 | 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0, | ||
2445 | 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800, | ||
2446 | 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0, | ||
2447 | 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555, | ||
2448 | 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff, | ||
2449 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
2450 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
2451 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
2452 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
2453 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
2454 | 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf, | ||
2455 | 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000, | ||
2456 | 0x03c14000, 0x00000000, 0xffff0000, 0x00000000, | ||
2457 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2458 | 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, | ||
2459 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2460 | 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2461 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2462 | 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2463 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2464 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2465 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2466 | 0xfe000000, 0x00000000, 0x00130000, 0x00000000, | ||
2467 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2468 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2469 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2470 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2471 | }, | ||
2472 | |||
2473 | /* dmiss_access image FROM DMISS_RATIO.IDF (Image 8) | ||
2474 | * | ||
2475 | * ctr0 : all loads and stores that retire (even lines) | ||
2476 | * ctr1 : all loads and stores that retire (odd lines) | ||
2477 | * ctr2 : dcache misses of retired loads/stores | ||
2478 | * ctr3 : all READ_PRIV and READ_SHAR_OR_PRIV on Runway | ||
2479 | * (Speculative and Non-Speculative) | ||
2480 | */ | ||
2481 | { | ||
2482 | 0x2d81e000, 0x00000000, 0x00000000, 0x00000000, | ||
2483 | 0x10101010, 0x00ffffff, 0xa003ffff, 0xfe800fff, | ||
2484 | 0xfffa003f, 0xffffe8ff, 0xffffffff, 0xffffffff, | ||
2485 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2486 | 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2487 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2488 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2489 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2490 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2491 | 0x00000000, 0x00000000, 0xd2280a00, 0x00000000, | ||
2492 | 0x0000000b, 0x46000000, 0x00000005, 0x555ff900, | ||
2493 | 0x80200000, 0x00000000, 0x0000907e, 0x00000000, | ||
2494 | 0x00005555, 0xff80bf8b, 0xab030303, 0x03030000, | ||
2495 | 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, | ||
2496 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
2497 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
2498 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
2499 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
2500 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
2501 | 0xffff5555, 0x55500000, 0x15153fe0, 0x27628880, | ||
2502 | 0x00000000, 0x00000002, 0x67840000, 0x00000001, | ||
2503 | 0x5557fc00, 0x00000000, 0xffff0000, 0x00000000, | ||
2504 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2505 | 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, | ||
2506 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2507 | 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2508 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2509 | 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2510 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2511 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2512 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2513 | 0xfe000000, 0x00000000, 0x00110000, 0x00000000, | ||
2514 | 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2515 | 0xf8ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2516 | 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2517 | 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2518 | }, | ||
2519 | |||
2520 | |||
2521 | /* big_cpi image (Image 9) | ||
2522 | * | ||
2523 | * ctr0 : Total number of CPU clock cycles. | ||
2524 | * ctr1 : Unused | ||
2525 | * ctr2 : Unused | ||
2526 | * ctr3 : Total number of Non-Nullified instructions retired. | ||
2527 | */ | ||
2528 | { | ||
2529 | 0x0c00c000, 0x00000000, 0x00060000, 0x00000000, | ||
2530 | 0xe7e7e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, | ||
2531 | 0xfff00000, 0x07ffff00, 0x07ffffff, 0x6007ffff, | ||
2532 | 0xa00007ff, 0xffff0007, 0xffffff00, 0x00000000, | ||
2533 | 0x603001c1, 0xe0000001, 0xc0c00000, 0x00000fff, | ||
2534 | 0xff00000f, 0xffff0000, 0x00000000, 0x00400000, | ||
2535 | 0x00001000, 0x00000004, 0x00000000, 0x01000000, | ||
2536 | 0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff, | ||
2537 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2538 | 0x00000000, 0x00000000, 0x00550005, 0x00220000, | ||
2539 | 0x0000000c, 0x71f00000, 0x00f00aa0, 0x0aaff000, | ||
2540 | 0x00005002, 0x20000000, 0x0000c413, 0x00000c0f, | ||
2541 | 0x00aa0000, 0xff00b600, 0x000500a0, 0x00000300, | ||
2542 | 0x000cc3f0, 0x0000c0f0, 0x0aa0000f, 0xff000000, | ||
2543 | 0x011000a0, 0x05503000, 0x00d03700, 0x00000f00, | ||
2544 | 0xaa005500, 0x00000000, 0x000055ff, 0xffff0000, | ||
2545 | 0x00000000, 0x00ff0000, 0x00000000, 0xf000aa00, | ||
2546 | 0x11000a00, 0x55000000, 0x0d037000, 0x00c0f00a, | ||
2547 | 0xa0055000, 0x0db00005, 0x5002a000, 0x00300000, | ||
2548 | 0xf40f0000, 0x0c0f00aa, 0x0000ff10, 0x27400000, | ||
2549 | 0x00008000, 0x00c00003, 0x037c0000, 0x003c02a8, | ||
2550 | 0x02abfc00, 0x00000000, 0x6fff0000, 0x00000000, | ||
2551 | 0x60000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2552 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2553 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2554 | 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2555 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2556 | 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2557 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2558 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2559 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2560 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2561 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2562 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2563 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2564 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2565 | }, | ||
2566 | |||
2567 | /* big_ls image (Image 10) | ||
2568 | * | ||
2569 | * ctr0 : Total number of CPU clock cycles during which local_stall_A1 is asserted | ||
2570 | * ctr1 : Overflow of Counter 0 | ||
2571 | * ctr2 : Total number of IFLUSH_AV | ||
2572 | * ctr3 : Overflow of Counter 2 | ||
2573 | */ | ||
2574 | { | ||
2575 | 0x0c000000, 0x00000000, 0x00060000, 0x00000000, | ||
2576 | 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2577 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2578 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2579 | 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2580 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2581 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2582 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2583 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2584 | 0x00000000, 0x00000000, 0x28880001, 0x54000000, | ||
2585 | 0x00000004, 0xb6200000, 0x000aaaa0, 0x05555288, | ||
2586 | 0x80000010, 0x00000000, 0x0000486e, 0x00000000, | ||
2587 | 0xaaaa0055, 0x55002888, 0x00545401, 0x03030000, | ||
2588 | 0x0007b000, 0x0000ff00, 0x00000000, 0x05000000, | ||
2589 | 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, | ||
2590 | 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, | ||
2591 | 0x00000000, 0x00ff0000, 0x00000000, 0x00000000, | ||
2592 | 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, | ||
2593 | 0x00000000, 0xa0000000, 0x00055fff, 0xfff00000, | ||
2594 | 0x00aa0000, 0x05502a2a, 0x00151500, 0x0a220015, | ||
2595 | 0x40400000, 0x00000001, 0xe2980000, 0x0002aaa8, | ||
2596 | 0x01555400, 0x00000000, 0x0df70000, 0x00000000, | ||
2597 | 0x00000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2598 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2599 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2600 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2601 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2602 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2603 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2604 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2605 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2606 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2607 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2608 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2609 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2610 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2611 | }, | ||
2612 | |||
2613 | /* br_abort image (Image 12) | ||
2614 | * | ||
2615 | * ctr0 : Total number of BRAD_STALLH | ||
2616 | * ctr1 : Total number of ONE_QUAD | ||
2617 | * ctr2 : Total number of BR0_ABRT | ||
2618 | * ctr3 : Total number of BR1_ABRT | ||
2619 | */ | ||
2620 | |||
2621 | { | ||
2622 | 0x0c002000, 0x00000000, 0x00060000, 0x00000000, | ||
2623 | 0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xff0fffff, | ||
2624 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2625 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2626 | 0x1077ffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2627 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2628 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2629 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2630 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2631 | 0x00000000, 0x00000000, 0x551b0000, 0x00000000, | ||
2632 | 0x0000000c, 0xd4f00000, 0x00000000, 0x0ffff001, | ||
2633 | 0xb0000000, 0x00000000, 0x0000fd4c, 0x00000000, | ||
2634 | 0x000000ff, 0xff00ff1b, 0x00000000, 0x00000000, | ||
2635 | 0x0000d000, 0x0000ff00, 0x00000000, 0x0e0fffff, | ||
2636 | 0xffffffff, 0xfffff000, 0x00000000, 0x000ff000, | ||
2637 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffff0000, | ||
2638 | 0x00000000, 0x00ff0000, 0x00000000, 0x00ffffff, | ||
2639 | 0xffffffff, 0xffff0000, 0x00000000, 0x00ff0000, | ||
2640 | 0x00000000, 0xffffffff, 0xffffffff, 0xfff00000, | ||
2641 | 0x00400000, 0x00000000, 0x00ffff00, 0x2a86c000, | ||
2642 | 0x00000000, 0x00000000, 0xf50c0000, 0x00000000, | ||
2643 | 0x03fffc00, 0x00000000, 0x1a250000, 0x00000000, | ||
2644 | 0x10000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2645 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2646 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2647 | 0xfff7fbfc, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2648 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2649 | 0x00000000, 0x00000000, 0xffffafff, 0xffffff3f, | ||
2650 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2651 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2652 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2653 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2654 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2655 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2656 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2657 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2658 | }, | ||
2659 | |||
2660 | |||
2661 | /* isnt image (Image 13) | ||
2662 | * | ||
2663 | * ctr0 : Total number of cycles for which iside_notrans is asserted. | ||
2664 | * ctr1 : Total number of times iside_notrans is asserted for 1-4 cycles. | ||
2665 | * ctr2 : Total number of times iside_notrans is asserted for 5-7 cycles. | ||
2666 | * ctr3 : Total number of times iside_notrans is asserted for > 7 cycles. | ||
2667 | */ | ||
2668 | |||
2669 | { | ||
2670 | 0x0c018000, 0x00000000, 0x00060000, 0x00000000, | ||
2671 | 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2672 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2673 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2674 | 0xc0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2675 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2676 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2677 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2678 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2679 | 0x00000000, 0x00000000, 0x22000000, 0x000001bc, | ||
2680 | 0x10000006, 0x00900000, 0x50000000, 0x00055a20, | ||
2681 | 0x00000000, 0x00016060, 0x0000c021, 0x00000540, | ||
2682 | 0x00000000, 0x55002200, 0x00000000, 0x56bc4000, | ||
2683 | 0x00048000, 0x0000ff00, 0x00000000, 0x17000000, | ||
2684 | 0x0000055f, 0xfffff000, 0x00000000, 0x000ff000, | ||
2685 | 0x00000000, 0x00000000, 0x000055ff, 0xffff0000, | ||
2686 | 0x00000000, 0x00ff0000, 0x00000000, 0x00000000, | ||
2687 | 0x000055ff, 0xffff0000, 0x00000000, 0x00ff0000, | ||
2688 | 0x00000000, 0x80000000, 0x00015bf3, 0xf5500000, | ||
2689 | 0x02210000, 0x00100000, 0x00005500, 0x08800000, | ||
2690 | 0x00001545, 0x85000001, 0x80240000, 0x11000000, | ||
2691 | 0x00015400, 0x00000000, 0xcdff0000, 0x00000000, | ||
2692 | 0xc0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2693 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2694 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2695 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2696 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2697 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2698 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2699 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2700 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2701 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2702 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2703 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2704 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2705 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2706 | }, | ||
2707 | |||
2708 | /* quadrant image (image 14) | ||
2709 | * | ||
2710 | * ctr0 : Total number of instructions in quadrant 0. | ||
2711 | * ctr1 : Total number of instructions in quadrant 1. | ||
2712 | * ctr2 : Total number of instructions in quadrant 2. | ||
2713 | * ctr3 : Total number of instructions in quadrant 3. | ||
2714 | * | ||
2715 | * Only works for 32-bit applications. | ||
2716 | */ | ||
2717 | |||
2718 | { | ||
2719 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
2720 | 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, | ||
2721 | 0xffffc000, 0x07ffff00, 0x07ffffff, 0x0007ffff, | ||
2722 | 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000, | ||
2723 | 0xf0000000, 0x0fffff00, 0x000fffff, 0x00000fff, | ||
2724 | 0xff00000f, 0xffff0000, 0x00000000, 0x00ffffff, | ||
2725 | 0xffcff000, 0x0000040f, 0xfffffffc, 0xff000000, | ||
2726 | 0x0080ffff, 0xffffcff0, 0x0000000c, 0x0fffffff, | ||
2727 | 0xfcff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2728 | 0x00000000, 0x00000000, 0x551b0000, 0x00000000, | ||
2729 | 0x00000003, 0x17000000, 0x00000000, 0x0ffff001, | ||
2730 | 0xb0000000, 0x00000000, 0x00000173, 0x00000000, | ||
2731 | 0x000000ff, 0xff00ff1b, 0x00000000, 0x00000000, | ||
2732 | 0x000f1ff0, 0xcfffff00, 0x00000000, 0x0f0fffff, | ||
2733 | 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000, | ||
2734 | 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3, | ||
2735 | 0x0ffff0cf, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
2736 | 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000, | ||
2737 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30, | ||
2738 | 0xff7f0000, 0x00000000, 0x00fffff0, 0x2a86c000, | ||
2739 | 0x00000000, 0x00000003, 0x05f00000, 0x00000000, | ||
2740 | 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, | ||
2741 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2742 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2743 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2744 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2745 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2746 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2747 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2748 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2749 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2750 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2751 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2752 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2753 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2754 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2755 | }, | ||
2756 | |||
2757 | /* rw_pdfet image (Image 15) | ||
2758 | * | ||
2759 | * ctr0 : Total of all READ_PRIV address valid cycles. | ||
2760 | * ctr1 : Total of all READ_PRIV data valid cycles. | ||
2761 | * ctr2 : Overflow of Counter 0. | ||
2762 | * ctr3 : Overflow of Counter 1. | ||
2763 | */ | ||
2764 | |||
2765 | { | ||
2766 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
2767 | 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2768 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2769 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2770 | 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2771 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2772 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2773 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2774 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2775 | 0x00000000, 0x00000000, 0x00001b00, 0xaa000000, | ||
2776 | 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000, | ||
2777 | 0x01b00000, 0x00000000, 0x00001037, 0x00000000, | ||
2778 | 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000, | ||
2779 | 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff, | ||
2780 | 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000, | ||
2781 | 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3, | ||
2782 | 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff, | ||
2783 | 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000, | ||
2784 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30, | ||
2785 | 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5, | ||
2786 | 0x40000000, 0x00000000, 0x731c0000, 0x000156ab, | ||
2787 | 0xfc000000, 0x00000000, 0xffff0000, 0x00000000, | ||
2788 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2789 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2790 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2791 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2792 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2793 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2794 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2795 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2796 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2797 | 0xfe000000, 0x00000000, 0x00100000, 0x00000000, | ||
2798 | 0xf8000000, 0x00000000, 0x00000000, 0x00000000, | ||
2799 | 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, | ||
2800 | 0x00ffffff, 0xffffffff, 0x00000000, 0x00000000, | ||
2801 | 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, | ||
2802 | }, | ||
2803 | |||
2804 | |||
2805 | /* rw_wdfet image (Image 16) | ||
2806 | * | ||
2807 | * ctr0 : Counts total number of writeback transactions. | ||
2808 | * ctr1 : Total number of data valid Runway cycles. | ||
2809 | * ctr2 : Overflow of Counter 0. | ||
2810 | * ctr3 : Overflow of Counter 1. | ||
2811 | */ | ||
2812 | |||
2813 | { | ||
2814 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
2815 | 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2816 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2817 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2818 | 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2819 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2820 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2821 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2822 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2823 | 0x00000000, 0x00000000, 0x00001b00, 0xaa000000, | ||
2824 | 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000, | ||
2825 | 0x01b00000, 0x00000000, 0x00001037, 0x00000000, | ||
2826 | 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000, | ||
2827 | 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff, | ||
2828 | 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000, | ||
2829 | 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3, | ||
2830 | 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff, | ||
2831 | 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000, | ||
2832 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30, | ||
2833 | 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5, | ||
2834 | 0x40000000, 0x00000000, 0x731c0000, 0x000156ab, | ||
2835 | 0xfc000000, 0x00000000, 0xffff0000, 0x00000000, | ||
2836 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2837 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2838 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2839 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2840 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2841 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2842 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2843 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2844 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2845 | 0xfe000000, 0x00000000, 0x00100000, 0x00000000, | ||
2846 | 0x98000000, 0x00000000, 0x00000000, 0x00000000, | ||
2847 | 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, | ||
2848 | 0x00ffffff, 0xffffffff, 0x00000000, 0x00000000, | ||
2849 | 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, | ||
2850 | }, | ||
2851 | |||
2852 | /* shlib_cpi image (Image 17) | ||
2853 | * | ||
2854 | * ctr0 : Total number of instructions in quadrant 0. | ||
2855 | * ctr1 : Total number of CPU clock cycles in quadrant 0. | ||
2856 | * ctr2 : Total number of Non-Nullified instructions retired. | ||
2857 | * ctr3 : Total number of CPU clock cycles. | ||
2858 | * | ||
2859 | * Only works for 32-bit shared libraries. | ||
2860 | */ | ||
2861 | |||
2862 | { | ||
2863 | 0x0c01e000, 0x00000000, 0x00060000, 0x00000000, | ||
2864 | 0xe0e0e0e0, 0x00001fff, 0xfc00007f, 0xfff00001, | ||
2865 | 0xffffc000, 0x07ffff00, 0x07ffffff, 0x0007ffff, | ||
2866 | 0xff0007ff, 0xffff0007, 0xffffff00, 0x00000000, | ||
2867 | 0xf0150000, 0x0fffff00, 0x000fffff, 0xffffffff, | ||
2868 | 0xffffffff, 0xffff0000, 0x00000000, 0x00ffffff, | ||
2869 | 0xffcff000, 0x0000000f, 0xfffffffc, 0xffffffff, | ||
2870 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2871 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2872 | 0x00000000, 0x00000000, 0x27000000, 0x00000055, | ||
2873 | 0x02000005, 0x7f500000, 0xc0000000, 0x000ff270, | ||
2874 | 0x00000000, 0x00000000, 0x00007700, 0x00000ff0, | ||
2875 | 0x00000000, 0x0000ffff, 0xffffffff, 0xffffff00, | ||
2876 | 0x00000000, 0x0000ff00, 0x00000000, 0x0f0fffff, | ||
2877 | 0xffffffff, 0xfffff000, 0x00000000, 0x000ff000, | ||
2878 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffff0000, | ||
2879 | 0x00000000, 0x00ff0000, 0x00000000, 0xf0ffffff, | ||
2880 | 0xffffffff, 0xffff0000, 0x00000000, 0x00ff0000, | ||
2881 | 0x00000000, 0x0fffffff, 0xffffffff, 0xfff00000, | ||
2882 | 0x00000000, 0x0ff00000, 0x000000a0, 0x3fffffff, | ||
2883 | 0xffffffff, 0xffc00000, 0x03d40000, 0x20000000, | ||
2884 | 0x0003fc00, 0x00000000, 0xffff0000, 0x00000000, | ||
2885 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2886 | 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000, | ||
2887 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2888 | 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2889 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2890 | 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f, | ||
2891 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2892 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2893 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2894 | 0xfe000000, 0x00000000, 0x00030000, 0x00000000, | ||
2895 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2896 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2897 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2898 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2899 | }, | ||
2900 | |||
2901 | /* flop image (Image 18) | ||
2902 | * | ||
2903 | * ctr0 : Total number of floating point instructions (opcode = 0xc). | ||
2904 | * ctr1 : Total number of floating point instructions (opcode = 0xe, 0x6, 0x2e, 0x26). | ||
2905 | * ctr2 : Unused | ||
2906 | * ctr3 : Unused | ||
2907 | */ | ||
2908 | |||
2909 | { | ||
2910 | 0x0001e000, 0x00000000, 0x00000000, 0x00000000, | ||
2911 | 0x00001010, 0x33ffffff, 0x006fffff, 0xfc5fffff, | ||
2912 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2913 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2914 | 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2915 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2916 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2917 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2918 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2919 | 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, | ||
2920 | 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, | ||
2921 | 0x90000000, 0x00000000, 0x0000907e, 0x00000000, | ||
2922 | 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, | ||
2923 | 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, | ||
2924 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
2925 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
2926 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
2927 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
2928 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
2929 | 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, | ||
2930 | 0x00000000, 0x00000002, 0x67840000, 0x00000000, | ||
2931 | 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, | ||
2932 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2933 | 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, | ||
2934 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2935 | 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2936 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2937 | 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2938 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2939 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2940 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2941 | 0xfe000000, 0x00000000, 0x00130000, 0x00000000, | ||
2942 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2943 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2944 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2945 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2946 | }, | ||
2947 | |||
2948 | /* cachemiss image FROM I_D_MISSES.IDF (Image 19) | ||
2949 | * | ||
2950 | * ctr0 : icache misses for retired instructions | ||
2951 | * ctr1 : total cycles | ||
2952 | * ctr2 : dcache misses for retired instructions | ||
2953 | * ctr3 : number of retired instructions | ||
2954 | */ | ||
2955 | { | ||
2956 | 0x2801e000, 0x00000000, 0x00010000, 0x00000000, | ||
2957 | 0x00001000, 0xffffffff, 0xffffffff, 0xfff00fff, | ||
2958 | 0xfffa3fff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2959 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
2960 | 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2961 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
2962 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2963 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2964 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
2965 | 0x00000000, 0x00000000, 0xf2fdf0f0, 0xf0f0f0f0, | ||
2966 | 0xffffffff, 0xf6c00000, 0x00000000, 0x0ff55800, | ||
2967 | 0x90000000, 0x00000000, 0x0000b0ff, 0xfffffff0, | ||
2968 | 0x00000003, 0x0100bfff, 0x3f3f3f3f, 0x3f3f5555, | ||
2969 | 0x555fffff, 0xffffff00, 0x00000000, 0x000fffff, | ||
2970 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
2971 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
2972 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
2973 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
2974 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
2975 | 0xffffffff, 0xfff00000, 0x000301b0, 0x2fefcfcf, | ||
2976 | 0xcfcfcfcf, 0xd5555557, 0xf7b40000, 0x00000000, | ||
2977 | 0x03c14000, 0x00000000, 0xffff0000, 0x00000000, | ||
2978 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
2979 | 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, | ||
2980 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
2981 | 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2982 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2983 | 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
2984 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
2985 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2986 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
2987 | 0xfe000000, 0x00000000, 0x00130000, 0x00000000, | ||
2988 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2989 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2990 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2991 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
2992 | }, | ||
2993 | |||
2994 | /* branch FROM br_report3.idf | ||
2995 | * | ||
2996 | * ctr0 : Total number of mispredicted branches. | ||
2997 | * ctr1 : Some Non-Nullified unpredictable branches. | ||
2998 | * ctr2 : Total number of branches (Nullified + Non-Nullified) | ||
2999 | * (Unpredicted+ Predicted Taken +Predicted Not Taken). | ||
3000 | * Total of All Branches. | ||
3001 | * ctr3 : Remaining Non-Nullified unpredictable branches. | ||
3002 | */ | ||
3003 | { | ||
3004 | 0x4001e000, 0x00000000, 0x00000000, 0x00000000, | ||
3005 | 0x00000000, 0xffffffff, 0xff9fffff, 0xfe0fffff, | ||
3006 | 0xffffbaff, 0xfdffc0ff, 0xfffdffff, 0xfffffeff, | ||
3007 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
3008 | 0xf4ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3009 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
3010 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3011 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3012 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
3013 | 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, | ||
3014 | 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, | ||
3015 | 0x90000000, 0x00000000, 0x0000907e, 0x00000000, | ||
3016 | 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, | ||
3017 | 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, | ||
3018 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
3019 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
3020 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
3021 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
3022 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
3023 | 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, | ||
3024 | 0x00000000, 0x00000002, 0x67840000, 0x00000000, | ||
3025 | 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, | ||
3026 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
3027 | 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, | ||
3028 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
3029 | 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
3030 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
3031 | 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
3032 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
3033 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
3034 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
3035 | 0xfe000000, 0x00000000, 0x00130000, 0x00000000, | ||
3036 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3037 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3038 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3039 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3040 | }, | ||
3041 | |||
3042 | /* crstack FROM crs_report.idf | ||
3043 | * | ||
3044 | * ctr0: correctly predicted branches by the pop_latch | ||
3045 | * ctr1: some procedure returns | ||
3046 | * ctr2: all branches, (includes nullified) | ||
3047 | * ctr3: remaining procedure returns | ||
3048 | */ | ||
3049 | { | ||
3050 | 0x4001e000, 0x00000000, 0x00000000, 0x00000000, | ||
3051 | 0x00000000, 0xffffffff, 0xffa10300, 0x000fffff, | ||
3052 | 0xffffbaf8, 0x3000007f, 0xffffffff, 0xfffffeff, | ||
3053 | 0xff7fffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
3054 | 0xf2ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3055 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
3056 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3057 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3058 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
3059 | 0x00000000, 0x00000000, 0xd22d0000, 0x00000000, | ||
3060 | 0x0000000b, 0x46000000, 0x00000000, 0x0ffff900, | ||
3061 | 0x90000000, 0x00000000, 0x0000907e, 0x00000000, | ||
3062 | 0x000000ff, 0xff00bfdf, 0x03030303, 0x03030000, | ||
3063 | 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, | ||
3064 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
3065 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
3066 | 0xffffffff, 0xffff0000, 0x00000000, 0xf0ffffff, | ||
3067 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
3068 | 0x00000000, 0x0fffffff, 0xffffffff, 0xffffffff, | ||
3069 | 0xffff5555, 0x55500000, 0x003f3ff0, 0x2766c000, | ||
3070 | 0x00000000, 0x00000002, 0x67840000, 0x00000000, | ||
3071 | 0x03fffc00, 0x00000000, 0xffff0000, 0x00000000, | ||
3072 | 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
3073 | 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, | ||
3074 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
3075 | 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
3076 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
3077 | 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
3078 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
3079 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
3080 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
3081 | 0xfe000000, 0x00000000, 0x00130000, 0x00000000, | ||
3082 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3083 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3084 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3085 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3086 | }, | ||
3087 | |||
3088 | /* icache_report image | ||
3089 | * | ||
3090 | * ctr0 : Icache misses actually used by the core. | ||
3091 | * ctr1 : ICORE_AV (Icache misses the core THINKS it needs, including fetching down speculative paths). | ||
3092 | * ctr2 : READs on Runway (Icache misses that made it out to Runway, including | ||
3093 | * prefetches). | ||
3094 | * ctr3 : Prefetch returns (1x and 2x). | ||
3095 | */ | ||
3096 | { | ||
3097 | 0x00000000, 0x00000000, 0x00010000, 0x00000000, | ||
3098 | 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3099 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3100 | 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000, | ||
3101 | 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3102 | 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, | ||
3103 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3104 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3105 | 0xffff0000, 0x00000000, 0x00000000, 0x00000000, | ||
3106 | 0x00000000, 0x00000000, 0xd2002d00, 0x00000000, | ||
3107 | 0x0000000b, 0x46000000, 0x0000000f, 0xf00ff900, | ||
3108 | 0x00900000, 0x00000000, 0x0000907e, 0x00000000, | ||
3109 | 0x0000ff00, 0xff83bf03, 0xdf030303, 0x03030000, | ||
3110 | 0x000dbfff, 0xffffff00, 0x00000000, 0x000fffff, | ||
3111 | 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff000, | ||
3112 | 0x00000000, 0x00ffffff, 0xffffffff, 0xffffffff, | ||
3113 | 0xffffffff, 0xffff0000, 0x00000000, 0x80ffffff, | ||
3114 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0000, | ||
3115 | 0x00000000, 0x4fffffff, 0xffffffff, 0xffffffff, | ||
3116 | 0xffff5555, 0x55500000, 0x3f003f80, 0x274026c0, | ||
3117 | 0x00000000, 0x00000002, 0x67840000, 0x00000003, | ||
3118 | 0xfc03fc00, 0x00000000, 0x0eff0000, 0x00000000, | ||
3119 | 0x00000000, 0x00000000, 0x00ffffff, 0xff3fffff, | ||
3120 | 0xffffffff, 0xffcfffff, 0xfff6fb7c, 0x00000000, | ||
3121 | 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff, | ||
3122 | 0xfff6fb7c, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
3123 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
3124 | 0x00000000, 0x00000000, 0xffff0fff, 0xffffff3f, | ||
3125 | 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc, | ||
3126 | 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
3127 | 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff, | ||
3128 | 0xfe000000, 0x00000000, 0x00130000, 0x00000000, | ||
3129 | 0xd0ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3130 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3131 | 0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3132 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
3133 | |||
3134 | } | ||
3135 | |||
3136 | }; | ||
3137 | |||
3138 | #endif | ||
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c new file mode 100644 index 000000000000..46e4a6881f11 --- /dev/null +++ b/arch/parisc/kernel/process.c | |||
@@ -0,0 +1,396 @@ | |||
1 | /* | ||
2 | * PARISC Architecture-dependent parts of process handling | ||
3 | * based on the work for i386 | ||
4 | * | ||
5 | * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org> | ||
6 | * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net> | ||
7 | * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org> | ||
8 | * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org> | ||
9 | * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org> | ||
10 | * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org> | ||
11 | * Copyright (C) 2000 David Kennedy <dkennedy with linuxcare.com> | ||
12 | * Copyright (C) 2000 Richard Hirst <rhirst with parisc-lixux.org> | ||
13 | * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org> | ||
14 | * Copyright (C) 2001 Alan Modra <amodra at parisc-linux.org> | ||
15 | * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org> | ||
16 | * Copyright (C) 2001-2002 Helge Deller <deller at parisc-linux.org> | ||
17 | * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> | ||
18 | * | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation; either version 2 of the License, or | ||
23 | * (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License | ||
31 | * along with this program; if not, write to the Free Software | ||
32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
33 | */ | ||
34 | |||
35 | #include <stdarg.h> | ||
36 | |||
37 | #include <linux/elf.h> | ||
38 | #include <linux/errno.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/mm.h> | ||
41 | #include <linux/module.h> | ||
42 | #include <linux/personality.h> | ||
43 | #include <linux/ptrace.h> | ||
44 | #include <linux/sched.h> | ||
45 | #include <linux/stddef.h> | ||
46 | #include <linux/unistd.h> | ||
47 | #include <linux/kallsyms.h> | ||
48 | |||
49 | #include <asm/io.h> | ||
50 | #include <asm/offsets.h> | ||
51 | #include <asm/pdc.h> | ||
52 | #include <asm/pdc_chassis.h> | ||
53 | #include <asm/pgalloc.h> | ||
54 | #include <asm/uaccess.h> | ||
55 | #include <asm/unwind.h> | ||
56 | |||
57 | static int hlt_counter; | ||
58 | |||
59 | /* | ||
60 | * Power off function, if any | ||
61 | */ | ||
62 | void (*pm_power_off)(void); | ||
63 | |||
64 | void disable_hlt(void) | ||
65 | { | ||
66 | hlt_counter++; | ||
67 | } | ||
68 | |||
69 | EXPORT_SYMBOL(disable_hlt); | ||
70 | |||
71 | void enable_hlt(void) | ||
72 | { | ||
73 | hlt_counter--; | ||
74 | } | ||
75 | |||
76 | EXPORT_SYMBOL(enable_hlt); | ||
77 | |||
78 | void default_idle(void) | ||
79 | { | ||
80 | barrier(); | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * The idle thread. There's no useful work to be | ||
85 | * done, so just try to conserve power and have a | ||
86 | * low exit latency (ie sit in a loop waiting for | ||
87 | * somebody to say that they'd like to reschedule) | ||
88 | */ | ||
89 | void cpu_idle(void) | ||
90 | { | ||
91 | /* endless idle loop with no priority at all */ | ||
92 | while (1) { | ||
93 | while (!need_resched()) | ||
94 | barrier(); | ||
95 | schedule(); | ||
96 | check_pgt_cache(); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | |||
101 | #ifdef __LP64__ | ||
102 | #define COMMAND_GLOBAL 0xfffffffffffe0030UL | ||
103 | #else | ||
104 | #define COMMAND_GLOBAL 0xfffe0030 | ||
105 | #endif | ||
106 | |||
107 | #define CMD_RESET 5 /* reset any module */ | ||
108 | |||
109 | /* | ||
110 | ** The Wright Brothers and Gecko systems have a H/W problem | ||
111 | ** (Lasi...'nuf said) may cause a broadcast reset to lockup | ||
112 | ** the system. An HVERSION dependent PDC call was developed | ||
113 | ** to perform a "safe", platform specific broadcast reset instead | ||
114 | ** of kludging up all the code. | ||
115 | ** | ||
116 | ** Older machines which do not implement PDC_BROADCAST_RESET will | ||
117 | ** return (with an error) and the regular broadcast reset can be | ||
118 | ** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET | ||
119 | ** the PDC call will not return (the system will be reset). | ||
120 | */ | ||
121 | void machine_restart(char *cmd) | ||
122 | { | ||
123 | #ifdef FASTBOOT_SELFTEST_SUPPORT | ||
124 | /* | ||
125 | ** If user has modified the Firmware Selftest Bitmap, | ||
126 | ** run the tests specified in the bitmap after the | ||
127 | ** system is rebooted w/PDC_DO_RESET. | ||
128 | ** | ||
129 | ** ftc_bitmap = 0x1AUL "Skip destructive memory tests" | ||
130 | ** | ||
131 | ** Using "directed resets" at each processor with the MEM_TOC | ||
132 | ** vector cleared will also avoid running destructive | ||
133 | ** memory self tests. (Not implemented yet) | ||
134 | */ | ||
135 | if (ftc_bitmap) { | ||
136 | pdc_do_firm_test_reset(ftc_bitmap); | ||
137 | } | ||
138 | #endif | ||
139 | /* set up a new led state on systems shipped with a LED State panel */ | ||
140 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); | ||
141 | |||
142 | /* "Normal" system reset */ | ||
143 | pdc_do_reset(); | ||
144 | |||
145 | /* Nope...box should reset with just CMD_RESET now */ | ||
146 | gsc_writel(CMD_RESET, COMMAND_GLOBAL); | ||
147 | |||
148 | /* Wait for RESET to lay us to rest. */ | ||
149 | while (1) ; | ||
150 | |||
151 | } | ||
152 | |||
153 | EXPORT_SYMBOL(machine_restart); | ||
154 | |||
155 | void machine_halt(void) | ||
156 | { | ||
157 | /* | ||
158 | ** The LED/ChassisCodes are updated by the led_halt() | ||
159 | ** function, called by the reboot notifier chain. | ||
160 | */ | ||
161 | } | ||
162 | |||
163 | EXPORT_SYMBOL(machine_halt); | ||
164 | |||
165 | |||
166 | /* | ||
167 | * This routine is called from sys_reboot to actually turn off the | ||
168 | * machine | ||
169 | */ | ||
170 | void machine_power_off(void) | ||
171 | { | ||
172 | /* If there is a registered power off handler, call it. */ | ||
173 | if(pm_power_off) | ||
174 | pm_power_off(); | ||
175 | |||
176 | /* Put the soft power button back under hardware control. | ||
177 | * If the user had already pressed the power button, the | ||
178 | * following call will immediately power off. */ | ||
179 | pdc_soft_power_button(0); | ||
180 | |||
181 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); | ||
182 | |||
183 | /* It seems we have no way to power the system off via | ||
184 | * software. The user has to press the button himself. */ | ||
185 | |||
186 | printk(KERN_EMERG "System shut down completed.\n" | ||
187 | KERN_EMERG "Please power this system off now."); | ||
188 | } | ||
189 | |||
190 | EXPORT_SYMBOL(machine_power_off); | ||
191 | |||
192 | |||
193 | /* | ||
194 | * Create a kernel thread | ||
195 | */ | ||
196 | |||
197 | extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
198 | pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
199 | { | ||
200 | |||
201 | /* | ||
202 | * FIXME: Once we are sure we don't need any debug here, | ||
203 | * kernel_thread can become a #define. | ||
204 | */ | ||
205 | |||
206 | return __kernel_thread(fn, arg, flags); | ||
207 | } | ||
208 | EXPORT_SYMBOL(kernel_thread); | ||
209 | |||
210 | /* | ||
211 | * Free current thread data structures etc.. | ||
212 | */ | ||
213 | void exit_thread(void) | ||
214 | { | ||
215 | } | ||
216 | |||
217 | void flush_thread(void) | ||
218 | { | ||
219 | /* Only needs to handle fpu stuff or perf monitors. | ||
220 | ** REVISIT: several arches implement a "lazy fpu state". | ||
221 | */ | ||
222 | set_fs(USER_DS); | ||
223 | } | ||
224 | |||
225 | void release_thread(struct task_struct *dead_task) | ||
226 | { | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * Fill in the FPU structure for a core dump. | ||
231 | */ | ||
232 | |||
233 | int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r) | ||
234 | { | ||
235 | if (regs == NULL) | ||
236 | return 0; | ||
237 | |||
238 | memcpy(r, regs->fr, sizeof *r); | ||
239 | return 1; | ||
240 | } | ||
241 | |||
242 | int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r) | ||
243 | { | ||
244 | memcpy(r, tsk->thread.regs.fr, sizeof(*r)); | ||
245 | return 1; | ||
246 | } | ||
247 | |||
248 | /* Note that "fork()" is implemented in terms of clone, with | ||
249 | parameters (SIGCHLD, regs->gr[30], regs). */ | ||
250 | int | ||
251 | sys_clone(unsigned long clone_flags, unsigned long usp, | ||
252 | struct pt_regs *regs) | ||
253 | { | ||
254 | int __user *user_tid = (int __user *)regs->gr[26]; | ||
255 | |||
256 | /* usp must be word aligned. This also prevents users from | ||
257 | * passing in the value 1 (which is the signal for a special | ||
258 | * return for a kernel thread) */ | ||
259 | usp = ALIGN(usp, 4); | ||
260 | |||
261 | /* A zero value for usp means use the current stack */ | ||
262 | if(usp == 0) | ||
263 | usp = regs->gr[30]; | ||
264 | |||
265 | return do_fork(clone_flags, usp, regs, 0, user_tid, NULL); | ||
266 | } | ||
267 | |||
268 | int | ||
269 | sys_vfork(struct pt_regs *regs) | ||
270 | { | ||
271 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL); | ||
272 | } | ||
273 | |||
274 | int | ||
275 | copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | ||
276 | unsigned long unused, /* in ia64 this is "user_stack_size" */ | ||
277 | struct task_struct * p, struct pt_regs * pregs) | ||
278 | { | ||
279 | struct pt_regs * cregs = &(p->thread.regs); | ||
280 | struct thread_info *ti = p->thread_info; | ||
281 | |||
282 | /* We have to use void * instead of a function pointer, because | ||
283 | * function pointers aren't a pointer to the function on 64-bit. | ||
284 | * Make them const so the compiler knows they live in .text */ | ||
285 | extern void * const ret_from_kernel_thread; | ||
286 | extern void * const child_return; | ||
287 | #ifdef CONFIG_HPUX | ||
288 | extern void * const hpux_child_return; | ||
289 | #endif | ||
290 | |||
291 | *cregs = *pregs; | ||
292 | |||
293 | /* Set the return value for the child. Note that this is not | ||
294 | actually restored by the syscall exit path, but we put it | ||
295 | here for consistency in case of signals. */ | ||
296 | cregs->gr[28] = 0; /* child */ | ||
297 | |||
298 | /* | ||
299 | * We need to differentiate between a user fork and a | ||
300 | * kernel fork. We can't use user_mode, because the | ||
301 | * the syscall path doesn't save iaoq. Right now | ||
302 | * We rely on the fact that kernel_thread passes | ||
303 | * in zero for usp. | ||
304 | */ | ||
305 | if (usp == 1) { | ||
306 | /* kernel thread */ | ||
307 | cregs->ksp = (((unsigned long)(ti)) + THREAD_SZ_ALGN); | ||
308 | /* Must exit via ret_from_kernel_thread in order | ||
309 | * to call schedule_tail() | ||
310 | */ | ||
311 | cregs->kpc = (unsigned long) &ret_from_kernel_thread; | ||
312 | /* | ||
313 | * Copy function and argument to be called from | ||
314 | * ret_from_kernel_thread. | ||
315 | */ | ||
316 | #ifdef __LP64__ | ||
317 | cregs->gr[27] = pregs->gr[27]; | ||
318 | #endif | ||
319 | cregs->gr[26] = pregs->gr[26]; | ||
320 | cregs->gr[25] = pregs->gr[25]; | ||
321 | } else { | ||
322 | /* user thread */ | ||
323 | /* | ||
324 | * Note that the fork wrappers are responsible | ||
325 | * for setting gr[21]. | ||
326 | */ | ||
327 | |||
328 | /* Use same stack depth as parent */ | ||
329 | cregs->ksp = ((unsigned long)(ti)) | ||
330 | + (pregs->gr[21] & (THREAD_SIZE - 1)); | ||
331 | cregs->gr[30] = usp; | ||
332 | if (p->personality == PER_HPUX) { | ||
333 | #ifdef CONFIG_HPUX | ||
334 | cregs->kpc = (unsigned long) &hpux_child_return; | ||
335 | #else | ||
336 | BUG(); | ||
337 | #endif | ||
338 | } else { | ||
339 | cregs->kpc = (unsigned long) &child_return; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | unsigned long thread_saved_pc(struct task_struct *t) | ||
347 | { | ||
348 | return t->thread.regs.kpc; | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * sys_execve() executes a new program. | ||
353 | */ | ||
354 | |||
355 | asmlinkage int sys_execve(struct pt_regs *regs) | ||
356 | { | ||
357 | int error; | ||
358 | char *filename; | ||
359 | |||
360 | filename = getname((const char __user *) regs->gr[26]); | ||
361 | error = PTR_ERR(filename); | ||
362 | if (IS_ERR(filename)) | ||
363 | goto out; | ||
364 | error = do_execve(filename, (char __user **) regs->gr[25], | ||
365 | (char __user **) regs->gr[24], regs); | ||
366 | if (error == 0) { | ||
367 | task_lock(current); | ||
368 | current->ptrace &= ~PT_DTRACE; | ||
369 | task_unlock(current); | ||
370 | } | ||
371 | putname(filename); | ||
372 | out: | ||
373 | |||
374 | return error; | ||
375 | } | ||
376 | |||
377 | unsigned long | ||
378 | get_wchan(struct task_struct *p) | ||
379 | { | ||
380 | struct unwind_frame_info info; | ||
381 | unsigned long ip; | ||
382 | int count = 0; | ||
383 | /* | ||
384 | * These bracket the sleeping functions.. | ||
385 | */ | ||
386 | |||
387 | unwind_frame_init_from_blocked_task(&info, p); | ||
388 | do { | ||
389 | if (unwind_once(&info) < 0) | ||
390 | return 0; | ||
391 | ip = info.ip; | ||
392 | if (!in_sched_functions(ip)) | ||
393 | return ip; | ||
394 | } while (count++ < 16); | ||
395 | return 0; | ||
396 | } | ||
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c new file mode 100644 index 000000000000..13b721cb9f55 --- /dev/null +++ b/arch/parisc/kernel/processor.c | |||
@@ -0,0 +1,400 @@ | |||
1 | /* $Id: processor.c,v 1.1 2002/07/20 16:27:06 rhirst Exp $ | ||
2 | * | ||
3 | * Initial setup-routines for HP 9000 based hardware. | ||
4 | * | ||
5 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
6 | * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de> | ||
7 | * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf) | ||
8 | * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net> | ||
9 | * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org> | ||
10 | * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net> | ||
11 | * | ||
12 | * Initial PA-RISC Version: 04-23-1999 by Helge Deller | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2, or (at your option) | ||
17 | * any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | * | ||
28 | */ | ||
29 | #include <linux/config.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/cpu.h> | ||
37 | |||
38 | #include <asm/cache.h> | ||
39 | #include <asm/hardware.h> /* for register_parisc_driver() stuff */ | ||
40 | #include <asm/processor.h> | ||
41 | #include <asm/page.h> | ||
42 | #include <asm/pdc.h> | ||
43 | #include <asm/pdcpat.h> | ||
44 | #include <asm/irq.h> /* for struct irq_region */ | ||
45 | #include <asm/parisc-device.h> | ||
46 | |||
47 | struct system_cpuinfo_parisc boot_cpu_data; | ||
48 | EXPORT_SYMBOL(boot_cpu_data); | ||
49 | |||
50 | struct cpuinfo_parisc cpu_data[NR_CPUS]; | ||
51 | |||
52 | /* | ||
53 | ** PARISC CPU driver - claim "device" and initialize CPU data structures. | ||
54 | ** | ||
55 | ** Consolidate per CPU initialization into (mostly) one module. | ||
56 | ** Monarch CPU will initialize boot_cpu_data which shouldn't | ||
57 | ** change once the system has booted. | ||
58 | ** | ||
59 | ** The callback *should* do per-instance initialization of | ||
60 | ** everything including the monarch. "Per CPU" init code in | ||
61 | ** setup.c:start_parisc() has migrated here and start_parisc() | ||
62 | ** will call register_parisc_driver(&cpu_driver) before calling do_inventory(). | ||
63 | ** | ||
64 | ** The goal of consolidating CPU initialization into one place is | ||
65 | ** to make sure all CPU's get initialized the same way. | ||
66 | ** The code path not shared is how PDC hands control of the CPU to the OS. | ||
67 | ** The initialization of OS data structures is the same (done below). | ||
68 | */ | ||
69 | |||
70 | /** | ||
71 | * processor_probe - Determine if processor driver should claim this device. | ||
72 | * @dev: The device which has been found. | ||
73 | * | ||
74 | * Determine if processor driver should claim this chip (return 0) or not | ||
75 | * (return 1). If so, initialize the chip and tell other partners in crime | ||
76 | * they have work to do. | ||
77 | */ | ||
78 | static int __init processor_probe(struct parisc_device *dev) | ||
79 | { | ||
80 | unsigned long txn_addr; | ||
81 | unsigned long cpuid; | ||
82 | struct cpuinfo_parisc *p; | ||
83 | |||
84 | #ifndef CONFIG_SMP | ||
85 | if (boot_cpu_data.cpu_count > 0) { | ||
86 | printk(KERN_INFO "CONFIG_SMP=n ignoring additional CPUs\n"); | ||
87 | return 1; | ||
88 | } | ||
89 | #endif | ||
90 | |||
91 | /* logical CPU ID and update global counter | ||
92 | * May get overwritten by PAT code. | ||
93 | */ | ||
94 | cpuid = boot_cpu_data.cpu_count; | ||
95 | txn_addr = dev->hpa; /* for legacy PDC */ | ||
96 | |||
97 | #ifdef __LP64__ | ||
98 | if (is_pdc_pat()) { | ||
99 | ulong status; | ||
100 | unsigned long bytecnt; | ||
101 | pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; | ||
102 | #undef USE_PAT_CPUID | ||
103 | #ifdef USE_PAT_CPUID | ||
104 | struct pdc_pat_cpu_num cpu_info; | ||
105 | #endif | ||
106 | |||
107 | status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc, | ||
108 | dev->mod_index, PA_VIEW, &pa_pdc_cell); | ||
109 | |||
110 | BUG_ON(PDC_OK != status); | ||
111 | |||
112 | /* verify it's the same as what do_pat_inventory() found */ | ||
113 | BUG_ON(dev->mod_info != pa_pdc_cell.mod_info); | ||
114 | BUG_ON(dev->pmod_loc != pa_pdc_cell.mod_location); | ||
115 | |||
116 | txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */ | ||
117 | |||
118 | #ifdef USE_PAT_CPUID | ||
119 | /* We need contiguous numbers for cpuid. Firmware's notion | ||
120 | * of cpuid is for physical CPUs and we just don't care yet. | ||
121 | * We'll care when we need to query PAT PDC about a CPU *after* | ||
122 | * boot time (ie shutdown a CPU from an OS perspective). | ||
123 | */ | ||
124 | /* get the cpu number */ | ||
125 | status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa); | ||
126 | |||
127 | BUG_ON(PDC_OK != status); | ||
128 | |||
129 | if (cpu_info.cpu_num >= NR_CPUS) { | ||
130 | printk(KERN_WARNING "IGNORING CPU at 0x%x," | ||
131 | " cpu_slot_id > NR_CPUS" | ||
132 | " (%ld > %d)\n", | ||
133 | dev->hpa, cpu_info.cpu_num, NR_CPUS); | ||
134 | /* Ignore CPU since it will only crash */ | ||
135 | boot_cpu_data.cpu_count--; | ||
136 | return 1; | ||
137 | } else { | ||
138 | cpuid = cpu_info.cpu_num; | ||
139 | } | ||
140 | #endif | ||
141 | } | ||
142 | #endif | ||
143 | |||
144 | p = &cpu_data[cpuid]; | ||
145 | boot_cpu_data.cpu_count++; | ||
146 | |||
147 | /* initialize counters */ | ||
148 | memset(p, 0, sizeof(struct cpuinfo_parisc)); | ||
149 | |||
150 | p->loops_per_jiffy = loops_per_jiffy; | ||
151 | p->dev = dev; /* Save IODC data in case we need it */ | ||
152 | p->hpa = dev->hpa; /* save CPU hpa */ | ||
153 | p->cpuid = cpuid; /* save CPU id */ | ||
154 | p->txn_addr = txn_addr; /* save CPU IRQ address */ | ||
155 | #ifdef CONFIG_SMP | ||
156 | spin_lock_init(&p->lock); | ||
157 | |||
158 | /* | ||
159 | ** FIXME: review if any other initialization is clobbered | ||
160 | ** for boot_cpu by the above memset(). | ||
161 | */ | ||
162 | |||
163 | /* stolen from init_percpu_prof() */ | ||
164 | cpu_data[cpuid].prof_counter = 1; | ||
165 | cpu_data[cpuid].prof_multiplier = 1; | ||
166 | #endif | ||
167 | |||
168 | /* | ||
169 | ** CONFIG_SMP: init_smp_config() will attempt to get CPU's into | ||
170 | ** OS control. RENDEZVOUS is the default state - see mem_set above. | ||
171 | ** p->state = STATE_RENDEZVOUS; | ||
172 | */ | ||
173 | |||
174 | #if 0 | ||
175 | /* CPU 0 IRQ table is statically allocated/initialized */ | ||
176 | if (cpuid) { | ||
177 | struct irqaction actions[]; | ||
178 | |||
179 | /* | ||
180 | ** itimer and ipi IRQ handlers are statically initialized in | ||
181 | ** arch/parisc/kernel/irq.c. ie Don't need to register them. | ||
182 | */ | ||
183 | actions = kmalloc(sizeof(struct irqaction)*MAX_CPU_IRQ, GFP_ATOMIC); | ||
184 | if (!actions) { | ||
185 | /* not getting it's own table, share with monarch */ | ||
186 | actions = cpu_irq_actions[0]; | ||
187 | } | ||
188 | |||
189 | cpu_irq_actions[cpuid] = actions; | ||
190 | } | ||
191 | #endif | ||
192 | |||
193 | /* | ||
194 | * Bring this CPU up now! (ignore bootstrap cpuid == 0) | ||
195 | */ | ||
196 | #ifdef CONFIG_SMP | ||
197 | if (cpuid) { | ||
198 | cpu_set(cpuid, cpu_present_map); | ||
199 | cpu_up(cpuid); | ||
200 | } | ||
201 | #endif | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * collect_boot_cpu_data - Fill the boot_cpu_data structure. | ||
208 | * | ||
209 | * This function collects and stores the generic processor information | ||
210 | * in the boot_cpu_data structure. | ||
211 | */ | ||
212 | void __init collect_boot_cpu_data(void) | ||
213 | { | ||
214 | memset(&boot_cpu_data, 0, sizeof(boot_cpu_data)); | ||
215 | |||
216 | boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ | ||
217 | |||
218 | /* get CPU-Model Information... */ | ||
219 | #define p ((unsigned long *)&boot_cpu_data.pdc.model) | ||
220 | if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK) | ||
221 | printk(KERN_INFO | ||
222 | "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
223 | p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); | ||
224 | #undef p | ||
225 | |||
226 | if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK) | ||
227 | printk(KERN_INFO "vers %08lx\n", | ||
228 | boot_cpu_data.pdc.versions); | ||
229 | |||
230 | if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK) | ||
231 | printk(KERN_INFO "CPUID vers %ld rev %ld (0x%08lx)\n", | ||
232 | (boot_cpu_data.pdc.cpuid >> 5) & 127, | ||
233 | boot_cpu_data.pdc.cpuid & 31, | ||
234 | boot_cpu_data.pdc.cpuid); | ||
235 | |||
236 | if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK) | ||
237 | printk(KERN_INFO "capabilities 0x%lx\n", | ||
238 | boot_cpu_data.pdc.capabilities); | ||
239 | |||
240 | if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name) == PDC_OK) | ||
241 | printk(KERN_INFO "model %s\n", | ||
242 | boot_cpu_data.pdc.sys_model_name); | ||
243 | |||
244 | boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion; | ||
245 | boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion; | ||
246 | |||
247 | boot_cpu_data.cpu_type = parisc_get_cpu_type(boot_cpu_data.hversion); | ||
248 | boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0]; | ||
249 | boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1]; | ||
250 | } | ||
251 | |||
252 | |||
253 | /** | ||
254 | * init_cpu_profiler - enable/setup per cpu profiling hooks. | ||
255 | * @cpunum: The processor instance. | ||
256 | * | ||
257 | * FIXME: doesn't do much yet... | ||
258 | */ | ||
259 | static inline void __init | ||
260 | init_percpu_prof(int cpunum) | ||
261 | { | ||
262 | cpu_data[cpunum].prof_counter = 1; | ||
263 | cpu_data[cpunum].prof_multiplier = 1; | ||
264 | } | ||
265 | |||
266 | |||
267 | /** | ||
268 | * init_per_cpu - Handle individual processor initializations. | ||
269 | * @cpunum: logical processor number. | ||
270 | * | ||
271 | * This function handles initialization for *every* CPU | ||
272 | * in the system: | ||
273 | * | ||
274 | * o Set "default" CPU width for trap handlers | ||
275 | * | ||
276 | * o Enable FP coprocessor | ||
277 | * REVISIT: this could be done in the "code 22" trap handler. | ||
278 | * (frowands idea - that way we know which processes need FP | ||
279 | * registers saved on the interrupt stack.) | ||
280 | * NEWS FLASH: wide kernels need FP coprocessor enabled to handle | ||
281 | * formatted printing of %lx for example (double divides I think) | ||
282 | * | ||
283 | * o Enable CPU profiling hooks. | ||
284 | */ | ||
285 | int __init init_per_cpu(int cpunum) | ||
286 | { | ||
287 | int ret; | ||
288 | struct pdc_coproc_cfg coproc_cfg; | ||
289 | |||
290 | set_firmware_width(); | ||
291 | ret = pdc_coproc_cfg(&coproc_cfg); | ||
292 | |||
293 | if(ret >= 0 && coproc_cfg.ccr_functional) { | ||
294 | mtctl(coproc_cfg.ccr_functional, 10); /* 10 == Coprocessor Control Reg */ | ||
295 | |||
296 | /* FWIW, FP rev/model is a more accurate way to determine | ||
297 | ** CPU type. CPU rev/model has some ambiguous cases. | ||
298 | */ | ||
299 | cpu_data[cpunum].fp_rev = coproc_cfg.revision; | ||
300 | cpu_data[cpunum].fp_model = coproc_cfg.model; | ||
301 | |||
302 | printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n", | ||
303 | cpunum, coproc_cfg.revision, coproc_cfg.model); | ||
304 | |||
305 | /* | ||
306 | ** store status register to stack (hopefully aligned) | ||
307 | ** and clear the T-bit. | ||
308 | */ | ||
309 | asm volatile ("fstd %fr0,8(%sp)"); | ||
310 | |||
311 | } else { | ||
312 | printk(KERN_WARNING "WARNING: No FP CoProcessor?!" | ||
313 | " (coproc_cfg.ccr_functional == 0x%lx, expected 0xc0)\n" | ||
314 | #ifdef __LP64__ | ||
315 | "Halting Machine - FP required\n" | ||
316 | #endif | ||
317 | , coproc_cfg.ccr_functional); | ||
318 | #ifdef __LP64__ | ||
319 | mdelay(100); /* previous chars get pushed to console */ | ||
320 | panic("FP CoProc not reported"); | ||
321 | #endif | ||
322 | } | ||
323 | |||
324 | /* FUTURE: Enable Performance Monitor : ccr bit 0x20 */ | ||
325 | init_percpu_prof(cpunum); | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Display cpu info for all cpu's. | ||
332 | */ | ||
333 | int | ||
334 | show_cpuinfo (struct seq_file *m, void *v) | ||
335 | { | ||
336 | int n; | ||
337 | |||
338 | for(n=0; n<boot_cpu_data.cpu_count; n++) { | ||
339 | #ifdef CONFIG_SMP | ||
340 | if (0 == cpu_data[n].hpa) | ||
341 | continue; | ||
342 | #ifdef ENTRY_SYS_CPUS | ||
343 | #error iCOD support wants to show CPU state here | ||
344 | #endif | ||
345 | #endif | ||
346 | seq_printf(m, "processor\t: %d\n" | ||
347 | "cpu family\t: PA-RISC %s\n", | ||
348 | n, boot_cpu_data.family_name); | ||
349 | |||
350 | seq_printf(m, "cpu\t\t: %s\n", boot_cpu_data.cpu_name ); | ||
351 | |||
352 | /* cpu MHz */ | ||
353 | seq_printf(m, "cpu MHz\t\t: %d.%06d\n", | ||
354 | boot_cpu_data.cpu_hz / 1000000, | ||
355 | boot_cpu_data.cpu_hz % 1000000 ); | ||
356 | |||
357 | seq_printf(m, "model\t\t: %s\n" | ||
358 | "model name\t: %s\n", | ||
359 | boot_cpu_data.pdc.sys_model_name, | ||
360 | cpu_data[n].dev ? | ||
361 | cpu_data[n].dev->name : "Unknown" ); | ||
362 | |||
363 | seq_printf(m, "hversion\t: 0x%08x\n" | ||
364 | "sversion\t: 0x%08x\n", | ||
365 | boot_cpu_data.hversion, | ||
366 | boot_cpu_data.sversion ); | ||
367 | |||
368 | /* print cachesize info */ | ||
369 | show_cache_info(m); | ||
370 | |||
371 | seq_printf(m, "bogomips\t: %lu.%02lu\n", | ||
372 | cpu_data[n].loops_per_jiffy / (500000 / HZ), | ||
373 | (cpu_data[n].loops_per_jiffy / (5000 / HZ)) % 100); | ||
374 | |||
375 | seq_printf(m, "software id\t: %ld\n\n", | ||
376 | boot_cpu_data.pdc.model.sw_id); | ||
377 | } | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static struct parisc_device_id processor_tbl[] = { | ||
382 | { HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID }, | ||
383 | { 0, } | ||
384 | }; | ||
385 | |||
386 | static struct parisc_driver cpu_driver = { | ||
387 | .name = "CPU", | ||
388 | .id_table = processor_tbl, | ||
389 | .probe = processor_probe | ||
390 | }; | ||
391 | |||
392 | /** | ||
393 | * processor_init - Processor initalization procedure. | ||
394 | * | ||
395 | * Register this driver. | ||
396 | */ | ||
397 | void __init processor_init(void) | ||
398 | { | ||
399 | register_parisc_driver(&cpu_driver); | ||
400 | } | ||
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c new file mode 100644 index 000000000000..2937a9236384 --- /dev/null +++ b/arch/parisc/kernel/ptrace.c | |||
@@ -0,0 +1,423 @@ | |||
1 | /* | ||
2 | * Kernel support for the ptrace() and syscall tracing interfaces. | ||
3 | * | ||
4 | * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc. | ||
5 | * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx> | ||
6 | * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org> | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/smp_lock.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/ptrace.h> | ||
16 | #include <linux/user.h> | ||
17 | #include <linux/personality.h> | ||
18 | #include <linux/security.h> | ||
19 | #include <linux/compat.h> | ||
20 | |||
21 | #include <asm/uaccess.h> | ||
22 | #include <asm/pgtable.h> | ||
23 | #include <asm/system.h> | ||
24 | #include <asm/processor.h> | ||
25 | #include <asm/offsets.h> | ||
26 | |||
27 | /* PSW bits we allow the debugger to modify */ | ||
28 | #define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB) | ||
29 | |||
30 | #undef DEBUG_PTRACE | ||
31 | |||
32 | #ifdef DEBUG_PTRACE | ||
33 | #define DBG(x...) printk(x) | ||
34 | #else | ||
35 | #define DBG(x...) | ||
36 | #endif | ||
37 | |||
38 | #ifdef __LP64__ | ||
39 | |||
40 | /* This function is needed to translate 32 bit pt_regs offsets in to | ||
41 | * 64 bit pt_regs offsets. For example, a 32 bit gdb under a 64 bit kernel | ||
42 | * will request offset 12 if it wants gr3, but the lower 32 bits of | ||
43 | * the 64 bit kernels view of gr3 will be at offset 28 (3*8 + 4). | ||
44 | * This code relies on a 32 bit pt_regs being comprised of 32 bit values | ||
45 | * except for the fp registers which (a) are 64 bits, and (b) follow | ||
46 | * the gr registers at the start of pt_regs. The 32 bit pt_regs should | ||
47 | * be half the size of the 64 bit pt_regs, plus 32*4 to allow for fr[] | ||
48 | * being 64 bit in both cases. | ||
49 | */ | ||
50 | |||
51 | static long translate_usr_offset(long offset) | ||
52 | { | ||
53 | if (offset < 0) | ||
54 | return -1; | ||
55 | else if (offset <= 32*4) /* gr[0..31] */ | ||
56 | return offset * 2 + 4; | ||
57 | else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */ | ||
58 | return offset + 32*4; | ||
59 | else if (offset < sizeof(struct pt_regs)/2 + 32*4) | ||
60 | return offset * 2 + 4 - 32*8; | ||
61 | else | ||
62 | return -1; | ||
63 | } | ||
64 | #endif | ||
65 | |||
66 | /* | ||
67 | * Called by kernel/ptrace.c when detaching.. | ||
68 | * | ||
69 | * Make sure single step bits etc are not set. | ||
70 | */ | ||
71 | void ptrace_disable(struct task_struct *child) | ||
72 | { | ||
73 | /* make sure the trap bits are not set */ | ||
74 | pa_psw(child)->r = 0; | ||
75 | pa_psw(child)->t = 0; | ||
76 | pa_psw(child)->h = 0; | ||
77 | pa_psw(child)->l = 0; | ||
78 | } | ||
79 | |||
80 | long sys_ptrace(long request, pid_t pid, long addr, long data) | ||
81 | { | ||
82 | struct task_struct *child; | ||
83 | long ret; | ||
84 | #ifdef DEBUG_PTRACE | ||
85 | long oaddr=addr, odata=data; | ||
86 | #endif | ||
87 | |||
88 | lock_kernel(); | ||
89 | ret = -EPERM; | ||
90 | if (request == PTRACE_TRACEME) { | ||
91 | /* are we already being traced? */ | ||
92 | if (current->ptrace & PT_PTRACED) | ||
93 | goto out; | ||
94 | |||
95 | ret = security_ptrace(current->parent, current); | ||
96 | if (ret) | ||
97 | goto out; | ||
98 | |||
99 | /* set the ptrace bit in the process flags. */ | ||
100 | current->ptrace |= PT_PTRACED; | ||
101 | ret = 0; | ||
102 | goto out; | ||
103 | } | ||
104 | |||
105 | ret = -ESRCH; | ||
106 | read_lock(&tasklist_lock); | ||
107 | child = find_task_by_pid(pid); | ||
108 | if (child) | ||
109 | get_task_struct(child); | ||
110 | read_unlock(&tasklist_lock); | ||
111 | if (!child) | ||
112 | goto out; | ||
113 | ret = -EPERM; | ||
114 | if (pid == 1) /* no messing around with init! */ | ||
115 | goto out_tsk; | ||
116 | |||
117 | if (request == PTRACE_ATTACH) { | ||
118 | ret = ptrace_attach(child); | ||
119 | goto out_tsk; | ||
120 | } | ||
121 | |||
122 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | ||
123 | if (ret < 0) | ||
124 | goto out_tsk; | ||
125 | |||
126 | switch (request) { | ||
127 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
128 | case PTRACE_PEEKDATA: { | ||
129 | int copied; | ||
130 | |||
131 | #ifdef __LP64__ | ||
132 | if (is_compat_task(child)) { | ||
133 | unsigned int tmp; | ||
134 | |||
135 | addr &= 0xffffffffL; | ||
136 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
137 | ret = -EIO; | ||
138 | if (copied != sizeof(tmp)) | ||
139 | goto out_tsk; | ||
140 | ret = put_user(tmp,(unsigned int *) data); | ||
141 | DBG("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n", | ||
142 | request == PTRACE_PEEKTEXT ? "TEXT" : "DATA", | ||
143 | pid, oaddr, odata, ret, tmp); | ||
144 | } | ||
145 | else | ||
146 | #endif | ||
147 | { | ||
148 | unsigned long tmp; | ||
149 | |||
150 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
151 | ret = -EIO; | ||
152 | if (copied != sizeof(tmp)) | ||
153 | goto out_tsk; | ||
154 | ret = put_user(tmp,(unsigned long *) data); | ||
155 | } | ||
156 | goto out_tsk; | ||
157 | } | ||
158 | |||
159 | /* when I and D space are separate, this will have to be fixed. */ | ||
160 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
161 | case PTRACE_POKEDATA: | ||
162 | ret = 0; | ||
163 | #ifdef __LP64__ | ||
164 | if (is_compat_task(child)) { | ||
165 | unsigned int tmp = (unsigned int)data; | ||
166 | DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n", | ||
167 | request == PTRACE_POKETEXT ? "TEXT" : "DATA", | ||
168 | pid, oaddr, odata); | ||
169 | addr &= 0xffffffffL; | ||
170 | if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp)) | ||
171 | goto out_tsk; | ||
172 | } | ||
173 | else | ||
174 | #endif | ||
175 | { | ||
176 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
177 | goto out_tsk; | ||
178 | } | ||
179 | ret = -EIO; | ||
180 | goto out_tsk; | ||
181 | |||
182 | /* Read the word at location addr in the USER area. For ptraced | ||
183 | processes, the kernel saves all regs on a syscall. */ | ||
184 | case PTRACE_PEEKUSR: { | ||
185 | ret = -EIO; | ||
186 | #ifdef __LP64__ | ||
187 | if (is_compat_task(child)) { | ||
188 | unsigned int tmp; | ||
189 | |||
190 | if (addr & (sizeof(int)-1)) | ||
191 | goto out_tsk; | ||
192 | if ((addr = translate_usr_offset(addr)) < 0) | ||
193 | goto out_tsk; | ||
194 | |||
195 | tmp = *(unsigned int *) ((char *) task_regs(child) + addr); | ||
196 | ret = put_user(tmp, (unsigned int *) data); | ||
197 | DBG("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n", | ||
198 | pid, oaddr, odata, ret, addr, tmp); | ||
199 | } | ||
200 | else | ||
201 | #endif | ||
202 | { | ||
203 | unsigned long tmp; | ||
204 | |||
205 | if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs)) | ||
206 | goto out_tsk; | ||
207 | tmp = *(unsigned long *) ((char *) task_regs(child) + addr); | ||
208 | ret = put_user(tmp, (unsigned long *) data); | ||
209 | } | ||
210 | goto out_tsk; | ||
211 | } | ||
212 | |||
213 | /* Write the word at location addr in the USER area. This will need | ||
214 | to change when the kernel no longer saves all regs on a syscall. | ||
215 | FIXME. There is a problem at the moment in that r3-r18 are only | ||
216 | saved if the process is ptraced on syscall entry, and even then | ||
217 | those values are overwritten by actual register values on syscall | ||
218 | exit. */ | ||
219 | case PTRACE_POKEUSR: | ||
220 | ret = -EIO; | ||
221 | /* Some register values written here may be ignored in | ||
222 | * entry.S:syscall_restore_rfi; e.g. iaoq is written with | ||
223 | * r31/r31+4, and not with the values in pt_regs. | ||
224 | */ | ||
225 | /* PT_PSW=0, so this is valid for 32 bit processes under 64 | ||
226 | * bit kernels. | ||
227 | */ | ||
228 | if (addr == PT_PSW) { | ||
229 | /* PT_PSW=0, so this is valid for 32 bit processes | ||
230 | * under 64 bit kernels. | ||
231 | * | ||
232 | * Allow writing to Nullify, Divide-step-correction, | ||
233 | * and carry/borrow bits. | ||
234 | * BEWARE, if you set N, and then single step, it won't | ||
235 | * stop on the nullified instruction. | ||
236 | */ | ||
237 | DBG("sys_ptrace(POKEUSR, %d, %lx, %lx)\n", | ||
238 | pid, oaddr, odata); | ||
239 | data &= USER_PSW_BITS; | ||
240 | task_regs(child)->gr[0] &= ~USER_PSW_BITS; | ||
241 | task_regs(child)->gr[0] |= data; | ||
242 | ret = 0; | ||
243 | goto out_tsk; | ||
244 | } | ||
245 | #ifdef __LP64__ | ||
246 | if (is_compat_task(child)) { | ||
247 | if (addr & (sizeof(int)-1)) | ||
248 | goto out_tsk; | ||
249 | if ((addr = translate_usr_offset(addr)) < 0) | ||
250 | goto out_tsk; | ||
251 | DBG("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n", | ||
252 | pid, oaddr, odata, addr); | ||
253 | if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { | ||
254 | /* Special case, fp regs are 64 bits anyway */ | ||
255 | *(unsigned int *) ((char *) task_regs(child) + addr) = data; | ||
256 | ret = 0; | ||
257 | } | ||
258 | else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) || | ||
259 | addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 || | ||
260 | addr == PT_SAR+4) { | ||
261 | /* Zero the top 32 bits */ | ||
262 | *(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0; | ||
263 | *(unsigned int *) ((char *) task_regs(child) + addr) = data; | ||
264 | ret = 0; | ||
265 | } | ||
266 | goto out_tsk; | ||
267 | } | ||
268 | else | ||
269 | #endif | ||
270 | { | ||
271 | if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs)) | ||
272 | goto out_tsk; | ||
273 | if ((addr >= PT_GR1 && addr <= PT_GR31) || | ||
274 | addr == PT_IAOQ0 || addr == PT_IAOQ1 || | ||
275 | (addr >= PT_FR0 && addr <= PT_FR31 + 4) || | ||
276 | addr == PT_SAR) { | ||
277 | *(unsigned long *) ((char *) task_regs(child) + addr) = data; | ||
278 | ret = 0; | ||
279 | } | ||
280 | goto out_tsk; | ||
281 | } | ||
282 | |||
283 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
284 | case PTRACE_CONT: | ||
285 | ret = -EIO; | ||
286 | DBG("sys_ptrace(%s)\n", | ||
287 | request == PTRACE_SYSCALL ? "SYSCALL" : "CONT"); | ||
288 | if ((unsigned long) data > _NSIG) | ||
289 | goto out_tsk; | ||
290 | child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); | ||
291 | if (request == PTRACE_SYSCALL) { | ||
292 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
293 | } else { | ||
294 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
295 | } | ||
296 | child->exit_code = data; | ||
297 | goto out_wake_notrap; | ||
298 | |||
299 | case PTRACE_KILL: | ||
300 | /* | ||
301 | * make the child exit. Best I can do is send it a | ||
302 | * sigkill. perhaps it should be put in the status | ||
303 | * that it wants to exit. | ||
304 | */ | ||
305 | DBG("sys_ptrace(KILL)\n"); | ||
306 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
307 | goto out_tsk; | ||
308 | child->exit_code = SIGKILL; | ||
309 | goto out_wake_notrap; | ||
310 | |||
311 | case PTRACE_SINGLEBLOCK: | ||
312 | DBG("sys_ptrace(SINGLEBLOCK)\n"); | ||
313 | ret = -EIO; | ||
314 | if ((unsigned long) data > _NSIG) | ||
315 | goto out_tsk; | ||
316 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
317 | child->ptrace &= ~PT_SINGLESTEP; | ||
318 | child->ptrace |= PT_BLOCKSTEP; | ||
319 | child->exit_code = data; | ||
320 | |||
321 | /* Enable taken branch trap. */ | ||
322 | pa_psw(child)->r = 0; | ||
323 | pa_psw(child)->t = 1; | ||
324 | pa_psw(child)->h = 0; | ||
325 | pa_psw(child)->l = 0; | ||
326 | goto out_wake; | ||
327 | |||
328 | case PTRACE_SINGLESTEP: | ||
329 | DBG("sys_ptrace(SINGLESTEP)\n"); | ||
330 | ret = -EIO; | ||
331 | if ((unsigned long) data > _NSIG) | ||
332 | goto out_tsk; | ||
333 | |||
334 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
335 | child->ptrace &= ~PT_BLOCKSTEP; | ||
336 | child->ptrace |= PT_SINGLESTEP; | ||
337 | child->exit_code = data; | ||
338 | |||
339 | if (pa_psw(child)->n) { | ||
340 | struct siginfo si; | ||
341 | |||
342 | /* Nullified, just crank over the queue. */ | ||
343 | task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1]; | ||
344 | task_regs(child)->iasq[0] = task_regs(child)->iasq[1]; | ||
345 | task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4; | ||
346 | pa_psw(child)->n = 0; | ||
347 | pa_psw(child)->x = 0; | ||
348 | pa_psw(child)->y = 0; | ||
349 | pa_psw(child)->z = 0; | ||
350 | pa_psw(child)->b = 0; | ||
351 | ptrace_disable(child); | ||
352 | /* Don't wake up the child, but let the | ||
353 | parent know something happened. */ | ||
354 | si.si_code = TRAP_TRACE; | ||
355 | si.si_addr = (void __user *) (task_regs(child)->iaoq[0] & ~3); | ||
356 | si.si_signo = SIGTRAP; | ||
357 | si.si_errno = 0; | ||
358 | force_sig_info(SIGTRAP, &si, child); | ||
359 | //notify_parent(child, SIGCHLD); | ||
360 | //ret = 0; | ||
361 | goto out_wake; | ||
362 | } | ||
363 | |||
364 | /* Enable recovery counter traps. The recovery counter | ||
365 | * itself will be set to zero on a task switch. If the | ||
366 | * task is suspended on a syscall then the syscall return | ||
367 | * path will overwrite the recovery counter with a suitable | ||
368 | * value such that it traps once back in user space. We | ||
369 | * disable interrupts in the childs PSW here also, to avoid | ||
370 | * interrupts while the recovery counter is decrementing. | ||
371 | */ | ||
372 | pa_psw(child)->r = 1; | ||
373 | pa_psw(child)->t = 0; | ||
374 | pa_psw(child)->h = 0; | ||
375 | pa_psw(child)->l = 0; | ||
376 | /* give it a chance to run. */ | ||
377 | goto out_wake; | ||
378 | |||
379 | case PTRACE_DETACH: | ||
380 | ret = ptrace_detach(child, data); | ||
381 | goto out_tsk; | ||
382 | |||
383 | case PTRACE_GETEVENTMSG: | ||
384 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); | ||
385 | goto out_tsk; | ||
386 | |||
387 | default: | ||
388 | ret = ptrace_request(child, request, addr, data); | ||
389 | goto out_tsk; | ||
390 | } | ||
391 | |||
392 | out_wake_notrap: | ||
393 | ptrace_disable(child); | ||
394 | out_wake: | ||
395 | wake_up_process(child); | ||
396 | ret = 0; | ||
397 | out_tsk: | ||
398 | put_task_struct(child); | ||
399 | out: | ||
400 | unlock_kernel(); | ||
401 | DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n", | ||
402 | request, pid, oaddr, odata, ret); | ||
403 | return ret; | ||
404 | } | ||
405 | |||
406 | void syscall_trace(void) | ||
407 | { | ||
408 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
409 | return; | ||
410 | if (!(current->ptrace & PT_PTRACED)) | ||
411 | return; | ||
412 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | ||
413 | ? 0x80 : 0)); | ||
414 | /* | ||
415 | * this isn't the same as continuing with a signal, but it will do | ||
416 | * for normal use. strace only continues with a signal if the | ||
417 | * stopping signal is not SIGTRAP. -brl | ||
418 | */ | ||
419 | if (current->exit_code) { | ||
420 | send_sig(current->exit_code, current, 1); | ||
421 | current->exit_code = 0; | ||
422 | } | ||
423 | } | ||
diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S new file mode 100644 index 000000000000..8dd5defb7316 --- /dev/null +++ b/arch/parisc/kernel/real2.S | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * | ||
3 | * This file is subject to the terms and conditions of the GNU General Public | ||
4 | * License. See the file "COPYING" in the main directory of this archive | ||
5 | * for more details. | ||
6 | * | ||
7 | * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com) | ||
8 | * | ||
9 | */ | ||
10 | #include <asm/assembly.h> | ||
11 | #include <asm/psw.h> | ||
12 | |||
13 | .section .bss | ||
14 | .export real_stack | ||
15 | .export real32_stack | ||
16 | .export real64_stack | ||
17 | .align 64 | ||
18 | real_stack: | ||
19 | real32_stack: | ||
20 | real64_stack: | ||
21 | .block 8192 | ||
22 | |||
23 | #ifdef __LP64__ | ||
24 | # define REG_SZ 8 | ||
25 | #else | ||
26 | # define REG_SZ 4 | ||
27 | #endif | ||
28 | |||
29 | #define N_SAVED_REGS 9 | ||
30 | |||
31 | save_cr_space: | ||
32 | .block REG_SZ * N_SAVED_REGS | ||
33 | save_cr_end: | ||
34 | |||
35 | |||
36 | /************************ 32-bit real-mode calls ***********************/ | ||
37 | /* This can be called in both narrow and wide kernels */ | ||
38 | |||
39 | .text | ||
40 | |||
41 | .export real32_call_asm | ||
42 | |||
43 | /* unsigned long real32_call_asm(unsigned int *sp, | ||
44 | * unsigned int *arg0p, | ||
45 | * unsigned int iodc_fn) | ||
46 | * sp is value of stack pointer to adopt before calling PDC (virt) | ||
47 | * arg0p points to where saved arg values may be found | ||
48 | * iodc_fn is the IODC function to call | ||
49 | */ | ||
50 | |||
51 | real32_call_asm: | ||
52 | STREG %rp, -RP_OFFSET(%sp) /* save RP */ | ||
53 | #ifdef __LP64__ | ||
54 | callee_save | ||
55 | ldo 2*REG_SZ(%sp), %sp /* room for a couple more saves */ | ||
56 | STREG %r27, -1*REG_SZ(%sp) | ||
57 | STREG %r29, -2*REG_SZ(%sp) | ||
58 | #endif | ||
59 | STREG %sp, -REG_SZ(%arg0) /* save SP on real-mode stack */ | ||
60 | copy %arg0, %sp /* adopt the real-mode SP */ | ||
61 | |||
62 | /* save iodc_fn */ | ||
63 | copy %arg2, %r31 | ||
64 | |||
65 | /* load up the arg registers from the saved arg area */ | ||
66 | /* 32-bit calling convention passes first 4 args in registers */ | ||
67 | ldw 0(%arg1), %arg0 /* note overwriting arg0 */ | ||
68 | ldw -8(%arg1), %arg2 | ||
69 | ldw -12(%arg1), %arg3 | ||
70 | ldw -4(%arg1), %arg1 /* obviously must do this one last! */ | ||
71 | |||
72 | tophys_r1 %sp | ||
73 | |||
74 | b,l rfi_virt2real,%r2 | ||
75 | nop | ||
76 | |||
77 | b,l save_control_regs,%r2 /* modifies r1, r2, r28 */ | ||
78 | nop | ||
79 | |||
80 | #ifdef __LP64__ | ||
81 | rsm PSW_SM_W, %r0 /* go narrow */ | ||
82 | #endif | ||
83 | |||
84 | load32 PA(ric_ret), %r2 | ||
85 | bv 0(%r31) | ||
86 | nop | ||
87 | ric_ret: | ||
88 | #ifdef __LP64__ | ||
89 | ssm PSW_SM_W, %r0 /* go wide */ | ||
90 | #endif | ||
91 | /* restore CRs before going virtual in case we page fault */ | ||
92 | b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */ | ||
93 | nop | ||
94 | |||
95 | b,l rfi_real2virt,%r2 | ||
96 | nop | ||
97 | |||
98 | tovirt_r1 %sp | ||
99 | LDREG -REG_SZ(%sp), %sp /* restore SP */ | ||
100 | #ifdef __LP64__ | ||
101 | LDREG -1*REG_SZ(%sp), %r27 | ||
102 | LDREG -2*REG_SZ(%sp), %r29 | ||
103 | ldo -2*REG_SZ(%sp), %sp | ||
104 | callee_rest | ||
105 | #endif | ||
106 | LDREG -RP_OFFSET(%sp), %rp /* restore RP */ | ||
107 | bv 0(%rp) | ||
108 | nop | ||
109 | |||
110 | |||
111 | # define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where) | ||
112 | # define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r | ||
113 | |||
114 | .text | ||
115 | save_control_regs: | ||
116 | load32 PA(save_cr_space), %r28 | ||
117 | PUSH_CR(%cr24, %r28) | ||
118 | PUSH_CR(%cr25, %r28) | ||
119 | PUSH_CR(%cr26, %r28) | ||
120 | PUSH_CR(%cr27, %r28) | ||
121 | PUSH_CR(%cr28, %r28) | ||
122 | PUSH_CR(%cr29, %r28) | ||
123 | PUSH_CR(%cr30, %r28) | ||
124 | PUSH_CR(%cr31, %r28) | ||
125 | PUSH_CR(%cr15, %r28) | ||
126 | bv 0(%r2) | ||
127 | nop | ||
128 | |||
129 | restore_control_regs: | ||
130 | load32 PA(save_cr_end), %r26 | ||
131 | POP_CR(%cr15, %r26) | ||
132 | POP_CR(%cr31, %r26) | ||
133 | POP_CR(%cr30, %r26) | ||
134 | POP_CR(%cr29, %r26) | ||
135 | POP_CR(%cr28, %r26) | ||
136 | POP_CR(%cr27, %r26) | ||
137 | POP_CR(%cr26, %r26) | ||
138 | POP_CR(%cr25, %r26) | ||
139 | POP_CR(%cr24, %r26) | ||
140 | bv 0(%r2) | ||
141 | nop | ||
142 | |||
143 | /* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for | ||
144 | * more general-purpose use by the several places which need RFIs | ||
145 | */ | ||
146 | .align 128 | ||
147 | .text | ||
148 | rfi_virt2real: | ||
149 | /* switch to real mode... */ | ||
150 | ssm 0,0 /* See "relied upon translation" */ | ||
151 | nop /* PA 2.0 Arch. F-5 */ | ||
152 | nop | ||
153 | nop | ||
154 | nop | ||
155 | nop | ||
156 | nop | ||
157 | nop | ||
158 | nop | ||
159 | |||
160 | rsm (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q & I bits to load iia queue */ | ||
161 | mtctl %r0, %cr17 /* Clear IIASQ tail */ | ||
162 | mtctl %r0, %cr17 /* Clear IIASQ head */ | ||
163 | load32 PA(rfi_v2r_1), %r1 | ||
164 | mtctl %r1, %cr18 /* IIAOQ head */ | ||
165 | ldo 4(%r1), %r1 | ||
166 | mtctl %r1, %cr18 /* IIAOQ tail */ | ||
167 | load32 REAL_MODE_PSW, %r1 | ||
168 | mtctl %r1, %cr22 | ||
169 | rfi | ||
170 | |||
171 | nop | ||
172 | nop | ||
173 | nop | ||
174 | nop | ||
175 | nop | ||
176 | nop | ||
177 | nop | ||
178 | nop | ||
179 | rfi_v2r_1: | ||
180 | tophys_r1 %r2 | ||
181 | bv 0(%r2) | ||
182 | nop | ||
183 | |||
184 | .text | ||
185 | .align 128 | ||
186 | rfi_real2virt: | ||
187 | ssm 0,0 /* See "relied upon translation" */ | ||
188 | nop /* PA 2.0 Arch. F-5 */ | ||
189 | nop | ||
190 | nop | ||
191 | nop | ||
192 | nop | ||
193 | nop | ||
194 | nop | ||
195 | nop | ||
196 | |||
197 | rsm PSW_SM_Q,%r0 /* disable Q bit to load iia queue */ | ||
198 | mtctl %r0, %cr17 /* Clear IIASQ tail */ | ||
199 | mtctl %r0, %cr17 /* Clear IIASQ head */ | ||
200 | load32 (rfi_r2v_1), %r1 | ||
201 | mtctl %r1, %cr18 /* IIAOQ head */ | ||
202 | ldo 4(%r1), %r1 | ||
203 | mtctl %r1, %cr18 /* IIAOQ tail */ | ||
204 | load32 KERNEL_PSW, %r1 | ||
205 | mtctl %r1, %cr22 | ||
206 | rfi | ||
207 | |||
208 | nop | ||
209 | nop | ||
210 | nop | ||
211 | nop | ||
212 | nop | ||
213 | nop | ||
214 | nop | ||
215 | nop | ||
216 | rfi_r2v_1: | ||
217 | tovirt_r1 %r2 | ||
218 | bv 0(%r2) | ||
219 | nop | ||
220 | |||
221 | #ifdef __LP64__ | ||
222 | |||
223 | /************************ 64-bit real-mode calls ***********************/ | ||
224 | /* This is only usable in wide kernels right now and will probably stay so */ | ||
225 | .text | ||
226 | .export real64_call_asm | ||
227 | /* unsigned long real64_call_asm(unsigned long *sp, | ||
228 | * unsigned long *arg0p, | ||
229 | * unsigned long fn) | ||
230 | * sp is value of stack pointer to adopt before calling PDC (virt) | ||
231 | * arg0p points to where saved arg values may be found | ||
232 | * iodc_fn is the IODC function to call | ||
233 | */ | ||
234 | real64_call_asm: | ||
235 | std %rp, -0x10(%sp) /* save RP */ | ||
236 | std %sp, -8(%arg0) /* save SP on real-mode stack */ | ||
237 | copy %arg0, %sp /* adopt the real-mode SP */ | ||
238 | |||
239 | /* save fn */ | ||
240 | copy %arg2, %r31 | ||
241 | |||
242 | /* set up the new ap */ | ||
243 | ldo 64(%arg1), %r29 | ||
244 | |||
245 | /* load up the arg registers from the saved arg area */ | ||
246 | /* 32-bit calling convention passes first 4 args in registers */ | ||
247 | ldd 0*REG_SZ(%arg1), %arg0 /* note overwriting arg0 */ | ||
248 | ldd 2*REG_SZ(%arg1), %arg2 | ||
249 | ldd 3*REG_SZ(%arg1), %arg3 | ||
250 | ldd 4*REG_SZ(%arg1), %r22 | ||
251 | ldd 5*REG_SZ(%arg1), %r21 | ||
252 | ldd 6*REG_SZ(%arg1), %r20 | ||
253 | ldd 7*REG_SZ(%arg1), %r19 | ||
254 | ldd 1*REG_SZ(%arg1), %arg1 /* do this one last! */ | ||
255 | |||
256 | tophys_r1 %sp | ||
257 | |||
258 | b,l rfi_virt2real,%r2 | ||
259 | nop | ||
260 | |||
261 | b,l save_control_regs,%r2 /* modifies r1, r2, r28 */ | ||
262 | nop | ||
263 | |||
264 | load32 PA(r64_ret), %r2 | ||
265 | bv 0(%r31) | ||
266 | nop | ||
267 | r64_ret: | ||
268 | /* restore CRs before going virtual in case we page fault */ | ||
269 | b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */ | ||
270 | nop | ||
271 | |||
272 | b,l rfi_real2virt,%r2 | ||
273 | nop | ||
274 | |||
275 | tovirt_r1 %sp | ||
276 | ldd -8(%sp), %sp /* restore SP */ | ||
277 | ldd -0x10(%sp), %rp /* restore RP */ | ||
278 | bv 0(%rp) | ||
279 | nop | ||
280 | |||
281 | #endif | ||
282 | |||
283 | .export pc_in_user_space | ||
284 | .text | ||
285 | /* Doesn't belong here but I couldn't find a nicer spot. */ | ||
286 | /* Should never get called, only used by profile stuff in time.c */ | ||
287 | pc_in_user_space: | ||
288 | bv,n 0(%rp) | ||
289 | nop | ||
290 | |||
291 | |||
292 | .export __canonicalize_funcptr_for_compare | ||
293 | .text | ||
294 | /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html | ||
295 | ** GCC 3.3 and later has a new function in libgcc.a for | ||
296 | ** comparing function pointers. | ||
297 | */ | ||
298 | __canonicalize_funcptr_for_compare: | ||
299 | #ifdef __LP64__ | ||
300 | bve (%r2) | ||
301 | #else | ||
302 | bv %r0(%r2) | ||
303 | #endif | ||
304 | copy %r26,%r28 | ||
diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c new file mode 100644 index 000000000000..ee806bcc3726 --- /dev/null +++ b/arch/parisc/kernel/semaphore.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard | ||
3 | */ | ||
4 | |||
5 | #include <linux/sched.h> | ||
6 | #include <linux/spinlock.h> | ||
7 | #include <linux/errno.h> | ||
8 | #include <linux/init.h> | ||
9 | |||
10 | /* | ||
11 | * Semaphores are complex as we wish to avoid using two variables. | ||
12 | * `count' has multiple roles, depending on its value. If it is positive | ||
13 | * or zero, there are no waiters. The functions here will never be | ||
14 | * called; see <asm/semaphore.h> | ||
15 | * | ||
16 | * When count is -1 it indicates there is at least one task waiting | ||
17 | * for the semaphore. | ||
18 | * | ||
19 | * When count is less than that, there are '- count - 1' wakeups | ||
20 | * pending. ie if it has value -3, there are 2 wakeups pending. | ||
21 | * | ||
22 | * Note that these functions are only called when there is contention | ||
23 | * on the lock, and as such all this is the "non-critical" part of the | ||
24 | * whole semaphore business. The critical part is the inline stuff in | ||
25 | * <asm/semaphore.h> where we want to avoid any extra jumps and calls. | ||
26 | */ | ||
27 | void __up(struct semaphore *sem) | ||
28 | { | ||
29 | sem->count--; | ||
30 | wake_up(&sem->wait); | ||
31 | } | ||
32 | |||
33 | #define wakers(count) (-1 - count) | ||
34 | |||
35 | #define DOWN_HEAD \ | ||
36 | int ret = 0; \ | ||
37 | DECLARE_WAITQUEUE(wait, current); \ | ||
38 | \ | ||
39 | /* Note that someone is waiting */ \ | ||
40 | if (sem->count == 0) \ | ||
41 | sem->count = -1; \ | ||
42 | \ | ||
43 | /* protected by the sentry still -- use unlocked version */ \ | ||
44 | wait.flags = WQ_FLAG_EXCLUSIVE; \ | ||
45 | __add_wait_queue_tail(&sem->wait, &wait); \ | ||
46 | lost_race: \ | ||
47 | spin_unlock_irq(&sem->sentry); \ | ||
48 | |||
49 | #define DOWN_TAIL \ | ||
50 | spin_lock_irq(&sem->sentry); \ | ||
51 | if (wakers(sem->count) == 0 && ret == 0) \ | ||
52 | goto lost_race; /* Someone stole our wakeup */ \ | ||
53 | __remove_wait_queue(&sem->wait, &wait); \ | ||
54 | current->state = TASK_RUNNING; \ | ||
55 | if (!waitqueue_active(&sem->wait) && (sem->count < 0)) \ | ||
56 | sem->count = wakers(sem->count); | ||
57 | |||
58 | #define UPDATE_COUNT \ | ||
59 | sem->count += (sem->count < 0) ? 1 : - 1; | ||
60 | |||
61 | |||
62 | void __sched __down(struct semaphore * sem) | ||
63 | { | ||
64 | DOWN_HEAD | ||
65 | |||
66 | for(;;) { | ||
67 | set_task_state(current, TASK_UNINTERRUPTIBLE); | ||
68 | /* we can _read_ this without the sentry */ | ||
69 | if (sem->count != -1) | ||
70 | break; | ||
71 | schedule(); | ||
72 | } | ||
73 | |||
74 | DOWN_TAIL | ||
75 | UPDATE_COUNT | ||
76 | } | ||
77 | |||
78 | int __sched __down_interruptible(struct semaphore * sem) | ||
79 | { | ||
80 | DOWN_HEAD | ||
81 | |||
82 | for(;;) { | ||
83 | set_task_state(current, TASK_INTERRUPTIBLE); | ||
84 | /* we can _read_ this without the sentry */ | ||
85 | if (sem->count != -1) | ||
86 | break; | ||
87 | |||
88 | if (signal_pending(current)) { | ||
89 | ret = -EINTR; | ||
90 | break; | ||
91 | } | ||
92 | schedule(); | ||
93 | } | ||
94 | |||
95 | DOWN_TAIL | ||
96 | |||
97 | if (!ret) { | ||
98 | UPDATE_COUNT | ||
99 | } | ||
100 | |||
101 | return ret; | ||
102 | } | ||
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c new file mode 100644 index 000000000000..73e9c34b0948 --- /dev/null +++ b/arch/parisc/kernel/setup.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $ | ||
2 | * | ||
3 | * Initial setup-routines for HP 9000 based hardware. | ||
4 | * | ||
5 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
6 | * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de> | ||
7 | * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf) | ||
8 | * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net> | ||
9 | * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org> | ||
10 | * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net> | ||
11 | * | ||
12 | * Initial PA-RISC Version: 04-23-1999 by Helge Deller | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2, or (at your option) | ||
17 | * any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/config.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/initrd.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/console.h> | ||
35 | #include <linux/seq_file.h> | ||
36 | #define PCI_DEBUG | ||
37 | #include <linux/pci.h> | ||
38 | #undef PCI_DEBUG | ||
39 | #include <linux/proc_fs.h> | ||
40 | |||
41 | #include <asm/processor.h> | ||
42 | #include <asm/pdc.h> | ||
43 | #include <asm/led.h> | ||
44 | #include <asm/machdep.h> /* for pa7300lc_init() proto */ | ||
45 | #include <asm/pdc_chassis.h> | ||
46 | #include <asm/io.h> | ||
47 | #include <asm/setup.h> | ||
48 | |||
49 | char command_line[COMMAND_LINE_SIZE]; | ||
50 | |||
51 | /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */ | ||
52 | struct proc_dir_entry * proc_runway_root = NULL; | ||
53 | struct proc_dir_entry * proc_gsc_root = NULL; | ||
54 | struct proc_dir_entry * proc_mckinley_root = NULL; | ||
55 | |||
56 | #if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA)) | ||
57 | int parisc_bus_is_phys = 1; /* Assume no IOMMU is present */ | ||
58 | EXPORT_SYMBOL(parisc_bus_is_phys); | ||
59 | #endif | ||
60 | |||
61 | /* This sets the vmerge boundary and size, it's here because it has to | ||
62 | * be available on all platforms (zero means no-virtual merging) */ | ||
63 | unsigned long parisc_vmerge_boundary = 0; | ||
64 | unsigned long parisc_vmerge_max_size = 0; | ||
65 | |||
66 | void __init setup_cmdline(char **cmdline_p) | ||
67 | { | ||
68 | extern unsigned int boot_args[]; | ||
69 | |||
70 | /* Collect stuff passed in from the boot loader */ | ||
71 | |||
72 | /* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */ | ||
73 | if (boot_args[0] < 64) { | ||
74 | /* called from hpux boot loader */ | ||
75 | saved_command_line[0] = '\0'; | ||
76 | } else { | ||
77 | strcpy(saved_command_line, (char *)__va(boot_args[1])); | ||
78 | |||
79 | #ifdef CONFIG_BLK_DEV_INITRD | ||
80 | if (boot_args[2] != 0) /* did palo pass us a ramdisk? */ | ||
81 | { | ||
82 | initrd_start = (unsigned long)__va(boot_args[2]); | ||
83 | initrd_end = (unsigned long)__va(boot_args[3]); | ||
84 | } | ||
85 | #endif | ||
86 | } | ||
87 | |||
88 | strcpy(command_line, saved_command_line); | ||
89 | *cmdline_p = command_line; | ||
90 | } | ||
91 | |||
92 | #ifdef CONFIG_PA11 | ||
93 | void __init dma_ops_init(void) | ||
94 | { | ||
95 | switch (boot_cpu_data.cpu_type) { | ||
96 | case pcx: | ||
97 | /* | ||
98 | * We've got way too many dependencies on 1.1 semantics | ||
99 | * to support 1.0 boxes at this point. | ||
100 | */ | ||
101 | panic( "PA-RISC Linux currently only supports machines that conform to\n" | ||
102 | "the PA-RISC 1.1 or 2.0 architecture specification.\n"); | ||
103 | |||
104 | case pcxs: | ||
105 | case pcxt: | ||
106 | hppa_dma_ops = &pcx_dma_ops; | ||
107 | break; | ||
108 | case pcxl2: | ||
109 | pa7300lc_init(); | ||
110 | case pcxl: /* falls through */ | ||
111 | hppa_dma_ops = &pcxl_dma_ops; | ||
112 | break; | ||
113 | default: | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | #endif | ||
118 | |||
119 | extern int init_per_cpu(int cpuid); | ||
120 | extern void collect_boot_cpu_data(void); | ||
121 | |||
122 | void __init setup_arch(char **cmdline_p) | ||
123 | { | ||
124 | #ifdef __LP64__ | ||
125 | extern int parisc_narrow_firmware; | ||
126 | #endif | ||
127 | |||
128 | init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */ | ||
129 | |||
130 | #ifdef __LP64__ | ||
131 | printk(KERN_INFO "The 64-bit Kernel has started...\n"); | ||
132 | #else | ||
133 | printk(KERN_INFO "The 32-bit Kernel has started...\n"); | ||
134 | #endif | ||
135 | |||
136 | pdc_console_init(); | ||
137 | |||
138 | #ifdef __LP64__ | ||
139 | if(parisc_narrow_firmware) { | ||
140 | printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n"); | ||
141 | } | ||
142 | #endif | ||
143 | setup_pdc(); | ||
144 | setup_cmdline(cmdline_p); | ||
145 | collect_boot_cpu_data(); | ||
146 | do_memory_inventory(); /* probe for physical memory */ | ||
147 | parisc_cache_init(); | ||
148 | paging_init(); | ||
149 | |||
150 | #ifdef CONFIG_CHASSIS_LCD_LED | ||
151 | /* initialize the LCD/LED after boot_cpu_data is available ! */ | ||
152 | led_init(); /* LCD/LED initialization */ | ||
153 | #endif | ||
154 | |||
155 | #ifdef CONFIG_PA11 | ||
156 | dma_ops_init(); | ||
157 | #endif | ||
158 | |||
159 | #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) | ||
160 | conswitchp = &dummy_con; /* we use take_over_console() later ! */ | ||
161 | #endif | ||
162 | |||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Display cpu info for all cpu's. | ||
167 | * for parisc this is in processor.c | ||
168 | */ | ||
169 | extern int show_cpuinfo (struct seq_file *m, void *v); | ||
170 | |||
171 | static void * | ||
172 | c_start (struct seq_file *m, loff_t *pos) | ||
173 | { | ||
174 | /* Looks like the caller will call repeatedly until we return | ||
175 | * 0, signaling EOF perhaps. This could be used to sequence | ||
176 | * through CPUs for example. Since we print all cpu info in our | ||
177 | * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above) | ||
178 | * we only allow for one "position". */ | ||
179 | return ((long)*pos < 1) ? (void *)1 : NULL; | ||
180 | } | ||
181 | |||
182 | static void * | ||
183 | c_next (struct seq_file *m, void *v, loff_t *pos) | ||
184 | { | ||
185 | ++*pos; | ||
186 | return c_start(m, pos); | ||
187 | } | ||
188 | |||
189 | static void | ||
190 | c_stop (struct seq_file *m, void *v) | ||
191 | { | ||
192 | } | ||
193 | |||
194 | struct seq_operations cpuinfo_op = { | ||
195 | .start = c_start, | ||
196 | .next = c_next, | ||
197 | .stop = c_stop, | ||
198 | .show = show_cpuinfo | ||
199 | }; | ||
200 | |||
201 | static void __init parisc_proc_mkdir(void) | ||
202 | { | ||
203 | /* | ||
204 | ** Can't call proc_mkdir() until after proc_root_init() has been | ||
205 | ** called by start_kernel(). In other words, this code can't | ||
206 | ** live in arch/.../setup.c because start_parisc() calls | ||
207 | ** start_kernel(). | ||
208 | */ | ||
209 | switch (boot_cpu_data.cpu_type) { | ||
210 | case pcxl: | ||
211 | case pcxl2: | ||
212 | if (NULL == proc_gsc_root) | ||
213 | { | ||
214 | proc_gsc_root = proc_mkdir("bus/gsc", NULL); | ||
215 | } | ||
216 | break; | ||
217 | case pcxt_: | ||
218 | case pcxu: | ||
219 | case pcxu_: | ||
220 | case pcxw: | ||
221 | case pcxw_: | ||
222 | case pcxw2: | ||
223 | if (NULL == proc_runway_root) | ||
224 | { | ||
225 | proc_runway_root = proc_mkdir("bus/runway", NULL); | ||
226 | } | ||
227 | break; | ||
228 | case mako: | ||
229 | if (NULL == proc_mckinley_root) | ||
230 | { | ||
231 | proc_mckinley_root = proc_mkdir("bus/mckinley", NULL); | ||
232 | } | ||
233 | break; | ||
234 | default: | ||
235 | /* FIXME: this was added to prevent the compiler | ||
236 | * complaining about missing pcx, pcxs and pcxt | ||
237 | * I'm assuming they have neither gsc nor runway */ | ||
238 | break; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | static struct resource central_bus = { | ||
243 | .name = "Central Bus", | ||
244 | .start = F_EXTEND(0xfff80000), | ||
245 | .end = F_EXTEND(0xfffaffff), | ||
246 | .flags = IORESOURCE_MEM, | ||
247 | }; | ||
248 | |||
249 | static struct resource local_broadcast = { | ||
250 | .name = "Local Broadcast", | ||
251 | .start = F_EXTEND(0xfffb0000), | ||
252 | .end = F_EXTEND(0xfffdffff), | ||
253 | .flags = IORESOURCE_MEM, | ||
254 | }; | ||
255 | |||
256 | static struct resource global_broadcast = { | ||
257 | .name = "Global Broadcast", | ||
258 | .start = F_EXTEND(0xfffe0000), | ||
259 | .end = F_EXTEND(0xffffffff), | ||
260 | .flags = IORESOURCE_MEM, | ||
261 | }; | ||
262 | |||
263 | static int __init parisc_init_resources(void) | ||
264 | { | ||
265 | int result; | ||
266 | |||
267 | result = request_resource(&iomem_resource, ¢ral_bus); | ||
268 | if (result < 0) { | ||
269 | printk(KERN_ERR | ||
270 | "%s: failed to claim %s address space!\n", | ||
271 | __FILE__, central_bus.name); | ||
272 | return result; | ||
273 | } | ||
274 | |||
275 | result = request_resource(&iomem_resource, &local_broadcast); | ||
276 | if (result < 0) { | ||
277 | printk(KERN_ERR | ||
278 | "%s: failed to claim %saddress space!\n", | ||
279 | __FILE__, local_broadcast.name); | ||
280 | return result; | ||
281 | } | ||
282 | |||
283 | result = request_resource(&iomem_resource, &global_broadcast); | ||
284 | if (result < 0) { | ||
285 | printk(KERN_ERR | ||
286 | "%s: failed to claim %s address space!\n", | ||
287 | __FILE__, global_broadcast.name); | ||
288 | return result; | ||
289 | } | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | extern void gsc_init(void); | ||
295 | extern void processor_init(void); | ||
296 | extern void ccio_init(void); | ||
297 | extern void hppb_init(void); | ||
298 | extern void dino_init(void); | ||
299 | extern void iosapic_init(void); | ||
300 | extern void lba_init(void); | ||
301 | extern void sba_init(void); | ||
302 | extern void eisa_init(void); | ||
303 | |||
304 | static int __init parisc_init(void) | ||
305 | { | ||
306 | parisc_proc_mkdir(); | ||
307 | parisc_init_resources(); | ||
308 | do_device_inventory(); /* probe for hardware */ | ||
309 | |||
310 | parisc_pdc_chassis_init(); | ||
311 | |||
312 | /* set up a new led state on systems shipped LED State panel */ | ||
313 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART); | ||
314 | |||
315 | processor_init(); | ||
316 | printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n", | ||
317 | boot_cpu_data.cpu_count, | ||
318 | boot_cpu_data.cpu_name, | ||
319 | boot_cpu_data.cpu_hz / 1000000, | ||
320 | boot_cpu_data.cpu_hz % 1000000 ); | ||
321 | |||
322 | parisc_setup_cache_timing(); | ||
323 | |||
324 | /* These are in a non-obvious order, will fix when we have an iotree */ | ||
325 | #if defined(CONFIG_IOSAPIC) | ||
326 | iosapic_init(); | ||
327 | #endif | ||
328 | #if defined(CONFIG_IOMMU_SBA) | ||
329 | sba_init(); | ||
330 | #endif | ||
331 | #if defined(CONFIG_PCI_LBA) | ||
332 | lba_init(); | ||
333 | #endif | ||
334 | |||
335 | /* CCIO before any potential subdevices */ | ||
336 | #if defined(CONFIG_IOMMU_CCIO) | ||
337 | ccio_init(); | ||
338 | #endif | ||
339 | |||
340 | /* | ||
341 | * Need to register Asp & Wax before the EISA adapters for the IRQ | ||
342 | * regions. EISA must come before PCI to be sure it gets IRQ region | ||
343 | * 0. | ||
344 | */ | ||
345 | #if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX) | ||
346 | gsc_init(); | ||
347 | #endif | ||
348 | #ifdef CONFIG_EISA | ||
349 | eisa_init(); | ||
350 | #endif | ||
351 | |||
352 | #if defined(CONFIG_HPPB) | ||
353 | hppb_init(); | ||
354 | #endif | ||
355 | |||
356 | #if defined(CONFIG_GSC_DINO) | ||
357 | dino_init(); | ||
358 | #endif | ||
359 | |||
360 | #ifdef CONFIG_CHASSIS_LCD_LED | ||
361 | register_led_regions(); /* register LED port info in procfs */ | ||
362 | #endif | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | arch_initcall(parisc_init); | ||
368 | |||
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c new file mode 100644 index 000000000000..9421bb98ea63 --- /dev/null +++ b/arch/parisc/kernel/signal.c | |||
@@ -0,0 +1,664 @@ | |||
1 | /* | ||
2 | * linux/arch/parisc/kernel/signal.c: Architecture-specific signal | ||
3 | * handling support. | ||
4 | * | ||
5 | * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org> | ||
6 | * Copyright (C) 2000 Linuxcare, Inc. | ||
7 | * | ||
8 | * Based on the ia64, i386, and alpha versions. | ||
9 | * | ||
10 | * Like the IA-64, we are a recent enough port (we are *starting* | ||
11 | * with glibc2.2) that we do not need to support the old non-realtime | ||
12 | * Linux signals. Therefore we don't. HP/UX signals will go in | ||
13 | * arch/parisc/hpux/signal.c when we figure out how to do them. | ||
14 | */ | ||
15 | |||
16 | #include <linux/sched.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/smp.h> | ||
19 | #include <linux/smp_lock.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/signal.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/wait.h> | ||
24 | #include <linux/ptrace.h> | ||
25 | #include <linux/unistd.h> | ||
26 | #include <linux/stddef.h> | ||
27 | #include <linux/compat.h> | ||
28 | #include <linux/elf.h> | ||
29 | #include <linux/personality.h> | ||
30 | #include <asm/ucontext.h> | ||
31 | #include <asm/rt_sigframe.h> | ||
32 | #include <asm/uaccess.h> | ||
33 | #include <asm/pgalloc.h> | ||
34 | #include <asm/cacheflush.h> | ||
35 | #include <asm/offsets.h> | ||
36 | |||
37 | #ifdef CONFIG_COMPAT | ||
38 | #include <linux/compat.h> | ||
39 | #include "signal32.h" | ||
40 | #endif | ||
41 | |||
42 | #define DEBUG_SIG 0 | ||
43 | #define DEBUG_SIG_LEVEL 2 | ||
44 | |||
45 | #if DEBUG_SIG | ||
46 | #define DBG(LEVEL, ...) \ | ||
47 | ((DEBUG_SIG_LEVEL >= LEVEL) \ | ||
48 | ? printk(__VA_ARGS__) : (void) 0) | ||
49 | #else | ||
50 | #define DBG(LEVEL, ...) | ||
51 | #endif | ||
52 | |||
53 | |||
54 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
55 | |||
56 | /* gcc will complain if a pointer is cast to an integer of different | ||
57 | * size. If you really need to do this (and we do for an ELF32 user | ||
58 | * application in an ELF64 kernel) then you have to do a cast to an | ||
59 | * integer of the same size first. The A() macro accomplishes | ||
60 | * this. */ | ||
61 | #define A(__x) ((unsigned long)(__x)) | ||
62 | |||
63 | int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall); | ||
64 | |||
65 | /* | ||
66 | * Atomically swap in the new signal mask, and wait for a signal. | ||
67 | */ | ||
68 | #ifdef __LP64__ | ||
69 | #include "sys32.h" | ||
70 | #endif | ||
71 | |||
72 | asmlinkage int | ||
73 | sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs) | ||
74 | { | ||
75 | sigset_t saveset, newset; | ||
76 | #ifdef __LP64__ | ||
77 | compat_sigset_t newset32; | ||
78 | |||
79 | if(personality(current->personality) == PER_LINUX32){ | ||
80 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
81 | if (sigsetsize != sizeof(compat_sigset_t)) | ||
82 | return -EINVAL; | ||
83 | if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32))) | ||
84 | return -EFAULT; | ||
85 | sigset_32to64(&newset,&newset32); | ||
86 | |||
87 | } else | ||
88 | #endif | ||
89 | { | ||
90 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
91 | if (sigsetsize != sizeof(sigset_t)) | ||
92 | return -EINVAL; | ||
93 | |||
94 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
95 | return -EFAULT; | ||
96 | } | ||
97 | |||
98 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
99 | |||
100 | spin_lock_irq(¤t->sighand->siglock); | ||
101 | saveset = current->blocked; | ||
102 | current->blocked = newset; | ||
103 | recalc_sigpending(); | ||
104 | spin_unlock_irq(¤t->sighand->siglock); | ||
105 | |||
106 | regs->gr[28] = -EINTR; | ||
107 | while (1) { | ||
108 | current->state = TASK_INTERRUPTIBLE; | ||
109 | schedule(); | ||
110 | if (do_signal(&saveset, regs, 1)) | ||
111 | return -EINTR; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * Do a signal return - restore sigcontext. | ||
117 | */ | ||
118 | |||
119 | /* Trampoline for calling rt_sigreturn() */ | ||
120 | #define INSN_LDI_R25_0 0x34190000 /* ldi 0,%r25 (in_syscall=0) */ | ||
121 | #define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */ | ||
122 | #define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */ | ||
123 | #define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */ | ||
124 | #define INSN_NOP 0x08000240 /* nop */ | ||
125 | /* For debugging */ | ||
126 | #define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */ | ||
127 | |||
128 | static long | ||
129 | restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) | ||
130 | { | ||
131 | long err = 0; | ||
132 | |||
133 | err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr)); | ||
134 | err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr)); | ||
135 | err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq)); | ||
136 | err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq)); | ||
137 | err |= __get_user(regs->sar, &sc->sc_sar); | ||
138 | DBG(2,"restore_sigcontext: iaoq is 0x%#lx / 0x%#lx\n", | ||
139 | regs->iaoq[0],regs->iaoq[1]); | ||
140 | DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]); | ||
141 | return err; | ||
142 | } | ||
143 | |||
144 | void | ||
145 | sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | ||
146 | { | ||
147 | struct rt_sigframe __user *frame; | ||
148 | struct siginfo si; | ||
149 | sigset_t set; | ||
150 | unsigned long usp = (regs->gr[30] & ~(0x01UL)); | ||
151 | unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE; | ||
152 | #ifdef __LP64__ | ||
153 | compat_sigset_t compat_set; | ||
154 | struct compat_rt_sigframe __user * compat_frame; | ||
155 | |||
156 | if(personality(current->personality) == PER_LINUX32) | ||
157 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; | ||
158 | #endif | ||
159 | |||
160 | |||
161 | /* Unwind the user stack to get the rt_sigframe structure. */ | ||
162 | frame = (struct rt_sigframe __user *) | ||
163 | (usp - sigframe_size); | ||
164 | DBG(2,"sys_rt_sigreturn: frame is %p\n", frame); | ||
165 | |||
166 | #ifdef __LP64__ | ||
167 | compat_frame = (struct compat_rt_sigframe __user *)frame; | ||
168 | |||
169 | if(personality(current->personality) == PER_LINUX32){ | ||
170 | DBG(2,"sys_rt_sigreturn: ELF32 process.\n"); | ||
171 | if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set))) | ||
172 | goto give_sigsegv; | ||
173 | sigset_32to64(&set,&compat_set); | ||
174 | } else | ||
175 | #endif | ||
176 | { | ||
177 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | ||
178 | goto give_sigsegv; | ||
179 | } | ||
180 | |||
181 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
182 | spin_lock_irq(¤t->sighand->siglock); | ||
183 | current->blocked = set; | ||
184 | recalc_sigpending(); | ||
185 | spin_unlock_irq(¤t->sighand->siglock); | ||
186 | |||
187 | /* Good thing we saved the old gr[30], eh? */ | ||
188 | #ifdef __LP64__ | ||
189 | if(personality(current->personality) == PER_LINUX32){ | ||
190 | DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n", | ||
191 | &compat_frame->uc.uc_mcontext); | ||
192 | // FIXME: Load upper half from register file | ||
193 | if (restore_sigcontext32(&compat_frame->uc.uc_mcontext, | ||
194 | &compat_frame->regs, regs)) | ||
195 | goto give_sigsegv; | ||
196 | DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n", | ||
197 | usp, &compat_frame->uc.uc_stack); | ||
198 | if (do_sigaltstack32(&compat_frame->uc.uc_stack, NULL, usp) == -EFAULT) | ||
199 | goto give_sigsegv; | ||
200 | } else | ||
201 | #endif | ||
202 | { | ||
203 | DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n", | ||
204 | &frame->uc.uc_mcontext); | ||
205 | if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) | ||
206 | goto give_sigsegv; | ||
207 | DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n", | ||
208 | usp, &frame->uc.uc_stack); | ||
209 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT) | ||
210 | goto give_sigsegv; | ||
211 | } | ||
212 | |||
213 | |||
214 | |||
215 | /* If we are on the syscall path IAOQ will not be restored, and | ||
216 | * if we are on the interrupt path we must not corrupt gr31. | ||
217 | */ | ||
218 | if (in_syscall) | ||
219 | regs->gr[31] = regs->iaoq[0]; | ||
220 | #if DEBUG_SIG | ||
221 | DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]); | ||
222 | show_regs(regs); | ||
223 | #endif | ||
224 | return; | ||
225 | |||
226 | give_sigsegv: | ||
227 | DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n"); | ||
228 | si.si_signo = SIGSEGV; | ||
229 | si.si_errno = 0; | ||
230 | si.si_code = SI_KERNEL; | ||
231 | si.si_pid = current->pid; | ||
232 | si.si_uid = current->uid; | ||
233 | si.si_addr = &frame->uc; | ||
234 | force_sig_info(SIGSEGV, &si, current); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * Set up a signal frame. | ||
240 | */ | ||
241 | |||
242 | static inline void __user * | ||
243 | get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) | ||
244 | { | ||
245 | /*FIXME: ELF32 vs. ELF64 has different frame_size, but since we | ||
246 | don't use the parameter it doesn't matter */ | ||
247 | |||
248 | DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n", | ||
249 | (unsigned long)ka, sp, frame_size); | ||
250 | |||
251 | if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) | ||
252 | sp = current->sas_ss_sp; /* Stacks grow up! */ | ||
253 | |||
254 | DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp); | ||
255 | return (void __user *) sp; /* Stacks grow up. Fun. */ | ||
256 | } | ||
257 | |||
258 | static long | ||
259 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall) | ||
260 | |||
261 | { | ||
262 | unsigned long flags = 0; | ||
263 | long err = 0; | ||
264 | |||
265 | if (on_sig_stack((unsigned long) sc)) | ||
266 | flags |= PARISC_SC_FLAG_ONSTACK; | ||
267 | if (in_syscall) { | ||
268 | flags |= PARISC_SC_FLAG_IN_SYSCALL; | ||
269 | /* regs->iaoq is undefined in the syscall return path */ | ||
270 | err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]); | ||
271 | err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]); | ||
272 | err |= __put_user(regs->sr[3], &sc->sc_iasq[0]); | ||
273 | err |= __put_user(regs->sr[3], &sc->sc_iasq[1]); | ||
274 | DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n", | ||
275 | regs->gr[31], regs->gr[31]+4); | ||
276 | } else { | ||
277 | err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq)); | ||
278 | err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq)); | ||
279 | DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n", | ||
280 | regs->iaoq[0], regs->iaoq[1]); | ||
281 | } | ||
282 | |||
283 | err |= __put_user(flags, &sc->sc_flags); | ||
284 | err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr)); | ||
285 | err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr)); | ||
286 | err |= __put_user(regs->sar, &sc->sc_sar); | ||
287 | DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]); | ||
288 | |||
289 | return err; | ||
290 | } | ||
291 | |||
292 | static long | ||
293 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
294 | sigset_t *set, struct pt_regs *regs, int in_syscall) | ||
295 | { | ||
296 | struct rt_sigframe __user *frame; | ||
297 | unsigned long rp, usp; | ||
298 | unsigned long haddr, sigframe_size; | ||
299 | struct siginfo si; | ||
300 | int err = 0; | ||
301 | #ifdef __LP64__ | ||
302 | compat_int_t compat_val; | ||
303 | struct compat_rt_sigframe __user * compat_frame; | ||
304 | compat_sigset_t compat_set; | ||
305 | #endif | ||
306 | |||
307 | usp = (regs->gr[30] & ~(0x01UL)); | ||
308 | /*FIXME: frame_size parameter is unused, remove it. */ | ||
309 | frame = get_sigframe(ka, usp, sizeof(*frame)); | ||
310 | |||
311 | DBG(1,"SETUP_RT_FRAME: START\n"); | ||
312 | DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info); | ||
313 | |||
314 | |||
315 | #ifdef __LP64__ | ||
316 | |||
317 | compat_frame = (struct compat_rt_sigframe __user *)frame; | ||
318 | |||
319 | if(personality(current->personality) == PER_LINUX32) { | ||
320 | DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info); | ||
321 | err |= compat_copy_siginfo_to_user(&compat_frame->info, info); | ||
322 | DBG(1,"SETUP_RT_FRAME: 1\n"); | ||
323 | compat_val = (compat_int_t)current->sas_ss_sp; | ||
324 | err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp); | ||
325 | DBG(1,"SETUP_RT_FRAME: 2\n"); | ||
326 | compat_val = (compat_int_t)current->sas_ss_size; | ||
327 | err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_size); | ||
328 | DBG(1,"SETUP_RT_FRAME: 3\n"); | ||
329 | compat_val = sas_ss_flags(regs->gr[30]); | ||
330 | err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_flags); | ||
331 | DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc); | ||
332 | DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext); | ||
333 | err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext, | ||
334 | &compat_frame->regs, regs, in_syscall); | ||
335 | sigset_64to32(&compat_set,set); | ||
336 | err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set)); | ||
337 | } else | ||
338 | #endif | ||
339 | { | ||
340 | DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info); | ||
341 | err |= copy_siginfo_to_user(&frame->info, info); | ||
342 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
343 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
344 | err |= __put_user(sas_ss_flags(regs->gr[30]), | ||
345 | &frame->uc.uc_stack.ss_flags); | ||
346 | DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc); | ||
347 | DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext); | ||
348 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall); | ||
349 | /* FIXME: Should probably be converted aswell for the compat case */ | ||
350 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
351 | } | ||
352 | |||
353 | if (err) | ||
354 | goto give_sigsegv; | ||
355 | |||
356 | /* Set up to return from userspace. If provided, use a stub | ||
357 | already in userspace. The first words of tramp are used to | ||
358 | save the previous sigrestartblock trampoline that might be | ||
359 | on the stack. We start the sigreturn trampoline at | ||
360 | SIGRESTARTBLOCK_TRAMP+X. */ | ||
361 | err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0, | ||
362 | &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]); | ||
363 | err |= __put_user(INSN_LDI_R20, | ||
364 | &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]); | ||
365 | err |= __put_user(INSN_BLE_SR2_R0, | ||
366 | &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]); | ||
367 | err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]); | ||
368 | |||
369 | #if DEBUG_SIG | ||
370 | /* Assert that we're flushing in the correct space... */ | ||
371 | { | ||
372 | int sid; | ||
373 | asm ("mfsp %%sr3,%0" : "=r" (sid)); | ||
374 | DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n", | ||
375 | sid, frame->tramp); | ||
376 | } | ||
377 | #endif | ||
378 | |||
379 | flush_user_dcache_range((unsigned long) &frame->tramp[0], | ||
380 | (unsigned long) &frame->tramp[TRAMP_SIZE]); | ||
381 | flush_user_icache_range((unsigned long) &frame->tramp[0], | ||
382 | (unsigned long) &frame->tramp[TRAMP_SIZE]); | ||
383 | |||
384 | /* TRAMP Words 0-4, Lenght 5 = SIGRESTARTBLOCK_TRAMP | ||
385 | * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP | ||
386 | * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP | ||
387 | */ | ||
388 | rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP]; | ||
389 | |||
390 | if (err) | ||
391 | goto give_sigsegv; | ||
392 | |||
393 | haddr = A(ka->sa.sa_handler); | ||
394 | /* The sa_handler may be a pointer to a function descriptor */ | ||
395 | #ifdef __LP64__ | ||
396 | if(personality(current->personality) == PER_LINUX32) { | ||
397 | #endif | ||
398 | if (haddr & PA_PLABEL_FDESC) { | ||
399 | Elf32_Fdesc fdesc; | ||
400 | Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3); | ||
401 | |||
402 | err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc)); | ||
403 | |||
404 | if (err) | ||
405 | goto give_sigsegv; | ||
406 | |||
407 | haddr = fdesc.addr; | ||
408 | regs->gr[19] = fdesc.gp; | ||
409 | } | ||
410 | #ifdef __LP64__ | ||
411 | } else { | ||
412 | Elf64_Fdesc fdesc; | ||
413 | Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3); | ||
414 | |||
415 | err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc)); | ||
416 | |||
417 | if (err) | ||
418 | goto give_sigsegv; | ||
419 | |||
420 | haddr = fdesc.addr; | ||
421 | regs->gr[19] = fdesc.gp; | ||
422 | DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n", | ||
423 | haddr, regs->gr[19], in_syscall); | ||
424 | } | ||
425 | #endif | ||
426 | |||
427 | /* The syscall return path will create IAOQ values from r31. | ||
428 | */ | ||
429 | sigframe_size = PARISC_RT_SIGFRAME_SIZE; | ||
430 | #ifdef __LP64__ | ||
431 | if(personality(current->personality) == PER_LINUX32) | ||
432 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; | ||
433 | #endif | ||
434 | if (in_syscall) { | ||
435 | regs->gr[31] = haddr; | ||
436 | #ifdef __LP64__ | ||
437 | if(personality(current->personality) == PER_LINUX) | ||
438 | sigframe_size |= 1; | ||
439 | #endif | ||
440 | } else { | ||
441 | unsigned long psw = USER_PSW; | ||
442 | #ifdef __LP64__ | ||
443 | if(personality(current->personality) == PER_LINUX) | ||
444 | psw |= PSW_W; | ||
445 | #endif | ||
446 | |||
447 | /* If we are singlestepping, arrange a trap to be delivered | ||
448 | when we return to userspace. Note the semantics -- we | ||
449 | should trap before the first insn in the handler is | ||
450 | executed. Ref: | ||
451 | http://sources.redhat.com/ml/gdb/2004-11/msg00245.html | ||
452 | */ | ||
453 | if (pa_psw(current)->r) { | ||
454 | pa_psw(current)->r = 0; | ||
455 | psw |= PSW_R; | ||
456 | mtctl(-1, 0); | ||
457 | } | ||
458 | |||
459 | regs->gr[0] = psw; | ||
460 | regs->iaoq[0] = haddr | 3; | ||
461 | regs->iaoq[1] = regs->iaoq[0] + 4; | ||
462 | } | ||
463 | |||
464 | regs->gr[2] = rp; /* userland return pointer */ | ||
465 | regs->gr[26] = sig; /* signal number */ | ||
466 | |||
467 | #ifdef __LP64__ | ||
468 | if(personality(current->personality) == PER_LINUX32){ | ||
469 | regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */ | ||
470 | regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */ | ||
471 | } else | ||
472 | #endif | ||
473 | { | ||
474 | regs->gr[25] = A(&frame->info); /* siginfo pointer */ | ||
475 | regs->gr[24] = A(&frame->uc); /* ucontext pointer */ | ||
476 | } | ||
477 | |||
478 | DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n", | ||
479 | regs->gr[30], sigframe_size, | ||
480 | regs->gr[30] + sigframe_size); | ||
481 | /* Raise the user stack pointer to make a proper call frame. */ | ||
482 | regs->gr[30] = (A(frame) + sigframe_size); | ||
483 | |||
484 | |||
485 | DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n", | ||
486 | current->comm, current->pid, frame, regs->gr[30], | ||
487 | regs->iaoq[0], regs->iaoq[1], rp); | ||
488 | |||
489 | return 1; | ||
490 | |||
491 | give_sigsegv: | ||
492 | DBG(1,"setup_rt_frame: sending SIGSEGV\n"); | ||
493 | if (sig == SIGSEGV) | ||
494 | ka->sa.sa_handler = SIG_DFL; | ||
495 | si.si_signo = SIGSEGV; | ||
496 | si.si_errno = 0; | ||
497 | si.si_code = SI_KERNEL; | ||
498 | si.si_pid = current->pid; | ||
499 | si.si_uid = current->uid; | ||
500 | si.si_addr = frame; | ||
501 | force_sig_info(SIGSEGV, &si, current); | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | /* | ||
506 | * OK, we're invoking a handler. | ||
507 | */ | ||
508 | |||
509 | static long | ||
510 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | ||
511 | sigset_t *oldset, struct pt_regs *regs, int in_syscall) | ||
512 | { | ||
513 | DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n", | ||
514 | sig, ka, info, oldset, regs); | ||
515 | |||
516 | /* Set up the stack frame */ | ||
517 | if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) | ||
518 | return 0; | ||
519 | |||
520 | if (!(ka->sa.sa_flags & SA_NODEFER)) { | ||
521 | spin_lock_irq(¤t->sighand->siglock); | ||
522 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
523 | sigaddset(¤t->blocked,sig); | ||
524 | recalc_sigpending(); | ||
525 | spin_unlock_irq(¤t->sighand->siglock); | ||
526 | } | ||
527 | return 1; | ||
528 | } | ||
529 | |||
530 | /* | ||
531 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
532 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
533 | * mistake. | ||
534 | * | ||
535 | * We need to be able to restore the syscall arguments (r21-r26) to | ||
536 | * restart syscalls. Thus, the syscall path should save them in the | ||
537 | * pt_regs structure (it's okay to do so since they are caller-save | ||
538 | * registers). As noted below, the syscall number gets restored for | ||
539 | * us due to the magic of delayed branching. | ||
540 | */ | ||
541 | |||
542 | asmlinkage int | ||
543 | do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) | ||
544 | { | ||
545 | siginfo_t info; | ||
546 | struct k_sigaction ka; | ||
547 | int signr; | ||
548 | |||
549 | DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n", | ||
550 | oldset, regs, regs->sr[7], in_syscall); | ||
551 | |||
552 | /* Everyone else checks to see if they are in kernel mode at | ||
553 | this point and exits if that's the case. I'm not sure why | ||
554 | we would be called in that case, but for some reason we | ||
555 | are. */ | ||
556 | |||
557 | if (!oldset) | ||
558 | oldset = ¤t->blocked; | ||
559 | |||
560 | DBG(1,"do_signal: oldset %08lx / %08lx\n", | ||
561 | oldset->sig[0], oldset->sig[1]); | ||
562 | |||
563 | |||
564 | /* May need to force signal if handle_signal failed to deliver */ | ||
565 | while (1) { | ||
566 | |||
567 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
568 | DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); | ||
569 | |||
570 | if (signr <= 0) | ||
571 | break; | ||
572 | |||
573 | /* Restart a system call if necessary. */ | ||
574 | if (in_syscall) { | ||
575 | /* Check the return code */ | ||
576 | switch (regs->gr[28]) { | ||
577 | case -ERESTART_RESTARTBLOCK: | ||
578 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
579 | case -ERESTARTNOHAND: | ||
580 | DBG(1,"ERESTARTNOHAND: returning -EINTR\n"); | ||
581 | regs->gr[28] = -EINTR; | ||
582 | break; | ||
583 | |||
584 | case -ERESTARTSYS: | ||
585 | if (!(ka.sa.sa_flags & SA_RESTART)) { | ||
586 | DBG(1,"ERESTARTSYS: putting -EINTR\n"); | ||
587 | regs->gr[28] = -EINTR; | ||
588 | break; | ||
589 | } | ||
590 | /* fallthrough */ | ||
591 | case -ERESTARTNOINTR: | ||
592 | /* A syscall is just a branch, so all | ||
593 | we have to do is fiddle the return pointer. */ | ||
594 | regs->gr[31] -= 8; /* delayed branching */ | ||
595 | /* Preserve original r28. */ | ||
596 | regs->gr[28] = regs->orig_r28; | ||
597 | break; | ||
598 | } | ||
599 | } | ||
600 | /* Whee! Actually deliver the signal. If the | ||
601 | delivery failed, we need to continue to iterate in | ||
602 | this loop so we can deliver the SIGSEGV... */ | ||
603 | if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { | ||
604 | DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", | ||
605 | regs->gr[28]); | ||
606 | return 1; | ||
607 | } | ||
608 | } | ||
609 | /* end of while(1) looping forever if we can't force a signal */ | ||
610 | |||
611 | /* Did we come from a system call? */ | ||
612 | if (in_syscall) { | ||
613 | /* Restart the system call - no handlers present */ | ||
614 | if (regs->gr[28] == -ERESTART_RESTARTBLOCK) { | ||
615 | unsigned int *usp = (unsigned int *)regs->gr[30]; | ||
616 | |||
617 | /* Setup a trampoline to restart the syscall | ||
618 | * with __NR_restart_syscall | ||
619 | * | ||
620 | * 0: <return address (orig r31)> | ||
621 | * 4: <2nd half for 64-bit> | ||
622 | * 8: ldw 0(%sp), %r31 | ||
623 | * 12: be 0x100(%sr2, %r0) | ||
624 | * 16: ldi __NR_restart_syscall, %r20 | ||
625 | */ | ||
626 | #ifndef __LP64__ | ||
627 | put_user(regs->gr[31], &usp[0]); | ||
628 | put_user(0x0fc0109f, &usp[2]); | ||
629 | #else | ||
630 | put_user(regs->gr[31] >> 32, &usp[0]); | ||
631 | put_user(regs->gr[31] & 0xffffffff, &usp[1]); | ||
632 | put_user(0x0fc010df, &usp[2]); | ||
633 | #endif | ||
634 | put_user(0xe0008200, &usp[3]); | ||
635 | put_user(0x34140000, &usp[4]); | ||
636 | |||
637 | /* Stack is 64-byte aligned, and we only | ||
638 | * need to flush 1 cache line */ | ||
639 | asm("fdc 0(%%sr3, %0)\n" | ||
640 | "fic 0(%%sr3, %0)\n" | ||
641 | "sync\n" | ||
642 | : : "r"(regs->gr[30])); | ||
643 | |||
644 | regs->gr[31] = regs->gr[30] + 8; | ||
645 | /* Preserve original r28. */ | ||
646 | regs->gr[28] = regs->orig_r28; | ||
647 | } else if (regs->gr[28] == -ERESTARTNOHAND || | ||
648 | regs->gr[28] == -ERESTARTSYS || | ||
649 | regs->gr[28] == -ERESTARTNOINTR) { | ||
650 | /* Hooray for delayed branching. We don't | ||
651 | have to restore %r20 (the system call | ||
652 | number) because it gets loaded in the delay | ||
653 | slot of the branch external instruction. */ | ||
654 | regs->gr[31] -= 8; | ||
655 | /* Preserve original r28. */ | ||
656 | regs->gr[28] = regs->orig_r28; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", | ||
661 | regs->gr[28]); | ||
662 | |||
663 | return 0; | ||
664 | } | ||
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c new file mode 100644 index 000000000000..0792e20efef3 --- /dev/null +++ b/arch/parisc/kernel/signal32.c | |||
@@ -0,0 +1,400 @@ | |||
1 | /* Signal support for 32-bit kernel builds | ||
2 | * | ||
3 | * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org> | ||
4 | * Code was mostly borrowed from kernel/signal.c. | ||
5 | * See kernel/signal.c for additional Copyrights. | ||
6 | * | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/compat.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/unistd.h> | ||
27 | #include <linux/smp_lock.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/syscalls.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/errno.h> | ||
33 | |||
34 | #include <asm/compat_signal.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | |||
37 | #include "signal32.h" | ||
38 | #include "sys32.h" | ||
39 | |||
40 | #define DEBUG_COMPAT_SIG 0 | ||
41 | #define DEBUG_COMPAT_SIG_LEVEL 2 | ||
42 | |||
43 | #if DEBUG_COMPAT_SIG | ||
44 | #define DBG(LEVEL, ...) \ | ||
45 | ((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \ | ||
46 | ? printk(__VA_ARGS__) : (void) 0) | ||
47 | #else | ||
48 | #define DBG(LEVEL, ...) | ||
49 | #endif | ||
50 | |||
51 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
52 | |||
53 | inline void | ||
54 | sigset_32to64(sigset_t *s64, compat_sigset_t *s32) | ||
55 | { | ||
56 | s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32); | ||
57 | } | ||
58 | |||
59 | inline void | ||
60 | sigset_64to32(compat_sigset_t *s32, sigset_t *s64) | ||
61 | { | ||
62 | s32->sig[0] = s64->sig[0] & 0xffffffffUL; | ||
63 | s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL; | ||
64 | } | ||
65 | |||
66 | static int | ||
67 | put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) | ||
68 | { | ||
69 | compat_sigset_t s; | ||
70 | |||
71 | if (sz != sizeof *set) panic("put_sigset32()"); | ||
72 | sigset_64to32(&s, set); | ||
73 | |||
74 | return copy_to_user(up, &s, sizeof s); | ||
75 | } | ||
76 | |||
77 | static int | ||
78 | get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) | ||
79 | { | ||
80 | compat_sigset_t s; | ||
81 | int r; | ||
82 | |||
83 | if (sz != sizeof *set) panic("put_sigset32()"); | ||
84 | |||
85 | if ((r = copy_from_user(&s, up, sz)) == 0) { | ||
86 | sigset_32to64(set, &s); | ||
87 | } | ||
88 | |||
89 | return r; | ||
90 | } | ||
91 | |||
92 | int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, | ||
93 | unsigned int sigsetsize) | ||
94 | { | ||
95 | sigset_t old_set, new_set; | ||
96 | int ret; | ||
97 | |||
98 | if (set && get_sigset32(set, &new_set, sigsetsize)) | ||
99 | return -EFAULT; | ||
100 | |||
101 | KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL, | ||
102 | oset ? (sigset_t __user *)&old_set : NULL, sigsetsize); | ||
103 | |||
104 | if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize)) | ||
105 | return -EFAULT; | ||
106 | |||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | |||
111 | int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize) | ||
112 | { | ||
113 | int ret; | ||
114 | sigset_t set; | ||
115 | |||
116 | KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize); | ||
117 | |||
118 | if (!ret && put_sigset32(uset, &set, sigsetsize)) | ||
119 | return -EFAULT; | ||
120 | |||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | long | ||
125 | sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact, | ||
126 | size_t sigsetsize) | ||
127 | { | ||
128 | struct k_sigaction32 new_sa32, old_sa32; | ||
129 | struct k_sigaction new_sa, old_sa; | ||
130 | int ret = -EINVAL; | ||
131 | |||
132 | if (act) { | ||
133 | if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa)) | ||
134 | return -EFAULT; | ||
135 | new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler; | ||
136 | new_sa.sa.sa_flags = new_sa32.sa.sa_flags; | ||
137 | sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask); | ||
138 | } | ||
139 | |||
140 | ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL); | ||
141 | |||
142 | if (!ret && oact) { | ||
143 | sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask); | ||
144 | old_sa32.sa.sa_flags = old_sa.sa.sa_flags; | ||
145 | old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler; | ||
146 | if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa)) | ||
147 | return -EFAULT; | ||
148 | } | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | int | ||
153 | do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp) | ||
154 | { | ||
155 | compat_stack_t ss32, oss32; | ||
156 | stack_t ss, oss; | ||
157 | stack_t *ssp = NULL, *ossp = NULL; | ||
158 | int ret; | ||
159 | |||
160 | if (uss32) { | ||
161 | if (copy_from_user(&ss32, uss32, sizeof ss32)) | ||
162 | return -EFAULT; | ||
163 | |||
164 | ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp; | ||
165 | ss.ss_flags = ss32.ss_flags; | ||
166 | ss.ss_size = ss32.ss_size; | ||
167 | |||
168 | ssp = &ss; | ||
169 | } | ||
170 | |||
171 | if (uoss32) | ||
172 | ossp = &oss; | ||
173 | |||
174 | KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp); | ||
175 | |||
176 | if (!ret && uoss32) { | ||
177 | oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp; | ||
178 | oss32.ss_flags = oss.ss_flags; | ||
179 | oss32.ss_size = oss.ss_size; | ||
180 | if (copy_to_user(uoss32, &oss32, sizeof *uoss32)) | ||
181 | return -EFAULT; | ||
182 | } | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | long | ||
188 | restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, | ||
189 | struct pt_regs *regs) | ||
190 | { | ||
191 | long err = 0; | ||
192 | compat_uint_t compat_reg; | ||
193 | compat_uint_t compat_regt; | ||
194 | int regn; | ||
195 | |||
196 | /* When loading 32-bit values into 64-bit registers make | ||
197 | sure to clear the upper 32-bits */ | ||
198 | DBG(2,"restore_sigcontext32: PER_LINUX32 process\n"); | ||
199 | DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs); | ||
200 | DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc)); | ||
201 | for(regn=0; regn < 32; regn++){ | ||
202 | err |= __get_user(compat_reg,&sc->sc_gr[regn]); | ||
203 | regs->gr[regn] = compat_reg; | ||
204 | /* Load upper half */ | ||
205 | err |= __get_user(compat_regt,&rf->rf_gr[regn]); | ||
206 | regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg; | ||
207 | DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n", | ||
208 | regn, regs->gr[regn], compat_regt, compat_reg); | ||
209 | } | ||
210 | DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr)); | ||
211 | /* XXX: BE WARNED FR's are 64-BIT! */ | ||
212 | err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr)); | ||
213 | |||
214 | /* Better safe than sorry, pass __get_user two things of | ||
215 | the same size and let gcc do the upward conversion to | ||
216 | 64-bits */ | ||
217 | err |= __get_user(compat_reg, &sc->sc_iaoq[0]); | ||
218 | /* Load upper half */ | ||
219 | err |= __get_user(compat_regt, &rf->rf_iaoq[0]); | ||
220 | regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg; | ||
221 | DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt); | ||
222 | DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n", | ||
223 | &sc->sc_iaoq[0], compat_reg); | ||
224 | |||
225 | err |= __get_user(compat_reg, &sc->sc_iaoq[1]); | ||
226 | /* Load upper half */ | ||
227 | err |= __get_user(compat_regt, &rf->rf_iaoq[1]); | ||
228 | regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg; | ||
229 | DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt); | ||
230 | DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n", | ||
231 | &sc->sc_iaoq[1],compat_reg); | ||
232 | DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n", | ||
233 | regs->iaoq[0],regs->iaoq[1]); | ||
234 | |||
235 | err |= __get_user(compat_reg, &sc->sc_iasq[0]); | ||
236 | /* Load the upper half for iasq */ | ||
237 | err |= __get_user(compat_regt, &rf->rf_iasq[0]); | ||
238 | regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg; | ||
239 | DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt); | ||
240 | |||
241 | err |= __get_user(compat_reg, &sc->sc_iasq[1]); | ||
242 | /* Load the upper half for iasq */ | ||
243 | err |= __get_user(compat_regt, &rf->rf_iasq[1]); | ||
244 | regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg; | ||
245 | DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt); | ||
246 | DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n", | ||
247 | regs->iasq[0],regs->iasq[1]); | ||
248 | |||
249 | err |= __get_user(compat_reg, &sc->sc_sar); | ||
250 | /* Load the upper half for sar */ | ||
251 | err |= __get_user(compat_regt, &rf->rf_sar); | ||
252 | regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg; | ||
253 | DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt); | ||
254 | DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar); | ||
255 | DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]); | ||
256 | |||
257 | return err; | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * Set up the sigcontext structure for this process. | ||
262 | * This is not an easy task if the kernel is 64-bit, it will require | ||
263 | * that we examine the process personality to determine if we need to | ||
264 | * truncate for a 32-bit userspace. | ||
265 | */ | ||
266 | long | ||
267 | setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, | ||
268 | struct pt_regs *regs, int in_syscall) | ||
269 | { | ||
270 | compat_int_t flags = 0; | ||
271 | long err = 0; | ||
272 | compat_uint_t compat_reg; | ||
273 | compat_uint_t compat_regb; | ||
274 | int regn; | ||
275 | |||
276 | if (on_sig_stack((unsigned long) sc)) | ||
277 | flags |= PARISC_SC_FLAG_ONSTACK; | ||
278 | |||
279 | if (in_syscall) { | ||
280 | |||
281 | DBG(1,"setup_sigcontext32: in_syscall\n"); | ||
282 | |||
283 | flags |= PARISC_SC_FLAG_IN_SYSCALL; | ||
284 | /* Truncate gr31 */ | ||
285 | compat_reg = (compat_uint_t)(regs->gr[31]); | ||
286 | /* regs->iaoq is undefined in the syscall return path */ | ||
287 | err |= __put_user(compat_reg, &sc->sc_iaoq[0]); | ||
288 | DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n", | ||
289 | &sc->sc_iaoq[0], compat_reg); | ||
290 | |||
291 | /* Store upper half */ | ||
292 | compat_reg = (compat_uint_t)(regs->gr[32] >> 32); | ||
293 | err |= __put_user(compat_reg, &rf->rf_iaoq[0]); | ||
294 | DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg); | ||
295 | |||
296 | |||
297 | compat_reg = (compat_uint_t)(regs->gr[31]+4); | ||
298 | err |= __put_user(compat_reg, &sc->sc_iaoq[1]); | ||
299 | DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n", | ||
300 | &sc->sc_iaoq[1], compat_reg); | ||
301 | /* Store upper half */ | ||
302 | compat_reg = (compat_uint_t)((regs->gr[32]+4) >> 32); | ||
303 | err |= __put_user(compat_reg, &rf->rf_iaoq[1]); | ||
304 | DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg); | ||
305 | |||
306 | /* Truncate sr3 */ | ||
307 | compat_reg = (compat_uint_t)(regs->sr[3]); | ||
308 | err |= __put_user(compat_reg, &sc->sc_iasq[0]); | ||
309 | err |= __put_user(compat_reg, &sc->sc_iasq[1]); | ||
310 | |||
311 | /* Store upper half */ | ||
312 | compat_reg = (compat_uint_t)(regs->sr[3] >> 32); | ||
313 | err |= __put_user(compat_reg, &rf->rf_iasq[0]); | ||
314 | err |= __put_user(compat_reg, &rf->rf_iasq[1]); | ||
315 | |||
316 | DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg); | ||
317 | DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg); | ||
318 | DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n", | ||
319 | regs->gr[31], regs->gr[31]+4); | ||
320 | |||
321 | } else { | ||
322 | |||
323 | compat_reg = (compat_uint_t)(regs->iaoq[0]); | ||
324 | err |= __put_user(compat_reg, &sc->sc_iaoq[0]); | ||
325 | DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n", | ||
326 | &sc->sc_iaoq[0], compat_reg); | ||
327 | /* Store upper half */ | ||
328 | compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32); | ||
329 | err |= __put_user(compat_reg, &rf->rf_iaoq[0]); | ||
330 | DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg); | ||
331 | |||
332 | compat_reg = (compat_uint_t)(regs->iaoq[1]); | ||
333 | err |= __put_user(compat_reg, &sc->sc_iaoq[1]); | ||
334 | DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n", | ||
335 | &sc->sc_iaoq[1], compat_reg); | ||
336 | /* Store upper half */ | ||
337 | compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32); | ||
338 | err |= __put_user(compat_reg, &rf->rf_iaoq[1]); | ||
339 | DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg); | ||
340 | |||
341 | |||
342 | compat_reg = (compat_uint_t)(regs->iasq[0]); | ||
343 | err |= __put_user(compat_reg, &sc->sc_iasq[0]); | ||
344 | DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n", | ||
345 | &sc->sc_iasq[0], compat_reg); | ||
346 | /* Store upper half */ | ||
347 | compat_reg = (compat_uint_t)(regs->iasq[0] >> 32); | ||
348 | err |= __put_user(compat_reg, &rf->rf_iasq[0]); | ||
349 | DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg); | ||
350 | |||
351 | |||
352 | compat_reg = (compat_uint_t)(regs->iasq[1]); | ||
353 | err |= __put_user(compat_reg, &sc->sc_iasq[1]); | ||
354 | DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n", | ||
355 | &sc->sc_iasq[1], compat_reg); | ||
356 | /* Store upper half */ | ||
357 | compat_reg = (compat_uint_t)(regs->iasq[1] >> 32); | ||
358 | err |= __put_user(compat_reg, &rf->rf_iasq[1]); | ||
359 | DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg); | ||
360 | |||
361 | /* Print out the IAOQ for debugging */ | ||
362 | DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n", | ||
363 | regs->iaoq[0], regs->iaoq[1]); | ||
364 | } | ||
365 | |||
366 | err |= __put_user(flags, &sc->sc_flags); | ||
367 | |||
368 | DBG(1,"setup_sigcontext32: Truncating general registers.\n"); | ||
369 | |||
370 | for(regn=0; regn < 32; regn++){ | ||
371 | /* Truncate a general register */ | ||
372 | compat_reg = (compat_uint_t)(regs->gr[regn]); | ||
373 | err |= __put_user(compat_reg, &sc->sc_gr[regn]); | ||
374 | /* Store upper half */ | ||
375 | compat_regb = (compat_uint_t)(regs->gr[regn] >> 32); | ||
376 | err |= __put_user(compat_regb, &rf->rf_gr[regn]); | ||
377 | |||
378 | /* DEBUG: Write out the "upper / lower" register data */ | ||
379 | DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn, | ||
380 | compat_regb, compat_reg); | ||
381 | } | ||
382 | |||
383 | /* Copy the floating point registers (same size) | ||
384 | XXX: BE WARNED FR's are 64-BIT! */ | ||
385 | DBG(1,"setup_sigcontext32: Copying from regs to sc, " | ||
386 | "sc->sc_fr size = %#lx, regs->fr size = %#lx\n", | ||
387 | sizeof(regs->fr), sizeof(sc->sc_fr)); | ||
388 | err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr)); | ||
389 | |||
390 | compat_reg = (compat_uint_t)(regs->sar); | ||
391 | err |= __put_user(compat_reg, &sc->sc_sar); | ||
392 | DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg); | ||
393 | /* Store upper half */ | ||
394 | compat_reg = (compat_uint_t)(regs->sar >> 32); | ||
395 | err |= __put_user(compat_reg, &rf->rf_sar); | ||
396 | DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg); | ||
397 | DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]); | ||
398 | |||
399 | return err; | ||
400 | } | ||
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h new file mode 100644 index 000000000000..4d1569e717cc --- /dev/null +++ b/arch/parisc/kernel/signal32.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org> | ||
3 | * Copyright (C) 2003 Carlos O'Donell <carlos at parisc-linux.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program 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 | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | #ifndef _PARISC64_KERNEL_SIGNAL32_H | ||
20 | #define _PARISC64_KERNEL_SIGNAL32_H | ||
21 | |||
22 | #include <linux/compat.h> | ||
23 | #include <asm/compat_signal.h> | ||
24 | #include <asm/compat_rt_sigframe.h> | ||
25 | |||
26 | /* ELF32 signal handling */ | ||
27 | |||
28 | struct k_sigaction32 { | ||
29 | struct compat_sigaction sa; | ||
30 | }; | ||
31 | |||
32 | void sigset_32to64(sigset_t *s64, compat_sigset_t *s32); | ||
33 | void sigset_64to32(compat_sigset_t *s32, sigset_t *s64); | ||
34 | int do_sigaltstack32 (const compat_stack_t __user *uss32, | ||
35 | compat_stack_t __user *uoss32, unsigned long sp); | ||
36 | long restore_sigcontext32(struct compat_sigcontext __user *sc, | ||
37 | struct compat_regfile __user *rf, | ||
38 | struct pt_regs *regs); | ||
39 | long setup_sigcontext32(struct compat_sigcontext __user *sc, | ||
40 | struct compat_regfile __user *rf, | ||
41 | struct pt_regs *regs, int in_syscall); | ||
42 | |||
43 | #endif | ||
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c new file mode 100644 index 000000000000..bcc7e83f5142 --- /dev/null +++ b/arch/parisc/kernel/smp.c | |||
@@ -0,0 +1,723 @@ | |||
1 | /* | ||
2 | ** SMP Support | ||
3 | ** | ||
4 | ** Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | ||
5 | ** Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com> | ||
6 | ** Copyright (C) 2001,2004 Grant Grundler <grundler@parisc-linux.org> | ||
7 | ** | ||
8 | ** Lots of stuff stolen from arch/alpha/kernel/smp.c | ||
9 | ** ...and then parisc stole from arch/ia64/kernel/smp.c. Thanks David! :^) | ||
10 | ** | ||
11 | ** Thanks to John Curry and Ullas Ponnadi. I learned alot from their work. | ||
12 | ** -grant (1/12/2001) | ||
13 | ** | ||
14 | ** This program is free software; you can redistribute it and/or modify | ||
15 | ** it under the terms of the GNU General Public License as published by | ||
16 | ** the Free Software Foundation; either version 2 of the License, or | ||
17 | ** (at your option) any later version. | ||
18 | */ | ||
19 | #undef ENTRY_SYS_CPUS /* syscall support for iCOD-like functionality */ | ||
20 | |||
21 | #include <linux/autoconf.h> | ||
22 | |||
23 | #include <linux/types.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/smp.h> | ||
33 | #include <linux/kernel_stat.h> | ||
34 | #include <linux/mm.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/bitops.h> | ||
37 | |||
38 | #include <asm/system.h> | ||
39 | #include <asm/atomic.h> | ||
40 | #include <asm/current.h> | ||
41 | #include <asm/delay.h> | ||
42 | #include <asm/pgalloc.h> /* for flush_tlb_all() proto/macro */ | ||
43 | |||
44 | #include <asm/io.h> | ||
45 | #include <asm/irq.h> /* for CPU_IRQ_REGION and friends */ | ||
46 | #include <asm/mmu_context.h> | ||
47 | #include <asm/page.h> | ||
48 | #include <asm/pgtable.h> | ||
49 | #include <asm/pgalloc.h> | ||
50 | #include <asm/processor.h> | ||
51 | #include <asm/ptrace.h> | ||
52 | #include <asm/unistd.h> | ||
53 | #include <asm/cacheflush.h> | ||
54 | |||
55 | #define kDEBUG 0 | ||
56 | |||
57 | DEFINE_SPINLOCK(smp_lock); | ||
58 | |||
59 | volatile struct task_struct *smp_init_current_idle_task; | ||
60 | |||
61 | static volatile int cpu_now_booting = 0; /* track which CPU is booting */ | ||
62 | |||
63 | static int parisc_max_cpus = 1; | ||
64 | |||
65 | /* online cpus are ones that we've managed to bring up completely | ||
66 | * possible cpus are all valid cpu | ||
67 | * present cpus are all detected cpu | ||
68 | * | ||
69 | * On startup we bring up the "possible" cpus. Since we discover | ||
70 | * CPUs later, we add them as hotplug, so the possible cpu mask is | ||
71 | * empty in the beginning. | ||
72 | */ | ||
73 | |||
74 | cpumask_t cpu_online_map = CPU_MASK_NONE; /* Bitmap of online CPUs */ | ||
75 | cpumask_t cpu_possible_map = CPU_MASK_ALL; /* Bitmap of Present CPUs */ | ||
76 | |||
77 | EXPORT_SYMBOL(cpu_online_map); | ||
78 | EXPORT_SYMBOL(cpu_possible_map); | ||
79 | |||
80 | |||
81 | struct smp_call_struct { | ||
82 | void (*func) (void *info); | ||
83 | void *info; | ||
84 | long wait; | ||
85 | atomic_t unstarted_count; | ||
86 | atomic_t unfinished_count; | ||
87 | }; | ||
88 | static volatile struct smp_call_struct *smp_call_function_data; | ||
89 | |||
90 | enum ipi_message_type { | ||
91 | IPI_NOP=0, | ||
92 | IPI_RESCHEDULE=1, | ||
93 | IPI_CALL_FUNC, | ||
94 | IPI_CPU_START, | ||
95 | IPI_CPU_STOP, | ||
96 | IPI_CPU_TEST | ||
97 | }; | ||
98 | |||
99 | |||
100 | /********** SMP inter processor interrupt and communication routines */ | ||
101 | |||
102 | #undef PER_CPU_IRQ_REGION | ||
103 | #ifdef PER_CPU_IRQ_REGION | ||
104 | /* XXX REVISIT Ignore for now. | ||
105 | ** *May* need this "hook" to register IPI handler | ||
106 | ** once we have perCPU ExtIntr switch tables. | ||
107 | */ | ||
108 | static void | ||
109 | ipi_init(int cpuid) | ||
110 | { | ||
111 | |||
112 | /* If CPU is present ... */ | ||
113 | #ifdef ENTRY_SYS_CPUS | ||
114 | /* *and* running (not stopped) ... */ | ||
115 | #error iCOD support wants state checked here. | ||
116 | #endif | ||
117 | |||
118 | #error verify IRQ_OFFSET(IPI_IRQ) is ipi_interrupt() in new IRQ region | ||
119 | |||
120 | if(cpu_online(cpuid) ) | ||
121 | { | ||
122 | switch_to_idle_task(current); | ||
123 | } | ||
124 | |||
125 | return; | ||
126 | } | ||
127 | #endif | ||
128 | |||
129 | |||
130 | /* | ||
131 | ** Yoink this CPU from the runnable list... | ||
132 | ** | ||
133 | */ | ||
134 | static void | ||
135 | halt_processor(void) | ||
136 | { | ||
137 | #ifdef ENTRY_SYS_CPUS | ||
138 | #error halt_processor() needs rework | ||
139 | /* | ||
140 | ** o migrate I/O interrupts off this CPU. | ||
141 | ** o leave IPI enabled - __cli() will disable IPI. | ||
142 | ** o leave CPU in online map - just change the state | ||
143 | */ | ||
144 | cpu_data[this_cpu].state = STATE_STOPPED; | ||
145 | mark_bh(IPI_BH); | ||
146 | #else | ||
147 | /* REVISIT : redirect I/O Interrupts to another CPU? */ | ||
148 | /* REVISIT : does PM *know* this CPU isn't available? */ | ||
149 | cpu_clear(smp_processor_id(), cpu_online_map); | ||
150 | local_irq_disable(); | ||
151 | for (;;) | ||
152 | ; | ||
153 | #endif | ||
154 | } | ||
155 | |||
156 | |||
157 | irqreturn_t | ||
158 | ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
159 | { | ||
160 | int this_cpu = smp_processor_id(); | ||
161 | struct cpuinfo_parisc *p = &cpu_data[this_cpu]; | ||
162 | unsigned long ops; | ||
163 | unsigned long flags; | ||
164 | |||
165 | /* Count this now; we may make a call that never returns. */ | ||
166 | p->ipi_count++; | ||
167 | |||
168 | mb(); /* Order interrupt and bit testing. */ | ||
169 | |||
170 | for (;;) { | ||
171 | spin_lock_irqsave(&(p->lock),flags); | ||
172 | ops = p->pending_ipi; | ||
173 | p->pending_ipi = 0; | ||
174 | spin_unlock_irqrestore(&(p->lock),flags); | ||
175 | |||
176 | mb(); /* Order bit clearing and data access. */ | ||
177 | |||
178 | if (!ops) | ||
179 | break; | ||
180 | |||
181 | while (ops) { | ||
182 | unsigned long which = ffz(~ops); | ||
183 | |||
184 | switch (which) { | ||
185 | case IPI_RESCHEDULE: | ||
186 | #if (kDEBUG>=100) | ||
187 | printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu); | ||
188 | #endif /* kDEBUG */ | ||
189 | ops &= ~(1 << IPI_RESCHEDULE); | ||
190 | /* | ||
191 | * Reschedule callback. Everything to be | ||
192 | * done is done by the interrupt return path. | ||
193 | */ | ||
194 | break; | ||
195 | |||
196 | case IPI_CALL_FUNC: | ||
197 | #if (kDEBUG>=100) | ||
198 | printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu); | ||
199 | #endif /* kDEBUG */ | ||
200 | ops &= ~(1 << IPI_CALL_FUNC); | ||
201 | { | ||
202 | volatile struct smp_call_struct *data; | ||
203 | void (*func)(void *info); | ||
204 | void *info; | ||
205 | int wait; | ||
206 | |||
207 | data = smp_call_function_data; | ||
208 | func = data->func; | ||
209 | info = data->info; | ||
210 | wait = data->wait; | ||
211 | |||
212 | mb(); | ||
213 | atomic_dec ((atomic_t *)&data->unstarted_count); | ||
214 | |||
215 | /* At this point, *data can't | ||
216 | * be relied upon. | ||
217 | */ | ||
218 | |||
219 | (*func)(info); | ||
220 | |||
221 | /* Notify the sending CPU that the | ||
222 | * task is done. | ||
223 | */ | ||
224 | mb(); | ||
225 | if (wait) | ||
226 | atomic_dec ((atomic_t *)&data->unfinished_count); | ||
227 | } | ||
228 | break; | ||
229 | |||
230 | case IPI_CPU_START: | ||
231 | #if (kDEBUG>=100) | ||
232 | printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu); | ||
233 | #endif /* kDEBUG */ | ||
234 | ops &= ~(1 << IPI_CPU_START); | ||
235 | #ifdef ENTRY_SYS_CPUS | ||
236 | p->state = STATE_RUNNING; | ||
237 | #endif | ||
238 | break; | ||
239 | |||
240 | case IPI_CPU_STOP: | ||
241 | #if (kDEBUG>=100) | ||
242 | printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu); | ||
243 | #endif /* kDEBUG */ | ||
244 | ops &= ~(1 << IPI_CPU_STOP); | ||
245 | #ifdef ENTRY_SYS_CPUS | ||
246 | #else | ||
247 | halt_processor(); | ||
248 | #endif | ||
249 | break; | ||
250 | |||
251 | case IPI_CPU_TEST: | ||
252 | #if (kDEBUG>=100) | ||
253 | printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu); | ||
254 | #endif /* kDEBUG */ | ||
255 | ops &= ~(1 << IPI_CPU_TEST); | ||
256 | break; | ||
257 | |||
258 | default: | ||
259 | printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", | ||
260 | this_cpu, which); | ||
261 | ops &= ~(1 << which); | ||
262 | return IRQ_NONE; | ||
263 | } /* Switch */ | ||
264 | } /* while (ops) */ | ||
265 | } | ||
266 | return IRQ_HANDLED; | ||
267 | } | ||
268 | |||
269 | |||
270 | static inline void | ||
271 | ipi_send(int cpu, enum ipi_message_type op) | ||
272 | { | ||
273 | struct cpuinfo_parisc *p = &cpu_data[cpu]; | ||
274 | unsigned long flags; | ||
275 | |||
276 | spin_lock_irqsave(&(p->lock),flags); | ||
277 | p->pending_ipi |= 1 << op; | ||
278 | gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa); | ||
279 | spin_unlock_irqrestore(&(p->lock),flags); | ||
280 | } | ||
281 | |||
282 | |||
283 | static inline void | ||
284 | send_IPI_single(int dest_cpu, enum ipi_message_type op) | ||
285 | { | ||
286 | if (dest_cpu == NO_PROC_ID) { | ||
287 | BUG(); | ||
288 | return; | ||
289 | } | ||
290 | |||
291 | ipi_send(dest_cpu, op); | ||
292 | } | ||
293 | |||
294 | static inline void | ||
295 | send_IPI_allbutself(enum ipi_message_type op) | ||
296 | { | ||
297 | int i; | ||
298 | |||
299 | for (i = 0; i < NR_CPUS; i++) { | ||
300 | if (cpu_online(i) && i != smp_processor_id()) | ||
301 | send_IPI_single(i, op); | ||
302 | } | ||
303 | } | ||
304 | |||
305 | |||
306 | inline void | ||
307 | smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); } | ||
308 | |||
309 | static inline void | ||
310 | smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); } | ||
311 | |||
312 | void | ||
313 | smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } | ||
314 | |||
315 | |||
316 | /** | ||
317 | * Run a function on all other CPUs. | ||
318 | * <func> The function to run. This must be fast and non-blocking. | ||
319 | * <info> An arbitrary pointer to pass to the function. | ||
320 | * <retry> If true, keep retrying until ready. | ||
321 | * <wait> If true, wait until function has completed on other CPUs. | ||
322 | * [RETURNS] 0 on success, else a negative status code. | ||
323 | * | ||
324 | * Does not return until remote CPUs are nearly ready to execute <func> | ||
325 | * or have executed. | ||
326 | */ | ||
327 | |||
328 | int | ||
329 | smp_call_function (void (*func) (void *info), void *info, int retry, int wait) | ||
330 | { | ||
331 | struct smp_call_struct data; | ||
332 | unsigned long timeout; | ||
333 | static DEFINE_SPINLOCK(lock); | ||
334 | int retries = 0; | ||
335 | |||
336 | if (num_online_cpus() < 2) | ||
337 | return 0; | ||
338 | |||
339 | /* Can deadlock when called with interrupts disabled */ | ||
340 | WARN_ON(irqs_disabled()); | ||
341 | |||
342 | data.func = func; | ||
343 | data.info = info; | ||
344 | data.wait = wait; | ||
345 | atomic_set(&data.unstarted_count, num_online_cpus() - 1); | ||
346 | atomic_set(&data.unfinished_count, num_online_cpus() - 1); | ||
347 | |||
348 | if (retry) { | ||
349 | spin_lock (&lock); | ||
350 | while (smp_call_function_data != 0) | ||
351 | barrier(); | ||
352 | } | ||
353 | else { | ||
354 | spin_lock (&lock); | ||
355 | if (smp_call_function_data) { | ||
356 | spin_unlock (&lock); | ||
357 | return -EBUSY; | ||
358 | } | ||
359 | } | ||
360 | |||
361 | smp_call_function_data = &data; | ||
362 | spin_unlock (&lock); | ||
363 | |||
364 | /* Send a message to all other CPUs and wait for them to respond */ | ||
365 | send_IPI_allbutself(IPI_CALL_FUNC); | ||
366 | |||
367 | retry: | ||
368 | /* Wait for response */ | ||
369 | timeout = jiffies + HZ; | ||
370 | while ( (atomic_read (&data.unstarted_count) > 0) && | ||
371 | time_before (jiffies, timeout) ) | ||
372 | barrier (); | ||
373 | |||
374 | if (atomic_read (&data.unstarted_count) > 0) { | ||
375 | printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d), try %d\n", | ||
376 | smp_processor_id(), ++retries); | ||
377 | goto retry; | ||
378 | } | ||
379 | /* We either got one or timed out. Release the lock */ | ||
380 | |||
381 | mb(); | ||
382 | smp_call_function_data = NULL; | ||
383 | |||
384 | while (wait && atomic_read (&data.unfinished_count) > 0) | ||
385 | barrier (); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | EXPORT_SYMBOL(smp_call_function); | ||
391 | |||
392 | /* | ||
393 | * Flush all other CPU's tlb and then mine. Do this with on_each_cpu() | ||
394 | * as we want to ensure all TLB's flushed before proceeding. | ||
395 | */ | ||
396 | |||
397 | extern void flush_tlb_all_local(void); | ||
398 | |||
399 | void | ||
400 | smp_flush_tlb_all(void) | ||
401 | { | ||
402 | on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1); | ||
403 | } | ||
404 | |||
405 | |||
406 | void | ||
407 | smp_do_timer(struct pt_regs *regs) | ||
408 | { | ||
409 | int cpu = smp_processor_id(); | ||
410 | struct cpuinfo_parisc *data = &cpu_data[cpu]; | ||
411 | |||
412 | if (!--data->prof_counter) { | ||
413 | data->prof_counter = data->prof_multiplier; | ||
414 | update_process_times(user_mode(regs)); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * Called by secondaries to update state and initialize CPU registers. | ||
420 | */ | ||
421 | static void __init | ||
422 | smp_cpu_init(int cpunum) | ||
423 | { | ||
424 | extern int init_per_cpu(int); /* arch/parisc/kernel/setup.c */ | ||
425 | extern void init_IRQ(void); /* arch/parisc/kernel/irq.c */ | ||
426 | |||
427 | /* Set modes and Enable floating point coprocessor */ | ||
428 | (void) init_per_cpu(cpunum); | ||
429 | |||
430 | disable_sr_hashing(); | ||
431 | |||
432 | mb(); | ||
433 | |||
434 | /* Well, support 2.4 linux scheme as well. */ | ||
435 | if (cpu_test_and_set(cpunum, cpu_online_map)) | ||
436 | { | ||
437 | extern void machine_halt(void); /* arch/parisc.../process.c */ | ||
438 | |||
439 | printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum); | ||
440 | machine_halt(); | ||
441 | } | ||
442 | |||
443 | /* Initialise the idle task for this CPU */ | ||
444 | atomic_inc(&init_mm.mm_count); | ||
445 | current->active_mm = &init_mm; | ||
446 | if(current->mm) | ||
447 | BUG(); | ||
448 | enter_lazy_tlb(&init_mm, current); | ||
449 | |||
450 | init_IRQ(); /* make sure no IRQ's are enabled or pending */ | ||
451 | } | ||
452 | |||
453 | |||
454 | /* | ||
455 | * Slaves start using C here. Indirectly called from smp_slave_stext. | ||
456 | * Do what start_kernel() and main() do for boot strap processor (aka monarch) | ||
457 | */ | ||
458 | void __init smp_callin(void) | ||
459 | { | ||
460 | int slave_id = cpu_now_booting; | ||
461 | #if 0 | ||
462 | void *istack; | ||
463 | #endif | ||
464 | |||
465 | smp_cpu_init(slave_id); | ||
466 | |||
467 | #if 0 /* NOT WORKING YET - see entry.S */ | ||
468 | istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER); | ||
469 | if (istack == NULL) { | ||
470 | printk(KERN_CRIT "Failed to allocate interrupt stack for cpu %d\n",slave_id); | ||
471 | BUG(); | ||
472 | } | ||
473 | mtctl(istack,31); | ||
474 | #endif | ||
475 | |||
476 | flush_cache_all_local(); /* start with known state */ | ||
477 | flush_tlb_all_local(); | ||
478 | |||
479 | local_irq_enable(); /* Interrupts have been off until now */ | ||
480 | |||
481 | cpu_idle(); /* Wait for timer to schedule some work */ | ||
482 | |||
483 | /* NOTREACHED */ | ||
484 | panic("smp_callin() AAAAaaaaahhhh....\n"); | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | * Bring one cpu online. | ||
489 | */ | ||
490 | int __init smp_boot_one_cpu(int cpuid) | ||
491 | { | ||
492 | struct task_struct *idle; | ||
493 | long timeout; | ||
494 | |||
495 | /* | ||
496 | * Create an idle task for this CPU. Note the address wed* give | ||
497 | * to kernel_thread is irrelevant -- it's going to start | ||
498 | * where OS_BOOT_RENDEVZ vector in SAL says to start. But | ||
499 | * this gets all the other task-y sort of data structures set | ||
500 | * up like we wish. We need to pull the just created idle task | ||
501 | * off the run queue and stuff it into the init_tasks[] array. | ||
502 | * Sheesh . . . | ||
503 | */ | ||
504 | |||
505 | idle = fork_idle(cpuid); | ||
506 | if (IS_ERR(idle)) | ||
507 | panic("SMP: fork failed for CPU:%d", cpuid); | ||
508 | |||
509 | idle->thread_info->cpu = cpuid; | ||
510 | |||
511 | /* Let _start know what logical CPU we're booting | ||
512 | ** (offset into init_tasks[],cpu_data[]) | ||
513 | */ | ||
514 | cpu_now_booting = cpuid; | ||
515 | |||
516 | /* | ||
517 | ** boot strap code needs to know the task address since | ||
518 | ** it also contains the process stack. | ||
519 | */ | ||
520 | smp_init_current_idle_task = idle ; | ||
521 | mb(); | ||
522 | |||
523 | printk("Releasing cpu %d now, hpa=%lx\n", cpuid, cpu_data[cpuid].hpa); | ||
524 | |||
525 | /* | ||
526 | ** This gets PDC to release the CPU from a very tight loop. | ||
527 | ** | ||
528 | ** From the PA-RISC 2.0 Firmware Architecture Reference Specification: | ||
529 | ** "The MEM_RENDEZ vector specifies the location of OS_RENDEZ which | ||
530 | ** is executed after receiving the rendezvous signal (an interrupt to | ||
531 | ** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the | ||
532 | ** contents of memory are valid." | ||
533 | */ | ||
534 | gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, cpu_data[cpuid].hpa); | ||
535 | mb(); | ||
536 | |||
537 | /* | ||
538 | * OK, wait a bit for that CPU to finish staggering about. | ||
539 | * Slave will set a bit when it reaches smp_cpu_init(). | ||
540 | * Once the "monarch CPU" sees the bit change, it can move on. | ||
541 | */ | ||
542 | for (timeout = 0; timeout < 10000; timeout++) { | ||
543 | if(cpu_online(cpuid)) { | ||
544 | /* Which implies Slave has started up */ | ||
545 | cpu_now_booting = 0; | ||
546 | smp_init_current_idle_task = NULL; | ||
547 | goto alive ; | ||
548 | } | ||
549 | udelay(100); | ||
550 | barrier(); | ||
551 | } | ||
552 | |||
553 | put_task_struct(idle); | ||
554 | idle = NULL; | ||
555 | |||
556 | printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); | ||
557 | return -1; | ||
558 | |||
559 | alive: | ||
560 | /* Remember the Slave data */ | ||
561 | #if (kDEBUG>=100) | ||
562 | printk(KERN_DEBUG "SMP: CPU:%d came alive after %ld _us\n", | ||
563 | cpuid, timeout * 100); | ||
564 | #endif /* kDEBUG */ | ||
565 | #ifdef ENTRY_SYS_CPUS | ||
566 | cpu_data[cpuid].state = STATE_RUNNING; | ||
567 | #endif | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | void __devinit smp_prepare_boot_cpu(void) | ||
572 | { | ||
573 | int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */ | ||
574 | |||
575 | #ifdef ENTRY_SYS_CPUS | ||
576 | cpu_data[0].state = STATE_RUNNING; | ||
577 | #endif | ||
578 | |||
579 | /* Setup BSP mappings */ | ||
580 | printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor); | ||
581 | |||
582 | cpu_set(bootstrap_processor, cpu_online_map); | ||
583 | cpu_set(bootstrap_processor, cpu_present_map); | ||
584 | } | ||
585 | |||
586 | |||
587 | |||
588 | /* | ||
589 | ** inventory.c:do_inventory() hasn't yet been run and thus we | ||
590 | ** don't 'discover' the additional CPU's until later. | ||
591 | */ | ||
592 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
593 | { | ||
594 | cpus_clear(cpu_present_map); | ||
595 | cpu_set(0, cpu_present_map); | ||
596 | |||
597 | parisc_max_cpus = max_cpus; | ||
598 | if (!max_cpus) | ||
599 | printk(KERN_INFO "SMP mode deactivated.\n"); | ||
600 | } | ||
601 | |||
602 | |||
603 | void smp_cpus_done(unsigned int cpu_max) | ||
604 | { | ||
605 | return; | ||
606 | } | ||
607 | |||
608 | |||
609 | int __devinit __cpu_up(unsigned int cpu) | ||
610 | { | ||
611 | if (cpu != 0 && cpu < parisc_max_cpus) | ||
612 | smp_boot_one_cpu(cpu); | ||
613 | |||
614 | return cpu_online(cpu) ? 0 : -ENOSYS; | ||
615 | } | ||
616 | |||
617 | |||
618 | |||
619 | #ifdef ENTRY_SYS_CPUS | ||
620 | /* Code goes along with: | ||
621 | ** entry.s: ENTRY_NAME(sys_cpus) / * 215, for cpu stat * / | ||
622 | */ | ||
623 | int sys_cpus(int argc, char **argv) | ||
624 | { | ||
625 | int i,j=0; | ||
626 | extern int current_pid(int cpu); | ||
627 | |||
628 | if( argc > 2 ) { | ||
629 | printk("sys_cpus:Only one argument supported\n"); | ||
630 | return (-1); | ||
631 | } | ||
632 | if ( argc == 1 ){ | ||
633 | |||
634 | #ifdef DUMP_MORE_STATE | ||
635 | for(i=0; i<NR_CPUS; i++) { | ||
636 | int cpus_per_line = 4; | ||
637 | if(cpu_online(i)) { | ||
638 | if (j++ % cpus_per_line) | ||
639 | printk(" %3d",i); | ||
640 | else | ||
641 | printk("\n %3d",i); | ||
642 | } | ||
643 | } | ||
644 | printk("\n"); | ||
645 | #else | ||
646 | printk("\n 0\n"); | ||
647 | #endif | ||
648 | } else if((argc==2) && !(strcmp(argv[1],"-l"))) { | ||
649 | printk("\nCPUSTATE TASK CPUNUM CPUID HARDCPU(HPA)\n"); | ||
650 | #ifdef DUMP_MORE_STATE | ||
651 | for(i=0;i<NR_CPUS;i++) { | ||
652 | if (!cpu_online(i)) | ||
653 | continue; | ||
654 | if (cpu_data[i].cpuid != NO_PROC_ID) { | ||
655 | switch(cpu_data[i].state) { | ||
656 | case STATE_RENDEZVOUS: | ||
657 | printk("RENDEZVS "); | ||
658 | break; | ||
659 | case STATE_RUNNING: | ||
660 | printk((current_pid(i)!=0) ? "RUNNING " : "IDLING "); | ||
661 | break; | ||
662 | case STATE_STOPPED: | ||
663 | printk("STOPPED "); | ||
664 | break; | ||
665 | case STATE_HALTED: | ||
666 | printk("HALTED "); | ||
667 | break; | ||
668 | default: | ||
669 | printk("%08x?", cpu_data[i].state); | ||
670 | break; | ||
671 | } | ||
672 | if(cpu_online(i)) { | ||
673 | printk(" %4d",current_pid(i)); | ||
674 | } | ||
675 | printk(" %6d",cpu_number_map(i)); | ||
676 | printk(" %5d",i); | ||
677 | printk(" 0x%lx\n",cpu_data[i].hpa); | ||
678 | } | ||
679 | } | ||
680 | #else | ||
681 | printk("\n%s %4d 0 0 --------", | ||
682 | (current->pid)?"RUNNING ": "IDLING ",current->pid); | ||
683 | #endif | ||
684 | } else if ((argc==2) && !(strcmp(argv[1],"-s"))) { | ||
685 | #ifdef DUMP_MORE_STATE | ||
686 | printk("\nCPUSTATE CPUID\n"); | ||
687 | for (i=0;i<NR_CPUS;i++) { | ||
688 | if (!cpu_online(i)) | ||
689 | continue; | ||
690 | if (cpu_data[i].cpuid != NO_PROC_ID) { | ||
691 | switch(cpu_data[i].state) { | ||
692 | case STATE_RENDEZVOUS: | ||
693 | printk("RENDEZVS");break; | ||
694 | case STATE_RUNNING: | ||
695 | printk((current_pid(i)!=0) ? "RUNNING " : "IDLING"); | ||
696 | break; | ||
697 | case STATE_STOPPED: | ||
698 | printk("STOPPED ");break; | ||
699 | case STATE_HALTED: | ||
700 | printk("HALTED ");break; | ||
701 | default: | ||
702 | } | ||
703 | printk(" %5d\n",i); | ||
704 | } | ||
705 | } | ||
706 | #else | ||
707 | printk("\n%s CPU0",(current->pid==0)?"RUNNING ":"IDLING "); | ||
708 | #endif | ||
709 | } else { | ||
710 | printk("sys_cpus:Unknown request\n"); | ||
711 | return (-1); | ||
712 | } | ||
713 | return 0; | ||
714 | } | ||
715 | #endif /* ENTRY_SYS_CPUS */ | ||
716 | |||
717 | #ifdef CONFIG_PROC_FS | ||
718 | int __init | ||
719 | setup_profiling_timer(unsigned int multiplier) | ||
720 | { | ||
721 | return -EINVAL; | ||
722 | } | ||
723 | #endif | ||
diff --git a/arch/parisc/kernel/sys32.h b/arch/parisc/kernel/sys32.h new file mode 100644 index 000000000000..06c2090cfaba --- /dev/null +++ b/arch/parisc/kernel/sys32.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Richard Hirst <rhirst at parisc-linux.org> | ||
3 | * Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org> | ||
4 | * Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #ifndef _PARISC64_KERNEL_SYS32_H | ||
21 | #define _PARISC64_KERNEL_SYS32_H | ||
22 | |||
23 | #include <linux/compat.h> | ||
24 | |||
25 | /* Call a kernel syscall which will use kernel space instead of user | ||
26 | * space for its copy_to/from_user. | ||
27 | */ | ||
28 | #define KERNEL_SYSCALL(ret, syscall, args...) \ | ||
29 | { \ | ||
30 | mm_segment_t old_fs = get_fs(); \ | ||
31 | set_fs(KERNEL_DS); \ | ||
32 | ret = syscall(args); \ | ||
33 | set_fs (old_fs); \ | ||
34 | } | ||
35 | |||
36 | #ifdef CONFIG_COMPAT | ||
37 | |||
38 | typedef __u32 __sighandler_t32; | ||
39 | |||
40 | struct sigaction32 { | ||
41 | __sighandler_t32 sa_handler; | ||
42 | unsigned int sa_flags; | ||
43 | compat_sigset_t sa_mask; /* mask last for extensibility */ | ||
44 | }; | ||
45 | |||
46 | #endif | ||
47 | |||
48 | #endif | ||
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c new file mode 100644 index 000000000000..7958cd8c8bf8 --- /dev/null +++ b/arch/parisc/kernel/sys_parisc.c | |||
@@ -0,0 +1,253 @@ | |||
1 | |||
2 | /* | ||
3 | * PARISC specific syscalls | ||
4 | * | ||
5 | * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org> | ||
6 | * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org> | ||
7 | * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org> | ||
8 | * | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <asm/uaccess.h> | ||
26 | #include <linux/file.h> | ||
27 | #include <linux/fs.h> | ||
28 | #include <linux/linkage.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/mman.h> | ||
31 | #include <linux/shm.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/syscalls.h> | ||
34 | |||
35 | int sys_pipe(int __user *fildes) | ||
36 | { | ||
37 | int fd[2]; | ||
38 | int error; | ||
39 | |||
40 | error = do_pipe(fd); | ||
41 | if (!error) { | ||
42 | if (copy_to_user(fildes, fd, 2*sizeof(int))) | ||
43 | error = -EFAULT; | ||
44 | } | ||
45 | return error; | ||
46 | } | ||
47 | |||
48 | static unsigned long get_unshared_area(unsigned long addr, unsigned long len) | ||
49 | { | ||
50 | struct vm_area_struct *vma; | ||
51 | |||
52 | addr = PAGE_ALIGN(addr); | ||
53 | |||
54 | for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { | ||
55 | /* At this point: (!vma || addr < vma->vm_end). */ | ||
56 | if (TASK_SIZE - len < addr) | ||
57 | return -ENOMEM; | ||
58 | if (!vma || addr + len <= vma->vm_start) | ||
59 | return addr; | ||
60 | addr = vma->vm_end; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | #define DCACHE_ALIGN(addr) (((addr) + (SHMLBA - 1)) &~ (SHMLBA - 1)) | ||
65 | |||
66 | /* | ||
67 | * We need to know the offset to use. Old scheme was to look for | ||
68 | * existing mapping and use the same offset. New scheme is to use the | ||
69 | * address of the kernel data structure as the seed for the offset. | ||
70 | * We'll see how that works... | ||
71 | * | ||
72 | * The mapping is cacheline aligned, so there's no information in the bottom | ||
73 | * few bits of the address. We're looking for 10 bits (4MB / 4k), so let's | ||
74 | * drop the bottom 8 bits and use bits 8-17. | ||
75 | */ | ||
76 | static int get_offset(struct address_space *mapping) | ||
77 | { | ||
78 | int offset = (unsigned long) mapping << (PAGE_SHIFT - 8); | ||
79 | return offset & 0x3FF000; | ||
80 | } | ||
81 | |||
82 | static unsigned long get_shared_area(struct address_space *mapping, | ||
83 | unsigned long addr, unsigned long len, unsigned long pgoff) | ||
84 | { | ||
85 | struct vm_area_struct *vma; | ||
86 | int offset = mapping ? get_offset(mapping) : 0; | ||
87 | |||
88 | addr = DCACHE_ALIGN(addr - offset) + offset; | ||
89 | |||
90 | for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { | ||
91 | /* At this point: (!vma || addr < vma->vm_end). */ | ||
92 | if (TASK_SIZE - len < addr) | ||
93 | return -ENOMEM; | ||
94 | if (!vma || addr + len <= vma->vm_start) | ||
95 | return addr; | ||
96 | addr = DCACHE_ALIGN(vma->vm_end - offset) + offset; | ||
97 | if (addr < vma->vm_end) /* handle wraparound */ | ||
98 | return -ENOMEM; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, | ||
103 | unsigned long len, unsigned long pgoff, unsigned long flags) | ||
104 | { | ||
105 | if (len > TASK_SIZE) | ||
106 | return -ENOMEM; | ||
107 | if (!addr) | ||
108 | addr = TASK_UNMAPPED_BASE; | ||
109 | |||
110 | if (filp) { | ||
111 | addr = get_shared_area(filp->f_mapping, addr, len, pgoff); | ||
112 | } else if(flags & MAP_SHARED) { | ||
113 | addr = get_shared_area(NULL, addr, len, pgoff); | ||
114 | } else { | ||
115 | addr = get_unshared_area(addr, len); | ||
116 | } | ||
117 | return addr; | ||
118 | } | ||
119 | |||
120 | static unsigned long do_mmap2(unsigned long addr, unsigned long len, | ||
121 | unsigned long prot, unsigned long flags, unsigned long fd, | ||
122 | unsigned long pgoff) | ||
123 | { | ||
124 | struct file * file = NULL; | ||
125 | unsigned long error = -EBADF; | ||
126 | if (!(flags & MAP_ANONYMOUS)) { | ||
127 | file = fget(fd); | ||
128 | if (!file) | ||
129 | goto out; | ||
130 | } | ||
131 | |||
132 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
133 | |||
134 | down_write(¤t->mm->mmap_sem); | ||
135 | error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
136 | up_write(¤t->mm->mmap_sem); | ||
137 | |||
138 | if (file != NULL) | ||
139 | fput(file); | ||
140 | out: | ||
141 | return error; | ||
142 | } | ||
143 | |||
144 | asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, | ||
145 | unsigned long prot, unsigned long flags, unsigned long fd, | ||
146 | unsigned long pgoff) | ||
147 | { | ||
148 | /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE | ||
149 | we have. */ | ||
150 | return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); | ||
151 | } | ||
152 | |||
153 | asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, | ||
154 | unsigned long prot, unsigned long flags, unsigned long fd, | ||
155 | unsigned long offset) | ||
156 | { | ||
157 | if (!(offset & ~PAGE_MASK)) { | ||
158 | return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); | ||
159 | } else { | ||
160 | return -EINVAL; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | long sys_shmat_wrapper(int shmid, char __user *shmaddr, int shmflag) | ||
165 | { | ||
166 | unsigned long raddr; | ||
167 | int r; | ||
168 | |||
169 | r = do_shmat(shmid, shmaddr, shmflag, &raddr); | ||
170 | if (r < 0) | ||
171 | return r; | ||
172 | return raddr; | ||
173 | } | ||
174 | |||
175 | /* Fucking broken ABI */ | ||
176 | |||
177 | #ifdef CONFIG_64BIT | ||
178 | asmlinkage long parisc_truncate64(const char __user * path, | ||
179 | unsigned int high, unsigned int low) | ||
180 | { | ||
181 | return sys_truncate(path, (long)high << 32 | low); | ||
182 | } | ||
183 | |||
184 | asmlinkage long parisc_ftruncate64(unsigned int fd, | ||
185 | unsigned int high, unsigned int low) | ||
186 | { | ||
187 | return sys_ftruncate(fd, (long)high << 32 | low); | ||
188 | } | ||
189 | |||
190 | /* stubs for the benefit of the syscall_table since truncate64 and truncate | ||
191 | * are identical on LP64 */ | ||
192 | asmlinkage long sys_truncate64(const char __user * path, unsigned long length) | ||
193 | { | ||
194 | return sys_truncate(path, length); | ||
195 | } | ||
196 | asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length) | ||
197 | { | ||
198 | return sys_ftruncate(fd, length); | ||
199 | } | ||
200 | asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
201 | { | ||
202 | return sys_fcntl(fd, cmd, arg); | ||
203 | } | ||
204 | #else | ||
205 | |||
206 | asmlinkage long parisc_truncate64(const char __user * path, | ||
207 | unsigned int high, unsigned int low) | ||
208 | { | ||
209 | return sys_truncate64(path, (loff_t)high << 32 | low); | ||
210 | } | ||
211 | |||
212 | asmlinkage long parisc_ftruncate64(unsigned int fd, | ||
213 | unsigned int high, unsigned int low) | ||
214 | { | ||
215 | return sys_ftruncate64(fd, (loff_t)high << 32 | low); | ||
216 | } | ||
217 | #endif | ||
218 | |||
219 | asmlinkage ssize_t parisc_pread64(unsigned int fd, char __user *buf, size_t count, | ||
220 | unsigned int high, unsigned int low) | ||
221 | { | ||
222 | return sys_pread64(fd, buf, count, (loff_t)high << 32 | low); | ||
223 | } | ||
224 | |||
225 | asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char __user *buf, | ||
226 | size_t count, unsigned int high, unsigned int low) | ||
227 | { | ||
228 | return sys_pwrite64(fd, buf, count, (loff_t)high << 32 | low); | ||
229 | } | ||
230 | |||
231 | asmlinkage ssize_t parisc_readahead(int fd, unsigned int high, unsigned int low, | ||
232 | size_t count) | ||
233 | { | ||
234 | return sys_readahead(fd, (loff_t)high << 32 | low, count); | ||
235 | } | ||
236 | |||
237 | asmlinkage long parisc_fadvise64_64(int fd, | ||
238 | unsigned int high_off, unsigned int low_off, | ||
239 | unsigned int high_len, unsigned int low_len, int advice) | ||
240 | { | ||
241 | return sys_fadvise64_64(fd, (loff_t)high_off << 32 | low_off, | ||
242 | (loff_t)high_len << 32 | low_len, advice); | ||
243 | } | ||
244 | |||
245 | asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag) | ||
246 | { | ||
247 | return -ENOMEM; | ||
248 | } | ||
249 | |||
250 | asmlinkage int sys_free_hugepages(unsigned long addr) | ||
251 | { | ||
252 | return -EINVAL; | ||
253 | } | ||
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c new file mode 100644 index 000000000000..613569018410 --- /dev/null +++ b/arch/parisc/kernel/sys_parisc32.c | |||
@@ -0,0 +1,720 @@ | |||
1 | /* | ||
2 | * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls. | ||
3 | * | ||
4 | * Copyright (C) 2000-2001 Hewlett Packard Company | ||
5 | * Copyright (C) 2000 John Marvin | ||
6 | * Copyright (C) 2001 Matthew Wilcox | ||
7 | * | ||
8 | * These routines maintain argument size conversion between 32bit and 64bit | ||
9 | * environment. Based heavily on sys_ia32.c and sys_sparc32.c. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/compat.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/fs.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/file.h> | ||
19 | #include <linux/signal.h> | ||
20 | #include <linux/resource.h> | ||
21 | #include <linux/times.h> | ||
22 | #include <linux/utsname.h> | ||
23 | #include <linux/time.h> | ||
24 | #include <linux/timex.h> | ||
25 | #include <linux/smp.h> | ||
26 | #include <linux/smp_lock.h> | ||
27 | #include <linux/sem.h> | ||
28 | #include <linux/msg.h> | ||
29 | #include <linux/shm.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/uio.h> | ||
32 | #include <linux/nfs_fs.h> | ||
33 | #include <linux/ncp_fs.h> | ||
34 | #include <linux/sunrpc/svc.h> | ||
35 | #include <linux/nfsd/nfsd.h> | ||
36 | #include <linux/nfsd/cache.h> | ||
37 | #include <linux/nfsd/xdr.h> | ||
38 | #include <linux/nfsd/syscall.h> | ||
39 | #include <linux/poll.h> | ||
40 | #include <linux/personality.h> | ||
41 | #include <linux/stat.h> | ||
42 | #include <linux/highmem.h> | ||
43 | #include <linux/highuid.h> | ||
44 | #include <linux/mman.h> | ||
45 | #include <linux/binfmts.h> | ||
46 | #include <linux/namei.h> | ||
47 | #include <linux/vfs.h> | ||
48 | #include <linux/ptrace.h> | ||
49 | #include <linux/swap.h> | ||
50 | #include <linux/syscalls.h> | ||
51 | |||
52 | #include <asm/types.h> | ||
53 | #include <asm/uaccess.h> | ||
54 | #include <asm/semaphore.h> | ||
55 | #include <asm/mmu_context.h> | ||
56 | |||
57 | #include "sys32.h" | ||
58 | |||
59 | #undef DEBUG | ||
60 | |||
61 | #ifdef DEBUG | ||
62 | #define DBG(x) printk x | ||
63 | #else | ||
64 | #define DBG(x) | ||
65 | #endif | ||
66 | |||
67 | /* | ||
68 | * sys32_execve() executes a new program. | ||
69 | */ | ||
70 | |||
71 | asmlinkage int sys32_execve(struct pt_regs *regs) | ||
72 | { | ||
73 | int error; | ||
74 | char *filename; | ||
75 | |||
76 | DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); | ||
77 | filename = getname((const char __user *) regs->gr[26]); | ||
78 | error = PTR_ERR(filename); | ||
79 | if (IS_ERR(filename)) | ||
80 | goto out; | ||
81 | error = compat_do_execve(filename, compat_ptr(regs->gr[25]), | ||
82 | compat_ptr(regs->gr[24]), regs); | ||
83 | if (error == 0) { | ||
84 | task_lock(current); | ||
85 | current->ptrace &= ~PT_DTRACE; | ||
86 | task_unlock(current); | ||
87 | } | ||
88 | putname(filename); | ||
89 | out: | ||
90 | |||
91 | return error; | ||
92 | } | ||
93 | |||
94 | asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, | ||
95 | int r22, int r21, int r20) | ||
96 | { | ||
97 | printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n", | ||
98 | current->comm, current->pid, r20); | ||
99 | return -ENOSYS; | ||
100 | } | ||
101 | |||
102 | #ifdef CONFIG_SYSCTL | ||
103 | |||
104 | struct __sysctl_args32 { | ||
105 | u32 name; | ||
106 | int nlen; | ||
107 | u32 oldval; | ||
108 | u32 oldlenp; | ||
109 | u32 newval; | ||
110 | u32 newlen; | ||
111 | u32 __unused[4]; | ||
112 | }; | ||
113 | |||
114 | asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) | ||
115 | { | ||
116 | struct __sysctl_args32 tmp; | ||
117 | int error; | ||
118 | unsigned int oldlen32; | ||
119 | size_t oldlen, *oldlenp = NULL; | ||
120 | unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7; | ||
121 | extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, | ||
122 | void *newval, size_t newlen); | ||
123 | |||
124 | DBG(("sysctl32(%p)\n", args)); | ||
125 | |||
126 | if (copy_from_user(&tmp, args, sizeof(tmp))) | ||
127 | return -EFAULT; | ||
128 | |||
129 | if (tmp.oldval && tmp.oldlenp) { | ||
130 | /* Duh, this is ugly and might not work if sysctl_args | ||
131 | is in read-only memory, but do_sysctl does indirectly | ||
132 | a lot of uaccess in both directions and we'd have to | ||
133 | basically copy the whole sysctl.c here, and | ||
134 | glibc's __sysctl uses rw memory for the structure | ||
135 | anyway. */ | ||
136 | /* a possibly better hack than this, which will avoid the | ||
137 | * problem if the struct is read only, is to push the | ||
138 | * 'oldlen' value out to the user's stack instead. -PB | ||
139 | */ | ||
140 | if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp)) | ||
141 | return -EFAULT; | ||
142 | oldlen = oldlen32; | ||
143 | if (put_user(oldlen, (size_t *)addr)) | ||
144 | return -EFAULT; | ||
145 | oldlenp = (size_t *)addr; | ||
146 | } | ||
147 | |||
148 | lock_kernel(); | ||
149 | error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval, | ||
150 | oldlenp, (void *)(u64)tmp.newval, tmp.newlen); | ||
151 | unlock_kernel(); | ||
152 | if (oldlenp) { | ||
153 | if (!error) { | ||
154 | if (get_user(oldlen, (size_t *)addr)) { | ||
155 | error = -EFAULT; | ||
156 | } else { | ||
157 | oldlen32 = oldlen; | ||
158 | if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp)) | ||
159 | error = -EFAULT; | ||
160 | } | ||
161 | } | ||
162 | if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused))) | ||
163 | error = -EFAULT; | ||
164 | } | ||
165 | return error; | ||
166 | } | ||
167 | |||
168 | #endif /* CONFIG_SYSCTL */ | ||
169 | |||
170 | asmlinkage long sys32_sched_rr_get_interval(pid_t pid, | ||
171 | struct compat_timespec __user *interval) | ||
172 | { | ||
173 | struct timespec t; | ||
174 | int ret; | ||
175 | |||
176 | KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t); | ||
177 | if (put_compat_timespec(&t, interval)) | ||
178 | return -EFAULT; | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | static int | ||
183 | put_compat_timeval(struct compat_timeval __user *u, struct timeval *t) | ||
184 | { | ||
185 | struct compat_timeval t32; | ||
186 | t32.tv_sec = t->tv_sec; | ||
187 | t32.tv_usec = t->tv_usec; | ||
188 | return copy_to_user(u, &t32, sizeof t32); | ||
189 | } | ||
190 | |||
191 | static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) | ||
192 | { | ||
193 | long usec; | ||
194 | |||
195 | if (__get_user(o->tv_sec, &i->tv_sec)) | ||
196 | return -EFAULT; | ||
197 | if (__get_user(usec, &i->tv_usec)) | ||
198 | return -EFAULT; | ||
199 | o->tv_nsec = usec * 1000; | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | asmlinkage int | ||
204 | sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) | ||
205 | { | ||
206 | extern void do_gettimeofday(struct timeval *tv); | ||
207 | |||
208 | if (tv) { | ||
209 | struct timeval ktv; | ||
210 | do_gettimeofday(&ktv); | ||
211 | if (put_compat_timeval(tv, &ktv)) | ||
212 | return -EFAULT; | ||
213 | } | ||
214 | if (tz) { | ||
215 | extern struct timezone sys_tz; | ||
216 | if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) | ||
217 | return -EFAULT; | ||
218 | } | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | asmlinkage | ||
223 | int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) | ||
224 | { | ||
225 | struct timespec kts; | ||
226 | struct timezone ktz; | ||
227 | |||
228 | if (tv) { | ||
229 | if (get_ts32(&kts, tv)) | ||
230 | return -EFAULT; | ||
231 | } | ||
232 | if (tz) { | ||
233 | if (copy_from_user(&ktz, tz, sizeof(ktz))) | ||
234 | return -EFAULT; | ||
235 | } | ||
236 | |||
237 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); | ||
238 | } | ||
239 | |||
240 | int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) | ||
241 | { | ||
242 | int err; | ||
243 | |||
244 | if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) || | ||
245 | !new_valid_dev(stat->rdev)) | ||
246 | return -EOVERFLOW; | ||
247 | |||
248 | err = put_user(new_encode_dev(stat->dev), &statbuf->st_dev); | ||
249 | err |= put_user(stat->ino, &statbuf->st_ino); | ||
250 | err |= put_user(stat->mode, &statbuf->st_mode); | ||
251 | err |= put_user(stat->nlink, &statbuf->st_nlink); | ||
252 | err |= put_user(0, &statbuf->st_reserved1); | ||
253 | err |= put_user(0, &statbuf->st_reserved2); | ||
254 | err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev); | ||
255 | err |= put_user(stat->size, &statbuf->st_size); | ||
256 | err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); | ||
257 | err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); | ||
258 | err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); | ||
259 | err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); | ||
260 | err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); | ||
261 | err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); | ||
262 | err |= put_user(stat->blksize, &statbuf->st_blksize); | ||
263 | err |= put_user(stat->blocks, &statbuf->st_blocks); | ||
264 | err |= put_user(0, &statbuf->__unused1); | ||
265 | err |= put_user(0, &statbuf->__unused2); | ||
266 | err |= put_user(0, &statbuf->__unused3); | ||
267 | err |= put_user(0, &statbuf->__unused4); | ||
268 | err |= put_user(0, &statbuf->__unused5); | ||
269 | err |= put_user(0, &statbuf->st_fstype); /* not avail */ | ||
270 | err |= put_user(0, &statbuf->st_realdev); /* not avail */ | ||
271 | err |= put_user(0, &statbuf->st_basemode); /* not avail */ | ||
272 | err |= put_user(0, &statbuf->st_spareshort); | ||
273 | err |= put_user(stat->uid, &statbuf->st_uid); | ||
274 | err |= put_user(stat->gid, &statbuf->st_gid); | ||
275 | err |= put_user(0, &statbuf->st_spare4[0]); | ||
276 | err |= put_user(0, &statbuf->st_spare4[1]); | ||
277 | err |= put_user(0, &statbuf->st_spare4[2]); | ||
278 | |||
279 | return err; | ||
280 | } | ||
281 | |||
282 | struct linux32_dirent { | ||
283 | u32 d_ino; | ||
284 | compat_off_t d_off; | ||
285 | u16 d_reclen; | ||
286 | char d_name[1]; | ||
287 | }; | ||
288 | |||
289 | struct old_linux32_dirent { | ||
290 | u32 d_ino; | ||
291 | u32 d_offset; | ||
292 | u16 d_namlen; | ||
293 | char d_name[1]; | ||
294 | }; | ||
295 | |||
296 | struct getdents32_callback { | ||
297 | struct linux32_dirent __user * current_dir; | ||
298 | struct linux32_dirent __user * previous; | ||
299 | int count; | ||
300 | int error; | ||
301 | }; | ||
302 | |||
303 | struct readdir32_callback { | ||
304 | struct old_linux32_dirent __user * dirent; | ||
305 | int count; | ||
306 | }; | ||
307 | |||
308 | #define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1))) | ||
309 | #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) | ||
310 | static int | ||
311 | filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, | ||
312 | unsigned int d_type) | ||
313 | { | ||
314 | struct linux32_dirent __user * dirent; | ||
315 | struct getdents32_callback * buf = (struct getdents32_callback *) __buf; | ||
316 | int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4); | ||
317 | |||
318 | buf->error = -EINVAL; /* only used if we fail.. */ | ||
319 | if (reclen > buf->count) | ||
320 | return -EINVAL; | ||
321 | dirent = buf->previous; | ||
322 | if (dirent) | ||
323 | put_user(offset, &dirent->d_off); | ||
324 | dirent = buf->current_dir; | ||
325 | buf->previous = dirent; | ||
326 | put_user(ino, &dirent->d_ino); | ||
327 | put_user(reclen, &dirent->d_reclen); | ||
328 | copy_to_user(dirent->d_name, name, namlen); | ||
329 | put_user(0, dirent->d_name + namlen); | ||
330 | dirent = ((void __user *)dirent) + reclen; | ||
331 | buf->current_dir = dirent; | ||
332 | buf->count -= reclen; | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | asmlinkage long | ||
337 | sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count) | ||
338 | { | ||
339 | struct file * file; | ||
340 | struct linux32_dirent __user * lastdirent; | ||
341 | struct getdents32_callback buf; | ||
342 | int error; | ||
343 | |||
344 | error = -EBADF; | ||
345 | file = fget(fd); | ||
346 | if (!file) | ||
347 | goto out; | ||
348 | |||
349 | buf.current_dir = (struct linux32_dirent __user *) dirent; | ||
350 | buf.previous = NULL; | ||
351 | buf.count = count; | ||
352 | buf.error = 0; | ||
353 | |||
354 | error = vfs_readdir(file, filldir32, &buf); | ||
355 | if (error < 0) | ||
356 | goto out_putf; | ||
357 | error = buf.error; | ||
358 | lastdirent = buf.previous; | ||
359 | if (lastdirent) { | ||
360 | put_user(file->f_pos, &lastdirent->d_off); | ||
361 | error = count - buf.count; | ||
362 | } | ||
363 | |||
364 | out_putf: | ||
365 | fput(file); | ||
366 | out: | ||
367 | return error; | ||
368 | } | ||
369 | |||
370 | static int | ||
371 | fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, | ||
372 | unsigned int d_type) | ||
373 | { | ||
374 | struct readdir32_callback * buf = (struct readdir32_callback *) __buf; | ||
375 | struct old_linux32_dirent __user * dirent; | ||
376 | |||
377 | if (buf->count) | ||
378 | return -EINVAL; | ||
379 | buf->count++; | ||
380 | dirent = buf->dirent; | ||
381 | put_user(ino, &dirent->d_ino); | ||
382 | put_user(offset, &dirent->d_offset); | ||
383 | put_user(namlen, &dirent->d_namlen); | ||
384 | copy_to_user(dirent->d_name, name, namlen); | ||
385 | put_user(0, dirent->d_name + namlen); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | asmlinkage long | ||
390 | sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count) | ||
391 | { | ||
392 | int error; | ||
393 | struct file * file; | ||
394 | struct readdir32_callback buf; | ||
395 | |||
396 | error = -EBADF; | ||
397 | file = fget(fd); | ||
398 | if (!file) | ||
399 | goto out; | ||
400 | |||
401 | buf.count = 0; | ||
402 | buf.dirent = dirent; | ||
403 | |||
404 | error = vfs_readdir(file, fillonedir32, &buf); | ||
405 | if (error >= 0) | ||
406 | error = buf.count; | ||
407 | fput(file); | ||
408 | out: | ||
409 | return error; | ||
410 | } | ||
411 | |||
412 | /*** copied from mips64 ***/ | ||
413 | /* | ||
414 | * Ooo, nasty. We need here to frob 32-bit unsigned longs to | ||
415 | * 64-bit unsigned longs. | ||
416 | */ | ||
417 | |||
418 | static inline int | ||
419 | get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) | ||
420 | { | ||
421 | n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); | ||
422 | if (ufdset) { | ||
423 | unsigned long odd; | ||
424 | |||
425 | if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32))) | ||
426 | return -EFAULT; | ||
427 | |||
428 | odd = n & 1UL; | ||
429 | n &= ~1UL; | ||
430 | while (n) { | ||
431 | unsigned long h, l; | ||
432 | __get_user(l, ufdset); | ||
433 | __get_user(h, ufdset+1); | ||
434 | ufdset += 2; | ||
435 | *fdset++ = h << 32 | l; | ||
436 | n -= 2; | ||
437 | } | ||
438 | if (odd) | ||
439 | __get_user(*fdset, ufdset); | ||
440 | } else { | ||
441 | /* Tricky, must clear full unsigned long in the | ||
442 | * kernel fdset at the end, this makes sure that | ||
443 | * actually happens. | ||
444 | */ | ||
445 | memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); | ||
446 | } | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static inline void | ||
451 | set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) | ||
452 | { | ||
453 | unsigned long odd; | ||
454 | n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); | ||
455 | |||
456 | if (!ufdset) | ||
457 | return; | ||
458 | |||
459 | odd = n & 1UL; | ||
460 | n &= ~1UL; | ||
461 | while (n) { | ||
462 | unsigned long h, l; | ||
463 | l = *fdset++; | ||
464 | h = l >> 32; | ||
465 | __put_user(l, ufdset); | ||
466 | __put_user(h, ufdset+1); | ||
467 | ufdset += 2; | ||
468 | n -= 2; | ||
469 | } | ||
470 | if (odd) | ||
471 | __put_user(*fdset, ufdset); | ||
472 | } | ||
473 | |||
474 | struct msgbuf32 { | ||
475 | int mtype; | ||
476 | char mtext[1]; | ||
477 | }; | ||
478 | |||
479 | asmlinkage long sys32_msgsnd(int msqid, | ||
480 | struct msgbuf32 __user *umsgp32, | ||
481 | size_t msgsz, int msgflg) | ||
482 | { | ||
483 | struct msgbuf *mb; | ||
484 | struct msgbuf32 mb32; | ||
485 | int err; | ||
486 | |||
487 | if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL) | ||
488 | return -ENOMEM; | ||
489 | |||
490 | err = get_user(mb32.mtype, &umsgp32->mtype); | ||
491 | mb->mtype = mb32.mtype; | ||
492 | err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz); | ||
493 | |||
494 | if (err) | ||
495 | err = -EFAULT; | ||
496 | else | ||
497 | KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg); | ||
498 | |||
499 | kfree(mb); | ||
500 | return err; | ||
501 | } | ||
502 | |||
503 | asmlinkage long sys32_msgrcv(int msqid, | ||
504 | struct msgbuf32 __user *umsgp32, | ||
505 | size_t msgsz, long msgtyp, int msgflg) | ||
506 | { | ||
507 | struct msgbuf *mb; | ||
508 | struct msgbuf32 mb32; | ||
509 | int err, len; | ||
510 | |||
511 | if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL) | ||
512 | return -ENOMEM; | ||
513 | |||
514 | KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg); | ||
515 | |||
516 | if (err >= 0) { | ||
517 | len = err; | ||
518 | mb32.mtype = mb->mtype; | ||
519 | err = put_user(mb32.mtype, &umsgp32->mtype); | ||
520 | err |= copy_to_user(&umsgp32->mtext, mb->mtext, len); | ||
521 | if (err) | ||
522 | err = -EFAULT; | ||
523 | else | ||
524 | err = len; | ||
525 | } | ||
526 | |||
527 | kfree(mb); | ||
528 | return err; | ||
529 | } | ||
530 | |||
531 | asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count) | ||
532 | { | ||
533 | mm_segment_t old_fs = get_fs(); | ||
534 | int ret; | ||
535 | off_t of; | ||
536 | |||
537 | if (offset && get_user(of, offset)) | ||
538 | return -EFAULT; | ||
539 | |||
540 | set_fs(KERNEL_DS); | ||
541 | ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); | ||
542 | set_fs(old_fs); | ||
543 | |||
544 | if (offset && put_user(of, offset)) | ||
545 | return -EFAULT; | ||
546 | |||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count) | ||
551 | { | ||
552 | mm_segment_t old_fs = get_fs(); | ||
553 | int ret; | ||
554 | loff_t lof; | ||
555 | |||
556 | if (offset && get_user(lof, offset)) | ||
557 | return -EFAULT; | ||
558 | |||
559 | set_fs(KERNEL_DS); | ||
560 | ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count); | ||
561 | set_fs(old_fs); | ||
562 | |||
563 | if (offset && put_user(lof, offset)) | ||
564 | return -EFAULT; | ||
565 | |||
566 | return ret; | ||
567 | } | ||
568 | |||
569 | |||
570 | struct timex32 { | ||
571 | unsigned int modes; /* mode selector */ | ||
572 | int offset; /* time offset (usec) */ | ||
573 | int freq; /* frequency offset (scaled ppm) */ | ||
574 | int maxerror; /* maximum error (usec) */ | ||
575 | int esterror; /* estimated error (usec) */ | ||
576 | int status; /* clock command/status */ | ||
577 | int constant; /* pll time constant */ | ||
578 | int precision; /* clock precision (usec) (read only) */ | ||
579 | int tolerance; /* clock frequency tolerance (ppm) | ||
580 | * (read only) | ||
581 | */ | ||
582 | struct compat_timeval time; /* (read only) */ | ||
583 | int tick; /* (modified) usecs between clock ticks */ | ||
584 | |||
585 | int ppsfreq; /* pps frequency (scaled ppm) (ro) */ | ||
586 | int jitter; /* pps jitter (us) (ro) */ | ||
587 | int shift; /* interval duration (s) (shift) (ro) */ | ||
588 | int stabil; /* pps stability (scaled ppm) (ro) */ | ||
589 | int jitcnt; /* jitter limit exceeded (ro) */ | ||
590 | int calcnt; /* calibration intervals (ro) */ | ||
591 | int errcnt; /* calibration errors (ro) */ | ||
592 | int stbcnt; /* stability limit exceeded (ro) */ | ||
593 | |||
594 | int :32; int :32; int :32; int :32; | ||
595 | int :32; int :32; int :32; int :32; | ||
596 | int :32; int :32; int :32; int :32; | ||
597 | }; | ||
598 | |||
599 | asmlinkage long sys32_adjtimex(struct timex32 __user *txc_p32) | ||
600 | { | ||
601 | struct timex txc; | ||
602 | struct timex32 t32; | ||
603 | int ret; | ||
604 | extern int do_adjtimex(struct timex *txc); | ||
605 | |||
606 | if(copy_from_user(&t32, txc_p32, sizeof(struct timex32))) | ||
607 | return -EFAULT; | ||
608 | #undef CP | ||
609 | #define CP(x) txc.x = t32.x | ||
610 | CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror); | ||
611 | CP(status); CP(constant); CP(precision); CP(tolerance); | ||
612 | CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter); | ||
613 | CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt); | ||
614 | CP(stbcnt); | ||
615 | ret = do_adjtimex(&txc); | ||
616 | #undef CP | ||
617 | #define CP(x) t32.x = txc.x | ||
618 | CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror); | ||
619 | CP(status); CP(constant); CP(precision); CP(tolerance); | ||
620 | CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter); | ||
621 | CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt); | ||
622 | CP(stbcnt); | ||
623 | return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret; | ||
624 | } | ||
625 | |||
626 | |||
627 | struct sysinfo32 { | ||
628 | s32 uptime; | ||
629 | u32 loads[3]; | ||
630 | u32 totalram; | ||
631 | u32 freeram; | ||
632 | u32 sharedram; | ||
633 | u32 bufferram; | ||
634 | u32 totalswap; | ||
635 | u32 freeswap; | ||
636 | unsigned short procs; | ||
637 | u32 totalhigh; | ||
638 | u32 freehigh; | ||
639 | u32 mem_unit; | ||
640 | char _f[12]; | ||
641 | }; | ||
642 | |||
643 | /* We used to call sys_sysinfo and translate the result. But sys_sysinfo | ||
644 | * undoes the good work done elsewhere, and rather than undoing the | ||
645 | * damage, I decided to just duplicate the code from sys_sysinfo here. | ||
646 | */ | ||
647 | |||
648 | asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info) | ||
649 | { | ||
650 | struct sysinfo val; | ||
651 | int err; | ||
652 | unsigned long seq; | ||
653 | |||
654 | /* We don't need a memset here because we copy the | ||
655 | * struct to userspace once element at a time. | ||
656 | */ | ||
657 | |||
658 | do { | ||
659 | seq = read_seqbegin(&xtime_lock); | ||
660 | val.uptime = jiffies / HZ; | ||
661 | |||
662 | val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); | ||
663 | val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); | ||
664 | val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); | ||
665 | |||
666 | val.procs = nr_threads; | ||
667 | } while (read_seqretry(&xtime_lock, seq)); | ||
668 | |||
669 | |||
670 | si_meminfo(&val); | ||
671 | si_swapinfo(&val); | ||
672 | |||
673 | err = put_user (val.uptime, &info->uptime); | ||
674 | err |= __put_user (val.loads[0], &info->loads[0]); | ||
675 | err |= __put_user (val.loads[1], &info->loads[1]); | ||
676 | err |= __put_user (val.loads[2], &info->loads[2]); | ||
677 | err |= __put_user (val.totalram, &info->totalram); | ||
678 | err |= __put_user (val.freeram, &info->freeram); | ||
679 | err |= __put_user (val.sharedram, &info->sharedram); | ||
680 | err |= __put_user (val.bufferram, &info->bufferram); | ||
681 | err |= __put_user (val.totalswap, &info->totalswap); | ||
682 | err |= __put_user (val.freeswap, &info->freeswap); | ||
683 | err |= __put_user (val.procs, &info->procs); | ||
684 | err |= __put_user (val.totalhigh, &info->totalhigh); | ||
685 | err |= __put_user (val.freehigh, &info->freehigh); | ||
686 | err |= __put_user (val.mem_unit, &info->mem_unit); | ||
687 | return err ? -EFAULT : 0; | ||
688 | } | ||
689 | |||
690 | |||
691 | /* lseek() needs a wrapper because 'offset' can be negative, but the top | ||
692 | * half of the argument has been zeroed by syscall.S. | ||
693 | */ | ||
694 | |||
695 | asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin) | ||
696 | { | ||
697 | return sys_lseek(fd, offset, origin); | ||
698 | } | ||
699 | |||
700 | asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg) | ||
701 | { | ||
702 | union semun u; | ||
703 | |||
704 | if (cmd == SETVAL) { | ||
705 | /* Ugh. arg is a union of int,ptr,ptr,ptr, so is 8 bytes. | ||
706 | * The int should be in the first 4, but our argument | ||
707 | * frobbing has left it in the last 4. | ||
708 | */ | ||
709 | u.val = *((int *)&arg + 1); | ||
710 | return sys_semctl (semid, semnum, cmd, u); | ||
711 | } | ||
712 | return sys_semctl (semid, semnum, cmd, arg); | ||
713 | } | ||
714 | |||
715 | long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf, | ||
716 | size_t len) | ||
717 | { | ||
718 | return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low, | ||
719 | buf, len); | ||
720 | } | ||
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S new file mode 100644 index 000000000000..32ea701f4d20 --- /dev/null +++ b/arch/parisc/kernel/syscall.S | |||
@@ -0,0 +1,703 @@ | |||
1 | /* | ||
2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
3 | * | ||
4 | * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai> | ||
5 | * Licensed under the GNU GPL. | ||
6 | * thanks to Philipp Rumpf, Mike Shaver and various others | ||
7 | * sorry about the wall, puffin.. | ||
8 | */ | ||
9 | |||
10 | #include <asm/offsets.h> | ||
11 | #include <asm/unistd.h> | ||
12 | #include <asm/errno.h> | ||
13 | #include <asm/psw.h> | ||
14 | #include <asm/thread_info.h> | ||
15 | |||
16 | #include <asm/assembly.h> | ||
17 | #include <asm/processor.h> | ||
18 | |||
19 | /* We fill the empty parts of the gateway page with | ||
20 | * something that will kill the kernel or a | ||
21 | * userspace application. | ||
22 | */ | ||
23 | #define KILL_INSN break 0,0 | ||
24 | |||
25 | #include <linux/config.h> /* for CONFIG_SMP */ | ||
26 | |||
27 | #ifdef __LP64__ | ||
28 | .level 2.0w | ||
29 | #else | ||
30 | .level 1.1 | ||
31 | #endif | ||
32 | |||
33 | #ifndef __LP64__ | ||
34 | .macro fixup_branch,lbl | ||
35 | b \lbl | ||
36 | .endm | ||
37 | #else | ||
38 | .macro fixup_branch,lbl | ||
39 | ldil L%\lbl, %r1 | ||
40 | ldo R%\lbl(%r1), %r1 | ||
41 | bv,n %r0(%r1) | ||
42 | .endm | ||
43 | #endif | ||
44 | |||
45 | .text | ||
46 | |||
47 | .import syscall_exit,code | ||
48 | .import syscall_exit_rfi,code | ||
49 | .export linux_gateway_page | ||
50 | |||
51 | /* Linux gateway page is aliased to virtual page 0 in the kernel | ||
52 | * address space. Since it is a gateway page it cannot be | ||
53 | * dereferenced, so null pointers will still fault. We start | ||
54 | * the actual entry point at 0x100. We put break instructions | ||
55 | * at the beginning of the page to trap null indirect function | ||
56 | * pointers. | ||
57 | */ | ||
58 | |||
59 | .align 4096 | ||
60 | linux_gateway_page: | ||
61 | |||
62 | /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */ | ||
63 | .rept 44 | ||
64 | KILL_INSN | ||
65 | .endr | ||
66 | |||
67 | /* ADDRESS 0xb0 to 0xb4, lws uses 1 insns for entry */ | ||
68 | /* Light-weight-syscall entry must always be located at 0xb0 */ | ||
69 | /* WARNING: Keep this number updated with table size changes */ | ||
70 | #define __NR_lws_entries (2) | ||
71 | |||
72 | lws_entry: | ||
73 | /* Unconditional branch to lws_start, located on the | ||
74 | same gateway page */ | ||
75 | b,n lws_start | ||
76 | |||
77 | /* Fill from 0xb4 to 0xe0 */ | ||
78 | .rept 11 | ||
79 | KILL_INSN | ||
80 | .endr | ||
81 | |||
82 | /* This function MUST be located at 0xe0 for glibc's threading | ||
83 | mechanism to work. DO NOT MOVE THIS CODE EVER! */ | ||
84 | set_thread_pointer: | ||
85 | gate .+8, %r0 /* increase privilege */ | ||
86 | depi 3, 31, 2, %r31 /* Ensure we return into user mode. */ | ||
87 | be 0(%sr7,%r31) /* return to user space */ | ||
88 | mtctl %r26, %cr27 /* move arg0 to the control register */ | ||
89 | |||
90 | /* Increase the chance of trapping if random jumps occur to this | ||
91 | address, fill from 0xf0 to 0x100 */ | ||
92 | .rept 4 | ||
93 | KILL_INSN | ||
94 | .endr | ||
95 | |||
96 | /* This address must remain fixed at 0x100 for glibc's syscalls to work */ | ||
97 | .align 256 | ||
98 | linux_gateway_entry: | ||
99 | gate .+8, %r0 /* become privileged */ | ||
100 | mtsp %r0,%sr4 /* get kernel space into sr4 */ | ||
101 | mtsp %r0,%sr5 /* get kernel space into sr5 */ | ||
102 | mtsp %r0,%sr6 /* get kernel space into sr6 */ | ||
103 | mfsp %sr7,%r1 /* save user sr7 */ | ||
104 | mtsp %r1,%sr3 /* and store it in sr3 */ | ||
105 | |||
106 | #ifdef __LP64__ | ||
107 | /* for now we can *always* set the W bit on entry to the syscall | ||
108 | * since we don't support wide userland processes. We could | ||
109 | * also save the current SM other than in r0 and restore it on | ||
110 | * exit from the syscall, and also use that value to know | ||
111 | * whether to do narrow or wide syscalls. -PB | ||
112 | */ | ||
113 | ssm PSW_SM_W, %r1 | ||
114 | extrd,u %r1,PSW_W_BIT,1,%r1 | ||
115 | /* sp must be aligned on 4, so deposit the W bit setting into | ||
116 | * the bottom of sp temporarily */ | ||
117 | or,ev %r1,%r30,%r30 | ||
118 | b,n 1f | ||
119 | /* The top halves of argument registers must be cleared on syscall | ||
120 | * entry from narrow executable. | ||
121 | */ | ||
122 | depdi 0, 31, 32, %r26 | ||
123 | depdi 0, 31, 32, %r25 | ||
124 | depdi 0, 31, 32, %r24 | ||
125 | depdi 0, 31, 32, %r23 | ||
126 | depdi 0, 31, 32, %r22 | ||
127 | depdi 0, 31, 32, %r21 | ||
128 | 1: | ||
129 | #endif | ||
130 | mfctl %cr30,%r1 | ||
131 | xor %r1,%r30,%r30 /* ye olde xor trick */ | ||
132 | xor %r1,%r30,%r1 | ||
133 | xor %r1,%r30,%r30 | ||
134 | |||
135 | ldo THREAD_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */ | ||
136 | |||
137 | /* N.B.: It is critical that we don't set sr7 to 0 until r30 | ||
138 | * contains a valid kernel stack pointer. It is also | ||
139 | * critical that we don't start using the kernel stack | ||
140 | * until after sr7 has been set to 0. | ||
141 | */ | ||
142 | |||
143 | mtsp %r0,%sr7 /* get kernel space into sr7 */ | ||
144 | STREGM %r1,FRAME_SIZE(%r30) /* save r1 (usp) here for now */ | ||
145 | mfctl %cr30,%r1 /* get task ptr in %r1 */ | ||
146 | LDREG TI_TASK(%r1),%r1 | ||
147 | |||
148 | /* Save some registers for sigcontext and potential task | ||
149 | switch (see entry.S for the details of which ones are | ||
150 | saved/restored). TASK_PT_PSW is zeroed so we can see whether | ||
151 | a process is on a syscall or not. For an interrupt the real | ||
152 | PSW value is stored. This is needed for gdb and sys_ptrace. */ | ||
153 | STREG %r0, TASK_PT_PSW(%r1) | ||
154 | STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */ | ||
155 | STREG %r19, TASK_PT_GR19(%r1) | ||
156 | |||
157 | LDREGM -FRAME_SIZE(%r30), %r2 /* get users sp back */ | ||
158 | #ifdef __LP64__ | ||
159 | extrd,u %r2,63,1,%r19 /* W hidden in bottom bit */ | ||
160 | #if 0 | ||
161 | xor %r19,%r2,%r2 /* clear bottom bit */ | ||
162 | depd,z %r19,1,1,%r19 | ||
163 | std %r19,TASK_PT_PSW(%r1) | ||
164 | #endif | ||
165 | #endif | ||
166 | STREG %r2, TASK_PT_GR30(%r1) /* ... and save it */ | ||
167 | |||
168 | STREG %r20, TASK_PT_GR20(%r1) | ||
169 | STREG %r21, TASK_PT_GR21(%r1) | ||
170 | STREG %r22, TASK_PT_GR22(%r1) | ||
171 | STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */ | ||
172 | STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */ | ||
173 | STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */ | ||
174 | STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ | ||
175 | STREG %r27, TASK_PT_GR27(%r1) /* user dp */ | ||
176 | STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ | ||
177 | STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ | ||
178 | STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */ | ||
179 | STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ | ||
180 | |||
181 | ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */ | ||
182 | save_fp %r27 /* or potential task switch */ | ||
183 | |||
184 | mfctl %cr11, %r27 /* i.e. SAR */ | ||
185 | STREG %r27, TASK_PT_SAR(%r1) | ||
186 | |||
187 | loadgp | ||
188 | |||
189 | #ifdef __LP64__ | ||
190 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
191 | copy %r19,%r2 /* W bit back to r2 */ | ||
192 | #else | ||
193 | /* no need to save these on stack in wide mode because the first 8 | ||
194 | * args are passed in registers */ | ||
195 | stw %r22, -52(%r30) /* 5th argument */ | ||
196 | stw %r21, -56(%r30) /* 6th argument */ | ||
197 | #endif | ||
198 | |||
199 | /* Are we being ptraced? */ | ||
200 | mfctl %cr30, %r1 | ||
201 | LDREG TI_TASK(%r1),%r1 | ||
202 | LDREG TASK_PTRACE(%r1), %r1 | ||
203 | bb,<,n %r1,31,.Ltracesys | ||
204 | |||
205 | /* Note! We cannot use the syscall table that is mapped | ||
206 | nearby since the gateway page is mapped execute-only. */ | ||
207 | |||
208 | #ifdef __LP64__ | ||
209 | ldil L%sys_call_table, %r1 | ||
210 | or,= %r2,%r2,%r2 | ||
211 | addil L%(sys_call_table64-sys_call_table), %r1 | ||
212 | ldo R%sys_call_table(%r1), %r19 | ||
213 | or,= %r2,%r2,%r2 | ||
214 | ldo R%sys_call_table64(%r1), %r19 | ||
215 | #else | ||
216 | ldil L%sys_call_table, %r1 | ||
217 | ldo R%sys_call_table(%r1), %r19 | ||
218 | #endif | ||
219 | comiclr,>>= __NR_Linux_syscalls, %r20, %r0 | ||
220 | b,n .Lsyscall_nosys | ||
221 | |||
222 | LDREGX %r20(%r19), %r19 | ||
223 | |||
224 | /* If this is a sys_rt_sigreturn call, and the signal was received | ||
225 | * when not in_syscall, then we want to return via syscall_exit_rfi, | ||
226 | * not syscall_exit. Signal no. in r20, in_syscall in r25 (see | ||
227 | * trampoline code in signal.c). | ||
228 | */ | ||
229 | ldi __NR_rt_sigreturn,%r2 | ||
230 | comb,= %r2,%r20,.Lrt_sigreturn | ||
231 | .Lin_syscall: | ||
232 | ldil L%syscall_exit,%r2 | ||
233 | be 0(%sr7,%r19) | ||
234 | ldo R%syscall_exit(%r2),%r2 | ||
235 | .Lrt_sigreturn: | ||
236 | comib,<> 0,%r25,.Lin_syscall | ||
237 | ldil L%syscall_exit_rfi,%r2 | ||
238 | be 0(%sr7,%r19) | ||
239 | ldo R%syscall_exit_rfi(%r2),%r2 | ||
240 | |||
241 | /* Note! Because we are not running where we were linked, any | ||
242 | calls to functions external to this file must be indirect. To | ||
243 | be safe, we apply the opposite rule to functions within this | ||
244 | file, with local labels given to them to ensure correctness. */ | ||
245 | |||
246 | .Lsyscall_nosys: | ||
247 | syscall_nosys: | ||
248 | ldil L%syscall_exit,%r1 | ||
249 | be R%syscall_exit(%sr7,%r1) | ||
250 | ldo -ENOSYS(%r0),%r28 /* set errno */ | ||
251 | |||
252 | |||
253 | /* Warning! This trace code is a virtual duplicate of the code above so be | ||
254 | * sure to maintain both! */ | ||
255 | .Ltracesys: | ||
256 | tracesys: | ||
257 | /* Need to save more registers so the debugger can see where we | ||
258 | * are. This saves only the lower 8 bits of PSW, so that the C | ||
259 | * bit is still clear on syscalls, and the D bit is set if this | ||
260 | * full register save path has been executed. We check the D | ||
261 | * bit on syscall_return_rfi to determine which registers to | ||
262 | * restore. An interrupt results in a full PSW saved with the | ||
263 | * C bit set, a non-straced syscall entry results in C and D clear | ||
264 | * in the saved PSW. | ||
265 | */ | ||
266 | ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ | ||
267 | LDREG TI_TASK(%r1), %r1 | ||
268 | ssm 0,%r2 | ||
269 | STREG %r2,TASK_PT_PSW(%r1) /* Lower 8 bits only!! */ | ||
270 | mfsp %sr0,%r2 | ||
271 | STREG %r2,TASK_PT_SR0(%r1) | ||
272 | mfsp %sr1,%r2 | ||
273 | STREG %r2,TASK_PT_SR1(%r1) | ||
274 | mfsp %sr2,%r2 | ||
275 | STREG %r2,TASK_PT_SR2(%r1) | ||
276 | mfsp %sr3,%r2 | ||
277 | STREG %r2,TASK_PT_SR3(%r1) | ||
278 | STREG %r2,TASK_PT_SR4(%r1) | ||
279 | STREG %r2,TASK_PT_SR5(%r1) | ||
280 | STREG %r2,TASK_PT_SR6(%r1) | ||
281 | STREG %r2,TASK_PT_SR7(%r1) | ||
282 | STREG %r2,TASK_PT_IASQ0(%r1) | ||
283 | STREG %r2,TASK_PT_IASQ1(%r1) | ||
284 | LDREG TASK_PT_GR31(%r1),%r2 | ||
285 | STREG %r2,TASK_PT_IAOQ0(%r1) | ||
286 | ldo 4(%r2),%r2 | ||
287 | STREG %r2,TASK_PT_IAOQ1(%r1) | ||
288 | ldo TASK_REGS(%r1),%r2 | ||
289 | /* reg_save %r2 */ | ||
290 | STREG %r3,PT_GR3(%r2) | ||
291 | STREG %r4,PT_GR4(%r2) | ||
292 | STREG %r5,PT_GR5(%r2) | ||
293 | STREG %r6,PT_GR6(%r2) | ||
294 | STREG %r7,PT_GR7(%r2) | ||
295 | STREG %r8,PT_GR8(%r2) | ||
296 | STREG %r9,PT_GR9(%r2) | ||
297 | STREG %r10,PT_GR10(%r2) | ||
298 | STREG %r11,PT_GR11(%r2) | ||
299 | STREG %r12,PT_GR12(%r2) | ||
300 | STREG %r13,PT_GR13(%r2) | ||
301 | STREG %r14,PT_GR14(%r2) | ||
302 | STREG %r15,PT_GR15(%r2) | ||
303 | STREG %r16,PT_GR16(%r2) | ||
304 | STREG %r17,PT_GR17(%r2) | ||
305 | STREG %r18,PT_GR18(%r2) | ||
306 | /* Finished saving things for the debugger */ | ||
307 | |||
308 | ldil L%syscall_trace,%r1 | ||
309 | ldil L%tracesys_next,%r2 | ||
310 | be R%syscall_trace(%sr7,%r1) | ||
311 | ldo R%tracesys_next(%r2),%r2 | ||
312 | |||
313 | tracesys_next: | ||
314 | ldil L%sys_call_table,%r1 | ||
315 | ldo R%sys_call_table(%r1), %r19 | ||
316 | |||
317 | ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ | ||
318 | LDREG TI_TASK(%r1), %r1 | ||
319 | LDREG TASK_PT_GR20(%r1), %r20 | ||
320 | LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */ | ||
321 | LDREG TASK_PT_GR25(%r1), %r25 | ||
322 | LDREG TASK_PT_GR24(%r1), %r24 | ||
323 | LDREG TASK_PT_GR23(%r1), %r23 | ||
324 | #ifdef __LP64__ | ||
325 | LDREG TASK_PT_GR22(%r1), %r22 | ||
326 | LDREG TASK_PT_GR21(%r1), %r21 | ||
327 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
328 | #endif | ||
329 | |||
330 | comiclr,>>= __NR_Linux_syscalls, %r20, %r0 | ||
331 | b,n .Lsyscall_nosys | ||
332 | |||
333 | LDREGX %r20(%r19), %r19 | ||
334 | |||
335 | /* If this is a sys_rt_sigreturn call, and the signal was received | ||
336 | * when not in_syscall, then we want to return via syscall_exit_rfi, | ||
337 | * not syscall_exit. Signal no. in r20, in_syscall in r25 (see | ||
338 | * trampoline code in signal.c). | ||
339 | */ | ||
340 | ldi __NR_rt_sigreturn,%r2 | ||
341 | comb,= %r2,%r20,.Ltrace_rt_sigreturn | ||
342 | .Ltrace_in_syscall: | ||
343 | ldil L%tracesys_exit,%r2 | ||
344 | be 0(%sr7,%r19) | ||
345 | ldo R%tracesys_exit(%r2),%r2 | ||
346 | |||
347 | /* Do *not* call this function on the gateway page, because it | ||
348 | makes a direct call to syscall_trace. */ | ||
349 | |||
350 | tracesys_exit: | ||
351 | ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ | ||
352 | LDREG TI_TASK(%r1), %r1 | ||
353 | #ifdef __LP64__ | ||
354 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
355 | #endif | ||
356 | bl syscall_trace, %r2 | ||
357 | STREG %r28,TASK_PT_GR28(%r1) /* save return value now */ | ||
358 | ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ | ||
359 | LDREG TI_TASK(%r1), %r1 | ||
360 | LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */ | ||
361 | |||
362 | ldil L%syscall_exit,%r1 | ||
363 | be,n R%syscall_exit(%sr7,%r1) | ||
364 | |||
365 | .Ltrace_rt_sigreturn: | ||
366 | comib,<> 0,%r25,.Ltrace_in_syscall | ||
367 | ldil L%tracesys_sigexit,%r2 | ||
368 | be 0(%sr7,%r19) | ||
369 | ldo R%tracesys_sigexit(%r2),%r2 | ||
370 | |||
371 | tracesys_sigexit: | ||
372 | ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ | ||
373 | LDREG 0(%r1), %r1 | ||
374 | #ifdef __LP64__ | ||
375 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
376 | #endif | ||
377 | bl syscall_trace, %r2 | ||
378 | nop | ||
379 | |||
380 | ldil L%syscall_exit_rfi,%r1 | ||
381 | be,n R%syscall_exit_rfi(%sr7,%r1) | ||
382 | |||
383 | |||
384 | /********************************************************* | ||
385 | Light-weight-syscall code | ||
386 | |||
387 | r20 - lws number | ||
388 | r26,r25,r24,r23,r22 - Input registers | ||
389 | r28 - Function return register | ||
390 | r21 - Error code. | ||
391 | |||
392 | Scracth: Any of the above that aren't being | ||
393 | currently used, including r1. | ||
394 | |||
395 | Return pointer: r31 (Not usable) | ||
396 | |||
397 | Error codes returned by entry path: | ||
398 | |||
399 | ENOSYS - r20 was an invalid LWS number. | ||
400 | |||
401 | *********************************************************/ | ||
402 | lws_start: | ||
403 | /* Gate and ensure we return to userspace */ | ||
404 | gate .+8, %r0 | ||
405 | depi 3, 31, 2, %r31 /* Ensure we return to userspace */ | ||
406 | |||
407 | #ifdef __LP64__ | ||
408 | /* FIXME: If we are a 64-bit kernel just | ||
409 | * turn this on unconditionally. | ||
410 | */ | ||
411 | ssm PSW_SM_W, %r1 | ||
412 | extrd,u %r1,PSW_W_BIT,1,%r1 | ||
413 | /* sp must be aligned on 4, so deposit the W bit setting into | ||
414 | * the bottom of sp temporarily */ | ||
415 | or,ev %r1,%r30,%r30 | ||
416 | |||
417 | /* Clip LWS number to a 32-bit value always */ | ||
418 | depdi 0, 31, 32, %r20 | ||
419 | #endif | ||
420 | |||
421 | /* Is the lws entry number valid? */ | ||
422 | comiclr,>>= __NR_lws_entries, %r20, %r0 | ||
423 | b,n lws_exit_nosys | ||
424 | |||
425 | /* WARNING: Trashing sr2 and sr3 */ | ||
426 | mfsp %sr7,%r1 /* get userspace into sr3 */ | ||
427 | mtsp %r1,%sr3 | ||
428 | mtsp %r0,%sr2 /* get kernel space into sr2 */ | ||
429 | |||
430 | /* Load table start */ | ||
431 | ldil L%lws_table, %r1 | ||
432 | ldo R%lws_table(%r1), %r28 /* Scratch use of r28 */ | ||
433 | LDREGX %r20(%sr2,r28), %r21 /* Scratch use of r21 */ | ||
434 | |||
435 | /* Jump to lws, lws table pointers already relocated */ | ||
436 | be,n 0(%sr2,%r21) | ||
437 | |||
438 | lws_exit_nosys: | ||
439 | ldo -ENOSYS(%r0),%r21 /* set errno */ | ||
440 | /* Fall through: Return to userspace */ | ||
441 | |||
442 | lws_exit: | ||
443 | #ifdef __LP64__ | ||
444 | /* decide whether to reset the wide mode bit | ||
445 | * | ||
446 | * For a syscall, the W bit is stored in the lowest bit | ||
447 | * of sp. Extract it and reset W if it is zero */ | ||
448 | extrd,u,*<> %r30,63,1,%r1 | ||
449 | rsm PSW_SM_W, %r0 | ||
450 | /* now reset the lowest bit of sp if it was set */ | ||
451 | xor %r30,%r1,%r30 | ||
452 | #endif | ||
453 | be,n 0(%sr3, %r31) | ||
454 | |||
455 | |||
456 | |||
457 | /*************************************************** | ||
458 | Implementing CAS as an atomic operation: | ||
459 | |||
460 | %r26 - Address to examine | ||
461 | %r25 - Old value to check (old) | ||
462 | %r24 - New value to set (new) | ||
463 | %r28 - Return prev through this register. | ||
464 | %r21 - Kernel error code | ||
465 | |||
466 | If debugging is DISabled: | ||
467 | |||
468 | %r21 has the following meanings: | ||
469 | |||
470 | EAGAIN - CAS is busy, ldcw failed, try again. | ||
471 | EFAULT - Read or write failed. | ||
472 | |||
473 | If debugging is enabled: | ||
474 | |||
475 | EDEADLOCK - CAS called recursively. | ||
476 | EAGAIN && r28 == 1 - CAS is busy. Lock contended. | ||
477 | EAGAIN && r28 == 2 - CAS is busy. ldcw failed. | ||
478 | EFAULT - Read or write failed. | ||
479 | |||
480 | Scratch: r20, r28, r1 | ||
481 | |||
482 | ****************************************************/ | ||
483 | |||
484 | /* Do not enable LWS debugging */ | ||
485 | #define ENABLE_LWS_DEBUG 0 | ||
486 | |||
487 | /* ELF64 Process entry path */ | ||
488 | lws_compare_and_swap64: | ||
489 | #ifdef __LP64__ | ||
490 | b,n lws_compare_and_swap | ||
491 | #else | ||
492 | /* If we are not a 64-bit kernel, then we don't | ||
493 | * implement having 64-bit input registers | ||
494 | */ | ||
495 | b,n lws_exit_nosys | ||
496 | #endif | ||
497 | |||
498 | /* ELF32 Process entry path */ | ||
499 | lws_compare_and_swap32: | ||
500 | #ifdef __LP64__ | ||
501 | /* Clip all the input registers */ | ||
502 | depdi 0, 31, 32, %r26 | ||
503 | depdi 0, 31, 32, %r25 | ||
504 | depdi 0, 31, 32, %r24 | ||
505 | #endif | ||
506 | |||
507 | lws_compare_and_swap: | ||
508 | #ifdef CONFIG_SMP | ||
509 | /* Load start of lock table */ | ||
510 | ldil L%lws_lock_start, %r20 | ||
511 | ldo R%lws_lock_start(%r20), %r28 | ||
512 | |||
513 | /* Extract four bits from r26 and hash lock (Bits 4-7) */ | ||
514 | extru %r26, 27, 4, %r20 | ||
515 | |||
516 | /* Find lock to use, the hash is either one of 0 to | ||
517 | 15, multiplied by 16 (keep it 16-byte aligned) | ||
518 | and add to the lock table offset. */ | ||
519 | shlw %r20, 4, %r20 | ||
520 | add %r20, %r28, %r20 | ||
521 | |||
522 | # ifdef ENABLE_LWS_DEBUG | ||
523 | /* | ||
524 | DEBUG, check for deadlock! | ||
525 | If the thread register values are the same | ||
526 | then we were the one that locked it last and | ||
527 | this is a recurisve call that will deadlock. | ||
528 | We *must* giveup this call and fail. | ||
529 | */ | ||
530 | ldw 4(%sr2,%r20), %r28 /* Load thread register */ | ||
531 | mfctl %cr27, %r21 /* Get current thread register */ | ||
532 | cmpb,<>,n %r21, %r28, cas_lock /* Called recursive? */ | ||
533 | b lws_exit /* Return error! */ | ||
534 | ldo -EDEADLOCK(%r0), %r21 | ||
535 | cas_lock: | ||
536 | cmpb,=,n %r0, %r28, cas_nocontend /* Is nobody using it? */ | ||
537 | ldo 1(%r0), %r28 /* 1st case */ | ||
538 | b lws_exit /* Contended... */ | ||
539 | ldo -EAGAIN(%r0), %r21 /* Spin in userspace */ | ||
540 | cas_nocontend: | ||
541 | # endif | ||
542 | /* ENABLE_LWS_DEBUG */ | ||
543 | |||
544 | ldcw 0(%sr2,%r20), %r28 /* Try to acquire the lock */ | ||
545 | cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */ | ||
546 | cas_wouldblock: | ||
547 | ldo 2(%r0), %r28 /* 2nd case */ | ||
548 | b lws_exit /* Contended... */ | ||
549 | ldo -EAGAIN(%r0), %r21 /* Spin in userspace */ | ||
550 | #endif | ||
551 | /* CONFIG_SMP */ | ||
552 | |||
553 | /* | ||
554 | prev = *addr; | ||
555 | if ( prev == old ) | ||
556 | *addr = new; | ||
557 | return prev; | ||
558 | */ | ||
559 | |||
560 | /* NOTES: | ||
561 | This all works becuse intr_do_signal | ||
562 | and schedule both check the return iasq | ||
563 | and see that we are on the kernel page | ||
564 | so this process is never scheduled off | ||
565 | or is ever sent any signal of any sort, | ||
566 | thus it is wholly atomic from usrspaces | ||
567 | perspective | ||
568 | */ | ||
569 | cas_action: | ||
570 | #if defined CONFIG_SMP && defined ENABLE_LWS_DEBUG | ||
571 | /* DEBUG */ | ||
572 | mfctl %cr27, %r1 | ||
573 | stw %r1, 4(%sr2,%r20) | ||
574 | #endif | ||
575 | /* The load and store could fail */ | ||
576 | 1: ldw 0(%sr3,%r26), %r28 | ||
577 | sub,<> %r28, %r25, %r0 | ||
578 | 2: stw %r24, 0(%sr3,%r26) | ||
579 | #ifdef CONFIG_SMP | ||
580 | /* Free lock */ | ||
581 | stw %r20, 0(%sr2,%r20) | ||
582 | # ifdef ENABLE_LWS_DEBUG | ||
583 | /* Clear thread register indicator */ | ||
584 | stw %r0, 4(%sr2,%r20) | ||
585 | # endif | ||
586 | #endif | ||
587 | /* Return to userspace, set no error */ | ||
588 | b lws_exit | ||
589 | copy %r0, %r21 | ||
590 | |||
591 | 3: | ||
592 | /* Error occured on load or store */ | ||
593 | #ifdef CONFIG_SMP | ||
594 | /* Free lock */ | ||
595 | stw %r20, 0(%sr2,%r20) | ||
596 | # ifdef ENABLE_LWS_DEBUG | ||
597 | stw %r0, 4(%sr2,%r20) | ||
598 | # endif | ||
599 | #endif | ||
600 | b lws_exit | ||
601 | ldo -EFAULT(%r0),%r21 /* set errno */ | ||
602 | nop | ||
603 | nop | ||
604 | nop | ||
605 | nop | ||
606 | |||
607 | /* Two exception table entries, one for the load, | ||
608 | the other for the store. Either return -EFAULT. | ||
609 | Each of the entries must be relocated. */ | ||
610 | .section __ex_table,"aw" | ||
611 | #ifdef __LP64__ | ||
612 | /* Pad the address calculation */ | ||
613 | .word 0,(2b - linux_gateway_page) | ||
614 | .word 0,(3b - linux_gateway_page) | ||
615 | #else | ||
616 | .word (2b - linux_gateway_page) | ||
617 | .word (3b - linux_gateway_page) | ||
618 | #endif | ||
619 | .previous | ||
620 | |||
621 | .section __ex_table,"aw" | ||
622 | #ifdef __LP64__ | ||
623 | /* Pad the address calculation */ | ||
624 | .word 0,(1b - linux_gateway_page) | ||
625 | .word 0,(3b - linux_gateway_page) | ||
626 | #else | ||
627 | .word (1b - linux_gateway_page) | ||
628 | .word (3b - linux_gateway_page) | ||
629 | #endif | ||
630 | .previous | ||
631 | |||
632 | end_compare_and_swap: | ||
633 | |||
634 | /* Make sure nothing else is placed on this page */ | ||
635 | .align 4096 | ||
636 | .export end_linux_gateway_page | ||
637 | end_linux_gateway_page: | ||
638 | |||
639 | /* Relocate symbols assuming linux_gateway_page is mapped | ||
640 | to virtual address 0x0 */ | ||
641 | #ifdef __LP64__ | ||
642 | /* FIXME: The code will always be on the gateay page | ||
643 | and thus it will be on the first 4k, the | ||
644 | assembler seems to think that the final | ||
645 | subtraction result is only a word in | ||
646 | length, so we pad the value. | ||
647 | */ | ||
648 | #define LWS_ENTRY(_name_) .word 0,(lws_##_name_ - linux_gateway_page) | ||
649 | #else | ||
650 | #define LWS_ENTRY(_name_) .word (lws_##_name_ - linux_gateway_page) | ||
651 | #endif | ||
652 | |||
653 | .align 4096 | ||
654 | /* Light-weight-syscall table */ | ||
655 | /* Start of lws table. */ | ||
656 | .export lws_table | ||
657 | .Llws_table: | ||
658 | lws_table: | ||
659 | LWS_ENTRY(compare_and_swap32) /* 0 - ELF32 Atomic compare and swap */ | ||
660 | LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic compare and swap */ | ||
661 | /* End of lws table */ | ||
662 | |||
663 | .align 4096 | ||
664 | .export sys_call_table | ||
665 | .Lsys_call_table: | ||
666 | sys_call_table: | ||
667 | #include "syscall_table.S" | ||
668 | |||
669 | #ifdef __LP64__ | ||
670 | .align 4096 | ||
671 | .export sys_call_table64 | ||
672 | .Lsys_call_table64: | ||
673 | sys_call_table64: | ||
674 | #define SYSCALL_TABLE_64BIT | ||
675 | #include "syscall_table.S" | ||
676 | #endif | ||
677 | |||
678 | #ifdef CONFIG_SMP | ||
679 | /* | ||
680 | All light-weight-syscall atomic operations | ||
681 | will use this set of locks | ||
682 | */ | ||
683 | .section .data | ||
684 | .align 4096 | ||
685 | .export lws_lock_start | ||
686 | .Llws_lock_start: | ||
687 | lws_lock_start: | ||
688 | /* lws locks */ | ||
689 | .align 16 | ||
690 | .rept 16 | ||
691 | /* Keep locks aligned at 16-bytes */ | ||
692 | .word 1 | ||
693 | .word 0 | ||
694 | .word 0 | ||
695 | .word 0 | ||
696 | .endr | ||
697 | .previous | ||
698 | #endif | ||
699 | /* CONFIG_SMP for lws_lock_start */ | ||
700 | |||
701 | .end | ||
702 | |||
703 | |||
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S new file mode 100644 index 000000000000..779b537100ec --- /dev/null +++ b/arch/parisc/kernel/syscall_table.S | |||
@@ -0,0 +1,372 @@ | |||
1 | /* System Call Table | ||
2 | * | ||
3 | * Copyright (C) 1999-2004 Matthew Wilcox <willy at parisc-linux.org> | ||
4 | * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org> | ||
5 | * Copyright (C) 2000 Alan Modra <amodra at parisc-linux.org> | ||
6 | * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org> | ||
7 | * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org> | ||
8 | * Copyright (C) 2000 Michael Ang <mang with subcarrier.org> | ||
9 | * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org> | ||
10 | * Copyright (C) 2000 Grant Grundler <grundler at parisc-linux.org> | ||
11 | * Copyright (C) 2001 Richard Hirst <rhirst with parisc-linux.org> | ||
12 | * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org> | ||
13 | * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org> | ||
14 | * Copyright (C) 2000-2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org> | ||
15 | * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> | ||
16 | * | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or modify | ||
19 | * it under the terms of the GNU General Public License as published by | ||
20 | * the Free Software Foundation; either version 2 of the License, or | ||
21 | * (at your option) any later version. | ||
22 | * | ||
23 | * This program is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with this program; if not, write to the Free Software | ||
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
31 | */ | ||
32 | |||
33 | #undef ENTRY_SAME | ||
34 | #undef ENTRY_DIFF | ||
35 | #undef ENTRY_UHOH | ||
36 | #undef ENTRY_COMP | ||
37 | #undef ENTRY_OURS | ||
38 | #if defined(__LP64__) && !defined(SYSCALL_TABLE_64BIT) | ||
39 | /* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and | ||
40 | * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific | ||
41 | * implementation is required on wide palinux. Use ENTRY_COMP where | ||
42 | * the compatability layer has a useful 32-bit implementation. | ||
43 | */ | ||
44 | #define ENTRY_SAME(_name_) .dword sys_##_name_ | ||
45 | #define ENTRY_DIFF(_name_) .dword sys32_##_name_ | ||
46 | #define ENTRY_UHOH(_name_) .dword sys32_##unimplemented | ||
47 | #define ENTRY_OURS(_name_) .dword parisc_##_name_ | ||
48 | #define ENTRY_COMP(_name_) .dword compat_sys_##_name_ | ||
49 | #elif defined(__LP64__) && defined(SYSCALL_TABLE_64BIT) | ||
50 | #define ENTRY_SAME(_name_) .dword sys_##_name_ | ||
51 | #define ENTRY_DIFF(_name_) .dword sys_##_name_ | ||
52 | #define ENTRY_UHOH(_name_) .dword sys_##_name_ | ||
53 | #define ENTRY_OURS(_name_) .dword sys_##_name_ | ||
54 | #define ENTRY_COMP(_name_) .dword sys_##_name_ | ||
55 | #else | ||
56 | #define ENTRY_SAME(_name_) .word sys_##_name_ | ||
57 | #define ENTRY_DIFF(_name_) .word sys_##_name_ | ||
58 | #define ENTRY_UHOH(_name_) .word sys_##_name_ | ||
59 | #define ENTRY_OURS(_name_) .word parisc_##_name_ | ||
60 | #define ENTRY_COMP(_name_) .word sys_##_name_ | ||
61 | #endif | ||
62 | |||
63 | ENTRY_SAME(restart_syscall) /* 0 */ | ||
64 | ENTRY_SAME(exit) | ||
65 | ENTRY_SAME(fork_wrapper) | ||
66 | ENTRY_SAME(read) | ||
67 | ENTRY_SAME(write) | ||
68 | ENTRY_SAME(open) /* 5 */ | ||
69 | ENTRY_SAME(close) | ||
70 | ENTRY_SAME(waitpid) | ||
71 | ENTRY_SAME(creat) | ||
72 | ENTRY_SAME(link) | ||
73 | ENTRY_SAME(unlink) /* 10 */ | ||
74 | ENTRY_DIFF(execve_wrapper) | ||
75 | ENTRY_SAME(chdir) | ||
76 | /* See comments in kernel/time.c!!! Maybe we don't need this? */ | ||
77 | ENTRY_COMP(time) | ||
78 | ENTRY_SAME(mknod) | ||
79 | ENTRY_SAME(chmod) /* 15 */ | ||
80 | ENTRY_SAME(lchown) | ||
81 | ENTRY_SAME(socket) | ||
82 | /* struct stat is MAYBE identical wide and narrow ?? */ | ||
83 | ENTRY_COMP(newstat) | ||
84 | ENTRY_DIFF(lseek) | ||
85 | ENTRY_SAME(getpid) /* 20 */ | ||
86 | /* the 'void * data' parameter may need re-packing in wide */ | ||
87 | ENTRY_COMP(mount) | ||
88 | /* concerned about struct sockaddr in wide/narrow */ | ||
89 | /* ---> I think sockaddr is OK unless the compiler packs the struct */ | ||
90 | /* differently to align the char array */ | ||
91 | ENTRY_SAME(bind) | ||
92 | ENTRY_SAME(setuid) | ||
93 | ENTRY_SAME(getuid) | ||
94 | ENTRY_COMP(stime) /* 25 */ | ||
95 | ENTRY_SAME(ptrace) | ||
96 | ENTRY_SAME(alarm) | ||
97 | /* see stat comment */ | ||
98 | ENTRY_COMP(newfstat) | ||
99 | ENTRY_SAME(pause) | ||
100 | /* struct utimbuf uses time_t which might vary */ | ||
101 | ENTRY_COMP(utime) /* 30 */ | ||
102 | /* struct sockaddr... */ | ||
103 | ENTRY_SAME(connect) | ||
104 | ENTRY_SAME(listen) | ||
105 | ENTRY_SAME(access) | ||
106 | ENTRY_SAME(nice) | ||
107 | /* struct sockaddr... */ | ||
108 | ENTRY_SAME(accept) /* 35 */ | ||
109 | ENTRY_SAME(sync) | ||
110 | ENTRY_SAME(kill) | ||
111 | ENTRY_SAME(rename) | ||
112 | ENTRY_SAME(mkdir) | ||
113 | ENTRY_SAME(rmdir) /* 40 */ | ||
114 | ENTRY_SAME(dup) | ||
115 | ENTRY_SAME(pipe) | ||
116 | ENTRY_COMP(times) | ||
117 | /* struct sockaddr... */ | ||
118 | ENTRY_SAME(getsockname) | ||
119 | /* it seems possible brk() could return a >4G pointer... */ | ||
120 | ENTRY_SAME(brk) /* 45 */ | ||
121 | ENTRY_SAME(setgid) | ||
122 | ENTRY_SAME(getgid) | ||
123 | ENTRY_SAME(signal) | ||
124 | ENTRY_SAME(geteuid) | ||
125 | ENTRY_SAME(getegid) /* 50 */ | ||
126 | ENTRY_SAME(acct) | ||
127 | ENTRY_SAME(umount) | ||
128 | /* struct sockaddr... */ | ||
129 | ENTRY_SAME(getpeername) | ||
130 | ENTRY_COMP(ioctl) | ||
131 | ENTRY_COMP(fcntl) /* 55 */ | ||
132 | ENTRY_SAME(socketpair) | ||
133 | ENTRY_SAME(setpgid) | ||
134 | ENTRY_SAME(send) | ||
135 | ENTRY_SAME(newuname) | ||
136 | ENTRY_SAME(umask) /* 60 */ | ||
137 | ENTRY_SAME(chroot) | ||
138 | ENTRY_SAME(ustat) | ||
139 | ENTRY_SAME(dup2) | ||
140 | ENTRY_SAME(getppid) | ||
141 | ENTRY_SAME(getpgrp) /* 65 */ | ||
142 | ENTRY_SAME(setsid) | ||
143 | ENTRY_SAME(pivot_root) | ||
144 | /* I don't like this */ | ||
145 | ENTRY_UHOH(sgetmask) | ||
146 | ENTRY_UHOH(ssetmask) | ||
147 | ENTRY_SAME(setreuid) /* 70 */ | ||
148 | ENTRY_SAME(setregid) | ||
149 | ENTRY_SAME(mincore) | ||
150 | ENTRY_COMP(sigpending) | ||
151 | ENTRY_SAME(sethostname) | ||
152 | /* Following 3 have linux-common-code structs containing longs -( */ | ||
153 | ENTRY_COMP(setrlimit) /* 75 */ | ||
154 | ENTRY_COMP(getrlimit) | ||
155 | ENTRY_COMP(getrusage) | ||
156 | /* struct timeval and timezone are maybe?? consistent wide and narrow */ | ||
157 | ENTRY_DIFF(gettimeofday) | ||
158 | ENTRY_DIFF(settimeofday) | ||
159 | ENTRY_SAME(getgroups) /* 80 */ | ||
160 | ENTRY_SAME(setgroups) | ||
161 | /* struct socketaddr... */ | ||
162 | ENTRY_SAME(sendto) | ||
163 | ENTRY_SAME(symlink) | ||
164 | /* see stat comment */ | ||
165 | ENTRY_COMP(newlstat) | ||
166 | ENTRY_SAME(readlink) /* 85 */ | ||
167 | ENTRY_SAME(ni_syscall) /* was uselib */ | ||
168 | ENTRY_SAME(swapon) | ||
169 | ENTRY_SAME(reboot) | ||
170 | ENTRY_SAME(mmap2) | ||
171 | ENTRY_SAME(mmap) /* 90 */ | ||
172 | ENTRY_SAME(munmap) | ||
173 | ENTRY_SAME(truncate) | ||
174 | ENTRY_SAME(ftruncate) | ||
175 | ENTRY_SAME(fchmod) | ||
176 | ENTRY_SAME(fchown) /* 95 */ | ||
177 | ENTRY_SAME(getpriority) | ||
178 | ENTRY_SAME(setpriority) | ||
179 | ENTRY_SAME(recv) | ||
180 | ENTRY_COMP(statfs) | ||
181 | ENTRY_COMP(fstatfs) /* 100 */ | ||
182 | ENTRY_SAME(stat64) | ||
183 | ENTRY_SAME(ni_syscall) /* was socketcall */ | ||
184 | ENTRY_SAME(syslog) | ||
185 | /* even though manpage says struct timeval contains longs, ours has | ||
186 | * time_t and suseconds_t -- both of which are safe wide/narrow */ | ||
187 | ENTRY_COMP(setitimer) | ||
188 | ENTRY_COMP(getitimer) /* 105 */ | ||
189 | ENTRY_SAME(capget) | ||
190 | ENTRY_SAME(capset) | ||
191 | ENTRY_OURS(pread64) | ||
192 | ENTRY_OURS(pwrite64) | ||
193 | ENTRY_SAME(getcwd) /* 110 */ | ||
194 | ENTRY_SAME(vhangup) | ||
195 | ENTRY_SAME(fstat64) | ||
196 | ENTRY_SAME(vfork_wrapper) | ||
197 | /* struct rusage contains longs... */ | ||
198 | ENTRY_COMP(wait4) | ||
199 | ENTRY_SAME(swapoff) /* 115 */ | ||
200 | ENTRY_DIFF(sysinfo) | ||
201 | ENTRY_SAME(shutdown) | ||
202 | ENTRY_SAME(fsync) | ||
203 | ENTRY_SAME(madvise) | ||
204 | ENTRY_SAME(clone_wrapper) /* 120 */ | ||
205 | ENTRY_SAME(setdomainname) | ||
206 | ENTRY_DIFF(sendfile) | ||
207 | /* struct sockaddr... */ | ||
208 | ENTRY_SAME(recvfrom) | ||
209 | /* struct timex contains longs */ | ||
210 | ENTRY_DIFF(adjtimex) | ||
211 | ENTRY_SAME(mprotect) /* 125 */ | ||
212 | /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */ | ||
213 | ENTRY_COMP(sigprocmask) | ||
214 | ENTRY_SAME(ni_syscall) /* create_module */ | ||
215 | ENTRY_SAME(init_module) | ||
216 | ENTRY_SAME(delete_module) | ||
217 | ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */ | ||
218 | /* time_t inside struct dqblk */ | ||
219 | ENTRY_SAME(quotactl) | ||
220 | ENTRY_SAME(getpgid) | ||
221 | ENTRY_SAME(fchdir) | ||
222 | ENTRY_SAME(bdflush) | ||
223 | ENTRY_SAME(sysfs) /* 135 */ | ||
224 | ENTRY_SAME(personality) | ||
225 | ENTRY_SAME(ni_syscall) /* for afs_syscall */ | ||
226 | ENTRY_SAME(setfsuid) | ||
227 | ENTRY_SAME(setfsgid) | ||
228 | /* I think this might work */ | ||
229 | ENTRY_SAME(llseek) /* 140 */ | ||
230 | /* struct linux_dirent has longs, like 'unsigned long d_ino' which | ||
231 | * almost definitely should be 'ino_t d_ino' but it's too late now */ | ||
232 | ENTRY_DIFF(getdents) | ||
233 | /* it is POSSIBLE that select will be OK because even though fd_set | ||
234 | * contains longs, the macros and sizes are clever. */ | ||
235 | ENTRY_COMP(select) | ||
236 | ENTRY_SAME(flock) | ||
237 | ENTRY_SAME(msync) | ||
238 | /* struct iovec contains pointers */ | ||
239 | ENTRY_COMP(readv) /* 145 */ | ||
240 | ENTRY_COMP(writev) | ||
241 | ENTRY_SAME(getsid) | ||
242 | ENTRY_SAME(fdatasync) | ||
243 | /* struct __sysctl_args is a mess */ | ||
244 | ENTRY_DIFF(sysctl) | ||
245 | ENTRY_SAME(mlock) /* 150 */ | ||
246 | ENTRY_SAME(munlock) | ||
247 | ENTRY_SAME(mlockall) | ||
248 | ENTRY_SAME(munlockall) | ||
249 | /* struct sched_param is ok for now */ | ||
250 | ENTRY_SAME(sched_setparam) | ||
251 | ENTRY_SAME(sched_getparam) /* 155 */ | ||
252 | ENTRY_SAME(sched_setscheduler) | ||
253 | ENTRY_SAME(sched_getscheduler) | ||
254 | ENTRY_SAME(sched_yield) | ||
255 | ENTRY_SAME(sched_get_priority_max) | ||
256 | ENTRY_SAME(sched_get_priority_min) /* 160 */ | ||
257 | /* These 2 would've worked if someone had defined struct timespec | ||
258 | * carefully, like timeval for example (which is about the same). | ||
259 | * Unfortunately it contains a long :-( */ | ||
260 | ENTRY_DIFF(sched_rr_get_interval) | ||
261 | ENTRY_COMP(nanosleep) | ||
262 | ENTRY_SAME(mremap) | ||
263 | ENTRY_SAME(setresuid) | ||
264 | ENTRY_SAME(getresuid) /* 165 */ | ||
265 | ENTRY_DIFF(sigaltstack_wrapper) | ||
266 | ENTRY_SAME(ni_syscall) /* query_module */ | ||
267 | ENTRY_SAME(poll) | ||
268 | /* structs contain pointers and an in_addr... */ | ||
269 | ENTRY_COMP(nfsservctl) | ||
270 | ENTRY_SAME(setresgid) /* 170 */ | ||
271 | ENTRY_SAME(getresgid) | ||
272 | ENTRY_SAME(prctl) | ||
273 | /* signals need a careful review */ | ||
274 | ENTRY_SAME(rt_sigreturn_wrapper) | ||
275 | ENTRY_DIFF(rt_sigaction) | ||
276 | ENTRY_DIFF(rt_sigprocmask) /* 175 */ | ||
277 | ENTRY_DIFF(rt_sigpending) | ||
278 | ENTRY_COMP(rt_sigtimedwait) | ||
279 | /* even though the struct siginfo_t is different, it appears like | ||
280 | * all the paths use values which should be same wide and narrow. | ||
281 | * Also the struct is padded to 128 bytes which means we don't have | ||
282 | * to worry about faulting trying to copy in a larger 64-bit | ||
283 | * struct from a 32-bit user-space app. | ||
284 | */ | ||
285 | ENTRY_SAME(rt_sigqueueinfo) | ||
286 | ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */ | ||
287 | ENTRY_SAME(chown) /* 180 */ | ||
288 | /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */ | ||
289 | ENTRY_COMP(setsockopt) | ||
290 | ENTRY_SAME(getsockopt) | ||
291 | ENTRY_COMP(sendmsg) | ||
292 | ENTRY_COMP(recvmsg) | ||
293 | ENTRY_SAME(semop) /* 185 */ | ||
294 | ENTRY_SAME(semget) | ||
295 | ENTRY_DIFF(semctl) | ||
296 | ENTRY_DIFF(msgsnd) | ||
297 | ENTRY_DIFF(msgrcv) | ||
298 | ENTRY_SAME(msgget) /* 190 */ | ||
299 | ENTRY_SAME(msgctl) | ||
300 | ENTRY_SAME(shmat_wrapper) | ||
301 | ENTRY_SAME(shmdt) | ||
302 | ENTRY_SAME(shmget) | ||
303 | ENTRY_SAME(shmctl) /* 195 */ | ||
304 | ENTRY_SAME(ni_syscall) /* streams1 */ | ||
305 | ENTRY_SAME(ni_syscall) /* streams2 */ | ||
306 | ENTRY_SAME(lstat64) | ||
307 | ENTRY_OURS(truncate64) | ||
308 | ENTRY_OURS(ftruncate64) /* 200 */ | ||
309 | ENTRY_SAME(getdents64) | ||
310 | ENTRY_COMP(fcntl64) | ||
311 | ENTRY_SAME(ni_syscall) /* attrctl -- dead */ | ||
312 | ENTRY_SAME(ni_syscall) /* acl_get -- dead */ | ||
313 | ENTRY_SAME(ni_syscall) /* 205 (acl_set -- dead) */ | ||
314 | ENTRY_SAME(gettid) | ||
315 | ENTRY_OURS(readahead) | ||
316 | ENTRY_SAME(tkill) | ||
317 | ENTRY_SAME(sendfile64) | ||
318 | ENTRY_COMP(futex) /* 210 */ | ||
319 | ENTRY_COMP(sched_setaffinity) | ||
320 | ENTRY_COMP(sched_getaffinity) | ||
321 | ENTRY_SAME(ni_syscall) /* set_thread_area */ | ||
322 | ENTRY_SAME(ni_syscall) /* get_thread_area */ | ||
323 | ENTRY_SAME(io_setup) /* 215 */ | ||
324 | ENTRY_SAME(io_destroy) | ||
325 | ENTRY_SAME(io_getevents) | ||
326 | ENTRY_SAME(io_submit) | ||
327 | ENTRY_SAME(io_cancel) | ||
328 | ENTRY_SAME(alloc_hugepages) /* 220 */ | ||
329 | ENTRY_SAME(free_hugepages) | ||
330 | ENTRY_SAME(exit_group) | ||
331 | ENTRY_DIFF(lookup_dcookie) | ||
332 | ENTRY_SAME(epoll_create) | ||
333 | ENTRY_SAME(epoll_ctl) /* 225 */ | ||
334 | ENTRY_SAME(epoll_wait) | ||
335 | ENTRY_SAME(remap_file_pages) | ||
336 | ENTRY_SAME(semtimedop) | ||
337 | ENTRY_SAME(mq_open) | ||
338 | ENTRY_SAME(mq_unlink) /* 230 */ | ||
339 | ENTRY_SAME(mq_timedsend) | ||
340 | ENTRY_SAME(mq_timedreceive) | ||
341 | ENTRY_SAME(mq_notify) | ||
342 | ENTRY_SAME(mq_getsetattr) | ||
343 | ENTRY_COMP(waitid) /* 235 */ | ||
344 | ENTRY_OURS(fadvise64_64) | ||
345 | ENTRY_SAME(set_tid_address) | ||
346 | ENTRY_SAME(setxattr) | ||
347 | ENTRY_SAME(lsetxattr) | ||
348 | ENTRY_SAME(fsetxattr) /* 240 */ | ||
349 | ENTRY_SAME(getxattr) | ||
350 | ENTRY_SAME(lgetxattr) | ||
351 | ENTRY_SAME(fgetxattr) | ||
352 | ENTRY_SAME(listxattr) | ||
353 | ENTRY_SAME(llistxattr) /* 245 */ | ||
354 | ENTRY_SAME(flistxattr) | ||
355 | ENTRY_SAME(removexattr) | ||
356 | ENTRY_SAME(lremovexattr) | ||
357 | ENTRY_SAME(fremovexattr) | ||
358 | ENTRY_COMP(timer_create) /* 250 */ | ||
359 | ENTRY_COMP(timer_settime) | ||
360 | ENTRY_COMP(timer_gettime) | ||
361 | ENTRY_SAME(timer_getoverrun) | ||
362 | ENTRY_SAME(timer_delete) | ||
363 | ENTRY_COMP(clock_settime) /* 255 */ | ||
364 | ENTRY_COMP(clock_gettime) | ||
365 | ENTRY_COMP(clock_getres) | ||
366 | ENTRY_COMP(clock_nanosleep) | ||
367 | ENTRY_SAME(tgkill) | ||
368 | ENTRY_COMP(mbind) /* 260 */ | ||
369 | ENTRY_COMP(get_mempolicy) | ||
370 | ENTRY_COMP(set_mempolicy) | ||
371 | /* Nothing yet */ | ||
372 | |||
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c new file mode 100644 index 000000000000..6cf7407344ba --- /dev/null +++ b/arch/parisc/kernel/time.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * linux/arch/parisc/kernel/time.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
5 | * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King | ||
6 | * Copyright (C) 1999 SuSE GmbH, (Philipp Rumpf, prumpf@tux.org) | ||
7 | * | ||
8 | * 1994-07-02 Alan Modra | ||
9 | * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime | ||
10 | * 1998-12-20 Updated NTP code according to technical memorandum Jan '96 | ||
11 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | ||
12 | */ | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/param.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/time.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/smp.h> | ||
25 | #include <linux/profile.h> | ||
26 | |||
27 | #include <asm/uaccess.h> | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/irq.h> | ||
30 | #include <asm/param.h> | ||
31 | #include <asm/pdc.h> | ||
32 | #include <asm/led.h> | ||
33 | |||
34 | #include <linux/timex.h> | ||
35 | |||
36 | u64 jiffies_64 = INITIAL_JIFFIES; | ||
37 | |||
38 | EXPORT_SYMBOL(jiffies_64); | ||
39 | |||
40 | /* xtime and wall_jiffies keep wall-clock time */ | ||
41 | extern unsigned long wall_jiffies; | ||
42 | |||
43 | static long clocktick; /* timer cycles per tick */ | ||
44 | static long halftick; | ||
45 | |||
46 | #ifdef CONFIG_SMP | ||
47 | extern void smp_do_timer(struct pt_regs *regs); | ||
48 | #endif | ||
49 | |||
50 | irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
51 | { | ||
52 | long now; | ||
53 | long next_tick; | ||
54 | int nticks; | ||
55 | int cpu = smp_processor_id(); | ||
56 | |||
57 | profile_tick(CPU_PROFILING, regs); | ||
58 | |||
59 | now = mfctl(16); | ||
60 | /* initialize next_tick to time at last clocktick */ | ||
61 | next_tick = cpu_data[cpu].it_value; | ||
62 | |||
63 | /* since time passes between the interrupt and the mfctl() | ||
64 | * above, it is never true that last_tick + clocktick == now. If we | ||
65 | * never miss a clocktick, we could set next_tick = last_tick + clocktick | ||
66 | * but maybe we'll miss ticks, hence the loop. | ||
67 | * | ||
68 | * Variables are *signed*. | ||
69 | */ | ||
70 | |||
71 | nticks = 0; | ||
72 | while((next_tick - now) < halftick) { | ||
73 | next_tick += clocktick; | ||
74 | nticks++; | ||
75 | } | ||
76 | mtctl(next_tick, 16); | ||
77 | cpu_data[cpu].it_value = next_tick; | ||
78 | |||
79 | while (nticks--) { | ||
80 | #ifdef CONFIG_SMP | ||
81 | smp_do_timer(regs); | ||
82 | #else | ||
83 | update_process_times(user_mode(regs)); | ||
84 | #endif | ||
85 | if (cpu == 0) { | ||
86 | write_seqlock(&xtime_lock); | ||
87 | do_timer(regs); | ||
88 | write_sequnlock(&xtime_lock); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #ifdef CONFIG_CHASSIS_LCD_LED | ||
93 | /* Only schedule the led tasklet on cpu 0, and only if it | ||
94 | * is enabled. | ||
95 | */ | ||
96 | if (cpu == 0 && !atomic_read(&led_tasklet.count)) | ||
97 | tasklet_schedule(&led_tasklet); | ||
98 | #endif | ||
99 | |||
100 | /* check soft power switch status */ | ||
101 | if (cpu == 0 && !atomic_read(&power_tasklet.count)) | ||
102 | tasklet_schedule(&power_tasklet); | ||
103 | |||
104 | return IRQ_HANDLED; | ||
105 | } | ||
106 | |||
107 | /*** converted from ia64 ***/ | ||
108 | /* | ||
109 | * Return the number of micro-seconds that elapsed since the last | ||
110 | * update to wall time (aka xtime aka wall_jiffies). The xtime_lock | ||
111 | * must be at least read-locked when calling this routine. | ||
112 | */ | ||
113 | static inline unsigned long | ||
114 | gettimeoffset (void) | ||
115 | { | ||
116 | #ifndef CONFIG_SMP | ||
117 | /* | ||
118 | * FIXME: This won't work on smp because jiffies are updated by cpu 0. | ||
119 | * Once parisc-linux learns the cr16 difference between processors, | ||
120 | * this could be made to work. | ||
121 | */ | ||
122 | long last_tick; | ||
123 | long elapsed_cycles; | ||
124 | |||
125 | /* it_value is the intended time of the next tick */ | ||
126 | last_tick = cpu_data[smp_processor_id()].it_value; | ||
127 | |||
128 | /* Subtract one tick and account for possible difference between | ||
129 | * when we expected the tick and when it actually arrived. | ||
130 | * (aka wall vs real) | ||
131 | */ | ||
132 | last_tick -= clocktick * (jiffies - wall_jiffies + 1); | ||
133 | elapsed_cycles = mfctl(16) - last_tick; | ||
134 | |||
135 | /* the precision of this math could be improved */ | ||
136 | return elapsed_cycles / (PAGE0->mem_10msec / 10000); | ||
137 | #else | ||
138 | return 0; | ||
139 | #endif | ||
140 | } | ||
141 | |||
142 | void | ||
143 | do_gettimeofday (struct timeval *tv) | ||
144 | { | ||
145 | unsigned long flags, seq, usec, sec; | ||
146 | |||
147 | do { | ||
148 | seq = read_seqbegin_irqsave(&xtime_lock, flags); | ||
149 | usec = gettimeoffset(); | ||
150 | sec = xtime.tv_sec; | ||
151 | usec += (xtime.tv_nsec / 1000); | ||
152 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
153 | |||
154 | while (usec >= 1000000) { | ||
155 | usec -= 1000000; | ||
156 | ++sec; | ||
157 | } | ||
158 | |||
159 | tv->tv_sec = sec; | ||
160 | tv->tv_usec = usec; | ||
161 | } | ||
162 | |||
163 | EXPORT_SYMBOL(do_gettimeofday); | ||
164 | |||
165 | int | ||
166 | do_settimeofday (struct timespec *tv) | ||
167 | { | ||
168 | time_t wtm_sec, sec = tv->tv_sec; | ||
169 | long wtm_nsec, nsec = tv->tv_nsec; | ||
170 | |||
171 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | ||
172 | return -EINVAL; | ||
173 | |||
174 | write_seqlock_irq(&xtime_lock); | ||
175 | { | ||
176 | /* | ||
177 | * This is revolting. We need to set "xtime" | ||
178 | * correctly. However, the value in this location is | ||
179 | * the value at the most recent update of wall time. | ||
180 | * Discover what correction gettimeofday would have | ||
181 | * done, and then undo it! | ||
182 | */ | ||
183 | nsec -= gettimeoffset() * 1000; | ||
184 | |||
185 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); | ||
186 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); | ||
187 | |||
188 | set_normalized_timespec(&xtime, sec, nsec); | ||
189 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); | ||
190 | |||
191 | time_adjust = 0; /* stop active adjtime() */ | ||
192 | time_status |= STA_UNSYNC; | ||
193 | time_maxerror = NTP_PHASE_LIMIT; | ||
194 | time_esterror = NTP_PHASE_LIMIT; | ||
195 | } | ||
196 | write_sequnlock_irq(&xtime_lock); | ||
197 | clock_was_set(); | ||
198 | return 0; | ||
199 | } | ||
200 | EXPORT_SYMBOL(do_settimeofday); | ||
201 | |||
202 | /* | ||
203 | * XXX: We can do better than this. | ||
204 | * Returns nanoseconds | ||
205 | */ | ||
206 | |||
207 | unsigned long long sched_clock(void) | ||
208 | { | ||
209 | return (unsigned long long)jiffies * (1000000000 / HZ); | ||
210 | } | ||
211 | |||
212 | |||
213 | void __init time_init(void) | ||
214 | { | ||
215 | unsigned long next_tick; | ||
216 | static struct pdc_tod tod_data; | ||
217 | |||
218 | clocktick = (100 * PAGE0->mem_10msec) / HZ; | ||
219 | halftick = clocktick / 2; | ||
220 | |||
221 | /* Setup clock interrupt timing */ | ||
222 | |||
223 | next_tick = mfctl(16); | ||
224 | next_tick += clocktick; | ||
225 | cpu_data[smp_processor_id()].it_value = next_tick; | ||
226 | |||
227 | /* kick off Itimer (CR16) */ | ||
228 | mtctl(next_tick, 16); | ||
229 | |||
230 | if(pdc_tod_read(&tod_data) == 0) { | ||
231 | write_seqlock_irq(&xtime_lock); | ||
232 | xtime.tv_sec = tod_data.tod_sec; | ||
233 | xtime.tv_nsec = tod_data.tod_usec * 1000; | ||
234 | set_normalized_timespec(&wall_to_monotonic, | ||
235 | -xtime.tv_sec, -xtime.tv_nsec); | ||
236 | write_sequnlock_irq(&xtime_lock); | ||
237 | } else { | ||
238 | printk(KERN_ERR "Error reading tod clock\n"); | ||
239 | xtime.tv_sec = 0; | ||
240 | xtime.tv_nsec = 0; | ||
241 | } | ||
242 | } | ||
243 | |||
diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c new file mode 100644 index 000000000000..ac2a40681414 --- /dev/null +++ b/arch/parisc/kernel/topology.c | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * arch/parisc/kernel/topology.c - Populate driverfs with topology information | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
12 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
13 | * details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/cpu.h> | ||
23 | |||
24 | static struct cpu cpu_devices[NR_CPUS]; | ||
25 | |||
26 | static int __init topology_init(void) | ||
27 | { | ||
28 | struct node *parent = NULL; | ||
29 | int num; | ||
30 | |||
31 | for_each_present_cpu(num) { | ||
32 | register_cpu(&cpu_devices[num], num, parent); | ||
33 | } | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | subsys_initcall(topology_init); | ||
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c new file mode 100644 index 000000000000..d2e5b229a2f4 --- /dev/null +++ b/arch/parisc/kernel/traps.c | |||
@@ -0,0 +1,834 @@ | |||
1 | /* | ||
2 | * linux/arch/parisc/traps.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
5 | * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org> | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * 'Traps.c' handles hardware traps and faults after we have saved some | ||
10 | * state in 'asm.s'. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/ptrace.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/smp.h> | ||
23 | #include <linux/smp_lock.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/console.h> | ||
28 | #include <linux/kallsyms.h> | ||
29 | |||
30 | #include <asm/assembly.h> | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/uaccess.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/irq.h> | ||
35 | #include <asm/traps.h> | ||
36 | #include <asm/unaligned.h> | ||
37 | #include <asm/atomic.h> | ||
38 | #include <asm/smp.h> | ||
39 | #include <asm/pdc.h> | ||
40 | #include <asm/pdc_chassis.h> | ||
41 | #include <asm/unwind.h> | ||
42 | |||
43 | #include "../math-emu/math-emu.h" /* for handle_fpe() */ | ||
44 | |||
45 | #define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */ | ||
46 | /* dumped to the console via printk) */ | ||
47 | |||
48 | #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) | ||
49 | DEFINE_SPINLOCK(pa_dbit_lock); | ||
50 | #endif | ||
51 | |||
52 | int printbinary(char *buf, unsigned long x, int nbits) | ||
53 | { | ||
54 | unsigned long mask = 1UL << (nbits - 1); | ||
55 | while (mask != 0) { | ||
56 | *buf++ = (mask & x ? '1' : '0'); | ||
57 | mask >>= 1; | ||
58 | } | ||
59 | *buf = '\0'; | ||
60 | |||
61 | return nbits; | ||
62 | } | ||
63 | |||
64 | #ifdef __LP64__ | ||
65 | #define RFMT "%016lx" | ||
66 | #else | ||
67 | #define RFMT "%08lx" | ||
68 | #endif | ||
69 | |||
70 | void show_regs(struct pt_regs *regs) | ||
71 | { | ||
72 | int i; | ||
73 | char buf[128], *p; | ||
74 | char *level; | ||
75 | unsigned long cr30; | ||
76 | unsigned long cr31; | ||
77 | |||
78 | level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT; | ||
79 | |||
80 | printk("%s\n", level); /* don't want to have that pretty register dump messed up */ | ||
81 | |||
82 | printk("%s YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level); | ||
83 | printbinary(buf, regs->gr[0], 32); | ||
84 | printk("%sPSW: %s %s\n", level, buf, print_tainted()); | ||
85 | |||
86 | for (i = 0; i < 32; i += 4) { | ||
87 | int j; | ||
88 | p = buf; | ||
89 | p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3); | ||
90 | for (j = 0; j < 4; j++) { | ||
91 | p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]); | ||
92 | } | ||
93 | printk("%s\n", buf); | ||
94 | } | ||
95 | |||
96 | for (i = 0; i < 8; i += 4) { | ||
97 | int j; | ||
98 | p = buf; | ||
99 | p += sprintf(p, "%ssr%d-%d ", level, i, i + 3); | ||
100 | for (j = 0; j < 4; j++) { | ||
101 | p += sprintf(p, " " RFMT, regs->sr[i + j]); | ||
102 | } | ||
103 | printk("%s\n", buf); | ||
104 | } | ||
105 | |||
106 | #if RIDICULOUSLY_VERBOSE | ||
107 | for (i = 0; i < 32; i += 2) | ||
108 | printk("%sFR%02d : %016lx FR%2d : %016lx", level, i, | ||
109 | regs->fr[i], i+1, regs->fr[i+1]); | ||
110 | #endif | ||
111 | |||
112 | cr30 = mfctl(30); | ||
113 | cr31 = mfctl(31); | ||
114 | printk("%s\n", level); | ||
115 | printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n", | ||
116 | level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]); | ||
117 | printk("%s IIR: %08lx ISR: " RFMT " IOR: " RFMT "\n", | ||
118 | level, regs->iir, regs->isr, regs->ior); | ||
119 | printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n", | ||
120 | level, current_thread_info()->cpu, cr30, cr31); | ||
121 | printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28); | ||
122 | printk(level); | ||
123 | print_symbol(" IAOQ[0]: %s\n", regs->iaoq[0]); | ||
124 | printk(level); | ||
125 | print_symbol(" IAOQ[1]: %s\n", regs->iaoq[1]); | ||
126 | printk(level); | ||
127 | print_symbol(" RP(r2): %s\n", regs->gr[2]); | ||
128 | } | ||
129 | |||
130 | |||
131 | void dump_stack(void) | ||
132 | { | ||
133 | show_stack(NULL, NULL); | ||
134 | } | ||
135 | |||
136 | EXPORT_SYMBOL(dump_stack); | ||
137 | |||
138 | static void do_show_stack(struct unwind_frame_info *info) | ||
139 | { | ||
140 | int i = 1; | ||
141 | |||
142 | printk("Backtrace:\n"); | ||
143 | while (i <= 16) { | ||
144 | if (unwind_once(info) < 0 || info->ip == 0) | ||
145 | break; | ||
146 | |||
147 | if (__kernel_text_address(info->ip)) { | ||
148 | printk(" [<" RFMT ">] ", info->ip); | ||
149 | #ifdef CONFIG_KALLSYMS | ||
150 | print_symbol("%s\n", info->ip); | ||
151 | #else | ||
152 | if ((i & 0x03) == 0) | ||
153 | printk("\n"); | ||
154 | #endif | ||
155 | i++; | ||
156 | } | ||
157 | } | ||
158 | printk("\n"); | ||
159 | } | ||
160 | |||
161 | void show_stack(struct task_struct *task, unsigned long *s) | ||
162 | { | ||
163 | struct unwind_frame_info info; | ||
164 | |||
165 | if (!task) { | ||
166 | unsigned long sp; | ||
167 | struct pt_regs *r; | ||
168 | |||
169 | HERE: | ||
170 | asm volatile ("copy %%r30, %0" : "=r"(sp)); | ||
171 | r = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL); | ||
172 | if (!r) | ||
173 | return; | ||
174 | memset(r, 0, sizeof(struct pt_regs)); | ||
175 | r->iaoq[0] = (unsigned long)&&HERE; | ||
176 | r->gr[2] = (unsigned long)__builtin_return_address(0); | ||
177 | r->gr[30] = sp; | ||
178 | unwind_frame_init(&info, current, r); | ||
179 | kfree(r); | ||
180 | } else { | ||
181 | unwind_frame_init_from_blocked_task(&info, task); | ||
182 | } | ||
183 | |||
184 | do_show_stack(&info); | ||
185 | } | ||
186 | |||
187 | void die_if_kernel(char *str, struct pt_regs *regs, long err) | ||
188 | { | ||
189 | if (user_mode(regs)) { | ||
190 | if (err == 0) | ||
191 | return; /* STFU */ | ||
192 | |||
193 | printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n", | ||
194 | current->comm, current->pid, str, err, regs->iaoq[0]); | ||
195 | #ifdef PRINT_USER_FAULTS | ||
196 | /* XXX for debugging only */ | ||
197 | show_regs(regs); | ||
198 | #endif | ||
199 | return; | ||
200 | } | ||
201 | |||
202 | oops_in_progress = 1; | ||
203 | |||
204 | /* Amuse the user in a SPARC fashion */ | ||
205 | printk( | ||
206 | " _______________________________ \n" | ||
207 | " < Your System ate a SPARC! Gah! >\n" | ||
208 | " ------------------------------- \n" | ||
209 | " \\ ^__^\n" | ||
210 | " \\ (xx)\\_______\n" | ||
211 | " (__)\\ )\\/\\\n" | ||
212 | " U ||----w |\n" | ||
213 | " || ||\n"); | ||
214 | |||
215 | /* unlock the pdc lock if necessary */ | ||
216 | pdc_emergency_unlock(); | ||
217 | |||
218 | /* maybe the kernel hasn't booted very far yet and hasn't been able | ||
219 | * to initialize the serial or STI console. In that case we should | ||
220 | * re-enable the pdc console, so that the user will be able to | ||
221 | * identify the problem. */ | ||
222 | if (!console_drivers) | ||
223 | pdc_console_restart(); | ||
224 | |||
225 | printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n", | ||
226 | current->comm, current->pid, str, err); | ||
227 | show_regs(regs); | ||
228 | |||
229 | /* Wot's wrong wif bein' racy? */ | ||
230 | if (current->thread.flags & PARISC_KERNEL_DEATH) { | ||
231 | printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__); | ||
232 | local_irq_enable(); | ||
233 | while (1); | ||
234 | } | ||
235 | |||
236 | current->thread.flags |= PARISC_KERNEL_DEATH; | ||
237 | do_exit(SIGSEGV); | ||
238 | } | ||
239 | |||
240 | int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs) | ||
241 | { | ||
242 | return syscall(regs); | ||
243 | } | ||
244 | |||
245 | /* gdb uses break 4,8 */ | ||
246 | #define GDB_BREAK_INSN 0x10004 | ||
247 | void handle_gdb_break(struct pt_regs *regs, int wot) | ||
248 | { | ||
249 | struct siginfo si; | ||
250 | |||
251 | si.si_code = wot; | ||
252 | si.si_addr = (void __user *) (regs->iaoq[0] & ~3); | ||
253 | si.si_signo = SIGTRAP; | ||
254 | si.si_errno = 0; | ||
255 | force_sig_info(SIGTRAP, &si, current); | ||
256 | } | ||
257 | |||
258 | void handle_break(unsigned iir, struct pt_regs *regs) | ||
259 | { | ||
260 | struct siginfo si; | ||
261 | |||
262 | switch(iir) { | ||
263 | case 0x00: | ||
264 | #ifdef PRINT_USER_FAULTS | ||
265 | printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n", | ||
266 | current->pid, current->comm); | ||
267 | #endif | ||
268 | die_if_kernel("Breakpoint", regs, 0); | ||
269 | #ifdef PRINT_USER_FAULTS | ||
270 | show_regs(regs); | ||
271 | #endif | ||
272 | si.si_code = TRAP_BRKPT; | ||
273 | si.si_addr = (void __user *) (regs->iaoq[0] & ~3); | ||
274 | si.si_signo = SIGTRAP; | ||
275 | force_sig_info(SIGTRAP, &si, current); | ||
276 | break; | ||
277 | |||
278 | case GDB_BREAK_INSN: | ||
279 | die_if_kernel("Breakpoint", regs, 0); | ||
280 | handle_gdb_break(regs, TRAP_BRKPT); | ||
281 | break; | ||
282 | |||
283 | default: | ||
284 | #ifdef PRINT_USER_FAULTS | ||
285 | printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n", | ||
286 | iir, current->pid, current->comm); | ||
287 | show_regs(regs); | ||
288 | #endif | ||
289 | si.si_signo = SIGTRAP; | ||
290 | si.si_code = TRAP_BRKPT; | ||
291 | si.si_addr = (void __user *) (regs->iaoq[0] & ~3); | ||
292 | force_sig_info(SIGTRAP, &si, current); | ||
293 | return; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | |||
298 | int handle_toc(void) | ||
299 | { | ||
300 | printk(KERN_CRIT "TOC call.\n"); | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static void default_trap(int code, struct pt_regs *regs) | ||
305 | { | ||
306 | printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id()); | ||
307 | show_regs(regs); | ||
308 | } | ||
309 | |||
310 | void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap; | ||
311 | |||
312 | |||
313 | void transfer_pim_to_trap_frame(struct pt_regs *regs) | ||
314 | { | ||
315 | register int i; | ||
316 | extern unsigned int hpmc_pim_data[]; | ||
317 | struct pdc_hpmc_pim_11 *pim_narrow; | ||
318 | struct pdc_hpmc_pim_20 *pim_wide; | ||
319 | |||
320 | if (boot_cpu_data.cpu_type >= pcxu) { | ||
321 | |||
322 | pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data; | ||
323 | |||
324 | /* | ||
325 | * Note: The following code will probably generate a | ||
326 | * bunch of truncation error warnings from the compiler. | ||
327 | * Could be handled with an ifdef, but perhaps there | ||
328 | * is a better way. | ||
329 | */ | ||
330 | |||
331 | regs->gr[0] = pim_wide->cr[22]; | ||
332 | |||
333 | for (i = 1; i < 32; i++) | ||
334 | regs->gr[i] = pim_wide->gr[i]; | ||
335 | |||
336 | for (i = 0; i < 32; i++) | ||
337 | regs->fr[i] = pim_wide->fr[i]; | ||
338 | |||
339 | for (i = 0; i < 8; i++) | ||
340 | regs->sr[i] = pim_wide->sr[i]; | ||
341 | |||
342 | regs->iasq[0] = pim_wide->cr[17]; | ||
343 | regs->iasq[1] = pim_wide->iasq_back; | ||
344 | regs->iaoq[0] = pim_wide->cr[18]; | ||
345 | regs->iaoq[1] = pim_wide->iaoq_back; | ||
346 | |||
347 | regs->sar = pim_wide->cr[11]; | ||
348 | regs->iir = pim_wide->cr[19]; | ||
349 | regs->isr = pim_wide->cr[20]; | ||
350 | regs->ior = pim_wide->cr[21]; | ||
351 | } | ||
352 | else { | ||
353 | pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data; | ||
354 | |||
355 | regs->gr[0] = pim_narrow->cr[22]; | ||
356 | |||
357 | for (i = 1; i < 32; i++) | ||
358 | regs->gr[i] = pim_narrow->gr[i]; | ||
359 | |||
360 | for (i = 0; i < 32; i++) | ||
361 | regs->fr[i] = pim_narrow->fr[i]; | ||
362 | |||
363 | for (i = 0; i < 8; i++) | ||
364 | regs->sr[i] = pim_narrow->sr[i]; | ||
365 | |||
366 | regs->iasq[0] = pim_narrow->cr[17]; | ||
367 | regs->iasq[1] = pim_narrow->iasq_back; | ||
368 | regs->iaoq[0] = pim_narrow->cr[18]; | ||
369 | regs->iaoq[1] = pim_narrow->iaoq_back; | ||
370 | |||
371 | regs->sar = pim_narrow->cr[11]; | ||
372 | regs->iir = pim_narrow->cr[19]; | ||
373 | regs->isr = pim_narrow->cr[20]; | ||
374 | regs->ior = pim_narrow->cr[21]; | ||
375 | } | ||
376 | |||
377 | /* | ||
378 | * The following fields only have meaning if we came through | ||
379 | * another path. So just zero them here. | ||
380 | */ | ||
381 | |||
382 | regs->ksp = 0; | ||
383 | regs->kpc = 0; | ||
384 | regs->orig_r28 = 0; | ||
385 | } | ||
386 | |||
387 | |||
388 | /* | ||
389 | * This routine is called as a last resort when everything else | ||
390 | * has gone clearly wrong. We get called for faults in kernel space, | ||
391 | * and HPMC's. | ||
392 | */ | ||
393 | void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset) | ||
394 | { | ||
395 | static DEFINE_SPINLOCK(terminate_lock); | ||
396 | |||
397 | oops_in_progress = 1; | ||
398 | |||
399 | set_eiem(0); | ||
400 | local_irq_disable(); | ||
401 | spin_lock(&terminate_lock); | ||
402 | |||
403 | /* unlock the pdc lock if necessary */ | ||
404 | pdc_emergency_unlock(); | ||
405 | |||
406 | /* restart pdc console if necessary */ | ||
407 | if (!console_drivers) | ||
408 | pdc_console_restart(); | ||
409 | |||
410 | /* Not all paths will gutter the processor... */ | ||
411 | switch(code){ | ||
412 | |||
413 | case 1: | ||
414 | transfer_pim_to_trap_frame(regs); | ||
415 | break; | ||
416 | |||
417 | default: | ||
418 | /* Fall through */ | ||
419 | break; | ||
420 | |||
421 | } | ||
422 | |||
423 | { | ||
424 | /* show_stack(NULL, (unsigned long *)regs->gr[30]); */ | ||
425 | struct unwind_frame_info info; | ||
426 | unwind_frame_init(&info, current, regs); | ||
427 | do_show_stack(&info); | ||
428 | } | ||
429 | |||
430 | printk("\n"); | ||
431 | printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n", | ||
432 | msg, code, regs, offset); | ||
433 | show_regs(regs); | ||
434 | |||
435 | spin_unlock(&terminate_lock); | ||
436 | |||
437 | /* put soft power button back under hardware control; | ||
438 | * if the user had pressed it once at any time, the | ||
439 | * system will shut down immediately right here. */ | ||
440 | pdc_soft_power_button(0); | ||
441 | |||
442 | /* Call kernel panic() so reboot timeouts work properly | ||
443 | * FIXME: This function should be on the list of | ||
444 | * panic notifiers, and we should call panic | ||
445 | * directly from the location that we wish. | ||
446 | * e.g. We should not call panic from | ||
447 | * parisc_terminate, but rather the oter way around. | ||
448 | * This hack works, prints the panic message twice, | ||
449 | * and it enables reboot timers! | ||
450 | */ | ||
451 | panic(msg); | ||
452 | } | ||
453 | |||
454 | void handle_interruption(int code, struct pt_regs *regs) | ||
455 | { | ||
456 | unsigned long fault_address = 0; | ||
457 | unsigned long fault_space = 0; | ||
458 | struct siginfo si; | ||
459 | |||
460 | if (code == 1) | ||
461 | pdc_console_restart(); /* switch back to pdc if HPMC */ | ||
462 | else | ||
463 | local_irq_enable(); | ||
464 | |||
465 | /* Security check: | ||
466 | * If the priority level is still user, and the | ||
467 | * faulting space is not equal to the active space | ||
468 | * then the user is attempting something in a space | ||
469 | * that does not belong to them. Kill the process. | ||
470 | * | ||
471 | * This is normally the situation when the user | ||
472 | * attempts to jump into the kernel space at the | ||
473 | * wrong offset, be it at the gateway page or a | ||
474 | * random location. | ||
475 | * | ||
476 | * We cannot normally signal the process because it | ||
477 | * could *be* on the gateway page, and processes | ||
478 | * executing on the gateway page can't have signals | ||
479 | * delivered. | ||
480 | * | ||
481 | * We merely readjust the address into the users | ||
482 | * space, at a destination address of zero, and | ||
483 | * allow processing to continue. | ||
484 | */ | ||
485 | if (((unsigned long)regs->iaoq[0] & 3) && | ||
486 | ((unsigned long)regs->iasq[0] != (unsigned long)regs->sr[7])) { | ||
487 | /* Kill the user process later */ | ||
488 | regs->iaoq[0] = 0 | 3; | ||
489 | regs->iaoq[1] = regs->iaoq[0] + 4; | ||
490 | regs->iasq[0] = regs->iasq[0] = regs->sr[7]; | ||
491 | regs->gr[0] &= ~PSW_B; | ||
492 | return; | ||
493 | } | ||
494 | |||
495 | #if 0 | ||
496 | printk(KERN_CRIT "Interruption # %d\n", code); | ||
497 | #endif | ||
498 | |||
499 | switch(code) { | ||
500 | |||
501 | case 1: | ||
502 | /* High-priority machine check (HPMC) */ | ||
503 | |||
504 | /* set up a new led state on systems shipped with a LED State panel */ | ||
505 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_HPMC); | ||
506 | |||
507 | parisc_terminate("High Priority Machine Check (HPMC)", | ||
508 | regs, code, 0); | ||
509 | /* NOT REACHED */ | ||
510 | |||
511 | case 2: | ||
512 | /* Power failure interrupt */ | ||
513 | printk(KERN_CRIT "Power failure interrupt !\n"); | ||
514 | return; | ||
515 | |||
516 | case 3: | ||
517 | /* Recovery counter trap */ | ||
518 | regs->gr[0] &= ~PSW_R; | ||
519 | if (user_space(regs)) | ||
520 | handle_gdb_break(regs, TRAP_TRACE); | ||
521 | /* else this must be the start of a syscall - just let it run */ | ||
522 | return; | ||
523 | |||
524 | case 5: | ||
525 | /* Low-priority machine check */ | ||
526 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC); | ||
527 | |||
528 | flush_all_caches(); | ||
529 | cpu_lpmc(5, regs); | ||
530 | return; | ||
531 | |||
532 | case 6: | ||
533 | /* Instruction TLB miss fault/Instruction page fault */ | ||
534 | fault_address = regs->iaoq[0]; | ||
535 | fault_space = regs->iasq[0]; | ||
536 | break; | ||
537 | |||
538 | case 8: | ||
539 | /* Illegal instruction trap */ | ||
540 | die_if_kernel("Illegal instruction", regs, code); | ||
541 | si.si_code = ILL_ILLOPC; | ||
542 | goto give_sigill; | ||
543 | |||
544 | case 9: | ||
545 | /* Break instruction trap */ | ||
546 | handle_break(regs->iir,regs); | ||
547 | return; | ||
548 | |||
549 | case 10: | ||
550 | /* Privileged operation trap */ | ||
551 | die_if_kernel("Privileged operation", regs, code); | ||
552 | si.si_code = ILL_PRVOPC; | ||
553 | goto give_sigill; | ||
554 | |||
555 | case 11: | ||
556 | /* Privileged register trap */ | ||
557 | if ((regs->iir & 0xffdfffe0) == 0x034008a0) { | ||
558 | |||
559 | /* This is a MFCTL cr26/cr27 to gr instruction. | ||
560 | * PCXS traps on this, so we need to emulate it. | ||
561 | */ | ||
562 | |||
563 | if (regs->iir & 0x00200000) | ||
564 | regs->gr[regs->iir & 0x1f] = mfctl(27); | ||
565 | else | ||
566 | regs->gr[regs->iir & 0x1f] = mfctl(26); | ||
567 | |||
568 | regs->iaoq[0] = regs->iaoq[1]; | ||
569 | regs->iaoq[1] += 4; | ||
570 | regs->iasq[0] = regs->iasq[1]; | ||
571 | return; | ||
572 | } | ||
573 | |||
574 | die_if_kernel("Privileged register usage", regs, code); | ||
575 | si.si_code = ILL_PRVREG; | ||
576 | give_sigill: | ||
577 | si.si_signo = SIGILL; | ||
578 | si.si_errno = 0; | ||
579 | si.si_addr = (void __user *) regs->iaoq[0]; | ||
580 | force_sig_info(SIGILL, &si, current); | ||
581 | return; | ||
582 | |||
583 | case 12: | ||
584 | /* Overflow Trap, let the userland signal handler do the cleanup */ | ||
585 | si.si_signo = SIGFPE; | ||
586 | si.si_code = FPE_INTOVF; | ||
587 | si.si_addr = (void __user *) regs->iaoq[0]; | ||
588 | force_sig_info(SIGFPE, &si, current); | ||
589 | return; | ||
590 | |||
591 | case 13: | ||
592 | /* Conditional Trap | ||
593 | The condition succees in an instruction which traps | ||
594 | on condition */ | ||
595 | if(user_mode(regs)){ | ||
596 | si.si_signo = SIGFPE; | ||
597 | /* Set to zero, and let the userspace app figure it out from | ||
598 | the insn pointed to by si_addr */ | ||
599 | si.si_code = 0; | ||
600 | si.si_addr = (void __user *) regs->iaoq[0]; | ||
601 | force_sig_info(SIGFPE, &si, current); | ||
602 | return; | ||
603 | } | ||
604 | /* The kernel doesn't want to handle condition codes */ | ||
605 | break; | ||
606 | |||
607 | case 14: | ||
608 | /* Assist Exception Trap, i.e. floating point exception. */ | ||
609 | die_if_kernel("Floating point exception", regs, 0); /* quiet */ | ||
610 | handle_fpe(regs); | ||
611 | return; | ||
612 | |||
613 | case 15: | ||
614 | /* Data TLB miss fault/Data page fault */ | ||
615 | /* Fall through */ | ||
616 | case 16: | ||
617 | /* Non-access instruction TLB miss fault */ | ||
618 | /* The instruction TLB entry needed for the target address of the FIC | ||
619 | is absent, and hardware can't find it, so we get to cleanup */ | ||
620 | /* Fall through */ | ||
621 | case 17: | ||
622 | /* Non-access data TLB miss fault/Non-access data page fault */ | ||
623 | /* FIXME: | ||
624 | Still need to add slow path emulation code here! | ||
625 | If the insn used a non-shadow register, then the tlb | ||
626 | handlers could not have their side-effect (e.g. probe | ||
627 | writing to a target register) emulated since rfir would | ||
628 | erase the changes to said register. Instead we have to | ||
629 | setup everything, call this function we are in, and emulate | ||
630 | by hand. Technically we need to emulate: | ||
631 | fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw | ||
632 | */ | ||
633 | fault_address = regs->ior; | ||
634 | fault_space = regs->isr; | ||
635 | break; | ||
636 | |||
637 | case 18: | ||
638 | /* PCXS only -- later cpu's split this into types 26,27 & 28 */ | ||
639 | /* Check for unaligned access */ | ||
640 | if (check_unaligned(regs)) { | ||
641 | handle_unaligned(regs); | ||
642 | return; | ||
643 | } | ||
644 | /* Fall Through */ | ||
645 | case 26: | ||
646 | /* PCXL: Data memory access rights trap */ | ||
647 | fault_address = regs->ior; | ||
648 | fault_space = regs->isr; | ||
649 | break; | ||
650 | |||
651 | case 19: | ||
652 | /* Data memory break trap */ | ||
653 | regs->gr[0] |= PSW_X; /* So we can single-step over the trap */ | ||
654 | /* fall thru */ | ||
655 | case 21: | ||
656 | /* Page reference trap */ | ||
657 | handle_gdb_break(regs, TRAP_HWBKPT); | ||
658 | return; | ||
659 | |||
660 | case 25: | ||
661 | /* Taken branch trap */ | ||
662 | regs->gr[0] &= ~PSW_T; | ||
663 | if (user_space(regs)) | ||
664 | handle_gdb_break(regs, TRAP_BRANCH); | ||
665 | /* else this must be the start of a syscall - just let it | ||
666 | * run. | ||
667 | */ | ||
668 | return; | ||
669 | |||
670 | case 7: | ||
671 | /* Instruction access rights */ | ||
672 | /* PCXL: Instruction memory protection trap */ | ||
673 | |||
674 | /* | ||
675 | * This could be caused by either: 1) a process attempting | ||
676 | * to execute within a vma that does not have execute | ||
677 | * permission, or 2) an access rights violation caused by a | ||
678 | * flush only translation set up by ptep_get_and_clear(). | ||
679 | * So we check the vma permissions to differentiate the two. | ||
680 | * If the vma indicates we have execute permission, then | ||
681 | * the cause is the latter one. In this case, we need to | ||
682 | * call do_page_fault() to fix the problem. | ||
683 | */ | ||
684 | |||
685 | if (user_mode(regs)) { | ||
686 | struct vm_area_struct *vma; | ||
687 | |||
688 | down_read(¤t->mm->mmap_sem); | ||
689 | vma = find_vma(current->mm,regs->iaoq[0]); | ||
690 | if (vma && (regs->iaoq[0] >= vma->vm_start) | ||
691 | && (vma->vm_flags & VM_EXEC)) { | ||
692 | |||
693 | fault_address = regs->iaoq[0]; | ||
694 | fault_space = regs->iasq[0]; | ||
695 | |||
696 | up_read(¤t->mm->mmap_sem); | ||
697 | break; /* call do_page_fault() */ | ||
698 | } | ||
699 | up_read(¤t->mm->mmap_sem); | ||
700 | } | ||
701 | /* Fall Through */ | ||
702 | case 27: | ||
703 | /* Data memory protection ID trap */ | ||
704 | die_if_kernel("Protection id trap", regs, code); | ||
705 | si.si_code = SEGV_MAPERR; | ||
706 | si.si_signo = SIGSEGV; | ||
707 | si.si_errno = 0; | ||
708 | if (code == 7) | ||
709 | si.si_addr = (void __user *) regs->iaoq[0]; | ||
710 | else | ||
711 | si.si_addr = (void __user *) regs->ior; | ||
712 | force_sig_info(SIGSEGV, &si, current); | ||
713 | return; | ||
714 | |||
715 | case 28: | ||
716 | /* Unaligned data reference trap */ | ||
717 | handle_unaligned(regs); | ||
718 | return; | ||
719 | |||
720 | default: | ||
721 | if (user_mode(regs)) { | ||
722 | #ifdef PRINT_USER_FAULTS | ||
723 | printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n", | ||
724 | current->pid, current->comm); | ||
725 | show_regs(regs); | ||
726 | #endif | ||
727 | /* SIGBUS, for lack of a better one. */ | ||
728 | si.si_signo = SIGBUS; | ||
729 | si.si_code = BUS_OBJERR; | ||
730 | si.si_errno = 0; | ||
731 | si.si_addr = (void __user *) regs->ior; | ||
732 | force_sig_info(SIGBUS, &si, current); | ||
733 | return; | ||
734 | } | ||
735 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); | ||
736 | |||
737 | parisc_terminate("Unexpected interruption", regs, code, 0); | ||
738 | /* NOT REACHED */ | ||
739 | } | ||
740 | |||
741 | if (user_mode(regs)) { | ||
742 | if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) { | ||
743 | #ifdef PRINT_USER_FAULTS | ||
744 | if (fault_space == 0) | ||
745 | printk(KERN_DEBUG "User Fault on Kernel Space "); | ||
746 | else | ||
747 | printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ", | ||
748 | code); | ||
749 | printk("pid=%d command='%s'\n", current->pid, current->comm); | ||
750 | show_regs(regs); | ||
751 | #endif | ||
752 | si.si_signo = SIGSEGV; | ||
753 | si.si_errno = 0; | ||
754 | si.si_code = SEGV_MAPERR; | ||
755 | si.si_addr = (void __user *) regs->ior; | ||
756 | force_sig_info(SIGSEGV, &si, current); | ||
757 | return; | ||
758 | } | ||
759 | } | ||
760 | else { | ||
761 | |||
762 | /* | ||
763 | * The kernel should never fault on its own address space. | ||
764 | */ | ||
765 | |||
766 | if (fault_space == 0) | ||
767 | { | ||
768 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); | ||
769 | parisc_terminate("Kernel Fault", regs, code, fault_address); | ||
770 | |||
771 | } | ||
772 | } | ||
773 | |||
774 | do_page_fault(regs, code, fault_address); | ||
775 | } | ||
776 | |||
777 | |||
778 | int __init check_ivt(void *iva) | ||
779 | { | ||
780 | int i; | ||
781 | u32 check = 0; | ||
782 | u32 *ivap; | ||
783 | u32 *hpmcp; | ||
784 | u32 length; | ||
785 | extern void os_hpmc(void); | ||
786 | extern void os_hpmc_end(void); | ||
787 | |||
788 | if (strcmp((char *)iva, "cows can fly")) | ||
789 | return -1; | ||
790 | |||
791 | ivap = (u32 *)iva; | ||
792 | |||
793 | for (i = 0; i < 8; i++) | ||
794 | *ivap++ = 0; | ||
795 | |||
796 | /* Compute Checksum for HPMC handler */ | ||
797 | |||
798 | length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc); | ||
799 | ivap[7] = length; | ||
800 | |||
801 | hpmcp = (u32 *)os_hpmc; | ||
802 | |||
803 | for (i=0; i<length/4; i++) | ||
804 | check += *hpmcp++; | ||
805 | |||
806 | for (i=0; i<8; i++) | ||
807 | check += ivap[i]; | ||
808 | |||
809 | ivap[5] = -check; | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | #ifndef __LP64__ | ||
815 | extern const void fault_vector_11; | ||
816 | #endif | ||
817 | extern const void fault_vector_20; | ||
818 | |||
819 | void __init trap_init(void) | ||
820 | { | ||
821 | void *iva; | ||
822 | |||
823 | if (boot_cpu_data.cpu_type >= pcxu) | ||
824 | iva = (void *) &fault_vector_20; | ||
825 | else | ||
826 | #ifdef __LP64__ | ||
827 | panic("Can't boot 64-bit OS on PA1.1 processor!"); | ||
828 | #else | ||
829 | iva = (void *) &fault_vector_11; | ||
830 | #endif | ||
831 | |||
832 | if (check_ivt(iva)) | ||
833 | panic("IVT invalid"); | ||
834 | } | ||
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c new file mode 100644 index 000000000000..62eea35bcd69 --- /dev/null +++ b/arch/parisc/kernel/unaligned.c | |||
@@ -0,0 +1,816 @@ | |||
1 | /* | ||
2 | * Unaligned memory access handler | ||
3 | * | ||
4 | * Copyright (C) 2001 Randolph Chung <tausq@debian.org> | ||
5 | * Significantly tweaked by LaMont Jones <lamont@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | |||
28 | /* #define DEBUG_UNALIGNED 1 */ | ||
29 | |||
30 | #ifdef DEBUG_UNALIGNED | ||
31 | #define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0) | ||
32 | #else | ||
33 | #define DPRINTF(fmt, args...) | ||
34 | #endif | ||
35 | |||
36 | #ifdef __LP64__ | ||
37 | #define RFMT "%016lx" | ||
38 | #else | ||
39 | #define RFMT "%08lx" | ||
40 | #endif | ||
41 | |||
42 | #define FIXUP_BRANCH(lbl) \ | ||
43 | "\tldil L%%" #lbl ", %%r1\n" \ | ||
44 | "\tldo R%%" #lbl "(%%r1), %%r1\n" \ | ||
45 | "\tbv,n %%r0(%%r1)\n" | ||
46 | |||
47 | /* 1111 1100 0000 0000 0001 0011 1100 0000 */ | ||
48 | #define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) | ||
49 | #define OPCODE2(a,b) ((a)<<26|(b)<<1) | ||
50 | #define OPCODE3(a,b) ((a)<<26|(b)<<2) | ||
51 | #define OPCODE4(a) ((a)<<26) | ||
52 | #define OPCODE1_MASK OPCODE1(0x3f,1,0xf) | ||
53 | #define OPCODE2_MASK OPCODE2(0x3f,1) | ||
54 | #define OPCODE3_MASK OPCODE3(0x3f,1) | ||
55 | #define OPCODE4_MASK OPCODE4(0x3f) | ||
56 | |||
57 | /* skip LDB - never unaligned (index) */ | ||
58 | #define OPCODE_LDH_I OPCODE1(0x03,0,0x1) | ||
59 | #define OPCODE_LDW_I OPCODE1(0x03,0,0x2) | ||
60 | #define OPCODE_LDD_I OPCODE1(0x03,0,0x3) | ||
61 | #define OPCODE_LDDA_I OPCODE1(0x03,0,0x4) | ||
62 | #define OPCODE_LDCD_I OPCODE1(0x03,0,0x5) | ||
63 | #define OPCODE_LDWA_I OPCODE1(0x03,0,0x6) | ||
64 | #define OPCODE_LDCW_I OPCODE1(0x03,0,0x7) | ||
65 | /* skip LDB - never unaligned (short) */ | ||
66 | #define OPCODE_LDH_S OPCODE1(0x03,1,0x1) | ||
67 | #define OPCODE_LDW_S OPCODE1(0x03,1,0x2) | ||
68 | #define OPCODE_LDD_S OPCODE1(0x03,1,0x3) | ||
69 | #define OPCODE_LDDA_S OPCODE1(0x03,1,0x4) | ||
70 | #define OPCODE_LDCD_S OPCODE1(0x03,1,0x5) | ||
71 | #define OPCODE_LDWA_S OPCODE1(0x03,1,0x6) | ||
72 | #define OPCODE_LDCW_S OPCODE1(0x03,1,0x7) | ||
73 | /* skip STB - never unaligned */ | ||
74 | #define OPCODE_STH OPCODE1(0x03,1,0x9) | ||
75 | #define OPCODE_STW OPCODE1(0x03,1,0xa) | ||
76 | #define OPCODE_STD OPCODE1(0x03,1,0xb) | ||
77 | /* skip STBY - never unaligned */ | ||
78 | /* skip STDBY - never unaligned */ | ||
79 | #define OPCODE_STWA OPCODE1(0x03,1,0xe) | ||
80 | #define OPCODE_STDA OPCODE1(0x03,1,0xf) | ||
81 | |||
82 | #define OPCODE_FLDWX OPCODE1(0x09,0,0x0) | ||
83 | #define OPCODE_FLDWXR OPCODE1(0x09,0,0x1) | ||
84 | #define OPCODE_FSTWX OPCODE1(0x09,0,0x8) | ||
85 | #define OPCODE_FSTWXR OPCODE1(0x09,0,0x9) | ||
86 | #define OPCODE_FLDWS OPCODE1(0x09,1,0x0) | ||
87 | #define OPCODE_FLDWSR OPCODE1(0x09,1,0x1) | ||
88 | #define OPCODE_FSTWS OPCODE1(0x09,1,0x8) | ||
89 | #define OPCODE_FSTWSR OPCODE1(0x09,1,0x9) | ||
90 | #define OPCODE_FLDDX OPCODE1(0x0b,0,0x0) | ||
91 | #define OPCODE_FSTDX OPCODE1(0x0b,0,0x8) | ||
92 | #define OPCODE_FLDDS OPCODE1(0x0b,1,0x0) | ||
93 | #define OPCODE_FSTDS OPCODE1(0x0b,1,0x8) | ||
94 | |||
95 | #define OPCODE_LDD_L OPCODE2(0x14,0) | ||
96 | #define OPCODE_FLDD_L OPCODE2(0x14,1) | ||
97 | #define OPCODE_STD_L OPCODE2(0x1c,0) | ||
98 | #define OPCODE_FSTD_L OPCODE2(0x1c,1) | ||
99 | |||
100 | #define OPCODE_LDW_M OPCODE3(0x17,1) | ||
101 | #define OPCODE_FLDW_L OPCODE3(0x17,0) | ||
102 | #define OPCODE_FSTW_L OPCODE3(0x1f,0) | ||
103 | #define OPCODE_STW_M OPCODE3(0x1f,1) | ||
104 | |||
105 | #define OPCODE_LDH_L OPCODE4(0x11) | ||
106 | #define OPCODE_LDW_L OPCODE4(0x12) | ||
107 | #define OPCODE_LDWM OPCODE4(0x13) | ||
108 | #define OPCODE_STH_L OPCODE4(0x19) | ||
109 | #define OPCODE_STW_L OPCODE4(0x1A) | ||
110 | #define OPCODE_STWM OPCODE4(0x1B) | ||
111 | |||
112 | #define MAJOR_OP(i) (((i)>>26)&0x3f) | ||
113 | #define R1(i) (((i)>>21)&0x1f) | ||
114 | #define R2(i) (((i)>>16)&0x1f) | ||
115 | #define R3(i) ((i)&0x1f) | ||
116 | #define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1)) | ||
117 | #define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0)) | ||
118 | #define IM5_2(i) IM((i)>>16,5) | ||
119 | #define IM5_3(i) IM((i),5) | ||
120 | #define IM14(i) IM((i),14) | ||
121 | |||
122 | #define ERR_NOTHANDLED -1 | ||
123 | #define ERR_PAGEFAULT -2 | ||
124 | |||
125 | int unaligned_enabled = 1; | ||
126 | |||
127 | void die_if_kernel (char *str, struct pt_regs *regs, long err); | ||
128 | |||
129 | static int emulate_ldh(struct pt_regs *regs, int toreg) | ||
130 | { | ||
131 | unsigned long saddr = regs->ior; | ||
132 | unsigned long val = 0; | ||
133 | int ret; | ||
134 | |||
135 | DPRINTF("load " RFMT ":" RFMT " to r%d for 2 bytes\n", | ||
136 | regs->isr, regs->ior, toreg); | ||
137 | |||
138 | __asm__ __volatile__ ( | ||
139 | " mtsp %4, %%sr1\n" | ||
140 | "1: ldbs 0(%%sr1,%3), %%r20\n" | ||
141 | "2: ldbs 1(%%sr1,%3), %0\n" | ||
142 | " depw %%r20, 23, 24, %0\n" | ||
143 | " copy %%r0, %1\n" | ||
144 | "3: \n" | ||
145 | " .section .fixup,\"ax\"\n" | ||
146 | "4: ldi -2, %1\n" | ||
147 | FIXUP_BRANCH(3b) | ||
148 | " .previous\n" | ||
149 | " .section __ex_table,\"aw\"\n" | ||
150 | #ifdef __LP64__ | ||
151 | " .dword 1b,4b\n" | ||
152 | " .dword 2b,4b\n" | ||
153 | #else | ||
154 | " .word 1b,4b\n" | ||
155 | " .word 2b,4b\n" | ||
156 | #endif | ||
157 | " .previous\n" | ||
158 | : "=r" (val), "=r" (ret) | ||
159 | : "0" (val), "r" (saddr), "r" (regs->isr) | ||
160 | : "r20" ); | ||
161 | |||
162 | DPRINTF("val = 0x" RFMT "\n", val); | ||
163 | |||
164 | if (toreg) | ||
165 | regs->gr[toreg] = val; | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int emulate_ldw(struct pt_regs *regs, int toreg, int flop) | ||
171 | { | ||
172 | unsigned long saddr = regs->ior; | ||
173 | unsigned long val = 0; | ||
174 | int ret; | ||
175 | |||
176 | DPRINTF("load " RFMT ":" RFMT " to r%d for 4 bytes\n", | ||
177 | regs->isr, regs->ior, toreg); | ||
178 | |||
179 | __asm__ __volatile__ ( | ||
180 | " zdep %3,28,2,%%r19\n" /* r19=(ofs&3)*8 */ | ||
181 | " mtsp %4, %%sr1\n" | ||
182 | " depw %%r0,31,2,%3\n" | ||
183 | "1: ldw 0(%%sr1,%3),%0\n" | ||
184 | "2: ldw 4(%%sr1,%3),%%r20\n" | ||
185 | " subi 32,%%r19,%%r19\n" | ||
186 | " mtctl %%r19,11\n" | ||
187 | " vshd %0,%%r20,%0\n" | ||
188 | " copy %%r0, %1\n" | ||
189 | "3: \n" | ||
190 | " .section .fixup,\"ax\"\n" | ||
191 | "4: ldi -2, %1\n" | ||
192 | FIXUP_BRANCH(3b) | ||
193 | " .previous\n" | ||
194 | " .section __ex_table,\"aw\"\n" | ||
195 | #ifdef __LP64__ | ||
196 | " .dword 1b,4b\n" | ||
197 | " .dword 2b,4b\n" | ||
198 | #else | ||
199 | " .word 1b,4b\n" | ||
200 | " .word 2b,4b\n" | ||
201 | #endif | ||
202 | " .previous\n" | ||
203 | : "=r" (val), "=r" (ret) | ||
204 | : "0" (val), "r" (saddr), "r" (regs->isr) | ||
205 | : "r19", "r20" ); | ||
206 | |||
207 | DPRINTF("val = 0x" RFMT "\n", val); | ||
208 | |||
209 | if (flop) | ||
210 | ((__u32*)(regs->fr))[toreg] = val; | ||
211 | else if (toreg) | ||
212 | regs->gr[toreg] = val; | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) | ||
217 | { | ||
218 | unsigned long saddr = regs->ior; | ||
219 | __u64 val = 0; | ||
220 | int ret; | ||
221 | |||
222 | DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n", | ||
223 | regs->isr, regs->ior, toreg); | ||
224 | #ifdef CONFIG_PA20 | ||
225 | |||
226 | #ifndef __LP64__ | ||
227 | if (!flop) | ||
228 | return -1; | ||
229 | #endif | ||
230 | __asm__ __volatile__ ( | ||
231 | " depd,z %3,60,3,%%r19\n" /* r19=(ofs&7)*8 */ | ||
232 | " mtsp %4, %%sr1\n" | ||
233 | " depd %%r0,63,3,%3\n" | ||
234 | "1: ldd 0(%%sr1,%3),%0\n" | ||
235 | "2: ldd 8(%%sr1,%3),%%r20\n" | ||
236 | " subi 64,%%r19,%%r19\n" | ||
237 | " mtsar %%r19\n" | ||
238 | " shrpd %0,%%r20,%%sar,%0\n" | ||
239 | " copy %%r0, %1\n" | ||
240 | "3: \n" | ||
241 | " .section .fixup,\"ax\"\n" | ||
242 | "4: ldi -2, %1\n" | ||
243 | FIXUP_BRANCH(3b) | ||
244 | " .previous\n" | ||
245 | " .section __ex_table,\"aw\"\n" | ||
246 | #ifdef __LP64__ | ||
247 | " .dword 1b,4b\n" | ||
248 | " .dword 2b,4b\n" | ||
249 | #else | ||
250 | " .word 1b,4b\n" | ||
251 | " .word 2b,4b\n" | ||
252 | #endif | ||
253 | " .previous\n" | ||
254 | : "=r" (val), "=r" (ret) | ||
255 | : "0" (val), "r" (saddr), "r" (regs->isr) | ||
256 | : "r19", "r20" ); | ||
257 | #else | ||
258 | { | ||
259 | unsigned long valh=0,vall=0; | ||
260 | __asm__ __volatile__ ( | ||
261 | " zdep %5,29,2,%%r19\n" /* r19=(ofs&3)*8 */ | ||
262 | " mtsp %6, %%sr1\n" | ||
263 | " dep %%r0,31,2,%5\n" | ||
264 | "1: ldw 0(%%sr1,%5),%0\n" | ||
265 | "2: ldw 4(%%sr1,%5),%1\n" | ||
266 | "3: ldw 8(%%sr1,%5),%%r20\n" | ||
267 | " subi 32,%%r19,%%r19\n" | ||
268 | " mtsar %%r19\n" | ||
269 | " vshd %0,%1,%0\n" | ||
270 | " vshd %1,%%r20,%1\n" | ||
271 | " copy %%r0, %2\n" | ||
272 | "4: \n" | ||
273 | " .section .fixup,\"ax\"\n" | ||
274 | "5: ldi -2, %2\n" | ||
275 | FIXUP_BRANCH(4b) | ||
276 | " .previous\n" | ||
277 | " .section __ex_table,\"aw\"\n" | ||
278 | #ifdef __LP64__ | ||
279 | " .dword 1b,5b\n" | ||
280 | " .dword 2b,5b\n" | ||
281 | " .dword 3b,5b\n" | ||
282 | #else | ||
283 | " .word 1b,5b\n" | ||
284 | " .word 2b,5b\n" | ||
285 | " .word 3b,5b\n" | ||
286 | #endif | ||
287 | " .previous\n" | ||
288 | : "=r" (valh), "=r" (vall), "=r" (ret) | ||
289 | : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr) | ||
290 | : "r19", "r20" ); | ||
291 | val=((__u64)valh<<32)|(__u64)vall; | ||
292 | } | ||
293 | #endif | ||
294 | |||
295 | DPRINTF("val = 0x%llx\n", val); | ||
296 | |||
297 | if (flop) | ||
298 | regs->fr[toreg] = val; | ||
299 | else if (toreg) | ||
300 | regs->gr[toreg] = val; | ||
301 | |||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | static int emulate_sth(struct pt_regs *regs, int frreg) | ||
306 | { | ||
307 | unsigned long val = regs->gr[frreg]; | ||
308 | int ret; | ||
309 | |||
310 | if (!frreg) | ||
311 | val = 0; | ||
312 | |||
313 | DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg, | ||
314 | val, regs->isr, regs->ior); | ||
315 | |||
316 | __asm__ __volatile__ ( | ||
317 | " mtsp %3, %%sr1\n" | ||
318 | " extrw,u %1, 23, 8, %%r19\n" | ||
319 | "1: stb %1, 1(%%sr1, %2)\n" | ||
320 | "2: stb %%r19, 0(%%sr1, %2)\n" | ||
321 | " copy %%r0, %0\n" | ||
322 | "3: \n" | ||
323 | " .section .fixup,\"ax\"\n" | ||
324 | "4: ldi -2, %0\n" | ||
325 | FIXUP_BRANCH(3b) | ||
326 | " .previous\n" | ||
327 | " .section __ex_table,\"aw\"\n" | ||
328 | #ifdef __LP64__ | ||
329 | " .dword 1b,4b\n" | ||
330 | " .dword 2b,4b\n" | ||
331 | #else | ||
332 | " .word 1b,4b\n" | ||
333 | " .word 2b,4b\n" | ||
334 | #endif | ||
335 | " .previous\n" | ||
336 | : "=r" (ret) | ||
337 | : "r" (val), "r" (regs->ior), "r" (regs->isr) | ||
338 | : "r19" ); | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | static int emulate_stw(struct pt_regs *regs, int frreg, int flop) | ||
344 | { | ||
345 | unsigned long val; | ||
346 | int ret; | ||
347 | |||
348 | if (flop) | ||
349 | val = ((__u32*)(regs->fr))[frreg]; | ||
350 | else if (frreg) | ||
351 | val = regs->gr[frreg]; | ||
352 | else | ||
353 | val = 0; | ||
354 | |||
355 | DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg, | ||
356 | val, regs->isr, regs->ior); | ||
357 | |||
358 | |||
359 | __asm__ __volatile__ ( | ||
360 | " mtsp %3, %%sr1\n" | ||
361 | " zdep %2, 28, 2, %%r19\n" | ||
362 | " dep %%r0, 31, 2, %2\n" | ||
363 | " mtsar %%r19\n" | ||
364 | " depwi,z -2, %%sar, 32, %%r19\n" | ||
365 | "1: ldw 0(%%sr1,%2),%%r20\n" | ||
366 | "2: ldw 4(%%sr1,%2),%%r21\n" | ||
367 | " vshd %%r0, %1, %%r22\n" | ||
368 | " vshd %1, %%r0, %%r1\n" | ||
369 | " and %%r20, %%r19, %%r20\n" | ||
370 | " andcm %%r21, %%r19, %%r21\n" | ||
371 | " or %%r22, %%r20, %%r20\n" | ||
372 | " or %%r1, %%r21, %%r21\n" | ||
373 | " stw %%r20,0(%%sr1,%2)\n" | ||
374 | " stw %%r21,4(%%sr1,%2)\n" | ||
375 | " copy %%r0, %0\n" | ||
376 | "3: \n" | ||
377 | " .section .fixup,\"ax\"\n" | ||
378 | "4: ldi -2, %0\n" | ||
379 | FIXUP_BRANCH(3b) | ||
380 | " .previous\n" | ||
381 | " .section __ex_table,\"aw\"\n" | ||
382 | #ifdef __LP64__ | ||
383 | " .dword 1b,4b\n" | ||
384 | " .dword 2b,4b\n" | ||
385 | #else | ||
386 | " .word 1b,4b\n" | ||
387 | " .word 2b,4b\n" | ||
388 | #endif | ||
389 | " .previous\n" | ||
390 | : "=r" (ret) | ||
391 | : "r" (val), "r" (regs->ior), "r" (regs->isr) | ||
392 | : "r19", "r20", "r21", "r22", "r1" ); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | static int emulate_std(struct pt_regs *regs, int frreg, int flop) | ||
397 | { | ||
398 | __u64 val; | ||
399 | int ret; | ||
400 | |||
401 | if (flop) | ||
402 | val = regs->fr[frreg]; | ||
403 | else if (frreg) | ||
404 | val = regs->gr[frreg]; | ||
405 | else | ||
406 | val = 0; | ||
407 | |||
408 | DPRINTF("store r%d (0x%016llx) to " RFMT ":" RFMT " for 8 bytes\n", frreg, | ||
409 | val, regs->isr, regs->ior); | ||
410 | |||
411 | #ifdef CONFIG_PA20 | ||
412 | #ifndef __LP64__ | ||
413 | if (!flop) | ||
414 | return -1; | ||
415 | #endif | ||
416 | __asm__ __volatile__ ( | ||
417 | " mtsp %3, %%sr1\n" | ||
418 | " depd,z %2, 60, 3, %%r19\n" | ||
419 | " depd %%r0, 63, 3, %2\n" | ||
420 | " mtsar %%r19\n" | ||
421 | " depdi,z -2, %%sar, 64, %%r19\n" | ||
422 | "1: ldd 0(%%sr1,%2),%%r20\n" | ||
423 | "2: ldd 8(%%sr1,%2),%%r21\n" | ||
424 | " shrpd %%r0, %1, %%sar, %%r22\n" | ||
425 | " shrpd %1, %%r0, %%sar, %%r1\n" | ||
426 | " and %%r20, %%r19, %%r20\n" | ||
427 | " andcm %%r21, %%r19, %%r21\n" | ||
428 | " or %%r22, %%r20, %%r20\n" | ||
429 | " or %%r1, %%r21, %%r21\n" | ||
430 | "3: std %%r20,0(%%sr1,%2)\n" | ||
431 | "4: std %%r21,8(%%sr1,%2)\n" | ||
432 | " copy %%r0, %0\n" | ||
433 | "5: \n" | ||
434 | " .section .fixup,\"ax\"\n" | ||
435 | "6: ldi -2, %0\n" | ||
436 | FIXUP_BRANCH(5b) | ||
437 | " .previous\n" | ||
438 | " .section __ex_table,\"aw\"\n" | ||
439 | #ifdef __LP64__ | ||
440 | " .dword 1b,6b\n" | ||
441 | " .dword 2b,6b\n" | ||
442 | " .dword 3b,6b\n" | ||
443 | " .dword 4b,6b\n" | ||
444 | #else | ||
445 | " .word 1b,6b\n" | ||
446 | " .word 2b,6b\n" | ||
447 | " .word 3b,6b\n" | ||
448 | " .word 4b,6b\n" | ||
449 | #endif | ||
450 | " .previous\n" | ||
451 | : "=r" (ret) | ||
452 | : "r" (val), "r" (regs->ior), "r" (regs->isr) | ||
453 | : "r19", "r20", "r21", "r22", "r1" ); | ||
454 | #else | ||
455 | { | ||
456 | unsigned long valh=(val>>32),vall=(val&0xffffffffl); | ||
457 | __asm__ __volatile__ ( | ||
458 | " mtsp %4, %%sr1\n" | ||
459 | " zdep %2, 29, 2, %%r19\n" | ||
460 | " dep %%r0, 31, 2, %2\n" | ||
461 | " mtsar %%r19\n" | ||
462 | " zvdepi -2, 32, %%r19\n" | ||
463 | "1: ldw 0(%%sr1,%3),%%r20\n" | ||
464 | "2: ldw 8(%%sr1,%3),%%r21\n" | ||
465 | " vshd %1, %2, %%r1\n" | ||
466 | " vshd %%r0, %1, %1\n" | ||
467 | " vshd %2, %%r0, %2\n" | ||
468 | " and %%r20, %%r19, %%r20\n" | ||
469 | " andcm %%r21, %%r19, %%r21\n" | ||
470 | " or %1, %%r20, %1\n" | ||
471 | " or %2, %%r21, %2\n" | ||
472 | "3: stw %1,0(%%sr1,%1)\n" | ||
473 | "4: stw %%r1,4(%%sr1,%3)\n" | ||
474 | "5: stw %2,8(%%sr1,%3)\n" | ||
475 | " copy %%r0, %0\n" | ||
476 | "6: \n" | ||
477 | " .section .fixup,\"ax\"\n" | ||
478 | "7: ldi -2, %0\n" | ||
479 | FIXUP_BRANCH(6b) | ||
480 | " .previous\n" | ||
481 | " .section __ex_table,\"aw\"\n" | ||
482 | #ifdef __LP64__ | ||
483 | " .dword 1b,7b\n" | ||
484 | " .dword 2b,7b\n" | ||
485 | " .dword 3b,7b\n" | ||
486 | " .dword 4b,7b\n" | ||
487 | " .dword 5b,7b\n" | ||
488 | #else | ||
489 | " .word 1b,7b\n" | ||
490 | " .word 2b,7b\n" | ||
491 | " .word 3b,7b\n" | ||
492 | " .word 4b,7b\n" | ||
493 | " .word 5b,7b\n" | ||
494 | #endif | ||
495 | " .previous\n" | ||
496 | : "=r" (ret) | ||
497 | : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr) | ||
498 | : "r19", "r20", "r21", "r1" ); | ||
499 | } | ||
500 | #endif | ||
501 | |||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | void handle_unaligned(struct pt_regs *regs) | ||
506 | { | ||
507 | static unsigned long unaligned_count = 0; | ||
508 | static unsigned long last_time = 0; | ||
509 | unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0; | ||
510 | int modify = 0; | ||
511 | int ret = ERR_NOTHANDLED; | ||
512 | struct siginfo si; | ||
513 | register int flop=0; /* true if this is a flop */ | ||
514 | |||
515 | /* log a message with pacing */ | ||
516 | if (user_mode(regs)) | ||
517 | { | ||
518 | if (unaligned_count > 5 && jiffies - last_time > 5*HZ) | ||
519 | { | ||
520 | unaligned_count = 0; | ||
521 | last_time = jiffies; | ||
522 | } | ||
523 | if (++unaligned_count < 5) | ||
524 | { | ||
525 | char buf[256]; | ||
526 | sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n", | ||
527 | current->comm, current->pid, regs->ior, regs->iaoq[0]); | ||
528 | printk(KERN_WARNING "%s", buf); | ||
529 | #ifdef DEBUG_UNALIGNED | ||
530 | show_regs(regs); | ||
531 | #endif | ||
532 | } | ||
533 | if (!unaligned_enabled) | ||
534 | goto force_sigbus; | ||
535 | } | ||
536 | |||
537 | /* handle modification - OK, it's ugly, see the instruction manual */ | ||
538 | switch (MAJOR_OP(regs->iir)) | ||
539 | { | ||
540 | case 0x03: | ||
541 | case 0x09: | ||
542 | case 0x0b: | ||
543 | if (regs->iir&0x20) | ||
544 | { | ||
545 | modify = 1; | ||
546 | if (regs->iir&0x1000) /* short loads */ | ||
547 | if (regs->iir&0x200) | ||
548 | newbase += IM5_3(regs->iir); | ||
549 | else | ||
550 | newbase += IM5_2(regs->iir); | ||
551 | else if (regs->iir&0x2000) /* scaled indexed */ | ||
552 | { | ||
553 | int shift=0; | ||
554 | switch (regs->iir & OPCODE1_MASK) | ||
555 | { | ||
556 | case OPCODE_LDH_I: | ||
557 | shift= 1; break; | ||
558 | case OPCODE_LDW_I: | ||
559 | shift= 2; break; | ||
560 | case OPCODE_LDD_I: | ||
561 | case OPCODE_LDDA_I: | ||
562 | shift= 3; break; | ||
563 | } | ||
564 | newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift; | ||
565 | } else /* simple indexed */ | ||
566 | newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0); | ||
567 | } | ||
568 | break; | ||
569 | case 0x13: | ||
570 | case 0x1b: | ||
571 | modify = 1; | ||
572 | newbase += IM14(regs->iir); | ||
573 | break; | ||
574 | case 0x14: | ||
575 | case 0x1c: | ||
576 | if (regs->iir&8) | ||
577 | { | ||
578 | modify = 1; | ||
579 | newbase += IM14(regs->iir&~0xe); | ||
580 | } | ||
581 | break; | ||
582 | case 0x16: | ||
583 | case 0x1e: | ||
584 | modify = 1; | ||
585 | newbase += IM14(regs->iir&6); | ||
586 | break; | ||
587 | case 0x17: | ||
588 | case 0x1f: | ||
589 | if (regs->iir&4) | ||
590 | { | ||
591 | modify = 1; | ||
592 | newbase += IM14(regs->iir&~4); | ||
593 | } | ||
594 | break; | ||
595 | } | ||
596 | |||
597 | /* TODO: make this cleaner... */ | ||
598 | switch (regs->iir & OPCODE1_MASK) | ||
599 | { | ||
600 | case OPCODE_LDH_I: | ||
601 | case OPCODE_LDH_S: | ||
602 | ret = emulate_ldh(regs, R3(regs->iir)); | ||
603 | break; | ||
604 | |||
605 | case OPCODE_LDW_I: | ||
606 | case OPCODE_LDWA_I: | ||
607 | case OPCODE_LDW_S: | ||
608 | case OPCODE_LDWA_S: | ||
609 | ret = emulate_ldw(regs, R3(regs->iir),0); | ||
610 | break; | ||
611 | |||
612 | case OPCODE_STH: | ||
613 | ret = emulate_sth(regs, R2(regs->iir)); | ||
614 | break; | ||
615 | |||
616 | case OPCODE_STW: | ||
617 | case OPCODE_STWA: | ||
618 | ret = emulate_stw(regs, R2(regs->iir),0); | ||
619 | break; | ||
620 | |||
621 | #ifdef CONFIG_PA20 | ||
622 | case OPCODE_LDD_I: | ||
623 | case OPCODE_LDDA_I: | ||
624 | case OPCODE_LDD_S: | ||
625 | case OPCODE_LDDA_S: | ||
626 | ret = emulate_ldd(regs, R3(regs->iir),0); | ||
627 | break; | ||
628 | |||
629 | case OPCODE_STD: | ||
630 | case OPCODE_STDA: | ||
631 | ret = emulate_std(regs, R2(regs->iir),0); | ||
632 | break; | ||
633 | #endif | ||
634 | |||
635 | case OPCODE_FLDWX: | ||
636 | case OPCODE_FLDWS: | ||
637 | case OPCODE_FLDWXR: | ||
638 | case OPCODE_FLDWSR: | ||
639 | flop=1; | ||
640 | ret = emulate_ldw(regs,FR3(regs->iir),1); | ||
641 | break; | ||
642 | |||
643 | case OPCODE_FLDDX: | ||
644 | case OPCODE_FLDDS: | ||
645 | flop=1; | ||
646 | ret = emulate_ldd(regs,R3(regs->iir),1); | ||
647 | break; | ||
648 | |||
649 | case OPCODE_FSTWX: | ||
650 | case OPCODE_FSTWS: | ||
651 | case OPCODE_FSTWXR: | ||
652 | case OPCODE_FSTWSR: | ||
653 | flop=1; | ||
654 | ret = emulate_stw(regs,FR3(regs->iir),1); | ||
655 | break; | ||
656 | |||
657 | case OPCODE_FSTDX: | ||
658 | case OPCODE_FSTDS: | ||
659 | flop=1; | ||
660 | ret = emulate_std(regs,R3(regs->iir),1); | ||
661 | break; | ||
662 | |||
663 | case OPCODE_LDCD_I: | ||
664 | case OPCODE_LDCW_I: | ||
665 | case OPCODE_LDCD_S: | ||
666 | case OPCODE_LDCW_S: | ||
667 | ret = ERR_NOTHANDLED; /* "undefined", but lets kill them. */ | ||
668 | break; | ||
669 | } | ||
670 | #ifdef CONFIG_PA20 | ||
671 | switch (regs->iir & OPCODE2_MASK) | ||
672 | { | ||
673 | case OPCODE_FLDD_L: | ||
674 | flop=1; | ||
675 | ret = emulate_ldd(regs,R2(regs->iir),1); | ||
676 | break; | ||
677 | case OPCODE_FSTD_L: | ||
678 | flop=1; | ||
679 | ret = emulate_std(regs, R2(regs->iir),1); | ||
680 | break; | ||
681 | |||
682 | #ifdef CONFIG_PA20 | ||
683 | case OPCODE_LDD_L: | ||
684 | ret = emulate_ldd(regs, R2(regs->iir),0); | ||
685 | break; | ||
686 | case OPCODE_STD_L: | ||
687 | ret = emulate_std(regs, R2(regs->iir),0); | ||
688 | break; | ||
689 | #endif | ||
690 | } | ||
691 | #endif | ||
692 | switch (regs->iir & OPCODE3_MASK) | ||
693 | { | ||
694 | case OPCODE_FLDW_L: | ||
695 | flop=1; | ||
696 | ret = emulate_ldw(regs, R2(regs->iir),0); | ||
697 | break; | ||
698 | case OPCODE_LDW_M: | ||
699 | ret = emulate_ldw(regs, R2(regs->iir),1); | ||
700 | break; | ||
701 | |||
702 | case OPCODE_FSTW_L: | ||
703 | flop=1; | ||
704 | ret = emulate_stw(regs, R2(regs->iir),1); | ||
705 | break; | ||
706 | case OPCODE_STW_M: | ||
707 | ret = emulate_stw(regs, R2(regs->iir),0); | ||
708 | break; | ||
709 | } | ||
710 | switch (regs->iir & OPCODE4_MASK) | ||
711 | { | ||
712 | case OPCODE_LDH_L: | ||
713 | ret = emulate_ldh(regs, R2(regs->iir)); | ||
714 | break; | ||
715 | case OPCODE_LDW_L: | ||
716 | case OPCODE_LDWM: | ||
717 | ret = emulate_ldw(regs, R2(regs->iir),0); | ||
718 | break; | ||
719 | case OPCODE_STH_L: | ||
720 | ret = emulate_sth(regs, R2(regs->iir)); | ||
721 | break; | ||
722 | case OPCODE_STW_L: | ||
723 | case OPCODE_STWM: | ||
724 | ret = emulate_stw(regs, R2(regs->iir),0); | ||
725 | break; | ||
726 | } | ||
727 | |||
728 | if (modify && R1(regs->iir)) | ||
729 | regs->gr[R1(regs->iir)] = newbase; | ||
730 | |||
731 | |||
732 | if (ret == ERR_NOTHANDLED) | ||
733 | printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir); | ||
734 | |||
735 | DPRINTF("ret = %d\n", ret); | ||
736 | |||
737 | if (ret) | ||
738 | { | ||
739 | printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret); | ||
740 | die_if_kernel("Unaligned data reference", regs, 28); | ||
741 | |||
742 | if (ret == ERR_PAGEFAULT) | ||
743 | { | ||
744 | si.si_signo = SIGSEGV; | ||
745 | si.si_errno = 0; | ||
746 | si.si_code = SEGV_MAPERR; | ||
747 | si.si_addr = (void __user *)regs->ior; | ||
748 | force_sig_info(SIGSEGV, &si, current); | ||
749 | } | ||
750 | else | ||
751 | { | ||
752 | force_sigbus: | ||
753 | /* couldn't handle it ... */ | ||
754 | si.si_signo = SIGBUS; | ||
755 | si.si_errno = 0; | ||
756 | si.si_code = BUS_ADRALN; | ||
757 | si.si_addr = (void __user *)regs->ior; | ||
758 | force_sig_info(SIGBUS, &si, current); | ||
759 | } | ||
760 | |||
761 | return; | ||
762 | } | ||
763 | |||
764 | /* else we handled it, let life go on. */ | ||
765 | regs->gr[0]|=PSW_N; | ||
766 | } | ||
767 | |||
768 | /* | ||
769 | * NB: check_unaligned() is only used for PCXS processors right | ||
770 | * now, so we only check for PA1.1 encodings at this point. | ||
771 | */ | ||
772 | |||
773 | int | ||
774 | check_unaligned(struct pt_regs *regs) | ||
775 | { | ||
776 | unsigned long align_mask; | ||
777 | |||
778 | /* Get alignment mask */ | ||
779 | |||
780 | align_mask = 0UL; | ||
781 | switch (regs->iir & OPCODE1_MASK) { | ||
782 | |||
783 | case OPCODE_LDH_I: | ||
784 | case OPCODE_LDH_S: | ||
785 | case OPCODE_STH: | ||
786 | align_mask = 1UL; | ||
787 | break; | ||
788 | |||
789 | case OPCODE_LDW_I: | ||
790 | case OPCODE_LDWA_I: | ||
791 | case OPCODE_LDW_S: | ||
792 | case OPCODE_LDWA_S: | ||
793 | case OPCODE_STW: | ||
794 | case OPCODE_STWA: | ||
795 | align_mask = 3UL; | ||
796 | break; | ||
797 | |||
798 | default: | ||
799 | switch (regs->iir & OPCODE4_MASK) { | ||
800 | case OPCODE_LDH_L: | ||
801 | case OPCODE_STH_L: | ||
802 | align_mask = 1UL; | ||
803 | break; | ||
804 | case OPCODE_LDW_L: | ||
805 | case OPCODE_LDWM: | ||
806 | case OPCODE_STW_L: | ||
807 | case OPCODE_STWM: | ||
808 | align_mask = 3UL; | ||
809 | break; | ||
810 | } | ||
811 | break; | ||
812 | } | ||
813 | |||
814 | return (int)(regs->ior & align_mask); | ||
815 | } | ||
816 | |||
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c new file mode 100644 index 000000000000..db141108412e --- /dev/null +++ b/arch/parisc/kernel/unwind.c | |||
@@ -0,0 +1,393 @@ | |||
1 | /* | ||
2 | * Kernel unwinding support | ||
3 | * | ||
4 | * (c) 2002-2004 Randolph Chung <tausq@debian.org> | ||
5 | * | ||
6 | * Derived partially from the IA64 implementation. The PA-RISC | ||
7 | * Runtime Architecture Document is also a useful reference to | ||
8 | * understand what is happening here | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/kallsyms.h> | ||
16 | |||
17 | #include <asm/uaccess.h> | ||
18 | #include <asm/assembly.h> | ||
19 | |||
20 | #include <asm/unwind.h> | ||
21 | |||
22 | /* #define DEBUG 1 */ | ||
23 | #ifdef DEBUG | ||
24 | #define dbg(x...) printk(x) | ||
25 | #else | ||
26 | #define dbg(x...) | ||
27 | #endif | ||
28 | |||
29 | extern struct unwind_table_entry __start___unwind[]; | ||
30 | extern struct unwind_table_entry __stop___unwind[]; | ||
31 | |||
32 | static spinlock_t unwind_lock; | ||
33 | /* | ||
34 | * the kernel unwind block is not dynamically allocated so that | ||
35 | * we can call unwind_init as early in the bootup process as | ||
36 | * possible (before the slab allocator is initialized) | ||
37 | */ | ||
38 | static struct unwind_table kernel_unwind_table; | ||
39 | static LIST_HEAD(unwind_tables); | ||
40 | |||
41 | static inline const struct unwind_table_entry * | ||
42 | find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr) | ||
43 | { | ||
44 | const struct unwind_table_entry *e = NULL; | ||
45 | unsigned long lo, hi, mid; | ||
46 | |||
47 | lo = 0; | ||
48 | hi = table->length - 1; | ||
49 | |||
50 | while (lo <= hi) { | ||
51 | mid = (hi - lo) / 2 + lo; | ||
52 | e = &table->table[mid]; | ||
53 | if (addr < e->region_start) | ||
54 | hi = mid - 1; | ||
55 | else if (addr > e->region_end) | ||
56 | lo = mid + 1; | ||
57 | else | ||
58 | return e; | ||
59 | } | ||
60 | |||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | static const struct unwind_table_entry * | ||
65 | find_unwind_entry(unsigned long addr) | ||
66 | { | ||
67 | struct unwind_table *table; | ||
68 | const struct unwind_table_entry *e = NULL; | ||
69 | |||
70 | if (addr >= kernel_unwind_table.start && | ||
71 | addr <= kernel_unwind_table.end) | ||
72 | e = find_unwind_entry_in_table(&kernel_unwind_table, addr); | ||
73 | else | ||
74 | list_for_each_entry(table, &unwind_tables, list) { | ||
75 | if (addr >= table->start && | ||
76 | addr <= table->end) | ||
77 | e = find_unwind_entry_in_table(table, addr); | ||
78 | if (e) | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | return e; | ||
83 | } | ||
84 | |||
85 | static void | ||
86 | unwind_table_init(struct unwind_table *table, const char *name, | ||
87 | unsigned long base_addr, unsigned long gp, | ||
88 | void *table_start, void *table_end) | ||
89 | { | ||
90 | struct unwind_table_entry *start = table_start; | ||
91 | struct unwind_table_entry *end = | ||
92 | (struct unwind_table_entry *)table_end - 1; | ||
93 | |||
94 | table->name = name; | ||
95 | table->base_addr = base_addr; | ||
96 | table->gp = gp; | ||
97 | table->start = base_addr + start->region_start; | ||
98 | table->end = base_addr + end->region_end; | ||
99 | table->table = (struct unwind_table_entry *)table_start; | ||
100 | table->length = end - start + 1; | ||
101 | INIT_LIST_HEAD(&table->list); | ||
102 | |||
103 | for (; start <= end; start++) { | ||
104 | if (start < end && | ||
105 | start->region_end > (start+1)->region_start) { | ||
106 | printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1); | ||
107 | } | ||
108 | |||
109 | start->region_start += base_addr; | ||
110 | start->region_end += base_addr; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | static void | ||
115 | unwind_table_sort(struct unwind_table_entry *start, | ||
116 | struct unwind_table_entry *finish) | ||
117 | { | ||
118 | struct unwind_table_entry el, *p, *q; | ||
119 | |||
120 | for (p = start + 1; p < finish; ++p) { | ||
121 | if (p[0].region_start < p[-1].region_start) { | ||
122 | el = *p; | ||
123 | q = p; | ||
124 | do { | ||
125 | q[0] = q[-1]; | ||
126 | --q; | ||
127 | } while (q > start && | ||
128 | el.region_start < q[-1].region_start); | ||
129 | *q = el; | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | struct unwind_table * | ||
135 | unwind_table_add(const char *name, unsigned long base_addr, | ||
136 | unsigned long gp, | ||
137 | void *start, void *end) | ||
138 | { | ||
139 | struct unwind_table *table; | ||
140 | unsigned long flags; | ||
141 | struct unwind_table_entry *s = (struct unwind_table_entry *)start; | ||
142 | struct unwind_table_entry *e = (struct unwind_table_entry *)end; | ||
143 | |||
144 | unwind_table_sort(s, e); | ||
145 | |||
146 | table = kmalloc(sizeof(struct unwind_table), GFP_USER); | ||
147 | if (table == NULL) | ||
148 | return NULL; | ||
149 | unwind_table_init(table, name, base_addr, gp, start, end); | ||
150 | spin_lock_irqsave(&unwind_lock, flags); | ||
151 | list_add_tail(&table->list, &unwind_tables); | ||
152 | spin_unlock_irqrestore(&unwind_lock, flags); | ||
153 | |||
154 | return table; | ||
155 | } | ||
156 | |||
157 | void unwind_table_remove(struct unwind_table *table) | ||
158 | { | ||
159 | unsigned long flags; | ||
160 | |||
161 | spin_lock_irqsave(&unwind_lock, flags); | ||
162 | list_del(&table->list); | ||
163 | spin_unlock_irqrestore(&unwind_lock, flags); | ||
164 | |||
165 | kfree(table); | ||
166 | } | ||
167 | |||
168 | /* Called from setup_arch to import the kernel unwind info */ | ||
169 | static int unwind_init(void) | ||
170 | { | ||
171 | long start, stop; | ||
172 | register unsigned long gp __asm__ ("r27"); | ||
173 | |||
174 | start = (long)&__start___unwind[0]; | ||
175 | stop = (long)&__stop___unwind[0]; | ||
176 | |||
177 | spin_lock_init(&unwind_lock); | ||
178 | |||
179 | printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n", | ||
180 | start, stop, | ||
181 | (stop - start) / sizeof(struct unwind_table_entry)); | ||
182 | |||
183 | unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START, | ||
184 | gp, | ||
185 | &__start___unwind[0], &__stop___unwind[0]); | ||
186 | #if 0 | ||
187 | { | ||
188 | int i; | ||
189 | for (i = 0; i < 10; i++) | ||
190 | { | ||
191 | printk("region 0x%x-0x%x\n", | ||
192 | __start___unwind[i].region_start, | ||
193 | __start___unwind[i].region_end); | ||
194 | } | ||
195 | } | ||
196 | #endif | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static void unwind_frame_regs(struct unwind_frame_info *info) | ||
201 | { | ||
202 | const struct unwind_table_entry *e; | ||
203 | unsigned long npc; | ||
204 | unsigned int insn; | ||
205 | long frame_size = 0; | ||
206 | int looking_for_rp, rpoffset = 0; | ||
207 | |||
208 | e = find_unwind_entry(info->ip); | ||
209 | if (e == NULL) { | ||
210 | unsigned long sp; | ||
211 | extern char _stext[], _etext[]; | ||
212 | |||
213 | dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip); | ||
214 | |||
215 | #ifdef CONFIG_KALLSYMS | ||
216 | /* Handle some frequent special cases.... */ | ||
217 | { | ||
218 | char symname[KSYM_NAME_LEN+1]; | ||
219 | char *modname; | ||
220 | unsigned long symsize, offset; | ||
221 | |||
222 | kallsyms_lookup(info->ip, &symsize, &offset, | ||
223 | &modname, symname); | ||
224 | |||
225 | dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname); | ||
226 | |||
227 | if (strcmp(symname, "_switch_to_ret") == 0) { | ||
228 | info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; | ||
229 | info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); | ||
230 | dbg("_switch_to_ret @ %lx - setting " | ||
231 | "prev_sp=%lx prev_ip=%lx\n", | ||
232 | info->ip, info->prev_sp, | ||
233 | info->prev_ip); | ||
234 | return; | ||
235 | } else if (strcmp(symname, "ret_from_kernel_thread") == 0 || | ||
236 | strcmp(symname, "syscall_exit") == 0) { | ||
237 | info->prev_ip = info->prev_sp = 0; | ||
238 | return; | ||
239 | } | ||
240 | } | ||
241 | #endif | ||
242 | |||
243 | /* Since we are doing the unwinding blind, we don't know if | ||
244 | we are adjusting the stack correctly or extracting the rp | ||
245 | correctly. The rp is checked to see if it belongs to the | ||
246 | kernel text section, if not we assume we don't have a | ||
247 | correct stack frame and we continue to unwind the stack. | ||
248 | This is not quite correct, and will fail for loadable | ||
249 | modules. */ | ||
250 | sp = info->sp & ~63; | ||
251 | do { | ||
252 | unsigned long tmp; | ||
253 | |||
254 | info->prev_sp = sp - 64; | ||
255 | info->prev_ip = 0; | ||
256 | if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) | ||
257 | break; | ||
258 | info->prev_ip = tmp; | ||
259 | sp = info->prev_sp; | ||
260 | } while (info->prev_ip < (unsigned long)_stext || | ||
261 | info->prev_ip > (unsigned long)_etext); | ||
262 | |||
263 | info->rp = 0; | ||
264 | |||
265 | dbg("analyzing func @ %lx with no unwind info, setting " | ||
266 | "prev_sp=%lx prev_ip=%lx\n", info->ip, | ||
267 | info->prev_sp, info->prev_ip); | ||
268 | } else { | ||
269 | dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, " | ||
270 | "Save_RP = %d, Millicode = %d size = %u\n", | ||
271 | e->region_start, e->region_end, e->Save_SP, e->Save_RP, | ||
272 | e->Millicode, e->Total_frame_size); | ||
273 | |||
274 | looking_for_rp = e->Save_RP; | ||
275 | |||
276 | for (npc = e->region_start; | ||
277 | (frame_size < (e->Total_frame_size << 3) || | ||
278 | looking_for_rp) && | ||
279 | npc < info->ip; | ||
280 | npc += 4) { | ||
281 | |||
282 | insn = *(unsigned int *)npc; | ||
283 | |||
284 | if ((insn & 0xffffc000) == 0x37de0000 || | ||
285 | (insn & 0xffe00000) == 0x6fc00000) { | ||
286 | /* ldo X(sp), sp, or stwm X,D(sp) */ | ||
287 | frame_size += (insn & 0x1 ? -1 << 13 : 0) | | ||
288 | ((insn & 0x3fff) >> 1); | ||
289 | dbg("analyzing func @ %lx, insn=%08x @ " | ||
290 | "%lx, frame_size = %ld\n", info->ip, | ||
291 | insn, npc, frame_size); | ||
292 | } else if ((insn & 0xffe00008) == 0x73c00008) { | ||
293 | /* std,ma X,D(sp) */ | ||
294 | frame_size += (insn & 0x1 ? -1 << 13 : 0) | | ||
295 | (((insn >> 4) & 0x3ff) << 3); | ||
296 | dbg("analyzing func @ %lx, insn=%08x @ " | ||
297 | "%lx, frame_size = %ld\n", info->ip, | ||
298 | insn, npc, frame_size); | ||
299 | } else if (insn == 0x6bc23fd9) { | ||
300 | /* stw rp,-20(sp) */ | ||
301 | rpoffset = 20; | ||
302 | looking_for_rp = 0; | ||
303 | dbg("analyzing func @ %lx, insn=stw rp," | ||
304 | "-20(sp) @ %lx\n", info->ip, npc); | ||
305 | } else if (insn == 0x0fc212c1) { | ||
306 | /* std rp,-16(sr0,sp) */ | ||
307 | rpoffset = 16; | ||
308 | looking_for_rp = 0; | ||
309 | dbg("analyzing func @ %lx, insn=std rp," | ||
310 | "-16(sp) @ %lx\n", info->ip, npc); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | info->prev_sp = info->sp - frame_size; | ||
315 | if (e->Millicode) | ||
316 | info->rp = info->r31; | ||
317 | else if (rpoffset) | ||
318 | info->rp = *(unsigned long *)(info->prev_sp - rpoffset); | ||
319 | info->prev_ip = info->rp; | ||
320 | info->rp = 0; | ||
321 | |||
322 | dbg("analyzing func @ %lx, setting prev_sp=%lx " | ||
323 | "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, | ||
324 | info->prev_ip, npc); | ||
325 | } | ||
326 | } | ||
327 | |||
328 | void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, | ||
329 | struct pt_regs *regs) | ||
330 | { | ||
331 | memset(info, 0, sizeof(struct unwind_frame_info)); | ||
332 | info->t = t; | ||
333 | info->sp = regs->gr[30]; | ||
334 | info->ip = regs->iaoq[0]; | ||
335 | info->rp = regs->gr[2]; | ||
336 | info->r31 = regs->gr[31]; | ||
337 | |||
338 | dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", | ||
339 | t ? (int)t->pid : -1, info->sp, info->ip); | ||
340 | } | ||
341 | |||
342 | void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t) | ||
343 | { | ||
344 | struct pt_regs *r = &t->thread.regs; | ||
345 | struct pt_regs *r2; | ||
346 | |||
347 | r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL); | ||
348 | if (!r2) | ||
349 | return; | ||
350 | *r2 = *r; | ||
351 | r2->gr[30] = r->ksp; | ||
352 | r2->iaoq[0] = r->kpc; | ||
353 | unwind_frame_init(info, t, r2); | ||
354 | kfree(r2); | ||
355 | } | ||
356 | |||
357 | void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs) | ||
358 | { | ||
359 | unwind_frame_init(info, current, regs); | ||
360 | } | ||
361 | |||
362 | int unwind_once(struct unwind_frame_info *next_frame) | ||
363 | { | ||
364 | unwind_frame_regs(next_frame); | ||
365 | |||
366 | if (next_frame->prev_sp == 0 || | ||
367 | next_frame->prev_ip == 0) | ||
368 | return -1; | ||
369 | |||
370 | next_frame->sp = next_frame->prev_sp; | ||
371 | next_frame->ip = next_frame->prev_ip; | ||
372 | next_frame->prev_sp = 0; | ||
373 | next_frame->prev_ip = 0; | ||
374 | |||
375 | dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", | ||
376 | next_frame->t ? (int)next_frame->t->pid : -1, | ||
377 | next_frame->sp, next_frame->ip); | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | int unwind_to_user(struct unwind_frame_info *info) | ||
383 | { | ||
384 | int ret; | ||
385 | |||
386 | do { | ||
387 | ret = unwind_once(info); | ||
388 | } while (!ret && !(info->ip & 3)); | ||
389 | |||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | module_init(unwind_init); | ||
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..e5fac3e08c7a --- /dev/null +++ b/arch/parisc/kernel/vmlinux.lds.S | |||
@@ -0,0 +1,207 @@ | |||
1 | /* Kernel link layout for various "sections" | ||
2 | * | ||
3 | * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org> | ||
4 | * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org> | ||
5 | * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org> | ||
6 | * Copyright (C) 2000 Michael Ang <mang with subcarrier.org> | ||
7 | * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> | ||
8 | * Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | */ | ||
25 | #include <linux/config.h> | ||
26 | #include <asm-generic/vmlinux.lds.h> | ||
27 | /* needed for the processor specific cache alignment size */ | ||
28 | #include <asm/cache.h> | ||
29 | #include <asm/page.h> | ||
30 | |||
31 | /* ld script to make hppa Linux kernel */ | ||
32 | #ifndef CONFIG_64BIT | ||
33 | OUTPUT_FORMAT("elf32-hppa-linux") | ||
34 | OUTPUT_ARCH(hppa) | ||
35 | #else | ||
36 | OUTPUT_FORMAT("elf64-hppa-linux") | ||
37 | OUTPUT_ARCH(hppa:hppa2.0w) | ||
38 | #endif | ||
39 | |||
40 | ENTRY(_stext) | ||
41 | #ifndef CONFIG_64BIT | ||
42 | jiffies = jiffies_64 + 4; | ||
43 | #else | ||
44 | jiffies = jiffies_64; | ||
45 | #endif | ||
46 | SECTIONS | ||
47 | { | ||
48 | |||
49 | . = KERNEL_BINARY_TEXT_START; | ||
50 | |||
51 | _text = .; /* Text and read-only data */ | ||
52 | .text ALIGN(16) : { | ||
53 | *(.text) | ||
54 | SCHED_TEXT | ||
55 | LOCK_TEXT | ||
56 | *(.text.do_softirq) | ||
57 | *(.text.sys_exit) | ||
58 | *(.text.do_sigaltstack) | ||
59 | *(.text.do_fork) | ||
60 | *(.text.*) | ||
61 | *(.fixup) | ||
62 | *(.lock.text) /* out-of-line lock text */ | ||
63 | *(.gnu.warning) | ||
64 | } = 0 | ||
65 | |||
66 | _etext = .; /* End of text section */ | ||
67 | |||
68 | RODATA | ||
69 | |||
70 | /* writeable */ | ||
71 | . = ALIGN(4096); /* Make sure this is paged aligned so | ||
72 | that we can properly leave these | ||
73 | as writable */ | ||
74 | data_start = .; | ||
75 | |||
76 | . = ALIGN(16); /* Exception table */ | ||
77 | __start___ex_table = .; | ||
78 | __ex_table : { *(__ex_table) } | ||
79 | __stop___ex_table = .; | ||
80 | |||
81 | __start___unwind = .; /* unwind info */ | ||
82 | .PARISC.unwind : { *(.PARISC.unwind) } | ||
83 | __stop___unwind = .; | ||
84 | |||
85 | .data : { /* Data */ | ||
86 | *(.data) | ||
87 | *(.data.vm0.pmd) | ||
88 | *(.data.vm0.pgd) | ||
89 | *(.data.vm0.pte) | ||
90 | CONSTRUCTORS | ||
91 | } | ||
92 | |||
93 | . = ALIGN(4096); | ||
94 | /* nosave data is really only used for software suspend...it's here | ||
95 | * just in case we ever implement it */ | ||
96 | __nosave_begin = .; | ||
97 | .data_nosave : { *(.data.nosave) } | ||
98 | . = ALIGN(4096); | ||
99 | __nosave_end = .; | ||
100 | |||
101 | . = ALIGN(L1_CACHE_BYTES); | ||
102 | .data.cacheline_aligned : { *(.data.cacheline_aligned) } | ||
103 | |||
104 | /* PA-RISC locks requires 16-byte alignment */ | ||
105 | . = ALIGN(16); | ||
106 | .data.lock_aligned : { *(.data.lock_aligned) } | ||
107 | |||
108 | _edata = .; /* End of data section */ | ||
109 | |||
110 | . = ALIGN(16384); /* init_task */ | ||
111 | .data.init_task : { *(.data.init_task) } | ||
112 | |||
113 | /* The interrupt stack is currently partially coded, but not yet | ||
114 | * implemented */ | ||
115 | . = ALIGN(16384); | ||
116 | init_istack : { *(init_istack) } | ||
117 | |||
118 | #ifdef CONFIG_64BIT | ||
119 | . = ALIGN(16); /* Linkage tables */ | ||
120 | .opd : { *(.opd) } PROVIDE (__gp = .); | ||
121 | .plt : { *(.plt) } | ||
122 | .dlt : { *(.dlt) } | ||
123 | #endif | ||
124 | |||
125 | . = ALIGN(16384); | ||
126 | __init_begin = .; | ||
127 | .init.text : { | ||
128 | _sinittext = .; | ||
129 | *(.init.text) | ||
130 | _einittext = .; | ||
131 | } | ||
132 | .init.data : { *(.init.data) } | ||
133 | . = ALIGN(16); | ||
134 | __setup_start = .; | ||
135 | .init.setup : { *(.init.setup) } | ||
136 | __setup_end = .; | ||
137 | __initcall_start = .; | ||
138 | .initcall.init : { | ||
139 | *(.initcall1.init) | ||
140 | *(.initcall2.init) | ||
141 | *(.initcall3.init) | ||
142 | *(.initcall4.init) | ||
143 | *(.initcall5.init) | ||
144 | *(.initcall6.init) | ||
145 | *(.initcall7.init) | ||
146 | } | ||
147 | __initcall_end = .; | ||
148 | __con_initcall_start = .; | ||
149 | .con_initcall.init : { *(.con_initcall.init) } | ||
150 | __con_initcall_end = .; | ||
151 | SECURITY_INIT | ||
152 | /* alternate instruction replacement. This is a mechanism x86 uses | ||
153 | * to detect the CPU type and replace generic instruction sequences | ||
154 | * with CPU specific ones. We don't currently do this in PA, but | ||
155 | * it seems like a good idea... */ | ||
156 | . = ALIGN(4); | ||
157 | __alt_instructions = .; | ||
158 | .altinstructions : { *(.altinstructions) } | ||
159 | __alt_instructions_end = .; | ||
160 | .altinstr_replacement : { *(.altinstr_replacement) } | ||
161 | /* .exit.text is discard at runtime, not link time, to deal with references | ||
162 | from .altinstructions and .eh_frame */ | ||
163 | .exit.text : { *(.exit.text) } | ||
164 | .exit.data : { *(.exit.data) } | ||
165 | . = ALIGN(4096); | ||
166 | __initramfs_start = .; | ||
167 | .init.ramfs : { *(.init.ramfs) } | ||
168 | __initramfs_end = .; | ||
169 | . = ALIGN(32); | ||
170 | __per_cpu_start = .; | ||
171 | .data.percpu : { *(.data.percpu) } | ||
172 | __per_cpu_end = .; | ||
173 | . = ALIGN(4096); | ||
174 | __init_end = .; | ||
175 | /* freed after init ends here */ | ||
176 | |||
177 | __bss_start = .; /* BSS */ | ||
178 | .bss : { *(.bss) *(COMMON) } | ||
179 | __bss_stop = .; | ||
180 | |||
181 | _end = . ; | ||
182 | |||
183 | /* Sections to be discarded */ | ||
184 | /DISCARD/ : { | ||
185 | *(.exitcall.exit) | ||
186 | #ifdef CONFIG_64BIT | ||
187 | /* temporary hack until binutils is fixed to not emit these | ||
188 | for static binaries */ | ||
189 | *(.interp) | ||
190 | *(.dynsym) | ||
191 | *(.dynstr) | ||
192 | *(.dynamic) | ||
193 | *(.hash) | ||
194 | #endif | ||
195 | } | ||
196 | |||
197 | /* Stabs debugging sections. */ | ||
198 | .stab 0 : { *(.stab) } | ||
199 | .stabstr 0 : { *(.stabstr) } | ||
200 | .stab.excl 0 : { *(.stab.excl) } | ||
201 | .stab.exclstr 0 : { *(.stab.exclstr) } | ||
202 | .stab.index 0 : { *(.stab.index) } | ||
203 | .stab.indexstr 0 : { *(.stab.indexstr) } | ||
204 | .comment 0 : { *(.comment) } | ||
205 | .note 0 : { *(.note) } | ||
206 | |||
207 | } | ||