aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/Makefile7
-rw-r--r--arch/powerpc/kernel/align.c530
-rw-r--r--arch/powerpc/kernel/idle_64.c121
-rw-r--r--arch/powerpc/kernel/misc_32.S8
-rw-r--r--arch/powerpc/kernel/nvram_64.c742
-rw-r--r--arch/powerpc/kernel/pci_64.c70
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c7
-rw-r--r--arch/powerpc/kernel/rtas-rtc.c6
-rw-r--r--arch/powerpc/kernel/rtas_pci.c68
-rw-r--r--arch/powerpc/kernel/setup-common.c1
-rw-r--r--arch/powerpc/kernel/smp.c7
-rw-r--r--arch/powerpc/kernel/time.c28
-rw-r--r--arch/powerpc/kernel/vdso32/cacheflush.S2
-rw-r--r--arch/powerpc/kernel/vdso32/datapage.S3
-rw-r--r--arch/powerpc/kernel/vdso32/gettimeofday.S4
-rw-r--r--arch/powerpc/kernel/vdso64/cacheflush.S2
-rw-r--r--arch/powerpc/kernel/vdso64/datapage.S3
-rw-r--r--arch/powerpc/kernel/vdso64/gettimeofday.S4
18 files changed, 1528 insertions, 85 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 4970e3721a84..9ed551b6c172 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,12 +12,12 @@ CFLAGS_btext.o += -fPIC
12endif 12endif
13 13
14obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ 14obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
15 irq.o signal_32.o pmc.o vdso.o 15 irq.o align.o signal_32.o pmc.o vdso.o
16obj-y += vdso32/ 16obj-y += vdso32/
17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ 17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
18 signal_64.o ptrace32.o systbl.o \ 18 signal_64.o ptrace32.o systbl.o \
19 paca.o ioctl32.o cpu_setup_power4.o \ 19 paca.o ioctl32.o cpu_setup_power4.o \
20 firmware.o sysfs.o udbg.o 20 firmware.o sysfs.o udbg.o idle_64.o
21obj-$(CONFIG_PPC64) += vdso64/ 21obj-$(CONFIG_PPC64) += vdso64/
22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o 22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
23obj-$(CONFIG_POWER4) += idle_power4.o 23obj-$(CONFIG_POWER4) += idle_power4.o
@@ -35,6 +35,7 @@ obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o
35obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o 35obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
36udbgscc-$(CONFIG_PPC64) := udbg_scc.o 36udbgscc-$(CONFIG_PPC64) := udbg_scc.o
37obj-$(CONFIG_PPC_PMAC) += $(udbgscc-y) 37obj-$(CONFIG_PPC_PMAC) += $(udbgscc-y)
38obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
38 39
39ifeq ($(CONFIG_PPC_MERGE),y) 40ifeq ($(CONFIG_PPC_MERGE),y)
40 41
@@ -78,5 +79,7 @@ smpobj-$(CONFIG_SMP) += smp.o
78 79
79endif 80endif
80 81
82obj-$(CONFIG_PPC64) += $(obj64-y)
83
81extra-$(CONFIG_PPC_FPU) += fpu.o 84extra-$(CONFIG_PPC_FPU) += fpu.o
82extra-$(CONFIG_PPC64) += entry_64.o 85extra-$(CONFIG_PPC64) += entry_64.o
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
new file mode 100644
index 000000000000..faaec9c6f78f
--- /dev/null
+++ b/arch/powerpc/kernel/align.c
@@ -0,0 +1,530 @@
1/* align.c - handle alignment exceptions for the Power PC.
2 *
3 * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
4 * Copyright (c) 1998-1999 TiVo, Inc.
5 * PowerPC 403GCX modifications.
6 * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
7 * PowerPC 403GCX/405GP modifications.
8 * Copyright (c) 2001-2002 PPC64 team, IBM Corp
9 * 64-bit and Power4 support
10 * Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp
11 * <benh@kernel.crashing.org>
12 * Merge ppc32 and ppc64 implementations
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
18 */
19
20#include <linux/kernel.h>
21#include <linux/mm.h>
22#include <asm/processor.h>
23#include <asm/uaccess.h>
24#include <asm/system.h>
25#include <asm/cache.h>
26#include <asm/cputable.h>
27
28struct aligninfo {
29 unsigned char len;
30 unsigned char flags;
31};
32
33#define IS_XFORM(inst) (((inst) >> 26) == 31)
34#define IS_DSFORM(inst) (((inst) >> 26) >= 56)
35
36#define INVALID { 0, 0 }
37
38#define LD 1 /* load */
39#define ST 2 /* store */
40#define SE 4 /* sign-extend value */
41#define F 8 /* to/from fp regs */
42#define U 0x10 /* update index register */
43#define M 0x20 /* multiple load/store */
44#define SW 0x40 /* byte swap int or ... */
45#define S 0x40 /* ... single-precision fp */
46#define SX 0x40 /* byte count in XER */
47#define HARD 0x80 /* string, stwcx. */
48
49#define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */
50
51#define SWAP(a, b) (t = (a), (a) = (b), (b) = t)
52
53/*
54 * The PowerPC stores certain bits of the instruction that caused the
55 * alignment exception in the DSISR register. This array maps those
56 * bits to information about the operand length and what the
57 * instruction would do.
58 */
59static struct aligninfo aligninfo[128] = {
60 { 4, LD }, /* 00 0 0000: lwz / lwarx */
61 INVALID, /* 00 0 0001 */
62 { 4, ST }, /* 00 0 0010: stw */
63 INVALID, /* 00 0 0011 */
64 { 2, LD }, /* 00 0 0100: lhz */
65 { 2, LD+SE }, /* 00 0 0101: lha */
66 { 2, ST }, /* 00 0 0110: sth */
67 { 4, LD+M }, /* 00 0 0111: lmw */
68 { 4, LD+F+S }, /* 00 0 1000: lfs */
69 { 8, LD+F }, /* 00 0 1001: lfd */
70 { 4, ST+F+S }, /* 00 0 1010: stfs */
71 { 8, ST+F }, /* 00 0 1011: stfd */
72 INVALID, /* 00 0 1100 */
73 { 8, LD }, /* 00 0 1101: ld/ldu/lwa */
74 INVALID, /* 00 0 1110 */
75 { 8, ST }, /* 00 0 1111: std/stdu */
76 { 4, LD+U }, /* 00 1 0000: lwzu */
77 INVALID, /* 00 1 0001 */
78 { 4, ST+U }, /* 00 1 0010: stwu */
79 INVALID, /* 00 1 0011 */
80 { 2, LD+U }, /* 00 1 0100: lhzu */
81 { 2, LD+SE+U }, /* 00 1 0101: lhau */
82 { 2, ST+U }, /* 00 1 0110: sthu */
83 { 4, ST+M }, /* 00 1 0111: stmw */
84 { 4, LD+F+S+U }, /* 00 1 1000: lfsu */
85 { 8, LD+F+U }, /* 00 1 1001: lfdu */
86 { 4, ST+F+S+U }, /* 00 1 1010: stfsu */
87 { 8, ST+F+U }, /* 00 1 1011: stfdu */
88 INVALID, /* 00 1 1100 */
89 INVALID, /* 00 1 1101 */
90 INVALID, /* 00 1 1110 */
91 INVALID, /* 00 1 1111 */
92 { 8, LD }, /* 01 0 0000: ldx */
93 INVALID, /* 01 0 0001 */
94 { 8, ST }, /* 01 0 0010: stdx */
95 INVALID, /* 01 0 0011 */
96 INVALID, /* 01 0 0100 */
97 { 4, LD+SE }, /* 01 0 0101: lwax */
98 INVALID, /* 01 0 0110 */
99 INVALID, /* 01 0 0111 */
100 { 4, LD+M+HARD+SX }, /* 01 0 1000: lswx */
101 { 4, LD+M+HARD }, /* 01 0 1001: lswi */
102 { 4, ST+M+HARD+SX }, /* 01 0 1010: stswx */
103 { 4, ST+M+HARD }, /* 01 0 1011: stswi */
104 INVALID, /* 01 0 1100 */
105 { 8, LD+U }, /* 01 0 1101: ldu */
106 INVALID, /* 01 0 1110 */
107 { 8, ST+U }, /* 01 0 1111: stdu */
108 { 8, LD+U }, /* 01 1 0000: ldux */
109 INVALID, /* 01 1 0001 */
110 { 8, ST+U }, /* 01 1 0010: stdux */
111 INVALID, /* 01 1 0011 */
112 INVALID, /* 01 1 0100 */
113 { 4, LD+SE+U }, /* 01 1 0101: lwaux */
114 INVALID, /* 01 1 0110 */
115 INVALID, /* 01 1 0111 */
116 INVALID, /* 01 1 1000 */
117 INVALID, /* 01 1 1001 */
118 INVALID, /* 01 1 1010 */
119 INVALID, /* 01 1 1011 */
120 INVALID, /* 01 1 1100 */
121 INVALID, /* 01 1 1101 */
122 INVALID, /* 01 1 1110 */
123 INVALID, /* 01 1 1111 */
124 INVALID, /* 10 0 0000 */
125 INVALID, /* 10 0 0001 */
126 INVALID, /* 10 0 0010: stwcx. */
127 INVALID, /* 10 0 0011 */
128 INVALID, /* 10 0 0100 */
129 INVALID, /* 10 0 0101 */
130 INVALID, /* 10 0 0110 */
131 INVALID, /* 10 0 0111 */
132 { 4, LD+SW }, /* 10 0 1000: lwbrx */
133 INVALID, /* 10 0 1001 */
134 { 4, ST+SW }, /* 10 0 1010: stwbrx */
135 INVALID, /* 10 0 1011 */
136 { 2, LD+SW }, /* 10 0 1100: lhbrx */
137 { 4, LD+SE }, /* 10 0 1101 lwa */
138 { 2, ST+SW }, /* 10 0 1110: sthbrx */
139 INVALID, /* 10 0 1111 */
140 INVALID, /* 10 1 0000 */
141 INVALID, /* 10 1 0001 */
142 INVALID, /* 10 1 0010 */
143 INVALID, /* 10 1 0011 */
144 INVALID, /* 10 1 0100 */
145 INVALID, /* 10 1 0101 */
146 INVALID, /* 10 1 0110 */
147 INVALID, /* 10 1 0111 */
148 INVALID, /* 10 1 1000 */
149 INVALID, /* 10 1 1001 */
150 INVALID, /* 10 1 1010 */
151 INVALID, /* 10 1 1011 */
152 INVALID, /* 10 1 1100 */
153 INVALID, /* 10 1 1101 */
154 INVALID, /* 10 1 1110 */
155 { 0, ST+HARD }, /* 10 1 1111: dcbz */
156 { 4, LD }, /* 11 0 0000: lwzx */
157 INVALID, /* 11 0 0001 */
158 { 4, ST }, /* 11 0 0010: stwx */
159 INVALID, /* 11 0 0011 */
160 { 2, LD }, /* 11 0 0100: lhzx */
161 { 2, LD+SE }, /* 11 0 0101: lhax */
162 { 2, ST }, /* 11 0 0110: sthx */
163 INVALID, /* 11 0 0111 */
164 { 4, LD+F+S }, /* 11 0 1000: lfsx */
165 { 8, LD+F }, /* 11 0 1001: lfdx */
166 { 4, ST+F+S }, /* 11 0 1010: stfsx */
167 { 8, ST+F }, /* 11 0 1011: stfdx */
168 INVALID, /* 11 0 1100 */
169 { 8, LD+M }, /* 11 0 1101: lmd */
170 INVALID, /* 11 0 1110 */
171 { 8, ST+M }, /* 11 0 1111: stmd */
172 { 4, LD+U }, /* 11 1 0000: lwzux */
173 INVALID, /* 11 1 0001 */
174 { 4, ST+U }, /* 11 1 0010: stwux */
175 INVALID, /* 11 1 0011 */
176 { 2, LD+U }, /* 11 1 0100: lhzux */
177 { 2, LD+SE+U }, /* 11 1 0101: lhaux */
178 { 2, ST+U }, /* 11 1 0110: sthux */
179 INVALID, /* 11 1 0111 */
180 { 4, LD+F+S+U }, /* 11 1 1000: lfsux */
181 { 8, LD+F+U }, /* 11 1 1001: lfdux */
182 { 4, ST+F+S+U }, /* 11 1 1010: stfsux */
183 { 8, ST+F+U }, /* 11 1 1011: stfdux */
184 INVALID, /* 11 1 1100 */
185 INVALID, /* 11 1 1101 */
186 INVALID, /* 11 1 1110 */
187 INVALID, /* 11 1 1111 */
188};
189
190/*
191 * Create a DSISR value from the instruction
192 */
193static inline unsigned make_dsisr(unsigned instr)
194{
195 unsigned dsisr;
196
197
198 /* bits 6:15 --> 22:31 */
199 dsisr = (instr & 0x03ff0000) >> 16;
200
201 if (IS_XFORM(instr)) {
202 /* bits 29:30 --> 15:16 */
203 dsisr |= (instr & 0x00000006) << 14;
204 /* bit 25 --> 17 */
205 dsisr |= (instr & 0x00000040) << 8;
206 /* bits 21:24 --> 18:21 */
207 dsisr |= (instr & 0x00000780) << 3;
208 } else {
209 /* bit 5 --> 17 */
210 dsisr |= (instr & 0x04000000) >> 12;
211 /* bits 1: 4 --> 18:21 */
212 dsisr |= (instr & 0x78000000) >> 17;
213 /* bits 30:31 --> 12:13 */
214 if (IS_DSFORM(instr))
215 dsisr |= (instr & 0x00000003) << 18;
216 }
217
218 return dsisr;
219}
220
221/*
222 * The dcbz (data cache block zero) instruction
223 * gives an alignment fault if used on non-cacheable
224 * memory. We handle the fault mainly for the
225 * case when we are running with the cache disabled
226 * for debugging.
227 */
228static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
229{
230 long __user *p;
231 int i, size;
232
233#ifdef __powerpc64__
234 size = ppc64_caches.dline_size;
235#else
236 size = L1_CACHE_BYTES;
237#endif
238 p = (long __user *) (regs->dar & -size);
239 if (user_mode(regs) && !access_ok(VERIFY_WRITE, p, size))
240 return -EFAULT;
241 for (i = 0; i < size / sizeof(long); ++i)
242 if (__put_user(0, p+i))
243 return -EFAULT;
244 return 1;
245}
246
247/*
248 * Emulate load & store multiple instructions
249 * On 64-bit machines, these instructions only affect/use the
250 * bottom 4 bytes of each register, and the loads clear the
251 * top 4 bytes of the affected register.
252 */
253#ifdef CONFIG_PPC64
254#define REG_BYTE(rp, i) *((u8 *)((rp) + ((i) >> 2)) + ((i) & 3) + 4)
255#else
256#define REG_BYTE(rp, i) *((u8 *)(rp) + (i))
257#endif
258
259static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
260 unsigned int reg, unsigned int nb,
261 unsigned int flags, unsigned int instr)
262{
263 unsigned long *rptr;
264 unsigned int nb0, i;
265
266 /*
267 * We do not try to emulate 8 bytes multiple as they aren't really
268 * available in our operating environments and we don't try to
269 * emulate multiples operations in kernel land as they should never
270 * be used/generated there at least not on unaligned boundaries
271 */
272 if (unlikely((nb > 4) || !user_mode(regs)))
273 return 0;
274
275 /* lmw, stmw, lswi/x, stswi/x */
276 nb0 = 0;
277 if (flags & HARD) {
278 if (flags & SX) {
279 nb = regs->xer & 127;
280 if (nb == 0)
281 return 1;
282 } else {
283 if (__get_user(instr,
284 (unsigned int __user *)regs->nip))
285 return -EFAULT;
286 nb = (instr >> 11) & 0x1f;
287 if (nb == 0)
288 nb = 32;
289 }
290 if (nb + reg * 4 > 128) {
291 nb0 = nb + reg * 4 - 128;
292 nb = 128 - reg * 4;
293 }
294 } else {
295 /* lwm, stmw */
296 nb = (32 - reg) * 4;
297 }
298
299 if (!access_ok((flags & ST ? VERIFY_WRITE: VERIFY_READ), addr, nb+nb0))
300 return -EFAULT; /* bad address */
301
302 rptr = &regs->gpr[reg];
303 if (flags & LD) {
304 /*
305 * This zeroes the top 4 bytes of the affected registers
306 * in 64-bit mode, and also zeroes out any remaining
307 * bytes of the last register for lsw*.
308 */
309 memset(rptr, 0, ((nb + 3) / 4) * sizeof(unsigned long));
310 if (nb0 > 0)
311 memset(&regs->gpr[0], 0,
312 ((nb0 + 3) / 4) * sizeof(unsigned long));
313
314 for (i = 0; i < nb; ++i)
315 if (__get_user(REG_BYTE(rptr, i), addr + i))
316 return -EFAULT;
317 if (nb0 > 0) {
318 rptr = &regs->gpr[0];
319 addr += nb;
320 for (i = 0; i < nb0; ++i)
321 if (__get_user(REG_BYTE(rptr, i), addr + i))
322 return -EFAULT;
323 }
324
325 } else {
326 for (i = 0; i < nb; ++i)
327 if (__put_user(REG_BYTE(rptr, i), addr + i))
328 return -EFAULT;
329 if (nb0 > 0) {
330 rptr = &regs->gpr[0];
331 addr += nb;
332 for (i = 0; i < nb0; ++i)
333 if (__put_user(REG_BYTE(rptr, i), addr + i))
334 return -EFAULT;
335 }
336 }
337 return 1;
338}
339
340
341/*
342 * Called on alignment exception. Attempts to fixup
343 *
344 * Return 1 on success
345 * Return 0 if unable to handle the interrupt
346 * Return -EFAULT if data address is bad
347 */
348
349int fix_alignment(struct pt_regs *regs)
350{
351 unsigned int instr, nb, flags;
352 unsigned int reg, areg;
353 unsigned int dsisr;
354 unsigned char __user *addr;
355 unsigned char __user *p;
356 int ret, t;
357 union {
358 u64 ll;
359 double dd;
360 unsigned char v[8];
361 struct {
362 unsigned hi32;
363 int low32;
364 } x32;
365 struct {
366 unsigned char hi48[6];
367 short low16;
368 } x16;
369 } data;
370
371 /*
372 * We require a complete register set, if not, then our assembly
373 * is broken
374 */
375 CHECK_FULL_REGS(regs);
376
377 dsisr = regs->dsisr;
378
379 /* Some processors don't provide us with a DSISR we can use here,
380 * let's make one up from the instruction
381 */
382 if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) {
383 unsigned int real_instr;
384 if (unlikely(__get_user(real_instr,
385 (unsigned int __user *)regs->nip)))
386 return -EFAULT;
387 dsisr = make_dsisr(real_instr);
388 }
389
390 /* extract the operation and registers from the dsisr */
391 reg = (dsisr >> 5) & 0x1f; /* source/dest register */
392 areg = dsisr & 0x1f; /* register to update */
393 instr = (dsisr >> 10) & 0x7f;
394 instr |= (dsisr >> 13) & 0x60;
395
396 /* Lookup the operation in our table */
397 nb = aligninfo[instr].len;
398 flags = aligninfo[instr].flags;
399
400 /* DAR has the operand effective address */
401 addr = (unsigned char __user *)regs->dar;
402
403 /* A size of 0 indicates an instruction we don't support, with
404 * the exception of DCBZ which is handled as a special case here
405 */
406 if (instr == DCBZ)
407 return emulate_dcbz(regs, addr);
408 if (unlikely(nb == 0))
409 return 0;
410
411 /* Load/Store Multiple instructions are handled in their own
412 * function
413 */
414 if (flags & M)
415 return emulate_multiple(regs, addr, reg, nb, flags, instr);
416
417 /* Verify the address of the operand */
418 if (unlikely(user_mode(regs) &&
419 !access_ok((flags & ST ? VERIFY_WRITE : VERIFY_READ),
420 addr, nb)))
421 return -EFAULT;
422
423 /* Force the fprs into the save area so we can reference them */
424 if (flags & F) {
425 /* userland only */
426 if (unlikely(!user_mode(regs)))
427 return 0;
428 flush_fp_to_thread(current);
429 }
430
431 /* If we are loading, get the data from user space, else
432 * get it from register values
433 */
434 if (flags & LD) {
435 data.ll = 0;
436 ret = 0;
437 p = addr;
438 switch (nb) {
439 case 8:
440 ret |= __get_user(data.v[0], p++);
441 ret |= __get_user(data.v[1], p++);
442 ret |= __get_user(data.v[2], p++);
443 ret |= __get_user(data.v[3], p++);
444 case 4:
445 ret |= __get_user(data.v[4], p++);
446 ret |= __get_user(data.v[5], p++);
447 case 2:
448 ret |= __get_user(data.v[6], p++);
449 ret |= __get_user(data.v[7], p++);
450 if (unlikely(ret))
451 return -EFAULT;
452 }
453 } else if (flags & F)
454 data.dd = current->thread.fpr[reg];
455 else
456 data.ll = regs->gpr[reg];
457
458 /* Perform other misc operations like sign extension, byteswap,
459 * or floating point single precision conversion
460 */
461 switch (flags & ~U) {
462 case LD+SE: /* sign extend */
463 if ( nb == 2 )
464 data.ll = data.x16.low16;
465 else /* nb must be 4 */
466 data.ll = data.x32.low32;
467 break;
468 case LD+S: /* byte-swap */
469 case ST+S:
470 if (nb == 2) {
471 SWAP(data.v[6], data.v[7]);
472 } else {
473 SWAP(data.v[4], data.v[7]);
474 SWAP(data.v[5], data.v[6]);
475 }
476 break;
477
478 /* Single-precision FP load and store require conversions... */
479 case LD+F+S:
480#ifdef CONFIG_PPC_FPU
481 preempt_disable();
482 enable_kernel_fp();
483 cvt_fd((float *)&data.v[4], &data.dd, &current->thread);
484 preempt_enable();
485#else
486 return 0;
487#endif
488 break;
489 case ST+F+S:
490#ifdef CONFIG_PPC_FPU
491 preempt_disable();
492 enable_kernel_fp();
493 cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
494 preempt_enable();
495#else
496 return 0;
497#endif
498 break;
499 }
500
501 /* Store result to memory or update registers */
502 if (flags & ST) {
503 ret = 0;
504 p = addr;
505 switch (nb) {
506 case 8:
507 ret |= __put_user(data.v[0], p++);
508 ret |= __put_user(data.v[1], p++);
509 ret |= __put_user(data.v[2], p++);
510 ret |= __put_user(data.v[3], p++);
511 case 4:
512 ret |= __put_user(data.v[4], p++);
513 ret |= __put_user(data.v[5], p++);
514 case 2:
515 ret |= __put_user(data.v[6], p++);
516 ret |= __put_user(data.v[7], p++);
517 }
518 if (unlikely(ret))
519 return -EFAULT;
520 } else if (flags & F)
521 current->thread.fpr[reg] = data.dd;
522 else
523 regs->gpr[reg] = data.ll;
524
525 /* Update RA as needed */
526 if (flags & U)
527 regs->gpr[areg] = regs->dar;
528
529 return 1;
530}
diff --git a/arch/powerpc/kernel/idle_64.c b/arch/powerpc/kernel/idle_64.c
new file mode 100644
index 000000000000..b879d3057ef8
--- /dev/null
+++ b/arch/powerpc/kernel/idle_64.c
@@ -0,0 +1,121 @@
1/*
2 * Idle daemon for PowerPC. Idle daemon will handle any action
3 * that needs to be taken when the system becomes idle.
4 *
5 * Originally Written by Cort Dougan (cort@cs.nmt.edu)
6 *
7 * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com>
8 *
9 * Additional shared processor, SMT, and firmware support
10 * Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/config.h>
19#include <linux/sched.h>
20#include <linux/kernel.h>
21#include <linux/smp.h>
22#include <linux/cpu.h>
23#include <linux/sysctl.h>
24
25#include <asm/system.h>
26#include <asm/processor.h>
27#include <asm/cputable.h>
28#include <asm/time.h>
29#include <asm/machdep.h>
30#include <asm/smp.h>
31
32extern void power4_idle(void);
33
34void default_idle(void)
35{
36 unsigned int cpu = smp_processor_id();
37 set_thread_flag(TIF_POLLING_NRFLAG);
38
39 while (1) {
40 if (!need_resched()) {
41 while (!need_resched() && !cpu_is_offline(cpu)) {
42 ppc64_runlatch_off();
43
44 /*
45 * Go into low thread priority and possibly
46 * low power mode.
47 */
48 HMT_low();
49 HMT_very_low();
50 }
51
52 HMT_medium();
53 }
54
55 ppc64_runlatch_on();
56 preempt_enable_no_resched();
57 schedule();
58 preempt_disable();
59 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
60 cpu_die();
61 }
62}
63
64void native_idle(void)
65{
66 while (1) {
67 ppc64_runlatch_off();
68
69 if (!need_resched())
70 power4_idle();
71
72 if (need_resched()) {
73 ppc64_runlatch_on();
74 preempt_enable_no_resched();
75 schedule();
76 preempt_disable();
77 }
78
79 if (cpu_is_offline(smp_processor_id()) &&
80 system_state == SYSTEM_RUNNING)
81 cpu_die();
82 }
83}
84
85void cpu_idle(void)
86{
87 BUG_ON(NULL == ppc_md.idle_loop);
88 ppc_md.idle_loop();
89}
90
91int powersave_nap;
92
93#ifdef CONFIG_SYSCTL
94/*
95 * Register the sysctl to set/clear powersave_nap.
96 */
97static ctl_table powersave_nap_ctl_table[]={
98 {
99 .ctl_name = KERN_PPC_POWERSAVE_NAP,
100 .procname = "powersave-nap",
101 .data = &powersave_nap,
102 .maxlen = sizeof(int),
103 .mode = 0644,
104 .proc_handler = &proc_dointvec,
105 },
106 { 0, },
107};
108static ctl_table powersave_nap_sysctl_root[] = {
109 { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
110 { 0,},
111};
112
113static int __init
114register_powersave_nap_sysctl(void)
115{
116 register_sysctl_table(powersave_nap_sysctl_root, 0);
117
118 return 0;
119}
120__initcall(register_powersave_nap_sysctl);
121#endif
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index f6d84a75ed26..624a983a9676 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -27,14 +27,6 @@
27 27
28 .text 28 .text
29 29
30 .align 5
31_GLOBAL(__delay)
32 cmpwi 0,r3,0
33 mtctr r3
34 beqlr
351: bdnz 1b
36 blr
37
38/* 30/*
39 * This returns the high 64 bits of the product of two 64-bit numbers. 31 * This returns the high 64 bits of the product of two 64-bit numbers.
40 */ 32 */
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
new file mode 100644
index 000000000000..c0fcd29918ce
--- /dev/null
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -0,0 +1,742 @@
1/*
2 * c 2001 PPC 64 Team, IBM Corp
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 * /dev/nvram driver for PPC64
10 *
11 * This perhaps should live in drivers/char
12 *
13 * TODO: Split the /dev/nvram part (that one can use
14 * drivers/char/generic_nvram.c) from the arch & partition
15 * parsing code.
16 */
17
18#include <linux/module.h>
19
20#include <linux/types.h>
21#include <linux/errno.h>
22#include <linux/fs.h>
23#include <linux/miscdevice.h>
24#include <linux/fcntl.h>
25#include <linux/nvram.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/spinlock.h>
29#include <asm/uaccess.h>
30#include <asm/nvram.h>
31#include <asm/rtas.h>
32#include <asm/prom.h>
33#include <asm/machdep.h>
34
35#undef DEBUG_NVRAM
36
37static int nvram_scan_partitions(void);
38static int nvram_setup_partition(void);
39static int nvram_create_os_partition(void);
40static int nvram_remove_os_partition(void);
41
42static struct nvram_partition * nvram_part;
43static long nvram_error_log_index = -1;
44static long nvram_error_log_size = 0;
45
46int no_logging = 1; /* Until we initialize everything,
47 * make sure we don't try logging
48 * anything */
49
50extern volatile int error_log_cnt;
51
52struct err_log_info {
53 int error_type;
54 unsigned int seq_num;
55};
56
57static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
58{
59 int size;
60
61 if (ppc_md.nvram_size == NULL)
62 return -ENODEV;
63 size = ppc_md.nvram_size();
64
65 switch (origin) {
66 case 1:
67 offset += file->f_pos;
68 break;
69 case 2:
70 offset += size;
71 break;
72 }
73 if (offset < 0)
74 return -EINVAL;
75 file->f_pos = offset;
76 return file->f_pos;
77}
78
79
80static ssize_t dev_nvram_read(struct file *file, char __user *buf,
81 size_t count, loff_t *ppos)
82{
83 ssize_t len;
84 char *tmp_buffer;
85 int size;
86
87 if (ppc_md.nvram_size == NULL)
88 return -ENODEV;
89 size = ppc_md.nvram_size();
90
91 if (!access_ok(VERIFY_WRITE, buf, count))
92 return -EFAULT;
93 if (*ppos >= size)
94 return 0;
95 if (count > size)
96 count = size;
97
98 tmp_buffer = (char *) kmalloc(count, GFP_KERNEL);
99 if (!tmp_buffer) {
100 printk(KERN_ERR "dev_read_nvram: kmalloc failed\n");
101 return -ENOMEM;
102 }
103
104 len = ppc_md.nvram_read(tmp_buffer, count, ppos);
105 if ((long)len <= 0) {
106 kfree(tmp_buffer);
107 return len;
108 }
109
110 if (copy_to_user(buf, tmp_buffer, len)) {
111 kfree(tmp_buffer);
112 return -EFAULT;
113 }
114
115 kfree(tmp_buffer);
116 return len;
117
118}
119
120static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
121 size_t count, loff_t *ppos)
122{
123 ssize_t len;
124 char * tmp_buffer;
125 int size;
126
127 if (ppc_md.nvram_size == NULL)
128 return -ENODEV;
129 size = ppc_md.nvram_size();
130
131 if (!access_ok(VERIFY_READ, buf, count))
132 return -EFAULT;
133 if (*ppos >= size)
134 return 0;
135 if (count > size)
136 count = size;
137
138 tmp_buffer = (char *) kmalloc(count, GFP_KERNEL);
139 if (!tmp_buffer) {
140 printk(KERN_ERR "dev_nvram_write: kmalloc failed\n");
141 return -ENOMEM;
142 }
143
144 if (copy_from_user(tmp_buffer, buf, count)) {
145 kfree(tmp_buffer);
146 return -EFAULT;
147 }
148
149 len = ppc_md.nvram_write(tmp_buffer, count, ppos);
150 if ((long)len <= 0) {
151 kfree(tmp_buffer);
152 return len;
153 }
154
155 kfree(tmp_buffer);
156 return len;
157}
158
159static int dev_nvram_ioctl(struct inode *inode, struct file *file,
160 unsigned int cmd, unsigned long arg)
161{
162 switch(cmd) {
163#ifdef CONFIG_PPC_PMAC
164 case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
165 printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
166 case IOC_NVRAM_GET_OFFSET: {
167 int part, offset;
168
169 if (_machine != PLATFORM_POWERMAC)
170 return -EINVAL;
171 if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
172 return -EFAULT;
173 if (part < pmac_nvram_OF || part > pmac_nvram_NR)
174 return -EINVAL;
175 offset = pmac_get_partition(part);
176 if (offset < 0)
177 return offset;
178 if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0)
179 return -EFAULT;
180 return 0;
181 }
182#endif /* CONFIG_PPC_PMAC */
183 }
184 return -EINVAL;
185}
186
187struct file_operations nvram_fops = {
188 .owner = THIS_MODULE,
189 .llseek = dev_nvram_llseek,
190 .read = dev_nvram_read,
191 .write = dev_nvram_write,
192 .ioctl = dev_nvram_ioctl,
193};
194
195static struct miscdevice nvram_dev = {
196 NVRAM_MINOR,
197 "nvram",
198 &nvram_fops
199};
200
201
202#ifdef DEBUG_NVRAM
203static void nvram_print_partitions(char * label)
204{
205 struct list_head * p;
206 struct nvram_partition * tmp_part;
207
208 printk(KERN_WARNING "--------%s---------\n", label);
209 printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
210 list_for_each(p, &nvram_part->partition) {
211 tmp_part = list_entry(p, struct nvram_partition, partition);
212 printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n",
213 tmp_part->index, tmp_part->header.signature,
214 tmp_part->header.checksum, tmp_part->header.length,
215 tmp_part->header.name);
216 }
217}
218#endif
219
220
221static int nvram_write_header(struct nvram_partition * part)
222{
223 loff_t tmp_index;
224 int rc;
225
226 tmp_index = part->index;
227 rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index);
228
229 return rc;
230}
231
232
233static unsigned char nvram_checksum(struct nvram_header *p)
234{
235 unsigned int c_sum, c_sum2;
236 unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */
237 c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];
238
239 /* The sum may have spilled into the 3rd byte. Fold it back. */
240 c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;
241 /* The sum cannot exceed 2 bytes. Fold it into a checksum */
242 c_sum2 = (c_sum >> 8) + (c_sum << 8);
243 c_sum = ((c_sum + c_sum2) >> 8) & 0xff;
244 return c_sum;
245}
246
247
248/*
249 * Find an nvram partition, sig can be 0 for any
250 * partition or name can be NULL for any name, else
251 * tries to match both
252 */
253struct nvram_partition *nvram_find_partition(int sig, const char *name)
254{
255 struct nvram_partition * part;
256 struct list_head * p;
257
258 list_for_each(p, &nvram_part->partition) {
259 part = list_entry(p, struct nvram_partition, partition);
260
261 if (sig && part->header.signature != sig)
262 continue;
263 if (name && 0 != strncmp(name, part->header.name, 12))
264 continue;
265 return part;
266 }
267 return NULL;
268}
269EXPORT_SYMBOL(nvram_find_partition);
270
271
272static int nvram_remove_os_partition(void)
273{
274 struct list_head *i;
275 struct list_head *j;
276 struct nvram_partition * part;
277 struct nvram_partition * cur_part;
278 int rc;
279
280 list_for_each(i, &nvram_part->partition) {
281 part = list_entry(i, struct nvram_partition, partition);
282 if (part->header.signature != NVRAM_SIG_OS)
283 continue;
284
285 /* Make os partition a free partition */
286 part->header.signature = NVRAM_SIG_FREE;
287 sprintf(part->header.name, "wwwwwwwwwwww");
288 part->header.checksum = nvram_checksum(&part->header);
289
290 /* Merge contiguous free partitions backwards */
291 list_for_each_prev(j, &part->partition) {
292 cur_part = list_entry(j, struct nvram_partition, partition);
293 if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {
294 break;
295 }
296
297 part->header.length += cur_part->header.length;
298 part->header.checksum = nvram_checksum(&part->header);
299 part->index = cur_part->index;
300
301 list_del(&cur_part->partition);
302 kfree(cur_part);
303 j = &part->partition; /* fixup our loop */
304 }
305
306 /* Merge contiguous free partitions forwards */
307 list_for_each(j, &part->partition) {
308 cur_part = list_entry(j, struct nvram_partition, partition);
309 if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {
310 break;
311 }
312
313 part->header.length += cur_part->header.length;
314 part->header.checksum = nvram_checksum(&part->header);
315
316 list_del(&cur_part->partition);
317 kfree(cur_part);
318 j = &part->partition; /* fixup our loop */
319 }
320
321 rc = nvram_write_header(part);
322 if (rc <= 0) {
323 printk(KERN_ERR "nvram_remove_os_partition: nvram_write failed (%d)\n", rc);
324 return rc;
325 }
326
327 }
328
329 return 0;
330}
331
332/* nvram_create_os_partition
333 *
334 * Create a OS linux partition to buffer error logs.
335 * Will create a partition starting at the first free
336 * space found if space has enough room.
337 */
338static int nvram_create_os_partition(void)
339{
340 struct nvram_partition *part;
341 struct nvram_partition *new_part;
342 struct nvram_partition *free_part = NULL;
343 int seq_init[2] = { 0, 0 };
344 loff_t tmp_index;
345 long size = 0;
346 int rc;
347
348 /* Find a free partition that will give us the maximum needed size
349 If can't find one that will give us the minimum size needed */
350 list_for_each_entry(part, &nvram_part->partition, partition) {
351 if (part->header.signature != NVRAM_SIG_FREE)
352 continue;
353
354 if (part->header.length >= NVRAM_MAX_REQ) {
355 size = NVRAM_MAX_REQ;
356 free_part = part;
357 break;
358 }
359 if (!size && part->header.length >= NVRAM_MIN_REQ) {
360 size = NVRAM_MIN_REQ;
361 free_part = part;
362 }
363 }
364 if (!size)
365 return -ENOSPC;
366
367 /* Create our OS partition */
368 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
369 if (!new_part) {
370 printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n");
371 return -ENOMEM;
372 }
373
374 new_part->index = free_part->index;
375 new_part->header.signature = NVRAM_SIG_OS;
376 new_part->header.length = size;
377 strcpy(new_part->header.name, "ppc64,linux");
378 new_part->header.checksum = nvram_checksum(&new_part->header);
379
380 rc = nvram_write_header(new_part);
381 if (rc <= 0) {
382 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header \
383 failed (%d)\n", rc);
384 return rc;
385 }
386
387 /* make sure and initialize to zero the sequence number and the error
388 type logged */
389 tmp_index = new_part->index + NVRAM_HEADER_LEN;
390 rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);
391 if (rc <= 0) {
392 printk(KERN_ERR "nvram_create_os_partition: nvram_write "
393 "failed (%d)\n", rc);
394 return rc;
395 }
396
397 nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN;
398 nvram_error_log_size = ((part->header.length - 1) *
399 NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
400
401 list_add_tail(&new_part->partition, &free_part->partition);
402
403 if (free_part->header.length <= size) {
404 list_del(&free_part->partition);
405 kfree(free_part);
406 return 0;
407 }
408
409 /* Adjust the partition we stole the space from */
410 free_part->index += size * NVRAM_BLOCK_LEN;
411 free_part->header.length -= size;
412 free_part->header.checksum = nvram_checksum(&free_part->header);
413
414 rc = nvram_write_header(free_part);
415 if (rc <= 0) {
416 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header "
417 "failed (%d)\n", rc);
418 return rc;
419 }
420
421 return 0;
422}
423
424
425/* nvram_setup_partition
426 *
427 * This will setup the partition we need for buffering the
428 * error logs and cleanup partitions if needed.
429 *
430 * The general strategy is the following:
431 * 1.) If there is ppc64,linux partition large enough then use it.
432 * 2.) If there is not a ppc64,linux partition large enough, search
433 * for a free partition that is large enough.
434 * 3.) If there is not a free partition large enough remove
435 * _all_ OS partitions and consolidate the space.
436 * 4.) Will first try getting a chunk that will satisfy the maximum
437 * error log size (NVRAM_MAX_REQ).
438 * 5.) If the max chunk cannot be allocated then try finding a chunk
439 * that will satisfy the minum needed (NVRAM_MIN_REQ).
440 */
441static int nvram_setup_partition(void)
442{
443 struct list_head * p;
444 struct nvram_partition * part;
445 int rc;
446
447 /* For now, we don't do any of this on pmac, until I
448 * have figured out if it's worth killing some unused stuffs
449 * in our nvram, as Apple defined partitions use pretty much
450 * all of the space
451 */
452 if (_machine == PLATFORM_POWERMAC)
453 return -ENOSPC;
454
455 /* see if we have an OS partition that meets our needs.
456 will try getting the max we need. If not we'll delete
457 partitions and try again. */
458 list_for_each(p, &nvram_part->partition) {
459 part = list_entry(p, struct nvram_partition, partition);
460 if (part->header.signature != NVRAM_SIG_OS)
461 continue;
462
463 if (strcmp(part->header.name, "ppc64,linux"))
464 continue;
465
466 if (part->header.length >= NVRAM_MIN_REQ) {
467 /* found our partition */
468 nvram_error_log_index = part->index + NVRAM_HEADER_LEN;
469 nvram_error_log_size = ((part->header.length - 1) *
470 NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
471 return 0;
472 }
473 }
474
475 /* try creating a partition with the free space we have */
476 rc = nvram_create_os_partition();
477 if (!rc) {
478 return 0;
479 }
480
481 /* need to free up some space */
482 rc = nvram_remove_os_partition();
483 if (rc) {
484 return rc;
485 }
486
487 /* create a partition in this new space */
488 rc = nvram_create_os_partition();
489 if (rc) {
490 printk(KERN_ERR "nvram_create_os_partition: Could not find a "
491 "NVRAM partition large enough\n");
492 return rc;
493 }
494
495 return 0;
496}
497
498
499static int nvram_scan_partitions(void)
500{
501 loff_t cur_index = 0;
502 struct nvram_header phead;
503 struct nvram_partition * tmp_part;
504 unsigned char c_sum;
505 char * header;
506 int total_size;
507 int err;
508
509 if (ppc_md.nvram_size == NULL)
510 return -ENODEV;
511 total_size = ppc_md.nvram_size();
512
513 header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
514 if (!header) {
515 printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");
516 return -ENOMEM;
517 }
518
519 while (cur_index < total_size) {
520
521 err = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index);
522 if (err != NVRAM_HEADER_LEN) {
523 printk(KERN_ERR "nvram_scan_partitions: Error parsing "
524 "nvram partitions\n");
525 goto out;
526 }
527
528 cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */
529
530 memcpy(&phead, header, NVRAM_HEADER_LEN);
531
532 err = 0;
533 c_sum = nvram_checksum(&phead);
534 if (c_sum != phead.checksum) {
535 printk(KERN_WARNING "WARNING: nvram partition checksum"
536 " was %02x, should be %02x!\n",
537 phead.checksum, c_sum);
538 printk(KERN_WARNING "Terminating nvram partition scan\n");
539 goto out;
540 }
541 if (!phead.length) {
542 printk(KERN_WARNING "WARNING: nvram corruption "
543 "detected: 0-length partition\n");
544 goto out;
545 }
546 tmp_part = (struct nvram_partition *)
547 kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
548 err = -ENOMEM;
549 if (!tmp_part) {
550 printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");
551 goto out;
552 }
553
554 memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
555 tmp_part->index = cur_index;
556 list_add_tail(&tmp_part->partition, &nvram_part->partition);
557
558 cur_index += phead.length * NVRAM_BLOCK_LEN;
559 }
560 err = 0;
561
562 out:
563 kfree(header);
564 return err;
565}
566
567static int __init nvram_init(void)
568{
569 int error;
570 int rc;
571
572 if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
573 return -ENODEV;
574
575 rc = misc_register(&nvram_dev);
576 if (rc != 0) {
577 printk(KERN_ERR "nvram_init: failed to register device\n");
578 return rc;
579 }
580
581 /* initialize our anchor for the nvram partition list */
582 nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
583 if (!nvram_part) {
584 printk(KERN_ERR "nvram_init: Failed kmalloc\n");
585 return -ENOMEM;
586 }
587 INIT_LIST_HEAD(&nvram_part->partition);
588
589 /* Get all the NVRAM partitions */
590 error = nvram_scan_partitions();
591 if (error) {
592 printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n");
593 return error;
594 }
595
596 if(nvram_setup_partition())
597 printk(KERN_WARNING "nvram_init: Could not find nvram partition"
598 " for nvram buffered error logging.\n");
599
600#ifdef DEBUG_NVRAM
601 nvram_print_partitions("NVRAM Partitions");
602#endif
603
604 return rc;
605}
606
607void __exit nvram_cleanup(void)
608{
609 misc_deregister( &nvram_dev );
610}
611
612
613#ifdef CONFIG_PPC_PSERIES
614
615/* nvram_write_error_log
616 *
617 * We need to buffer the error logs into nvram to ensure that we have
618 * the failure information to decode. If we have a severe error there
619 * is no way to guarantee that the OS or the machine is in a state to
620 * get back to user land and write the error to disk. For example if
621 * the SCSI device driver causes a Machine Check by writing to a bad
622 * IO address, there is no way of guaranteeing that the device driver
623 * is in any state that is would also be able to write the error data
624 * captured to disk, thus we buffer it in NVRAM for analysis on the
625 * next boot.
626 *
627 * In NVRAM the partition containing the error log buffer will looks like:
628 * Header (in bytes):
629 * +-----------+----------+--------+------------+------------------+
630 * | signature | checksum | length | name | data |
631 * |0 |1 |2 3|4 15|16 length-1|
632 * +-----------+----------+--------+------------+------------------+
633 *
634 * The 'data' section would look like (in bytes):
635 * +--------------+------------+-----------------------------------+
636 * | event_logged | sequence # | error log |
637 * |0 3|4 7|8 nvram_error_log_size-1|
638 * +--------------+------------+-----------------------------------+
639 *
640 * event_logged: 0 if event has not been logged to syslog, 1 if it has
641 * sequence #: The unique sequence # for each event. (until it wraps)
642 * error log: The error log from event_scan
643 */
644int nvram_write_error_log(char * buff, int length, unsigned int err_type)
645{
646 int rc;
647 loff_t tmp_index;
648 struct err_log_info info;
649
650 if (no_logging) {
651 return -EPERM;
652 }
653
654 if (nvram_error_log_index == -1) {
655 return -ESPIPE;
656 }
657
658 if (length > nvram_error_log_size) {
659 length = nvram_error_log_size;
660 }
661
662 info.error_type = err_type;
663 info.seq_num = error_log_cnt;
664
665 tmp_index = nvram_error_log_index;
666
667 rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
668 if (rc <= 0) {
669 printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
670 return rc;
671 }
672
673 rc = ppc_md.nvram_write(buff, length, &tmp_index);
674 if (rc <= 0) {
675 printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
676 return rc;
677 }
678
679 return 0;
680}
681
682/* nvram_read_error_log
683 *
684 * Reads nvram for error log for at most 'length'
685 */
686int nvram_read_error_log(char * buff, int length, unsigned int * err_type)
687{
688 int rc;
689 loff_t tmp_index;
690 struct err_log_info info;
691
692 if (nvram_error_log_index == -1)
693 return -1;
694
695 if (length > nvram_error_log_size)
696 length = nvram_error_log_size;
697
698 tmp_index = nvram_error_log_index;
699
700 rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
701 if (rc <= 0) {
702 printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
703 return rc;
704 }
705
706 rc = ppc_md.nvram_read(buff, length, &tmp_index);
707 if (rc <= 0) {
708 printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
709 return rc;
710 }
711
712 error_log_cnt = info.seq_num;
713 *err_type = info.error_type;
714
715 return 0;
716}
717
718/* This doesn't actually zero anything, but it sets the event_logged
719 * word to tell that this event is safely in syslog.
720 */
721int nvram_clear_error_log(void)
722{
723 loff_t tmp_index;
724 int clear_word = ERR_FLAG_ALREADY_LOGGED;
725 int rc;
726
727 tmp_index = nvram_error_log_index;
728
729 rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
730 if (rc <= 0) {
731 printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
732 return rc;
733 }
734
735 return 0;
736}
737
738#endif /* CONFIG_PPC_PSERIES */
739
740module_init(nvram_init);
741module_exit(nvram_cleanup);
742MODULE_LICENSE("GPL");
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 3cef1b8f57f0..5a5b24685081 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -30,10 +30,10 @@
30#include <asm/byteorder.h> 30#include <asm/byteorder.h>
31#include <asm/irq.h> 31#include <asm/irq.h>
32#include <asm/machdep.h> 32#include <asm/machdep.h>
33#include <asm/udbg.h>
34#include <asm/ppc-pci.h> 33#include <asm/ppc-pci.h>
35 34
36#ifdef DEBUG 35#ifdef DEBUG
36#include <asm/udbg.h>
37#define DBG(fmt...) udbg_printf(fmt) 37#define DBG(fmt...) udbg_printf(fmt)
38#else 38#else
39#define DBG(fmt...) 39#define DBG(fmt...)
@@ -187,7 +187,7 @@ static DEFINE_SPINLOCK(hose_spinlock);
187/* 187/*
188 * pci_controller(phb) initialized common variables. 188 * pci_controller(phb) initialized common variables.
189 */ 189 */
190void __devinit pci_setup_pci_controller(struct pci_controller *hose) 190static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
191{ 191{
192 memset(hose, 0, sizeof(struct pci_controller)); 192 memset(hose, 0, sizeof(struct pci_controller));
193 193
@@ -197,6 +197,65 @@ void __devinit pci_setup_pci_controller(struct pci_controller *hose)
197 spin_unlock(&hose_spinlock); 197 spin_unlock(&hose_spinlock);
198} 198}
199 199
200static void add_linux_pci_domain(struct device_node *dev,
201 struct pci_controller *phb)
202{
203 struct property *of_prop;
204 unsigned int size;
205
206 of_prop = (struct property *)
207 get_property(dev, "linux,pci-domain", &size);
208 if (of_prop != NULL)
209 return;
210 WARN_ON(of_prop && size < sizeof(int));
211 if (of_prop && size < sizeof(int))
212 of_prop = NULL;
213 size = sizeof(struct property) + sizeof(int);
214 if (of_prop == NULL) {
215 if (mem_init_done)
216 of_prop = kmalloc(size, GFP_KERNEL);
217 else
218 of_prop = alloc_bootmem(size);
219 }
220 memset(of_prop, 0, sizeof(struct property));
221 of_prop->name = "linux,pci-domain";
222 of_prop->length = sizeof(int);
223 of_prop->value = (unsigned char *)&of_prop[1];
224 *((int *)of_prop->value) = phb->global_number;
225 prom_add_property(dev, of_prop);
226}
227
228struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
229{
230 struct pci_controller *phb;
231
232 if (mem_init_done)
233 phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
234 else
235 phb = alloc_bootmem(sizeof (struct pci_controller));
236 if (phb == NULL)
237 return NULL;
238 pci_setup_pci_controller(phb);
239 phb->arch_data = dev;
240 phb->is_dynamic = mem_init_done;
241 if (dev)
242 add_linux_pci_domain(dev, phb);
243 return phb;
244}
245
246void pcibios_free_controller(struct pci_controller *phb)
247{
248 if (phb->arch_data) {
249 struct device_node *np = phb->arch_data;
250 int *domain = (int *)get_property(np,
251 "linux,pci-domain", NULL);
252 if (domain)
253 *domain = -1;
254 }
255 if (phb->is_dynamic)
256 kfree(phb);
257}
258
200static void __init pcibios_claim_one_bus(struct pci_bus *b) 259static void __init pcibios_claim_one_bus(struct pci_bus *b)
201{ 260{
202 struct pci_dev *dev; 261 struct pci_dev *dev;
@@ -907,9 +966,10 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
907 * (size depending on dev->n_addr_cells) 966 * (size depending on dev->n_addr_cells)
908 * cells 4+5 or 5+6: the size of the range 967 * cells 4+5 or 5+6: the size of the range
909 */ 968 */
910 rlen = 0;
911 hose->io_base_phys = 0;
912 ranges = (unsigned int *) get_property(dev, "ranges", &rlen); 969 ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
970 if (ranges == NULL)
971 return;
972 hose->io_base_phys = 0;
913 while ((rlen -= np * sizeof(unsigned int)) >= 0) { 973 while ((rlen -= np * sizeof(unsigned int)) >= 0) {
914 res = NULL; 974 res = NULL;
915 pci_space = ranges[0]; 975 pci_space = ranges[0];
@@ -1107,6 +1167,8 @@ int remap_bus_range(struct pci_bus *bus)
1107 1167
1108 if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) 1168 if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
1109 return 1; 1169 return 1;
1170 if (start_phys == 0)
1171 return 1;
1110 printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); 1172 printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
1111 if (__ioremap_explicit(start_phys, start_virt, size, 1173 if (__ioremap_explicit(start_phys, start_virt, size,
1112 _PAGE_NO_CACHE | _PAGE_GUARDED)) 1174 _PAGE_NO_CACHE | _PAGE_GUARDED))
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 5dcf4ba05ee8..59846b40d521 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -105,6 +105,13 @@ EXPORT_SYMBOL(__clear_user);
105EXPORT_SYMBOL(__strncpy_from_user); 105EXPORT_SYMBOL(__strncpy_from_user);
106EXPORT_SYMBOL(__strnlen_user); 106EXPORT_SYMBOL(__strnlen_user);
107 107
108#ifndef __powerpc64__
109EXPORT_SYMBOL(__ide_mm_insl);
110EXPORT_SYMBOL(__ide_mm_outsw);
111EXPORT_SYMBOL(__ide_mm_insw);
112EXPORT_SYMBOL(__ide_mm_outsl);
113#endif
114
108EXPORT_SYMBOL(_insb); 115EXPORT_SYMBOL(_insb);
109EXPORT_SYMBOL(_outsb); 116EXPORT_SYMBOL(_outsb);
110EXPORT_SYMBOL(_insw); 117EXPORT_SYMBOL(_insw);
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c
index 7b948662704c..635d3b9a8811 100644
--- a/arch/powerpc/kernel/rtas-rtc.c
+++ b/arch/powerpc/kernel/rtas-rtc.c
@@ -15,7 +15,7 @@ unsigned long __init rtas_get_boot_time(void)
15{ 15{
16 int ret[8]; 16 int ret[8];
17 int error, wait_time; 17 int error, wait_time;
18 unsigned long max_wait_tb; 18 u64 max_wait_tb;
19 19
20 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; 20 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
21 do { 21 do {
@@ -45,7 +45,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm)
45{ 45{
46 int ret[8]; 46 int ret[8];
47 int error, wait_time; 47 int error, wait_time;
48 unsigned long max_wait_tb; 48 u64 max_wait_tb;
49 49
50 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; 50 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
51 do { 51 do {
@@ -80,7 +80,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm)
80int rtas_set_rtc_time(struct rtc_time *tm) 80int rtas_set_rtc_time(struct rtc_time *tm)
81{ 81{
82 int error, wait_time; 82 int error, wait_time;
83 unsigned long max_wait_tb; 83 u64 max_wait_tb;
84 84
85 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; 85 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
86 do { 86 do {
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 0e5a8e116653..60dec2401c26 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -304,75 +304,18 @@ static int __devinit setup_phb(struct device_node *dev,
304 struct pci_controller *phb, 304 struct pci_controller *phb,
305 unsigned int addr_size_words) 305 unsigned int addr_size_words)
306{ 306{
307 pci_setup_pci_controller(phb);
308
309 if (is_python(dev)) 307 if (is_python(dev))
310 python_countermeasures(dev, addr_size_words); 308 python_countermeasures(dev, addr_size_words);
311 309
312 if (phb_set_bus_ranges(dev, phb)) 310 if (phb_set_bus_ranges(dev, phb))
313 return 1; 311 return 1;
314 312
315 phb->arch_data = dev;
316 phb->ops = &rtas_pci_ops; 313 phb->ops = &rtas_pci_ops;
317 phb->buid = get_phb_buid(dev); 314 phb->buid = get_phb_buid(dev);
318 315
319 return 0; 316 return 0;
320} 317}
321 318
322static void __devinit add_linux_pci_domain(struct device_node *dev,
323 struct pci_controller *phb,
324 struct property *of_prop)
325{
326 memset(of_prop, 0, sizeof(struct property));
327 of_prop->name = "linux,pci-domain";
328 of_prop->length = sizeof(phb->global_number);
329 of_prop->value = (unsigned char *)&of_prop[1];
330 memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
331 prom_add_property(dev, of_prop);
332}
333
334static struct pci_controller * __init alloc_phb(struct device_node *dev,
335 unsigned int addr_size_words)
336{
337 struct pci_controller *phb;
338 struct property *of_prop;
339
340 phb = alloc_bootmem(sizeof(struct pci_controller));
341 if (phb == NULL)
342 return NULL;
343
344 of_prop = alloc_bootmem(sizeof(struct property) +
345 sizeof(phb->global_number));
346 if (!of_prop)
347 return NULL;
348
349 if (setup_phb(dev, phb, addr_size_words))
350 return NULL;
351
352 add_linux_pci_domain(dev, phb, of_prop);
353
354 return phb;
355}
356
357static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)
358{
359 struct pci_controller *phb;
360
361 phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
362 GFP_KERNEL);
363 if (phb == NULL)
364 return NULL;
365
366 if (setup_phb(dev, phb, addr_size_words))
367 return NULL;
368
369 phb->is_dynamic = 1;
370
371 /* TODO: linux,pci-domain? */
372
373 return phb;
374}
375
376unsigned long __init find_and_init_phbs(void) 319unsigned long __init find_and_init_phbs(void)
377{ 320{
378 struct device_node *node; 321 struct device_node *node;
@@ -397,10 +340,10 @@ unsigned long __init find_and_init_phbs(void)
397 if (node->type == NULL || strcmp(node->type, "pci") != 0) 340 if (node->type == NULL || strcmp(node->type, "pci") != 0)
398 continue; 341 continue;
399 342
400 phb = alloc_phb(node, root_size_cells); 343 phb = pcibios_alloc_controller(node);
401 if (!phb) 344 if (!phb)
402 continue; 345 continue;
403 346 setup_phb(node, phb, root_size_cells);
404 pci_process_bridge_OF_ranges(phb, node, 0); 347 pci_process_bridge_OF_ranges(phb, node, 0);
405 pci_setup_phb_io(phb, index == 0); 348 pci_setup_phb_io(phb, index == 0);
406#ifdef CONFIG_PPC_PSERIES 349#ifdef CONFIG_PPC_PSERIES
@@ -446,10 +389,10 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
446 root_size_cells = prom_n_size_cells(root); 389 root_size_cells = prom_n_size_cells(root);
447 390
448 primary = list_empty(&hose_list); 391 primary = list_empty(&hose_list);
449 phb = alloc_phb_dynamic(dn, root_size_cells); 392 phb = pcibios_alloc_controller(dn);
450 if (!phb) 393 if (!phb)
451 return NULL; 394 return NULL;
452 395 setup_phb(dn, phb, root_size_cells);
453 pci_process_bridge_OF_ranges(phb, dn, primary); 396 pci_process_bridge_OF_ranges(phb, dn, primary);
454 397
455 pci_setup_phb_io_dynamic(phb, primary); 398 pci_setup_phb_io_dynamic(phb, primary);
@@ -505,8 +448,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
505 } 448 }
506 449
507 list_del(&phb->list_node); 450 list_del(&phb->list_node);
508 if (phb->is_dynamic) 451 pcibios_free_controller(phb);
509 kfree(phb);
510 452
511 return 0; 453 return 0;
512} 454}
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 33e7f2c7f194..bd3eb4292b53 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -59,6 +59,7 @@
59#undef DEBUG 59#undef DEBUG
60 60
61#ifdef DEBUG 61#ifdef DEBUG
62#include <asm/udbg.h>
62#define DBG(fmt...) udbg_printf(fmt) 63#define DBG(fmt...) udbg_printf(fmt)
63#else 64#else
64#define DBG(fmt...) 65#define DBG(fmt...)
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 62dfc5b8d765..30374d2f88e5 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -49,15 +49,16 @@
49#include <asm/paca.h> 49#include <asm/paca.h>
50#endif 50#endif
51 51
52int smp_hw_index[NR_CPUS];
53struct thread_info *secondary_ti;
54
55#ifdef DEBUG 52#ifdef DEBUG
53#include <asm/udbg.h>
56#define DBG(fmt...) udbg_printf(fmt) 54#define DBG(fmt...) udbg_printf(fmt)
57#else 55#else
58#define DBG(fmt...) 56#define DBG(fmt...)
59#endif 57#endif
60 58
59int smp_hw_index[NR_CPUS];
60struct thread_info *secondary_ti;
61
61cpumask_t cpu_possible_map = CPU_MASK_NONE; 62cpumask_t cpu_possible_map = CPU_MASK_NONE;
62cpumask_t cpu_online_map = CPU_MASK_NONE; 63cpumask_t cpu_online_map = CPU_MASK_NONE;
63cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; 64cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 070b4b458aaf..de8479769bb7 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -130,6 +130,34 @@ unsigned long tb_last_stamp;
130 */ 130 */
131DEFINE_PER_CPU(unsigned long, last_jiffy); 131DEFINE_PER_CPU(unsigned long, last_jiffy);
132 132
133void __delay(unsigned long loops)
134{
135 unsigned long start;
136 int diff;
137
138 if (__USE_RTC()) {
139 start = get_rtcl();
140 do {
141 /* the RTCL register wraps at 1000000000 */
142 diff = get_rtcl() - start;
143 if (diff < 0)
144 diff += 1000000000;
145 } while (diff < loops);
146 } else {
147 start = get_tbl();
148 while (get_tbl() - start < loops)
149 HMT_low();
150 HMT_medium();
151 }
152}
153EXPORT_SYMBOL(__delay);
154
155void udelay(unsigned long usecs)
156{
157 __delay(tb_ticks_per_usec * usecs);
158}
159EXPORT_SYMBOL(udelay);
160
133static __inline__ void timer_check_rtc(void) 161static __inline__ void timer_check_rtc(void)
134{ 162{
135 /* 163 /*
diff --git a/arch/powerpc/kernel/vdso32/cacheflush.S b/arch/powerpc/kernel/vdso32/cacheflush.S
index c8db993574ee..09629aea3e47 100644
--- a/arch/powerpc/kernel/vdso32/cacheflush.S
+++ b/arch/powerpc/kernel/vdso32/cacheflush.S
@@ -35,6 +35,7 @@ V_FUNCTION_BEGIN(__kernel_sync_dicache)
35 subf r8,r6,r4 /* compute length */ 35 subf r8,r6,r4 /* compute length */
36 add r8,r8,r5 /* ensure we get enough */ 36 add r8,r8,r5 /* ensure we get enough */
37 srwi. r8,r8,7 /* compute line count */ 37 srwi. r8,r8,7 /* compute line count */
38 crclr cr0*4+so
38 beqlr /* nothing to do? */ 39 beqlr /* nothing to do? */
39 mtctr r8 40 mtctr r8
40 mr r3,r6 41 mr r3,r6
@@ -58,6 +59,7 @@ V_FUNCTION_END(__kernel_sync_dicache)
58 */ 59 */
59V_FUNCTION_BEGIN(__kernel_sync_dicache_p5) 60V_FUNCTION_BEGIN(__kernel_sync_dicache_p5)
60 .cfi_startproc 61 .cfi_startproc
62 crclr cr0*4+so
61 sync 63 sync
62 isync 64 isync
63 li r3,0 65 li r3,0
diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S
index f6b38472318d..4709f1d9542c 100644
--- a/arch/powerpc/kernel/vdso32/datapage.S
+++ b/arch/powerpc/kernel/vdso32/datapage.S
@@ -54,7 +54,6 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
54 .cfi_startproc 54 .cfi_startproc
55 mflr r12 55 mflr r12
56 .cfi_register lr,r12 56 .cfi_register lr,r12
57
58 mr r4,r3 57 mr r4,r3
59 bl __get_datapage@local 58 bl __get_datapage@local
60 mtlr r12 59 mtlr r12
@@ -63,6 +62,7 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
63 beqlr 62 beqlr
64 li r0,__NR_syscalls 63 li r0,__NR_syscalls
65 stw r0,0(r4) 64 stw r0,0(r4)
65 crclr cr0*4+so
66 blr 66 blr
67 .cfi_endproc 67 .cfi_endproc
68V_FUNCTION_END(__kernel_get_syscall_map) 68V_FUNCTION_END(__kernel_get_syscall_map)
@@ -80,6 +80,7 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
80 lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) 80 lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
81 lwz r3,CFG_TB_TICKS_PER_SEC(r3) 81 lwz r3,CFG_TB_TICKS_PER_SEC(r3)
82 mtlr r12 82 mtlr r12
83 crclr cr0*4+so
83 blr 84 blr
84 .cfi_endproc 85 .cfi_endproc
85V_FUNCTION_END(__kernel_get_tbfreq) 86V_FUNCTION_END(__kernel_get_tbfreq)
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
index 0a32a41d50b0..7eebff03a041 100644
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -59,6 +59,7 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday)
59 stw r5,TZONE_TZ_DSTTIME(r11) 59 stw r5,TZONE_TZ_DSTTIME(r11)
60 60
611: mtlr r12 611: mtlr r12
62 crclr cr0*4+so
62 li r3,0 63 li r3,0
63 blr 64 blr
64 65
@@ -117,6 +118,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
117 mulli r5,r5,1000 118 mulli r5,r5,1000
118 stw r5,TSPC32_TV_NSEC(r11) 119 stw r5,TSPC32_TV_NSEC(r11)
119 mtlr r12 120 mtlr r12
121 crclr cr0*4+so
120 li r3,0 122 li r3,0
121 blr 123 blr
122 124
@@ -185,6 +187,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
185 stw r4,TSPC32_TV_NSEC(r11) 187 stw r4,TSPC32_TV_NSEC(r11)
186 188
187 mtlr r12 189 mtlr r12
190 crclr cr0*4+so
188 li r3,0 191 li r3,0
189 blr 192 blr
190 193
@@ -219,6 +222,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
219 222
220 li r3,0 223 li r3,0
221 cmpli cr0,r4,0 224 cmpli cr0,r4,0
225 crclr cr0*4+so
222 beqlr 226 beqlr
223 lis r5,CLOCK_REALTIME_RES@h 227 lis r5,CLOCK_REALTIME_RES@h
224 ori r5,r5,CLOCK_REALTIME_RES@l 228 ori r5,r5,CLOCK_REALTIME_RES@l
diff --git a/arch/powerpc/kernel/vdso64/cacheflush.S b/arch/powerpc/kernel/vdso64/cacheflush.S
index d4a0ad28d534..cb4ae0a5edd0 100644
--- a/arch/powerpc/kernel/vdso64/cacheflush.S
+++ b/arch/powerpc/kernel/vdso64/cacheflush.S
@@ -35,6 +35,7 @@ V_FUNCTION_BEGIN(__kernel_sync_dicache)
35 subf r8,r6,r4 /* compute length */ 35 subf r8,r6,r4 /* compute length */
36 add r8,r8,r5 /* ensure we get enough */ 36 add r8,r8,r5 /* ensure we get enough */
37 srwi. r8,r8,7 /* compute line count */ 37 srwi. r8,r8,7 /* compute line count */
38 crclr cr0*4+so
38 beqlr /* nothing to do? */ 39 beqlr /* nothing to do? */
39 mtctr r8 40 mtctr r8
40 mr r3,r6 41 mr r3,r6
@@ -58,6 +59,7 @@ V_FUNCTION_END(__kernel_sync_dicache)
58 */ 59 */
59V_FUNCTION_BEGIN(__kernel_sync_dicache_p5) 60V_FUNCTION_BEGIN(__kernel_sync_dicache_p5)
60 .cfi_startproc 61 .cfi_startproc
62 crclr cr0*4+so
61 sync 63 sync
62 isync 64 isync
63 li r3,0 65 li r3,0
diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S
index 6393e4137bc7..3b2dd7d0c1eb 100644
--- a/arch/powerpc/kernel/vdso64/datapage.S
+++ b/arch/powerpc/kernel/vdso64/datapage.S
@@ -54,12 +54,12 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
54 .cfi_startproc 54 .cfi_startproc
55 mflr r12 55 mflr r12
56 .cfi_register lr,r12 56 .cfi_register lr,r12
57
58 mr r4,r3 57 mr r4,r3
59 bl V_LOCAL_FUNC(__get_datapage) 58 bl V_LOCAL_FUNC(__get_datapage)
60 mtlr r12 59 mtlr r12
61 addi r3,r3,CFG_SYSCALL_MAP64 60 addi r3,r3,CFG_SYSCALL_MAP64
62 cmpli cr0,r4,0 61 cmpli cr0,r4,0
62 crclr cr0*4+so
63 beqlr 63 beqlr
64 li r0,__NR_syscalls 64 li r0,__NR_syscalls
65 stw r0,0(r4) 65 stw r0,0(r4)
@@ -80,6 +80,7 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
80 bl V_LOCAL_FUNC(__get_datapage) 80 bl V_LOCAL_FUNC(__get_datapage)
81 ld r3,CFG_TB_TICKS_PER_SEC(r3) 81 ld r3,CFG_TB_TICKS_PER_SEC(r3)
82 mtlr r12 82 mtlr r12
83 crclr cr0*4+so
83 blr 84 blr
84 .cfi_endproc 85 .cfi_endproc
85V_FUNCTION_END(__kernel_get_tbfreq) 86V_FUNCTION_END(__kernel_get_tbfreq)
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
index 1a89094715cc..ccaeda5136d1 100644
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -52,6 +52,7 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday)
52 stw r4,TZONE_TZ_MINWEST(r10) 52 stw r4,TZONE_TZ_MINWEST(r10)
53 stw r5,TZONE_TZ_DSTTIME(r10) 53 stw r5,TZONE_TZ_DSTTIME(r10)
541: mtlr r12 541: mtlr r12
55 crclr cr0*4+so
55 li r3,0 /* always success */ 56 li r3,0 /* always success */
56 blr 57 blr
57 .cfi_endproc 58 .cfi_endproc
@@ -99,6 +100,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
99 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */ 100 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */
100 101
101 mtlr r12 102 mtlr r12
103 crclr cr0*4+so
102 li r3,0 104 li r3,0
103 blr 105 blr
104 106
@@ -159,6 +161,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
159 std r7,TSPC64_TV_NSEC(r11) 161 std r7,TSPC64_TV_NSEC(r11)
160 162
161 mtlr r12 163 mtlr r12
164 crclr cr0*4+so
162 li r3,0 165 li r3,0
163 blr 166 blr
164 167
@@ -193,6 +196,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
193 196
194 li r3,0 197 li r3,0
195 cmpli cr0,r4,0 198 cmpli cr0,r4,0
199 crclr cr0*4+so
196 beqlr 200 beqlr
197 lis r5,CLOCK_REALTIME_RES@h 201 lis r5,CLOCK_REALTIME_RES@h
198 ori r5,r5,CLOCK_REALTIME_RES@l 202 ori r5,r5,CLOCK_REALTIME_RES@l