aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-05-03 03:14:09 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-05-03 03:14:09 -0400
commit27b030d58c8e72fc7a95187a791bd9406e350f02 (patch)
treeab3bab7f39a5ce5bab65578a7e08fa4dfdeb198c /arch/ppc64
parent79d20b14a0d651f15b0ef9a22b6cf12d284a6d38 (diff)
parent6628465e33ca694bd8fd5c3cf4eb7ff9177bc694 (diff)
Merge with master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'arch/ppc64')
-rw-r--r--arch/ppc64/boot/addnote.c60
-rw-r--r--arch/ppc64/kernel/HvLpEvent.c2
-rw-r--r--arch/ppc64/kernel/nvram.c17
-rw-r--r--arch/ppc64/kernel/pSeries_hvCall.S8
-rw-r--r--arch/ppc64/kernel/prom.c4
-rw-r--r--arch/ppc64/kernel/prom_init.c115
-rw-r--r--arch/ppc64/kernel/ptrace.c5
-rw-r--r--arch/ppc64/kernel/ptrace32.c5
-rw-r--r--arch/ppc64/kernel/signal32.c4
-rw-r--r--arch/ppc64/kernel/smp.c12
-rw-r--r--arch/ppc64/kernel/time.c12
-rw-r--r--arch/ppc64/kernel/vdso32/Makefile2
-rw-r--r--arch/ppc64/kernel/vdso32/note.S25
-rw-r--r--arch/ppc64/kernel/vdso32/vdso32.lds.S3
-rw-r--r--arch/ppc64/kernel/vdso64/Makefile2
-rw-r--r--arch/ppc64/kernel/vdso64/note.S1
-rw-r--r--arch/ppc64/kernel/vdso64/vdso64.lds.S5
-rw-r--r--arch/ppc64/mm/hash_low.S9
-rw-r--r--arch/ppc64/mm/hugetlbpage.c45
-rw-r--r--arch/ppc64/mm/init.c198
-rw-r--r--arch/ppc64/mm/slb.c9
21 files changed, 375 insertions, 168 deletions
diff --git a/arch/ppc64/boot/addnote.c b/arch/ppc64/boot/addnote.c
index 66ff8103bf4d..719663a694bb 100644
--- a/arch/ppc64/boot/addnote.c
+++ b/arch/ppc64/boot/addnote.c
@@ -19,6 +19,7 @@
19#include <unistd.h> 19#include <unistd.h>
20#include <string.h> 20#include <string.h>
21 21
22/* CHRP note section */
22char arch[] = "PowerPC"; 23char arch[] = "PowerPC";
23 24
24#define N_DESCR 6 25#define N_DESCR 6
@@ -31,6 +32,29 @@ unsigned int descr[N_DESCR] = {
31 0x4000, /* load-base */ 32 0x4000, /* load-base */
32}; 33};
33 34
35/* RPA note section */
36char rpaname[] = "IBM,RPA-Client-Config";
37
38/*
39 * Note: setting ignore_my_client_config *should* mean that OF ignores
40 * all the other fields, but there is a firmware bug which means that
41 * it looks at the splpar field at least. So these values need to be
42 * reasonable.
43 */
44#define N_RPA_DESCR 8
45unsigned int rpanote[N_RPA_DESCR] = {
46 0, /* lparaffinity */
47 64, /* min_rmo_size */
48 0, /* min_rmo_percent */
49 40, /* max_pft_size */
50 1, /* splpar */
51 -1, /* min_load */
52 0, /* new_mem_def */
53 1, /* ignore_my_client_config */
54};
55
56#define ROUNDUP(len) (((len) + 3) & ~3)
57
34unsigned char buf[512]; 58unsigned char buf[512];
35 59
36#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) 60#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1]))
@@ -69,7 +93,7 @@ main(int ac, char **av)
69{ 93{
70 int fd, n, i; 94 int fd, n, i;
71 int ph, ps, np; 95 int ph, ps, np;
72 int nnote, ns; 96 int nnote, nnote2, ns;
73 97
74 if (ac != 2) { 98 if (ac != 2) {
75 fprintf(stderr, "Usage: %s elf-file\n", av[0]); 99 fprintf(stderr, "Usage: %s elf-file\n", av[0]);
@@ -81,7 +105,8 @@ main(int ac, char **av)
81 exit(1); 105 exit(1);
82 } 106 }
83 107
84 nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4; 108 nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr);
109 nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote);
85 110
86 n = read(fd, buf, sizeof(buf)); 111 n = read(fd, buf, sizeof(buf));
87 if (n < 0) { 112 if (n < 0) {
@@ -104,7 +129,7 @@ main(int ac, char **av)
104 np = GET_16BE(E_PHNUM); 129 np = GET_16BE(E_PHNUM);
105 if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) 130 if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
106 goto notelf; 131 goto notelf;
107 if (ph + (np + 1) * ps + nnote > n) 132 if (ph + (np + 2) * ps + nnote + nnote2 > n)
108 goto nospace; 133 goto nospace;
109 134
110 for (i = 0; i < np; ++i) { 135 for (i = 0; i < np; ++i) {
@@ -117,12 +142,12 @@ main(int ac, char **av)
117 } 142 }
118 143
119 /* XXX check that the area we want to use is all zeroes */ 144 /* XXX check that the area we want to use is all zeroes */
120 for (i = 0; i < ps + nnote; ++i) 145 for (i = 0; i < 2 * ps + nnote + nnote2; ++i)
121 if (buf[ph + i] != 0) 146 if (buf[ph + i] != 0)
122 goto nospace; 147 goto nospace;
123 148
124 /* fill in the program header entry */ 149 /* fill in the program header entry */
125 ns = ph + ps; 150 ns = ph + 2 * ps;
126 PUT_32BE(ph + PH_TYPE, PT_NOTE); 151 PUT_32BE(ph + PH_TYPE, PT_NOTE);
127 PUT_32BE(ph + PH_OFFSET, ns); 152 PUT_32BE(ph + PH_OFFSET, ns);
128 PUT_32BE(ph + PH_FILESZ, nnote); 153 PUT_32BE(ph + PH_FILESZ, nnote);
@@ -134,11 +159,26 @@ main(int ac, char **av)
134 PUT_32BE(ns + 8, 0x1275); 159 PUT_32BE(ns + 8, 0x1275);
135 strcpy(&buf[ns + 12], arch); 160 strcpy(&buf[ns + 12], arch);
136 ns += 12 + strlen(arch) + 1; 161 ns += 12 + strlen(arch) + 1;
137 for (i = 0; i < N_DESCR; ++i) 162 for (i = 0; i < N_DESCR; ++i, ns += 4)
138 PUT_32BE(ns + i * 4, descr[i]); 163 PUT_32BE(ns, descr[i]);
164
165 /* fill in the second program header entry and the RPA note area */
166 ph += ps;
167 PUT_32BE(ph + PH_TYPE, PT_NOTE);
168 PUT_32BE(ph + PH_OFFSET, ns);
169 PUT_32BE(ph + PH_FILESZ, nnote2);
170
171 /* fill in the note area we point to */
172 PUT_32BE(ns, strlen(rpaname) + 1);
173 PUT_32BE(ns + 4, sizeof(rpanote));
174 PUT_32BE(ns + 8, 0x12759999);
175 strcpy(&buf[ns + 12], rpaname);
176 ns += 12 + ROUNDUP(strlen(rpaname) + 1);
177 for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
178 PUT_32BE(ns, rpanote[i]);
139 179
140 /* Update the number of program headers */ 180 /* Update the number of program headers */
141 PUT_16BE(E_PHNUM, np + 1); 181 PUT_16BE(E_PHNUM, np + 2);
142 182
143 /* write back */ 183 /* write back */
144 lseek(fd, (long) 0, SEEK_SET); 184 lseek(fd, (long) 0, SEEK_SET);
@@ -155,11 +195,11 @@ main(int ac, char **av)
155 exit(0); 195 exit(0);
156 196
157 notelf: 197 notelf:
158 fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]); 198 fprintf(stderr, "%s does not appear to be an ELF file\n", av[1]);
159 exit(1); 199 exit(1);
160 200
161 nospace: 201 nospace:
162 fprintf(stderr, "sorry, I can't find space in %s to put the note\n", 202 fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
163 av[0]); 203 av[1]);
164 exit(1); 204 exit(1);
165} 205}
diff --git a/arch/ppc64/kernel/HvLpEvent.c b/arch/ppc64/kernel/HvLpEvent.c
index 9802beefa217..f8f19637f73f 100644
--- a/arch/ppc64/kernel/HvLpEvent.c
+++ b/arch/ppc64/kernel/HvLpEvent.c
@@ -45,7 +45,7 @@ int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType )
45 /* We now sleep until all other CPUs have scheduled. This ensures that 45 /* We now sleep until all other CPUs have scheduled. This ensures that
46 * the deletion is seen by all other CPUs, and that the deleted handler 46 * the deletion is seen by all other CPUs, and that the deleted handler
47 * isn't still running on another CPU when we return. */ 47 * isn't still running on another CPU when we return. */
48 synchronize_kernel(); 48 synchronize_rcu();
49 } 49 }
50 } 50 }
51 return rc; 51 return rc;
diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c
index b9069c2d1933..4e71781a4414 100644
--- a/arch/ppc64/kernel/nvram.c
+++ b/arch/ppc64/kernel/nvram.c
@@ -339,9 +339,9 @@ static int nvram_remove_os_partition(void)
339static int nvram_create_os_partition(void) 339static int nvram_create_os_partition(void)
340{ 340{
341 struct list_head * p; 341 struct list_head * p;
342 struct nvram_partition * part; 342 struct nvram_partition *part = NULL;
343 struct nvram_partition * new_part = NULL; 343 struct nvram_partition *new_part = NULL;
344 struct nvram_partition * free_part = NULL; 344 struct nvram_partition *free_part = NULL;
345 int seq_init[2] = { 0, 0 }; 345 int seq_init[2] = { 0, 0 };
346 loff_t tmp_index; 346 loff_t tmp_index;
347 long size = 0; 347 long size = 0;
@@ -364,13 +364,11 @@ static int nvram_create_os_partition(void)
364 free_part = part; 364 free_part = part;
365 } 365 }
366 } 366 }
367 if (!size) { 367 if (!size)
368 return -ENOSPC; 368 return -ENOSPC;
369 }
370 369
371 /* Create our OS partition */ 370 /* Create our OS partition */
372 new_part = (struct nvram_partition *) 371 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
373 kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
374 if (!new_part) { 372 if (!new_part) {
375 printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); 373 printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n");
376 return -ENOMEM; 374 return -ENOMEM;
@@ -379,7 +377,7 @@ static int nvram_create_os_partition(void)
379 new_part->index = free_part->index; 377 new_part->index = free_part->index;
380 new_part->header.signature = NVRAM_SIG_OS; 378 new_part->header.signature = NVRAM_SIG_OS;
381 new_part->header.length = size; 379 new_part->header.length = size;
382 sprintf(new_part->header.name, "ppc64,linux"); 380 strcpy(new_part->header.name, "ppc64,linux");
383 new_part->header.checksum = nvram_checksum(&new_part->header); 381 new_part->header.checksum = nvram_checksum(&new_part->header);
384 382
385 rc = nvram_write_header(new_part); 383 rc = nvram_write_header(new_part);
@@ -394,7 +392,8 @@ static int nvram_create_os_partition(void)
394 tmp_index = new_part->index + NVRAM_HEADER_LEN; 392 tmp_index = new_part->index + NVRAM_HEADER_LEN;
395 rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index); 393 rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);
396 if (rc <= 0) { 394 if (rc <= 0) {
397 printk(KERN_ERR "nvram_create_os_partition: nvram_write failed (%d)\n", rc); 395 printk(KERN_ERR "nvram_create_os_partition: nvram_write "
396 "failed (%d)\n", rc);
398 return rc; 397 return rc;
399 } 398 }
400 399
diff --git a/arch/ppc64/kernel/pSeries_hvCall.S b/arch/ppc64/kernel/pSeries_hvCall.S
index 0715d3038019..176e8da76466 100644
--- a/arch/ppc64/kernel/pSeries_hvCall.S
+++ b/arch/ppc64/kernel/pSeries_hvCall.S
@@ -28,6 +28,8 @@
28 unsigned long *out3); R10 28 unsigned long *out3); R10
29 */ 29 */
30_GLOBAL(plpar_hcall) 30_GLOBAL(plpar_hcall)
31 HMT_MEDIUM
32
31 mfcr r0 33 mfcr r0
32 34
33 std r8,STK_PARM(r8)(r1) /* Save out ptrs */ 35 std r8,STK_PARM(r8)(r1) /* Save out ptrs */
@@ -53,6 +55,8 @@ _GLOBAL(plpar_hcall)
53 55
54/* Simple interface with no output values (other than status) */ 56/* Simple interface with no output values (other than status) */
55_GLOBAL(plpar_hcall_norets) 57_GLOBAL(plpar_hcall_norets)
58 HMT_MEDIUM
59
56 mfcr r0 60 mfcr r0
57 stw r0,8(r1) 61 stw r0,8(r1)
58 62
@@ -75,6 +79,8 @@ _GLOBAL(plpar_hcall_norets)
75 unsigned long *out1); 120(R1) 79 unsigned long *out1); 120(R1)
76 */ 80 */
77_GLOBAL(plpar_hcall_8arg_2ret) 81_GLOBAL(plpar_hcall_8arg_2ret)
82 HMT_MEDIUM
83
78 mfcr r0 84 mfcr r0
79 ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */ 85 ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */
80 stw r0,8(r1) 86 stw r0,8(r1)
@@ -99,6 +105,8 @@ _GLOBAL(plpar_hcall_8arg_2ret)
99 unsigned long *out4); 112(R1) 105 unsigned long *out4); 112(R1)
100 */ 106 */
101_GLOBAL(plpar_hcall_4out) 107_GLOBAL(plpar_hcall_4out)
108 HMT_MEDIUM
109
102 mfcr r0 110 mfcr r0
103 stw r0,8(r1) 111 stw r0,8(r1)
104 112
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 45a4ad08fbc2..fe2946c58314 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -321,6 +321,10 @@ static int __devinit finish_node_interrupts(struct device_node *np,
321 char *name = get_property(ic->parent, "name", NULL); 321 char *name = get_property(ic->parent, "name", NULL);
322 if (name && !strcmp(name, "u3")) 322 if (name && !strcmp(name, "u3"))
323 np->intrs[intrcount].line += 128; 323 np->intrs[intrcount].line += 128;
324 else if (!(name && !strcmp(name, "mac-io")))
325 /* ignore other cascaded controllers, such as
326 the k2-sata-root */
327 break;
324 } 328 }
325 np->intrs[intrcount].sense = 1; 329 np->intrs[intrcount].sense = 1;
326 if (n > 1) 330 if (n > 1)
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index 8dffa9ae2623..35ec42de962e 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -493,6 +493,113 @@ static void __init early_cmdline_parse(void)
493} 493}
494 494
495/* 495/*
496 * To tell the firmware what our capabilities are, we have to pass
497 * it a fake 32-bit ELF header containing a couple of PT_NOTE sections
498 * that contain structures that contain the actual values.
499 */
500static struct fake_elf {
501 Elf32_Ehdr elfhdr;
502 Elf32_Phdr phdr[2];
503 struct chrpnote {
504 u32 namesz;
505 u32 descsz;
506 u32 type;
507 char name[8]; /* "PowerPC" */
508 struct chrpdesc {
509 u32 real_mode;
510 u32 real_base;
511 u32 real_size;
512 u32 virt_base;
513 u32 virt_size;
514 u32 load_base;
515 } chrpdesc;
516 } chrpnote;
517 struct rpanote {
518 u32 namesz;
519 u32 descsz;
520 u32 type;
521 char name[24]; /* "IBM,RPA-Client-Config" */
522 struct rpadesc {
523 u32 lpar_affinity;
524 u32 min_rmo_size;
525 u32 min_rmo_percent;
526 u32 max_pft_size;
527 u32 splpar;
528 u32 min_load;
529 u32 new_mem_def;
530 u32 ignore_me;
531 } rpadesc;
532 } rpanote;
533} fake_elf = {
534 .elfhdr = {
535 .e_ident = { 0x7f, 'E', 'L', 'F',
536 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
537 .e_type = ET_EXEC, /* yeah right */
538 .e_machine = EM_PPC,
539 .e_version = EV_CURRENT,
540 .e_phoff = offsetof(struct fake_elf, phdr),
541 .e_phentsize = sizeof(Elf32_Phdr),
542 .e_phnum = 2
543 },
544 .phdr = {
545 [0] = {
546 .p_type = PT_NOTE,
547 .p_offset = offsetof(struct fake_elf, chrpnote),
548 .p_filesz = sizeof(struct chrpnote)
549 }, [1] = {
550 .p_type = PT_NOTE,
551 .p_offset = offsetof(struct fake_elf, rpanote),
552 .p_filesz = sizeof(struct rpanote)
553 }
554 },
555 .chrpnote = {
556 .namesz = sizeof("PowerPC"),
557 .descsz = sizeof(struct chrpdesc),
558 .type = 0x1275,
559 .name = "PowerPC",
560 .chrpdesc = {
561 .real_mode = ~0U, /* ~0 means "don't care" */
562 .real_base = ~0U,
563 .real_size = ~0U,
564 .virt_base = ~0U,
565 .virt_size = ~0U,
566 .load_base = ~0U
567 },
568 },
569 .rpanote = {
570 .namesz = sizeof("IBM,RPA-Client-Config"),
571 .descsz = sizeof(struct rpadesc),
572 .type = 0x12759999,
573 .name = "IBM,RPA-Client-Config",
574 .rpadesc = {
575 .lpar_affinity = 0,
576 .min_rmo_size = 64, /* in megabytes */
577 .min_rmo_percent = 0,
578 .max_pft_size = 48, /* 2^48 bytes max PFT size */
579 .splpar = 1,
580 .min_load = ~0U,
581 .new_mem_def = 0
582 }
583 }
584};
585
586static void __init prom_send_capabilities(void)
587{
588 unsigned long offset = reloc_offset();
589 ihandle elfloader;
590 int ret;
591
592 elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
593 if (elfloader == 0) {
594 prom_printf("couldn't open /packages/elf-loader\n");
595 return;
596 }
597 ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"),
598 elfloader, ADDR(&fake_elf));
599 call_prom("close", 1, 0, elfloader);
600}
601
602/*
496 * Memory allocation strategy... our layout is normally: 603 * Memory allocation strategy... our layout is normally:
497 * 604 *
498 * at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd 605 * at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd
@@ -1448,6 +1555,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1448 } 1555 }
1449} 1556}
1450 1557
1558/*
1559 * The Open Firmware 1275 specification states properties must be 31 bytes or
1560 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
1561 */
1562#define MAX_PROPERTY_NAME 64
1563
1451static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, 1564static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1452 unsigned long *mem_end) 1565 unsigned long *mem_end)
1453{ 1566{
@@ -1457,7 +1570,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1457 unsigned long soff; 1570 unsigned long soff;
1458 unsigned char *valp; 1571 unsigned char *valp;
1459 unsigned long offset = reloc_offset(); 1572 unsigned long offset = reloc_offset();
1460 char pname[32]; 1573 char pname[MAX_PROPERTY_NAME];
1461 char *path; 1574 char *path;
1462 1575
1463 path = RELOC(prom_scratch); 1576 path = RELOC(prom_scratch);
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index 3c76333ec3a9..9f8c6087ae56 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -28,6 +28,7 @@
28#include <linux/security.h> 28#include <linux/security.h>
29#include <linux/audit.h> 29#include <linux/audit.h>
30#include <linux/seccomp.h> 30#include <linux/seccomp.h>
31#include <linux/signal.h>
31 32
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33#include <asm/page.h> 34#include <asm/page.h>
@@ -162,7 +163,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
162 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ 163 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
163 case PTRACE_CONT: { /* restart after signal. */ 164 case PTRACE_CONT: { /* restart after signal. */
164 ret = -EIO; 165 ret = -EIO;
165 if ((unsigned long) data > _NSIG) 166 if (!valid_signal(data))
166 break; 167 break;
167 if (request == PTRACE_SYSCALL) 168 if (request == PTRACE_SYSCALL)
168 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 169 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -194,7 +195,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
194 195
195 case PTRACE_SINGLESTEP: { /* set the trap flag. */ 196 case PTRACE_SINGLESTEP: { /* set the trap flag. */
196 ret = -EIO; 197 ret = -EIO;
197 if ((unsigned long) data > _NSIG) 198 if (!valid_signal(data))
198 break; 199 break;
199 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 200 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
200 set_single_step(child); 201 set_single_step(child);
diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
index ee81b1b776cc..16436426c7e2 100644
--- a/arch/ppc64/kernel/ptrace32.c
+++ b/arch/ppc64/kernel/ptrace32.c
@@ -26,6 +26,7 @@
26#include <linux/ptrace.h> 26#include <linux/ptrace.h>
27#include <linux/user.h> 27#include <linux/user.h>
28#include <linux/security.h> 28#include <linux/security.h>
29#include <linux/signal.h>
29 30
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
31#include <asm/page.h> 32#include <asm/page.h>
@@ -293,7 +294,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
293 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ 294 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
294 case PTRACE_CONT: { /* restart after signal. */ 295 case PTRACE_CONT: { /* restart after signal. */
295 ret = -EIO; 296 ret = -EIO;
296 if ((unsigned long) data > _NSIG) 297 if (!valid_signal(data))
297 break; 298 break;
298 if (request == PTRACE_SYSCALL) 299 if (request == PTRACE_SYSCALL)
299 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 300 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -325,7 +326,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
325 326
326 case PTRACE_SINGLESTEP: { /* set the trap flag. */ 327 case PTRACE_SINGLESTEP: { /* set the trap flag. */
327 ret = -EIO; 328 ret = -EIO;
328 if ((unsigned long) data > _NSIG) 329 if (!valid_signal(data))
329 break; 330 break;
330 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 331 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
331 set_single_step(child); 332 set_single_step(child);
diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
index b0e167db6af9..3c2fa5c284c0 100644
--- a/arch/ppc64/kernel/signal32.c
+++ b/arch/ppc64/kernel/signal32.c
@@ -657,7 +657,7 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
657 657
658 /* Save user registers on the stack */ 658 /* Save user registers on the stack */
659 frame = &rt_sf->uc.uc_mcontext; 659 frame = &rt_sf->uc.uc_mcontext;
660 if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) 660 if (put_user(regs->gpr[1], (u32 __user *)newsp))
661 goto badframe; 661 goto badframe;
662 662
663 if (vdso32_rt_sigtramp && current->thread.vdso_base) { 663 if (vdso32_rt_sigtramp && current->thread.vdso_base) {
@@ -842,7 +842,7 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka,
842 regs->link = (unsigned long) frame->mctx.tramp; 842 regs->link = (unsigned long) frame->mctx.tramp;
843 } 843 }
844 844
845 if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) 845 if (put_user(regs->gpr[1], (u32 __user *)newsp))
846 goto badframe; 846 goto badframe;
847 regs->gpr[1] = (unsigned long) newsp; 847 regs->gpr[1] = (unsigned long) newsp;
848 regs->gpr[3] = sig; 848 regs->gpr[3] = sig;
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
index 1c92da3e4525..3b906cd94037 100644
--- a/arch/ppc64/kernel/smp.c
+++ b/arch/ppc64/kernel/smp.c
@@ -125,7 +125,7 @@ void __devinit smp_generic_kick_cpu(int nr)
125 * the processor will continue on to secondary_start 125 * the processor will continue on to secondary_start
126 */ 126 */
127 paca[nr].cpu_start = 1; 127 paca[nr].cpu_start = 1;
128 mb(); 128 smp_mb();
129} 129}
130 130
131#endif /* CONFIG_PPC_MULTIPLATFORM */ 131#endif /* CONFIG_PPC_MULTIPLATFORM */
@@ -256,7 +256,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
256 } 256 }
257 257
258 call_data = &data; 258 call_data = &data;
259 wmb(); 259 smp_wmb();
260 /* Send a message to all other CPUs and wait for them to respond */ 260 /* Send a message to all other CPUs and wait for them to respond */
261 smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION); 261 smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION);
262 262
@@ -431,7 +431,7 @@ int generic_cpu_enable(unsigned int cpu)
431 431
432 /* get the target out of it's holding state */ 432 /* get the target out of it's holding state */
433 per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; 433 per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
434 wmb(); 434 smp_wmb();
435 435
436 while (!cpu_online(cpu)) 436 while (!cpu_online(cpu))
437 cpu_relax(); 437 cpu_relax();
@@ -447,7 +447,7 @@ void generic_cpu_die(unsigned int cpu)
447 int i; 447 int i;
448 448
449 for (i = 0; i < 100; i++) { 449 for (i = 0; i < 100; i++) {
450 rmb(); 450 smp_rmb();
451 if (per_cpu(cpu_state, cpu) == CPU_DEAD) 451 if (per_cpu(cpu_state, cpu) == CPU_DEAD)
452 return; 452 return;
453 msleep(100); 453 msleep(100);
@@ -463,7 +463,7 @@ void generic_mach_cpu_die(void)
463 cpu = smp_processor_id(); 463 cpu = smp_processor_id();
464 printk(KERN_DEBUG "CPU%d offline\n", cpu); 464 printk(KERN_DEBUG "CPU%d offline\n", cpu);
465 __get_cpu_var(cpu_state) = CPU_DEAD; 465 __get_cpu_var(cpu_state) = CPU_DEAD;
466 wmb(); 466 smp_wmb();
467 while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) 467 while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
468 cpu_relax(); 468 cpu_relax();
469 469
@@ -515,7 +515,7 @@ int __devinit __cpu_up(unsigned int cpu)
515 * be written out to main store before we release 515 * be written out to main store before we release
516 * the processor. 516 * the processor.
517 */ 517 */
518 mb(); 518 smp_mb();
519 519
520 /* wake up cpus */ 520 /* wake up cpus */
521 DBG("smp: kicking cpu %d\n", cpu); 521 DBG("smp: kicking cpu %d\n", cpu);
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 77ded5a363b6..772a465b49f9 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -221,15 +221,15 @@ static __inline__ void timer_recalc_offset(unsigned long cur_tb)
221 temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs; 221 temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs;
222 temp_varp->tb_orig_stamp = new_tb_orig_stamp; 222 temp_varp->tb_orig_stamp = new_tb_orig_stamp;
223 temp_varp->stamp_xsec = new_stamp_xsec; 223 temp_varp->stamp_xsec = new_stamp_xsec;
224 mb(); 224 smp_mb();
225 do_gtod.varp = temp_varp; 225 do_gtod.varp = temp_varp;
226 do_gtod.var_idx = temp_idx; 226 do_gtod.var_idx = temp_idx;
227 227
228 ++(systemcfg->tb_update_count); 228 ++(systemcfg->tb_update_count);
229 wmb(); 229 smp_wmb();
230 systemcfg->tb_orig_stamp = new_tb_orig_stamp; 230 systemcfg->tb_orig_stamp = new_tb_orig_stamp;
231 systemcfg->stamp_xsec = new_stamp_xsec; 231 systemcfg->stamp_xsec = new_stamp_xsec;
232 wmb(); 232 smp_wmb();
233 ++(systemcfg->tb_update_count); 233 ++(systemcfg->tb_update_count);
234} 234}
235 235
@@ -648,7 +648,7 @@ void ppc_adjtimex(void)
648 temp_varp->tb_to_xs = new_tb_to_xs; 648 temp_varp->tb_to_xs = new_tb_to_xs;
649 temp_varp->stamp_xsec = new_stamp_xsec; 649 temp_varp->stamp_xsec = new_stamp_xsec;
650 temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp; 650 temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp;
651 mb(); 651 smp_mb();
652 do_gtod.varp = temp_varp; 652 do_gtod.varp = temp_varp;
653 do_gtod.var_idx = temp_idx; 653 do_gtod.var_idx = temp_idx;
654 654
@@ -662,10 +662,10 @@ void ppc_adjtimex(void)
662 * loops back and reads them again until this criteria is met. 662 * loops back and reads them again until this criteria is met.
663 */ 663 */
664 ++(systemcfg->tb_update_count); 664 ++(systemcfg->tb_update_count);
665 wmb(); 665 smp_wmb();
666 systemcfg->tb_to_xs = new_tb_to_xs; 666 systemcfg->tb_to_xs = new_tb_to_xs;
667 systemcfg->stamp_xsec = new_stamp_xsec; 667 systemcfg->stamp_xsec = new_stamp_xsec;
668 wmb(); 668 smp_wmb();
669 ++(systemcfg->tb_update_count); 669 ++(systemcfg->tb_update_count);
670 670
671 write_sequnlock_irqrestore( &xtime_lock, flags ); 671 write_sequnlock_irqrestore( &xtime_lock, flags );
diff --git a/arch/ppc64/kernel/vdso32/Makefile b/arch/ppc64/kernel/vdso32/Makefile
index ede2f7e477c2..0b1b0df973eb 100644
--- a/arch/ppc64/kernel/vdso32/Makefile
+++ b/arch/ppc64/kernel/vdso32/Makefile
@@ -1,7 +1,7 @@
1 1
2# List of files in the vdso, has to be asm only for now 2# List of files in the vdso, has to be asm only for now
3 3
4obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o 4obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
5 5
6# Build rules 6# Build rules
7 7
diff --git a/arch/ppc64/kernel/vdso32/note.S b/arch/ppc64/kernel/vdso32/note.S
new file mode 100644
index 000000000000..d4b5be4f3d5f
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/note.S
@@ -0,0 +1,25 @@
1/*
2 * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
3 * Here we can supply some information useful to userland.
4 */
5
6#include <linux/uts.h>
7#include <linux/version.h>
8
9#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \
10 .section name, flags; \
11 .balign 4; \
12 .long 1f - 0f; /* name length */ \
13 .long 3f - 2f; /* data length */ \
14 .long type; /* note type */ \
150: .asciz vendor; /* vendor name */ \
161: .balign 4; \
172:
18
19#define ASM_ELF_NOTE_END \
203: .balign 4; /* pad out section */ \
21 .previous
22
23 ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0)
24 .long LINUX_VERSION_CODE
25 ASM_ELF_NOTE_END
diff --git a/arch/ppc64/kernel/vdso32/vdso32.lds.S b/arch/ppc64/kernel/vdso32/vdso32.lds.S
index cca27bd03a57..11290c902ba3 100644
--- a/arch/ppc64/kernel/vdso32/vdso32.lds.S
+++ b/arch/ppc64/kernel/vdso32/vdso32.lds.S
@@ -20,6 +20,8 @@ SECTIONS
20 .gnu.version_d : { *(.gnu.version_d) } 20 .gnu.version_d : { *(.gnu.version_d) }
21 .gnu.version_r : { *(.gnu.version_r) } 21 .gnu.version_r : { *(.gnu.version_r) }
22 22
23 .note : { *(.note.*) } :text :note
24
23 . = ALIGN (16); 25 . = ALIGN (16);
24 .text : 26 .text :
25 { 27 {
@@ -87,6 +89,7 @@ SECTIONS
87PHDRS 89PHDRS
88{ 90{
89 text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ 91 text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
92 note PT_NOTE FLAGS(4); /* PF_R */
90 dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ 93 dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
91 eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ 94 eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
92} 95}
diff --git a/arch/ppc64/kernel/vdso64/Makefile b/arch/ppc64/kernel/vdso64/Makefile
index bd3f70b1a384..ab39988452cc 100644
--- a/arch/ppc64/kernel/vdso64/Makefile
+++ b/arch/ppc64/kernel/vdso64/Makefile
@@ -1,6 +1,6 @@
1# List of files in the vdso, has to be asm only for now 1# List of files in the vdso, has to be asm only for now
2 2
3obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o 3obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
4 4
5# Build rules 5# Build rules
6 6
diff --git a/arch/ppc64/kernel/vdso64/note.S b/arch/ppc64/kernel/vdso64/note.S
new file mode 100644
index 000000000000..dc2a509f7e8a
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/note.S
@@ -0,0 +1 @@
#include "../vdso32/note.S"
diff --git a/arch/ppc64/kernel/vdso64/vdso64.lds.S b/arch/ppc64/kernel/vdso64/vdso64.lds.S
index 942c815c7bc7..9cb28181da80 100644
--- a/arch/ppc64/kernel/vdso64/vdso64.lds.S
+++ b/arch/ppc64/kernel/vdso64/vdso64.lds.S
@@ -18,12 +18,14 @@ SECTIONS
18 .gnu.version_d : { *(.gnu.version_d) } 18 .gnu.version_d : { *(.gnu.version_d) }
19 .gnu.version_r : { *(.gnu.version_r) } 19 .gnu.version_r : { *(.gnu.version_r) }
20 20
21 .note : { *(.note.*) } :text :note
22
21 . = ALIGN (16); 23 . = ALIGN (16);
22 .text : 24 .text :
23 { 25 {
24 *(.text .stub .text.* .gnu.linkonce.t.*) 26 *(.text .stub .text.* .gnu.linkonce.t.*)
25 *(.sfpr .glink) 27 *(.sfpr .glink)
26 } 28 } :text
27 PROVIDE (__etext = .); 29 PROVIDE (__etext = .);
28 PROVIDE (_etext = .); 30 PROVIDE (_etext = .);
29 PROVIDE (etext = .); 31 PROVIDE (etext = .);
@@ -88,6 +90,7 @@ SECTIONS
88PHDRS 90PHDRS
89{ 91{
90 text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ 92 text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
93 note PT_NOTE FLAGS(4); /* PF_R */
91 dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ 94 dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
92 eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ 95 eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
93} 96}
diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S
index 8c0156a37001..c23d46956dd9 100644
--- a/arch/ppc64/mm/hash_low.S
+++ b/arch/ppc64/mm/hash_low.S
@@ -85,7 +85,10 @@ _GLOBAL(__hash_page)
85 bne- htab_wrong_access 85 bne- htab_wrong_access
86 /* Check if PTE is busy */ 86 /* Check if PTE is busy */
87 andi. r0,r31,_PAGE_BUSY 87 andi. r0,r31,_PAGE_BUSY
88 bne- 1b 88 /* If so, just bail out and refault if needed. Someone else
89 * is changing this PTE anyway and might hash it.
90 */
91 bne- bail_ok
89 /* Prepare new PTE value (turn access RW into DIRTY, then 92 /* Prepare new PTE value (turn access RW into DIRTY, then
90 * add BUSY,HASHPTE and ACCESSED) 93 * add BUSY,HASHPTE and ACCESSED)
91 */ 94 */
@@ -215,6 +218,10 @@ _GLOBAL(htab_call_hpte_remove)
215 /* Try all again */ 218 /* Try all again */
216 b htab_insert_pte 219 b htab_insert_pte
217 220
221bail_ok:
222 li r3,0
223 b bail
224
218htab_pte_insert_ok: 225htab_pte_insert_ok:
219 /* Insert slot number & secondary bit in PTE */ 226 /* Insert slot number & secondary bit in PTE */
220 rldimi r30,r3,12,63-15 227 rldimi r30,r3,12,63-15
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index 390296efe3e0..d3bf86a5c1ad 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -42,7 +42,7 @@ static inline int hugepgd_index(unsigned long addr)
42 return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT; 42 return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT;
43} 43}
44 44
45static pgd_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr) 45static pud_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
46{ 46{
47 int index; 47 int index;
48 48
@@ -52,21 +52,21 @@ static pgd_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
52 52
53 index = hugepgd_index(addr); 53 index = hugepgd_index(addr);
54 BUG_ON(index >= PTRS_PER_HUGEPGD); 54 BUG_ON(index >= PTRS_PER_HUGEPGD);
55 return mm->context.huge_pgdir + index; 55 return (pud_t *)(mm->context.huge_pgdir + index);
56} 56}
57 57
58static inline pte_t *hugepte_offset(pgd_t *dir, unsigned long addr) 58static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr)
59{ 59{
60 int index; 60 int index;
61 61
62 if (pgd_none(*dir)) 62 if (pud_none(*dir))
63 return NULL; 63 return NULL;
64 64
65 index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE; 65 index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE;
66 return (pte_t *)pgd_page(*dir) + index; 66 return (pte_t *)pud_page(*dir) + index;
67} 67}
68 68
69static pgd_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr) 69static pud_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
70{ 70{
71 BUG_ON(! in_hugepage_area(mm->context, addr)); 71 BUG_ON(! in_hugepage_area(mm->context, addr));
72 72
@@ -90,10 +90,9 @@ static pgd_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
90 return hugepgd_offset(mm, addr); 90 return hugepgd_offset(mm, addr);
91} 91}
92 92
93static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir, 93static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr)
94 unsigned long addr)
95{ 94{
96 if (! pgd_present(*dir)) { 95 if (! pud_present(*dir)) {
97 pte_t *new; 96 pte_t *new;
98 97
99 spin_unlock(&mm->page_table_lock); 98 spin_unlock(&mm->page_table_lock);
@@ -104,7 +103,7 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir,
104 * Because we dropped the lock, we should re-check the 103 * Because we dropped the lock, we should re-check the
105 * entry, as somebody else could have populated it.. 104 * entry, as somebody else could have populated it..
106 */ 105 */
107 if (pgd_present(*dir)) { 106 if (pud_present(*dir)) {
108 if (new) 107 if (new)
109 kmem_cache_free(zero_cache, new); 108 kmem_cache_free(zero_cache, new);
110 } else { 109 } else {
@@ -115,7 +114,7 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir,
115 ptepage = virt_to_page(new); 114 ptepage = virt_to_page(new);
116 ptepage->mapping = (void *) mm; 115 ptepage->mapping = (void *) mm;
117 ptepage->index = addr & HUGEPGDIR_MASK; 116 ptepage->index = addr & HUGEPGDIR_MASK;
118 pgd_populate(mm, dir, new); 117 pud_populate(mm, dir, new);
119 } 118 }
120 } 119 }
121 120
@@ -124,28 +123,28 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir,
124 123
125static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) 124static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
126{ 125{
127 pgd_t *pgd; 126 pud_t *pud;
128 127
129 BUG_ON(! in_hugepage_area(mm->context, addr)); 128 BUG_ON(! in_hugepage_area(mm->context, addr));
130 129
131 pgd = hugepgd_offset(mm, addr); 130 pud = hugepgd_offset(mm, addr);
132 if (! pgd) 131 if (! pud)
133 return NULL; 132 return NULL;
134 133
135 return hugepte_offset(pgd, addr); 134 return hugepte_offset(pud, addr);
136} 135}
137 136
138static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) 137static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
139{ 138{
140 pgd_t *pgd; 139 pud_t *pud;
141 140
142 BUG_ON(! in_hugepage_area(mm->context, addr)); 141 BUG_ON(! in_hugepage_area(mm->context, addr));
143 142
144 pgd = hugepgd_alloc(mm, addr); 143 pud = hugepgd_alloc(mm, addr);
145 if (! pgd) 144 if (! pud)
146 return NULL; 145 return NULL;
147 146
148 return hugepte_alloc(mm, pgd, addr); 147 return hugepte_alloc(mm, pud, addr);
149} 148}
150 149
151static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, 150static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
@@ -709,10 +708,10 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm)
709 708
710 /* cleanup any hugepte pages leftover */ 709 /* cleanup any hugepte pages leftover */
711 for (i = 0; i < PTRS_PER_HUGEPGD; i++) { 710 for (i = 0; i < PTRS_PER_HUGEPGD; i++) {
712 pgd_t *pgd = pgdir + i; 711 pud_t *pud = (pud_t *)(pgdir + i);
713 712
714 if (! pgd_none(*pgd)) { 713 if (! pud_none(*pud)) {
715 pte_t *pte = (pte_t *)pgd_page(*pgd); 714 pte_t *pte = (pte_t *)pud_page(*pud);
716 struct page *ptepage = virt_to_page(pte); 715 struct page *ptepage = virt_to_page(pte);
717 716
718 ptepage->mapping = NULL; 717 ptepage->mapping = NULL;
@@ -720,7 +719,7 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm)
720 BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE)); 719 BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE));
721 kmem_cache_free(zero_cache, pte); 720 kmem_cache_free(zero_cache, pte);
722 } 721 }
723 pgd_clear(pgd); 722 pud_clear(pud);
724 } 723 }
725 724
726 BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE)); 725 BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE));
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index a7149b9fc35c..cf33d7ec2e29 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -136,14 +136,78 @@ void iounmap(volatile void __iomem *addr)
136 136
137#else 137#else
138 138
139static void unmap_im_area_pte(pmd_t *pmd, unsigned long addr,
140 unsigned long end)
141{
142 pte_t *pte;
143
144 pte = pte_offset_kernel(pmd, addr);
145 do {
146 pte_t ptent = ptep_get_and_clear(&ioremap_mm, addr, pte);
147 WARN_ON(!pte_none(ptent) && !pte_present(ptent));
148 } while (pte++, addr += PAGE_SIZE, addr != end);
149}
150
151static inline void unmap_im_area_pmd(pud_t *pud, unsigned long addr,
152 unsigned long end)
153{
154 pmd_t *pmd;
155 unsigned long next;
156
157 pmd = pmd_offset(pud, addr);
158 do {
159 next = pmd_addr_end(addr, end);
160 if (pmd_none_or_clear_bad(pmd))
161 continue;
162 unmap_im_area_pte(pmd, addr, next);
163 } while (pmd++, addr = next, addr != end);
164}
165
166static inline void unmap_im_area_pud(pgd_t *pgd, unsigned long addr,
167 unsigned long end)
168{
169 pud_t *pud;
170 unsigned long next;
171
172 pud = pud_offset(pgd, addr);
173 do {
174 next = pud_addr_end(addr, end);
175 if (pud_none_or_clear_bad(pud))
176 continue;
177 unmap_im_area_pmd(pud, addr, next);
178 } while (pud++, addr = next, addr != end);
179}
180
181static void unmap_im_area(unsigned long addr, unsigned long end)
182{
183 struct mm_struct *mm = &ioremap_mm;
184 unsigned long next;
185 pgd_t *pgd;
186
187 spin_lock(&mm->page_table_lock);
188
189 pgd = pgd_offset_i(addr);
190 flush_cache_vunmap(addr, end);
191 do {
192 next = pgd_addr_end(addr, end);
193 if (pgd_none_or_clear_bad(pgd))
194 continue;
195 unmap_im_area_pud(pgd, addr, next);
196 } while (pgd++, addr = next, addr != end);
197 flush_tlb_kernel_range(start, end);
198
199 spin_unlock(&mm->page_table_lock);
200}
201
139/* 202/*
140 * map_io_page currently only called by __ioremap 203 * map_io_page currently only called by __ioremap
141 * map_io_page adds an entry to the ioremap page table 204 * map_io_page adds an entry to the ioremap page table
142 * and adds an entry to the HPT, possibly bolting it 205 * and adds an entry to the HPT, possibly bolting it
143 */ 206 */
144static void map_io_page(unsigned long ea, unsigned long pa, int flags) 207static int map_io_page(unsigned long ea, unsigned long pa, int flags)
145{ 208{
146 pgd_t *pgdp; 209 pgd_t *pgdp;
210 pud_t *pudp;
147 pmd_t *pmdp; 211 pmd_t *pmdp;
148 pte_t *ptep; 212 pte_t *ptep;
149 unsigned long vsid; 213 unsigned long vsid;
@@ -151,9 +215,15 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags)
151 if (mem_init_done) { 215 if (mem_init_done) {
152 spin_lock(&ioremap_mm.page_table_lock); 216 spin_lock(&ioremap_mm.page_table_lock);
153 pgdp = pgd_offset_i(ea); 217 pgdp = pgd_offset_i(ea);
154 pmdp = pmd_alloc(&ioremap_mm, pgdp, ea); 218 pudp = pud_alloc(&ioremap_mm, pgdp, ea);
219 if (!pudp)
220 return -ENOMEM;
221 pmdp = pmd_alloc(&ioremap_mm, pudp, ea);
222 if (!pmdp)
223 return -ENOMEM;
155 ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea); 224 ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
156 225 if (!ptep)
226 return -ENOMEM;
157 pa = abs_to_phys(pa); 227 pa = abs_to_phys(pa);
158 set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, 228 set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
159 __pgprot(flags))); 229 __pgprot(flags)));
@@ -181,6 +251,7 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags)
181 panic("map_io_page: could not insert mapping"); 251 panic("map_io_page: could not insert mapping");
182 } 252 }
183 } 253 }
254 return 0;
184} 255}
185 256
186 257
@@ -194,9 +265,14 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
194 flags |= pgprot_val(PAGE_KERNEL); 265 flags |= pgprot_val(PAGE_KERNEL);
195 266
196 for (i = 0; i < size; i += PAGE_SIZE) 267 for (i = 0; i < size; i += PAGE_SIZE)
197 map_io_page(ea+i, pa+i, flags); 268 if (map_io_page(ea+i, pa+i, flags))
269 goto failure;
198 270
199 return (void __iomem *) (ea + (addr & ~PAGE_MASK)); 271 return (void __iomem *) (ea + (addr & ~PAGE_MASK));
272 failure:
273 if (mem_init_done)
274 unmap_im_area(ea, ea + size);
275 return NULL;
200} 276}
201 277
202 278
@@ -206,10 +282,11 @@ ioremap(unsigned long addr, unsigned long size)
206 return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED); 282 return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
207} 283}
208 284
209void __iomem * 285void __iomem * __ioremap(unsigned long addr, unsigned long size,
210__ioremap(unsigned long addr, unsigned long size, unsigned long flags) 286 unsigned long flags)
211{ 287{
212 unsigned long pa, ea; 288 unsigned long pa, ea;
289 void __iomem *ret;
213 290
214 /* 291 /*
215 * Choose an address to map it to. 292 * Choose an address to map it to.
@@ -232,12 +309,16 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
232 if (area == NULL) 309 if (area == NULL)
233 return NULL; 310 return NULL;
234 ea = (unsigned long)(area->addr); 311 ea = (unsigned long)(area->addr);
312 ret = __ioremap_com(addr, pa, ea, size, flags);
313 if (!ret)
314 im_free(area->addr);
235 } else { 315 } else {
236 ea = ioremap_bot; 316 ea = ioremap_bot;
237 ioremap_bot += size; 317 ret = __ioremap_com(addr, pa, ea, size, flags);
318 if (ret)
319 ioremap_bot += size;
238 } 320 }
239 321 return ret;
240 return __ioremap_com(addr, pa, ea, size, flags);
241} 322}
242 323
243#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) 324#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
@@ -246,6 +327,7 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
246 unsigned long size, unsigned long flags) 327 unsigned long size, unsigned long flags)
247{ 328{
248 struct vm_struct *area; 329 struct vm_struct *area;
330 void __iomem *ret;
249 331
250 /* For now, require page-aligned values for pa, ea, and size */ 332 /* For now, require page-aligned values for pa, ea, and size */
251 if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) || 333 if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
@@ -276,7 +358,12 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
276 } 358 }
277 } 359 }
278 360
279 if (__ioremap_com(pa, pa, ea, size, flags) != (void *) ea) { 361 ret = __ioremap_com(pa, pa, ea, size, flags);
362 if (ret == NULL) {
363 printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
364 return 1;
365 }
366 if (ret != (void *) ea) {
280 printk(KERN_ERR "__ioremap_com() returned unexpected addr\n"); 367 printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
281 return 1; 368 return 1;
282 } 369 }
@@ -284,69 +371,6 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
284 return 0; 371 return 0;
285} 372}
286 373
287static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
288 unsigned long size)
289{
290 unsigned long base, end;
291 pte_t *pte;
292
293 if (pmd_none(*pmd))
294 return;
295 if (pmd_bad(*pmd)) {
296 pmd_ERROR(*pmd);
297 pmd_clear(pmd);
298 return;
299 }
300
301 pte = pte_offset_kernel(pmd, address);
302 base = address & PMD_MASK;
303 address &= ~PMD_MASK;
304 end = address + size;
305 if (end > PMD_SIZE)
306 end = PMD_SIZE;
307
308 do {
309 pte_t page;
310 page = ptep_get_and_clear(&ioremap_mm, base + address, pte);
311 address += PAGE_SIZE;
312 pte++;
313 if (pte_none(page))
314 continue;
315 if (pte_present(page))
316 continue;
317 printk(KERN_CRIT "Whee.. Swapped out page in kernel page"
318 " table\n");
319 } while (address < end);
320}
321
322static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
323 unsigned long size)
324{
325 unsigned long base, end;
326 pmd_t *pmd;
327
328 if (pgd_none(*dir))
329 return;
330 if (pgd_bad(*dir)) {
331 pgd_ERROR(*dir);
332 pgd_clear(dir);
333 return;
334 }
335
336 pmd = pmd_offset(dir, address);
337 base = address & PGDIR_MASK;
338 address &= ~PGDIR_MASK;
339 end = address + size;
340 if (end > PGDIR_SIZE)
341 end = PGDIR_SIZE;
342
343 do {
344 unmap_im_area_pte(pmd, base + address, end - address);
345 address = (address + PMD_SIZE) & PMD_MASK;
346 pmd++;
347 } while (address < end);
348}
349
350/* 374/*
351 * Unmap an IO region and remove it from imalloc'd list. 375 * Unmap an IO region and remove it from imalloc'd list.
352 * Access to IO memory should be serialized by driver. 376 * Access to IO memory should be serialized by driver.
@@ -356,39 +380,19 @@ static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
356 */ 380 */
357void iounmap(volatile void __iomem *token) 381void iounmap(volatile void __iomem *token)
358{ 382{
359 unsigned long address, start, end, size; 383 unsigned long address, size;
360 struct mm_struct *mm;
361 pgd_t *dir;
362 void *addr; 384 void *addr;
363 385
364 if (!mem_init_done) { 386 if (!mem_init_done)
365 return; 387 return;
366 }
367 388
368 addr = (void *) ((unsigned long __force) token & PAGE_MASK); 389 addr = (void *) ((unsigned long __force) token & PAGE_MASK);
369 390
370 if ((size = im_free(addr)) == 0) { 391 if ((size = im_free(addr)) == 0)
371 return; 392 return;
372 }
373 393
374 address = (unsigned long)addr; 394 address = (unsigned long)addr;
375 start = address; 395 unmap_im_area(address, address + size);
376 end = address + size;
377
378 mm = &ioremap_mm;
379 spin_lock(&mm->page_table_lock);
380
381 dir = pgd_offset_i(address);
382 flush_cache_vunmap(address, end);
383 do {
384 unmap_im_area_pmd(dir, address, end - address);
385 address = (address + PGDIR_SIZE) & PGDIR_MASK;
386 dir++;
387 } while (address && (address < end));
388 flush_tlb_kernel_range(start, end);
389
390 spin_unlock(&mm->page_table_lock);
391 return;
392} 396}
393 397
394static int iounmap_subset_regions(unsigned long addr, unsigned long size) 398static int iounmap_subset_regions(unsigned long addr, unsigned long size)
diff --git a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c
index 6a20773f695d..244150a0bc18 100644
--- a/arch/ppc64/mm/slb.c
+++ b/arch/ppc64/mm/slb.c
@@ -33,8 +33,8 @@ static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags)
33 return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags; 33 return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
34} 34}
35 35
36static inline void create_slbe(unsigned long ea, unsigned long vsid, 36static inline void create_slbe(unsigned long ea, unsigned long flags,
37 unsigned long flags, unsigned long entry) 37 unsigned long entry)
38{ 38{
39 asm volatile("slbmte %0,%1" : 39 asm volatile("slbmte %0,%1" :
40 : "r" (mk_vsid_data(ea, flags)), 40 : "r" (mk_vsid_data(ea, flags)),
@@ -145,9 +145,8 @@ void slb_initialize(void)
145 asm volatile("isync":::"memory"); 145 asm volatile("isync":::"memory");
146 asm volatile("slbmte %0,%0"::"r" (0) : "memory"); 146 asm volatile("slbmte %0,%0"::"r" (0) : "memory");
147 asm volatile("isync; slbia; isync":::"memory"); 147 asm volatile("isync; slbia; isync":::"memory");
148 create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE), flags, 0); 148 create_slbe(KERNELBASE, flags, 0);
149 create_slbe(VMALLOCBASE, get_kernel_vsid(KERNELBASE), 149 create_slbe(VMALLOCBASE, SLB_VSID_KERNEL, 1);
150 SLB_VSID_KERNEL, 1);
151 /* We don't bolt the stack for the time being - we're in boot, 150 /* We don't bolt the stack for the time being - we're in boot,
152 * so the stack is in the bolted segment. By the time it goes 151 * so the stack is in the bolted segment. By the time it goes
153 * elsewhere, we'll call _switch() which will bolt in the new 152 * elsewhere, we'll call _switch() which will bolt in the new