aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-08-29 20:11:29 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-08-29 20:11:29 -0400
commit40193713df2cdb9c233b3fc2029ecdccb40cb1e4 (patch)
treedb2ce73665b250672f5f5c0cf7544ec370c122f9 /arch
parent8f3d17fb7bcb7c255197d11469fb5e9695c9d2f4 (diff)
parentc594adad5653491813959277fb87a2fef54c4e05 (diff)
Merge HEAD from master.kernel.org:/pub/scm/linux/kernel/git/paulus/ppc64-2.6
Diffstat (limited to 'arch')
-rw-r--r--arch/ppc/boot/utils/addRamDisk.c203
-rw-r--r--arch/ppc64/Kconfig74
-rw-r--r--arch/ppc64/boot/Makefile4
-rw-r--r--arch/ppc64/boot/addnote.c4
-rw-r--r--arch/ppc64/boot/crt0.S2
-rw-r--r--arch/ppc64/boot/div64.S2
-rw-r--r--arch/ppc64/boot/elf.h149
-rw-r--r--arch/ppc64/boot/main.c55
-rw-r--r--arch/ppc64/boot/page.h34
-rw-r--r--arch/ppc64/boot/ppc32-types.h36
-rw-r--r--arch/ppc64/boot/ppc_asm.h62
-rw-r--r--arch/ppc64/boot/prom.c196
-rw-r--r--arch/ppc64/boot/prom.h18
-rw-r--r--arch/ppc64/boot/stdio.h16
-rw-r--r--arch/ppc64/boot/string.S2
-rw-r--r--arch/ppc64/boot/string.h16
-rw-r--r--arch/ppc64/boot/zlib.c2
-rw-r--r--arch/ppc64/configs/iSeries_defconfig1
-rw-r--r--arch/ppc64/kernel/LparData.c37
-rw-r--r--arch/ppc64/kernel/Makefile7
-rw-r--r--arch/ppc64/kernel/asm-offsets.c3
-rw-r--r--arch/ppc64/kernel/cputable.c40
-rw-r--r--arch/ppc64/kernel/firmware.c47
-rw-r--r--arch/ppc64/kernel/head.S509
-rw-r--r--arch/ppc64/kernel/iSeries_htab.c5
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c30
-rw-r--r--arch/ppc64/kernel/iSeries_vio.c144
-rw-r--r--arch/ppc64/kernel/lmb.c151
-rw-r--r--arch/ppc64/kernel/lparcfg.c6
-rw-r--r--arch/ppc64/kernel/misc.S98
-rw-r--r--arch/ppc64/kernel/pSeries_iommu.c3
-rw-r--r--arch/ppc64/kernel/pSeries_lpar.c4
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c39
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c3
-rw-r--r--arch/ppc64/kernel/pSeries_vio.c266
-rw-r--r--arch/ppc64/kernel/pacaData.c4
-rw-r--r--arch/ppc64/kernel/pmac_setup.c2
-rw-r--r--arch/ppc64/kernel/pmc.c21
-rw-r--r--arch/ppc64/kernel/process.c12
-rw-r--r--arch/ppc64/kernel/prom.c184
-rw-r--r--arch/ppc64/kernel/prom_init.c88
-rw-r--r--arch/ppc64/kernel/rtas_pci.c19
-rw-r--r--arch/ppc64/kernel/setup.c28
-rw-r--r--arch/ppc64/kernel/sysfs.c57
-rw-r--r--arch/ppc64/kernel/time.c7
-rw-r--r--arch/ppc64/kernel/vio.c407
-rw-r--r--arch/ppc64/mm/hash_native.c3
-rw-r--r--arch/ppc64/mm/hash_utils.c4
-rw-r--r--arch/ppc64/mm/hugetlbpage.c388
-rw-r--r--arch/ppc64/mm/imalloc.c2
-rw-r--r--arch/ppc64/mm/init.c96
-rw-r--r--arch/ppc64/mm/numa.c2
-rw-r--r--arch/ppc64/mm/slb_low.S25
-rw-r--r--arch/ppc64/mm/tlb.c95
-rw-r--r--arch/ppc64/xmon/start.c2
-rw-r--r--arch/ppc64/xmon/xmon.c28
56 files changed, 1920 insertions, 1822 deletions
diff --git a/arch/ppc/boot/utils/addRamDisk.c b/arch/ppc/boot/utils/addRamDisk.c
deleted file mode 100644
index 93400dfcce7f..000000000000
--- a/arch/ppc/boot/utils/addRamDisk.c
+++ /dev/null
@@ -1,203 +0,0 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <netinet/in.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <string.h>
8
9#define ElfHeaderSize (64 * 1024)
10#define ElfPages (ElfHeaderSize / 4096)
11#define KERNELBASE (0xc0000000)
12
13void get4k(FILE *file, char *buf )
14{
15 unsigned j;
16 unsigned num = fread(buf, 1, 4096, file);
17 for ( j=num; j<4096; ++j )
18 buf[j] = 0;
19}
20
21void put4k(FILE *file, char *buf )
22{
23 fwrite(buf, 1, 4096, file);
24}
25
26void death(const char *msg, FILE *fdesc, const char *fname)
27{
28 printf(msg);
29 fclose(fdesc);
30 unlink(fname);
31 exit(1);
32}
33
34int main(int argc, char **argv)
35{
36 char inbuf[4096];
37 FILE *ramDisk = NULL;
38 FILE *inputVmlinux = NULL;
39 FILE *outputVmlinux = NULL;
40 unsigned i = 0;
41 u_int32_t ramFileLen = 0;
42 u_int32_t ramLen = 0;
43 u_int32_t roundR = 0;
44 u_int32_t kernelLen = 0;
45 u_int32_t actualKernelLen = 0;
46 u_int32_t round = 0;
47 u_int32_t roundedKernelLen = 0;
48 u_int32_t ramStartOffs = 0;
49 u_int32_t ramPages = 0;
50 u_int32_t roundedKernelPages = 0;
51 u_int32_t hvReleaseData = 0;
52 u_int32_t eyeCatcher = 0xc8a5d9c4;
53 u_int32_t naca = 0;
54 u_int32_t xRamDisk = 0;
55 u_int32_t xRamDiskSize = 0;
56 if ( argc < 2 ) {
57 printf("Name of RAM disk file missing.\n");
58 exit(1);
59 }
60
61 if ( argc < 3 ) {
62 printf("Name of vmlinux file missing.\n");
63 exit(1);
64 }
65
66 if ( argc < 4 ) {
67 printf("Name of vmlinux output file missing.\n");
68 exit(1);
69 }
70
71 ramDisk = fopen(argv[1], "r");
72 if ( ! ramDisk ) {
73 printf("RAM disk file \"%s\" failed to open.\n", argv[1]);
74 exit(1);
75 }
76 inputVmlinux = fopen(argv[2], "r");
77 if ( ! inputVmlinux ) {
78 printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
79 exit(1);
80 }
81 outputVmlinux = fopen(argv[3], "w+");
82 if ( ! outputVmlinux ) {
83 printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
84 exit(1);
85 }
86 fseek(ramDisk, 0, SEEK_END);
87 ramFileLen = ftell(ramDisk);
88 fseek(ramDisk, 0, SEEK_SET);
89 printf("%s file size = %d\n", argv[1], ramFileLen);
90
91 ramLen = ramFileLen;
92
93 roundR = 4096 - (ramLen % 4096);
94 if ( roundR ) {
95 printf("Rounding RAM disk file up to a multiple of 4096, adding %d\n", roundR);
96 ramLen += roundR;
97 }
98
99 printf("Rounded RAM disk size is %d\n", ramLen);
100 fseek(inputVmlinux, 0, SEEK_END);
101 kernelLen = ftell(inputVmlinux);
102 fseek(inputVmlinux, 0, SEEK_SET);
103 printf("kernel file size = %d\n", kernelLen);
104 if ( kernelLen == 0 ) {
105 printf("You must have a linux kernel specified as argv[2]\n");
106 exit(1);
107 }
108
109 actualKernelLen = kernelLen - ElfHeaderSize;
110
111 printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen);
112
113 round = actualKernelLen % 4096;
114 roundedKernelLen = actualKernelLen;
115 if ( round )
116 roundedKernelLen += (4096 - round);
117
118 printf("actual kernel length rounded up to a 4k multiple = %d\n", roundedKernelLen);
119
120 ramStartOffs = roundedKernelLen;
121 ramPages = ramLen / 4096;
122
123 printf("RAM disk pages to copy = %d\n", ramPages);
124
125 // Copy 64K ELF header
126 for (i=0; i<(ElfPages); ++i) {
127 get4k( inputVmlinux, inbuf );
128 put4k( outputVmlinux, inbuf );
129 }
130
131 roundedKernelPages = roundedKernelLen / 4096;
132
133 fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
134
135 for ( i=0; i<roundedKernelPages; ++i ) {
136 get4k( inputVmlinux, inbuf );
137 put4k( outputVmlinux, inbuf );
138 }
139
140 for ( i=0; i<ramPages; ++i ) {
141 get4k( ramDisk, inbuf );
142 put4k( outputVmlinux, inbuf );
143 }
144
145 /* Close the input files */
146 fclose(ramDisk);
147 fclose(inputVmlinux);
148 /* And flush the written output file */
149 fflush(outputVmlinux);
150
151 /* fseek to the hvReleaseData pointer */
152 fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);
153 if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {
154 death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[3]);
155 }
156 hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */
157 printf("hvReleaseData is at %08x\n", hvReleaseData);
158
159 /* fseek to the hvReleaseData */
160 fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);
161 if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {
162 death("Could not read hvReleaseData\n", outputVmlinux, argv[3]);
163 }
164 /* Check hvReleaseData sanity */
165 if (memcmp(inbuf, &eyeCatcher, 4) != 0) {
166 death("hvReleaseData is invalid\n", outputVmlinux, argv[3]);
167 }
168 /* Get the naca pointer */
169 naca = ntohl(*((u_int32_t *) &inbuf[0x0c])) - KERNELBASE;
170 printf("naca is at %08x\n", naca);
171
172 /* fseek to the naca */
173 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
174 if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {
175 death("Could not read naca\n", outputVmlinux, argv[3]);
176 }
177 xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));
178 xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));
179 /* Make sure a RAM disk isn't already present */
180 if ((xRamDisk != 0) || (xRamDiskSize != 0)) {
181 death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[3]);
182 }
183 /* Fill in the values */
184 *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);
185 *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages);
186
187 /* Write out the new naca */
188 fflush(outputVmlinux);
189 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
190 if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {
191 death("Could not write naca\n", outputVmlinux, argv[3]);
192 }
193 printf("RAM Disk of 0x%x pages size is attached to the kernel at offset 0x%08x\n",
194 ramPages, ramStartOffs);
195
196 /* Done */
197 fclose(outputVmlinux);
198 /* Set permission to executable */
199 chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
200
201 return 0;
202}
203
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 2ce87836c671..13b262f10216 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -302,12 +302,6 @@ config GENERIC_HARDIRQS
302 bool 302 bool
303 default y 303 default y
304 304
305config MSCHUNKS
306 bool
307 depends on PPC_ISERIES
308 default y
309
310
311config PPC_RTAS 305config PPC_RTAS
312 bool 306 bool
313 depends on PPC_PSERIES || PPC_BPA 307 depends on PPC_PSERIES || PPC_BPA
@@ -350,13 +344,46 @@ config SECCOMP
350 344
351 If unsure, say Y. Only embedded should say N here. 345 If unsure, say Y. Only embedded should say N here.
352 346
347source "fs/Kconfig.binfmt"
348
349config HOTPLUG_CPU
350 bool "Support for hot-pluggable CPUs"
351 depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
352 select HOTPLUG
353 ---help---
354 Say Y here to be able to turn CPUs off and on.
355
356 Say N if you are unsure.
357
358config PROC_DEVICETREE
359 bool "Support for Open Firmware device tree in /proc"
360 depends on !PPC_ISERIES
361 help
362 This option adds a device-tree directory under /proc which contains
363 an image of the device tree that the kernel copies from Open
364 Firmware. If unsure, say Y here.
365
366config CMDLINE_BOOL
367 bool "Default bootloader kernel arguments"
368 depends on !PPC_ISERIES
369
370config CMDLINE
371 string "Initial kernel command string"
372 depends on CMDLINE_BOOL
373 default "console=ttyS0,9600 console=tty0 root=/dev/sda2"
374 help
375 On some platforms, there is currently no way for the boot loader to
376 pass arguments to the kernel. For these platforms, you can supply
377 some command-line options at build time by entering them here. In
378 most cases you will need to specify the root device here.
379
353endmenu 380endmenu
354 381
355config ISA_DMA_API 382config ISA_DMA_API
356 bool 383 bool
357 default y 384 default y
358 385
359menu "General setup" 386menu "Bus Options"
360 387
361config ISA 388config ISA
362 bool 389 bool
@@ -389,45 +416,12 @@ config PCI_DOMAINS
389 bool 416 bool
390 default PCI 417 default PCI
391 418
392source "fs/Kconfig.binfmt"
393
394source "drivers/pci/Kconfig" 419source "drivers/pci/Kconfig"
395 420
396config HOTPLUG_CPU
397 bool "Support for hot-pluggable CPUs"
398 depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
399 select HOTPLUG
400 ---help---
401 Say Y here to be able to turn CPUs off and on.
402
403 Say N if you are unsure.
404
405source "drivers/pcmcia/Kconfig" 421source "drivers/pcmcia/Kconfig"
406 422
407source "drivers/pci/hotplug/Kconfig" 423source "drivers/pci/hotplug/Kconfig"
408 424
409config PROC_DEVICETREE
410 bool "Support for Open Firmware device tree in /proc"
411 depends on !PPC_ISERIES
412 help
413 This option adds a device-tree directory under /proc which contains
414 an image of the device tree that the kernel copies from Open
415 Firmware. If unsure, say Y here.
416
417config CMDLINE_BOOL
418 bool "Default bootloader kernel arguments"
419 depends on !PPC_ISERIES
420
421config CMDLINE
422 string "Initial kernel command string"
423 depends on CMDLINE_BOOL
424 default "console=ttyS0,9600 console=tty0 root=/dev/sda2"
425 help
426 On some platforms, there is currently no way for the boot loader to
427 pass arguments to the kernel. For these platforms, you can supply
428 some command-line options at build time by entering them here. In
429 most cases you will need to specify the root device here.
430
431endmenu 425endmenu
432 426
433source "net/Kconfig" 427source "net/Kconfig"
diff --git a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
index 683b2d43c15f..2c5f5e73d00c 100644
--- a/arch/ppc64/boot/Makefile
+++ b/arch/ppc64/boot/Makefile
@@ -22,8 +22,8 @@
22 22
23 23
24HOSTCC := gcc 24HOSTCC := gcc
25BOOTCFLAGS := $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin 25BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem $(shell $(CROSS32CC) -print-file-name=include)
26BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional 26BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
27BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds 27BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
28OBJCOPYFLAGS := contents,alloc,load,readonly,data 28OBJCOPYFLAGS := contents,alloc,load,readonly,data
29 29
diff --git a/arch/ppc64/boot/addnote.c b/arch/ppc64/boot/addnote.c
index 719663a694bb..8041a9845ab7 100644
--- a/arch/ppc64/boot/addnote.c
+++ b/arch/ppc64/boot/addnote.c
@@ -157,7 +157,7 @@ main(int ac, char **av)
157 PUT_32BE(ns, strlen(arch) + 1); 157 PUT_32BE(ns, strlen(arch) + 1);
158 PUT_32BE(ns + 4, N_DESCR * 4); 158 PUT_32BE(ns + 4, N_DESCR * 4);
159 PUT_32BE(ns + 8, 0x1275); 159 PUT_32BE(ns + 8, 0x1275);
160 strcpy(&buf[ns + 12], arch); 160 strcpy((char *) &buf[ns + 12], arch);
161 ns += 12 + strlen(arch) + 1; 161 ns += 12 + strlen(arch) + 1;
162 for (i = 0; i < N_DESCR; ++i, ns += 4) 162 for (i = 0; i < N_DESCR; ++i, ns += 4)
163 PUT_32BE(ns, descr[i]); 163 PUT_32BE(ns, descr[i]);
@@ -172,7 +172,7 @@ main(int ac, char **av)
172 PUT_32BE(ns, strlen(rpaname) + 1); 172 PUT_32BE(ns, strlen(rpaname) + 1);
173 PUT_32BE(ns + 4, sizeof(rpanote)); 173 PUT_32BE(ns + 4, sizeof(rpanote));
174 PUT_32BE(ns + 8, 0x12759999); 174 PUT_32BE(ns + 8, 0x12759999);
175 strcpy(&buf[ns + 12], rpaname); 175 strcpy((char *) &buf[ns + 12], rpaname);
176 ns += 12 + ROUNDUP(strlen(rpaname) + 1); 176 ns += 12 + ROUNDUP(strlen(rpaname) + 1);
177 for (i = 0; i < N_RPA_DESCR; ++i, ns += 4) 177 for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
178 PUT_32BE(ns, rpanote[i]); 178 PUT_32BE(ns, rpanote[i]);
diff --git a/arch/ppc64/boot/crt0.S b/arch/ppc64/boot/crt0.S
index 04d3e74cd72f..3861e7f9cf19 100644
--- a/arch/ppc64/boot/crt0.S
+++ b/arch/ppc64/boot/crt0.S
@@ -9,7 +9,7 @@
9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32. 9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32.
10 */ 10 */
11 11
12#include <asm/ppc_asm.h> 12#include "ppc_asm.h"
13 13
14 .text 14 .text
15 .globl _start 15 .globl _start
diff --git a/arch/ppc64/boot/div64.S b/arch/ppc64/boot/div64.S
index 38f7e466d7d6..722f360a32a9 100644
--- a/arch/ppc64/boot/div64.S
+++ b/arch/ppc64/boot/div64.S
@@ -13,7 +13,7 @@
13 * as published by the Free Software Foundation; either version 13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version. 14 * 2 of the License, or (at your option) any later version.
15 */ 15 */
16#include <asm/ppc_asm.h> 16#include "ppc_asm.h"
17 17
18 .globl __div64_32 18 .globl __div64_32
19__div64_32: 19__div64_32:
diff --git a/arch/ppc64/boot/elf.h b/arch/ppc64/boot/elf.h
new file mode 100644
index 000000000000..d4828fcf1cb9
--- /dev/null
+++ b/arch/ppc64/boot/elf.h
@@ -0,0 +1,149 @@
1#ifndef _PPC_BOOT_ELF_H_
2#define _PPC_BOOT_ELF_H_
3
4/* 32-bit ELF base types. */
5typedef unsigned int Elf32_Addr;
6typedef unsigned short Elf32_Half;
7typedef unsigned int Elf32_Off;
8typedef signed int Elf32_Sword;
9typedef unsigned int Elf32_Word;
10
11/* 64-bit ELF base types. */
12typedef unsigned long long Elf64_Addr;
13typedef unsigned short Elf64_Half;
14typedef signed short Elf64_SHalf;
15typedef unsigned long long Elf64_Off;
16typedef signed int Elf64_Sword;
17typedef unsigned int Elf64_Word;
18typedef unsigned long long Elf64_Xword;
19typedef signed long long Elf64_Sxword;
20
21/* These constants are for the segment types stored in the image headers */
22#define PT_NULL 0
23#define PT_LOAD 1
24#define PT_DYNAMIC 2
25#define PT_INTERP 3
26#define PT_NOTE 4
27#define PT_SHLIB 5
28#define PT_PHDR 6
29#define PT_TLS 7 /* Thread local storage segment */
30#define PT_LOOS 0x60000000 /* OS-specific */
31#define PT_HIOS 0x6fffffff /* OS-specific */
32#define PT_LOPROC 0x70000000
33#define PT_HIPROC 0x7fffffff
34#define PT_GNU_EH_FRAME 0x6474e550
35
36#define PT_GNU_STACK (PT_LOOS + 0x474e551)
37
38/* These constants define the different elf file types */
39#define ET_NONE 0
40#define ET_REL 1
41#define ET_EXEC 2
42#define ET_DYN 3
43#define ET_CORE 4
44#define ET_LOPROC 0xff00
45#define ET_HIPROC 0xffff
46
47/* These constants define the various ELF target machines */
48#define EM_NONE 0
49#define EM_PPC 20 /* PowerPC */
50#define EM_PPC64 21 /* PowerPC64 */
51
52#define EI_NIDENT 16
53
54typedef struct elf32_hdr {
55 unsigned char e_ident[EI_NIDENT];
56 Elf32_Half e_type;
57 Elf32_Half e_machine;
58 Elf32_Word e_version;
59 Elf32_Addr e_entry; /* Entry point */
60 Elf32_Off e_phoff;
61 Elf32_Off e_shoff;
62 Elf32_Word e_flags;
63 Elf32_Half e_ehsize;
64 Elf32_Half e_phentsize;
65 Elf32_Half e_phnum;
66 Elf32_Half e_shentsize;
67 Elf32_Half e_shnum;
68 Elf32_Half e_shstrndx;
69} Elf32_Ehdr;
70
71typedef struct elf64_hdr {
72 unsigned char e_ident[16]; /* ELF "magic number" */
73 Elf64_Half e_type;
74 Elf64_Half e_machine;
75 Elf64_Word e_version;
76 Elf64_Addr e_entry; /* Entry point virtual address */
77 Elf64_Off e_phoff; /* Program header table file offset */
78 Elf64_Off e_shoff; /* Section header table file offset */
79 Elf64_Word e_flags;
80 Elf64_Half e_ehsize;
81 Elf64_Half e_phentsize;
82 Elf64_Half e_phnum;
83 Elf64_Half e_shentsize;
84 Elf64_Half e_shnum;
85 Elf64_Half e_shstrndx;
86} Elf64_Ehdr;
87
88/* These constants define the permissions on sections in the program
89 header, p_flags. */
90#define PF_R 0x4
91#define PF_W 0x2
92#define PF_X 0x1
93
94typedef struct elf32_phdr {
95 Elf32_Word p_type;
96 Elf32_Off p_offset;
97 Elf32_Addr p_vaddr;
98 Elf32_Addr p_paddr;
99 Elf32_Word p_filesz;
100 Elf32_Word p_memsz;
101 Elf32_Word p_flags;
102 Elf32_Word p_align;
103} Elf32_Phdr;
104
105typedef struct elf64_phdr {
106 Elf64_Word p_type;
107 Elf64_Word p_flags;
108 Elf64_Off p_offset; /* Segment file offset */
109 Elf64_Addr p_vaddr; /* Segment virtual address */
110 Elf64_Addr p_paddr; /* Segment physical address */
111 Elf64_Xword p_filesz; /* Segment size in file */
112 Elf64_Xword p_memsz; /* Segment size in memory */
113 Elf64_Xword p_align; /* Segment alignment, file & memory */
114} Elf64_Phdr;
115
116#define EI_MAG0 0 /* e_ident[] indexes */
117#define EI_MAG1 1
118#define EI_MAG2 2
119#define EI_MAG3 3
120#define EI_CLASS 4
121#define EI_DATA 5
122#define EI_VERSION 6
123#define EI_OSABI 7
124#define EI_PAD 8
125
126#define ELFMAG0 0x7f /* EI_MAG */
127#define ELFMAG1 'E'
128#define ELFMAG2 'L'
129#define ELFMAG3 'F'
130#define ELFMAG "\177ELF"
131#define SELFMAG 4
132
133#define ELFCLASSNONE 0 /* EI_CLASS */
134#define ELFCLASS32 1
135#define ELFCLASS64 2
136#define ELFCLASSNUM 3
137
138#define ELFDATANONE 0 /* e_ident[EI_DATA] */
139#define ELFDATA2LSB 1
140#define ELFDATA2MSB 2
141
142#define EV_NONE 0 /* e_version, EI_VERSION */
143#define EV_CURRENT 1
144#define EV_NUM 2
145
146#define ELFOSABI_NONE 0
147#define ELFOSABI_LINUX 3
148
149#endif /* _PPC_BOOT_ELF_H_ */
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index 199d9804f61c..99e68cfbe688 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -8,36 +8,28 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11#include "ppc32-types.h" 11#include <stdarg.h>
12#include <stddef.h>
13#include "elf.h"
14#include "page.h"
15#include "string.h"
16#include "stdio.h"
17#include "prom.h"
12#include "zlib.h" 18#include "zlib.h"
13#include <linux/elf.h> 19
14#include <linux/string.h> 20static void gunzip(void *, int, unsigned char *, int *);
15#include <asm/processor.h> 21extern void flush_cache(void *, unsigned long);
16#include <asm/page.h> 22
17
18extern void *finddevice(const char *);
19extern int getprop(void *, const char *, void *, int);
20extern void printf(const char *fmt, ...);
21extern int sprintf(char *buf, const char *fmt, ...);
22void gunzip(void *, int, unsigned char *, int *);
23void *claim(unsigned int, unsigned int, unsigned int);
24void flush_cache(void *, unsigned long);
25void pause(void);
26extern void exit(void);
27
28unsigned long strlen(const char *s);
29void *memmove(void *dest, const void *src, unsigned long n);
30void *memcpy(void *dest, const void *src, unsigned long n);
31 23
32/* Value picked to match that used by yaboot */ 24/* Value picked to match that used by yaboot */
33#define PROG_START 0x01400000 25#define PROG_START 0x01400000
34#define RAM_END (256<<20) // Fixme: use OF */ 26#define RAM_END (256<<20) // Fixme: use OF */
35 27
36char *avail_ram; 28static char *avail_ram;
37char *begin_avail, *end_avail; 29static char *begin_avail, *end_avail;
38char *avail_high; 30static char *avail_high;
39unsigned int heap_use; 31static unsigned int heap_use;
40unsigned int heap_max; 32static unsigned int heap_max;
41 33
42extern char _start[]; 34extern char _start[];
43extern char _vmlinux_start[]; 35extern char _vmlinux_start[];
@@ -52,9 +44,9 @@ struct addr_range {
52 unsigned long size; 44 unsigned long size;
53 unsigned long memsize; 45 unsigned long memsize;
54}; 46};
55struct addr_range vmlinux = {0, 0, 0}; 47static struct addr_range vmlinux = {0, 0, 0};
56struct addr_range vmlinuz = {0, 0, 0}; 48static struct addr_range vmlinuz = {0, 0, 0};
57struct addr_range initrd = {0, 0, 0}; 49static struct addr_range initrd = {0, 0, 0};
58 50
59static char scratch[128<<10]; /* 128kB of scratch space for gunzip */ 51static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
60 52
@@ -64,13 +56,6 @@ typedef void (*kernel_entry_t)( unsigned long,
64 void *); 56 void *);
65 57
66 58
67int (*prom)(void *);
68
69void *chosen_handle;
70void *stdin;
71void *stdout;
72void *stderr;
73
74#undef DEBUG 59#undef DEBUG
75 60
76static unsigned long claim_base = PROG_START; 61static unsigned long claim_base = PROG_START;
@@ -277,7 +262,7 @@ void zfree(void *x, void *addr, unsigned nb)
277 262
278#define DEFLATED 8 263#define DEFLATED 8
279 264
280void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) 265static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
281{ 266{
282 z_stream s; 267 z_stream s;
283 int r, i, flags; 268 int r, i, flags;
diff --git a/arch/ppc64/boot/page.h b/arch/ppc64/boot/page.h
new file mode 100644
index 000000000000..14eca30fef64
--- /dev/null
+++ b/arch/ppc64/boot/page.h
@@ -0,0 +1,34 @@
1#ifndef _PPC_BOOT_PAGE_H
2#define _PPC_BOOT_PAGE_H
3/*
4 * Copyright (C) 2001 PPC64 Team, IBM Corp
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#ifdef __ASSEMBLY__
13#define ASM_CONST(x) x
14#else
15#define __ASM_CONST(x) x##UL
16#define ASM_CONST(x) __ASM_CONST(x)
17#endif
18
19/* PAGE_SHIFT determines the page size */
20#define PAGE_SHIFT 12
21#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
22#define PAGE_MASK (~(PAGE_SIZE-1))
23
24/* align addr on a size boundary - adjust address up/down if needed */
25#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
26#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
27
28/* align addr on a size boundary - adjust address up if needed */
29#define _ALIGN(addr,size) _ALIGN_UP(addr,size)
30
31/* to align the pointer to the (next) page boundary */
32#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
33
34#endif /* _PPC_BOOT_PAGE_H */
diff --git a/arch/ppc64/boot/ppc32-types.h b/arch/ppc64/boot/ppc32-types.h
deleted file mode 100644
index f7b8884f8f70..000000000000
--- a/arch/ppc64/boot/ppc32-types.h
+++ /dev/null
@@ -1,36 +0,0 @@
1#ifndef _PPC64_TYPES_H
2#define _PPC64_TYPES_H
3
4typedef __signed__ char __s8;
5typedef unsigned char __u8;
6
7typedef __signed__ short __s16;
8typedef unsigned short __u16;
9
10typedef __signed__ int __s32;
11typedef unsigned int __u32;
12
13typedef __signed__ long long __s64;
14typedef unsigned long long __u64;
15
16typedef signed char s8;
17typedef unsigned char u8;
18
19typedef signed short s16;
20typedef unsigned short u16;
21
22typedef signed int s32;
23typedef unsigned int u32;
24
25typedef signed long long s64;
26typedef unsigned long long u64;
27
28typedef struct {
29 __u32 u[4];
30} __attribute((aligned(16))) __vector128;
31
32#define BITS_PER_LONG 32
33
34typedef __vector128 vector128;
35
36#endif /* _PPC64_TYPES_H */
diff --git a/arch/ppc64/boot/ppc_asm.h b/arch/ppc64/boot/ppc_asm.h
new file mode 100644
index 000000000000..1c2c2817f9b7
--- /dev/null
+++ b/arch/ppc64/boot/ppc_asm.h
@@ -0,0 +1,62 @@
1#ifndef _PPC64_PPC_ASM_H
2#define _PPC64_PPC_ASM_H
3/*
4 *
5 * Definitions used by various bits of low-level assembly code on PowerPC.
6 *
7 * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15/* Condition Register Bit Fields */
16
17#define cr0 0
18#define cr1 1
19#define cr2 2
20#define cr3 3
21#define cr4 4
22#define cr5 5
23#define cr6 6
24#define cr7 7
25
26
27/* General Purpose Registers (GPRs) */
28
29#define r0 0
30#define r1 1
31#define r2 2
32#define r3 3
33#define r4 4
34#define r5 5
35#define r6 6
36#define r7 7
37#define r8 8
38#define r9 9
39#define r10 10
40#define r11 11
41#define r12 12
42#define r13 13
43#define r14 14
44#define r15 15
45#define r16 16
46#define r17 17
47#define r18 18
48#define r19 19
49#define r20 20
50#define r21 21
51#define r22 22
52#define r23 23
53#define r24 24
54#define r25 25
55#define r26 26
56#define r27 27
57#define r28 28
58#define r29 29
59#define r30 30
60#define r31 31
61
62#endif /* _PPC64_PPC_ASM_H */
diff --git a/arch/ppc64/boot/prom.c b/arch/ppc64/boot/prom.c
index 5e48b80ff5a0..4bea2f4dcb06 100644
--- a/arch/ppc64/boot/prom.c
+++ b/arch/ppc64/boot/prom.c
@@ -7,43 +7,19 @@
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9#include <stdarg.h> 9#include <stdarg.h>
10#include <linux/types.h> 10#include <stddef.h>
11#include <linux/string.h> 11#include "string.h"
12#include <linux/ctype.h> 12#include "stdio.h"
13 13#include "prom.h"
14extern __u32 __div64_32(unsigned long long *dividend, __u32 divisor);
15
16/* The unnecessary pointer compare is there
17 * to check for type safety (n must be 64bit)
18 */
19# define do_div(n,base) ({ \
20 __u32 __base = (base); \
21 __u32 __rem; \
22 (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
23 if (((n) >> 32) == 0) { \
24 __rem = (__u32)(n) % __base; \
25 (n) = (__u32)(n) / __base; \
26 } else \
27 __rem = __div64_32(&(n), __base); \
28 __rem; \
29 })
30 14
31int (*prom)(void *); 15int (*prom)(void *);
32 16
33void *chosen_handle; 17void *chosen_handle;
18
34void *stdin; 19void *stdin;
35void *stdout; 20void *stdout;
36void *stderr; 21void *stderr;
37 22
38void exit(void);
39void *finddevice(const char *name);
40int getprop(void *phandle, const char *name, void *buf, int buflen);
41void chrpboot(int a1, int a2, void *prom); /* in main.c */
42
43int printf(char *fmt, ...);
44
45/* there is no convenient header to get this from... -- paulus */
46extern unsigned long strlen(const char *);
47 23
48int 24int
49write(void *handle, void *ptr, int nb) 25write(void *handle, void *ptr, int nb)
@@ -210,107 +186,6 @@ fputs(char *str, void *f)
210 return write(f, str, n) == n? 0: -1; 186 return write(f, str, n) == n? 0: -1;
211} 187}
212 188
213int
214readchar(void)
215{
216 char ch;
217
218 for (;;) {
219 switch (read(stdin, &ch, 1)) {
220 case 1:
221 return ch;
222 case -1:
223 printf("read(stdin) returned -1\r\n");
224 return -1;
225 }
226 }
227}
228
229static char line[256];
230static char *lineptr;
231static int lineleft;
232
233int
234getchar(void)
235{
236 int c;
237
238 if (lineleft == 0) {
239 lineptr = line;
240 for (;;) {
241 c = readchar();
242 if (c == -1 || c == 4)
243 break;
244 if (c == '\r' || c == '\n') {
245 *lineptr++ = '\n';
246 putchar('\n');
247 break;
248 }
249 switch (c) {
250 case 0177:
251 case '\b':
252 if (lineptr > line) {
253 putchar('\b');
254 putchar(' ');
255 putchar('\b');
256 --lineptr;
257 }
258 break;
259 case 'U' & 0x1F:
260 while (lineptr > line) {
261 putchar('\b');
262 putchar(' ');
263 putchar('\b');
264 --lineptr;
265 }
266 break;
267 default:
268 if (lineptr >= &line[sizeof(line) - 1])
269 putchar('\a');
270 else {
271 putchar(c);
272 *lineptr++ = c;
273 }
274 }
275 }
276 lineleft = lineptr - line;
277 lineptr = line;
278 }
279 if (lineleft == 0)
280 return -1;
281 --lineleft;
282 return *lineptr++;
283}
284
285
286
287/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
288unsigned char _ctype[] = {
289_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
290_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
291_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
292_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
293_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
294_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
295_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
296_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
297_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
298_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
299_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
300_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
301_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
302_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
303_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
304_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
3050,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
307_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
308_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
309_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
310_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
311_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
312_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
313
314size_t strnlen(const char * s, size_t count) 189size_t strnlen(const char * s, size_t count)
315{ 190{
316 const char *sc; 191 const char *sc;
@@ -320,44 +195,30 @@ size_t strnlen(const char * s, size_t count)
320 return sc - s; 195 return sc - s;
321} 196}
322 197
323unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) 198extern unsigned int __div64_32(unsigned long long *dividend,
324{ 199 unsigned int divisor);
325 unsigned long result = 0,value;
326 200
327 if (!base) { 201/* The unnecessary pointer compare is there
328 base = 10; 202 * to check for type safety (n must be 64bit)
329 if (*cp == '0') { 203 */
330 base = 8; 204# define do_div(n,base) ({ \
331 cp++; 205 unsigned int __base = (base); \
332 if ((*cp == 'x') && isxdigit(cp[1])) { 206 unsigned int __rem; \
333 cp++; 207 (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
334 base = 16; 208 if (((n) >> 32) == 0) { \
335 } 209 __rem = (unsigned int)(n) % __base; \
336 } 210 (n) = (unsigned int)(n) / __base; \
337 } 211 } else \
338 while (isxdigit(*cp) && 212 __rem = __div64_32(&(n), __base); \
339 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { 213 __rem; \
340 result = result*base + value; 214 })
341 cp++;
342 }
343 if (endp)
344 *endp = (char *)cp;
345 return result;
346}
347
348long simple_strtol(const char *cp,char **endp,unsigned int base)
349{
350 if(*cp=='-')
351 return -simple_strtoul(cp+1,endp,base);
352 return simple_strtoul(cp,endp,base);
353}
354 215
355static int skip_atoi(const char **s) 216static int skip_atoi(const char **s)
356{ 217{
357 int i=0; 218 int i, c;
358 219
359 while (isdigit(**s)) 220 for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
360 i = i*10 + *((*s)++) - '0'; 221 i = i*10 + c - '0';
361 return i; 222 return i;
362} 223}
363 224
@@ -436,9 +297,6 @@ static char * number(char * str, unsigned long long num, int base, int size, int
436 return str; 297 return str;
437} 298}
438 299
439/* Forward decl. needed for IP address printing stuff... */
440int sprintf(char * buf, const char *fmt, ...);
441
442int vsprintf(char *buf, const char *fmt, va_list args) 300int vsprintf(char *buf, const char *fmt, va_list args)
443{ 301{
444 int len; 302 int len;
@@ -477,7 +335,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
477 335
478 /* get field width */ 336 /* get field width */
479 field_width = -1; 337 field_width = -1;
480 if (isdigit(*fmt)) 338 if ('0' <= *fmt && *fmt <= '9')
481 field_width = skip_atoi(&fmt); 339 field_width = skip_atoi(&fmt);
482 else if (*fmt == '*') { 340 else if (*fmt == '*') {
483 ++fmt; 341 ++fmt;
@@ -493,7 +351,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
493 precision = -1; 351 precision = -1;
494 if (*fmt == '.') { 352 if (*fmt == '.') {
495 ++fmt; 353 ++fmt;
496 if (isdigit(*fmt)) 354 if ('0' <= *fmt && *fmt <= '9')
497 precision = skip_atoi(&fmt); 355 precision = skip_atoi(&fmt);
498 else if (*fmt == '*') { 356 else if (*fmt == '*') {
499 ++fmt; 357 ++fmt;
@@ -628,7 +486,7 @@ int sprintf(char * buf, const char *fmt, ...)
628static char sprint_buf[1024]; 486static char sprint_buf[1024];
629 487
630int 488int
631printf(char *fmt, ...) 489printf(const char *fmt, ...)
632{ 490{
633 va_list args; 491 va_list args;
634 int n; 492 int n;
diff --git a/arch/ppc64/boot/prom.h b/arch/ppc64/boot/prom.h
new file mode 100644
index 000000000000..96ab5aec740c
--- /dev/null
+++ b/arch/ppc64/boot/prom.h
@@ -0,0 +1,18 @@
1#ifndef _PPC_BOOT_PROM_H_
2#define _PPC_BOOT_PROM_H_
3
4extern int (*prom) (void *);
5extern void *chosen_handle;
6
7extern void *stdin;
8extern void *stdout;
9extern void *stderr;
10
11extern int write(void *handle, void *ptr, int nb);
12extern int read(void *handle, void *ptr, int nb);
13extern void exit(void);
14extern void pause(void);
15extern void *finddevice(const char *);
16extern void *claim(unsigned long virt, unsigned long size, unsigned long align);
17extern int getprop(void *phandle, const char *name, void *buf, int buflen);
18#endif /* _PPC_BOOT_PROM_H_ */
diff --git a/arch/ppc64/boot/stdio.h b/arch/ppc64/boot/stdio.h
new file mode 100644
index 000000000000..24bd3a8dee94
--- /dev/null
+++ b/arch/ppc64/boot/stdio.h
@@ -0,0 +1,16 @@
1#ifndef _PPC_BOOT_STDIO_H_
2#define _PPC_BOOT_STDIO_H_
3
4extern int printf(const char *fmt, ...);
5
6extern int sprintf(char *buf, const char *fmt, ...);
7
8extern int vsprintf(char *buf, const char *fmt, va_list args);
9
10extern int putc(int c, void *f);
11extern int putchar(int c);
12extern int getchar(void);
13
14extern int fputs(char *str, void *f);
15
16#endif /* _PPC_BOOT_STDIO_H_ */
diff --git a/arch/ppc64/boot/string.S b/arch/ppc64/boot/string.S
index ba5f2d21c9ea..7ade87ae7718 100644
--- a/arch/ppc64/boot/string.S
+++ b/arch/ppc64/boot/string.S
@@ -9,7 +9,7 @@
9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32. 9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32.
10 */ 10 */
11 11
12#include <asm/ppc_asm.h> 12#include "ppc_asm.h"
13 13
14 .text 14 .text
15 .globl strcpy 15 .globl strcpy
diff --git a/arch/ppc64/boot/string.h b/arch/ppc64/boot/string.h
new file mode 100644
index 000000000000..9289258bcbd6
--- /dev/null
+++ b/arch/ppc64/boot/string.h
@@ -0,0 +1,16 @@
1#ifndef _PPC_BOOT_STRING_H_
2#define _PPC_BOOT_STRING_H_
3
4extern char *strcpy(char *dest, const char *src);
5extern char *strncpy(char *dest, const char *src, size_t n);
6extern char *strcat(char *dest, const char *src);
7extern int strcmp(const char *s1, const char *s2);
8extern size_t strlen(const char *s);
9extern size_t strnlen(const char *s, size_t count);
10
11extern void *memset(void *s, int c, size_t n);
12extern void *memmove(void *dest, const void *src, unsigned long n);
13extern void *memcpy(void *dest, const void *src, unsigned long n);
14extern int memcmp(const void *s1, const void *s2, size_t n);
15
16#endif /* _PPC_BOOT_STRING_H_ */
diff --git a/arch/ppc64/boot/zlib.c b/arch/ppc64/boot/zlib.c
index 78837e884b8b..0d910cd2079d 100644
--- a/arch/ppc64/boot/zlib.c
+++ b/arch/ppc64/boot/zlib.c
@@ -107,7 +107,7 @@ extern void *memcpy(void *, const void *, unsigned long);
107 107
108/* Diagnostic functions */ 108/* Diagnostic functions */
109#ifdef DEBUG_ZLIB 109#ifdef DEBUG_ZLIB
110# include <stdio.h> 110# include "stdio.h"
111# ifndef verbose 111# ifndef verbose
112# define verbose 0 112# define verbose 0
113# endif 113# endif
diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
index 394ba18b58c7..219c6677abcc 100644
--- a/arch/ppc64/configs/iSeries_defconfig
+++ b/arch/ppc64/configs/iSeries_defconfig
@@ -99,7 +99,6 @@ CONFIG_HZ_100=y
99# CONFIG_HZ_1000 is not set 99# CONFIG_HZ_1000 is not set
100CONFIG_HZ=100 100CONFIG_HZ=100
101CONFIG_GENERIC_HARDIRQS=y 101CONFIG_GENERIC_HARDIRQS=y
102CONFIG_MSCHUNKS=y
103CONFIG_LPARCFG=y 102CONFIG_LPARCFG=y
104CONFIG_SECCOMP=y 103CONFIG_SECCOMP=y
105CONFIG_ISA_DMA_API=y 104CONFIG_ISA_DMA_API=y
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
index 1c11031c838e..0a9c23ca2f0c 100644
--- a/arch/ppc64/kernel/LparData.c
+++ b/arch/ppc64/kernel/LparData.c
@@ -51,6 +51,17 @@ struct HvReleaseData hvReleaseData = {
51 0xf4, 0x4b, 0xf6, 0xf4 }, 51 0xf4, 0x4b, 0xf6, 0xf4 },
52}; 52};
53 53
54/*
55 * The NACA. The first dword of the naca is required by the iSeries
56 * hypervisor to point to itVpdAreas. The hypervisor finds the NACA
57 * through the pointer in hvReleaseData.
58 */
59struct naca_struct naca = {
60 .xItVpdAreas = &itVpdAreas,
61 .xRamDisk = 0,
62 .xRamDiskSize = 0,
63};
64
54extern void system_reset_iSeries(void); 65extern void system_reset_iSeries(void);
55extern void machine_check_iSeries(void); 66extern void machine_check_iSeries(void);
56extern void data_access_iSeries(void); 67extern void data_access_iSeries(void);
@@ -214,29 +225,3 @@ struct ItVpdAreas itVpdAreas = {
214 0,0 225 0,0
215 } 226 }
216}; 227};
217
218struct msChunks msChunks;
219EXPORT_SYMBOL(msChunks);
220
221/* Depending on whether this is called from iSeries or pSeries setup
222 * code, the location of the msChunks struct may or may not have
223 * to be reloc'd, so we force the caller to do that for us by passing
224 * in a pointer to the structure.
225 */
226unsigned long
227msChunks_alloc(unsigned long mem, unsigned long num_chunks, unsigned long chunk_size)
228{
229 unsigned long offset = reloc_offset();
230 struct msChunks *_msChunks = PTRRELOC(&msChunks);
231
232 _msChunks->num_chunks = num_chunks;
233 _msChunks->chunk_size = chunk_size;
234 _msChunks->chunk_shift = __ilog2(chunk_size);
235 _msChunks->chunk_mask = (1UL<<_msChunks->chunk_shift)-1;
236
237 mem = _ALIGN(mem, sizeof(msChunks_entry));
238 _msChunks->abs = (msChunks_entry *)(mem + offset);
239 mem += num_chunks * sizeof(msChunks_entry);
240
241 return mem;
242}
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 2ecccb6b4f8c..f4b3bfcc109d 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -11,7 +11,7 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \
11 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ 11 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
12 ptrace32.o signal32.o rtc.o init_task.o \ 12 ptrace32.o signal32.o rtc.o init_task.o \
13 lmb.o cputable.o cpu_setup_power4.o idle_power4.o \ 13 lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
14 iommu.o sysfs.o vdso.o pmc.o 14 iommu.o sysfs.o vdso.o pmc.o firmware.o
15obj-y += vdso32/ vdso64/ 15obj-y += vdso32/ vdso64/
16 16
17obj-$(CONFIG_PPC_OF) += of_device.o 17obj-$(CONFIG_PPC_OF) += of_device.o
@@ -50,7 +50,10 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o
50obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o 50obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
51obj-$(CONFIG_BOOTX_TEXT) += btext.o 51obj-$(CONFIG_BOOTX_TEXT) += btext.o
52obj-$(CONFIG_HVCS) += hvcserver.o 52obj-$(CONFIG_HVCS) += hvcserver.o
53obj-$(CONFIG_IBMVIO) += vio.o 53
54vio-obj-$(CONFIG_PPC_PSERIES) += pSeries_vio.o
55vio-obj-$(CONFIG_PPC_ISERIES) += iSeries_vio.o
56obj-$(CONFIG_IBMVIO) += vio.o $(vio-obj-y)
54obj-$(CONFIG_XICS) += xics.o 57obj-$(CONFIG_XICS) += xics.o
55obj-$(CONFIG_MPIC) += mpic.o 58obj-$(CONFIG_MPIC) += mpic.o
56 59
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index abb9e5b5da03..17e35d0fed09 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -94,7 +94,8 @@ int main(void)
94 DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); 94 DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
95 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); 95 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
96#ifdef CONFIG_HUGETLB_PAGE 96#ifdef CONFIG_HUGETLB_PAGE
97 DEFINE(PACAHTLBSEGS, offsetof(struct paca_struct, context.htlb_segs)); 97 DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
98 DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
98#endif /* CONFIG_HUGETLB_PAGE */ 99#endif /* CONFIG_HUGETLB_PAGE */
99 DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); 100 DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr));
100 DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); 101 DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
index 77cec42f9525..4847f2ac8c9f 100644
--- a/arch/ppc64/kernel/cputable.c
+++ b/arch/ppc64/kernel/cputable.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Modifications for ppc64: 6 * Modifications for ppc64:
7 * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com> 7 * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 11 * as published by the Free Software Foundation; either version
@@ -60,7 +60,6 @@ struct cpu_spec cpu_specs[] = {
60 .icache_bsize = 128, 60 .icache_bsize = 128,
61 .dcache_bsize = 128, 61 .dcache_bsize = 128,
62 .cpu_setup = __setup_cpu_power3, 62 .cpu_setup = __setup_cpu_power3,
63 .firmware_features = COMMON_PPC64_FW,
64 }, 63 },
65 { /* Power3+ */ 64 { /* Power3+ */
66 .pvr_mask = 0xffff0000, 65 .pvr_mask = 0xffff0000,
@@ -73,7 +72,6 @@ struct cpu_spec cpu_specs[] = {
73 .icache_bsize = 128, 72 .icache_bsize = 128,
74 .dcache_bsize = 128, 73 .dcache_bsize = 128,
75 .cpu_setup = __setup_cpu_power3, 74 .cpu_setup = __setup_cpu_power3,
76 .firmware_features = COMMON_PPC64_FW,
77 }, 75 },
78 { /* Northstar */ 76 { /* Northstar */
79 .pvr_mask = 0xffff0000, 77 .pvr_mask = 0xffff0000,
@@ -86,7 +84,6 @@ struct cpu_spec cpu_specs[] = {
86 .icache_bsize = 128, 84 .icache_bsize = 128,
87 .dcache_bsize = 128, 85 .dcache_bsize = 128,
88 .cpu_setup = __setup_cpu_power3, 86 .cpu_setup = __setup_cpu_power3,
89 .firmware_features = COMMON_PPC64_FW,
90 }, 87 },
91 { /* Pulsar */ 88 { /* Pulsar */
92 .pvr_mask = 0xffff0000, 89 .pvr_mask = 0xffff0000,
@@ -99,7 +96,6 @@ struct cpu_spec cpu_specs[] = {
99 .icache_bsize = 128, 96 .icache_bsize = 128,
100 .dcache_bsize = 128, 97 .dcache_bsize = 128,
101 .cpu_setup = __setup_cpu_power3, 98 .cpu_setup = __setup_cpu_power3,
102 .firmware_features = COMMON_PPC64_FW,
103 }, 99 },
104 { /* I-star */ 100 { /* I-star */
105 .pvr_mask = 0xffff0000, 101 .pvr_mask = 0xffff0000,
@@ -112,7 +108,6 @@ struct cpu_spec cpu_specs[] = {
112 .icache_bsize = 128, 108 .icache_bsize = 128,
113 .dcache_bsize = 128, 109 .dcache_bsize = 128,
114 .cpu_setup = __setup_cpu_power3, 110 .cpu_setup = __setup_cpu_power3,
115 .firmware_features = COMMON_PPC64_FW,
116 }, 111 },
117 { /* S-star */ 112 { /* S-star */
118 .pvr_mask = 0xffff0000, 113 .pvr_mask = 0xffff0000,
@@ -125,7 +120,6 @@ struct cpu_spec cpu_specs[] = {
125 .icache_bsize = 128, 120 .icache_bsize = 128,
126 .dcache_bsize = 128, 121 .dcache_bsize = 128,
127 .cpu_setup = __setup_cpu_power3, 122 .cpu_setup = __setup_cpu_power3,
128 .firmware_features = COMMON_PPC64_FW,
129 }, 123 },
130 { /* Power4 */ 124 { /* Power4 */
131 .pvr_mask = 0xffff0000, 125 .pvr_mask = 0xffff0000,
@@ -138,7 +132,6 @@ struct cpu_spec cpu_specs[] = {
138 .icache_bsize = 128, 132 .icache_bsize = 128,
139 .dcache_bsize = 128, 133 .dcache_bsize = 128,
140 .cpu_setup = __setup_cpu_power4, 134 .cpu_setup = __setup_cpu_power4,
141 .firmware_features = COMMON_PPC64_FW,
142 }, 135 },
143 { /* Power4+ */ 136 { /* Power4+ */
144 .pvr_mask = 0xffff0000, 137 .pvr_mask = 0xffff0000,
@@ -151,7 +144,6 @@ struct cpu_spec cpu_specs[] = {
151 .icache_bsize = 128, 144 .icache_bsize = 128,
152 .dcache_bsize = 128, 145 .dcache_bsize = 128,
153 .cpu_setup = __setup_cpu_power4, 146 .cpu_setup = __setup_cpu_power4,
154 .firmware_features = COMMON_PPC64_FW,
155 }, 147 },
156 { /* PPC970 */ 148 { /* PPC970 */
157 .pvr_mask = 0xffff0000, 149 .pvr_mask = 0xffff0000,
@@ -166,7 +158,6 @@ struct cpu_spec cpu_specs[] = {
166 .icache_bsize = 128, 158 .icache_bsize = 128,
167 .dcache_bsize = 128, 159 .dcache_bsize = 128,
168 .cpu_setup = __setup_cpu_ppc970, 160 .cpu_setup = __setup_cpu_ppc970,
169 .firmware_features = COMMON_PPC64_FW,
170 }, 161 },
171 { /* PPC970FX */ 162 { /* PPC970FX */
172 .pvr_mask = 0xffff0000, 163 .pvr_mask = 0xffff0000,
@@ -181,7 +172,6 @@ struct cpu_spec cpu_specs[] = {
181 .icache_bsize = 128, 172 .icache_bsize = 128,
182 .dcache_bsize = 128, 173 .dcache_bsize = 128,
183 .cpu_setup = __setup_cpu_ppc970, 174 .cpu_setup = __setup_cpu_ppc970,
184 .firmware_features = COMMON_PPC64_FW,
185 }, 175 },
186 { /* PPC970MP */ 176 { /* PPC970MP */
187 .pvr_mask = 0xffff0000, 177 .pvr_mask = 0xffff0000,
@@ -196,7 +186,6 @@ struct cpu_spec cpu_specs[] = {
196 .icache_bsize = 128, 186 .icache_bsize = 128,
197 .dcache_bsize = 128, 187 .dcache_bsize = 128,
198 .cpu_setup = __setup_cpu_ppc970, 188 .cpu_setup = __setup_cpu_ppc970,
199 .firmware_features = COMMON_PPC64_FW,
200 }, 189 },
201 { /* Power5 */ 190 { /* Power5 */
202 .pvr_mask = 0xffff0000, 191 .pvr_mask = 0xffff0000,
@@ -211,7 +200,6 @@ struct cpu_spec cpu_specs[] = {
211 .icache_bsize = 128, 200 .icache_bsize = 128,
212 .dcache_bsize = 128, 201 .dcache_bsize = 128,
213 .cpu_setup = __setup_cpu_power4, 202 .cpu_setup = __setup_cpu_power4,
214 .firmware_features = COMMON_PPC64_FW,
215 }, 203 },
216 { /* Power5 */ 204 { /* Power5 */
217 .pvr_mask = 0xffff0000, 205 .pvr_mask = 0xffff0000,
@@ -226,7 +214,6 @@ struct cpu_spec cpu_specs[] = {
226 .icache_bsize = 128, 214 .icache_bsize = 128,
227 .dcache_bsize = 128, 215 .dcache_bsize = 128,
228 .cpu_setup = __setup_cpu_power4, 216 .cpu_setup = __setup_cpu_power4,
229 .firmware_features = COMMON_PPC64_FW,
230 }, 217 },
231 { /* BE DD1.x */ 218 { /* BE DD1.x */
232 .pvr_mask = 0xffff0000, 219 .pvr_mask = 0xffff0000,
@@ -241,7 +228,6 @@ struct cpu_spec cpu_specs[] = {
241 .icache_bsize = 128, 228 .icache_bsize = 128,
242 .dcache_bsize = 128, 229 .dcache_bsize = 128,
243 .cpu_setup = __setup_cpu_be, 230 .cpu_setup = __setup_cpu_be,
244 .firmware_features = COMMON_PPC64_FW,
245 }, 231 },
246 { /* default match */ 232 { /* default match */
247 .pvr_mask = 0x00000000, 233 .pvr_mask = 0x00000000,
@@ -254,29 +240,5 @@ struct cpu_spec cpu_specs[] = {
254 .icache_bsize = 128, 240 .icache_bsize = 128,
255 .dcache_bsize = 128, 241 .dcache_bsize = 128,
256 .cpu_setup = __setup_cpu_power4, 242 .cpu_setup = __setup_cpu_power4,
257 .firmware_features = COMMON_PPC64_FW,
258 } 243 }
259}; 244};
260
261firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
262 {FW_FEATURE_PFT, "hcall-pft"},
263 {FW_FEATURE_TCE, "hcall-tce"},
264 {FW_FEATURE_SPRG0, "hcall-sprg0"},
265 {FW_FEATURE_DABR, "hcall-dabr"},
266 {FW_FEATURE_COPY, "hcall-copy"},
267 {FW_FEATURE_ASR, "hcall-asr"},
268 {FW_FEATURE_DEBUG, "hcall-debug"},
269 {FW_FEATURE_PERF, "hcall-perf"},
270 {FW_FEATURE_DUMP, "hcall-dump"},
271 {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
272 {FW_FEATURE_MIGRATE, "hcall-migrate"},
273 {FW_FEATURE_PERFMON, "hcall-perfmon"},
274 {FW_FEATURE_CRQ, "hcall-crq"},
275 {FW_FEATURE_VIO, "hcall-vio"},
276 {FW_FEATURE_RDMA, "hcall-rdma"},
277 {FW_FEATURE_LLAN, "hcall-lLAN"},
278 {FW_FEATURE_BULK, "hcall-bulk"},
279 {FW_FEATURE_XDABR, "hcall-xdabr"},
280 {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
281 {FW_FEATURE_SPLPAR, "hcall-splpar"},
282};
diff --git a/arch/ppc64/kernel/firmware.c b/arch/ppc64/kernel/firmware.c
new file mode 100644
index 000000000000..d8432c0fb27d
--- /dev/null
+++ b/arch/ppc64/kernel/firmware.c
@@ -0,0 +1,47 @@
1/*
2 * arch/ppc64/kernel/firmware.c
3 *
4 * Extracted from cputable.c
5 *
6 * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
7 *
8 * Modifications for ppc64:
9 * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
10 * Copyright (C) 2005 Stephen Rothwell, IBM Corporation
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
20#include <asm/firmware.h>
21
22unsigned long ppc64_firmware_features;
23
24#ifdef CONFIG_PPC_PSERIES
25firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
26 {FW_FEATURE_PFT, "hcall-pft"},
27 {FW_FEATURE_TCE, "hcall-tce"},
28 {FW_FEATURE_SPRG0, "hcall-sprg0"},
29 {FW_FEATURE_DABR, "hcall-dabr"},
30 {FW_FEATURE_COPY, "hcall-copy"},
31 {FW_FEATURE_ASR, "hcall-asr"},
32 {FW_FEATURE_DEBUG, "hcall-debug"},
33 {FW_FEATURE_PERF, "hcall-perf"},
34 {FW_FEATURE_DUMP, "hcall-dump"},
35 {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
36 {FW_FEATURE_MIGRATE, "hcall-migrate"},
37 {FW_FEATURE_PERFMON, "hcall-perfmon"},
38 {FW_FEATURE_CRQ, "hcall-crq"},
39 {FW_FEATURE_VIO, "hcall-vio"},
40 {FW_FEATURE_RDMA, "hcall-rdma"},
41 {FW_FEATURE_LLAN, "hcall-lLAN"},
42 {FW_FEATURE_BULK, "hcall-bulk"},
43 {FW_FEATURE_XDABR, "hcall-xdabr"},
44 {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
45 {FW_FEATURE_SPLPAR, "hcall-splpar"},
46};
47#endif
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index accaa052d31f..cccec4902646 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -23,14 +23,11 @@
23 * 2 of the License, or (at your option) any later version. 23 * 2 of the License, or (at your option) any later version.
24 */ 24 */
25 25
26#define SECONDARY_PROCESSORS
27
28#include <linux/config.h> 26#include <linux/config.h>
29#include <linux/threads.h> 27#include <linux/threads.h>
30#include <asm/processor.h> 28#include <asm/processor.h>
31#include <asm/page.h> 29#include <asm/page.h>
32#include <asm/mmu.h> 30#include <asm/mmu.h>
33#include <asm/naca.h>
34#include <asm/systemcfg.h> 31#include <asm/systemcfg.h>
35#include <asm/ppc_asm.h> 32#include <asm/ppc_asm.h>
36#include <asm/offsets.h> 33#include <asm/offsets.h>
@@ -45,18 +42,13 @@
45#endif 42#endif
46 43
47/* 44/*
48 * hcall interface to pSeries LPAR
49 */
50#define H_SET_ASR 0x30
51
52/*
53 * We layout physical memory as follows: 45 * We layout physical memory as follows:
54 * 0x0000 - 0x00ff : Secondary processor spin code 46 * 0x0000 - 0x00ff : Secondary processor spin code
55 * 0x0100 - 0x2fff : pSeries Interrupt prologs 47 * 0x0100 - 0x2fff : pSeries Interrupt prologs
56 * 0x3000 - 0x3fff : Interrupt support 48 * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs
57 * 0x4000 - 0x4fff : NACA 49 * 0x6000 - 0x6fff : Initial (CPU0) segment table
58 * 0x6000 : iSeries and common interrupt prologs 50 * 0x7000 - 0x7fff : FWNMI data area
59 * 0x9000 - 0x9fff : Initial segment table 51 * 0x8000 - : Early init and support code
60 */ 52 */
61 53
62/* 54/*
@@ -94,6 +86,7 @@ END_FTR_SECTION(0, 1)
94 86
95 /* Catch branch to 0 in real mode */ 87 /* Catch branch to 0 in real mode */
96 trap 88 trap
89
97#ifdef CONFIG_PPC_ISERIES 90#ifdef CONFIG_PPC_ISERIES
98 /* 91 /*
99 * At offset 0x20, there is a pointer to iSeries LPAR data. 92 * At offset 0x20, there is a pointer to iSeries LPAR data.
@@ -103,12 +96,12 @@ END_FTR_SECTION(0, 1)
103 .llong hvReleaseData-KERNELBASE 96 .llong hvReleaseData-KERNELBASE
104 97
105 /* 98 /*
106 * At offset 0x28 and 0x30 are offsets to the msChunks 99 * At offset 0x28 and 0x30 are offsets to the mschunks_map
107 * array (used by the iSeries LPAR debugger to do translation 100 * array (used by the iSeries LPAR debugger to do translation
108 * between physical addresses and absolute addresses) and 101 * between physical addresses and absolute addresses) and
109 * to the pidhash table (also used by the debugger) 102 * to the pidhash table (also used by the debugger)
110 */ 103 */
111 .llong msChunks-KERNELBASE 104 .llong mschunks_map-KERNELBASE
112 .llong 0 /* pidhash-KERNELBASE SFRXXX */ 105 .llong 0 /* pidhash-KERNELBASE SFRXXX */
113 106
114 /* Offset 0x38 - Pointer to start of embedded System.map */ 107 /* Offset 0x38 - Pointer to start of embedded System.map */
@@ -120,7 +113,7 @@ embedded_sysmap_start:
120embedded_sysmap_end: 113embedded_sysmap_end:
121 .llong 0 114 .llong 0
122 115
123#else /* CONFIG_PPC_ISERIES */ 116#endif /* CONFIG_PPC_ISERIES */
124 117
125 /* Secondary processors spin on this value until it goes to 1. */ 118 /* Secondary processors spin on this value until it goes to 1. */
126 .globl __secondary_hold_spinloop 119 .globl __secondary_hold_spinloop
@@ -155,7 +148,7 @@ _GLOBAL(__secondary_hold)
155 std r24,__secondary_hold_acknowledge@l(0) 148 std r24,__secondary_hold_acknowledge@l(0)
156 sync 149 sync
157 150
158 /* All secondary cpu's wait here until told to start. */ 151 /* All secondary cpus wait here until told to start. */
159100: ld r4,__secondary_hold_spinloop@l(0) 152100: ld r4,__secondary_hold_spinloop@l(0)
160 cmpdi 0,r4,1 153 cmpdi 0,r4,1
161 bne 100b 154 bne 100b
@@ -170,7 +163,6 @@ _GLOBAL(__secondary_hold)
170 BUG_OPCODE 163 BUG_OPCODE
171#endif 164#endif
172#endif 165#endif
173#endif
174 166
175/* This value is used to mark exception frames on the stack. */ 167/* This value is used to mark exception frames on the stack. */
176 .section ".toc","aw" 168 .section ".toc","aw"
@@ -502,33 +494,37 @@ system_call_pSeries:
502 STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) 494 STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
503 STD_EXCEPTION_PSERIES(0x1700, altivec_assist) 495 STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
504 496
497 . = 0x3000
498
499/*** pSeries interrupt support ***/
500
505 /* moved from 0xf00 */ 501 /* moved from 0xf00 */
506 STD_EXCEPTION_PSERIES(0x3000, performance_monitor) 502 STD_EXCEPTION_PSERIES(., performance_monitor)
507 503
508 . = 0x3100 504 .align 7
509_GLOBAL(do_stab_bolted_pSeries) 505_GLOBAL(do_stab_bolted_pSeries)
510 mtcrf 0x80,r12 506 mtcrf 0x80,r12
511 mfspr r12,SPRG2 507 mfspr r12,SPRG2
512 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) 508 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
513 509
514 510/*
515 /* Space for the naca. Architected to be located at real address 511 * Vectors for the FWNMI option. Share common code.
516 * NACA_PHYS_ADDR. Various tools rely on this location being fixed. 512 */
517 * The first dword of the naca is required by iSeries LPAR to 513 .globl system_reset_fwnmi
518 * point to itVpdAreas. On pSeries native, this value is not used. 514system_reset_fwnmi:
519 */ 515 HMT_MEDIUM
520 . = NACA_PHYS_ADDR 516 mtspr SPRG1,r13 /* save r13 */
521 .globl __end_interrupts 517 RUNLATCH_ON(r13)
522__end_interrupts: 518 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
523#ifdef CONFIG_PPC_ISERIES
524 .globl naca
525naca:
526 .llong itVpdAreas
527 .llong 0 /* xRamDisk */
528 .llong 0 /* xRamDiskSize */
529 519
530 . = 0x6100 520 .globl machine_check_fwnmi
521machine_check_fwnmi:
522 HMT_MEDIUM
523 mtspr SPRG1,r13 /* save r13 */
524 RUNLATCH_ON(r13)
525 EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
531 526
527#ifdef CONFIG_PPC_ISERIES
532/*** ISeries-LPAR interrupt handlers ***/ 528/*** ISeries-LPAR interrupt handlers ***/
533 529
534 STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC) 530 STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC)
@@ -626,9 +622,7 @@ system_reset_iSeries:
626 622
627 cmpwi 0,r23,0 623 cmpwi 0,r23,0
628 beq iSeries_secondary_smp_loop /* Loop until told to go */ 624 beq iSeries_secondary_smp_loop /* Loop until told to go */
629#ifdef SECONDARY_PROCESSORS
630 bne .__secondary_start /* Loop until told to go */ 625 bne .__secondary_start /* Loop until told to go */
631#endif
632iSeries_secondary_smp_loop: 626iSeries_secondary_smp_loop:
633 /* Let the Hypervisor know we are alive */ 627 /* Let the Hypervisor know we are alive */
634 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ 628 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
@@ -671,51 +665,8 @@ hardware_interrupt_iSeries_masked:
671 ld r13,PACA_EXGEN+EX_R13(r13) 665 ld r13,PACA_EXGEN+EX_R13(r13)
672 rfid 666 rfid
673 b . /* prevent speculative execution */ 667 b . /* prevent speculative execution */
674#endif
675
676/*
677 * Data area reserved for FWNMI option.
678 */
679 .= 0x7000
680 .globl fwnmi_data_area
681fwnmi_data_area:
682
683#ifdef CONFIG_PPC_ISERIES
684 . = LPARMAP_PHYS
685#include "lparmap.s"
686#endif /* CONFIG_PPC_ISERIES */ 668#endif /* CONFIG_PPC_ISERIES */
687 669
688/*
689 * Vectors for the FWNMI option. Share common code.
690 */
691 . = 0x8000
692 .globl system_reset_fwnmi
693system_reset_fwnmi:
694 HMT_MEDIUM
695 mtspr SPRG1,r13 /* save r13 */
696 RUNLATCH_ON(r13)
697 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
698 .globl machine_check_fwnmi
699machine_check_fwnmi:
700 HMT_MEDIUM
701 mtspr SPRG1,r13 /* save r13 */
702 RUNLATCH_ON(r13)
703 EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
704
705 /*
706 * Space for the initial segment table
707 * For LPAR, the hypervisor must fill in at least one entry
708 * before we get control (with relocate on)
709 */
710 . = STAB0_PHYS_ADDR
711 .globl __start_stab
712__start_stab:
713
714 . = (STAB0_PHYS_ADDR + PAGE_SIZE)
715 .globl __end_stab
716__end_stab:
717
718
719/*** Common interrupt handlers ***/ 670/*** Common interrupt handlers ***/
720 671
721 STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception) 672 STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
@@ -752,8 +703,8 @@ machine_check_common:
752 * R9 contains the saved CR, r13 points to the paca, 703 * R9 contains the saved CR, r13 points to the paca,
753 * r10 contains the (bad) kernel stack pointer, 704 * r10 contains the (bad) kernel stack pointer,
754 * r11 and r12 contain the saved SRR0 and SRR1. 705 * r11 and r12 contain the saved SRR0 and SRR1.
755 * We switch to using the paca guard page as an emergency stack, 706 * We switch to using an emergency stack, save the registers there,
756 * save the registers there, and call kernel_bad_stack(), which panics. 707 * and call kernel_bad_stack(), which panics.
757 */ 708 */
758bad_stack: 709bad_stack:
759 ld r1,PACAEMERGSP(r13) 710 ld r1,PACAEMERGSP(r13)
@@ -906,6 +857,62 @@ fp_unavailable_common:
906 bl .kernel_fp_unavailable_exception 857 bl .kernel_fp_unavailable_exception
907 BUG_OPCODE 858 BUG_OPCODE
908 859
860/*
861 * load_up_fpu(unused, unused, tsk)
862 * Disable FP for the task which had the FPU previously,
863 * and save its floating-point registers in its thread_struct.
864 * Enables the FPU for use in the kernel on return.
865 * On SMP we know the fpu is free, since we give it up every
866 * switch (ie, no lazy save of the FP registers).
867 * On entry: r13 == 'current' && last_task_used_math != 'current'
868 */
869_STATIC(load_up_fpu)
870 mfmsr r5 /* grab the current MSR */
871 ori r5,r5,MSR_FP
872 mtmsrd r5 /* enable use of fpu now */
873 isync
874/*
875 * For SMP, we don't do lazy FPU switching because it just gets too
876 * horrendously complex, especially when a task switches from one CPU
877 * to another. Instead we call giveup_fpu in switch_to.
878 *
879 */
880#ifndef CONFIG_SMP
881 ld r3,last_task_used_math@got(r2)
882 ld r4,0(r3)
883 cmpdi 0,r4,0
884 beq 1f
885 /* Save FP state to last_task_used_math's THREAD struct */
886 addi r4,r4,THREAD
887 SAVE_32FPRS(0, r4)
888 mffs fr0
889 stfd fr0,THREAD_FPSCR(r4)
890 /* Disable FP for last_task_used_math */
891 ld r5,PT_REGS(r4)
892 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
893 li r6,MSR_FP|MSR_FE0|MSR_FE1
894 andc r4,r4,r6
895 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
8961:
897#endif /* CONFIG_SMP */
898 /* enable use of FP after return */
899 ld r4,PACACURRENT(r13)
900 addi r5,r4,THREAD /* Get THREAD */
901 ld r4,THREAD_FPEXC_MODE(r5)
902 ori r12,r12,MSR_FP
903 or r12,r12,r4
904 std r12,_MSR(r1)
905 lfd fr0,THREAD_FPSCR(r5)
906 mtfsf 0xff,fr0
907 REST_32FPRS(0, r5)
908#ifndef CONFIG_SMP
909 /* Update last_task_used_math to 'current' */
910 subi r4,r5,THREAD /* Back to 'current' */
911 std r4,0(r3)
912#endif /* CONFIG_SMP */
913 /* restore registers and return */
914 b fast_exception_return
915
909 .align 7 916 .align 7
910 .globl altivec_unavailable_common 917 .globl altivec_unavailable_common
911altivec_unavailable_common: 918altivec_unavailable_common:
@@ -921,6 +928,80 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
921 bl .altivec_unavailable_exception 928 bl .altivec_unavailable_exception
922 b .ret_from_except 929 b .ret_from_except
923 930
931#ifdef CONFIG_ALTIVEC
932/*
933 * load_up_altivec(unused, unused, tsk)
934 * Disable VMX for the task which had it previously,
935 * and save its vector registers in its thread_struct.
936 * Enables the VMX for use in the kernel on return.
937 * On SMP we know the VMX is free, since we give it up every
938 * switch (ie, no lazy save of the vector registers).
939 * On entry: r13 == 'current' && last_task_used_altivec != 'current'
940 */
941_STATIC(load_up_altivec)
942 mfmsr r5 /* grab the current MSR */
943 oris r5,r5,MSR_VEC@h
944 mtmsrd r5 /* enable use of VMX now */
945 isync
946
947/*
948 * For SMP, we don't do lazy VMX switching because it just gets too
949 * horrendously complex, especially when a task switches from one CPU
950 * to another. Instead we call giveup_altvec in switch_to.
951 * VRSAVE isn't dealt with here, that is done in the normal context
952 * switch code. Note that we could rely on vrsave value to eventually
953 * avoid saving all of the VREGs here...
954 */
955#ifndef CONFIG_SMP
956 ld r3,last_task_used_altivec@got(r2)
957 ld r4,0(r3)
958 cmpdi 0,r4,0
959 beq 1f
960 /* Save VMX state to last_task_used_altivec's THREAD struct */
961 addi r4,r4,THREAD
962 SAVE_32VRS(0,r5,r4)
963 mfvscr vr0
964 li r10,THREAD_VSCR
965 stvx vr0,r10,r4
966 /* Disable VMX for last_task_used_altivec */
967 ld r5,PT_REGS(r4)
968 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
969 lis r6,MSR_VEC@h
970 andc r4,r4,r6
971 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
9721:
973#endif /* CONFIG_SMP */
974 /* Hack: if we get an altivec unavailable trap with VRSAVE
975 * set to all zeros, we assume this is a broken application
976 * that fails to set it properly, and thus we switch it to
977 * all 1's
978 */
979 mfspr r4,SPRN_VRSAVE
980 cmpdi 0,r4,0
981 bne+ 1f
982 li r4,-1
983 mtspr SPRN_VRSAVE,r4
9841:
985 /* enable use of VMX after return */
986 ld r4,PACACURRENT(r13)
987 addi r5,r4,THREAD /* Get THREAD */
988 oris r12,r12,MSR_VEC@h
989 std r12,_MSR(r1)
990 li r4,1
991 li r10,THREAD_VSCR
992 stw r4,THREAD_USED_VR(r5)
993 lvx vr0,r10,r5
994 mtvscr vr0
995 REST_32VRS(0,r4,r5)
996#ifndef CONFIG_SMP
997 /* Update last_task_used_math to 'current' */
998 subi r4,r5,THREAD /* Back to 'current' */
999 std r4,0(r3)
1000#endif /* CONFIG_SMP */
1001 /* restore registers and return */
1002 b fast_exception_return
1003#endif /* CONFIG_ALTIVEC */
1004
924/* 1005/*
925 * Hash table stuff 1006 * Hash table stuff
926 */ 1007 */
@@ -1167,6 +1248,28 @@ unrecov_slb:
1167 bl .unrecoverable_exception 1248 bl .unrecoverable_exception
1168 b 1b 1249 b 1b
1169 1250
1251/*
1252 * Space for CPU0's segment table.
1253 *
1254 * On iSeries, the hypervisor must fill in at least one entry before
1255 * we get control (with relocate on). The address is give to the hv
1256 * as a page number (see xLparMap in LparData.c), so this must be at a
1257 * fixed address (the linker can't compute (u64)&initial_stab >>
1258 * PAGE_SHIFT).
1259 */
1260 . = STAB0_PHYS_ADDR /* 0x6000 */
1261 .globl initial_stab
1262initial_stab:
1263 .space 4096
1264
1265/*
1266 * Data area reserved for FWNMI option.
1267 * This address (0x7000) is fixed by the RPA.
1268 */
1269 .= 0x7000
1270 .globl fwnmi_data_area
1271fwnmi_data_area:
1272 .space PAGE_SIZE
1170 1273
1171/* 1274/*
1172 * On pSeries, secondary processors spin in the following code. 1275 * On pSeries, secondary processors spin in the following code.
@@ -1200,7 +1303,7 @@ _GLOBAL(pSeries_secondary_smp_init)
1200 b .kexec_wait /* next kernel might do better */ 1303 b .kexec_wait /* next kernel might do better */
1201 1304
12022: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */ 13052: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */
1203 /* From now on, r24 is expected to be logica cpuid */ 1306 /* From now on, r24 is expected to be logical cpuid */
1204 mr r24,r5 1307 mr r24,r5
12053: HMT_LOW 13083: HMT_LOW
1206 lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ 1309 lbz r23,PACAPROCSTART(r13) /* Test if this processor should */
@@ -1213,10 +1316,8 @@ _GLOBAL(pSeries_secondary_smp_init)
1213 1316
1214 cmpwi 0,r23,0 1317 cmpwi 0,r23,0
1215#ifdef CONFIG_SMP 1318#ifdef CONFIG_SMP
1216#ifdef SECONDARY_PROCESSORS
1217 bne .__secondary_start 1319 bne .__secondary_start
1218#endif 1320#endif
1219#endif
1220 b 3b /* Loop until told to go */ 1321 b 3b /* Loop until told to go */
1221 1322
1222#ifdef CONFIG_PPC_ISERIES 1323#ifdef CONFIG_PPC_ISERIES
@@ -1430,228 +1531,6 @@ _GLOBAL(copy_and_flush)
1430.align 8 1531.align 8
1431copy_to_here: 1532copy_to_here:
1432 1533
1433/*
1434 * load_up_fpu(unused, unused, tsk)
1435 * Disable FP for the task which had the FPU previously,
1436 * and save its floating-point registers in its thread_struct.
1437 * Enables the FPU for use in the kernel on return.
1438 * On SMP we know the fpu is free, since we give it up every
1439 * switch (ie, no lazy save of the FP registers).
1440 * On entry: r13 == 'current' && last_task_used_math != 'current'
1441 */
1442_STATIC(load_up_fpu)
1443 mfmsr r5 /* grab the current MSR */
1444 ori r5,r5,MSR_FP
1445 mtmsrd r5 /* enable use of fpu now */
1446 isync
1447/*
1448 * For SMP, we don't do lazy FPU switching because it just gets too
1449 * horrendously complex, especially when a task switches from one CPU
1450 * to another. Instead we call giveup_fpu in switch_to.
1451 *
1452 */
1453#ifndef CONFIG_SMP
1454 ld r3,last_task_used_math@got(r2)
1455 ld r4,0(r3)
1456 cmpdi 0,r4,0
1457 beq 1f
1458 /* Save FP state to last_task_used_math's THREAD struct */
1459 addi r4,r4,THREAD
1460 SAVE_32FPRS(0, r4)
1461 mffs fr0
1462 stfd fr0,THREAD_FPSCR(r4)
1463 /* Disable FP for last_task_used_math */
1464 ld r5,PT_REGS(r4)
1465 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1466 li r6,MSR_FP|MSR_FE0|MSR_FE1
1467 andc r4,r4,r6
1468 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
14691:
1470#endif /* CONFIG_SMP */
1471 /* enable use of FP after return */
1472 ld r4,PACACURRENT(r13)
1473 addi r5,r4,THREAD /* Get THREAD */
1474 ld r4,THREAD_FPEXC_MODE(r5)
1475 ori r12,r12,MSR_FP
1476 or r12,r12,r4
1477 std r12,_MSR(r1)
1478 lfd fr0,THREAD_FPSCR(r5)
1479 mtfsf 0xff,fr0
1480 REST_32FPRS(0, r5)
1481#ifndef CONFIG_SMP
1482 /* Update last_task_used_math to 'current' */
1483 subi r4,r5,THREAD /* Back to 'current' */
1484 std r4,0(r3)
1485#endif /* CONFIG_SMP */
1486 /* restore registers and return */
1487 b fast_exception_return
1488
1489/*
1490 * disable_kernel_fp()
1491 * Disable the FPU.
1492 */
1493_GLOBAL(disable_kernel_fp)
1494 mfmsr r3
1495 rldicl r0,r3,(63-MSR_FP_LG),1
1496 rldicl r3,r0,(MSR_FP_LG+1),0
1497 mtmsrd r3 /* disable use of fpu now */
1498 isync
1499 blr
1500
1501/*
1502 * giveup_fpu(tsk)
1503 * Disable FP for the task given as the argument,
1504 * and save the floating-point registers in its thread_struct.
1505 * Enables the FPU for use in the kernel on return.
1506 */
1507_GLOBAL(giveup_fpu)
1508 mfmsr r5
1509 ori r5,r5,MSR_FP
1510 mtmsrd r5 /* enable use of fpu now */
1511 isync
1512 cmpdi 0,r3,0
1513 beqlr- /* if no previous owner, done */
1514 addi r3,r3,THREAD /* want THREAD of task */
1515 ld r5,PT_REGS(r3)
1516 cmpdi 0,r5,0
1517 SAVE_32FPRS(0, r3)
1518 mffs fr0
1519 stfd fr0,THREAD_FPSCR(r3)
1520 beq 1f
1521 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1522 li r3,MSR_FP|MSR_FE0|MSR_FE1
1523 andc r4,r4,r3 /* disable FP for previous task */
1524 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
15251:
1526#ifndef CONFIG_SMP
1527 li r5,0
1528 ld r4,last_task_used_math@got(r2)
1529 std r5,0(r4)
1530#endif /* CONFIG_SMP */
1531 blr
1532
1533
1534#ifdef CONFIG_ALTIVEC
1535
1536/*
1537 * load_up_altivec(unused, unused, tsk)
1538 * Disable VMX for the task which had it previously,
1539 * and save its vector registers in its thread_struct.
1540 * Enables the VMX for use in the kernel on return.
1541 * On SMP we know the VMX is free, since we give it up every
1542 * switch (ie, no lazy save of the vector registers).
1543 * On entry: r13 == 'current' && last_task_used_altivec != 'current'
1544 */
1545_STATIC(load_up_altivec)
1546 mfmsr r5 /* grab the current MSR */
1547 oris r5,r5,MSR_VEC@h
1548 mtmsrd r5 /* enable use of VMX now */
1549 isync
1550
1551/*
1552 * For SMP, we don't do lazy VMX switching because it just gets too
1553 * horrendously complex, especially when a task switches from one CPU
1554 * to another. Instead we call giveup_altvec in switch_to.
1555 * VRSAVE isn't dealt with here, that is done in the normal context
1556 * switch code. Note that we could rely on vrsave value to eventually
1557 * avoid saving all of the VREGs here...
1558 */
1559#ifndef CONFIG_SMP
1560 ld r3,last_task_used_altivec@got(r2)
1561 ld r4,0(r3)
1562 cmpdi 0,r4,0
1563 beq 1f
1564 /* Save VMX state to last_task_used_altivec's THREAD struct */
1565 addi r4,r4,THREAD
1566 SAVE_32VRS(0,r5,r4)
1567 mfvscr vr0
1568 li r10,THREAD_VSCR
1569 stvx vr0,r10,r4
1570 /* Disable VMX for last_task_used_altivec */
1571 ld r5,PT_REGS(r4)
1572 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1573 lis r6,MSR_VEC@h
1574 andc r4,r4,r6
1575 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
15761:
1577#endif /* CONFIG_SMP */
1578 /* Hack: if we get an altivec unavailable trap with VRSAVE
1579 * set to all zeros, we assume this is a broken application
1580 * that fails to set it properly, and thus we switch it to
1581 * all 1's
1582 */
1583 mfspr r4,SPRN_VRSAVE
1584 cmpdi 0,r4,0
1585 bne+ 1f
1586 li r4,-1
1587 mtspr SPRN_VRSAVE,r4
15881:
1589 /* enable use of VMX after return */
1590 ld r4,PACACURRENT(r13)
1591 addi r5,r4,THREAD /* Get THREAD */
1592 oris r12,r12,MSR_VEC@h
1593 std r12,_MSR(r1)
1594 li r4,1
1595 li r10,THREAD_VSCR
1596 stw r4,THREAD_USED_VR(r5)
1597 lvx vr0,r10,r5
1598 mtvscr vr0
1599 REST_32VRS(0,r4,r5)
1600#ifndef CONFIG_SMP
1601 /* Update last_task_used_math to 'current' */
1602 subi r4,r5,THREAD /* Back to 'current' */
1603 std r4,0(r3)
1604#endif /* CONFIG_SMP */
1605 /* restore registers and return */
1606 b fast_exception_return
1607
1608/*
1609 * disable_kernel_altivec()
1610 * Disable the VMX.
1611 */
1612_GLOBAL(disable_kernel_altivec)
1613 mfmsr r3
1614 rldicl r0,r3,(63-MSR_VEC_LG),1
1615 rldicl r3,r0,(MSR_VEC_LG+1),0
1616 mtmsrd r3 /* disable use of VMX now */
1617 isync
1618 blr
1619
1620/*
1621 * giveup_altivec(tsk)
1622 * Disable VMX for the task given as the argument,
1623 * and save the vector registers in its thread_struct.
1624 * Enables the VMX for use in the kernel on return.
1625 */
1626_GLOBAL(giveup_altivec)
1627 mfmsr r5
1628 oris r5,r5,MSR_VEC@h
1629 mtmsrd r5 /* enable use of VMX now */
1630 isync
1631 cmpdi 0,r3,0
1632 beqlr- /* if no previous owner, done */
1633 addi r3,r3,THREAD /* want THREAD of task */
1634 ld r5,PT_REGS(r3)
1635 cmpdi 0,r5,0
1636 SAVE_32VRS(0,r4,r3)
1637 mfvscr vr0
1638 li r4,THREAD_VSCR
1639 stvx vr0,r4,r3
1640 beq 1f
1641 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1642 lis r3,MSR_VEC@h
1643 andc r4,r4,r3 /* disable FP for previous task */
1644 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
16451:
1646#ifndef CONFIG_SMP
1647 li r5,0
1648 ld r4,last_task_used_altivec@got(r2)
1649 std r5,0(r4)
1650#endif /* CONFIG_SMP */
1651 blr
1652
1653#endif /* CONFIG_ALTIVEC */
1654
1655#ifdef CONFIG_SMP 1534#ifdef CONFIG_SMP
1656#ifdef CONFIG_PPC_PMAC 1535#ifdef CONFIG_PPC_PMAC
1657/* 1536/*
@@ -2002,9 +1881,6 @@ _STATIC(start_here_common)
2002 1881
2003 bl .start_kernel 1882 bl .start_kernel
2004 1883
2005_GLOBAL(__setup_cpu_power3)
2006 blr
2007
2008_GLOBAL(hmt_init) 1884_GLOBAL(hmt_init)
2009#ifdef CONFIG_HMT 1885#ifdef CONFIG_HMT
2010 LOADADDR(r5, hmt_thread_data) 1886 LOADADDR(r5, hmt_thread_data)
@@ -2095,20 +1971,19 @@ _GLOBAL(smp_release_cpus)
2095 1971
2096/* 1972/*
2097 * We put a few things here that have to be page-aligned. 1973 * We put a few things here that have to be page-aligned.
2098 * This stuff goes at the beginning of the data segment, 1974 * This stuff goes at the beginning of the bss, which is page-aligned.
2099 * which is page-aligned.
2100 */ 1975 */
2101 .data 1976 .section ".bss"
1977
2102 .align 12 1978 .align 12
2103 .globl sdata 1979
2104sdata:
2105 .globl empty_zero_page 1980 .globl empty_zero_page
2106empty_zero_page: 1981empty_zero_page:
2107 .space 4096 1982 .space PAGE_SIZE
2108 1983
2109 .globl swapper_pg_dir 1984 .globl swapper_pg_dir
2110swapper_pg_dir: 1985swapper_pg_dir:
2111 .space 4096 1986 .space PAGE_SIZE
2112 1987
2113/* 1988/*
2114 * This space gets a copy of optional info passed to us by the bootstrap 1989 * This space gets a copy of optional info passed to us by the bootstrap
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
index b0250ae4a72a..2192055a90a0 100644
--- a/arch/ppc64/kernel/iSeries_htab.c
+++ b/arch/ppc64/kernel/iSeries_htab.c
@@ -41,6 +41,7 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
41 unsigned long prpn, unsigned long vflags, 41 unsigned long prpn, unsigned long vflags,
42 unsigned long rflags) 42 unsigned long rflags)
43{ 43{
44 unsigned long arpn;
44 long slot; 45 long slot;
45 hpte_t lhpte; 46 hpte_t lhpte;
46 int secondary = 0; 47 int secondary = 0;
@@ -70,8 +71,10 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
70 slot &= 0x7fffffffffffffff; 71 slot &= 0x7fffffffffffffff;
71 } 72 }
72 73
74 arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT;
75
73 lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; 76 lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
74 lhpte.r = (physRpn_to_absRpn(prpn) << HPTE_R_RPN_SHIFT) | rflags; 77 lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
75 78
76 /* Now fill in the actual HPTE */ 79 /* Now fill in the actual HPTE */
77 HvCallHpt_addValidate(slot, secondary, &lhpte); 80 HvCallHpt_addValidate(slot, secondary, &lhpte);
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index a649edbb23b6..3ffefbbc6623 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -39,6 +39,7 @@
39#include <asm/cputable.h> 39#include <asm/cputable.h>
40#include <asm/sections.h> 40#include <asm/sections.h>
41#include <asm/iommu.h> 41#include <asm/iommu.h>
42#include <asm/firmware.h>
42 43
43#include <asm/time.h> 44#include <asm/time.h>
44#include "iSeries_setup.h" 45#include "iSeries_setup.h"
@@ -314,6 +315,8 @@ static void __init iSeries_init_early(void)
314 315
315 DBG(" -> iSeries_init_early()\n"); 316 DBG(" -> iSeries_init_early()\n");
316 317
318 ppc64_firmware_features = FW_FEATURE_ISERIES;
319
317 ppcdbg_initialize(); 320 ppcdbg_initialize();
318 321
319#if defined(CONFIG_BLK_DEV_INITRD) 322#if defined(CONFIG_BLK_DEV_INITRD)
@@ -412,6 +415,22 @@ static void __init iSeries_init_early(void)
412 DBG(" <- iSeries_init_early()\n"); 415 DBG(" <- iSeries_init_early()\n");
413} 416}
414 417
418struct mschunks_map mschunks_map = {
419 /* XXX We don't use these, but Piranha might need them. */
420 .chunk_size = MSCHUNKS_CHUNK_SIZE,
421 .chunk_shift = MSCHUNKS_CHUNK_SHIFT,
422 .chunk_mask = MSCHUNKS_OFFSET_MASK,
423};
424EXPORT_SYMBOL(mschunks_map);
425
426void mschunks_alloc(unsigned long num_chunks)
427{
428 klimit = _ALIGN(klimit, sizeof(u32));
429 mschunks_map.mapping = (u32 *)klimit;
430 klimit += num_chunks * sizeof(u32);
431 mschunks_map.num_chunks = num_chunks;
432}
433
415/* 434/*
416 * The iSeries may have very large memories ( > 128 GB ) and a partition 435 * The iSeries may have very large memories ( > 128 GB ) and a partition
417 * may get memory in "chunks" that may be anywhere in the 2**52 real 436 * may get memory in "chunks" that may be anywhere in the 2**52 real
@@ -449,7 +468,7 @@ static void __init build_iSeries_Memory_Map(void)
449 468
450 /* Chunk size on iSeries is 256K bytes */ 469 /* Chunk size on iSeries is 256K bytes */
451 totalChunks = (u32)HvLpConfig_getMsChunks(); 470 totalChunks = (u32)HvLpConfig_getMsChunks();
452 klimit = msChunks_alloc(klimit, totalChunks, 1UL << 18); 471 mschunks_alloc(totalChunks);
453 472
454 /* 473 /*
455 * Get absolute address of our load area 474 * Get absolute address of our load area
@@ -486,7 +505,7 @@ static void __init build_iSeries_Memory_Map(void)
486 printk("Load area size %dK\n", loadAreaSize * 256); 505 printk("Load area size %dK\n", loadAreaSize * 256);
487 506
488 for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk) 507 for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk)
489 msChunks.abs[nextPhysChunk] = 508 mschunks_map.mapping[nextPhysChunk] =
490 loadAreaFirstChunk + nextPhysChunk; 509 loadAreaFirstChunk + nextPhysChunk;
491 510
492 /* 511 /*
@@ -495,7 +514,7 @@ static void __init build_iSeries_Memory_Map(void)
495 */ 514 */
496 hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress()); 515 hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());
497 hptSizePages = (u32)HvCallHpt_getHptPages(); 516 hptSizePages = (u32)HvCallHpt_getHptPages();
498 hptSizeChunks = hptSizePages >> (msChunks.chunk_shift - PAGE_SHIFT); 517 hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT);
499 hptLastChunk = hptFirstChunk + hptSizeChunks - 1; 518 hptLastChunk = hptFirstChunk + hptSizeChunks - 1;
500 519
501 printk("HPT absolute addr = %016lx, size = %dK\n", 520 printk("HPT absolute addr = %016lx, size = %dK\n",
@@ -552,7 +571,8 @@ static void __init build_iSeries_Memory_Map(void)
552 (absChunk > hptLastChunk)) && 571 (absChunk > hptLastChunk)) &&
553 ((absChunk < loadAreaFirstChunk) || 572 ((absChunk < loadAreaFirstChunk) ||
554 (absChunk > loadAreaLastChunk))) { 573 (absChunk > loadAreaLastChunk))) {
555 msChunks.abs[nextPhysChunk] = absChunk; 574 mschunks_map.mapping[nextPhysChunk] =
575 absChunk;
556 ++nextPhysChunk; 576 ++nextPhysChunk;
557 } 577 }
558 } 578 }
@@ -944,6 +964,8 @@ void __init iSeries_early_setup(void)
944 ppc_md.calibrate_decr = iSeries_calibrate_decr; 964 ppc_md.calibrate_decr = iSeries_calibrate_decr;
945 ppc_md.progress = iSeries_progress; 965 ppc_md.progress = iSeries_progress;
946 966
967 /* XXX Implement enable_pmcs for iSeries */
968
947 if (get_paca()->lppaca.shared_proc) { 969 if (get_paca()->lppaca.shared_proc) {
948 ppc_md.idle_loop = iseries_shared_idle; 970 ppc_md.idle_loop = iseries_shared_idle;
949 printk(KERN_INFO "Using shared processor idle loop\n"); 971 printk(KERN_INFO "Using shared processor idle loop\n");
diff --git a/arch/ppc64/kernel/iSeries_vio.c b/arch/ppc64/kernel/iSeries_vio.c
new file mode 100644
index 000000000000..b4268cc4ba48
--- /dev/null
+++ b/arch/ppc64/kernel/iSeries_vio.c
@@ -0,0 +1,144 @@
1/*
2 * IBM PowerPC iSeries Virtual I/O Infrastructure Support.
3 *
4 * Copyright (c) 2005 Stephen Rothwell, IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <linux/types.h>
12#include <linux/device.h>
13#include <linux/init.h>
14
15#include <asm/vio.h>
16#include <asm/iommu.h>
17#include <asm/abs_addr.h>
18#include <asm/page.h>
19#include <asm/iSeries/vio.h>
20#include <asm/iSeries/HvTypes.h>
21#include <asm/iSeries/HvLpConfig.h>
22#include <asm/iSeries/HvCallXm.h>
23
24struct device *iSeries_vio_dev = &vio_bus_device.dev;
25EXPORT_SYMBOL(iSeries_vio_dev);
26
27static struct iommu_table veth_iommu_table;
28static struct iommu_table vio_iommu_table;
29
30static void __init iommu_vio_init(void)
31{
32 struct iommu_table *t;
33 struct iommu_table_cb cb;
34 unsigned long cbp;
35 unsigned long itc_entries;
36
37 cb.itc_busno = 255; /* Bus 255 is the virtual bus */
38 cb.itc_virtbus = 0xff; /* Ask for virtual bus */
39
40 cbp = virt_to_abs(&cb);
41 HvCallXm_getTceTableParms(cbp);
42
43 itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);
44 veth_iommu_table.it_size = itc_entries / 2;
45 veth_iommu_table.it_busno = cb.itc_busno;
46 veth_iommu_table.it_offset = cb.itc_offset;
47 veth_iommu_table.it_index = cb.itc_index;
48 veth_iommu_table.it_type = TCE_VB;
49 veth_iommu_table.it_blocksize = 1;
50
51 t = iommu_init_table(&veth_iommu_table);
52
53 if (!t)
54 printk("Virtual Bus VETH TCE table failed.\n");
55
56 vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;
57 vio_iommu_table.it_busno = cb.itc_busno;
58 vio_iommu_table.it_offset = cb.itc_offset +
59 veth_iommu_table.it_size;
60 vio_iommu_table.it_index = cb.itc_index;
61 vio_iommu_table.it_type = TCE_VB;
62 vio_iommu_table.it_blocksize = 1;
63
64 t = iommu_init_table(&vio_iommu_table);
65
66 if (!t)
67 printk("Virtual Bus VIO TCE table failed.\n");
68}
69
70/**
71 * vio_register_device: - Register a new vio device.
72 * @voidev: The device to register.
73 */
74static struct vio_dev *__init vio_register_device_iseries(char *type,
75 uint32_t unit_num)
76{
77 struct vio_dev *viodev;
78
79 /* allocate a vio_dev for this node */
80 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
81 if (!viodev)
82 return NULL;
83 memset(viodev, 0, sizeof(struct vio_dev));
84
85 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
86
87 return vio_register_device_common(viodev, viodev->dev.bus_id, type,
88 unit_num, &vio_iommu_table);
89}
90
91void __init probe_bus_iseries(void)
92{
93 HvLpIndexMap vlan_map;
94 struct vio_dev *viodev;
95 int i;
96
97 /* there is only one of each of these */
98 vio_register_device_iseries("viocons", 0);
99 vio_register_device_iseries("vscsi", 0);
100
101 vlan_map = HvLpConfig_getVirtualLanIndexMap();
102 for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
103 if ((vlan_map & (0x8000 >> i)) == 0)
104 continue;
105 viodev = vio_register_device_iseries("vlan", i);
106 /* veth is special and has it own iommu_table */
107 viodev->iommu_table = &veth_iommu_table;
108 }
109 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
110 vio_register_device_iseries("viodasd", i);
111 for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
112 vio_register_device_iseries("viocd", i);
113 for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
114 vio_register_device_iseries("viotape", i);
115}
116
117/**
118 * vio_match_device_iseries: - Tell if a iSeries VIO device matches a
119 * vio_device_id
120 */
121static int vio_match_device_iseries(const struct vio_device_id *id,
122 const struct vio_dev *dev)
123{
124 return strncmp(dev->type, id->type, strlen(id->type)) == 0;
125}
126
127/**
128 * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
129 */
130static int __init vio_bus_init_iseries(void)
131{
132 int err;
133
134 err = vio_bus_init(vio_match_device_iseries, NULL, NULL);
135 if (err == 0) {
136 iommu_vio_init();
137 vio_bus_device.iommu_table = &vio_iommu_table;
138 iSeries_vio_dev = &vio_bus_device.dev;
139 probe_bus_iseries();
140 }
141 return err;
142}
143
144__initcall(vio_bus_init_iseries);
diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
index d6c6bd03d2a4..5adaca2ddc9d 100644
--- a/arch/ppc64/kernel/lmb.c
+++ b/arch/ppc64/kernel/lmb.c
@@ -28,33 +28,28 @@ void lmb_dump_all(void)
28{ 28{
29#ifdef DEBUG 29#ifdef DEBUG
30 unsigned long i; 30 unsigned long i;
31 struct lmb *_lmb = &lmb;
32 31
33 udbg_printf("lmb_dump_all:\n"); 32 udbg_printf("lmb_dump_all:\n");
34 udbg_printf(" memory.cnt = 0x%lx\n", 33 udbg_printf(" memory.cnt = 0x%lx\n",
35 _lmb->memory.cnt); 34 lmb.memory.cnt);
36 udbg_printf(" memory.size = 0x%lx\n", 35 udbg_printf(" memory.size = 0x%lx\n",
37 _lmb->memory.size); 36 lmb.memory.size);
38 for (i=0; i < _lmb->memory.cnt ;i++) { 37 for (i=0; i < lmb.memory.cnt ;i++) {
39 udbg_printf(" memory.region[0x%x].base = 0x%lx\n", 38 udbg_printf(" memory.region[0x%x].base = 0x%lx\n",
40 i, _lmb->memory.region[i].base); 39 i, lmb.memory.region[i].base);
41 udbg_printf(" .physbase = 0x%lx\n",
42 _lmb->memory.region[i].physbase);
43 udbg_printf(" .size = 0x%lx\n", 40 udbg_printf(" .size = 0x%lx\n",
44 _lmb->memory.region[i].size); 41 lmb.memory.region[i].size);
45 } 42 }
46 43
47 udbg_printf("\n reserved.cnt = 0x%lx\n", 44 udbg_printf("\n reserved.cnt = 0x%lx\n",
48 _lmb->reserved.cnt); 45 lmb.reserved.cnt);
49 udbg_printf(" reserved.size = 0x%lx\n", 46 udbg_printf(" reserved.size = 0x%lx\n",
50 _lmb->reserved.size); 47 lmb.reserved.size);
51 for (i=0; i < _lmb->reserved.cnt ;i++) { 48 for (i=0; i < lmb.reserved.cnt ;i++) {
52 udbg_printf(" reserved.region[0x%x].base = 0x%lx\n", 49 udbg_printf(" reserved.region[0x%x].base = 0x%lx\n",
53 i, _lmb->reserved.region[i].base); 50 i, lmb.reserved.region[i].base);
54 udbg_printf(" .physbase = 0x%lx\n",
55 _lmb->reserved.region[i].physbase);
56 udbg_printf(" .size = 0x%lx\n", 51 udbg_printf(" .size = 0x%lx\n",
57 _lmb->reserved.region[i].size); 52 lmb.reserved.region[i].size);
58 } 53 }
59#endif /* DEBUG */ 54#endif /* DEBUG */
60} 55}
@@ -98,7 +93,6 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
98 rgn->region[r1].size += rgn->region[r2].size; 93 rgn->region[r1].size += rgn->region[r2].size;
99 for (i=r2; i < rgn->cnt-1; i++) { 94 for (i=r2; i < rgn->cnt-1; i++) {
100 rgn->region[i].base = rgn->region[i+1].base; 95 rgn->region[i].base = rgn->region[i+1].base;
101 rgn->region[i].physbase = rgn->region[i+1].physbase;
102 rgn->region[i].size = rgn->region[i+1].size; 96 rgn->region[i].size = rgn->region[i+1].size;
103 } 97 }
104 rgn->cnt--; 98 rgn->cnt--;
@@ -108,49 +102,29 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
108void __init 102void __init
109lmb_init(void) 103lmb_init(void)
110{ 104{
111 struct lmb *_lmb = &lmb;
112
113 /* Create a dummy zero size LMB which will get coalesced away later. 105 /* Create a dummy zero size LMB which will get coalesced away later.
114 * This simplifies the lmb_add() code below... 106 * This simplifies the lmb_add() code below...
115 */ 107 */
116 _lmb->memory.region[0].base = 0; 108 lmb.memory.region[0].base = 0;
117 _lmb->memory.region[0].size = 0; 109 lmb.memory.region[0].size = 0;
118 _lmb->memory.cnt = 1; 110 lmb.memory.cnt = 1;
119 111
120 /* Ditto. */ 112 /* Ditto. */
121 _lmb->reserved.region[0].base = 0; 113 lmb.reserved.region[0].base = 0;
122 _lmb->reserved.region[0].size = 0; 114 lmb.reserved.region[0].size = 0;
123 _lmb->reserved.cnt = 1; 115 lmb.reserved.cnt = 1;
124} 116}
125 117
126/* This routine called with relocation disabled. */ 118/* This routine called with relocation disabled. */
127void __init 119void __init
128lmb_analyze(void) 120lmb_analyze(void)
129{ 121{
130 unsigned long i; 122 int i;
131 unsigned long mem_size = 0; 123
132 unsigned long size_mask = 0; 124 lmb.memory.size = 0;
133 struct lmb *_lmb = &lmb;
134#ifdef CONFIG_MSCHUNKS
135 unsigned long physbase = 0;
136#endif
137
138 for (i=0; i < _lmb->memory.cnt; i++) {
139 unsigned long lmb_size;
140
141 lmb_size = _lmb->memory.region[i].size;
142
143#ifdef CONFIG_MSCHUNKS
144 _lmb->memory.region[i].physbase = physbase;
145 physbase += lmb_size;
146#else
147 _lmb->memory.region[i].physbase = _lmb->memory.region[i].base;
148#endif
149 mem_size += lmb_size;
150 size_mask |= lmb_size;
151 }
152 125
153 _lmb->memory.size = mem_size; 126 for (i = 0; i < lmb.memory.cnt; i++)
127 lmb.memory.size += lmb.memory.region[i].size;
154} 128}
155 129
156/* This routine called with relocation disabled. */ 130/* This routine called with relocation disabled. */
@@ -168,7 +142,6 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
168 adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); 142 adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
169 if ( adjacent > 0 ) { 143 if ( adjacent > 0 ) {
170 rgn->region[i].base -= size; 144 rgn->region[i].base -= size;
171 rgn->region[i].physbase -= size;
172 rgn->region[i].size += size; 145 rgn->region[i].size += size;
173 coalesced++; 146 coalesced++;
174 break; 147 break;
@@ -195,11 +168,9 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
195 for (i=rgn->cnt-1; i >= 0; i--) { 168 for (i=rgn->cnt-1; i >= 0; i--) {
196 if (base < rgn->region[i].base) { 169 if (base < rgn->region[i].base) {
197 rgn->region[i+1].base = rgn->region[i].base; 170 rgn->region[i+1].base = rgn->region[i].base;
198 rgn->region[i+1].physbase = rgn->region[i].physbase;
199 rgn->region[i+1].size = rgn->region[i].size; 171 rgn->region[i+1].size = rgn->region[i].size;
200 } else { 172 } else {
201 rgn->region[i+1].base = base; 173 rgn->region[i+1].base = base;
202 rgn->region[i+1].physbase = lmb_abs_to_phys(base);
203 rgn->region[i+1].size = size; 174 rgn->region[i+1].size = size;
204 break; 175 break;
205 } 176 }
@@ -213,12 +184,11 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
213long __init 184long __init
214lmb_add(unsigned long base, unsigned long size) 185lmb_add(unsigned long base, unsigned long size)
215{ 186{
216 struct lmb *_lmb = &lmb; 187 struct lmb_region *_rgn = &(lmb.memory);
217 struct lmb_region *_rgn = &(_lmb->memory);
218 188
219 /* On pSeries LPAR systems, the first LMB is our RMO region. */ 189 /* On pSeries LPAR systems, the first LMB is our RMO region. */
220 if ( base == 0 ) 190 if ( base == 0 )
221 _lmb->rmo_size = size; 191 lmb.rmo_size = size;
222 192
223 return lmb_add_region(_rgn, base, size); 193 return lmb_add_region(_rgn, base, size);
224 194
@@ -227,8 +197,7 @@ lmb_add(unsigned long base, unsigned long size)
227long __init 197long __init
228lmb_reserve(unsigned long base, unsigned long size) 198lmb_reserve(unsigned long base, unsigned long size)
229{ 199{
230 struct lmb *_lmb = &lmb; 200 struct lmb_region *_rgn = &(lmb.reserved);
231 struct lmb_region *_rgn = &(_lmb->reserved);
232 201
233 return lmb_add_region(_rgn, base, size); 202 return lmb_add_region(_rgn, base, size);
234} 203}
@@ -260,13 +229,10 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
260{ 229{
261 long i, j; 230 long i, j;
262 unsigned long base = 0; 231 unsigned long base = 0;
263 struct lmb *_lmb = &lmb;
264 struct lmb_region *_mem = &(_lmb->memory);
265 struct lmb_region *_rsv = &(_lmb->reserved);
266 232
267 for (i=_mem->cnt-1; i >= 0; i--) { 233 for (i=lmb.memory.cnt-1; i >= 0; i--) {
268 unsigned long lmbbase = _mem->region[i].base; 234 unsigned long lmbbase = lmb.memory.region[i].base;
269 unsigned long lmbsize = _mem->region[i].size; 235 unsigned long lmbsize = lmb.memory.region[i].size;
270 236
271 if ( max_addr == LMB_ALLOC_ANYWHERE ) 237 if ( max_addr == LMB_ALLOC_ANYWHERE )
272 base = _ALIGN_DOWN(lmbbase+lmbsize-size, align); 238 base = _ALIGN_DOWN(lmbbase+lmbsize-size, align);
@@ -276,8 +242,8 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
276 continue; 242 continue;
277 243
278 while ( (lmbbase <= base) && 244 while ( (lmbbase <= base) &&
279 ((j = lmb_overlaps_region(_rsv,base,size)) >= 0) ) { 245 ((j = lmb_overlaps_region(&lmb.reserved,base,size)) >= 0) ) {
280 base = _ALIGN_DOWN(_rsv->region[j].base-size, align); 246 base = _ALIGN_DOWN(lmb.reserved.region[j].base-size, align);
281 } 247 }
282 248
283 if ( (base != 0) && (lmbbase <= base) ) 249 if ( (base != 0) && (lmbbase <= base) )
@@ -287,62 +253,24 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
287 if ( i < 0 ) 253 if ( i < 0 )
288 return 0; 254 return 0;
289 255
290 lmb_add_region(_rsv, base, size); 256 lmb_add_region(&lmb.reserved, base, size);
291 257
292 return base; 258 return base;
293} 259}
294 260
261/* You must call lmb_analyze() before this. */
295unsigned long __init 262unsigned long __init
296lmb_phys_mem_size(void) 263lmb_phys_mem_size(void)
297{ 264{
298 struct lmb *_lmb = &lmb; 265 return lmb.memory.size;
299#ifdef CONFIG_MSCHUNKS
300 return _lmb->memory.size;
301#else
302 struct lmb_region *_mem = &(_lmb->memory);
303 unsigned long total = 0;
304 int i;
305
306 /* add all physical memory to the bootmem map */
307 for (i=0; i < _mem->cnt; i++)
308 total += _mem->region[i].size;
309 return total;
310#endif /* CONFIG_MSCHUNKS */
311} 266}
312 267
313unsigned long __init 268unsigned long __init
314lmb_end_of_DRAM(void) 269lmb_end_of_DRAM(void)
315{ 270{
316 struct lmb *_lmb = &lmb; 271 int idx = lmb.memory.cnt - 1;
317 struct lmb_region *_mem = &(_lmb->memory);
318 int idx = _mem->cnt - 1;
319
320#ifdef CONFIG_MSCHUNKS
321 return (_mem->region[idx].physbase + _mem->region[idx].size);
322#else
323 return (_mem->region[idx].base + _mem->region[idx].size);
324#endif /* CONFIG_MSCHUNKS */
325
326 return 0;
327}
328
329unsigned long __init
330lmb_abs_to_phys(unsigned long aa)
331{
332 unsigned long i, pa = aa;
333 struct lmb *_lmb = &lmb;
334 struct lmb_region *_mem = &(_lmb->memory);
335
336 for (i=0; i < _mem->cnt; i++) {
337 unsigned long lmbbase = _mem->region[i].base;
338 unsigned long lmbsize = _mem->region[i].size;
339 if ( lmb_addrs_overlap(aa,1,lmbbase,lmbsize) ) {
340 pa = _mem->region[i].physbase + (aa - lmbbase);
341 break;
342 }
343 }
344 272
345 return pa; 273 return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
346} 274}
347 275
348/* 276/*
@@ -353,20 +281,19 @@ void __init lmb_enforce_memory_limit(void)
353{ 281{
354 extern unsigned long memory_limit; 282 extern unsigned long memory_limit;
355 unsigned long i, limit; 283 unsigned long i, limit;
356 struct lmb_region *mem = &(lmb.memory);
357 284
358 if (! memory_limit) 285 if (! memory_limit)
359 return; 286 return;
360 287
361 limit = memory_limit; 288 limit = memory_limit;
362 for (i = 0; i < mem->cnt; i++) { 289 for (i = 0; i < lmb.memory.cnt; i++) {
363 if (limit > mem->region[i].size) { 290 if (limit > lmb.memory.region[i].size) {
364 limit -= mem->region[i].size; 291 limit -= lmb.memory.region[i].size;
365 continue; 292 continue;
366 } 293 }
367 294
368 mem->region[i].size = limit; 295 lmb.memory.region[i].size = limit;
369 mem->cnt = i + 1; 296 lmb.memory.cnt = i + 1;
370 break; 297 break;
371 } 298 }
372} 299}
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index 02e96627fa66..9d034ff062b1 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -29,7 +29,7 @@
29#include <asm/iSeries/HvLpConfig.h> 29#include <asm/iSeries/HvLpConfig.h>
30#include <asm/lppaca.h> 30#include <asm/lppaca.h>
31#include <asm/hvcall.h> 31#include <asm/hvcall.h>
32#include <asm/cputable.h> 32#include <asm/firmware.h>
33#include <asm/rtas.h> 33#include <asm/rtas.h>
34#include <asm/system.h> 34#include <asm/system.h>
35#include <asm/time.h> 35#include <asm/time.h>
@@ -377,7 +377,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
377 377
378 partition_active_processors = lparcfg_count_active_processors(); 378 partition_active_processors = lparcfg_count_active_processors();
379 379
380 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { 380 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
381 unsigned long h_entitled, h_unallocated; 381 unsigned long h_entitled, h_unallocated;
382 unsigned long h_aggregation, h_resource; 382 unsigned long h_aggregation, h_resource;
383 unsigned long pool_idle_time, pool_procs; 383 unsigned long pool_idle_time, pool_procs;
@@ -571,7 +571,7 @@ int __init lparcfg_init(void)
571 mode_t mode = S_IRUSR; 571 mode_t mode = S_IRUSR;
572 572
573 /* Allow writing if we have FW_FEATURE_SPLPAR */ 573 /* Allow writing if we have FW_FEATURE_SPLPAR */
574 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { 574 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
575 lparcfg_fops.write = lparcfg_write; 575 lparcfg_fops.write = lparcfg_write;
576 mode |= S_IWUSR; 576 mode |= S_IWUSR;
577 } 577 }
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index a05b50b738e9..474df0a862bf 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -680,6 +680,104 @@ _GLOBAL(kernel_thread)
680 ld r30,-16(r1) 680 ld r30,-16(r1)
681 blr 681 blr
682 682
683/*
684 * disable_kernel_fp()
685 * Disable the FPU.
686 */
687_GLOBAL(disable_kernel_fp)
688 mfmsr r3
689 rldicl r0,r3,(63-MSR_FP_LG),1
690 rldicl r3,r0,(MSR_FP_LG+1),0
691 mtmsrd r3 /* disable use of fpu now */
692 isync
693 blr
694
695/*
696 * giveup_fpu(tsk)
697 * Disable FP for the task given as the argument,
698 * and save the floating-point registers in its thread_struct.
699 * Enables the FPU for use in the kernel on return.
700 */
701_GLOBAL(giveup_fpu)
702 mfmsr r5
703 ori r5,r5,MSR_FP
704 mtmsrd r5 /* enable use of fpu now */
705 isync
706 cmpdi 0,r3,0
707 beqlr- /* if no previous owner, done */
708 addi r3,r3,THREAD /* want THREAD of task */
709 ld r5,PT_REGS(r3)
710 cmpdi 0,r5,0
711 SAVE_32FPRS(0, r3)
712 mffs fr0
713 stfd fr0,THREAD_FPSCR(r3)
714 beq 1f
715 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
716 li r3,MSR_FP|MSR_FE0|MSR_FE1
717 andc r4,r4,r3 /* disable FP for previous task */
718 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
7191:
720#ifndef CONFIG_SMP
721 li r5,0
722 ld r4,last_task_used_math@got(r2)
723 std r5,0(r4)
724#endif /* CONFIG_SMP */
725 blr
726
727#ifdef CONFIG_ALTIVEC
728
729#if 0 /* this has no callers for now */
730/*
731 * disable_kernel_altivec()
732 * Disable the VMX.
733 */
734_GLOBAL(disable_kernel_altivec)
735 mfmsr r3
736 rldicl r0,r3,(63-MSR_VEC_LG),1
737 rldicl r3,r0,(MSR_VEC_LG+1),0
738 mtmsrd r3 /* disable use of VMX now */
739 isync
740 blr
741#endif /* 0 */
742
743/*
744 * giveup_altivec(tsk)
745 * Disable VMX for the task given as the argument,
746 * and save the vector registers in its thread_struct.
747 * Enables the VMX for use in the kernel on return.
748 */
749_GLOBAL(giveup_altivec)
750 mfmsr r5
751 oris r5,r5,MSR_VEC@h
752 mtmsrd r5 /* enable use of VMX now */
753 isync
754 cmpdi 0,r3,0
755 beqlr- /* if no previous owner, done */
756 addi r3,r3,THREAD /* want THREAD of task */
757 ld r5,PT_REGS(r3)
758 cmpdi 0,r5,0
759 SAVE_32VRS(0,r4,r3)
760 mfvscr vr0
761 li r4,THREAD_VSCR
762 stvx vr0,r4,r3
763 beq 1f
764 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
765 lis r3,MSR_VEC@h
766 andc r4,r4,r3 /* disable FP for previous task */
767 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
7681:
769#ifndef CONFIG_SMP
770 li r5,0
771 ld r4,last_task_used_altivec@got(r2)
772 std r5,0(r4)
773#endif /* CONFIG_SMP */
774 blr
775
776#endif /* CONFIG_ALTIVEC */
777
778_GLOBAL(__setup_cpu_power3)
779 blr
780
683/* kexec_wait(phys_cpu) 781/* kexec_wait(phys_cpu)
684 * 782 *
685 * wait for the flag to change, indicating this kernel is going away but 783 * wait for the flag to change, indicating this kernel is going away but
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 69130522a87e..9d5e1e7fc389 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -45,6 +45,7 @@
45#include <asm/plpar_wrappers.h> 45#include <asm/plpar_wrappers.h>
46#include <asm/pSeries_reconfig.h> 46#include <asm/pSeries_reconfig.h>
47#include <asm/systemcfg.h> 47#include <asm/systemcfg.h>
48#include <asm/firmware.h>
48#include "pci.h" 49#include "pci.h"
49 50
50#define DBG(fmt...) 51#define DBG(fmt...)
@@ -546,7 +547,7 @@ void iommu_init_early_pSeries(void)
546 } 547 }
547 548
548 if (systemcfg->platform & PLATFORM_LPAR) { 549 if (systemcfg->platform & PLATFORM_LPAR) {
549 if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) { 550 if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
550 ppc_md.tce_build = tce_buildmulti_pSeriesLP; 551 ppc_md.tce_build = tce_buildmulti_pSeriesLP;
551 ppc_md.tce_free = tce_freemulti_pSeriesLP; 552 ppc_md.tce_free = tce_freemulti_pSeriesLP;
552 } else { 553 } else {
diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
index 74dd144dcce8..0a3ddc9227c5 100644
--- a/arch/ppc64/kernel/pSeries_lpar.c
+++ b/arch/ppc64/kernel/pSeries_lpar.c
@@ -52,7 +52,6 @@ EXPORT_SYMBOL(plpar_hcall_4out);
52EXPORT_SYMBOL(plpar_hcall_norets); 52EXPORT_SYMBOL(plpar_hcall_norets);
53EXPORT_SYMBOL(plpar_hcall_8arg_2ret); 53EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
54 54
55extern void fw_feature_init(void);
56extern void pSeries_find_serial_port(void); 55extern void pSeries_find_serial_port(void);
57 56
58 57
@@ -279,7 +278,6 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
279 unsigned long va, unsigned long prpn, 278 unsigned long va, unsigned long prpn,
280 unsigned long vflags, unsigned long rflags) 279 unsigned long vflags, unsigned long rflags)
281{ 280{
282 unsigned long arpn = physRpn_to_absRpn(prpn);
283 unsigned long lpar_rc; 281 unsigned long lpar_rc;
284 unsigned long flags; 282 unsigned long flags;
285 unsigned long slot; 283 unsigned long slot;
@@ -290,7 +288,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
290 if (vflags & HPTE_V_LARGE) 288 if (vflags & HPTE_V_LARGE)
291 hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT); 289 hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT);
292 290
293 hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags; 291 hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
294 292
295 /* Now fill in the actual HPTE */ 293 /* Now fill in the actual HPTE */
296 /* Set CEC cookie to 0 */ 294 /* Set CEC cookie to 0 */
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 5bec956e44a0..f0f0630cf07c 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -60,7 +60,8 @@
60#include <asm/nvram.h> 60#include <asm/nvram.h>
61#include <asm/plpar_wrappers.h> 61#include <asm/plpar_wrappers.h>
62#include <asm/xics.h> 62#include <asm/xics.h>
63#include <asm/cputable.h> 63#include <asm/firmware.h>
64#include <asm/pmc.h>
64 65
65#include "i8259.h" 66#include "i8259.h"
66#include "mpic.h" 67#include "mpic.h"
@@ -187,6 +188,21 @@ static void __init pSeries_setup_mpic(void)
187 " MPIC "); 188 " MPIC ");
188} 189}
189 190
191static void pseries_lpar_enable_pmcs(void)
192{
193 unsigned long set, reset;
194
195 power4_enable_pmcs();
196
197 set = 1UL << 63;
198 reset = 0;
199 plpar_hcall_norets(H_PERFMON, set, reset);
200
201 /* instruct hypervisor to maintain PMCs */
202 if (firmware_has_feature(FW_FEATURE_SPLPAR))
203 get_paca()->lppaca.pmcregs_in_use = 1;
204}
205
190static void __init pSeries_setup_arch(void) 206static void __init pSeries_setup_arch(void)
191{ 207{
192 /* Fixup ppc_md depending on the type of interrupt controller */ 208 /* Fixup ppc_md depending on the type of interrupt controller */
@@ -231,11 +247,9 @@ static void __init pSeries_setup_arch(void)
231 247
232 pSeries_nvram_init(); 248 pSeries_nvram_init();
233 249
234 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
235 vpa_init(boot_cpuid);
236
237 /* Choose an idle loop */ 250 /* Choose an idle loop */
238 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { 251 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
252 vpa_init(boot_cpuid);
239 if (get_paca()->lppaca.shared_proc) { 253 if (get_paca()->lppaca.shared_proc) {
240 printk(KERN_INFO "Using shared processor idle loop\n"); 254 printk(KERN_INFO "Using shared processor idle loop\n");
241 ppc_md.idle_loop = pseries_shared_idle; 255 ppc_md.idle_loop = pseries_shared_idle;
@@ -247,6 +261,11 @@ static void __init pSeries_setup_arch(void)
247 printk(KERN_INFO "Using default idle loop\n"); 261 printk(KERN_INFO "Using default idle loop\n");
248 ppc_md.idle_loop = default_idle; 262 ppc_md.idle_loop = default_idle;
249 } 263 }
264
265 if (systemcfg->platform & PLATFORM_LPAR)
266 ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
267 else
268 ppc_md.enable_pmcs = power4_enable_pmcs;
250} 269}
251 270
252static int __init pSeries_init_panel(void) 271static int __init pSeries_init_panel(void)
@@ -260,11 +279,11 @@ static int __init pSeries_init_panel(void)
260arch_initcall(pSeries_init_panel); 279arch_initcall(pSeries_init_panel);
261 280
262 281
263/* Build up the firmware_features bitmask field 282/* Build up the ppc64_firmware_features bitmask field
264 * using contents of device-tree/ibm,hypertas-functions. 283 * using contents of device-tree/ibm,hypertas-functions.
265 * Ultimately this functionality may be moved into prom.c prom_init(). 284 * Ultimately this functionality may be moved into prom.c prom_init().
266 */ 285 */
267void __init fw_feature_init(void) 286static void __init fw_feature_init(void)
268{ 287{
269 struct device_node * dn; 288 struct device_node * dn;
270 char * hypertas; 289 char * hypertas;
@@ -272,7 +291,7 @@ void __init fw_feature_init(void)
272 291
273 DBG(" -> fw_feature_init()\n"); 292 DBG(" -> fw_feature_init()\n");
274 293
275 cur_cpu_spec->firmware_features = 0; 294 ppc64_firmware_features = 0;
276 dn = of_find_node_by_path("/rtas"); 295 dn = of_find_node_by_path("/rtas");
277 if (dn == NULL) { 296 if (dn == NULL) {
278 printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n"); 297 printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
@@ -288,7 +307,7 @@ void __init fw_feature_init(void)
288 if ((firmware_features_table[i].name) && 307 if ((firmware_features_table[i].name) &&
289 (strcmp(firmware_features_table[i].name,hypertas))==0) { 308 (strcmp(firmware_features_table[i].name,hypertas))==0) {
290 /* we have a match */ 309 /* we have a match */
291 cur_cpu_spec->firmware_features |= 310 ppc64_firmware_features |=
292 (firmware_features_table[i].val); 311 (firmware_features_table[i].val);
293 break; 312 break;
294 } 313 }
@@ -302,7 +321,7 @@ void __init fw_feature_init(void)
302 of_node_put(dn); 321 of_node_put(dn);
303 no_rtas: 322 no_rtas:
304 printk(KERN_INFO "firmware_features = 0x%lx\n", 323 printk(KERN_INFO "firmware_features = 0x%lx\n",
305 cur_cpu_spec->firmware_features); 324 ppc64_firmware_features);
306 325
307 DBG(" <- fw_feature_init()\n"); 326 DBG(" <- fw_feature_init()\n");
308} 327}
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index 62c55a123560..79c7f3223665 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -41,6 +41,7 @@
41#include <asm/machdep.h> 41#include <asm/machdep.h>
42#include <asm/xics.h> 42#include <asm/xics.h>
43#include <asm/cputable.h> 43#include <asm/cputable.h>
44#include <asm/firmware.h>
44#include <asm/system.h> 45#include <asm/system.h>
45#include <asm/rtas.h> 46#include <asm/rtas.h>
46#include <asm/plpar_wrappers.h> 47#include <asm/plpar_wrappers.h>
@@ -326,7 +327,7 @@ static void __devinit smp_xics_setup_cpu(int cpu)
326 if (cpu != boot_cpuid) 327 if (cpu != boot_cpuid)
327 xics_setup_cpu(); 328 xics_setup_cpu();
328 329
329 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) 330 if (firmware_has_feature(FW_FEATURE_SPLPAR))
330 vpa_init(cpu); 331 vpa_init(cpu);
331 332
332 cpu_clear(cpu, of_spin_map); 333 cpu_clear(cpu, of_spin_map);
diff --git a/arch/ppc64/kernel/pSeries_vio.c b/arch/ppc64/kernel/pSeries_vio.c
new file mode 100644
index 000000000000..338f9e1bdc09
--- /dev/null
+++ b/arch/ppc64/kernel/pSeries_vio.c
@@ -0,0 +1,266 @@
1/*
2 * IBM PowerPC pSeries Virtual I/O Infrastructure Support.
3 *
4 * Copyright (c) 2003-2005 IBM Corp.
5 * Dave Engebretsen engebret@us.ibm.com
6 * Santiago Leon santil@us.ibm.com
7 * Hollis Blanchard <hollisb@us.ibm.com>
8 * Stephen Rothwell
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/mm.h>
19#include <linux/kobject.h>
20#include <asm/iommu.h>
21#include <asm/dma.h>
22#include <asm/vio.h>
23#include <asm/hvcall.h>
24
25extern struct subsystem devices_subsys; /* needed for vio_find_name() */
26
27static void probe_bus_pseries(void)
28{
29 struct device_node *node_vroot, *of_node;
30
31 node_vroot = find_devices("vdevice");
32 if ((node_vroot == NULL) || (node_vroot->child == NULL))
33 /* this machine doesn't do virtual IO, and that's ok */
34 return;
35
36 /*
37 * Create struct vio_devices for each virtual device in the device tree.
38 * Drivers will associate with them later.
39 */
40 for (of_node = node_vroot->child; of_node != NULL;
41 of_node = of_node->sibling) {
42 printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
43 vio_register_device_node(of_node);
44 }
45}
46
47/**
48 * vio_match_device_pseries: - Tell if a pSeries VIO device matches a
49 * vio_device_id
50 */
51static int vio_match_device_pseries(const struct vio_device_id *id,
52 const struct vio_dev *dev)
53{
54 return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&
55 device_is_compatible(dev->dev.platform_data, id->compat);
56}
57
58static void vio_release_device_pseries(struct device *dev)
59{
60 /* XXX free TCE table */
61 of_node_put(dev->platform_data);
62}
63
64static ssize_t viodev_show_devspec(struct device *dev,
65 struct device_attribute *attr, char *buf)
66{
67 struct device_node *of_node = dev->platform_data;
68
69 return sprintf(buf, "%s\n", of_node->full_name);
70}
71DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
72
73static void vio_unregister_device_pseries(struct vio_dev *viodev)
74{
75 device_remove_file(&viodev->dev, &dev_attr_devspec);
76}
77
78/**
79 * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
80 */
81static int __init vio_bus_init_pseries(void)
82{
83 int err;
84
85 err = vio_bus_init(vio_match_device_pseries,
86 vio_unregister_device_pseries,
87 vio_release_device_pseries);
88 if (err == 0)
89 probe_bus_pseries();
90 return err;
91}
92
93__initcall(vio_bus_init_pseries);
94
95/**
96 * vio_build_iommu_table: - gets the dma information from OF and
97 * builds the TCE tree.
98 * @dev: the virtual device.
99 *
100 * Returns a pointer to the built tce tree, or NULL if it can't
101 * find property.
102*/
103static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
104{
105 unsigned int *dma_window;
106 struct iommu_table *newTceTable;
107 unsigned long offset;
108 int dma_window_property_size;
109
110 dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
111 if(!dma_window) {
112 return NULL;
113 }
114
115 newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
116
117 /* There should be some code to extract the phys-encoded offset
118 using prom_n_addr_cells(). However, according to a comment
119 on earlier versions, it's always zero, so we don't bother */
120 offset = dma_window[1] >> PAGE_SHIFT;
121
122 /* TCE table size - measured in tce entries */
123 newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
124 /* offset for VIO should always be 0 */
125 newTceTable->it_offset = offset;
126 newTceTable->it_busno = 0;
127 newTceTable->it_index = (unsigned long)dma_window[0];
128 newTceTable->it_type = TCE_VB;
129
130 return iommu_init_table(newTceTable);
131}
132
133/**
134 * vio_register_device_node: - Register a new vio device.
135 * @of_node: The OF node for this device.
136 *
137 * Creates and initializes a vio_dev structure from the data in
138 * of_node (dev.platform_data) and adds it to the list of virtual devices.
139 * Returns a pointer to the created vio_dev or NULL if node has
140 * NULL device_type or compatible fields.
141 */
142struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
143{
144 struct vio_dev *viodev;
145 unsigned int *unit_address;
146 unsigned int *irq_p;
147
148 /* we need the 'device_type' property, in order to match with drivers */
149 if ((NULL == of_node->type)) {
150 printk(KERN_WARNING
151 "%s: node %s missing 'device_type'\n", __FUNCTION__,
152 of_node->name ? of_node->name : "<unknown>");
153 return NULL;
154 }
155
156 unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
157 if (!unit_address) {
158 printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
159 of_node->name ? of_node->name : "<unknown>");
160 return NULL;
161 }
162
163 /* allocate a vio_dev for this node */
164 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
165 if (!viodev) {
166 return NULL;
167 }
168 memset(viodev, 0, sizeof(struct vio_dev));
169
170 viodev->dev.platform_data = of_node_get(of_node);
171
172 viodev->irq = NO_IRQ;
173 irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
174 if (irq_p) {
175 int virq = virt_irq_create_mapping(*irq_p);
176 if (virq == NO_IRQ) {
177 printk(KERN_ERR "Unable to allocate interrupt "
178 "number for %s\n", of_node->full_name);
179 } else
180 viodev->irq = irq_offset_up(virq);
181 }
182
183 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
184
185 /* register with generic device framework */
186 if (vio_register_device_common(viodev, of_node->name, of_node->type,
187 *unit_address, vio_build_iommu_table(viodev))
188 == NULL) {
189 /* XXX free TCE table */
190 kfree(viodev);
191 return NULL;
192 }
193 device_create_file(&viodev->dev, &dev_attr_devspec);
194
195 return viodev;
196}
197EXPORT_SYMBOL(vio_register_device_node);
198
199/**
200 * vio_get_attribute: - get attribute for virtual device
201 * @vdev: The vio device to get property.
202 * @which: The property/attribute to be extracted.
203 * @length: Pointer to length of returned data size (unused if NULL).
204 *
205 * Calls prom.c's get_property() to return the value of the
206 * attribute specified by the preprocessor constant @which
207*/
208const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
209{
210 return get_property(vdev->dev.platform_data, (char*)which, length);
211}
212EXPORT_SYMBOL(vio_get_attribute);
213
214/* vio_find_name() - internal because only vio.c knows how we formatted the
215 * kobject name
216 * XXX once vio_bus_type.devices is actually used as a kset in
217 * drivers/base/bus.c, this function should be removed in favor of
218 * "device_find(kobj_name, &vio_bus_type)"
219 */
220static struct vio_dev *vio_find_name(const char *kobj_name)
221{
222 struct kobject *found;
223
224 found = kset_find_obj(&devices_subsys.kset, kobj_name);
225 if (!found)
226 return NULL;
227
228 return to_vio_dev(container_of(found, struct device, kobj));
229}
230
231/**
232 * vio_find_node - find an already-registered vio_dev
233 * @vnode: device_node of the virtual device we're looking for
234 */
235struct vio_dev *vio_find_node(struct device_node *vnode)
236{
237 uint32_t *unit_address;
238 char kobj_name[BUS_ID_SIZE];
239
240 /* construct the kobject name from the device node */
241 unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
242 if (!unit_address)
243 return NULL;
244 snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
245
246 return vio_find_name(kobj_name);
247}
248EXPORT_SYMBOL(vio_find_node);
249
250int vio_enable_interrupts(struct vio_dev *dev)
251{
252 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
253 if (rc != H_Success)
254 printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
255 return rc;
256}
257EXPORT_SYMBOL(vio_enable_interrupts);
258
259int vio_disable_interrupts(struct vio_dev *dev)
260{
261 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
262 if (rc != H_Success)
263 printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
264 return rc;
265}
266EXPORT_SYMBOL(vio_disable_interrupts);
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
index 6316188737b6..6182a2cd90a5 100644
--- a/arch/ppc64/kernel/pacaData.c
+++ b/arch/ppc64/kernel/pacaData.c
@@ -78,7 +78,7 @@ extern unsigned long __toc_start;
78 78
79#define BOOTCPU_PACA_INIT(number) \ 79#define BOOTCPU_PACA_INIT(number) \
80{ \ 80{ \
81 PACA_INIT_COMMON(number, 1, 0, STAB0_VIRT_ADDR) \ 81 PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \
82 PACA_INIT_ISERIES(number) \ 82 PACA_INIT_ISERIES(number) \
83} 83}
84 84
@@ -90,7 +90,7 @@ extern unsigned long __toc_start;
90 90
91#define BOOTCPU_PACA_INIT(number) \ 91#define BOOTCPU_PACA_INIT(number) \
92{ \ 92{ \
93 PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR) \ 93 PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \
94} 94}
95#endif 95#endif
96 96
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index e40877fa67cd..8ff86a766cdf 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -71,6 +71,7 @@
71#include <asm/of_device.h> 71#include <asm/of_device.h>
72#include <asm/lmb.h> 72#include <asm/lmb.h>
73#include <asm/smu.h> 73#include <asm/smu.h>
74#include <asm/pmc.h>
74 75
75#include "pmac.h" 76#include "pmac.h"
76#include "mpic.h" 77#include "mpic.h"
@@ -511,4 +512,5 @@ struct machdep_calls __initdata pmac_md = {
511 .progress = pmac_progress, 512 .progress = pmac_progress,
512 .check_legacy_ioport = pmac_check_legacy_ioport, 513 .check_legacy_ioport = pmac_check_legacy_ioport,
513 .idle_loop = native_idle, 514 .idle_loop = native_idle,
515 .enable_pmcs = power4_enable_pmcs,
514}; 516};
diff --git a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c
index 67be773f9c00..cdfec7438d01 100644
--- a/arch/ppc64/kernel/pmc.c
+++ b/arch/ppc64/kernel/pmc.c
@@ -65,3 +65,24 @@ void release_pmc_hardware(void)
65 spin_unlock(&pmc_owner_lock); 65 spin_unlock(&pmc_owner_lock);
66} 66}
67EXPORT_SYMBOL_GPL(release_pmc_hardware); 67EXPORT_SYMBOL_GPL(release_pmc_hardware);
68
69void power4_enable_pmcs(void)
70{
71 unsigned long hid0;
72
73 hid0 = mfspr(HID0);
74 hid0 |= 1UL << (63 - 20);
75
76 /* POWER4 requires the following sequence */
77 asm volatile(
78 "sync\n"
79 "mtspr %1, %0\n"
80 "mfspr %0, %1\n"
81 "mfspr %0, %1\n"
82 "mfspr %0, %1\n"
83 "mfspr %0, %1\n"
84 "mfspr %0, %1\n"
85 "mfspr %0, %1\n"
86 "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
87 "memory");
88}
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index f7cae05e40fb..7a7e027653ad 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -50,6 +50,7 @@
50#include <asm/machdep.h> 50#include <asm/machdep.h>
51#include <asm/iSeries/HvCallHpt.h> 51#include <asm/iSeries/HvCallHpt.h>
52#include <asm/cputable.h> 52#include <asm/cputable.h>
53#include <asm/firmware.h>
53#include <asm/sections.h> 54#include <asm/sections.h>
54#include <asm/tlbflush.h> 55#include <asm/tlbflush.h>
55#include <asm/time.h> 56#include <asm/time.h>
@@ -202,11 +203,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
202 new_thread = &new->thread; 203 new_thread = &new->thread;
203 old_thread = &current->thread; 204 old_thread = &current->thread;
204 205
205/* Collect purr utilization data per process and per processor wise */ 206 /* Collect purr utilization data per process and per processor
206/* purr is nothing but processor time base */ 207 * wise purr is nothing but processor time base
207 208 */
208#if defined(CONFIG_PPC_PSERIES) 209 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
209 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
210 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); 210 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
211 long unsigned start_tb, current_tb; 211 long unsigned start_tb, current_tb;
212 start_tb = old_thread->start_tb; 212 start_tb = old_thread->start_tb;
@@ -214,8 +214,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
214 old_thread->accum_tb += (current_tb - start_tb); 214 old_thread->accum_tb += (current_tb - start_tb);
215 new_thread->start_tb = current_tb; 215 new_thread->start_tb = current_tb;
216 } 216 }
217#endif
218
219 217
220 local_irq_save(flags); 218 local_irq_save(flags);
221 last = _switch(old_thread, new_thread); 219 last = _switch(old_thread, new_thread);
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 5aca01ddd81f..b21848826791 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -625,8 +625,8 @@ void __init finish_device_tree(void)
625 625
626static inline char *find_flat_dt_string(u32 offset) 626static inline char *find_flat_dt_string(u32 offset)
627{ 627{
628 return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings 628 return ((char *)initial_boot_params) +
629 + offset; 629 initial_boot_params->off_dt_strings + offset;
630} 630}
631 631
632/** 632/**
@@ -635,26 +635,33 @@ static inline char *find_flat_dt_string(u32 offset)
635 * unflatten the tree 635 * unflatten the tree
636 */ 636 */
637static int __init scan_flat_dt(int (*it)(unsigned long node, 637static int __init scan_flat_dt(int (*it)(unsigned long node,
638 const char *full_path, void *data), 638 const char *uname, int depth,
639 void *data),
639 void *data) 640 void *data)
640{ 641{
641 unsigned long p = ((unsigned long)initial_boot_params) + 642 unsigned long p = ((unsigned long)initial_boot_params) +
642 initial_boot_params->off_dt_struct; 643 initial_boot_params->off_dt_struct;
643 int rc = 0; 644 int rc = 0;
645 int depth = -1;
644 646
645 do { 647 do {
646 u32 tag = *((u32 *)p); 648 u32 tag = *((u32 *)p);
647 char *pathp; 649 char *pathp;
648 650
649 p += 4; 651 p += 4;
650 if (tag == OF_DT_END_NODE) 652 if (tag == OF_DT_END_NODE) {
653 depth --;
654 continue;
655 }
656 if (tag == OF_DT_NOP)
651 continue; 657 continue;
652 if (tag == OF_DT_END) 658 if (tag == OF_DT_END)
653 break; 659 break;
654 if (tag == OF_DT_PROP) { 660 if (tag == OF_DT_PROP) {
655 u32 sz = *((u32 *)p); 661 u32 sz = *((u32 *)p);
656 p += 8; 662 p += 8;
657 p = _ALIGN(p, sz >= 8 ? 8 : 4); 663 if (initial_boot_params->version < 0x10)
664 p = _ALIGN(p, sz >= 8 ? 8 : 4);
658 p += sz; 665 p += sz;
659 p = _ALIGN(p, 4); 666 p = _ALIGN(p, 4);
660 continue; 667 continue;
@@ -664,9 +671,18 @@ static int __init scan_flat_dt(int (*it)(unsigned long node,
664 " device tree !\n", tag); 671 " device tree !\n", tag);
665 return -EINVAL; 672 return -EINVAL;
666 } 673 }
674 depth++;
667 pathp = (char *)p; 675 pathp = (char *)p;
668 p = _ALIGN(p + strlen(pathp) + 1, 4); 676 p = _ALIGN(p + strlen(pathp) + 1, 4);
669 rc = it(p, pathp, data); 677 if ((*pathp) == '/') {
678 char *lp, *np;
679 for (lp = NULL, np = pathp; *np; np++)
680 if ((*np) == '/')
681 lp = np+1;
682 if (lp != NULL)
683 pathp = lp;
684 }
685 rc = it(p, pathp, depth, data);
670 if (rc != 0) 686 if (rc != 0)
671 break; 687 break;
672 } while(1); 688 } while(1);
@@ -689,17 +705,21 @@ static void* __init get_flat_dt_prop(unsigned long node, const char *name,
689 const char *nstr; 705 const char *nstr;
690 706
691 p += 4; 707 p += 4;
708 if (tag == OF_DT_NOP)
709 continue;
692 if (tag != OF_DT_PROP) 710 if (tag != OF_DT_PROP)
693 return NULL; 711 return NULL;
694 712
695 sz = *((u32 *)p); 713 sz = *((u32 *)p);
696 noff = *((u32 *)(p + 4)); 714 noff = *((u32 *)(p + 4));
697 p += 8; 715 p += 8;
698 p = _ALIGN(p, sz >= 8 ? 8 : 4); 716 if (initial_boot_params->version < 0x10)
717 p = _ALIGN(p, sz >= 8 ? 8 : 4);
699 718
700 nstr = find_flat_dt_string(noff); 719 nstr = find_flat_dt_string(noff);
701 if (nstr == NULL) { 720 if (nstr == NULL) {
702 printk(KERN_WARNING "Can't find property index name !\n"); 721 printk(KERN_WARNING "Can't find property index"
722 " name !\n");
703 return NULL; 723 return NULL;
704 } 724 }
705 if (strcmp(name, nstr) == 0) { 725 if (strcmp(name, nstr) == 0) {
@@ -713,7 +733,7 @@ static void* __init get_flat_dt_prop(unsigned long node, const char *name,
713} 733}
714 734
715static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, 735static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
716 unsigned long align) 736 unsigned long align)
717{ 737{
718 void *res; 738 void *res;
719 739
@@ -727,13 +747,16 @@ static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
727static unsigned long __init unflatten_dt_node(unsigned long mem, 747static unsigned long __init unflatten_dt_node(unsigned long mem,
728 unsigned long *p, 748 unsigned long *p,
729 struct device_node *dad, 749 struct device_node *dad,
730 struct device_node ***allnextpp) 750 struct device_node ***allnextpp,
751 unsigned long fpsize)
731{ 752{
732 struct device_node *np; 753 struct device_node *np;
733 struct property *pp, **prev_pp = NULL; 754 struct property *pp, **prev_pp = NULL;
734 char *pathp; 755 char *pathp;
735 u32 tag; 756 u32 tag;
736 unsigned int l; 757 unsigned int l, allocl;
758 int has_name = 0;
759 int new_format = 0;
737 760
738 tag = *((u32 *)(*p)); 761 tag = *((u32 *)(*p));
739 if (tag != OF_DT_BEGIN_NODE) { 762 if (tag != OF_DT_BEGIN_NODE) {
@@ -742,21 +765,62 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
742 } 765 }
743 *p += 4; 766 *p += 4;
744 pathp = (char *)*p; 767 pathp = (char *)*p;
745 l = strlen(pathp) + 1; 768 l = allocl = strlen(pathp) + 1;
746 *p = _ALIGN(*p + l, 4); 769 *p = _ALIGN(*p + l, 4);
747 770
748 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l, 771 /* version 0x10 has a more compact unit name here instead of the full
772 * path. we accumulate the full path size using "fpsize", we'll rebuild
773 * it later. We detect this because the first character of the name is
774 * not '/'.
775 */
776 if ((*pathp) != '/') {
777 new_format = 1;
778 if (fpsize == 0) {
779 /* root node: special case. fpsize accounts for path
780 * plus terminating zero. root node only has '/', so
781 * fpsize should be 2, but we want to avoid the first
782 * level nodes to have two '/' so we use fpsize 1 here
783 */
784 fpsize = 1;
785 allocl = 2;
786 } else {
787 /* account for '/' and path size minus terminal 0
788 * already in 'l'
789 */
790 fpsize += l;
791 allocl = fpsize;
792 }
793 }
794
795
796 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
749 __alignof__(struct device_node)); 797 __alignof__(struct device_node));
750 if (allnextpp) { 798 if (allnextpp) {
751 memset(np, 0, sizeof(*np)); 799 memset(np, 0, sizeof(*np));
752 np->full_name = ((char*)np) + sizeof(struct device_node); 800 np->full_name = ((char*)np) + sizeof(struct device_node);
753 memcpy(np->full_name, pathp, l); 801 if (new_format) {
802 char *p = np->full_name;
803 /* rebuild full path for new format */
804 if (dad && dad->parent) {
805 strcpy(p, dad->full_name);
806#ifdef DEBUG
807 if ((strlen(p) + l + 1) != allocl) {
808 DBG("%s: p: %d, l: %d, a: %d\n",
809 pathp, strlen(p), l, allocl);
810 }
811#endif
812 p += strlen(p);
813 }
814 *(p++) = '/';
815 memcpy(p, pathp, l);
816 } else
817 memcpy(np->full_name, pathp, l);
754 prev_pp = &np->properties; 818 prev_pp = &np->properties;
755 **allnextpp = np; 819 **allnextpp = np;
756 *allnextpp = &np->allnext; 820 *allnextpp = &np->allnext;
757 if (dad != NULL) { 821 if (dad != NULL) {
758 np->parent = dad; 822 np->parent = dad;
759 /* we temporarily use the `next' field as `last_child'. */ 823 /* we temporarily use the next field as `last_child'*/
760 if (dad->next == 0) 824 if (dad->next == 0)
761 dad->child = np; 825 dad->child = np;
762 else 826 else
@@ -770,18 +834,26 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
770 char *pname; 834 char *pname;
771 835
772 tag = *((u32 *)(*p)); 836 tag = *((u32 *)(*p));
837 if (tag == OF_DT_NOP) {
838 *p += 4;
839 continue;
840 }
773 if (tag != OF_DT_PROP) 841 if (tag != OF_DT_PROP)
774 break; 842 break;
775 *p += 4; 843 *p += 4;
776 sz = *((u32 *)(*p)); 844 sz = *((u32 *)(*p));
777 noff = *((u32 *)((*p) + 4)); 845 noff = *((u32 *)((*p) + 4));
778 *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4); 846 *p += 8;
847 if (initial_boot_params->version < 0x10)
848 *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
779 849
780 pname = find_flat_dt_string(noff); 850 pname = find_flat_dt_string(noff);
781 if (pname == NULL) { 851 if (pname == NULL) {
782 printk("Can't find property name in list !\n"); 852 printk("Can't find property name in list !\n");
783 break; 853 break;
784 } 854 }
855 if (strcmp(pname, "name") == 0)
856 has_name = 1;
785 l = strlen(pname) + 1; 857 l = strlen(pname) + 1;
786 pp = unflatten_dt_alloc(&mem, sizeof(struct property), 858 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
787 __alignof__(struct property)); 859 __alignof__(struct property));
@@ -801,6 +873,36 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
801 } 873 }
802 *p = _ALIGN((*p) + sz, 4); 874 *p = _ALIGN((*p) + sz, 4);
803 } 875 }
876 /* with version 0x10 we may not have the name property, recreate
877 * it here from the unit name if absent
878 */
879 if (!has_name) {
880 char *p = pathp, *ps = pathp, *pa = NULL;
881 int sz;
882
883 while (*p) {
884 if ((*p) == '@')
885 pa = p;
886 if ((*p) == '/')
887 ps = p + 1;
888 p++;
889 }
890 if (pa < ps)
891 pa = p;
892 sz = (pa - ps) + 1;
893 pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
894 __alignof__(struct property));
895 if (allnextpp) {
896 pp->name = "name";
897 pp->length = sz;
898 pp->value = (unsigned char *)(pp + 1);
899 *prev_pp = pp;
900 prev_pp = &pp->next;
901 memcpy(pp->value, ps, sz - 1);
902 ((char *)pp->value)[sz - 1] = 0;
903 DBG("fixed up name for %s -> %s\n", pathp, pp->value);
904 }
905 }
804 if (allnextpp) { 906 if (allnextpp) {
805 *prev_pp = NULL; 907 *prev_pp = NULL;
806 np->name = get_property(np, "name", NULL); 908 np->name = get_property(np, "name", NULL);
@@ -812,11 +914,11 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
812 np->type = "<NULL>"; 914 np->type = "<NULL>";
813 } 915 }
814 while (tag == OF_DT_BEGIN_NODE) { 916 while (tag == OF_DT_BEGIN_NODE) {
815 mem = unflatten_dt_node(mem, p, np, allnextpp); 917 mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
816 tag = *((u32 *)(*p)); 918 tag = *((u32 *)(*p));
817 } 919 }
818 if (tag != OF_DT_END_NODE) { 920 if (tag != OF_DT_END_NODE) {
819 printk("Weird tag at start of node: %x\n", tag); 921 printk("Weird tag at end of node: %x\n", tag);
820 return mem; 922 return mem;
821 } 923 }
822 *p += 4; 924 *p += 4;
@@ -842,21 +944,32 @@ void __init unflatten_device_tree(void)
842 /* First pass, scan for size */ 944 /* First pass, scan for size */
843 start = ((unsigned long)initial_boot_params) + 945 start = ((unsigned long)initial_boot_params) +
844 initial_boot_params->off_dt_struct; 946 initial_boot_params->off_dt_struct;
845 size = unflatten_dt_node(0, &start, NULL, NULL); 947 size = unflatten_dt_node(0, &start, NULL, NULL, 0);
948 size = (size | 3) + 1;
846 949
847 DBG(" size is %lx, allocating...\n", size); 950 DBG(" size is %lx, allocating...\n", size);
848 951
849 /* Allocate memory for the expanded device tree */ 952 /* Allocate memory for the expanded device tree */
850 mem = (unsigned long)abs_to_virt(lmb_alloc(size, 953 mem = lmb_alloc(size + 4, __alignof__(struct device_node));
851 __alignof__(struct device_node))); 954 if (!mem) {
955 DBG("Couldn't allocate memory with lmb_alloc()!\n");
956 panic("Couldn't allocate memory with lmb_alloc()!\n");
957 }
958 mem = (unsigned long)abs_to_virt(mem);
959
960 ((u32 *)mem)[size / 4] = 0xdeadbeef;
961
852 DBG(" unflattening...\n", mem); 962 DBG(" unflattening...\n", mem);
853 963
854 /* Second pass, do actual unflattening */ 964 /* Second pass, do actual unflattening */
855 start = ((unsigned long)initial_boot_params) + 965 start = ((unsigned long)initial_boot_params) +
856 initial_boot_params->off_dt_struct; 966 initial_boot_params->off_dt_struct;
857 unflatten_dt_node(mem, &start, NULL, &allnextp); 967 unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
858 if (*((u32 *)start) != OF_DT_END) 968 if (*((u32 *)start) != OF_DT_END)
859 printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start)); 969 printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start));
970 if (((u32 *)mem)[size / 4] != 0xdeadbeef)
971 printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
972 ((u32 *)mem)[size / 4] );
860 *allnextp = NULL; 973 *allnextp = NULL;
861 974
862 /* Get pointer to OF "/chosen" node for use everywhere */ 975 /* Get pointer to OF "/chosen" node for use everywhere */
@@ -880,7 +993,7 @@ void __init unflatten_device_tree(void)
880 993
881 994
882static int __init early_init_dt_scan_cpus(unsigned long node, 995static int __init early_init_dt_scan_cpus(unsigned long node,
883 const char *full_path, void *data) 996 const char *uname, int depth, void *data)
884{ 997{
885 char *type = get_flat_dt_prop(node, "device_type", NULL); 998 char *type = get_flat_dt_prop(node, "device_type", NULL);
886 u32 *prop; 999 u32 *prop;
@@ -947,13 +1060,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
947} 1060}
948 1061
949static int __init early_init_dt_scan_chosen(unsigned long node, 1062static int __init early_init_dt_scan_chosen(unsigned long node,
950 const char *full_path, void *data) 1063 const char *uname, int depth, void *data)
951{ 1064{
952 u32 *prop; 1065 u32 *prop;
953 u64 *prop64; 1066 u64 *prop64;
954 extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end; 1067 extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
955 1068
956 if (strcmp(full_path, "/chosen") != 0) 1069 DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
1070
1071 if (depth != 1 || strcmp(uname, "chosen") != 0)
957 return 0; 1072 return 0;
958 1073
959 /* get platform type */ 1074 /* get platform type */
@@ -1003,18 +1118,20 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1003} 1118}
1004 1119
1005static int __init early_init_dt_scan_root(unsigned long node, 1120static int __init early_init_dt_scan_root(unsigned long node,
1006 const char *full_path, void *data) 1121 const char *uname, int depth, void *data)
1007{ 1122{
1008 u32 *prop; 1123 u32 *prop;
1009 1124
1010 if (strcmp(full_path, "/") != 0) 1125 if (depth != 0)
1011 return 0; 1126 return 0;
1012 1127
1013 prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL); 1128 prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);
1014 dt_root_size_cells = (prop == NULL) ? 1 : *prop; 1129 dt_root_size_cells = (prop == NULL) ? 1 : *prop;
1015 1130 DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
1131
1016 prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL); 1132 prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);
1017 dt_root_addr_cells = (prop == NULL) ? 2 : *prop; 1133 dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
1134 DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
1018 1135
1019 /* break now */ 1136 /* break now */
1020 return 1; 1137 return 1;
@@ -1042,7 +1159,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
1042 1159
1043 1160
1044static int __init early_init_dt_scan_memory(unsigned long node, 1161static int __init early_init_dt_scan_memory(unsigned long node,
1045 const char *full_path, void *data) 1162 const char *uname, int depth, void *data)
1046{ 1163{
1047 char *type = get_flat_dt_prop(node, "device_type", NULL); 1164 char *type = get_flat_dt_prop(node, "device_type", NULL);
1048 cell_t *reg, *endp; 1165 cell_t *reg, *endp;
@@ -1058,7 +1175,9 @@ static int __init early_init_dt_scan_memory(unsigned long node,
1058 1175
1059 endp = reg + (l / sizeof(cell_t)); 1176 endp = reg + (l / sizeof(cell_t));
1060 1177
1061 DBG("memory scan node %s ...\n", full_path); 1178 DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
1179 uname, l, reg[0], reg[1], reg[2], reg[3]);
1180
1062 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { 1181 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
1063 unsigned long base, size; 1182 unsigned long base, size;
1064 1183
@@ -1469,10 +1588,11 @@ struct device_node *of_find_node_by_path(const char *path)
1469 struct device_node *np = allnodes; 1588 struct device_node *np = allnodes;
1470 1589
1471 read_lock(&devtree_lock); 1590 read_lock(&devtree_lock);
1472 for (; np != 0; np = np->allnext) 1591 for (; np != 0; np = np->allnext) {
1473 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0 1592 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0
1474 && of_node_get(np)) 1593 && of_node_get(np))
1475 break; 1594 break;
1595 }
1476 read_unlock(&devtree_lock); 1596 read_unlock(&devtree_lock);
1477 return np; 1597 return np;
1478} 1598}
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index dbbe6c79d8da..adcf972711fc 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -1534,7 +1534,8 @@ static unsigned long __init dt_find_string(char *str)
1534 */ 1534 */
1535#define MAX_PROPERTY_NAME 64 1535#define MAX_PROPERTY_NAME 64
1536 1536
1537static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, 1537static void __init scan_dt_build_strings(phandle node,
1538 unsigned long *mem_start,
1538 unsigned long *mem_end) 1539 unsigned long *mem_end)
1539{ 1540{
1540 unsigned long offset = reloc_offset(); 1541 unsigned long offset = reloc_offset();
@@ -1547,16 +1548,21 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1547 /* get and store all property names */ 1548 /* get and store all property names */
1548 prev_name = RELOC(""); 1549 prev_name = RELOC("");
1549 for (;;) { 1550 for (;;) {
1550 int rc;
1551
1552 /* 64 is max len of name including nul. */ 1551 /* 64 is max len of name including nul. */
1553 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); 1552 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
1554 rc = call_prom("nextprop", 3, 1, node, prev_name, namep); 1553 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
1555 if (rc != 1) {
1556 /* No more nodes: unwind alloc */ 1554 /* No more nodes: unwind alloc */
1557 *mem_start = (unsigned long)namep; 1555 *mem_start = (unsigned long)namep;
1558 break; 1556 break;
1559 } 1557 }
1558
1559 /* skip "name" */
1560 if (strcmp(namep, RELOC("name")) == 0) {
1561 *mem_start = (unsigned long)namep;
1562 prev_name = RELOC("name");
1563 continue;
1564 }
1565 /* get/create string entry */
1560 soff = dt_find_string(namep); 1566 soff = dt_find_string(namep);
1561 if (soff != 0) { 1567 if (soff != 0) {
1562 *mem_start = (unsigned long)namep; 1568 *mem_start = (unsigned long)namep;
@@ -1571,7 +1577,7 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1571 1577
1572 /* do all our children */ 1578 /* do all our children */
1573 child = call_prom("child", 1, 1, node); 1579 child = call_prom("child", 1, 1, node);
1574 while (child != (phandle)0) { 1580 while (child != 0) {
1575 scan_dt_build_strings(child, mem_start, mem_end); 1581 scan_dt_build_strings(child, mem_start, mem_end);
1576 child = call_prom("peer", 1, 1, child); 1582 child = call_prom("peer", 1, 1, child);
1577 } 1583 }
@@ -1580,16 +1586,13 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1580static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, 1586static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1581 unsigned long *mem_end) 1587 unsigned long *mem_end)
1582{ 1588{
1583 int l, align;
1584 phandle child; 1589 phandle child;
1585 char *namep, *prev_name, *sstart, *p, *ep; 1590 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
1586 unsigned long soff; 1591 unsigned long soff;
1587 unsigned char *valp; 1592 unsigned char *valp;
1588 unsigned long offset = reloc_offset(); 1593 unsigned long offset = reloc_offset();
1589 char pname[MAX_PROPERTY_NAME]; 1594 static char pname[MAX_PROPERTY_NAME];
1590 char *path; 1595 int l;
1591
1592 path = RELOC(prom_scratch);
1593 1596
1594 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); 1597 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
1595 1598
@@ -1599,23 +1602,33 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1599 namep, *mem_end - *mem_start); 1602 namep, *mem_end - *mem_start);
1600 if (l >= 0) { 1603 if (l >= 0) {
1601 /* Didn't fit? Get more room. */ 1604 /* Didn't fit? Get more room. */
1602 if (l+1 > *mem_end - *mem_start) { 1605 if ((l+1) > (*mem_end - *mem_start)) {
1603 namep = make_room(mem_start, mem_end, l+1, 1); 1606 namep = make_room(mem_start, mem_end, l+1, 1);
1604 call_prom("package-to-path", 3, 1, node, namep, l); 1607 call_prom("package-to-path", 3, 1, node, namep, l);
1605 } 1608 }
1606 namep[l] = '\0'; 1609 namep[l] = '\0';
1610
1607 /* Fixup an Apple bug where they have bogus \0 chars in the 1611 /* Fixup an Apple bug where they have bogus \0 chars in the
1608 * middle of the path in some properties 1612 * middle of the path in some properties
1609 */ 1613 */
1610 for (p = namep, ep = namep + l; p < ep; p++) 1614 for (p = namep, ep = namep + l; p < ep; p++)
1611 if (*p == '\0') { 1615 if (*p == '\0') {
1612 memmove(p, p+1, ep - p); 1616 memmove(p, p+1, ep - p);
1613 ep--; l--; 1617 ep--; l--; p--;
1614 } 1618 }
1615 *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); 1619
1620 /* now try to extract the unit name in that mess */
1621 for (p = namep, lp = NULL; *p; p++)
1622 if (*p == '/')
1623 lp = p + 1;
1624 if (lp != NULL)
1625 memmove(namep, lp, strlen(lp) + 1);
1626 *mem_start = _ALIGN(((unsigned long) namep) +
1627 strlen(namep) + 1, 4);
1616 } 1628 }
1617 1629
1618 /* get it again for debugging */ 1630 /* get it again for debugging */
1631 path = RELOC(prom_scratch);
1619 memset(path, 0, PROM_SCRATCH_SIZE); 1632 memset(path, 0, PROM_SCRATCH_SIZE);
1620 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); 1633 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1621 1634
@@ -1623,23 +1636,27 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1623 prev_name = RELOC(""); 1636 prev_name = RELOC("");
1624 sstart = (char *)RELOC(dt_string_start); 1637 sstart = (char *)RELOC(dt_string_start);
1625 for (;;) { 1638 for (;;) {
1626 int rc; 1639 if (call_prom("nextprop", 3, 1, node, prev_name,
1627 1640 RELOC(pname)) != 1)
1628 rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
1629 if (rc != 1)
1630 break; 1641 break;
1631 1642
1643 /* skip "name" */
1644 if (strcmp(RELOC(pname), RELOC("name")) == 0) {
1645 prev_name = RELOC("name");
1646 continue;
1647 }
1648
1632 /* find string offset */ 1649 /* find string offset */
1633 soff = dt_find_string(pname); 1650 soff = dt_find_string(RELOC(pname));
1634 if (soff == 0) { 1651 if (soff == 0) {
1635 prom_printf("WARNING: Can't find string index for <%s>, node %s\n", 1652 prom_printf("WARNING: Can't find string index for"
1636 pname, path); 1653 " <%s>, node %s\n", RELOC(pname), path);
1637 break; 1654 break;
1638 } 1655 }
1639 prev_name = sstart + soff; 1656 prev_name = sstart + soff;
1640 1657
1641 /* get length */ 1658 /* get length */
1642 l = call_prom("getproplen", 2, 1, node, pname); 1659 l = call_prom("getproplen", 2, 1, node, RELOC(pname));
1643 1660
1644 /* sanity checks */ 1661 /* sanity checks */
1645 if (l == PROM_ERROR) 1662 if (l == PROM_ERROR)
@@ -1648,7 +1665,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1648 prom_printf("WARNING: ignoring large property "); 1665 prom_printf("WARNING: ignoring large property ");
1649 /* It seems OF doesn't null-terminate the path :-( */ 1666 /* It seems OF doesn't null-terminate the path :-( */
1650 prom_printf("[%s] ", path); 1667 prom_printf("[%s] ", path);
1651 prom_printf("%s length 0x%x\n", pname, l); 1668 prom_printf("%s length 0x%x\n", RELOC(pname), l);
1652 continue; 1669 continue;
1653 } 1670 }
1654 1671
@@ -1658,17 +1675,16 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1658 dt_push_token(soff, mem_start, mem_end); 1675 dt_push_token(soff, mem_start, mem_end);
1659 1676
1660 /* push property content */ 1677 /* push property content */
1661 align = (l >= 8) ? 8 : 4; 1678 valp = make_room(mem_start, mem_end, l, 4);
1662 valp = make_room(mem_start, mem_end, l, align); 1679 call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
1663 call_prom("getprop", 4, 1, node, pname, valp, l);
1664 *mem_start = _ALIGN(*mem_start, 4); 1680 *mem_start = _ALIGN(*mem_start, 4);
1665 } 1681 }
1666 1682
1667 /* Add a "linux,phandle" property. */ 1683 /* Add a "linux,phandle" property. */
1668 soff = dt_find_string(RELOC("linux,phandle")); 1684 soff = dt_find_string(RELOC("linux,phandle"));
1669 if (soff == 0) 1685 if (soff == 0)
1670 prom_printf("WARNING: Can't find string index for <linux-phandle>" 1686 prom_printf("WARNING: Can't find string index for"
1671 " node %s\n", path); 1687 " <linux-phandle> node %s\n", path);
1672 else { 1688 else {
1673 dt_push_token(OF_DT_PROP, mem_start, mem_end); 1689 dt_push_token(OF_DT_PROP, mem_start, mem_end);
1674 dt_push_token(4, mem_start, mem_end); 1690 dt_push_token(4, mem_start, mem_end);
@@ -1679,7 +1695,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1679 1695
1680 /* do all our children */ 1696 /* do all our children */
1681 child = call_prom("child", 1, 1, node); 1697 child = call_prom("child", 1, 1, node);
1682 while (child != (phandle)0) { 1698 while (child != 0) {
1683 scan_dt_build_struct(child, mem_start, mem_end); 1699 scan_dt_build_struct(child, mem_start, mem_end);
1684 child = call_prom("peer", 1, 1, child); 1700 child = call_prom("peer", 1, 1, child);
1685 } 1701 }
@@ -1718,7 +1734,8 @@ static void __init flatten_device_tree(void)
1718 1734
1719 /* Build header and make room for mem rsv map */ 1735 /* Build header and make room for mem rsv map */
1720 mem_start = _ALIGN(mem_start, 4); 1736 mem_start = _ALIGN(mem_start, 4);
1721 hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4); 1737 hdr = make_room(&mem_start, &mem_end,
1738 sizeof(struct boot_param_header), 4);
1722 RELOC(dt_header_start) = (unsigned long)hdr; 1739 RELOC(dt_header_start) = (unsigned long)hdr;
1723 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8); 1740 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
1724 1741
@@ -1731,11 +1748,11 @@ static void __init flatten_device_tree(void)
1731 namep = make_room(&mem_start, &mem_end, 16, 1); 1748 namep = make_room(&mem_start, &mem_end, 16, 1);
1732 strcpy(namep, RELOC("linux,phandle")); 1749 strcpy(namep, RELOC("linux,phandle"));
1733 mem_start = (unsigned long)namep + strlen(namep) + 1; 1750 mem_start = (unsigned long)namep + strlen(namep) + 1;
1734 RELOC(dt_string_end) = mem_start;
1735 1751
1736 /* Build string array */ 1752 /* Build string array */
1737 prom_printf("Building dt strings...\n"); 1753 prom_printf("Building dt strings...\n");
1738 scan_dt_build_strings(root, &mem_start, &mem_end); 1754 scan_dt_build_strings(root, &mem_start, &mem_end);
1755 RELOC(dt_string_end) = mem_start;
1739 1756
1740 /* Build structure */ 1757 /* Build structure */
1741 mem_start = PAGE_ALIGN(mem_start); 1758 mem_start = PAGE_ALIGN(mem_start);
@@ -1750,9 +1767,11 @@ static void __init flatten_device_tree(void)
1750 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); 1767 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
1751 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); 1768 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
1752 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start); 1769 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
1770 hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);
1753 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start); 1771 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
1754 hdr->version = OF_DT_VERSION; 1772 hdr->version = OF_DT_VERSION;
1755 hdr->last_comp_version = 1; 1773 /* Version 16 is not backward compatible */
1774 hdr->last_comp_version = 0x10;
1756 1775
1757 /* Reserve the whole thing and copy the reserve map in, we 1776 /* Reserve the whole thing and copy the reserve map in, we
1758 * also bump mem_reserve_cnt to cause further reservations to 1777 * also bump mem_reserve_cnt to cause further reservations to
@@ -1808,6 +1827,9 @@ static void __init fixup_device_tree(void)
1808 /* does it need fixup ? */ 1827 /* does it need fixup ? */
1809 if (prom_getproplen(i2c, "interrupts") > 0) 1828 if (prom_getproplen(i2c, "interrupts") > 0)
1810 return; 1829 return;
1830
1831 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
1832
1811 /* interrupt on this revision of u3 is number 0 and level */ 1833 /* interrupt on this revision of u3 is number 0 and level */
1812 interrupts[0] = 0; 1834 interrupts[0] = 0;
1813 interrupts[1] = 1; 1835 interrupts[1] = 1;
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
index 1048817befb8..1dccadaddd1d 100644
--- a/arch/ppc64/kernel/rtas_pci.c
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -58,6 +58,21 @@ static int config_access_valid(struct device_node *dn, int where)
58 return 0; 58 return 0;
59} 59}
60 60
61static int of_device_available(struct device_node * dn)
62{
63 char * status;
64
65 status = get_property(dn, "status", NULL);
66
67 if (!status)
68 return 1;
69
70 if (!strcmp(status, "okay"))
71 return 1;
72
73 return 0;
74}
75
61static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) 76static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
62{ 77{
63 int returnval = -1; 78 int returnval = -1;
@@ -103,7 +118,7 @@ static int rtas_pci_read_config(struct pci_bus *bus,
103 118
104 /* Search only direct children of the bus */ 119 /* Search only direct children of the bus */
105 for (dn = busdn->child; dn; dn = dn->sibling) 120 for (dn = busdn->child; dn; dn = dn->sibling)
106 if (dn->devfn == devfn) 121 if (dn->devfn == devfn && of_device_available(dn))
107 return rtas_read_config(dn, where, size, val); 122 return rtas_read_config(dn, where, size, val);
108 return PCIBIOS_DEVICE_NOT_FOUND; 123 return PCIBIOS_DEVICE_NOT_FOUND;
109} 124}
@@ -146,7 +161,7 @@ static int rtas_pci_write_config(struct pci_bus *bus,
146 161
147 /* Search only direct children of the bus */ 162 /* Search only direct children of the bus */
148 for (dn = busdn->child; dn; dn = dn->sibling) 163 for (dn = busdn->child; dn; dn = dn->sibling)
149 if (dn->devfn == devfn) 164 if (dn->devfn == devfn && of_device_available(dn))
150 return rtas_write_config(dn, where, size, val); 165 return rtas_write_config(dn, where, size, val);
151 return PCIBIOS_DEVICE_NOT_FOUND; 166 return PCIBIOS_DEVICE_NOT_FOUND;
152} 167}
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index e9c24d2dbd91..ee3b20de2e7a 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -536,15 +536,19 @@ static void __init check_for_initrd(void)
536 536
537 DBG(" -> check_for_initrd()\n"); 537 DBG(" -> check_for_initrd()\n");
538 538
539 prop = (u64 *)get_property(of_chosen, "linux,initrd-start", NULL); 539 if (of_chosen) {
540 if (prop != NULL) { 540 prop = (u64 *)get_property(of_chosen,
541 initrd_start = (unsigned long)__va(*prop); 541 "linux,initrd-start", NULL);
542 prop = (u64 *)get_property(of_chosen, "linux,initrd-end", NULL);
543 if (prop != NULL) { 542 if (prop != NULL) {
544 initrd_end = (unsigned long)__va(*prop); 543 initrd_start = (unsigned long)__va(*prop);
545 initrd_below_start_ok = 1; 544 prop = (u64 *)get_property(of_chosen,
546 } else 545 "linux,initrd-end", NULL);
547 initrd_start = 0; 546 if (prop != NULL) {
547 initrd_end = (unsigned long)__va(*prop);
548 initrd_below_start_ok = 1;
549 } else
550 initrd_start = 0;
551 }
548 } 552 }
549 553
550 /* If we were passed an initrd, set the ROOT_DEV properly if the values 554 /* If we were passed an initrd, set the ROOT_DEV properly if the values
@@ -627,7 +631,7 @@ void __init setup_system(void)
627 * Initialize xmon 631 * Initialize xmon
628 */ 632 */
629#ifdef CONFIG_XMON_DEFAULT 633#ifdef CONFIG_XMON_DEFAULT
630 xmon_init(); 634 xmon_init(1);
631#endif 635#endif
632 /* 636 /*
633 * Register early console 637 * Register early console
@@ -1343,11 +1347,13 @@ static int __init early_xmon(char *p)
1343 /* ensure xmon is enabled */ 1347 /* ensure xmon is enabled */
1344 if (p) { 1348 if (p) {
1345 if (strncmp(p, "on", 2) == 0) 1349 if (strncmp(p, "on", 2) == 0)
1346 xmon_init(); 1350 xmon_init(1);
1351 if (strncmp(p, "off", 3) == 0)
1352 xmon_init(0);
1347 if (strncmp(p, "early", 5) != 0) 1353 if (strncmp(p, "early", 5) != 0)
1348 return 0; 1354 return 0;
1349 } 1355 }
1350 xmon_init(); 1356 xmon_init(1);
1351 debugger(NULL); 1357 debugger(NULL);
1352 1358
1353 return 0; 1359 return 0;
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 02b8ac4e0168..f311ee7c0070 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -13,6 +13,7 @@
13#include <asm/current.h> 13#include <asm/current.h>
14#include <asm/processor.h> 14#include <asm/processor.h>
15#include <asm/cputable.h> 15#include <asm/cputable.h>
16#include <asm/firmware.h>
16#include <asm/hvcall.h> 17#include <asm/hvcall.h>
17#include <asm/prom.h> 18#include <asm/prom.h>
18#include <asm/systemcfg.h> 19#include <asm/systemcfg.h>
@@ -100,6 +101,8 @@ static int __init setup_smt_snooze_delay(char *str)
100} 101}
101__setup("smt-snooze-delay=", setup_smt_snooze_delay); 102__setup("smt-snooze-delay=", setup_smt_snooze_delay);
102 103
104#endif /* CONFIG_PPC_MULTIPLATFORM */
105
103/* 106/*
104 * Enabling PMCs will slow partition context switch times so we only do 107 * Enabling PMCs will slow partition context switch times so we only do
105 * it the first time we write to the PMCs. 108 * it the first time we write to the PMCs.
@@ -109,65 +112,15 @@ static DEFINE_PER_CPU(char, pmcs_enabled);
109 112
110void ppc64_enable_pmcs(void) 113void ppc64_enable_pmcs(void)
111{ 114{
112 unsigned long hid0;
113#ifdef CONFIG_PPC_PSERIES
114 unsigned long set, reset;
115#endif /* CONFIG_PPC_PSERIES */
116
117 /* Only need to enable them once */ 115 /* Only need to enable them once */
118 if (__get_cpu_var(pmcs_enabled)) 116 if (__get_cpu_var(pmcs_enabled))
119 return; 117 return;
120 118
121 __get_cpu_var(pmcs_enabled) = 1; 119 __get_cpu_var(pmcs_enabled) = 1;
122 120
123 switch (systemcfg->platform) { 121 if (ppc_md.enable_pmcs)
124 case PLATFORM_PSERIES: 122 ppc_md.enable_pmcs();
125 case PLATFORM_POWERMAC:
126 hid0 = mfspr(HID0);
127 hid0 |= 1UL << (63 - 20);
128
129 /* POWER4 requires the following sequence */
130 asm volatile(
131 "sync\n"
132 "mtspr %1, %0\n"
133 "mfspr %0, %1\n"
134 "mfspr %0, %1\n"
135 "mfspr %0, %1\n"
136 "mfspr %0, %1\n"
137 "mfspr %0, %1\n"
138 "mfspr %0, %1\n"
139 "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
140 "memory");
141 break;
142
143#ifdef CONFIG_PPC_PSERIES
144 case PLATFORM_PSERIES_LPAR:
145 set = 1UL << 63;
146 reset = 0;
147 plpar_hcall_norets(H_PERFMON, set, reset);
148 break;
149#endif /* CONFIG_PPC_PSERIES */
150
151 default:
152 break;
153 }
154
155#ifdef CONFIG_PPC_PSERIES
156 /* instruct hypervisor to maintain PMCs */
157 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
158 get_paca()->lppaca.pmcregs_in_use = 1;
159#endif /* CONFIG_PPC_PSERIES */
160} 123}
161
162#else
163
164/* PMC stuff */
165void ppc64_enable_pmcs(void)
166{
167 /* XXX Implement for iseries */
168}
169#endif /* CONFIG_PPC_MULTIPLATFORM */
170
171EXPORT_SYMBOL(ppc64_enable_pmcs); 124EXPORT_SYMBOL(ppc64_enable_pmcs);
172 125
173/* XXX convert to rusty's on_one_cpu */ 126/* XXX convert to rusty's on_one_cpu */
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 909462e1adea..1696e1b05bb9 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -67,6 +67,7 @@
67#include <asm/prom.h> 67#include <asm/prom.h>
68#include <asm/sections.h> 68#include <asm/sections.h>
69#include <asm/systemcfg.h> 69#include <asm/systemcfg.h>
70#include <asm/firmware.h>
70 71
71u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; 72u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
72 73
@@ -370,13 +371,11 @@ int timer_interrupt(struct pt_regs * regs)
370 process_hvlpevents(regs); 371 process_hvlpevents(regs);
371#endif 372#endif
372 373
373/* collect purr register values often, for accurate calculations */ 374 /* collect purr register values often, for accurate calculations */
374#if defined(CONFIG_PPC_PSERIES) 375 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
375 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
376 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); 376 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
377 cu->current_tb = mfspr(SPRN_PURR); 377 cu->current_tb = mfspr(SPRN_PURR);
378 } 378 }
379#endif
380 379
381 irq_exit(); 380 irq_exit();
382 381
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index 0c0ba71ac0e8..3b790bafcaad 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -1,10 +1,11 @@
1/* 1/*
2 * IBM PowerPC Virtual I/O Infrastructure Support. 2 * IBM PowerPC Virtual I/O Infrastructure Support.
3 * 3 *
4 * Copyright (c) 2003 IBM Corp. 4 * Copyright (c) 2003-2005 IBM Corp.
5 * Dave Engebretsen engebret@us.ibm.com 5 * Dave Engebretsen engebret@us.ibm.com
6 * Santiago Leon santil@us.ibm.com 6 * Santiago Leon santil@us.ibm.com
7 * Hollis Blanchard <hollisb@us.ibm.com> 7 * Hollis Blanchard <hollisb@us.ibm.com>
8 * Stephen Rothwell
8 * 9 *
9 * This program is free software; you can redistribute it and/or 10 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 11 * modify it under the terms of the GNU General Public License
@@ -14,57 +15,27 @@
14 15
15#include <linux/init.h> 16#include <linux/init.h>
16#include <linux/console.h> 17#include <linux/console.h>
17#include <linux/version.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/kobject.h>
20#include <linux/mm.h> 19#include <linux/mm.h>
21#include <linux/dma-mapping.h> 20#include <linux/dma-mapping.h>
22#include <asm/rtas.h>
23#include <asm/iommu.h> 21#include <asm/iommu.h>
24#include <asm/dma.h> 22#include <asm/dma.h>
25#include <asm/ppcdebug.h>
26#include <asm/vio.h> 23#include <asm/vio.h>
27#include <asm/hvcall.h>
28#include <asm/iSeries/vio.h>
29#include <asm/iSeries/HvTypes.h>
30#include <asm/iSeries/HvCallXm.h>
31#include <asm/iSeries/HvLpConfig.h>
32
33#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
34
35extern struct subsystem devices_subsys; /* needed for vio_find_name() */
36 24
37static const struct vio_device_id *vio_match_device( 25static const struct vio_device_id *vio_match_device(
38 const struct vio_device_id *, const struct vio_dev *); 26 const struct vio_device_id *, const struct vio_dev *);
39 27
40#ifdef CONFIG_PPC_PSERIES 28struct vio_dev vio_bus_device = { /* fake "parent" device */
41static struct iommu_table *vio_build_iommu_table(struct vio_dev *);
42static int vio_num_address_cells;
43#endif
44#ifdef CONFIG_PPC_ISERIES
45static struct iommu_table veth_iommu_table;
46static struct iommu_table vio_iommu_table;
47#endif
48static struct vio_dev vio_bus_device = { /* fake "parent" device */
49 .name = vio_bus_device.dev.bus_id, 29 .name = vio_bus_device.dev.bus_id,
50 .type = "", 30 .type = "",
51#ifdef CONFIG_PPC_ISERIES
52 .iommu_table = &vio_iommu_table,
53#endif
54 .dev.bus_id = "vio", 31 .dev.bus_id = "vio",
55 .dev.bus = &vio_bus_type, 32 .dev.bus = &vio_bus_type,
56}; 33};
57 34
58#ifdef CONFIG_PPC_ISERIES 35static int (*is_match)(const struct vio_device_id *id,
59static struct vio_dev *__init vio_register_device_iseries(char *type, 36 const struct vio_dev *dev);
60 uint32_t unit_num); 37static void (*unregister_device_callback)(struct vio_dev *dev);
61 38static void (*release_device_callback)(struct device *dev);
62struct device *iSeries_vio_dev = &vio_bus_device.dev;
63EXPORT_SYMBOL(iSeries_vio_dev);
64
65#define device_is_compatible(a, b) 1
66
67#endif
68 39
69/* convert from struct device to struct vio_dev and pass to driver. 40/* convert from struct device to struct vio_dev and pass to driver.
70 * dev->driver has already been set by generic code because vio_bus_match 41 * dev->driver has already been set by generic code because vio_bus_match
@@ -76,8 +47,6 @@ static int vio_bus_probe(struct device *dev)
76 const struct vio_device_id *id; 47 const struct vio_device_id *id;
77 int error = -ENODEV; 48 int error = -ENODEV;
78 49
79 DBGENTER();
80
81 if (!viodrv->probe) 50 if (!viodrv->probe)
82 return error; 51 return error;
83 52
@@ -95,8 +64,6 @@ static int vio_bus_remove(struct device *dev)
95 struct vio_dev *viodev = to_vio_dev(dev); 64 struct vio_dev *viodev = to_vio_dev(dev);
96 struct vio_driver *viodrv = to_vio_driver(dev->driver); 65 struct vio_driver *viodrv = to_vio_driver(dev->driver);
97 66
98 DBGENTER();
99
100 if (viodrv->remove) { 67 if (viodrv->remove) {
101 return viodrv->remove(viodev); 68 return viodrv->remove(viodev);
102 } 69 }
@@ -146,178 +113,65 @@ EXPORT_SYMBOL(vio_unregister_driver);
146static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids, 113static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids,
147 const struct vio_dev *dev) 114 const struct vio_dev *dev)
148{ 115{
149 DBGENTER();
150
151 while (ids->type) { 116 while (ids->type) {
152 if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && 117 if (is_match(ids, dev))
153 device_is_compatible(dev->dev.platform_data, ids->compat))
154 return ids; 118 return ids;
155 ids++; 119 ids++;
156 } 120 }
157 return NULL; 121 return NULL;
158} 122}
159 123
160#ifdef CONFIG_PPC_ISERIES
161void __init iommu_vio_init(void)
162{
163 struct iommu_table *t;
164 struct iommu_table_cb cb;
165 unsigned long cbp;
166 unsigned long itc_entries;
167
168 cb.itc_busno = 255; /* Bus 255 is the virtual bus */
169 cb.itc_virtbus = 0xff; /* Ask for virtual bus */
170
171 cbp = virt_to_abs(&cb);
172 HvCallXm_getTceTableParms(cbp);
173
174 itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);
175 veth_iommu_table.it_size = itc_entries / 2;
176 veth_iommu_table.it_busno = cb.itc_busno;
177 veth_iommu_table.it_offset = cb.itc_offset;
178 veth_iommu_table.it_index = cb.itc_index;
179 veth_iommu_table.it_type = TCE_VB;
180 veth_iommu_table.it_blocksize = 1;
181
182 t = iommu_init_table(&veth_iommu_table);
183
184 if (!t)
185 printk("Virtual Bus VETH TCE table failed.\n");
186
187 vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;
188 vio_iommu_table.it_busno = cb.itc_busno;
189 vio_iommu_table.it_offset = cb.itc_offset +
190 veth_iommu_table.it_size;
191 vio_iommu_table.it_index = cb.itc_index;
192 vio_iommu_table.it_type = TCE_VB;
193 vio_iommu_table.it_blocksize = 1;
194
195 t = iommu_init_table(&vio_iommu_table);
196
197 if (!t)
198 printk("Virtual Bus VIO TCE table failed.\n");
199}
200#endif
201
202#ifdef CONFIG_PPC_PSERIES
203static void probe_bus_pseries(void)
204{
205 struct device_node *node_vroot, *of_node;
206
207 node_vroot = find_devices("vdevice");
208 if ((node_vroot == NULL) || (node_vroot->child == NULL))
209 /* this machine doesn't do virtual IO, and that's ok */
210 return;
211
212 vio_num_address_cells = prom_n_addr_cells(node_vroot->child);
213
214 /*
215 * Create struct vio_devices for each virtual device in the device tree.
216 * Drivers will associate with them later.
217 */
218 for (of_node = node_vroot->child; of_node != NULL;
219 of_node = of_node->sibling) {
220 printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
221 vio_register_device_node(of_node);
222 }
223}
224#endif
225
226#ifdef CONFIG_PPC_ISERIES
227static void probe_bus_iseries(void)
228{
229 HvLpIndexMap vlan_map = HvLpConfig_getVirtualLanIndexMap();
230 struct vio_dev *viodev;
231 int i;
232
233 /* there is only one of each of these */
234 vio_register_device_iseries("viocons", 0);
235 vio_register_device_iseries("vscsi", 0);
236
237 vlan_map = HvLpConfig_getVirtualLanIndexMap();
238 for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
239 if ((vlan_map & (0x8000 >> i)) == 0)
240 continue;
241 viodev = vio_register_device_iseries("vlan", i);
242 /* veth is special and has it own iommu_table */
243 viodev->iommu_table = &veth_iommu_table;
244 }
245 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
246 vio_register_device_iseries("viodasd", i);
247 for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
248 vio_register_device_iseries("viocd", i);
249 for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
250 vio_register_device_iseries("viotape", i);
251}
252#endif
253
254/** 124/**
255 * vio_bus_init: - Initialize the virtual IO bus 125 * vio_bus_init: - Initialize the virtual IO bus
256 */ 126 */
257static int __init vio_bus_init(void) 127int __init vio_bus_init(int (*match_func)(const struct vio_device_id *id,
128 const struct vio_dev *dev),
129 void (*unregister_dev)(struct vio_dev *),
130 void (*release_dev)(struct device *))
258{ 131{
259 int err; 132 int err;
260 133
134 is_match = match_func;
135 unregister_device_callback = unregister_dev;
136 release_device_callback = release_dev;
137
261 err = bus_register(&vio_bus_type); 138 err = bus_register(&vio_bus_type);
262 if (err) { 139 if (err) {
263 printk(KERN_ERR "failed to register VIO bus\n"); 140 printk(KERN_ERR "failed to register VIO bus\n");
264 return err; 141 return err;
265 } 142 }
266 143
267 /* the fake parent of all vio devices, just to give us a nice directory */ 144 /* the fake parent of all vio devices, just to give us
145 * a nice directory
146 */
268 err = device_register(&vio_bus_device.dev); 147 err = device_register(&vio_bus_device.dev);
269 if (err) { 148 if (err) {
270 printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__, 149 printk(KERN_WARNING "%s: device_register returned %i\n",
271 err); 150 __FUNCTION__, err);
272 return err; 151 return err;
273 } 152 }
274 153
275#ifdef CONFIG_PPC_PSERIES
276 probe_bus_pseries();
277#endif
278#ifdef CONFIG_PPC_ISERIES
279 probe_bus_iseries();
280#endif
281
282 return 0; 154 return 0;
283} 155}
284 156
285__initcall(vio_bus_init);
286
287/* vio_dev refcount hit 0 */ 157/* vio_dev refcount hit 0 */
288static void __devinit vio_dev_release(struct device *dev) 158static void __devinit vio_dev_release(struct device *dev)
289{ 159{
290 DBGENTER(); 160 if (release_device_callback)
291 161 release_device_callback(dev);
292#ifdef CONFIG_PPC_PSERIES
293 /* XXX free TCE table */
294 of_node_put(dev->platform_data);
295#endif
296 kfree(to_vio_dev(dev)); 162 kfree(to_vio_dev(dev));
297} 163}
298 164
299#ifdef CONFIG_PPC_PSERIES
300static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
301{
302 struct device_node *of_node = dev->platform_data;
303
304 return sprintf(buf, "%s\n", of_node->full_name);
305}
306DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
307#endif
308
309static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf) 165static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)
310{ 166{
311 return sprintf(buf, "%s\n", to_vio_dev(dev)->name); 167 return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
312} 168}
313DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); 169DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
314 170
315static struct vio_dev * __devinit vio_register_device_common( 171struct vio_dev * __devinit vio_register_device_common(
316 struct vio_dev *viodev, char *name, char *type, 172 struct vio_dev *viodev, char *name, char *type,
317 uint32_t unit_address, struct iommu_table *iommu_table) 173 uint32_t unit_address, struct iommu_table *iommu_table)
318{ 174{
319 DBGENTER();
320
321 viodev->name = name; 175 viodev->name = name;
322 viodev->type = type; 176 viodev->type = type;
323 viodev->unit_address = unit_address; 177 viodev->unit_address = unit_address;
@@ -338,222 +192,15 @@ static struct vio_dev * __devinit vio_register_device_common(
338 return viodev; 192 return viodev;
339} 193}
340 194
341#ifdef CONFIG_PPC_PSERIES
342/**
343 * vio_register_device_node: - Register a new vio device.
344 * @of_node: The OF node for this device.
345 *
346 * Creates and initializes a vio_dev structure from the data in
347 * of_node (dev.platform_data) and adds it to the list of virtual devices.
348 * Returns a pointer to the created vio_dev or NULL if node has
349 * NULL device_type or compatible fields.
350 */
351struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
352{
353 struct vio_dev *viodev;
354 unsigned int *unit_address;
355 unsigned int *irq_p;
356
357 DBGENTER();
358
359 /* we need the 'device_type' property, in order to match with drivers */
360 if ((NULL == of_node->type)) {
361 printk(KERN_WARNING
362 "%s: node %s missing 'device_type'\n", __FUNCTION__,
363 of_node->name ? of_node->name : "<unknown>");
364 return NULL;
365 }
366
367 unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
368 if (!unit_address) {
369 printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
370 of_node->name ? of_node->name : "<unknown>");
371 return NULL;
372 }
373
374 /* allocate a vio_dev for this node */
375 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
376 if (!viodev) {
377 return NULL;
378 }
379 memset(viodev, 0, sizeof(struct vio_dev));
380
381 viodev->dev.platform_data = of_node_get(of_node);
382
383 viodev->irq = NO_IRQ;
384 irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
385 if (irq_p) {
386 int virq = virt_irq_create_mapping(*irq_p);
387 if (virq == NO_IRQ) {
388 printk(KERN_ERR "Unable to allocate interrupt "
389 "number for %s\n", of_node->full_name);
390 } else
391 viodev->irq = irq_offset_up(virq);
392 }
393
394 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
395
396 /* register with generic device framework */
397 if (vio_register_device_common(viodev, of_node->name, of_node->type,
398 *unit_address, vio_build_iommu_table(viodev))
399 == NULL) {
400 /* XXX free TCE table */
401 kfree(viodev);
402 return NULL;
403 }
404 device_create_file(&viodev->dev, &dev_attr_devspec);
405
406 return viodev;
407}
408EXPORT_SYMBOL(vio_register_device_node);
409#endif
410
411#ifdef CONFIG_PPC_ISERIES
412/**
413 * vio_register_device: - Register a new vio device.
414 * @voidev: The device to register.
415 */
416static struct vio_dev *__init vio_register_device_iseries(char *type,
417 uint32_t unit_num)
418{
419 struct vio_dev *viodev;
420
421 DBGENTER();
422
423 /* allocate a vio_dev for this node */
424 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
425 if (!viodev)
426 return NULL;
427 memset(viodev, 0, sizeof(struct vio_dev));
428
429 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
430
431 return vio_register_device_common(viodev, viodev->dev.bus_id, type,
432 unit_num, &vio_iommu_table);
433}
434#endif
435
436void __devinit vio_unregister_device(struct vio_dev *viodev) 195void __devinit vio_unregister_device(struct vio_dev *viodev)
437{ 196{
438 DBGENTER(); 197 if (unregister_device_callback)
439#ifdef CONFIG_PPC_PSERIES 198 unregister_device_callback(viodev);
440 device_remove_file(&viodev->dev, &dev_attr_devspec);
441#endif
442 device_remove_file(&viodev->dev, &dev_attr_name); 199 device_remove_file(&viodev->dev, &dev_attr_name);
443 device_unregister(&viodev->dev); 200 device_unregister(&viodev->dev);
444} 201}
445EXPORT_SYMBOL(vio_unregister_device); 202EXPORT_SYMBOL(vio_unregister_device);
446 203
447#ifdef CONFIG_PPC_PSERIES
448/**
449 * vio_get_attribute: - get attribute for virtual device
450 * @vdev: The vio device to get property.
451 * @which: The property/attribute to be extracted.
452 * @length: Pointer to length of returned data size (unused if NULL).
453 *
454 * Calls prom.c's get_property() to return the value of the
455 * attribute specified by the preprocessor constant @which
456*/
457const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
458{
459 return get_property(vdev->dev.platform_data, (char*)which, length);
460}
461EXPORT_SYMBOL(vio_get_attribute);
462
463/* vio_find_name() - internal because only vio.c knows how we formatted the
464 * kobject name
465 * XXX once vio_bus_type.devices is actually used as a kset in
466 * drivers/base/bus.c, this function should be removed in favor of
467 * "device_find(kobj_name, &vio_bus_type)"
468 */
469static struct vio_dev *vio_find_name(const char *kobj_name)
470{
471 struct kobject *found;
472
473 found = kset_find_obj(&devices_subsys.kset, kobj_name);
474 if (!found)
475 return NULL;
476
477 return to_vio_dev(container_of(found, struct device, kobj));
478}
479
480/**
481 * vio_find_node - find an already-registered vio_dev
482 * @vnode: device_node of the virtual device we're looking for
483 */
484struct vio_dev *vio_find_node(struct device_node *vnode)
485{
486 uint32_t *unit_address;
487 char kobj_name[BUS_ID_SIZE];
488
489 /* construct the kobject name from the device node */
490 unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
491 if (!unit_address)
492 return NULL;
493 snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
494
495 return vio_find_name(kobj_name);
496}
497EXPORT_SYMBOL(vio_find_node);
498
499/**
500 * vio_build_iommu_table: - gets the dma information from OF and builds the TCE tree.
501 * @dev: the virtual device.
502 *
503 * Returns a pointer to the built tce tree, or NULL if it can't
504 * find property.
505*/
506static struct iommu_table * vio_build_iommu_table(struct vio_dev *dev)
507{
508 unsigned int *dma_window;
509 struct iommu_table *newTceTable;
510 unsigned long offset;
511 int dma_window_property_size;
512
513 dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
514 if(!dma_window) {
515 return NULL;
516 }
517
518 newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
519
520 /* There should be some code to extract the phys-encoded offset
521 using prom_n_addr_cells(). However, according to a comment
522 on earlier versions, it's always zero, so we don't bother */
523 offset = dma_window[1] >> PAGE_SHIFT;
524
525 /* TCE table size - measured in tce entries */
526 newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
527 /* offset for VIO should always be 0 */
528 newTceTable->it_offset = offset;
529 newTceTable->it_busno = 0;
530 newTceTable->it_index = (unsigned long)dma_window[0];
531 newTceTable->it_type = TCE_VB;
532
533 return iommu_init_table(newTceTable);
534}
535
536int vio_enable_interrupts(struct vio_dev *dev)
537{
538 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
539 if (rc != H_Success) {
540 printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
541 }
542 return rc;
543}
544EXPORT_SYMBOL(vio_enable_interrupts);
545
546int vio_disable_interrupts(struct vio_dev *dev)
547{
548 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
549 if (rc != H_Success) {
550 printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
551 }
552 return rc;
553}
554EXPORT_SYMBOL(vio_disable_interrupts);
555#endif
556
557static dma_addr_t vio_map_single(struct device *dev, void *vaddr, 204static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
558 size_t size, enum dma_data_direction direction) 205 size_t size, enum dma_data_direction direction)
559{ 206{
@@ -617,8 +264,6 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv)
617 const struct vio_device_id *ids = vio_drv->id_table; 264 const struct vio_device_id *ids = vio_drv->id_table;
618 const struct vio_device_id *found_id; 265 const struct vio_device_id *found_id;
619 266
620 DBGENTER();
621
622 if (!ids) 267 if (!ids)
623 return 0; 268 return 0;
624 269
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index a6abd3a979bf..7626bb59954d 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -51,7 +51,6 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va,
51 unsigned long prpn, unsigned long vflags, 51 unsigned long prpn, unsigned long vflags,
52 unsigned long rflags) 52 unsigned long rflags)
53{ 53{
54 unsigned long arpn = physRpn_to_absRpn(prpn);
55 hpte_t *hptep = htab_address + hpte_group; 54 hpte_t *hptep = htab_address + hpte_group;
56 unsigned long hpte_v, hpte_r; 55 unsigned long hpte_v, hpte_r;
57 int i; 56 int i;
@@ -74,7 +73,7 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va,
74 hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; 73 hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
75 if (vflags & HPTE_V_LARGE) 74 if (vflags & HPTE_V_LARGE)
76 va &= ~(1UL << HPTE_V_AVPN_SHIFT); 75 va &= ~(1UL << HPTE_V_AVPN_SHIFT);
77 hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags; 76 hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
78 77
79 hptep->r = hpte_r; 78 hptep->r = hpte_r;
80 /* Guarantee the second dword is visible before the valid bit */ 79 /* Guarantee the second dword is visible before the valid bit */
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 623b5d130c31..09475c8edf7c 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -210,7 +210,7 @@ void __init htab_initialize(void)
210 210
211 /* create bolted the linear mapping in the hash table */ 211 /* create bolted the linear mapping in the hash table */
212 for (i=0; i < lmb.memory.cnt; i++) { 212 for (i=0; i < lmb.memory.cnt; i++) {
213 base = lmb.memory.region[i].physbase + KERNELBASE; 213 base = lmb.memory.region[i].base + KERNELBASE;
214 size = lmb.memory.region[i].size; 214 size = lmb.memory.region[i].size;
215 215
216 DBG("creating mapping for region: %lx : %lx\n", base, size); 216 DBG("creating mapping for region: %lx : %lx\n", base, size);
@@ -302,7 +302,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
302 int local = 0; 302 int local = 0;
303 cpumask_t tmp; 303 cpumask_t tmp;
304 304
305 if ((ea & ~REGION_MASK) > EADDR_MASK) 305 if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
306 return 1; 306 return 1;
307 307
308 switch (REGION_ID(ea)) { 308 switch (REGION_ID(ea)) {
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index f9524602818d..e7833c80eb68 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -27,124 +27,94 @@
27 27
28#include <linux/sysctl.h> 28#include <linux/sysctl.h>
29 29
30#define HUGEPGDIR_SHIFT (HPAGE_SHIFT + PAGE_SHIFT - 3) 30#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
31#define HUGEPGDIR_SIZE (1UL << HUGEPGDIR_SHIFT) 31#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
32#define HUGEPGDIR_MASK (~(HUGEPGDIR_SIZE-1))
33 32
34#define HUGEPTE_INDEX_SIZE 9 33/* Modelled after find_linux_pte() */
35#define HUGEPGD_INDEX_SIZE 10 34pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
36
37#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE)
38#define PTRS_PER_HUGEPGD (1 << HUGEPGD_INDEX_SIZE)
39
40static inline int hugepgd_index(unsigned long addr)
41{
42 return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT;
43}
44
45static pud_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
46{ 35{
47 int index; 36 pgd_t *pg;
37 pud_t *pu;
38 pmd_t *pm;
39 pte_t *pt;
48 40
49 if (! mm->context.huge_pgdir) 41 BUG_ON(! in_hugepage_area(mm->context, addr));
50 return NULL;
51 42
43 addr &= HPAGE_MASK;
44
45 pg = pgd_offset(mm, addr);
46 if (!pgd_none(*pg)) {
47 pu = pud_offset(pg, addr);
48 if (!pud_none(*pu)) {
49 pm = pmd_offset(pu, addr);
50 pt = (pte_t *)pm;
51 BUG_ON(!pmd_none(*pm)
52 && !(pte_present(*pt) && pte_huge(*pt)));
53 return pt;
54 }
55 }
52 56
53 index = hugepgd_index(addr); 57 return NULL;
54 BUG_ON(index >= PTRS_PER_HUGEPGD);
55 return (pud_t *)(mm->context.huge_pgdir + index);
56} 58}
57 59
58static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr) 60pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
59{ 61{
60 int index; 62 pgd_t *pg;
61 63 pud_t *pu;
62 if (pud_none(*dir)) 64 pmd_t *pm;
63 return NULL; 65 pte_t *pt;
64 66
65 index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE;
66 return (pte_t *)pud_page(*dir) + index;
67}
68
69static pud_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
70{
71 BUG_ON(! in_hugepage_area(mm->context, addr)); 67 BUG_ON(! in_hugepage_area(mm->context, addr));
72 68
73 if (! mm->context.huge_pgdir) { 69 addr &= HPAGE_MASK;
74 pgd_t *new;
75 spin_unlock(&mm->page_table_lock);
76 /* Don't use pgd_alloc(), because we want __GFP_REPEAT */
77 new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT);
78 BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));
79 spin_lock(&mm->page_table_lock);
80 70
81 /* 71 pg = pgd_offset(mm, addr);
82 * Because we dropped the lock, we should re-check the 72 pu = pud_alloc(mm, pg, addr);
83 * entry, as somebody else could have populated it..
84 */
85 if (mm->context.huge_pgdir)
86 pgd_free(new);
87 else
88 mm->context.huge_pgdir = new;
89 }
90 return hugepgd_offset(mm, addr);
91}
92 73
93static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr) 74 if (pu) {
94{ 75 pm = pmd_alloc(mm, pu, addr);
95 if (! pud_present(*dir)) { 76 if (pm) {
96 pte_t *new; 77 pt = (pte_t *)pm;
97 78 BUG_ON(!pmd_none(*pm)
98 spin_unlock(&mm->page_table_lock); 79 && !(pte_present(*pt) && pte_huge(*pt)));
99 new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT); 80 return pt;
100 BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));
101 spin_lock(&mm->page_table_lock);
102 /*
103 * Because we dropped the lock, we should re-check the
104 * entry, as somebody else could have populated it..
105 */
106 if (pud_present(*dir)) {
107 if (new)
108 kmem_cache_free(zero_cache, new);
109 } else {
110 struct page *ptepage;
111
112 if (! new)
113 return NULL;
114 ptepage = virt_to_page(new);
115 ptepage->mapping = (void *) mm;
116 ptepage->index = addr & HUGEPGDIR_MASK;
117 pud_populate(mm, dir, new);
118 } 81 }
119 } 82 }
120 83
121 return hugepte_offset(dir, addr); 84 return NULL;
122} 85}
123 86
124pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) 87#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE)
125{
126 pud_t *pud;
127 88
128 BUG_ON(! in_hugepage_area(mm->context, addr)); 89void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
90 pte_t *ptep, pte_t pte)
91{
92 int i;
129 93
130 pud = hugepgd_offset(mm, addr); 94 if (pte_present(*ptep)) {
131 if (! pud) 95 pte_clear(mm, addr, ptep);
132 return NULL; 96 flush_tlb_pending();
97 }
133 98
134 return hugepte_offset(pud, addr); 99 for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) {
100 *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
101 ptep++;
102 }
135} 103}
136 104
137pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) 105pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
106 pte_t *ptep)
138{ 107{
139 pud_t *pud; 108 unsigned long old = pte_update(ptep, ~0UL);
109 int i;
140 110
141 BUG_ON(! in_hugepage_area(mm->context, addr)); 111 if (old & _PAGE_HASHPTE)
112 hpte_update(mm, addr, old, 0);
142 113
143 pud = hugepgd_alloc(mm, addr); 114 for (i = 1; i < HUGEPTE_BATCH_SIZE; i++)
144 if (! pud) 115 ptep[i] = __pte(0);
145 return NULL;
146 116
147 return hugepte_alloc(mm, pud, addr); 117 return __pte(old);
148} 118}
149 119
150/* 120/*
@@ -162,15 +132,17 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
162 return 0; 132 return 0;
163} 133}
164 134
165static void flush_segments(void *parm) 135static void flush_low_segments(void *parm)
166{ 136{
167 u16 segs = (unsigned long) parm; 137 u16 areas = (unsigned long) parm;
168 unsigned long i; 138 unsigned long i;
169 139
170 asm volatile("isync" : : : "memory"); 140 asm volatile("isync" : : : "memory");
171 141
172 for (i = 0; i < 16; i++) { 142 BUILD_BUG_ON((sizeof(areas)*8) != NUM_LOW_AREAS);
173 if (! (segs & (1U << i))) 143
144 for (i = 0; i < NUM_LOW_AREAS; i++) {
145 if (! (areas & (1U << i)))
174 continue; 146 continue;
175 asm volatile("slbie %0" : : "r" (i << SID_SHIFT)); 147 asm volatile("slbie %0" : : "r" (i << SID_SHIFT));
176 } 148 }
@@ -178,13 +150,33 @@ static void flush_segments(void *parm)
178 asm volatile("isync" : : : "memory"); 150 asm volatile("isync" : : : "memory");
179} 151}
180 152
181static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg) 153static void flush_high_segments(void *parm)
182{ 154{
183 unsigned long start = seg << SID_SHIFT; 155 u16 areas = (unsigned long) parm;
184 unsigned long end = (seg+1) << SID_SHIFT; 156 unsigned long i, j;
157
158 asm volatile("isync" : : : "memory");
159
160 BUILD_BUG_ON((sizeof(areas)*8) != NUM_HIGH_AREAS);
161
162 for (i = 0; i < NUM_HIGH_AREAS; i++) {
163 if (! (areas & (1U << i)))
164 continue;
165 for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)
166 asm volatile("slbie %0"
167 :: "r" ((i << HTLB_AREA_SHIFT) + (j << SID_SHIFT)));
168 }
169
170 asm volatile("isync" : : : "memory");
171}
172
173static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)
174{
175 unsigned long start = area << SID_SHIFT;
176 unsigned long end = (area+1) << SID_SHIFT;
185 struct vm_area_struct *vma; 177 struct vm_area_struct *vma;
186 178
187 BUG_ON(seg >= 16); 179 BUG_ON(area >= NUM_LOW_AREAS);
188 180
189 /* Check no VMAs are in the region */ 181 /* Check no VMAs are in the region */
190 vma = find_vma(mm, start); 182 vma = find_vma(mm, start);
@@ -194,20 +186,39 @@ static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg)
194 return 0; 186 return 0;
195} 187}
196 188
197static int open_low_hpage_segs(struct mm_struct *mm, u16 newsegs) 189static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
190{
191 unsigned long start = area << HTLB_AREA_SHIFT;
192 unsigned long end = (area+1) << HTLB_AREA_SHIFT;
193 struct vm_area_struct *vma;
194
195 BUG_ON(area >= NUM_HIGH_AREAS);
196
197 /* Check no VMAs are in the region */
198 vma = find_vma(mm, start);
199 if (vma && (vma->vm_start < end))
200 return -EBUSY;
201
202 return 0;
203}
204
205static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)
198{ 206{
199 unsigned long i; 207 unsigned long i;
200 208
201 newsegs &= ~(mm->context.htlb_segs); 209 BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);
202 if (! newsegs) 210 BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);
211
212 newareas &= ~(mm->context.low_htlb_areas);
213 if (! newareas)
203 return 0; /* The segments we want are already open */ 214 return 0; /* The segments we want are already open */
204 215
205 for (i = 0; i < 16; i++) 216 for (i = 0; i < NUM_LOW_AREAS; i++)
206 if ((1 << i) & newsegs) 217 if ((1 << i) & newareas)
207 if (prepare_low_seg_for_htlb(mm, i) != 0) 218 if (prepare_low_area_for_htlb(mm, i) != 0)
208 return -EBUSY; 219 return -EBUSY;
209 220
210 mm->context.htlb_segs |= newsegs; 221 mm->context.low_htlb_areas |= newareas;
211 222
212 /* update the paca copy of the context struct */ 223 /* update the paca copy of the context struct */
213 get_paca()->context = mm->context; 224 get_paca()->context = mm->context;
@@ -215,29 +226,63 @@ static int open_low_hpage_segs(struct mm_struct *mm, u16 newsegs)
215 /* the context change must make it to memory before the flush, 226 /* the context change must make it to memory before the flush,
216 * so that further SLB misses do the right thing. */ 227 * so that further SLB misses do the right thing. */
217 mb(); 228 mb();
218 on_each_cpu(flush_segments, (void *)(unsigned long)newsegs, 0, 1); 229 on_each_cpu(flush_low_segments, (void *)(unsigned long)newareas, 0, 1);
230
231 return 0;
232}
233
234static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)
235{
236 unsigned long i;
237
238 BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);
239 BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)
240 != NUM_HIGH_AREAS);
241
242 newareas &= ~(mm->context.high_htlb_areas);
243 if (! newareas)
244 return 0; /* The areas we want are already open */
245
246 for (i = 0; i < NUM_HIGH_AREAS; i++)
247 if ((1 << i) & newareas)
248 if (prepare_high_area_for_htlb(mm, i) != 0)
249 return -EBUSY;
250
251 mm->context.high_htlb_areas |= newareas;
252
253 /* update the paca copy of the context struct */
254 get_paca()->context = mm->context;
255
256 /* the context change must make it to memory before the flush,
257 * so that further SLB misses do the right thing. */
258 mb();
259 on_each_cpu(flush_high_segments, (void *)(unsigned long)newareas, 0, 1);
219 260
220 return 0; 261 return 0;
221} 262}
222 263
223int prepare_hugepage_range(unsigned long addr, unsigned long len) 264int prepare_hugepage_range(unsigned long addr, unsigned long len)
224{ 265{
225 if (within_hugepage_high_range(addr, len)) 266 int err;
226 return 0; 267
227 else if ((addr < 0x100000000UL) && ((addr+len) < 0x100000000UL)) { 268 if ( (addr+len) < addr )
228 int err; 269 return -EINVAL;
229 /* Yes, we need both tests, in case addr+len overflows 270
230 * 64-bit arithmetic */ 271 if ((addr + len) < 0x100000000UL)
231 err = open_low_hpage_segs(current->mm, 272 err = open_low_hpage_areas(current->mm,
232 LOW_ESID_MASK(addr, len)); 273 LOW_ESID_MASK(addr, len));
233 if (err) 274 else
234 printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)" 275 err = open_high_hpage_areas(current->mm,
235 " failed (segs: 0x%04hx)\n", addr, len, 276 HTLB_AREA_MASK(addr, len));
236 LOW_ESID_MASK(addr, len)); 277 if (err) {
278 printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"
279 " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n",
280 addr, len,
281 LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len));
237 return err; 282 return err;
238 } 283 }
239 284
240 return -EINVAL; 285 return 0;
241} 286}
242 287
243struct page * 288struct page *
@@ -309,8 +354,8 @@ full_search:
309 vma = find_vma(mm, addr); 354 vma = find_vma(mm, addr);
310 continue; 355 continue;
311 } 356 }
312 if (touches_hugepage_high_range(addr, len)) { 357 if (touches_hugepage_high_range(mm, addr, len)) {
313 addr = TASK_HPAGE_END; 358 addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
314 vma = find_vma(mm, addr); 359 vma = find_vma(mm, addr);
315 continue; 360 continue;
316 } 361 }
@@ -389,8 +434,9 @@ hugepage_recheck:
389 if (touches_hugepage_low_range(mm, addr, len)) { 434 if (touches_hugepage_low_range(mm, addr, len)) {
390 addr = (addr & ((~0) << SID_SHIFT)) - len; 435 addr = (addr & ((~0) << SID_SHIFT)) - len;
391 goto hugepage_recheck; 436 goto hugepage_recheck;
392 } else if (touches_hugepage_high_range(addr, len)) { 437 } else if (touches_hugepage_high_range(mm, addr, len)) {
393 addr = TASK_HPAGE_BASE - len; 438 addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len;
439 goto hugepage_recheck;
394 } 440 }
395 441
396 /* 442 /*
@@ -481,23 +527,28 @@ static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
481 return -ENOMEM; 527 return -ENOMEM;
482} 528}
483 529
484static unsigned long htlb_get_high_area(unsigned long len) 530static unsigned long htlb_get_high_area(unsigned long len, u16 areamask)
485{ 531{
486 unsigned long addr = TASK_HPAGE_BASE; 532 unsigned long addr = 0x100000000UL;
487 struct vm_area_struct *vma; 533 struct vm_area_struct *vma;
488 534
489 vma = find_vma(current->mm, addr); 535 vma = find_vma(current->mm, addr);
490 for (vma = find_vma(current->mm, addr); 536 while (addr + len <= TASK_SIZE_USER64) {
491 addr + len <= TASK_HPAGE_END;
492 vma = vma->vm_next) {
493 BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */ 537 BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
494 BUG_ON(! within_hugepage_high_range(addr, len)); 538
539 if (! __within_hugepage_high_range(addr, len, areamask)) {
540 addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
541 vma = find_vma(current->mm, addr);
542 continue;
543 }
495 544
496 if (!vma || (addr + len) <= vma->vm_start) 545 if (!vma || (addr + len) <= vma->vm_start)
497 return addr; 546 return addr;
498 addr = ALIGN(vma->vm_end, HPAGE_SIZE); 547 addr = ALIGN(vma->vm_end, HPAGE_SIZE);
499 /* Because we're in a hugepage region, this alignment 548 /* Depending on segmask this might not be a confirmed
500 * should not skip us over any VMAs */ 549 * hugepage region, so the ALIGN could have skipped
550 * some VMAs */
551 vma = find_vma(current->mm, addr);
501 } 552 }
502 553
503 return -ENOMEM; 554 return -ENOMEM;
@@ -507,6 +558,9 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
507 unsigned long len, unsigned long pgoff, 558 unsigned long len, unsigned long pgoff,
508 unsigned long flags) 559 unsigned long flags)
509{ 560{
561 int lastshift;
562 u16 areamask, curareas;
563
510 if (len & ~HPAGE_MASK) 564 if (len & ~HPAGE_MASK)
511 return -EINVAL; 565 return -EINVAL;
512 566
@@ -514,67 +568,49 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
514 return -EINVAL; 568 return -EINVAL;
515 569
516 if (test_thread_flag(TIF_32BIT)) { 570 if (test_thread_flag(TIF_32BIT)) {
517 int lastshift = 0; 571 curareas = current->mm->context.low_htlb_areas;
518 u16 segmask, cursegs = current->mm->context.htlb_segs;
519 572
520 /* First see if we can do the mapping in the existing 573 /* First see if we can do the mapping in the existing
521 * low hpage segments */ 574 * low areas */
522 addr = htlb_get_low_area(len, cursegs); 575 addr = htlb_get_low_area(len, curareas);
523 if (addr != -ENOMEM) 576 if (addr != -ENOMEM)
524 return addr; 577 return addr;
525 578
526 for (segmask = LOW_ESID_MASK(0x100000000UL-len, len); 579 lastshift = 0;
527 ! lastshift; segmask >>=1) { 580 for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
528 if (segmask & 1) 581 ! lastshift; areamask >>=1) {
582 if (areamask & 1)
529 lastshift = 1; 583 lastshift = 1;
530 584
531 addr = htlb_get_low_area(len, cursegs | segmask); 585 addr = htlb_get_low_area(len, curareas | areamask);
532 if ((addr != -ENOMEM) 586 if ((addr != -ENOMEM)
533 && open_low_hpage_segs(current->mm, segmask) == 0) 587 && open_low_hpage_areas(current->mm, areamask) == 0)
534 return addr; 588 return addr;
535 } 589 }
536 printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
537 " enough segments\n");
538 return -ENOMEM;
539 } else { 590 } else {
540 return htlb_get_high_area(len); 591 curareas = current->mm->context.high_htlb_areas;
541 }
542}
543
544void hugetlb_mm_free_pgd(struct mm_struct *mm)
545{
546 int i;
547 pgd_t *pgdir;
548
549 spin_lock(&mm->page_table_lock);
550
551 pgdir = mm->context.huge_pgdir;
552 if (! pgdir)
553 goto out;
554
555 mm->context.huge_pgdir = NULL;
556 592
557 /* cleanup any hugepte pages leftover */ 593 /* First see if we can do the mapping in the existing
558 for (i = 0; i < PTRS_PER_HUGEPGD; i++) { 594 * high areas */
559 pud_t *pud = (pud_t *)(pgdir + i); 595 addr = htlb_get_high_area(len, curareas);
560 596 if (addr != -ENOMEM)
561 if (! pud_none(*pud)) { 597 return addr;
562 pte_t *pte = (pte_t *)pud_page(*pud);
563 struct page *ptepage = virt_to_page(pte);
564 598
565 ptepage->mapping = NULL; 599 lastshift = 0;
600 for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
601 ! lastshift; areamask >>=1) {
602 if (areamask & 1)
603 lastshift = 1;
566 604
567 BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE)); 605 addr = htlb_get_high_area(len, curareas | areamask);
568 kmem_cache_free(zero_cache, pte); 606 if ((addr != -ENOMEM)
607 && open_high_hpage_areas(current->mm, areamask) == 0)
608 return addr;
569 } 609 }
570 pud_clear(pud);
571 } 610 }
572 611 printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
573 BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE)); 612 " enough areas\n");
574 kmem_cache_free(zero_cache, pgdir); 613 return -ENOMEM;
575
576 out:
577 spin_unlock(&mm->page_table_lock);
578} 614}
579 615
580int hash_huge_page(struct mm_struct *mm, unsigned long access, 616int hash_huge_page(struct mm_struct *mm, unsigned long access,
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index b6e75b891ac0..c65b87b92756 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -31,7 +31,7 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
31 break; 31 break;
32 if ((unsigned long)tmp->addr >= ioremap_bot) 32 if ((unsigned long)tmp->addr >= ioremap_bot)
33 addr = tmp->size + (unsigned long) tmp->addr; 33 addr = tmp->size + (unsigned long) tmp->addr;
34 if (addr > IMALLOC_END-size) 34 if (addr >= IMALLOC_END-size)
35 return 1; 35 return 1;
36 } 36 }
37 *im_addr = addr; 37 *im_addr = addr;
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index e58a24d42879..c02dc9809ca5 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -42,7 +42,6 @@
42 42
43#include <asm/pgalloc.h> 43#include <asm/pgalloc.h>
44#include <asm/page.h> 44#include <asm/page.h>
45#include <asm/abs_addr.h>
46#include <asm/prom.h> 45#include <asm/prom.h>
47#include <asm/lmb.h> 46#include <asm/lmb.h>
48#include <asm/rtas.h> 47#include <asm/rtas.h>
@@ -66,6 +65,14 @@
66#include <asm/vdso.h> 65#include <asm/vdso.h>
67#include <asm/imalloc.h> 66#include <asm/imalloc.h>
68 67
68#if PGTABLE_RANGE > USER_VSID_RANGE
69#warning Limited user VSID range means pagetable space is wasted
70#endif
71
72#if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
73#warning TASK_SIZE is smaller than it needs to be.
74#endif
75
69int mem_init_done; 76int mem_init_done;
70unsigned long ioremap_bot = IMALLOC_BASE; 77unsigned long ioremap_bot = IMALLOC_BASE;
71static unsigned long phbs_io_bot = PHBS_IO_BASE; 78static unsigned long phbs_io_bot = PHBS_IO_BASE;
@@ -159,7 +166,6 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
159 ptep = pte_alloc_kernel(&init_mm, pmdp, ea); 166 ptep = pte_alloc_kernel(&init_mm, pmdp, ea);
160 if (!ptep) 167 if (!ptep)
161 return -ENOMEM; 168 return -ENOMEM;
162 pa = abs_to_phys(pa);
163 set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, 169 set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
164 __pgprot(flags))); 170 __pgprot(flags)));
165 spin_unlock(&init_mm.page_table_lock); 171 spin_unlock(&init_mm.page_table_lock);
@@ -226,7 +232,7 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size,
226 * Before that, we map using addresses going 232 * Before that, we map using addresses going
227 * up from ioremap_bot. imalloc will use 233 * up from ioremap_bot. imalloc will use
228 * the addresses from ioremap_bot through 234 * the addresses from ioremap_bot through
229 * IMALLOC_END (0xE000001fffffffff) 235 * IMALLOC_END
230 * 236 *
231 */ 237 */
232 pa = addr & PAGE_MASK; 238 pa = addr & PAGE_MASK;
@@ -417,12 +423,6 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
417 int index; 423 int index;
418 int err; 424 int err;
419 425
420#ifdef CONFIG_HUGETLB_PAGE
421 /* We leave htlb_segs as it was, but for a fork, we need to
422 * clear the huge_pgdir. */
423 mm->context.huge_pgdir = NULL;
424#endif
425
426again: 426again:
427 if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL)) 427 if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
428 return -ENOMEM; 428 return -ENOMEM;
@@ -453,8 +453,6 @@ void destroy_context(struct mm_struct *mm)
453 spin_unlock(&mmu_context_lock); 453 spin_unlock(&mmu_context_lock);
454 454
455 mm->context.id = NO_CONTEXT; 455 mm->context.id = NO_CONTEXT;
456
457 hugetlb_mm_free_pgd(mm);
458} 456}
459 457
460/* 458/*
@@ -484,9 +482,9 @@ void __init mm_init_ppc64(void)
484 for (i = 1; i < lmb.memory.cnt; i++) { 482 for (i = 1; i < lmb.memory.cnt; i++) {
485 unsigned long base, prevbase, prevsize; 483 unsigned long base, prevbase, prevsize;
486 484
487 prevbase = lmb.memory.region[i-1].physbase; 485 prevbase = lmb.memory.region[i-1].base;
488 prevsize = lmb.memory.region[i-1].size; 486 prevsize = lmb.memory.region[i-1].size;
489 base = lmb.memory.region[i].physbase; 487 base = lmb.memory.region[i].base;
490 if (base > (prevbase + prevsize)) { 488 if (base > (prevbase + prevsize)) {
491 io_hole_start = prevbase + prevsize; 489 io_hole_start = prevbase + prevsize;
492 io_hole_size = base - (prevbase + prevsize); 490 io_hole_size = base - (prevbase + prevsize);
@@ -513,11 +511,8 @@ int page_is_ram(unsigned long pfn)
513 for (i=0; i < lmb.memory.cnt; i++) { 511 for (i=0; i < lmb.memory.cnt; i++) {
514 unsigned long base; 512 unsigned long base;
515 513
516#ifdef CONFIG_MSCHUNKS
517 base = lmb.memory.region[i].physbase;
518#else
519 base = lmb.memory.region[i].base; 514 base = lmb.memory.region[i].base;
520#endif 515
521 if ((paddr >= base) && 516 if ((paddr >= base) &&
522 (paddr < (base + lmb.memory.region[i].size))) { 517 (paddr < (base + lmb.memory.region[i].size))) {
523 return 1; 518 return 1;
@@ -547,7 +542,7 @@ void __init do_init_bootmem(void)
547 */ 542 */
548 bootmap_pages = bootmem_bootmap_pages(total_pages); 543 bootmap_pages = bootmem_bootmap_pages(total_pages);
549 544
550 start = abs_to_phys(lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE)); 545 start = lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
551 BUG_ON(!start); 546 BUG_ON(!start);
552 547
553 boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); 548 boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
@@ -558,25 +553,25 @@ void __init do_init_bootmem(void)
558 * present. 553 * present.
559 */ 554 */
560 for (i=0; i < lmb.memory.cnt; i++) { 555 for (i=0; i < lmb.memory.cnt; i++) {
561 unsigned long physbase, size; 556 unsigned long base, size;
562 unsigned long start_pfn, end_pfn; 557 unsigned long start_pfn, end_pfn;
563 558
564 physbase = lmb.memory.region[i].physbase; 559 base = lmb.memory.region[i].base;
565 size = lmb.memory.region[i].size; 560 size = lmb.memory.region[i].size;
566 561
567 start_pfn = physbase >> PAGE_SHIFT; 562 start_pfn = base >> PAGE_SHIFT;
568 end_pfn = start_pfn + (size >> PAGE_SHIFT); 563 end_pfn = start_pfn + (size >> PAGE_SHIFT);
569 memory_present(0, start_pfn, end_pfn); 564 memory_present(0, start_pfn, end_pfn);
570 565
571 free_bootmem(physbase, size); 566 free_bootmem(base, size);
572 } 567 }
573 568
574 /* reserve the sections we're already using */ 569 /* reserve the sections we're already using */
575 for (i=0; i < lmb.reserved.cnt; i++) { 570 for (i=0; i < lmb.reserved.cnt; i++) {
576 unsigned long physbase = lmb.reserved.region[i].physbase; 571 unsigned long base = lmb.reserved.region[i].base;
577 unsigned long size = lmb.reserved.region[i].size; 572 unsigned long size = lmb.reserved.region[i].size;
578 573
579 reserve_bootmem(physbase, size); 574 reserve_bootmem(base, size);
580 } 575 }
581} 576}
582 577
@@ -615,10 +610,10 @@ static int __init setup_kcore(void)
615 int i; 610 int i;
616 611
617 for (i=0; i < lmb.memory.cnt; i++) { 612 for (i=0; i < lmb.memory.cnt; i++) {
618 unsigned long physbase, size; 613 unsigned long base, size;
619 struct kcore_list *kcore_mem; 614 struct kcore_list *kcore_mem;
620 615
621 physbase = lmb.memory.region[i].physbase; 616 base = lmb.memory.region[i].base;
622 size = lmb.memory.region[i].size; 617 size = lmb.memory.region[i].size;
623 618
624 /* GFP_ATOMIC to avoid might_sleep warnings during boot */ 619 /* GFP_ATOMIC to avoid might_sleep warnings during boot */
@@ -626,7 +621,7 @@ static int __init setup_kcore(void)
626 if (!kcore_mem) 621 if (!kcore_mem)
627 panic("mem_init: kmalloc failed\n"); 622 panic("mem_init: kmalloc failed\n");
628 623
629 kclist_add(kcore_mem, __va(physbase), size); 624 kclist_add(kcore_mem, __va(base), size);
630 } 625 }
631 626
632 kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); 627 kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START);
@@ -686,9 +681,6 @@ void __init mem_init(void)
686 681
687 mem_init_done = 1; 682 mem_init_done = 1;
688 683
689#ifdef CONFIG_PPC_ISERIES
690 iommu_vio_init();
691#endif
692 /* Initialize the vDSO */ 684 /* Initialize the vDSO */
693 vdso_init(); 685 vdso_init();
694} 686}
@@ -833,23 +825,43 @@ void __iomem * reserve_phb_iospace(unsigned long size)
833 return virt_addr; 825 return virt_addr;
834} 826}
835 827
836kmem_cache_t *zero_cache; 828static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
837
838static void zero_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
839{ 829{
840 memset(pte, 0, PAGE_SIZE); 830 memset(addr, 0, kmem_cache_size(cache));
841} 831}
842 832
833static const int pgtable_cache_size[2] = {
834 PTE_TABLE_SIZE, PMD_TABLE_SIZE
835};
836static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
837 "pgd_pte_cache", "pud_pmd_cache",
838};
839
840kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
841
843void pgtable_cache_init(void) 842void pgtable_cache_init(void)
844{ 843{
845 zero_cache = kmem_cache_create("zero", 844 int i;
846 PAGE_SIZE, 845
847 0, 846 BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]);
848 SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, 847 BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]);
849 zero_ctor, 848 BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]);
850 NULL); 849 BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]);
851 if (!zero_cache) 850
852 panic("pgtable_cache_init(): could not create zero_cache!\n"); 851 for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) {
852 int size = pgtable_cache_size[i];
853 const char *name = pgtable_cache_name[i];
854
855 pgtable_cache[i] = kmem_cache_create(name,
856 size, size,
857 SLAB_HWCACHE_ALIGN
858 | SLAB_MUST_HWCACHE_ALIGN,
859 zero_ctor,
860 NULL);
861 if (! pgtable_cache[i])
862 panic("pgtable_cache_init(): could not create %s!\n",
863 name);
864 }
853} 865}
854 866
855pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, 867pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index 0b191f2de016..c3116f0d788c 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -671,7 +671,7 @@ new_range:
671 * Mark reserved regions on this node 671 * Mark reserved regions on this node
672 */ 672 */
673 for (i = 0; i < lmb.reserved.cnt; i++) { 673 for (i = 0; i < lmb.reserved.cnt; i++) {
674 unsigned long physbase = lmb.reserved.region[i].physbase; 674 unsigned long physbase = lmb.reserved.region[i].base;
675 unsigned long size = lmb.reserved.region[i].size; 675 unsigned long size = lmb.reserved.region[i].size;
676 676
677 if (pa_to_nid(physbase) != nid && 677 if (pa_to_nid(physbase) != nid &&
diff --git a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S
index 8379d678f70f..bab255889c58 100644
--- a/arch/ppc64/mm/slb_low.S
+++ b/arch/ppc64/mm/slb_low.S
@@ -89,28 +89,29 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
89 b 9f 89 b 9f
90 90
910: /* user address: proto-VSID = context<<15 | ESID */ 910: /* user address: proto-VSID = context<<15 | ESID */
92 li r11,SLB_VSID_USER 92 srdi. r9,r3,USER_ESID_BITS
93
94 srdi. r9,r3,13
95 bne- 8f /* invalid ea bits set */ 93 bne- 8f /* invalid ea bits set */
96 94
97#ifdef CONFIG_HUGETLB_PAGE 95#ifdef CONFIG_HUGETLB_PAGE
98BEGIN_FTR_SECTION 96BEGIN_FTR_SECTION
99 /* check against the hugepage ranges */ 97 lhz r9,PACAHIGHHTLBAREAS(r13)
100 cmpldi r3,(TASK_HPAGE_END>>SID_SHIFT) 98 srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT)
101 bge 6f /* >= TASK_HPAGE_END */ 99 srd r9,r9,r11
102 cmpldi r3,(TASK_HPAGE_BASE>>SID_SHIFT) 100 andi. r9,r9,1
103 bge 5f /* TASK_HPAGE_BASE..TASK_HPAGE_END */ 101 bne 5f
102
103 li r11,SLB_VSID_USER
104
104 cmpldi r3,16 105 cmpldi r3,16
105 bge 6f /* 4GB..TASK_HPAGE_BASE */ 106 bge 6f
106 107
107 lhz r9,PACAHTLBSEGS(r13) 108 lhz r9,PACALOWHTLBAREAS(r13)
108 srd r9,r9,r3 109 srd r9,r9,r3
109 andi. r9,r9,1 110 andi. r9,r9,1
111
110 beq 6f 112 beq 6f
111 113
1125: /* this is a hugepage user address */ 1145: li r11,SLB_VSID_USER|SLB_VSID_L
113 li r11,(SLB_VSID_USER|SLB_VSID_L)
114END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) 115END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
115#endif /* CONFIG_HUGETLB_PAGE */ 116#endif /* CONFIG_HUGETLB_PAGE */
116 117
diff --git a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
index 26f0172c4527..d8a6593a13f0 100644
--- a/arch/ppc64/mm/tlb.c
+++ b/arch/ppc64/mm/tlb.c
@@ -41,7 +41,58 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
41DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); 41DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
42unsigned long pte_freelist_forced_free; 42unsigned long pte_freelist_forced_free;
43 43
44void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage) 44struct pte_freelist_batch
45{
46 struct rcu_head rcu;
47 unsigned int index;
48 pgtable_free_t tables[0];
49};
50
51DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
52unsigned long pte_freelist_forced_free;
53
54#define PTE_FREELIST_SIZE \
55 ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
56 / sizeof(pgtable_free_t))
57
58#ifdef CONFIG_SMP
59static void pte_free_smp_sync(void *arg)
60{
61 /* Do nothing, just ensure we sync with all CPUs */
62}
63#endif
64
65/* This is only called when we are critically out of memory
66 * (and fail to get a page in pte_free_tlb).
67 */
68static void pgtable_free_now(pgtable_free_t pgf)
69{
70 pte_freelist_forced_free++;
71
72 smp_call_function(pte_free_smp_sync, NULL, 0, 1);
73
74 pgtable_free(pgf);
75}
76
77static void pte_free_rcu_callback(struct rcu_head *head)
78{
79 struct pte_freelist_batch *batch =
80 container_of(head, struct pte_freelist_batch, rcu);
81 unsigned int i;
82
83 for (i = 0; i < batch->index; i++)
84 pgtable_free(batch->tables[i]);
85
86 free_page((unsigned long)batch);
87}
88
89static void pte_free_submit(struct pte_freelist_batch *batch)
90{
91 INIT_RCU_HEAD(&batch->rcu);
92 call_rcu(&batch->rcu, pte_free_rcu_callback);
93}
94
95void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
45{ 96{
46 /* This is safe as we are holding page_table_lock */ 97 /* This is safe as we are holding page_table_lock */
47 cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id()); 98 cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
@@ -49,19 +100,19 @@ void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage)
49 100
50 if (atomic_read(&tlb->mm->mm_users) < 2 || 101 if (atomic_read(&tlb->mm->mm_users) < 2 ||
51 cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) { 102 cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
52 pte_free(ptepage); 103 pgtable_free(pgf);
53 return; 104 return;
54 } 105 }
55 106
56 if (*batchp == NULL) { 107 if (*batchp == NULL) {
57 *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); 108 *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
58 if (*batchp == NULL) { 109 if (*batchp == NULL) {
59 pte_free_now(ptepage); 110 pgtable_free_now(pgf);
60 return; 111 return;
61 } 112 }
62 (*batchp)->index = 0; 113 (*batchp)->index = 0;
63 } 114 }
64 (*batchp)->pages[(*batchp)->index++] = ptepage; 115 (*batchp)->tables[(*batchp)->index++] = pgf;
65 if ((*batchp)->index == PTE_FREELIST_SIZE) { 116 if ((*batchp)->index == PTE_FREELIST_SIZE) {
66 pte_free_submit(*batchp); 117 pte_free_submit(*batchp);
67 *batchp = NULL; 118 *batchp = NULL;
@@ -132,42 +183,6 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
132 put_cpu(); 183 put_cpu();
133} 184}
134 185
135#ifdef CONFIG_SMP
136static void pte_free_smp_sync(void *arg)
137{
138 /* Do nothing, just ensure we sync with all CPUs */
139}
140#endif
141
142/* This is only called when we are critically out of memory
143 * (and fail to get a page in pte_free_tlb).
144 */
145void pte_free_now(struct page *ptepage)
146{
147 pte_freelist_forced_free++;
148
149 smp_call_function(pte_free_smp_sync, NULL, 0, 1);
150
151 pte_free(ptepage);
152}
153
154static void pte_free_rcu_callback(struct rcu_head *head)
155{
156 struct pte_freelist_batch *batch =
157 container_of(head, struct pte_freelist_batch, rcu);
158 unsigned int i;
159
160 for (i = 0; i < batch->index; i++)
161 pte_free(batch->pages[i]);
162 free_page((unsigned long)batch);
163}
164
165void pte_free_submit(struct pte_freelist_batch *batch)
166{
167 INIT_RCU_HEAD(&batch->rcu);
168 call_rcu(&batch->rcu, pte_free_rcu_callback);
169}
170
171void pte_free_finish(void) 186void pte_free_finish(void)
172{ 187{
173 /* This is safe as we are holding page_table_lock */ 188 /* This is safe as we are holding page_table_lock */
diff --git a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c
index a9265bcc79b2..f86b584acd76 100644
--- a/arch/ppc64/xmon/start.c
+++ b/arch/ppc64/xmon/start.c
@@ -27,7 +27,7 @@ static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
27 struct tty_struct *tty) 27 struct tty_struct *tty)
28{ 28{
29 /* ensure xmon is enabled */ 29 /* ensure xmon is enabled */
30 xmon_init(); 30 xmon_init(1);
31 debugger(pt_regs); 31 debugger(pt_regs);
32} 32}
33 33
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index 05539439e6bc..45908b10acd3 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -2496,15 +2496,25 @@ static void dump_stab(void)
2496 } 2496 }
2497} 2497}
2498 2498
2499void xmon_init(void) 2499void xmon_init(int enable)
2500{ 2500{
2501 __debugger = xmon; 2501 if (enable) {
2502 __debugger_ipi = xmon_ipi; 2502 __debugger = xmon;
2503 __debugger_bpt = xmon_bpt; 2503 __debugger_ipi = xmon_ipi;
2504 __debugger_sstep = xmon_sstep; 2504 __debugger_bpt = xmon_bpt;
2505 __debugger_iabr_match = xmon_iabr_match; 2505 __debugger_sstep = xmon_sstep;
2506 __debugger_dabr_match = xmon_dabr_match; 2506 __debugger_iabr_match = xmon_iabr_match;
2507 __debugger_fault_handler = xmon_fault_handler; 2507 __debugger_dabr_match = xmon_dabr_match;
2508 __debugger_fault_handler = xmon_fault_handler;
2509 } else {
2510 __debugger = NULL;
2511 __debugger_ipi = NULL;
2512 __debugger_bpt = NULL;
2513 __debugger_sstep = NULL;
2514 __debugger_iabr_match = NULL;
2515 __debugger_dabr_match = NULL;
2516 __debugger_fault_handler = NULL;
2517 }
2508} 2518}
2509 2519
2510void dump_segments(void) 2520void dump_segments(void)