aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/Makefile13
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kernel/cpu_setup_power4.S233
-rw-r--r--arch/powerpc/kernel/cputable.c19
-rw-r--r--arch/powerpc/kernel/firmware.c45
-rw-r--r--arch/powerpc/kernel/fpu.S24
-rw-r--r--arch/powerpc/kernel/head_64.S91
-rw-r--r--arch/powerpc/kernel/ioctl32.c49
-rw-r--r--arch/powerpc/kernel/irq.c478
-rw-r--r--arch/powerpc/kernel/lparcfg.c612
-rw-r--r--arch/powerpc/kernel/misc_32.S23
-rw-r--r--arch/powerpc/kernel/misc_64.S8
-rw-r--r--arch/powerpc/kernel/paca.c142
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c5
-rw-r--r--arch/powerpc/kernel/proc_ppc64.c126
-rw-r--r--arch/powerpc/kernel/prom.c35
-rw-r--r--arch/powerpc/kernel/prom_init.c187
-rw-r--r--arch/powerpc/kernel/rtas-proc.c2
-rw-r--r--arch/powerpc/kernel/rtas.c5
-rw-r--r--arch/powerpc/kernel/rtas_pci.c513
-rw-r--r--arch/powerpc/kernel/setup-common.c37
-rw-r--r--arch/powerpc/kernel/setup.h6
-rw-r--r--arch/powerpc/kernel/setup_32.c18
-rw-r--r--arch/powerpc/kernel/setup_64.c93
-rw-r--r--arch/powerpc/kernel/signal_32.c1
-rw-r--r--arch/powerpc/kernel/smp.c9
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c1
-rw-r--r--arch/powerpc/kernel/sysfs.c384
-rw-r--r--arch/powerpc/kernel/time.c31
-rw-r--r--arch/powerpc/kernel/traps.c2
30 files changed, 2900 insertions, 293 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index b3ae2993efb8..c04bbd320594 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -4,6 +4,7 @@
4 4
5ifeq ($(CONFIG_PPC64),y) 5ifeq ($(CONFIG_PPC64),y)
6EXTRA_CFLAGS += -mno-minimal-toc 6EXTRA_CFLAGS += -mno-minimal-toc
7CFLAGS_ioctl32.o += -Ifs/
7endif 8endif
8ifeq ($(CONFIG_PPC32),y) 9ifeq ($(CONFIG_PPC32),y)
9CFLAGS_prom_init.o += -fPIC 10CFLAGS_prom_init.o += -fPIC
@@ -11,15 +12,21 @@ CFLAGS_btext.o += -fPIC
11endif 12endif
12 13
13obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ 14obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
14 signal_32.o pmc.o 15 irq.o signal_32.o pmc.o
15obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ 16obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
16 signal_64.o ptrace32.o systbl.o 17 signal_64.o ptrace32.o systbl.o \
18 paca.o ioctl32.o cpu_setup_power4.o \
19 firmware.o sysfs.o
17obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o 20obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
18obj-$(CONFIG_POWER4) += idle_power4.o 21obj-$(CONFIG_POWER4) += idle_power4.o
19obj-$(CONFIG_PPC_OF) += of_device.o 22obj-$(CONFIG_PPC_OF) += of_device.o
20obj-$(CONFIG_PPC_RTAS) += rtas.o 23procfs-$(CONFIG_PPC64) := proc_ppc64.o
24obj-$(CONFIG_PROC_FS) += $(procfs-y)
25rtaspci-$(CONFIG_PPC64) := rtas_pci.o
26obj-$(CONFIG_PPC_RTAS) += rtas.o $(rtaspci-y)
21obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o 27obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
22obj-$(CONFIG_RTAS_PROC) += rtas-proc.o 28obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
29obj-$(CONFIG_LPARCFG) += lparcfg.o
23obj-$(CONFIG_IBMVIO) += vio.o 30obj-$(CONFIG_IBMVIO) += vio.o
24obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 31obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
25 32
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index b75757251994..8793102711a8 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -106,7 +106,6 @@ int main(void)
106 DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); 106 DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size));
107 DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); 107 DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
108 DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); 108 DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
109 DEFINE(PLATFORM, offsetof(struct systemcfg, platform));
110 DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); 109 DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
111 110
112 /* paca */ 111 /* paca */
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S
new file mode 100644
index 000000000000..cca942fe6115
--- /dev/null
+++ b/arch/powerpc/kernel/cpu_setup_power4.S
@@ -0,0 +1,233 @@
1/*
2 * This file contains low level CPU setup functions.
3 * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 */
11
12#include <linux/config.h>
13#include <asm/processor.h>
14#include <asm/page.h>
15#include <asm/cputable.h>
16#include <asm/ppc_asm.h>
17#include <asm/asm-offsets.h>
18#include <asm/cache.h>
19
20_GLOBAL(__970_cpu_preinit)
21 /*
22 * Do nothing if not running in HV mode
23 */
24 mfmsr r0
25 rldicl. r0,r0,4,63
26 beqlr
27
28 /*
29 * Deal only with PPC970 and PPC970FX.
30 */
31 mfspr r0,SPRN_PVR
32 srwi r0,r0,16
33 cmpwi r0,0x39
34 beq 1f
35 cmpwi r0,0x3c
36 beq 1f
37 cmpwi r0,0x44
38 bnelr
391:
40
41 /* Make sure HID4:rm_ci is off before MMU is turned off, that large
42 * pages are enabled with HID4:61 and clear HID5:DCBZ_size and
43 * HID5:DCBZ32_ill
44 */
45 li r0,0
46 mfspr r3,SPRN_HID4
47 rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */
48 rldimi r3,r0,2,61 /* clear bit 61 (lg_pg_en) */
49 sync
50 mtspr SPRN_HID4,r3
51 isync
52 sync
53 mfspr r3,SPRN_HID5
54 rldimi r3,r0,6,56 /* clear bits 56 & 57 (DCBZ*) */
55 sync
56 mtspr SPRN_HID5,r3
57 isync
58 sync
59
60 /* Setup some basic HID1 features */
61 mfspr r0,SPRN_HID1
62 li r3,0x1200 /* enable i-fetch cacheability */
63 sldi r3,r3,44 /* and prefetch */
64 or r0,r0,r3
65 mtspr SPRN_HID1,r0
66 mtspr SPRN_HID1,r0
67 isync
68
69 /* Clear HIOR */
70 li r0,0
71 sync
72 mtspr SPRN_HIOR,0 /* Clear interrupt prefix */
73 isync
74 blr
75
76_GLOBAL(__setup_cpu_power4)
77 blr
78
79_GLOBAL(__setup_cpu_be)
80 /* Set large page sizes LP=0: 16MB, LP=1: 64KB */
81 addi r3, 0, 0
82 ori r3, r3, HID6_LB
83 sldi r3, r3, 32
84 nor r3, r3, r3
85 mfspr r4, SPRN_HID6
86 and r4, r4, r3
87 addi r3, 0, 0x02000
88 sldi r3, r3, 32
89 or r4, r4, r3
90 mtspr SPRN_HID6, r4
91 blr
92
93_GLOBAL(__setup_cpu_ppc970)
94 mfspr r0,SPRN_HID0
95 li r11,5 /* clear DOZE and SLEEP */
96 rldimi r0,r11,52,8 /* set NAP and DPM */
97 mtspr SPRN_HID0,r0
98 mfspr r0,SPRN_HID0
99 mfspr r0,SPRN_HID0
100 mfspr r0,SPRN_HID0
101 mfspr r0,SPRN_HID0
102 mfspr r0,SPRN_HID0
103 mfspr r0,SPRN_HID0
104 sync
105 isync
106 blr
107
108/* Definitions for the table use to save CPU states */
109#define CS_HID0 0
110#define CS_HID1 8
111#define CS_HID4 16
112#define CS_HID5 24
113#define CS_SIZE 32
114
115 .data
116 .balign L1_CACHE_BYTES,0
117cpu_state_storage:
118 .space CS_SIZE
119 .balign L1_CACHE_BYTES,0
120 .text
121
122/* Called in normal context to backup CPU 0 state. This
123 * does not include cache settings. This function is also
124 * called for machine sleep. This does not include the MMU
125 * setup, BATs, etc... but rather the "special" registers
126 * like HID0, HID1, HID4, etc...
127 */
128_GLOBAL(__save_cpu_setup)
129 /* Some CR fields are volatile, we back it up all */
130 mfcr r7
131
132 /* Get storage ptr */
133 LOADADDR(r5,cpu_state_storage)
134
135 /* We only deal with 970 for now */
136 mfspr r0,SPRN_PVR
137 srwi r0,r0,16
138 cmpwi r0,0x39
139 beq 1f
140 cmpwi r0,0x3c
141 beq 1f
142 cmpwi r0,0x44
143 bne 2f
144
1451: /* Save HID0,1,4 and 5 */
146 mfspr r3,SPRN_HID0
147 std r3,CS_HID0(r5)
148 mfspr r3,SPRN_HID1
149 std r3,CS_HID1(r5)
150 mfspr r3,SPRN_HID4
151 std r3,CS_HID4(r5)
152 mfspr r3,SPRN_HID5
153 std r3,CS_HID5(r5)
154
1552:
156 mtcr r7
157 blr
158
159/* Called with no MMU context (typically MSR:IR/DR off) to
160 * restore CPU state as backed up by the previous
161 * function. This does not include cache setting
162 */
163_GLOBAL(__restore_cpu_setup)
164 /* Get storage ptr (FIXME when using anton reloc as we
165 * are running with translation disabled here
166 */
167 LOADADDR(r5,cpu_state_storage)
168
169 /* We only deal with 970 for now */
170 mfspr r0,SPRN_PVR
171 srwi r0,r0,16
172 cmpwi r0,0x39
173 beq 1f
174 cmpwi r0,0x3c
175 beq 1f
176 cmpwi r0,0x44
177 bnelr
178
1791: /* Before accessing memory, we make sure rm_ci is clear */
180 li r0,0
181 mfspr r3,SPRN_HID4
182 rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */
183 sync
184 mtspr SPRN_HID4,r3
185 isync
186 sync
187
188 /* Clear interrupt prefix */
189 li r0,0
190 sync
191 mtspr SPRN_HIOR,0
192 isync
193
194 /* Restore HID0 */
195 ld r3,CS_HID0(r5)
196 sync
197 isync
198 mtspr SPRN_HID0,r3
199 mfspr r3,SPRN_HID0
200 mfspr r3,SPRN_HID0
201 mfspr r3,SPRN_HID0
202 mfspr r3,SPRN_HID0
203 mfspr r3,SPRN_HID0
204 mfspr r3,SPRN_HID0
205 sync
206 isync
207
208 /* Restore HID1 */
209 ld r3,CS_HID1(r5)
210 sync
211 isync
212 mtspr SPRN_HID1,r3
213 mtspr SPRN_HID1,r3
214 sync
215 isync
216
217 /* Restore HID4 */
218 ld r3,CS_HID4(r5)
219 sync
220 isync
221 mtspr SPRN_HID4,r3
222 sync
223 isync
224
225 /* Restore HID5 */
226 ld r3,CS_HID5(r5)
227 sync
228 isync
229 mtspr SPRN_HID5,r3
230 sync
231 isync
232 blr
233
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index cc4e9eb1c13f..1d85cedbbb7b 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -52,6 +52,9 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
52#define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ 52#define COMMON_USER (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \
53 PPC_FEATURE_HAS_MMU) 53 PPC_FEATURE_HAS_MMU)
54#define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64) 54#define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64)
55#define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4)
56#define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5)
57#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS)
55 58
56 59
57/* We only set the spe features if the kernel was compiled with 60/* We only set the spe features if the kernel was compiled with
@@ -160,7 +163,7 @@ struct cpu_spec cpu_specs[] = {
160 .pvr_value = 0x00350000, 163 .pvr_value = 0x00350000,
161 .cpu_name = "POWER4 (gp)", 164 .cpu_name = "POWER4 (gp)",
162 .cpu_features = CPU_FTRS_POWER4, 165 .cpu_features = CPU_FTRS_POWER4,
163 .cpu_user_features = COMMON_USER_PPC64, 166 .cpu_user_features = COMMON_USER_POWER4,
164 .icache_bsize = 128, 167 .icache_bsize = 128,
165 .dcache_bsize = 128, 168 .dcache_bsize = 128,
166 .num_pmcs = 8, 169 .num_pmcs = 8,
@@ -175,7 +178,7 @@ struct cpu_spec cpu_specs[] = {
175 .pvr_value = 0x00380000, 178 .pvr_value = 0x00380000,
176 .cpu_name = "POWER4+ (gq)", 179 .cpu_name = "POWER4+ (gq)",
177 .cpu_features = CPU_FTRS_POWER4, 180 .cpu_features = CPU_FTRS_POWER4,
178 .cpu_user_features = COMMON_USER_PPC64, 181 .cpu_user_features = COMMON_USER_POWER4,
179 .icache_bsize = 128, 182 .icache_bsize = 128,
180 .dcache_bsize = 128, 183 .dcache_bsize = 128,
181 .num_pmcs = 8, 184 .num_pmcs = 8,
@@ -190,7 +193,7 @@ struct cpu_spec cpu_specs[] = {
190 .pvr_value = 0x00390000, 193 .pvr_value = 0x00390000,
191 .cpu_name = "PPC970", 194 .cpu_name = "PPC970",
192 .cpu_features = CPU_FTRS_PPC970, 195 .cpu_features = CPU_FTRS_PPC970,
193 .cpu_user_features = COMMON_USER_PPC64 | 196 .cpu_user_features = COMMON_USER_POWER4 |
194 PPC_FEATURE_HAS_ALTIVEC_COMP, 197 PPC_FEATURE_HAS_ALTIVEC_COMP,
195 .icache_bsize = 128, 198 .icache_bsize = 128,
196 .dcache_bsize = 128, 199 .dcache_bsize = 128,
@@ -212,7 +215,7 @@ struct cpu_spec cpu_specs[] = {
212#else 215#else
213 .cpu_features = CPU_FTRS_PPC970, 216 .cpu_features = CPU_FTRS_PPC970,
214#endif 217#endif
215 .cpu_user_features = COMMON_USER_PPC64 | 218 .cpu_user_features = COMMON_USER_POWER4 |
216 PPC_FEATURE_HAS_ALTIVEC_COMP, 219 PPC_FEATURE_HAS_ALTIVEC_COMP,
217 .icache_bsize = 128, 220 .icache_bsize = 128,
218 .dcache_bsize = 128, 221 .dcache_bsize = 128,
@@ -230,7 +233,7 @@ struct cpu_spec cpu_specs[] = {
230 .pvr_value = 0x00440000, 233 .pvr_value = 0x00440000,
231 .cpu_name = "PPC970MP", 234 .cpu_name = "PPC970MP",
232 .cpu_features = CPU_FTRS_PPC970, 235 .cpu_features = CPU_FTRS_PPC970,
233 .cpu_user_features = COMMON_USER_PPC64 | 236 .cpu_user_features = COMMON_USER_POWER4 |
234 PPC_FEATURE_HAS_ALTIVEC_COMP, 237 PPC_FEATURE_HAS_ALTIVEC_COMP,
235 .icache_bsize = 128, 238 .icache_bsize = 128,
236 .dcache_bsize = 128, 239 .dcache_bsize = 128,
@@ -245,7 +248,7 @@ struct cpu_spec cpu_specs[] = {
245 .pvr_value = 0x003a0000, 248 .pvr_value = 0x003a0000,
246 .cpu_name = "POWER5 (gr)", 249 .cpu_name = "POWER5 (gr)",
247 .cpu_features = CPU_FTRS_POWER5, 250 .cpu_features = CPU_FTRS_POWER5,
248 .cpu_user_features = COMMON_USER_PPC64, 251 .cpu_user_features = COMMON_USER_POWER5,
249 .icache_bsize = 128, 252 .icache_bsize = 128,
250 .dcache_bsize = 128, 253 .dcache_bsize = 128,
251 .num_pmcs = 6, 254 .num_pmcs = 6,
@@ -260,7 +263,7 @@ struct cpu_spec cpu_specs[] = {
260 .pvr_value = 0x003b0000, 263 .pvr_value = 0x003b0000,
261 .cpu_name = "POWER5 (gs)", 264 .cpu_name = "POWER5 (gs)",
262 .cpu_features = CPU_FTRS_POWER5, 265 .cpu_features = CPU_FTRS_POWER5,
263 .cpu_user_features = COMMON_USER_PPC64, 266 .cpu_user_features = COMMON_USER_POWER5_PLUS,
264 .icache_bsize = 128, 267 .icache_bsize = 128,
265 .dcache_bsize = 128, 268 .dcache_bsize = 128,
266 .num_pmcs = 6, 269 .num_pmcs = 6,
@@ -276,7 +279,7 @@ struct cpu_spec cpu_specs[] = {
276 .cpu_name = "Cell Broadband Engine", 279 .cpu_name = "Cell Broadband Engine",
277 .cpu_features = CPU_FTRS_CELL, 280 .cpu_features = CPU_FTRS_CELL,
278 .cpu_user_features = COMMON_USER_PPC64 | 281 .cpu_user_features = COMMON_USER_PPC64 |
279 PPC_FEATURE_HAS_ALTIVEC_COMP, 282 PPC_FEATURE_CELL | PPC_FEATURE_HAS_ALTIVEC_COMP,
280 .icache_bsize = 128, 283 .icache_bsize = 128,
281 .dcache_bsize = 128, 284 .dcache_bsize = 128,
282 .cpu_setup = __setup_cpu_be, 285 .cpu_setup = __setup_cpu_be,
diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c
new file mode 100644
index 000000000000..65eae752a527
--- /dev/null
+++ b/arch/powerpc/kernel/firmware.c
@@ -0,0 +1,45 @@
1/*
2 * Extracted from cputable.c
3 *
4 * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
5 *
6 * Modifications for ppc64:
7 * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
8 * Copyright (C) 2005 Stephen Rothwell, IBM Corporation
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/config.h>
17
18#include <asm/firmware.h>
19
20unsigned long ppc64_firmware_features;
21
22#ifdef CONFIG_PPC_PSERIES
23firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
24 {FW_FEATURE_PFT, "hcall-pft"},
25 {FW_FEATURE_TCE, "hcall-tce"},
26 {FW_FEATURE_SPRG0, "hcall-sprg0"},
27 {FW_FEATURE_DABR, "hcall-dabr"},
28 {FW_FEATURE_COPY, "hcall-copy"},
29 {FW_FEATURE_ASR, "hcall-asr"},
30 {FW_FEATURE_DEBUG, "hcall-debug"},
31 {FW_FEATURE_PERF, "hcall-perf"},
32 {FW_FEATURE_DUMP, "hcall-dump"},
33 {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
34 {FW_FEATURE_MIGRATE, "hcall-migrate"},
35 {FW_FEATURE_PERFMON, "hcall-perfmon"},
36 {FW_FEATURE_CRQ, "hcall-crq"},
37 {FW_FEATURE_VIO, "hcall-vio"},
38 {FW_FEATURE_RDMA, "hcall-rdma"},
39 {FW_FEATURE_LLAN, "hcall-lLAN"},
40 {FW_FEATURE_BULK, "hcall-bulk"},
41 {FW_FEATURE_XDABR, "hcall-xdabr"},
42 {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
43 {FW_FEATURE_SPLPAR, "hcall-splpar"},
44};
45#endif
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 4d6001fa1cf2..b780b42c95fc 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -41,20 +41,20 @@ _GLOBAL(load_up_fpu)
41#ifndef CONFIG_SMP 41#ifndef CONFIG_SMP
42 LOADBASE(r3, last_task_used_math) 42 LOADBASE(r3, last_task_used_math)
43 toreal(r3) 43 toreal(r3)
44 LDL r4,OFF(last_task_used_math)(r3) 44 PPC_LL r4,OFF(last_task_used_math)(r3)
45 CMPI 0,r4,0 45 PPC_LCMPI 0,r4,0
46 beq 1f 46 beq 1f
47 toreal(r4) 47 toreal(r4)
48 addi r4,r4,THREAD /* want last_task_used_math->thread */ 48 addi r4,r4,THREAD /* want last_task_used_math->thread */
49 SAVE_32FPRS(0, r4) 49 SAVE_32FPRS(0, r4)
50 mffs fr0 50 mffs fr0
51 stfd fr0,THREAD_FPSCR(r4) 51 stfd fr0,THREAD_FPSCR(r4)
52 LDL r5,PT_REGS(r4) 52 PPC_LL r5,PT_REGS(r4)
53 toreal(r5) 53 toreal(r5)
54 LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 54 PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
55 li r10,MSR_FP|MSR_FE0|MSR_FE1 55 li r10,MSR_FP|MSR_FE0|MSR_FE1
56 andc r4,r4,r10 /* disable FP for previous task */ 56 andc r4,r4,r10 /* disable FP for previous task */
57 STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 57 PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
581: 581:
59#endif /* CONFIG_SMP */ 59#endif /* CONFIG_SMP */
60 /* enable use of FP after return */ 60 /* enable use of FP after return */
@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu)
77#ifndef CONFIG_SMP 77#ifndef CONFIG_SMP
78 subi r4,r5,THREAD 78 subi r4,r5,THREAD
79 fromreal(r4) 79 fromreal(r4)
80 STL r4,OFF(last_task_used_math)(r3) 80 PPC_STL r4,OFF(last_task_used_math)(r3)
81#endif /* CONFIG_SMP */ 81#endif /* CONFIG_SMP */
82 /* restore registers and return */ 82 /* restore registers and return */
83 /* we haven't used ctr or xer or lr */ 83 /* we haven't used ctr or xer or lr */
@@ -97,24 +97,24 @@ _GLOBAL(giveup_fpu)
97 MTMSRD(r5) /* enable use of fpu now */ 97 MTMSRD(r5) /* enable use of fpu now */
98 SYNC_601 98 SYNC_601
99 isync 99 isync
100 CMPI 0,r3,0 100 PPC_LCMPI 0,r3,0
101 beqlr- /* if no previous owner, done */ 101 beqlr- /* if no previous owner, done */
102 addi r3,r3,THREAD /* want THREAD of task */ 102 addi r3,r3,THREAD /* want THREAD of task */
103 LDL r5,PT_REGS(r3) 103 PPC_LL r5,PT_REGS(r3)
104 CMPI 0,r5,0 104 PPC_LCMPI 0,r5,0
105 SAVE_32FPRS(0, r3) 105 SAVE_32FPRS(0, r3)
106 mffs fr0 106 mffs fr0
107 stfd fr0,THREAD_FPSCR(r3) 107 stfd fr0,THREAD_FPSCR(r3)
108 beq 1f 108 beq 1f
109 LDL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 109 PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
110 li r3,MSR_FP|MSR_FE0|MSR_FE1 110 li r3,MSR_FP|MSR_FE0|MSR_FE1
111 andc r4,r4,r3 /* disable FP for previous task */ 111 andc r4,r4,r3 /* disable FP for previous task */
112 STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 112 PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1131: 1131:
114#ifndef CONFIG_SMP 114#ifndef CONFIG_SMP
115 li r5,0 115 li r5,0
116 LOADBASE(r4,last_task_used_math) 116 LOADBASE(r4,last_task_used_math)
117 STL r5,OFF(last_task_used_math)(r4) 117 PPC_STL r5,OFF(last_task_used_math)(r4)
118#endif /* CONFIG_SMP */ 118#endif /* CONFIG_SMP */
119 blr 119 blr
120 120
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 16ab40daa738..8a8bf79ef044 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -28,7 +28,6 @@
28#include <asm/reg.h> 28#include <asm/reg.h>
29#include <asm/page.h> 29#include <asm/page.h>
30#include <asm/mmu.h> 30#include <asm/mmu.h>
31#include <asm/systemcfg.h>
32#include <asm/ppc_asm.h> 31#include <asm/ppc_asm.h>
33#include <asm/asm-offsets.h> 32#include <asm/asm-offsets.h>
34#include <asm/bug.h> 33#include <asm/bug.h>
@@ -1697,25 +1696,14 @@ _GLOBAL(pmac_secondary_start)
1697 * SPRG3 = paca virtual address 1696 * SPRG3 = paca virtual address
1698 */ 1697 */
1699_GLOBAL(__secondary_start) 1698_GLOBAL(__secondary_start)
1699 /* Set thread priority to MEDIUM */
1700 HMT_MEDIUM
1700 1701
1701 HMT_MEDIUM /* Set thread priority to MEDIUM */ 1702 /* Load TOC */
1702
1703 ld r2,PACATOC(r13) 1703 ld r2,PACATOC(r13)
1704 li r6,0 1704
1705 stb r6,PACAPROCENABLED(r13) 1705 /* Do early setup for that CPU (stab, slb, hash table pointer) */
1706 1706 bl .early_setup_secondary
1707#ifndef CONFIG_PPC_ISERIES
1708 /* Initialize the page table pointer register. */
1709 LOADADDR(r6,_SDR1)
1710 ld r6,0(r6) /* get the value of _SDR1 */
1711 mtspr SPRN_SDR1,r6 /* set the htab location */
1712#endif
1713 /* Initialize the first segment table (or SLB) entry */
1714 ld r3,PACASTABVIRT(r13) /* get addr of segment table */
1715BEGIN_FTR_SECTION
1716 bl .stab_initialize
1717END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
1718 bl .slb_initialize
1719 1707
1720 /* Initialize the kernel stack. Just a repeat for iSeries. */ 1708 /* Initialize the kernel stack. Just a repeat for iSeries. */
1721 LOADADDR(r3,current_set) 1709 LOADADDR(r3,current_set)
@@ -1724,37 +1712,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
1724 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD 1712 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
1725 std r1,PACAKSAVE(r13) 1713 std r1,PACAKSAVE(r13)
1726 1714
1727 ld r3,PACASTABREAL(r13) /* get raddr of segment table */ 1715 /* Clear backchain so we get nice backtraces */
1728 ori r4,r3,1 /* turn on valid bit */
1729
1730#ifdef CONFIG_PPC_ISERIES
1731 li r0,-1 /* hypervisor call */
1732 li r3,1
1733 sldi r3,r3,63 /* 0x8000000000000000 */
1734 ori r3,r3,4 /* 0x8000000000000004 */
1735 sc /* HvCall_setASR */
1736#else
1737 /* set the ASR */
1738 ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
1739 ld r3,0(r3)
1740 lwz r3,PLATFORM(r3) /* r3 = platform flags */
1741 andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
1742 beq 98f /* branch if result is 0 */
1743 mfspr r3,SPRN_PVR
1744 srwi r3,r3,16
1745 cmpwi r3,0x37 /* SStar */
1746 beq 97f
1747 cmpwi r3,0x36 /* IStar */
1748 beq 97f
1749 cmpwi r3,0x34 /* Pulsar */
1750 bne 98f
175197: li r3,H_SET_ASR /* hcall = H_SET_ASR */
1752 HVSC /* Invoking hcall */
1753 b 99f
175498: /* !(rpa hypervisor) || !(star) */
1755 mtasr r4 /* set the stab location */
175699:
1757#endif
1758 li r7,0 1716 li r7,0
1759 mtlr r7 1717 mtlr r7
1760 1718
@@ -1777,6 +1735,7 @@ _GLOBAL(start_secondary_prolog)
1777 li r3,0 1735 li r3,0
1778 std r3,0(r1) /* Zero the stack frame pointer */ 1736 std r3,0(r1) /* Zero the stack frame pointer */
1779 bl .start_secondary 1737 bl .start_secondary
1738 b .
1780#endif 1739#endif
1781 1740
1782/* 1741/*
@@ -1896,40 +1855,6 @@ _STATIC(start_here_multiplatform)
1896 mr r3,r31 1855 mr r3,r31
1897 bl .early_setup 1856 bl .early_setup
1898 1857
1899 /* set the ASR */
1900 ld r3,PACASTABREAL(r13)
1901 ori r4,r3,1 /* turn on valid bit */
1902 ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
1903 ld r3,0(r3)
1904 lwz r3,PLATFORM(r3) /* r3 = platform flags */
1905 andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
1906 beq 98f /* branch if result is 0 */
1907 mfspr r3,SPRN_PVR
1908 srwi r3,r3,16
1909 cmpwi r3,0x37 /* SStar */
1910 beq 97f
1911 cmpwi r3,0x36 /* IStar */
1912 beq 97f
1913 cmpwi r3,0x34 /* Pulsar */
1914 bne 98f
191597: li r3,H_SET_ASR /* hcall = H_SET_ASR */
1916 HVSC /* Invoking hcall */
1917 b 99f
191898: /* !(rpa hypervisor) || !(star) */
1919 mtasr r4 /* set the stab location */
192099:
1921 /* Set SDR1 (hash table pointer) */
1922 ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
1923 ld r3,0(r3)
1924 lwz r3,PLATFORM(r3) /* r3 = platform flags */
1925 /* Test if bit 0 is set (LPAR bit) */
1926 andi. r3,r3,PLATFORM_LPAR
1927 bne 98f /* branch if result is !0 */
1928 LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
1929 add r6,r6,r26
1930 ld r6,0(r6) /* get the value of _SDR1 */
1931 mtspr SPRN_SDR1,r6 /* set the htab location */
193298:
1933 LOADADDR(r3,.start_here_common) 1858 LOADADDR(r3,.start_here_common)
1934 SET_REG_TO_CONST(r4, MSR_KERNEL) 1859 SET_REG_TO_CONST(r4, MSR_KERNEL)
1935 mtspr SPRN_SRR0,r3 1860 mtspr SPRN_SRR0,r3
diff --git a/arch/powerpc/kernel/ioctl32.c b/arch/powerpc/kernel/ioctl32.c
new file mode 100644
index 000000000000..3fa6a93adbd0
--- /dev/null
+++ b/arch/powerpc/kernel/ioctl32.c
@@ -0,0 +1,49 @@
1/*
2 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
3 *
4 * Based on sparc64 ioctl32.c by:
5 *
6 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
7 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
8 *
9 * ppc64 changes:
10 *
11 * Copyright (C) 2000 Ken Aaker (kdaaker@rchland.vnet.ibm.com)
12 * Copyright (C) 2001 Anton Blanchard (antonb@au.ibm.com)
13 *
14 * These routines maintain argument size conversion between 32bit and 64bit
15 * ioctls.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version
20 * 2 of the License, or (at your option) any later version.
21 */
22
23#define INCLUDES
24#include "compat_ioctl.c"
25#include <linux/syscalls.h>
26
27#define CODE
28#include "compat_ioctl.c"
29
30#define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
31#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl)
32
33#define IOCTL_TABLE_START \
34 struct ioctl_trans ioctl_start[] = {
35#define IOCTL_TABLE_END \
36 };
37
38IOCTL_TABLE_START
39#include <linux/compat_ioctl.h>
40#define DECLARES
41#include "compat_ioctl.c"
42
43/* Little p (/dev/rtc, /dev/envctrl, etc.) */
44COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */
45COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */
46
47IOCTL_TABLE_END
48
49int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
new file mode 100644
index 000000000000..4b7940693f3d
--- /dev/null
+++ b/arch/powerpc/kernel/irq.c
@@ -0,0 +1,478 @@
1/*
2 * arch/ppc/kernel/irq.c
3 *
4 * Derived from arch/i386/kernel/irq.c
5 * Copyright (C) 1992 Linus Torvalds
6 * Adapted from arch/i386 by Gary Thomas
7 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
8 * Updated and modified by Cort Dougan <cort@fsmlabs.com>
9 * Copyright (C) 1996-2001 Cort Dougan
10 * Adapted for Power Macintosh by Paul Mackerras
11 * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
12 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
18 *
19 * This file contains the code used by various IRQ handling routines:
20 * asking for different IRQ's should be done through these routines
21 * instead of just grabbing them. Thus setups with different IRQ numbers
22 * shouldn't result in any weird surprises, and installing new handlers
23 * should be easier.
24 *
25 * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the
26 * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit
27 * mask register (of which only 16 are defined), hence the weird shifting
28 * and complement of the cached_irq_mask. I want to be able to stuff
29 * this right into the SIU SMASK register.
30 * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx
31 * to reduce code space and undefined function references.
32 */
33
34#include <linux/errno.h>
35#include <linux/module.h>
36#include <linux/threads.h>
37#include <linux/kernel_stat.h>
38#include <linux/signal.h>
39#include <linux/sched.h>
40#include <linux/ptrace.h>
41#include <linux/ioport.h>
42#include <linux/interrupt.h>
43#include <linux/timex.h>
44#include <linux/config.h>
45#include <linux/init.h>
46#include <linux/slab.h>
47#include <linux/pci.h>
48#include <linux/delay.h>
49#include <linux/irq.h>
50#include <linux/proc_fs.h>
51#include <linux/random.h>
52#include <linux/seq_file.h>
53#include <linux/cpumask.h>
54#include <linux/profile.h>
55#include <linux/bitops.h>
56#ifdef CONFIG_PPC64
57#include <linux/kallsyms.h>
58#endif
59
60#include <asm/uaccess.h>
61#include <asm/system.h>
62#include <asm/io.h>
63#include <asm/pgtable.h>
64#include <asm/irq.h>
65#include <asm/cache.h>
66#include <asm/prom.h>
67#include <asm/ptrace.h>
68#include <asm/machdep.h>
69#ifdef CONFIG_PPC64
70#include <asm/iseries/it_lp_queue.h>
71#include <asm/paca.h>
72#endif
73
74static int ppc_spurious_interrupts;
75
76#if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP)
77extern void iSeries_smp_message_recv(struct pt_regs *);
78#endif
79
80#ifdef CONFIG_PPC32
81#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
82
83unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
84atomic_t ppc_n_lost_interrupts;
85
86#ifdef CONFIG_TAU_INT
87extern int tau_initialized;
88extern int tau_interrupts(int);
89#endif
90
91#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE)
92extern atomic_t ipi_recv;
93extern atomic_t ipi_sent;
94#endif
95#endif /* CONFIG_PPC32 */
96
97#ifdef CONFIG_PPC64
98EXPORT_SYMBOL(irq_desc);
99
100int distribute_irqs = 1;
101int __irq_offset_value;
102u64 ppc64_interrupt_controller;
103#endif /* CONFIG_PPC64 */
104
105int show_interrupts(struct seq_file *p, void *v)
106{
107 int i = *(loff_t *)v, j;
108 struct irqaction *action;
109 irq_desc_t *desc;
110 unsigned long flags;
111
112 if (i == 0) {
113 seq_puts(p, " ");
114 for_each_online_cpu(j)
115 seq_printf(p, "CPU%d ", j);
116 seq_putc(p, '\n');
117 }
118
119 if (i < NR_IRQS) {
120 desc = get_irq_desc(i);
121 spin_lock_irqsave(&desc->lock, flags);
122 action = desc->action;
123 if (!action || !action->handler)
124 goto skip;
125 seq_printf(p, "%3d: ", i);
126#ifdef CONFIG_SMP
127 for_each_online_cpu(j)
128 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
129#else
130 seq_printf(p, "%10u ", kstat_irqs(i));
131#endif /* CONFIG_SMP */
132 if (desc->handler)
133 seq_printf(p, " %s ", desc->handler->typename);
134 else
135 seq_puts(p, " None ");
136 seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
137 seq_printf(p, " %s", action->name);
138 for (action = action->next; action; action = action->next)
139 seq_printf(p, ", %s", action->name);
140 seq_putc(p, '\n');
141skip:
142 spin_unlock_irqrestore(&desc->lock, flags);
143 } else if (i == NR_IRQS) {
144#ifdef CONFIG_PPC32
145#ifdef CONFIG_TAU_INT
146 if (tau_initialized){
147 seq_puts(p, "TAU: ");
148 for (j = 0; j < NR_CPUS; j++)
149 if (cpu_online(j))
150 seq_printf(p, "%10u ", tau_interrupts(j));
151 seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
152 }
153#endif
154#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE)
155 /* should this be per processor send/receive? */
156 seq_printf(p, "IPI (recv/sent): %10u/%u\n",
157 atomic_read(&ipi_recv), atomic_read(&ipi_sent));
158#endif
159#endif /* CONFIG_PPC32 */
160 seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
161 }
162 return 0;
163}
164
165#ifdef CONFIG_HOTPLUG_CPU
166void fixup_irqs(cpumask_t map)
167{
168 unsigned int irq;
169 static int warned;
170
171 for_each_irq(irq) {
172 cpumask_t mask;
173
174 if (irq_desc[irq].status & IRQ_PER_CPU)
175 continue;
176
177 cpus_and(mask, irq_affinity[irq], map);
178 if (any_online_cpu(mask) == NR_CPUS) {
179 printk("Breaking affinity for irq %i\n", irq);
180 mask = map;
181 }
182 if (irq_desc[irq].handler->set_affinity)
183 irq_desc[irq].handler->set_affinity(irq, mask);
184 else if (irq_desc[irq].action && !(warned++))
185 printk("Cannot set affinity for irq %i\n", irq);
186 }
187
188 local_irq_enable();
189 mdelay(1);
190 local_irq_disable();
191}
192#endif
193
194#ifdef CONFIG_PPC_ISERIES
195void do_IRQ(struct pt_regs *regs)
196{
197 struct paca_struct *lpaca;
198
199 irq_enter();
200
201#ifdef CONFIG_DEBUG_STACKOVERFLOW
202 /* Debugging check for stack overflow: is there less than 2KB free? */
203 {
204 long sp;
205
206 sp = __get_SP() & (THREAD_SIZE-1);
207
208 if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
209 printk("do_IRQ: stack overflow: %ld\n",
210 sp - sizeof(struct thread_info));
211 dump_stack();
212 }
213 }
214#endif
215
216 lpaca = get_paca();
217#ifdef CONFIG_SMP
218 if (lpaca->lppaca.int_dword.fields.ipi_cnt) {
219 lpaca->lppaca.int_dword.fields.ipi_cnt = 0;
220 iSeries_smp_message_recv(regs);
221 }
222#endif /* CONFIG_SMP */
223 if (hvlpevent_is_pending())
224 process_hvlpevents(regs);
225
226 irq_exit();
227
228 if (lpaca->lppaca.int_dword.fields.decr_int) {
229 lpaca->lppaca.int_dword.fields.decr_int = 0;
230 /* Signal a fake decrementer interrupt */
231 timer_interrupt(regs);
232 }
233}
234
235#else /* CONFIG_PPC_ISERIES */
236
237void do_IRQ(struct pt_regs *regs)
238{
239 int irq;
240#ifdef CONFIG_IRQSTACKS
241 struct thread_info *curtp, *irqtp;
242#endif
243
244 irq_enter();
245
246#ifdef CONFIG_DEBUG_STACKOVERFLOW
247 /* Debugging check for stack overflow: is there less than 2KB free? */
248 {
249 long sp;
250
251 sp = __get_SP() & (THREAD_SIZE-1);
252
253 if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
254 printk("do_IRQ: stack overflow: %ld\n",
255 sp - sizeof(struct thread_info));
256 dump_stack();
257 }
258 }
259#endif
260
261 /*
262 * Every platform is required to implement ppc_md.get_irq.
263 * This function will either return an irq number or -1 to
264 * indicate there are no more pending.
265 * The value -2 is for buggy hardware and means that this IRQ
266 * has already been handled. -- Tom
267 */
268 irq = ppc_md.get_irq(regs);
269
270 if (irq >= 0) {
271#ifdef CONFIG_IRQSTACKS
272 /* Switch to the irq stack to handle this */
273 curtp = current_thread_info();
274 irqtp = hardirq_ctx[smp_processor_id()];
275 if (curtp != irqtp) {
276 irqtp->task = curtp->task;
277 irqtp->flags = 0;
278 call___do_IRQ(irq, regs, irqtp);
279 irqtp->task = NULL;
280 if (irqtp->flags)
281 set_bits(irqtp->flags, &curtp->flags);
282 } else
283#endif
284 __do_IRQ(irq, regs);
285 } else
286#ifdef CONFIG_PPC32
287 if (irq != -2)
288#endif
289 /* That's not SMP safe ... but who cares ? */
290 ppc_spurious_interrupts++;
291 irq_exit();
292}
293
294#endif /* CONFIG_PPC_ISERIES */
295
296void __init init_IRQ(void)
297{
298#ifdef CONFIG_PPC64
299 static int once = 0;
300
301 if (once)
302 return;
303
304 once++;
305
306#endif
307 ppc_md.init_IRQ();
308#ifdef CONFIG_PPC64
309 irq_ctx_init();
310#endif
311}
312
313#ifdef CONFIG_PPC64
314#ifndef CONFIG_PPC_ISERIES
315/*
316 * Virtual IRQ mapping code, used on systems with XICS interrupt controllers.
317 */
318
319#define UNDEFINED_IRQ 0xffffffff
320unsigned int virt_irq_to_real_map[NR_IRQS];
321
322/*
323 * Don't use virtual irqs 0, 1, 2 for devices.
324 * The pcnet32 driver considers interrupt numbers < 2 to be invalid,
325 * and 2 is the XICS IPI interrupt.
326 * We limit virtual irqs to 17 less than NR_IRQS so that when we
327 * offset them by 16 (to reserve the first 16 for ISA interrupts)
328 * we don't end up with an interrupt number >= NR_IRQS.
329 */
330#define MIN_VIRT_IRQ 3
331#define MAX_VIRT_IRQ (NR_IRQS - NUM_ISA_INTERRUPTS - 1)
332#define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1)
333
334void
335virt_irq_init(void)
336{
337 int i;
338 for (i = 0; i < NR_IRQS; i++)
339 virt_irq_to_real_map[i] = UNDEFINED_IRQ;
340}
341
342/* Create a mapping for a real_irq if it doesn't already exist.
343 * Return the virtual irq as a convenience.
344 */
345int virt_irq_create_mapping(unsigned int real_irq)
346{
347 unsigned int virq, first_virq;
348 static int warned;
349
350 if (ppc64_interrupt_controller == IC_OPEN_PIC)
351 return real_irq; /* no mapping for openpic (for now) */
352
353 if (ppc64_interrupt_controller == IC_CELL_PIC)
354 return real_irq; /* no mapping for iic either */
355
356 /* don't map interrupts < MIN_VIRT_IRQ */
357 if (real_irq < MIN_VIRT_IRQ) {
358 virt_irq_to_real_map[real_irq] = real_irq;
359 return real_irq;
360 }
361
362 /* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */
363 virq = real_irq;
364 if (virq > MAX_VIRT_IRQ)
365 virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
366
367 /* search for this number or a free slot */
368 first_virq = virq;
369 while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) {
370 if (virt_irq_to_real_map[virq] == real_irq)
371 return virq;
372 if (++virq > MAX_VIRT_IRQ)
373 virq = MIN_VIRT_IRQ;
374 if (virq == first_virq)
375 goto nospace; /* oops, no free slots */
376 }
377
378 virt_irq_to_real_map[virq] = real_irq;
379 return virq;
380
381 nospace:
382 if (!warned) {
383 printk(KERN_CRIT "Interrupt table is full\n");
384 printk(KERN_CRIT "Increase NR_IRQS (currently %d) "
385 "in your kernel sources and rebuild.\n", NR_IRQS);
386 warned = 1;
387 }
388 return NO_IRQ;
389}
390
391/*
392 * In most cases will get a hit on the very first slot checked in the
393 * virt_irq_to_real_map. Only when there are a large number of
394 * IRQs will this be expensive.
395 */
396unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
397{
398 unsigned int virq;
399 unsigned int first_virq;
400
401 virq = real_irq;
402
403 if (virq > MAX_VIRT_IRQ)
404 virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
405
406 first_virq = virq;
407
408 do {
409 if (virt_irq_to_real_map[virq] == real_irq)
410 return virq;
411
412 virq++;
413
414 if (virq >= MAX_VIRT_IRQ)
415 virq = 0;
416
417 } while (first_virq != virq);
418
419 return NO_IRQ;
420
421}
422
423#endif /* CONFIG_PPC_ISERIES */
424
425#ifdef CONFIG_IRQSTACKS
426struct thread_info *softirq_ctx[NR_CPUS];
427struct thread_info *hardirq_ctx[NR_CPUS];
428
429void irq_ctx_init(void)
430{
431 struct thread_info *tp;
432 int i;
433
434 for_each_cpu(i) {
435 memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
436 tp = softirq_ctx[i];
437 tp->cpu = i;
438 tp->preempt_count = SOFTIRQ_OFFSET;
439
440 memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
441 tp = hardirq_ctx[i];
442 tp->cpu = i;
443 tp->preempt_count = HARDIRQ_OFFSET;
444 }
445}
446
447void do_softirq(void)
448{
449 unsigned long flags;
450 struct thread_info *curtp, *irqtp;
451
452 if (in_interrupt())
453 return;
454
455 local_irq_save(flags);
456
457 if (local_softirq_pending()) {
458 curtp = current_thread_info();
459 irqtp = softirq_ctx[smp_processor_id()];
460 irqtp->task = curtp->task;
461 call_do_softirq(irqtp);
462 irqtp->task = NULL;
463 }
464
465 local_irq_restore(flags);
466}
467EXPORT_SYMBOL(do_softirq);
468
469#endif /* CONFIG_IRQSTACKS */
470
471static int __init setup_noirqdistrib(char *str)
472{
473 distribute_irqs = 0;
474 return 1;
475}
476
477__setup("noirqdistrib", setup_noirqdistrib);
478#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
new file mode 100644
index 000000000000..5e954fae031f
--- /dev/null
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -0,0 +1,612 @@
1/*
2 * PowerPC64 LPAR Configuration Information Driver
3 *
4 * Dave Engebretsen engebret@us.ibm.com
5 * Copyright (c) 2003 Dave Engebretsen
6 * Will Schmidt willschm@us.ibm.com
7 * SPLPAR updates, Copyright (c) 2003 Will Schmidt IBM Corporation.
8 * seq_file updates, Copyright (c) 2004 Will Schmidt IBM Corporation.
9 * Nathan Lynch nathanl@austin.ibm.com
10 * Added lparcfg_write, Copyright (C) 2004 Nathan Lynch 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 * This driver creates a proc file at /proc/ppc64/lparcfg which contains
18 * keyword - value pairs that specify the configuration of the partition.
19 */
20
21#include <linux/config.h>
22#include <linux/module.h>
23#include <linux/types.h>
24#include <linux/errno.h>
25#include <linux/proc_fs.h>
26#include <linux/init.h>
27#include <linux/seq_file.h>
28#include <asm/uaccess.h>
29#include <asm/iseries/hv_lp_config.h>
30#include <asm/lppaca.h>
31#include <asm/hvcall.h>
32#include <asm/firmware.h>
33#include <asm/rtas.h>
34#include <asm/system.h>
35#include <asm/time.h>
36#include <asm/iseries/it_exp_vpd_panel.h>
37#include <asm/prom.h>
38#include <asm/systemcfg.h>
39
40#define MODULE_VERS "1.6"
41#define MODULE_NAME "lparcfg"
42
43/* #define LPARCFG_DEBUG */
44
45/* find a better place for this function... */
46void log_plpar_hcall_return(unsigned long rc, char *tag)
47{
48 if (rc == 0) /* success, return */
49 return;
50/* check for null tag ? */
51 if (rc == H_Hardware)
52 printk(KERN_INFO
53 "plpar-hcall (%s) failed with hardware fault\n", tag);
54 else if (rc == H_Function)
55 printk(KERN_INFO
56 "plpar-hcall (%s) failed; function not allowed\n", tag);
57 else if (rc == H_Authority)
58 printk(KERN_INFO
59 "plpar-hcall (%s) failed; not authorized to this function\n",
60 tag);
61 else if (rc == H_Parameter)
62 printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
63 tag);
64 else
65 printk(KERN_INFO
66 "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",
67 tag, rc);
68
69}
70
71static struct proc_dir_entry *proc_ppc64_lparcfg;
72#define LPARCFG_BUFF_SIZE 4096
73
74#ifdef CONFIG_PPC_ISERIES
75
76/*
77 * For iSeries legacy systems, the PPA purr function is available from the
78 * emulated_time_base field in the paca.
79 */
80static unsigned long get_purr(void)
81{
82 unsigned long sum_purr = 0;
83 int cpu;
84 struct paca_struct *lpaca;
85
86 for_each_cpu(cpu) {
87 lpaca = paca + cpu;
88 sum_purr += lpaca->lppaca.emulated_time_base;
89
90#ifdef PURR_DEBUG
91 printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n",
92 cpu, lpaca->lppaca.emulated_time_base);
93#endif
94 }
95 return sum_purr;
96}
97
98#define lparcfg_write NULL
99
100/*
101 * Methods used to fetch LPAR data when running on an iSeries platform.
102 */
103static int lparcfg_data(struct seq_file *m, void *v)
104{
105 unsigned long pool_id, lp_index;
106 int shared, entitled_capacity, max_entitled_capacity;
107 int processors, max_processors;
108 struct paca_struct *lpaca = get_paca();
109 unsigned long purr = get_purr();
110
111 seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
112
113 shared = (int)(lpaca->lppaca_ptr->shared_proc);
114 seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
115 e2a(xItExtVpdPanel.mfgID[2]),
116 e2a(xItExtVpdPanel.mfgID[3]),
117 e2a(xItExtVpdPanel.systemSerial[1]),
118 e2a(xItExtVpdPanel.systemSerial[2]),
119 e2a(xItExtVpdPanel.systemSerial[3]),
120 e2a(xItExtVpdPanel.systemSerial[4]),
121 e2a(xItExtVpdPanel.systemSerial[5]));
122
123 seq_printf(m, "system_type=%c%c%c%c\n",
124 e2a(xItExtVpdPanel.machineType[0]),
125 e2a(xItExtVpdPanel.machineType[1]),
126 e2a(xItExtVpdPanel.machineType[2]),
127 e2a(xItExtVpdPanel.machineType[3]));
128
129 lp_index = HvLpConfig_getLpIndex();
130 seq_printf(m, "partition_id=%d\n", (int)lp_index);
131
132 seq_printf(m, "system_active_processors=%d\n",
133 (int)HvLpConfig_getSystemPhysicalProcessors());
134
135 seq_printf(m, "system_potential_processors=%d\n",
136 (int)HvLpConfig_getSystemPhysicalProcessors());
137
138 processors = (int)HvLpConfig_getPhysicalProcessors();
139 seq_printf(m, "partition_active_processors=%d\n", processors);
140
141 max_processors = (int)HvLpConfig_getMaxPhysicalProcessors();
142 seq_printf(m, "partition_potential_processors=%d\n", max_processors);
143
144 if (shared) {
145 entitled_capacity = HvLpConfig_getSharedProcUnits();
146 max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits();
147 } else {
148 entitled_capacity = processors * 100;
149 max_entitled_capacity = max_processors * 100;
150 }
151 seq_printf(m, "partition_entitled_capacity=%d\n", entitled_capacity);
152
153 seq_printf(m, "partition_max_entitled_capacity=%d\n",
154 max_entitled_capacity);
155
156 if (shared) {
157 pool_id = HvLpConfig_getSharedPoolIndex();
158 seq_printf(m, "pool=%d\n", (int)pool_id);
159 seq_printf(m, "pool_capacity=%d\n",
160 (int)(HvLpConfig_getNumProcsInSharedPool(pool_id) *
161 100));
162 seq_printf(m, "purr=%ld\n", purr);
163 }
164
165 seq_printf(m, "shared_processor_mode=%d\n", shared);
166
167 return 0;
168}
169#endif /* CONFIG_PPC_ISERIES */
170
171#ifdef CONFIG_PPC_PSERIES
172/*
173 * Methods used to fetch LPAR data when running on a pSeries platform.
174 */
175
176/*
177 * H_GET_PPP hcall returns info in 4 parms.
178 * entitled_capacity,unallocated_capacity,
179 * aggregation, resource_capability).
180 *
181 * R4 = Entitled Processor Capacity Percentage.
182 * R5 = Unallocated Processor Capacity Percentage.
183 * R6 (AABBCCDDEEFFGGHH).
184 * XXXX - reserved (0)
185 * XXXX - reserved (0)
186 * XXXX - Group Number
187 * XXXX - Pool Number.
188 * R7 (IIJJKKLLMMNNOOPP).
189 * XX - reserved. (0)
190 * XX - bit 0-6 reserved (0). bit 7 is Capped indicator.
191 * XX - variable processor Capacity Weight
192 * XX - Unallocated Variable Processor Capacity Weight.
193 * XXXX - Active processors in Physical Processor Pool.
194 * XXXX - Processors active on platform.
195 */
196static unsigned int h_get_ppp(unsigned long *entitled,
197 unsigned long *unallocated,
198 unsigned long *aggregation,
199 unsigned long *resource)
200{
201 unsigned long rc;
202 rc = plpar_hcall_4out(H_GET_PPP, 0, 0, 0, 0, entitled, unallocated,
203 aggregation, resource);
204
205 log_plpar_hcall_return(rc, "H_GET_PPP");
206
207 return rc;
208}
209
210static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
211{
212 unsigned long rc;
213 unsigned long dummy;
214 rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
215
216 log_plpar_hcall_return(rc, "H_PIC");
217}
218
219static unsigned long get_purr(void);
220
221/* Track sum of all purrs across all processors. This is used to further */
222/* calculate usage values by different applications */
223
224static unsigned long get_purr(void)
225{
226 unsigned long sum_purr = 0;
227 int cpu;
228 struct cpu_usage *cu;
229
230 for_each_cpu(cpu) {
231 cu = &per_cpu(cpu_usage_array, cpu);
232 sum_purr += cu->current_tb;
233 }
234 return sum_purr;
235}
236
237#define SPLPAR_CHARACTERISTICS_TOKEN 20
238#define SPLPAR_MAXLENGTH 1026*(sizeof(char))
239
240/*
241 * parse_system_parameter_string()
242 * Retrieve the potential_processors, max_entitled_capacity and friends
243 * through the get-system-parameter rtas call. Replace keyword strings as
244 * necessary.
245 */
246static void parse_system_parameter_string(struct seq_file *m)
247{
248 int call_status;
249
250 char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
251 if (!local_buffer) {
252 printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
253 __FILE__, __FUNCTION__, __LINE__);
254 return;
255 }
256
257 spin_lock(&rtas_data_buf_lock);
258 memset(rtas_data_buf, 0, SPLPAR_MAXLENGTH);
259 call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
260 NULL,
261 SPLPAR_CHARACTERISTICS_TOKEN,
262 __pa(rtas_data_buf));
263 memcpy(local_buffer, rtas_data_buf, SPLPAR_MAXLENGTH);
264 spin_unlock(&rtas_data_buf_lock);
265
266 if (call_status != 0) {
267 printk(KERN_INFO
268 "%s %s Error calling get-system-parameter (0x%x)\n",
269 __FILE__, __FUNCTION__, call_status);
270 } else {
271 int splpar_strlen;
272 int idx, w_idx;
273 char *workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
274 if (!workbuffer) {
275 printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
276 __FILE__, __FUNCTION__, __LINE__);
277 kfree(local_buffer);
278 return;
279 }
280#ifdef LPARCFG_DEBUG
281 printk(KERN_INFO "success calling get-system-parameter \n");
282#endif
283 splpar_strlen = local_buffer[0] * 16 + local_buffer[1];
284 local_buffer += 2; /* step over strlen value */
285
286 memset(workbuffer, 0, SPLPAR_MAXLENGTH);
287 w_idx = 0;
288 idx = 0;
289 while ((*local_buffer) && (idx < splpar_strlen)) {
290 workbuffer[w_idx++] = local_buffer[idx++];
291 if ((local_buffer[idx] == ',')
292 || (local_buffer[idx] == '\0')) {
293 workbuffer[w_idx] = '\0';
294 if (w_idx) {
295 /* avoid the empty string */
296 seq_printf(m, "%s\n", workbuffer);
297 }
298 memset(workbuffer, 0, SPLPAR_MAXLENGTH);
299 idx++; /* skip the comma */
300 w_idx = 0;
301 } else if (local_buffer[idx] == '=') {
302 /* code here to replace workbuffer contents
303 with different keyword strings */
304 if (0 == strcmp(workbuffer, "MaxEntCap")) {
305 strcpy(workbuffer,
306 "partition_max_entitled_capacity");
307 w_idx = strlen(workbuffer);
308 }
309 if (0 == strcmp(workbuffer, "MaxPlatProcs")) {
310 strcpy(workbuffer,
311 "system_potential_processors");
312 w_idx = strlen(workbuffer);
313 }
314 }
315 }
316 kfree(workbuffer);
317 local_buffer -= 2; /* back up over strlen value */
318 }
319 kfree(local_buffer);
320}
321
322static int lparcfg_count_active_processors(void);
323
324/* Return the number of processors in the system.
325 * This function reads through the device tree and counts
326 * the virtual processors, this does not include threads.
327 */
328static int lparcfg_count_active_processors(void)
329{
330 struct device_node *cpus_dn = NULL;
331 int count = 0;
332
333 while ((cpus_dn = of_find_node_by_type(cpus_dn, "cpu"))) {
334#ifdef LPARCFG_DEBUG
335 printk(KERN_ERR "cpus_dn %p \n", cpus_dn);
336#endif
337 count++;
338 }
339 return count;
340}
341
342static int lparcfg_data(struct seq_file *m, void *v)
343{
344 int partition_potential_processors;
345 int partition_active_processors;
346 struct device_node *rootdn;
347 const char *model = "";
348 const char *system_id = "";
349 unsigned int *lp_index_ptr, lp_index = 0;
350 struct device_node *rtas_node;
351 int *lrdrp;
352
353 rootdn = find_path_device("/");
354 if (rootdn) {
355 model = get_property(rootdn, "model", NULL);
356 system_id = get_property(rootdn, "system-id", NULL);
357 lp_index_ptr = (unsigned int *)
358 get_property(rootdn, "ibm,partition-no", NULL);
359 if (lp_index_ptr)
360 lp_index = *lp_index_ptr;
361 }
362
363 seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
364
365 seq_printf(m, "serial_number=%s\n", system_id);
366
367 seq_printf(m, "system_type=%s\n", model);
368
369 seq_printf(m, "partition_id=%d\n", (int)lp_index);
370
371 rtas_node = find_path_device("/rtas");
372 lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL);
373
374 if (lrdrp == NULL) {
375 partition_potential_processors = _systemcfg->processorCount;
376 } else {
377 partition_potential_processors = *(lrdrp + 4);
378 }
379
380 partition_active_processors = lparcfg_count_active_processors();
381
382 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
383 unsigned long h_entitled, h_unallocated;
384 unsigned long h_aggregation, h_resource;
385 unsigned long pool_idle_time, pool_procs;
386 unsigned long purr;
387
388 h_get_ppp(&h_entitled, &h_unallocated, &h_aggregation,
389 &h_resource);
390
391 seq_printf(m, "R4=0x%lx\n", h_entitled);
392 seq_printf(m, "R5=0x%lx\n", h_unallocated);
393 seq_printf(m, "R6=0x%lx\n", h_aggregation);
394 seq_printf(m, "R7=0x%lx\n", h_resource);
395
396 purr = get_purr();
397
398 /* this call handles the ibm,get-system-parameter contents */
399 parse_system_parameter_string(m);
400
401 seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled);
402
403 seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff);
404
405 seq_printf(m, "system_active_processors=%ld\n",
406 (h_resource >> 0 * 8) & 0xffff);
407
408 /* pool related entries are apropriate for shared configs */
409 if (paca[0].lppaca.shared_proc) {
410
411 h_pic(&pool_idle_time, &pool_procs);
412
413 seq_printf(m, "pool=%ld\n",
414 (h_aggregation >> 0 * 8) & 0xffff);
415
416 /* report pool_capacity in percentage */
417 seq_printf(m, "pool_capacity=%ld\n",
418 ((h_resource >> 2 * 8) & 0xffff) * 100);
419
420 seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time);
421
422 seq_printf(m, "pool_num_procs=%ld\n", pool_procs);
423 }
424
425 seq_printf(m, "unallocated_capacity_weight=%ld\n",
426 (h_resource >> 4 * 8) & 0xFF);
427
428 seq_printf(m, "capacity_weight=%ld\n",
429 (h_resource >> 5 * 8) & 0xFF);
430
431 seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01);
432
433 seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated);
434
435 seq_printf(m, "purr=%ld\n", purr);
436
437 } else { /* non SPLPAR case */
438
439 seq_printf(m, "system_active_processors=%d\n",
440 partition_potential_processors);
441
442 seq_printf(m, "system_potential_processors=%d\n",
443 partition_potential_processors);
444
445 seq_printf(m, "partition_max_entitled_capacity=%d\n",
446 partition_potential_processors * 100);
447
448 seq_printf(m, "partition_entitled_capacity=%d\n",
449 partition_active_processors * 100);
450 }
451
452 seq_printf(m, "partition_active_processors=%d\n",
453 partition_active_processors);
454
455 seq_printf(m, "partition_potential_processors=%d\n",
456 partition_potential_processors);
457
458 seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.shared_proc);
459
460 return 0;
461}
462
463/*
464 * Interface for changing system parameters (variable capacity weight
465 * and entitled capacity). Format of input is "param_name=value";
466 * anything after value is ignored. Valid parameters at this time are
467 * "partition_entitled_capacity" and "capacity_weight". We use
468 * H_SET_PPP to alter parameters.
469 *
470 * This function should be invoked only on systems with
471 * FW_FEATURE_SPLPAR.
472 */
473static ssize_t lparcfg_write(struct file *file, const char __user * buf,
474 size_t count, loff_t * off)
475{
476 char *kbuf;
477 char *tmp;
478 u64 new_entitled, *new_entitled_ptr = &new_entitled;
479 u8 new_weight, *new_weight_ptr = &new_weight;
480
481 unsigned long current_entitled; /* parameters for h_get_ppp */
482 unsigned long dummy;
483 unsigned long resource;
484 u8 current_weight;
485
486 ssize_t retval = -ENOMEM;
487
488 kbuf = kmalloc(count, GFP_KERNEL);
489 if (!kbuf)
490 goto out;
491
492 retval = -EFAULT;
493 if (copy_from_user(kbuf, buf, count))
494 goto out;
495
496 retval = -EINVAL;
497 kbuf[count - 1] = '\0';
498 tmp = strchr(kbuf, '=');
499 if (!tmp)
500 goto out;
501
502 *tmp++ = '\0';
503
504 if (!strcmp(kbuf, "partition_entitled_capacity")) {
505 char *endp;
506 *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
507 if (endp == tmp)
508 goto out;
509 new_weight_ptr = &current_weight;
510 } else if (!strcmp(kbuf, "capacity_weight")) {
511 char *endp;
512 *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
513 if (endp == tmp)
514 goto out;
515 new_entitled_ptr = &current_entitled;
516 } else
517 goto out;
518
519 /* Get our current parameters */
520 retval = h_get_ppp(&current_entitled, &dummy, &dummy, &resource);
521 if (retval) {
522 retval = -EIO;
523 goto out;
524 }
525
526 current_weight = (resource >> 5 * 8) & 0xFF;
527
528 pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
529 __FUNCTION__, current_entitled, current_weight);
530
531 pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
532 __FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
533
534 retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
535 *new_weight_ptr);
536
537 if (retval == H_Success || retval == H_Constrained) {
538 retval = count;
539 } else if (retval == H_Busy) {
540 retval = -EBUSY;
541 } else if (retval == H_Hardware) {
542 retval = -EIO;
543 } else if (retval == H_Parameter) {
544 retval = -EINVAL;
545 } else {
546 printk(KERN_WARNING "%s: received unknown hv return code %ld",
547 __FUNCTION__, retval);
548 retval = -EIO;
549 }
550
551 out:
552 kfree(kbuf);
553 return retval;
554}
555
556#endif /* CONFIG_PPC_PSERIES */
557
558static int lparcfg_open(struct inode *inode, struct file *file)
559{
560 return single_open(file, lparcfg_data, NULL);
561}
562
563struct file_operations lparcfg_fops = {
564 .owner = THIS_MODULE,
565 .read = seq_read,
566 .open = lparcfg_open,
567 .release = single_release,
568};
569
570int __init lparcfg_init(void)
571{
572 struct proc_dir_entry *ent;
573 mode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
574
575 /* Allow writing if we have FW_FEATURE_SPLPAR */
576 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
577 lparcfg_fops.write = lparcfg_write;
578 mode |= S_IWUSR;
579 }
580
581 ent = create_proc_entry("ppc64/lparcfg", mode, NULL);
582 if (ent) {
583 ent->proc_fops = &lparcfg_fops;
584 ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL);
585 if (!ent->data) {
586 printk(KERN_ERR
587 "Failed to allocate buffer for lparcfg\n");
588 remove_proc_entry("lparcfg", ent->parent);
589 return -ENOMEM;
590 }
591 } else {
592 printk(KERN_ERR "Failed to create ppc64/lparcfg\n");
593 return -EIO;
594 }
595
596 proc_ppc64_lparcfg = ent;
597 return 0;
598}
599
600void __exit lparcfg_cleanup(void)
601{
602 if (proc_ppc64_lparcfg) {
603 kfree(proc_ppc64_lparcfg->data);
604 remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);
605 }
606}
607
608module_init(lparcfg_init);
609module_exit(lparcfg_cleanup);
610MODULE_DESCRIPTION("Interface for LPAR configuration data");
611MODULE_AUTHOR("Dave Engebretsen");
612MODULE_LICENSE("GPL");
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 3bedb532aed9..f6d84a75ed26 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -519,7 +519,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
519 * 519 *
520 * flush_icache_range(unsigned long start, unsigned long stop) 520 * flush_icache_range(unsigned long start, unsigned long stop)
521 */ 521 */
522_GLOBAL(flush_icache_range) 522_GLOBAL(__flush_icache_range)
523BEGIN_FTR_SECTION 523BEGIN_FTR_SECTION
524 blr /* for 601, do nothing */ 524 blr /* for 601, do nothing */
525END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) 525END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
@@ -607,27 +607,6 @@ _GLOBAL(invalidate_dcache_range)
607 sync /* wait for dcbi's to get to ram */ 607 sync /* wait for dcbi's to get to ram */
608 blr 608 blr
609 609
610#ifdef CONFIG_NOT_COHERENT_CACHE
611/*
612 * 40x cores have 8K or 16K dcache and 32 byte line size.
613 * 44x has a 32K dcache and 32 byte line size.
614 * 8xx has 1, 2, 4, 8K variants.
615 * For now, cover the worst case of the 44x.
616 * Must be called with external interrupts disabled.
617 */
618#define CACHE_NWAYS 64
619#define CACHE_NLINES 16
620
621_GLOBAL(flush_dcache_all)
622 li r4, (2 * CACHE_NWAYS * CACHE_NLINES)
623 mtctr r4
624 lis r5, KERNELBASE@h
6251: lwz r3, 0(r5) /* Load one word from every line */
626 addi r5, r5, L1_CACHE_BYTES
627 bdnz 1b
628 blr
629#endif /* CONFIG_NOT_COHERENT_CACHE */
630
631/* 610/*
632 * Flush a particular page from the data cache to RAM. 611 * Flush a particular page from the data cache to RAM.
633 * Note: this is necessary because the instruction cache does *not* 612 * Note: this is necessary because the instruction cache does *not*
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index ae1433da09b2..ae48a002f81a 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -89,12 +89,12 @@ _GLOBAL(call_do_softirq)
89 mtlr r0 89 mtlr r0
90 blr 90 blr
91 91
92_GLOBAL(call_handle_IRQ_event) 92_GLOBAL(call___do_IRQ)
93 mflr r0 93 mflr r0
94 std r0,16(r1) 94 std r0,16(r1)
95 stdu r1,THREAD_SIZE-112(r6) 95 stdu r1,THREAD_SIZE-112(r5)
96 mr r1,r6 96 mr r1,r5
97 bl .handle_IRQ_event 97 bl .__do_IRQ
98 ld r1,0(r1) 98 ld r1,0(r1)
99 ld r0,16(r1) 99 ld r0,16(r1)
100 mtlr r0 100 mtlr r0
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
new file mode 100644
index 000000000000..3cf2517c5f91
--- /dev/null
+++ b/arch/powerpc/kernel/paca.c
@@ -0,0 +1,142 @@
1/*
2 * c 2001 PPC 64 Team, IBM Corp
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <linux/config.h>
11#include <linux/types.h>
12#include <linux/threads.h>
13#include <linux/module.h>
14
15#include <asm/processor.h>
16#include <asm/ptrace.h>
17#include <asm/page.h>
18#include <asm/systemcfg.h>
19#include <asm/lppaca.h>
20#include <asm/iseries/it_lp_queue.h>
21#include <asm/paca.h>
22
23static union {
24 struct systemcfg data;
25 u8 page[PAGE_SIZE];
26} systemcfg_store __attribute__((__section__(".data.page.aligned")));
27struct systemcfg *_systemcfg = &systemcfg_store.data;
28
29
30/* This symbol is provided by the linker - let it fill in the paca
31 * field correctly */
32extern unsigned long __toc_start;
33
34/* The Paca is an array with one entry per processor. Each contains an
35 * lppaca, which contains the information shared between the
36 * hypervisor and Linux. Each also contains an ItLpRegSave area which
37 * is used by the hypervisor to save registers.
38 * On systems with hardware multi-threading, there are two threads
39 * per processor. The Paca array must contain an entry for each thread.
40 * The VPD Areas will give a max logical processors = 2 * max physical
41 * processors. The processor VPD array needs one entry per physical
42 * processor (not thread).
43 */
44#define PACA_INIT_COMMON(number, start, asrr, asrv) \
45 .lock_token = 0x8000, \
46 .paca_index = (number), /* Paca Index */ \
47 .default_decr = 0x00ff0000, /* Initial Decr */ \
48 .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
49 .stab_real = (asrr), /* Real pointer to segment table */ \
50 .stab_addr = (asrv), /* Virt pointer to segment table */ \
51 .cpu_start = (start), /* Processor start */ \
52 .hw_cpu_id = 0xffff, \
53 .lppaca = { \
54 .desc = 0xd397d781, /* "LpPa" */ \
55 .size = sizeof(struct lppaca), \
56 .dyn_proc_status = 2, \
57 .decr_val = 0x00ff0000, \
58 .fpregs_in_use = 1, \
59 .end_of_quantum = 0xfffffffffffffffful, \
60 .slb_count = 64, \
61 .vmxregs_in_use = 0, \
62 }, \
63
64#ifdef CONFIG_PPC_ISERIES
65#define PACA_INIT_ISERIES(number) \
66 .lppaca_ptr = &paca[number].lppaca, \
67 .reg_save_ptr = &paca[number].reg_save, \
68 .reg_save = { \
69 .xDesc = 0xd397d9e2, /* "LpRS" */ \
70 .xSize = sizeof(struct ItLpRegSave) \
71 }
72
73#define PACA_INIT(number) \
74{ \
75 PACA_INIT_COMMON(number, 0, 0, 0) \
76 PACA_INIT_ISERIES(number) \
77}
78
79#define BOOTCPU_PACA_INIT(number) \
80{ \
81 PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \
82 PACA_INIT_ISERIES(number) \
83}
84
85#else
86#define PACA_INIT(number) \
87{ \
88 PACA_INIT_COMMON(number, 0, 0, 0) \
89}
90
91#define BOOTCPU_PACA_INIT(number) \
92{ \
93 PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \
94}
95#endif
96
97struct paca_struct paca[] = {
98 BOOTCPU_PACA_INIT(0),
99#if NR_CPUS > 1
100 PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3),
101#if NR_CPUS > 4
102 PACA_INIT( 4), PACA_INIT( 5), PACA_INIT( 6), PACA_INIT( 7),
103#if NR_CPUS > 8
104 PACA_INIT( 8), PACA_INIT( 9), PACA_INIT( 10), PACA_INIT( 11),
105 PACA_INIT( 12), PACA_INIT( 13), PACA_INIT( 14), PACA_INIT( 15),
106 PACA_INIT( 16), PACA_INIT( 17), PACA_INIT( 18), PACA_INIT( 19),
107 PACA_INIT( 20), PACA_INIT( 21), PACA_INIT( 22), PACA_INIT( 23),
108 PACA_INIT( 24), PACA_INIT( 25), PACA_INIT( 26), PACA_INIT( 27),
109 PACA_INIT( 28), PACA_INIT( 29), PACA_INIT( 30), PACA_INIT( 31),
110#if NR_CPUS > 32
111 PACA_INIT( 32), PACA_INIT( 33), PACA_INIT( 34), PACA_INIT( 35),
112 PACA_INIT( 36), PACA_INIT( 37), PACA_INIT( 38), PACA_INIT( 39),
113 PACA_INIT( 40), PACA_INIT( 41), PACA_INIT( 42), PACA_INIT( 43),
114 PACA_INIT( 44), PACA_INIT( 45), PACA_INIT( 46), PACA_INIT( 47),
115 PACA_INIT( 48), PACA_INIT( 49), PACA_INIT( 50), PACA_INIT( 51),
116 PACA_INIT( 52), PACA_INIT( 53), PACA_INIT( 54), PACA_INIT( 55),
117 PACA_INIT( 56), PACA_INIT( 57), PACA_INIT( 58), PACA_INIT( 59),
118 PACA_INIT( 60), PACA_INIT( 61), PACA_INIT( 62), PACA_INIT( 63),
119#if NR_CPUS > 64
120 PACA_INIT( 64), PACA_INIT( 65), PACA_INIT( 66), PACA_INIT( 67),
121 PACA_INIT( 68), PACA_INIT( 69), PACA_INIT( 70), PACA_INIT( 71),
122 PACA_INIT( 72), PACA_INIT( 73), PACA_INIT( 74), PACA_INIT( 75),
123 PACA_INIT( 76), PACA_INIT( 77), PACA_INIT( 78), PACA_INIT( 79),
124 PACA_INIT( 80), PACA_INIT( 81), PACA_INIT( 82), PACA_INIT( 83),
125 PACA_INIT( 84), PACA_INIT( 85), PACA_INIT( 86), PACA_INIT( 87),
126 PACA_INIT( 88), PACA_INIT( 89), PACA_INIT( 90), PACA_INIT( 91),
127 PACA_INIT( 92), PACA_INIT( 93), PACA_INIT( 94), PACA_INIT( 95),
128 PACA_INIT( 96), PACA_INIT( 97), PACA_INIT( 98), PACA_INIT( 99),
129 PACA_INIT(100), PACA_INIT(101), PACA_INIT(102), PACA_INIT(103),
130 PACA_INIT(104), PACA_INIT(105), PACA_INIT(106), PACA_INIT(107),
131 PACA_INIT(108), PACA_INIT(109), PACA_INIT(110), PACA_INIT(111),
132 PACA_INIT(112), PACA_INIT(113), PACA_INIT(114), PACA_INIT(115),
133 PACA_INIT(116), PACA_INIT(117), PACA_INIT(118), PACA_INIT(119),
134 PACA_INIT(120), PACA_INIT(121), PACA_INIT(122), PACA_INIT(123),
135 PACA_INIT(124), PACA_INIT(125), PACA_INIT(126), PACA_INIT(127),
136#endif
137#endif
138#endif
139#endif
140#endif
141};
142EXPORT_SYMBOL(paca);
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 47d6f7e2ea9f..5dcf4ba05ee8 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -44,6 +44,7 @@
44#include <asm/cputable.h> 44#include <asm/cputable.h>
45#include <asm/btext.h> 45#include <asm/btext.h>
46#include <asm/div64.h> 46#include <asm/div64.h>
47#include <asm/signal.h>
47 48
48#ifdef CONFIG_8xx 49#ifdef CONFIG_8xx
49#include <asm/commproc.h> 50#include <asm/commproc.h>
@@ -56,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs);
56extern void alignment_exception(struct pt_regs *regs); 57extern void alignment_exception(struct pt_regs *regs);
57extern void program_check_exception(struct pt_regs *regs); 58extern void program_check_exception(struct pt_regs *regs);
58extern void single_step_exception(struct pt_regs *regs); 59extern void single_step_exception(struct pt_regs *regs);
59extern int do_signal(sigset_t *, struct pt_regs *);
60extern int pmac_newworld; 60extern int pmac_newworld;
61extern int sys_sigreturn(struct pt_regs *regs); 61extern int sys_sigreturn(struct pt_regs *regs);
62 62
@@ -188,9 +188,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
188EXPORT_SYMBOL(cuda_request); 188EXPORT_SYMBOL(cuda_request);
189EXPORT_SYMBOL(cuda_poll); 189EXPORT_SYMBOL(cuda_poll);
190#endif /* CONFIG_ADB_CUDA */ 190#endif /* CONFIG_ADB_CUDA */
191#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32)
192EXPORT_SYMBOL(_machine);
193#endif
194#ifdef CONFIG_PPC_PMAC 191#ifdef CONFIG_PPC_PMAC
195EXPORT_SYMBOL(sys_ctrler); 192EXPORT_SYMBOL(sys_ctrler);
196#endif 193#endif
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
new file mode 100644
index 000000000000..a1c19502fe8b
--- /dev/null
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -0,0 +1,126 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <linux/config.h>
20#include <linux/init.h>
21#include <linux/mm.h>
22#include <linux/proc_fs.h>
23#include <linux/slab.h>
24#include <linux/kernel.h>
25
26#include <asm/systemcfg.h>
27#include <asm/rtas.h>
28#include <asm/uaccess.h>
29#include <asm/prom.h>
30
31static loff_t page_map_seek( struct file *file, loff_t off, int whence);
32static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
33 loff_t *ppos);
34static int page_map_mmap( struct file *file, struct vm_area_struct *vma );
35
36static struct file_operations page_map_fops = {
37 .llseek = page_map_seek,
38 .read = page_map_read,
39 .mmap = page_map_mmap
40};
41
42/*
43 * Create the ppc64 and ppc64/rtas directories early. This allows us to
44 * assume that they have been previously created in drivers.
45 */
46static int __init proc_ppc64_create(void)
47{
48 struct proc_dir_entry *root;
49
50 root = proc_mkdir("ppc64", NULL);
51 if (!root)
52 return 1;
53
54 if (!(platform_is_pseries() || _machine == PLATFORM_CELL))
55 return 0;
56
57 if (!proc_mkdir("rtas", root))
58 return 1;
59
60 if (!proc_symlink("rtas", NULL, "ppc64/rtas"))
61 return 1;
62
63 return 0;
64}
65core_initcall(proc_ppc64_create);
66
67static int __init proc_ppc64_init(void)
68{
69 struct proc_dir_entry *pde;
70
71 pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL);
72 if (!pde)
73 return 1;
74 pde->nlink = 1;
75 pde->data = _systemcfg;
76 pde->size = PAGE_SIZE;
77 pde->proc_fops = &page_map_fops;
78
79 return 0;
80}
81__initcall(proc_ppc64_init);
82
83static loff_t page_map_seek( struct file *file, loff_t off, int whence)
84{
85 loff_t new;
86 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
87
88 switch(whence) {
89 case 0:
90 new = off;
91 break;
92 case 1:
93 new = file->f_pos + off;
94 break;
95 case 2:
96 new = dp->size + off;
97 break;
98 default:
99 return -EINVAL;
100 }
101 if ( new < 0 || new > dp->size )
102 return -EINVAL;
103 return (file->f_pos = new);
104}
105
106static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
107 loff_t *ppos)
108{
109 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
110 return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
111}
112
113static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
114{
115 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
116
117 vma->vm_flags |= VM_SHM | VM_LOCKED;
118
119 if ((vma->vm_end - vma->vm_start) > dp->size)
120 return -EINVAL;
121
122 remap_pfn_range(vma, vma->vm_start, __pa(dp->data) >> PAGE_SHIFT,
123 dp->size, vma->vm_page_prot);
124 return 0;
125}
126
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f645adb57534..6a5b468edb4d 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -48,9 +48,6 @@
48#include <asm/machdep.h> 48#include <asm/machdep.h>
49#include <asm/pSeries_reconfig.h> 49#include <asm/pSeries_reconfig.h>
50#include <asm/pci-bridge.h> 50#include <asm/pci-bridge.h>
51#ifdef CONFIG_PPC64
52#include <asm/systemcfg.h>
53#endif
54 51
55#ifdef DEBUG 52#ifdef DEBUG
56#define DBG(fmt...) printk(KERN_ERR fmt) 53#define DBG(fmt...) printk(KERN_ERR fmt)
@@ -74,10 +71,6 @@ struct isa_reg_property {
74typedef int interpret_func(struct device_node *, unsigned long *, 71typedef int interpret_func(struct device_node *, unsigned long *,
75 int, int, int); 72 int, int, int);
76 73
77extern struct rtas_t rtas;
78extern struct lmb lmb;
79extern unsigned long klimit;
80
81static int __initdata dt_root_addr_cells; 74static int __initdata dt_root_addr_cells;
82static int __initdata dt_root_size_cells; 75static int __initdata dt_root_size_cells;
83 76
@@ -391,7 +384,7 @@ static int __devinit finish_node_interrupts(struct device_node *np,
391 384
392#ifdef CONFIG_PPC64 385#ifdef CONFIG_PPC64
393 /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ 386 /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */
394 if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { 387 if (_machine == PLATFORM_POWERMAC && ic && ic->parent) {
395 char *name = get_property(ic->parent, "name", NULL); 388 char *name = get_property(ic->parent, "name", NULL);
396 if (name && !strcmp(name, "u3")) 389 if (name && !strcmp(name, "u3"))
397 np->intrs[intrcount].line += 128; 390 np->intrs[intrcount].line += 128;
@@ -1087,9 +1080,9 @@ void __init unflatten_device_tree(void)
1087static int __init early_init_dt_scan_cpus(unsigned long node, 1080static int __init early_init_dt_scan_cpus(unsigned long node,
1088 const char *uname, int depth, void *data) 1081 const char *uname, int depth, void *data)
1089{ 1082{
1090 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
1091 u32 *prop; 1083 u32 *prop;
1092 unsigned long size = 0; 1084 unsigned long size;
1085 char *type = of_get_flat_dt_prop(node, "device_type", &size);
1093 1086
1094 /* We are scanning "cpu" nodes only */ 1087 /* We are scanning "cpu" nodes only */
1095 if (type == NULL || strcmp(type, "cpu") != 0) 1088 if (type == NULL || strcmp(type, "cpu") != 0)
@@ -1115,7 +1108,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
1115 1108
1116#ifdef CONFIG_ALTIVEC 1109#ifdef CONFIG_ALTIVEC
1117 /* Check if we have a VMX and eventually update CPU features */ 1110 /* Check if we have a VMX and eventually update CPU features */
1118 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size); 1111 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL);
1119 if (prop && (*prop) > 0) { 1112 if (prop && (*prop) > 0) {
1120 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; 1113 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
1121 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; 1114 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
@@ -1161,13 +1154,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1161 prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); 1154 prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
1162 if (prop == NULL) 1155 if (prop == NULL)
1163 return 0; 1156 return 0;
1164#ifdef CONFIG_PPC64
1165 systemcfg->platform = *prop;
1166#else
1167#ifdef CONFIG_PPC_MULTIPLATFORM 1157#ifdef CONFIG_PPC_MULTIPLATFORM
1168 _machine = *prop; 1158 _machine = *prop;
1169#endif 1159#endif
1170#endif
1171 1160
1172#ifdef CONFIG_PPC64 1161#ifdef CONFIG_PPC64
1173 /* check if iommu is forced on or off */ 1162 /* check if iommu is forced on or off */
@@ -1264,7 +1253,14 @@ static int __init early_init_dt_scan_memory(unsigned long node,
1264 unsigned long l; 1253 unsigned long l;
1265 1254
1266 /* We are scanning "memory" nodes only */ 1255 /* We are scanning "memory" nodes only */
1267 if (type == NULL || strcmp(type, "memory") != 0) 1256 if (type == NULL) {
1257 /*
1258 * The longtrail doesn't have a device_type on the
1259 * /memory node, so look for the node called /memory@0.
1260 */
1261 if (depth != 1 || strcmp(uname, "memory@0") != 0)
1262 return 0;
1263 } else if (strcmp(type, "memory") != 0)
1268 return 0; 1264 return 0;
1269 1265
1270 reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); 1266 reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
@@ -1339,9 +1335,6 @@ void __init early_init_devtree(void *params)
1339 of_scan_flat_dt(early_init_dt_scan_memory, NULL); 1335 of_scan_flat_dt(early_init_dt_scan_memory, NULL);
1340 lmb_enforce_memory_limit(memory_limit); 1336 lmb_enforce_memory_limit(memory_limit);
1341 lmb_analyze(); 1337 lmb_analyze();
1342#ifdef CONFIG_PPC64
1343 systemcfg->physicalMemorySize = lmb_phys_mem_size();
1344#endif
1345 lmb_reserve(0, __pa(klimit)); 1338 lmb_reserve(0, __pa(klimit));
1346 1339
1347 DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); 1340 DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
@@ -1908,7 +1901,7 @@ static int of_finish_dynamic_node(struct device_node *node,
1908 /* We don't support that function on PowerMac, at least 1901 /* We don't support that function on PowerMac, at least
1909 * not yet 1902 * not yet
1910 */ 1903 */
1911 if (systemcfg->platform == PLATFORM_POWERMAC) 1904 if (_machine == PLATFORM_POWERMAC)
1912 return -ENODEV; 1905 return -ENODEV;
1913 1906
1914 /* fix up new node's linux_phandle field */ 1907 /* fix up new node's linux_phandle field */
@@ -1992,9 +1985,11 @@ int prom_add_property(struct device_node* np, struct property* prop)
1992 *next = prop; 1985 *next = prop;
1993 write_unlock(&devtree_lock); 1986 write_unlock(&devtree_lock);
1994 1987
1988#ifdef CONFIG_PROC_DEVICETREE
1995 /* try to add to proc as well if it was initialized */ 1989 /* try to add to proc as well if it was initialized */
1996 if (np->pde) 1990 if (np->pde)
1997 proc_device_tree_add_prop(np->pde, prop); 1991 proc_device_tree_add_prop(np->pde, prop);
1992#endif /* CONFIG_PROC_DEVICETREE */
1998 1993
1999 return 0; 1994 return 0;
2000} 1995}
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 6dc33d19fc2a..4ce0105c308e 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224;
94#ifdef CONFIG_PPC64 94#ifdef CONFIG_PPC64
95#define RELOC(x) (*PTRRELOC(&(x))) 95#define RELOC(x) (*PTRRELOC(&(x)))
96#define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) 96#define ADDR(x) (u32) add_reloc_offset((unsigned long)(x))
97#define OF_WORKAROUNDS 0
97#else 98#else
98#define RELOC(x) (x) 99#define RELOC(x) (x)
99#define ADDR(x) (u32) (x) 100#define ADDR(x) (u32) (x)
101#define OF_WORKAROUNDS of_workarounds
102int of_workarounds;
100#endif 103#endif
101 104
105#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
106#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */
107
102#define PROM_BUG() do { \ 108#define PROM_BUG() do { \
103 prom_printf("kernel BUG at %s line 0x%x!\n", \ 109 prom_printf("kernel BUG at %s line 0x%x!\n", \
104 RELOC(__FILE__), __LINE__); \ 110 RELOC(__FILE__), __LINE__); \
@@ -111,11 +117,6 @@ extern const struct linux_logo logo_linux_clut224;
111#define prom_debug(x...) 117#define prom_debug(x...)
112#endif 118#endif
113 119
114#ifdef CONFIG_PPC32
115#define PLATFORM_POWERMAC _MACH_Pmac
116#define PLATFORM_CHRP _MACH_chrp
117#endif
118
119 120
120typedef u32 prom_arg_t; 121typedef u32 prom_arg_t;
121 122
@@ -128,10 +129,11 @@ struct prom_args {
128 129
129struct prom_t { 130struct prom_t {
130 ihandle root; 131 ihandle root;
131 ihandle chosen; 132 phandle chosen;
132 int cpu; 133 int cpu;
133 ihandle stdout; 134 ihandle stdout;
134 ihandle mmumap; 135 ihandle mmumap;
136 ihandle memory;
135}; 137};
136 138
137struct mem_map_entry { 139struct mem_map_entry {
@@ -360,16 +362,36 @@ static void __init prom_printf(const char *format, ...)
360static unsigned int __init prom_claim(unsigned long virt, unsigned long size, 362static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
361 unsigned long align) 363 unsigned long align)
362{ 364{
363 int ret;
364 struct prom_t *_prom = &RELOC(prom); 365 struct prom_t *_prom = &RELOC(prom);
365 366
366 ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, 367 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
367 (prom_arg_t)align); 368 /*
368 if (ret != -1 && _prom->mmumap != 0) 369 * Old OF requires we claim physical and virtual separately
369 /* old pmacs need us to map as well */ 370 * and then map explicitly (assuming virtual mode)
371 */
372 int ret;
373 prom_arg_t result;
374
375 ret = call_prom_ret("call-method", 5, 2, &result,
376 ADDR("claim"), _prom->memory,
377 align, size, virt);
378 if (ret != 0 || result == -1)
379 return -1;
380 ret = call_prom_ret("call-method", 5, 2, &result,
381 ADDR("claim"), _prom->mmumap,
382 align, size, virt);
383 if (ret != 0) {
384 call_prom("call-method", 4, 1, ADDR("release"),
385 _prom->memory, size, virt);
386 return -1;
387 }
388 /* the 0x12 is M (coherence) + PP == read/write */
370 call_prom("call-method", 6, 1, 389 call_prom("call-method", 6, 1,
371 ADDR("map"), _prom->mmumap, 0, size, virt, virt); 390 ADDR("map"), _prom->mmumap, 0x12, size, virt, virt);
372 return ret; 391 return virt;
392 }
393 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
394 (prom_arg_t)align);
373} 395}
374 396
375static void __init __attribute__((noreturn)) prom_panic(const char *reason) 397static void __init __attribute__((noreturn)) prom_panic(const char *reason)
@@ -415,11 +437,52 @@ static int inline prom_getproplen(phandle node, const char *pname)
415 return call_prom("getproplen", 2, 1, node, ADDR(pname)); 437 return call_prom("getproplen", 2, 1, node, ADDR(pname));
416} 438}
417 439
418static int inline prom_setprop(phandle node, const char *pname, 440static void add_string(char **str, const char *q)
419 void *value, size_t valuelen)
420{ 441{
421 return call_prom("setprop", 4, 1, node, ADDR(pname), 442 char *p = *str;
422 (u32)(unsigned long) value, (u32) valuelen); 443
444 while (*q)
445 *p++ = *q++;
446 *p++ = ' ';
447 *str = p;
448}
449
450static char *tohex(unsigned int x)
451{
452 static char digits[] = "0123456789abcdef";
453 static char result[9];
454 int i;
455
456 result[8] = 0;
457 i = 8;
458 do {
459 --i;
460 result[i] = digits[x & 0xf];
461 x >>= 4;
462 } while (x != 0 && i > 0);
463 return &result[i];
464}
465
466static int __init prom_setprop(phandle node, const char *nodename,
467 const char *pname, void *value, size_t valuelen)
468{
469 char cmd[256], *p;
470
471 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
472 return call_prom("setprop", 4, 1, node, ADDR(pname),
473 (u32)(unsigned long) value, (u32) valuelen);
474
475 /* gah... setprop doesn't work on longtrail, have to use interpret */
476 p = cmd;
477 add_string(&p, "dev");
478 add_string(&p, nodename);
479 add_string(&p, tohex((u32)(unsigned long) value));
480 add_string(&p, tohex(valuelen));
481 add_string(&p, tohex(ADDR(pname)));
482 add_string(&p, tohex(strlen(RELOC(pname))));
483 add_string(&p, "property");
484 *p = 0;
485 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
423} 486}
424 487
425/* We can't use the standard versions because of RELOC headaches. */ 488/* We can't use the standard versions because of RELOC headaches. */
@@ -980,7 +1043,7 @@ static void __init prom_instantiate_rtas(void)
980 1043
981 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); 1044 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
982 if (!IHANDLE_VALID(rtas_inst)) { 1045 if (!IHANDLE_VALID(rtas_inst)) {
983 prom_printf("opening rtas package failed"); 1046 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
984 return; 1047 return;
985 } 1048 }
986 1049
@@ -988,7 +1051,7 @@ static void __init prom_instantiate_rtas(void)
988 1051
989 if (call_prom_ret("call-method", 3, 2, &entry, 1052 if (call_prom_ret("call-method", 3, 2, &entry,
990 ADDR("instantiate-rtas"), 1053 ADDR("instantiate-rtas"),
991 rtas_inst, base) == PROM_ERROR 1054 rtas_inst, base) != 0
992 || entry == 0) { 1055 || entry == 0) {
993 prom_printf(" failed\n"); 1056 prom_printf(" failed\n");
994 return; 1057 return;
@@ -997,8 +1060,10 @@ static void __init prom_instantiate_rtas(void)
997 1060
998 reserve_mem(base, size); 1061 reserve_mem(base, size);
999 1062
1000 prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); 1063 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
1001 prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); 1064 &base, sizeof(base));
1065 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
1066 &entry, sizeof(entry));
1002 1067
1003 prom_debug("rtas base = 0x%x\n", base); 1068 prom_debug("rtas base = 0x%x\n", base);
1004 prom_debug("rtas entry = 0x%x\n", entry); 1069 prom_debug("rtas entry = 0x%x\n", entry);
@@ -1089,10 +1154,6 @@ static void __init prom_initialize_tce_table(void)
1089 if (base < local_alloc_bottom) 1154 if (base < local_alloc_bottom)
1090 local_alloc_bottom = base; 1155 local_alloc_bottom = base;
1091 1156
1092 /* Save away the TCE table attributes for later use. */
1093 prom_setprop(node, "linux,tce-base", &base, sizeof(base));
1094 prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
1095
1096 /* It seems OF doesn't null-terminate the path :-( */ 1157 /* It seems OF doesn't null-terminate the path :-( */
1097 memset(path, 0, sizeof(path)); 1158 memset(path, 0, sizeof(path));
1098 /* Call OF to setup the TCE hardware */ 1159 /* Call OF to setup the TCE hardware */
@@ -1101,6 +1162,10 @@ static void __init prom_initialize_tce_table(void)
1101 prom_printf("package-to-path failed\n"); 1162 prom_printf("package-to-path failed\n");
1102 } 1163 }
1103 1164
1165 /* Save away the TCE table attributes for later use. */
1166 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1167 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1168
1104 prom_debug("TCE table: %s\n", path); 1169 prom_debug("TCE table: %s\n", path);
1105 prom_debug("\tnode = 0x%x\n", node); 1170 prom_debug("\tnode = 0x%x\n", node);
1106 prom_debug("\tbase = 0x%x\n", base); 1171 prom_debug("\tbase = 0x%x\n", base);
@@ -1342,6 +1407,7 @@ static void __init prom_init_client_services(unsigned long pp)
1342/* 1407/*
1343 * For really old powermacs, we need to map things we claim. 1408 * For really old powermacs, we need to map things we claim.
1344 * For that, we need the ihandle of the mmu. 1409 * For that, we need the ihandle of the mmu.
1410 * Also, on the longtrail, we need to work around other bugs.
1345 */ 1411 */
1346static void __init prom_find_mmu(void) 1412static void __init prom_find_mmu(void)
1347{ 1413{
@@ -1355,12 +1421,19 @@ static void __init prom_find_mmu(void)
1355 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) 1421 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
1356 return; 1422 return;
1357 version[sizeof(version) - 1] = 0; 1423 version[sizeof(version) - 1] = 0;
1358 prom_printf("OF version is '%s'\n", version);
1359 /* XXX might need to add other versions here */ 1424 /* XXX might need to add other versions here */
1360 if (strcmp(version, "Open Firmware, 1.0.5") != 0) 1425 if (strcmp(version, "Open Firmware, 1.0.5") == 0)
1426 of_workarounds = OF_WA_CLAIM;
1427 else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
1428 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
1429 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
1430 } else
1361 return; 1431 return;
1432 _prom->memory = call_prom("open", 1, 1, ADDR("/memory"));
1362 prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, 1433 prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
1363 sizeof(_prom->mmumap)); 1434 sizeof(_prom->mmumap));
1435 if (!IHANDLE_VALID(_prom->memory) || !IHANDLE_VALID(_prom->mmumap))
1436 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
1364} 1437}
1365#else 1438#else
1366#define prom_find_mmu() 1439#define prom_find_mmu()
@@ -1382,16 +1455,17 @@ static void __init prom_init_stdout(void)
1382 memset(path, 0, 256); 1455 memset(path, 0, 256);
1383 call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); 1456 call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
1384 val = call_prom("instance-to-package", 1, 1, _prom->stdout); 1457 val = call_prom("instance-to-package", 1, 1, _prom->stdout);
1385 prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); 1458 prom_setprop(_prom->chosen, "/chosen", "linux,stdout-package",
1459 &val, sizeof(val));
1386 prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); 1460 prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
1387 prom_setprop(_prom->chosen, "linux,stdout-path", 1461 prom_setprop(_prom->chosen, "/chosen", "linux,stdout-path",
1388 RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); 1462 path, strlen(path) + 1);
1389 1463
1390 /* If it's a display, note it */ 1464 /* If it's a display, note it */
1391 memset(type, 0, sizeof(type)); 1465 memset(type, 0, sizeof(type));
1392 prom_getprop(val, "device_type", type, sizeof(type)); 1466 prom_getprop(val, "device_type", type, sizeof(type));
1393 if (strcmp(type, RELOC("display")) == 0) 1467 if (strcmp(type, RELOC("display")) == 0)
1394 prom_setprop(val, "linux,boot-display", NULL, 0); 1468 prom_setprop(val, path, "linux,boot-display", NULL, 0);
1395} 1469}
1396 1470
1397static void __init prom_close_stdin(void) 1471static void __init prom_close_stdin(void)
@@ -1514,7 +1588,7 @@ static void __init prom_check_displays(void)
1514 1588
1515 /* Success */ 1589 /* Success */
1516 prom_printf("done\n"); 1590 prom_printf("done\n");
1517 prom_setprop(node, "linux,opened", NULL, 0); 1591 prom_setprop(node, path, "linux,opened", NULL, 0);
1518 1592
1519 /* Setup a usable color table when the appropriate 1593 /* Setup a usable color table when the appropriate
1520 * method is available. Should update this to set-colors */ 1594 * method is available. Should update this to set-colors */
@@ -1884,9 +1958,11 @@ static void __init fixup_device_tree(void)
1884 /* interrupt on this revision of u3 is number 0 and level */ 1958 /* interrupt on this revision of u3 is number 0 and level */
1885 interrupts[0] = 0; 1959 interrupts[0] = 0;
1886 interrupts[1] = 1; 1960 interrupts[1] = 1;
1887 prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); 1961 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
1962 &interrupts, sizeof(interrupts));
1888 parent = (u32)mpic; 1963 parent = (u32)mpic;
1889 prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); 1964 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
1965 &parent, sizeof(parent));
1890#endif 1966#endif
1891} 1967}
1892 1968
@@ -1922,11 +1998,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
1922 RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; 1998 RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
1923 1999
1924 val = RELOC(prom_initrd_start); 2000 val = RELOC(prom_initrd_start);
1925 prom_setprop(_prom->chosen, "linux,initrd-start", &val, 2001 prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",
1926 sizeof(val)); 2002 &val, sizeof(val));
1927 val = RELOC(prom_initrd_end); 2003 val = RELOC(prom_initrd_end);
1928 prom_setprop(_prom->chosen, "linux,initrd-end", &val, 2004 prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",
1929 sizeof(val)); 2005 &val, sizeof(val));
1930 2006
1931 reserve_mem(RELOC(prom_initrd_start), 2007 reserve_mem(RELOC(prom_initrd_start),
1932 RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); 2008 RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
@@ -1969,14 +2045,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
1969 prom_init_client_services(pp); 2045 prom_init_client_services(pp);
1970 2046
1971 /* 2047 /*
1972 * Init prom stdout device 2048 * See if this OF is old enough that we need to do explicit maps
2049 * and other workarounds
1973 */ 2050 */
1974 prom_init_stdout(); 2051 prom_find_mmu();
1975 2052
1976 /* 2053 /*
1977 * See if this OF is old enough that we need to do explicit maps 2054 * Init prom stdout device
1978 */ 2055 */
1979 prom_find_mmu(); 2056 prom_init_stdout();
1980 2057
1981 /* 2058 /*
1982 * Check for an initrd 2059 * Check for an initrd
@@ -1989,14 +2066,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
1989 */ 2066 */
1990 RELOC(of_platform) = prom_find_machine_type(); 2067 RELOC(of_platform) = prom_find_machine_type();
1991 getprop_rval = RELOC(of_platform); 2068 getprop_rval = RELOC(of_platform);
1992 prom_setprop(_prom->chosen, "linux,platform", 2069 prom_setprop(_prom->chosen, "/chosen", "linux,platform",
1993 &getprop_rval, sizeof(getprop_rval)); 2070 &getprop_rval, sizeof(getprop_rval));
1994 2071
1995#ifdef CONFIG_PPC_PSERIES 2072#ifdef CONFIG_PPC_PSERIES
1996 /* 2073 /*
1997 * On pSeries, inform the firmware about our capabilities 2074 * On pSeries, inform the firmware about our capabilities
1998 */ 2075 */
1999 if (RELOC(of_platform) & PLATFORM_PSERIES) 2076 if (RELOC(of_platform) == PLATFORM_PSERIES ||
2077 RELOC(of_platform) == PLATFORM_PSERIES_LPAR)
2000 prom_send_capabilities(); 2078 prom_send_capabilities();
2001#endif 2079#endif
2002 2080
@@ -2050,21 +2128,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2050 * Fill in some infos for use by the kernel later on 2128 * Fill in some infos for use by the kernel later on
2051 */ 2129 */
2052 if (RELOC(prom_memory_limit)) 2130 if (RELOC(prom_memory_limit))
2053 prom_setprop(_prom->chosen, "linux,memory-limit", 2131 prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
2054 &RELOC(prom_memory_limit), 2132 &RELOC(prom_memory_limit),
2055 sizeof(prom_memory_limit)); 2133 sizeof(prom_memory_limit));
2056#ifdef CONFIG_PPC64 2134#ifdef CONFIG_PPC64
2057 if (RELOC(ppc64_iommu_off)) 2135 if (RELOC(ppc64_iommu_off))
2058 prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); 2136 prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
2137 NULL, 0);
2059 2138
2060 if (RELOC(iommu_force_on)) 2139 if (RELOC(iommu_force_on))
2061 prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); 2140 prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on",
2141 NULL, 0);
2062 2142
2063 if (RELOC(prom_tce_alloc_start)) { 2143 if (RELOC(prom_tce_alloc_start)) {
2064 prom_setprop(_prom->chosen, "linux,tce-alloc-start", 2144 prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start",
2065 &RELOC(prom_tce_alloc_start), 2145 &RELOC(prom_tce_alloc_start),
2066 sizeof(prom_tce_alloc_start)); 2146 sizeof(prom_tce_alloc_start));
2067 prom_setprop(_prom->chosen, "linux,tce-alloc-end", 2147 prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end",
2068 &RELOC(prom_tce_alloc_end), 2148 &RELOC(prom_tce_alloc_end),
2069 sizeof(prom_tce_alloc_end)); 2149 sizeof(prom_tce_alloc_end));
2070 } 2150 }
@@ -2081,8 +2161,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2081 prom_printf("copying OF device tree ...\n"); 2161 prom_printf("copying OF device tree ...\n");
2082 flatten_device_tree(); 2162 flatten_device_tree();
2083 2163
2084 /* in case stdin is USB and still active on IBM machines... */ 2164 /*
2085 prom_close_stdin(); 2165 * in case stdin is USB and still active on IBM machines...
2166 * Unfortunately quiesce crashes on some powermacs if we have
2167 * closed stdin already (in particular the powerbook 101).
2168 */
2169 if (RELOC(of_platform) != PLATFORM_POWERMAC)
2170 prom_close_stdin();
2086 2171
2087 /* 2172 /*
2088 * Call OF "quiesce" method to shut down pending DMA's from 2173 * Call OF "quiesce" method to shut down pending DMA's from
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 5bdd5b079d96..ae1a36449ccd 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -259,7 +259,7 @@ static int __init proc_rtas_init(void)
259{ 259{
260 struct proc_dir_entry *entry; 260 struct proc_dir_entry *entry;
261 261
262 if (!(systemcfg->platform & PLATFORM_PSERIES)) 262 if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR)
263 return 1; 263 return 1;
264 264
265 rtas_node = of_find_node_by_name(NULL, "rtas"); 265 rtas_node = of_find_node_by_name(NULL, "rtas");
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 9d4e07f6f1ec..4283fa33f784 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -29,9 +29,6 @@
29#include <asm/delay.h> 29#include <asm/delay.h>
30#include <asm/uaccess.h> 30#include <asm/uaccess.h>
31#include <asm/lmb.h> 31#include <asm/lmb.h>
32#ifdef CONFIG_PPC64
33#include <asm/systemcfg.h>
34#endif
35 32
36struct rtas_t rtas = { 33struct rtas_t rtas = {
37 .lock = SPIN_LOCK_UNLOCKED 34 .lock = SPIN_LOCK_UNLOCKED
@@ -671,7 +668,7 @@ void __init rtas_initialize(void)
671 * the stop-self token if any 668 * the stop-self token if any
672 */ 669 */
673#ifdef CONFIG_PPC64 670#ifdef CONFIG_PPC64
674 if (systemcfg->platform == PLATFORM_PSERIES_LPAR) 671 if (_machine == PLATFORM_PSERIES_LPAR)
675 rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); 672 rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
676#endif 673#endif
677 rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); 674 rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
new file mode 100644
index 000000000000..0e5a8e116653
--- /dev/null
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -0,0 +1,513 @@
1/*
2 * arch/ppc64/kernel/rtas_pci.c
3 *
4 * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
5 * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
6 *
7 * RTAS specific routines for PCI.
8 *
9 * Based on code from pci.c, chrp_pci.c and pSeries_pci.c
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26#include <linux/kernel.h>
27#include <linux/threads.h>
28#include <linux/pci.h>
29#include <linux/string.h>
30#include <linux/init.h>
31#include <linux/bootmem.h>
32
33#include <asm/io.h>
34#include <asm/pgtable.h>
35#include <asm/irq.h>
36#include <asm/prom.h>
37#include <asm/machdep.h>
38#include <asm/pci-bridge.h>
39#include <asm/iommu.h>
40#include <asm/rtas.h>
41#include <asm/mpic.h>
42#include <asm/ppc-pci.h>
43
44/* RTAS tokens */
45static int read_pci_config;
46static int write_pci_config;
47static int ibm_read_pci_config;
48static int ibm_write_pci_config;
49
50static inline int config_access_valid(struct pci_dn *dn, int where)
51{
52 if (where < 256)
53 return 1;
54 if (where < 4096 && dn->pci_ext_config_space)
55 return 1;
56
57 return 0;
58}
59
60static int of_device_available(struct device_node * dn)
61{
62 char * status;
63
64 status = get_property(dn, "status", NULL);
65
66 if (!status)
67 return 1;
68
69 if (!strcmp(status, "okay"))
70 return 1;
71
72 return 0;
73}
74
75static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
76{
77 int returnval = -1;
78 unsigned long buid, addr;
79 int ret;
80
81 if (!pdn)
82 return PCIBIOS_DEVICE_NOT_FOUND;
83 if (!config_access_valid(pdn, where))
84 return PCIBIOS_BAD_REGISTER_NUMBER;
85
86 addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
87 (pdn->devfn << 8) | (where & 0xff);
88 buid = pdn->phb->buid;
89 if (buid) {
90 ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
91 addr, BUID_HI(buid), BUID_LO(buid), size);
92 } else {
93 ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
94 }
95 *val = returnval;
96
97 if (ret)
98 return PCIBIOS_DEVICE_NOT_FOUND;
99
100 if (returnval == EEH_IO_ERROR_VALUE(size) &&
101 eeh_dn_check_failure (pdn->node, NULL))
102 return PCIBIOS_DEVICE_NOT_FOUND;
103
104 return PCIBIOS_SUCCESSFUL;
105}
106
107static int rtas_pci_read_config(struct pci_bus *bus,
108 unsigned int devfn,
109 int where, int size, u32 *val)
110{
111 struct device_node *busdn, *dn;
112
113 if (bus->self)
114 busdn = pci_device_to_OF_node(bus->self);
115 else
116 busdn = bus->sysdata; /* must be a phb */
117
118 /* Search only direct children of the bus */
119 for (dn = busdn->child; dn; dn = dn->sibling) {
120 struct pci_dn *pdn = PCI_DN(dn);
121 if (pdn && pdn->devfn == devfn
122 && of_device_available(dn))
123 return rtas_read_config(pdn, where, size, val);
124 }
125
126 return PCIBIOS_DEVICE_NOT_FOUND;
127}
128
129int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val)
130{
131 unsigned long buid, addr;
132 int ret;
133
134 if (!pdn)
135 return PCIBIOS_DEVICE_NOT_FOUND;
136 if (!config_access_valid(pdn, where))
137 return PCIBIOS_BAD_REGISTER_NUMBER;
138
139 addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
140 (pdn->devfn << 8) | (where & 0xff);
141 buid = pdn->phb->buid;
142 if (buid) {
143 ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr,
144 BUID_HI(buid), BUID_LO(buid), size, (ulong) val);
145 } else {
146 ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
147 }
148
149 if (ret)
150 return PCIBIOS_DEVICE_NOT_FOUND;
151
152 return PCIBIOS_SUCCESSFUL;
153}
154
155static int rtas_pci_write_config(struct pci_bus *bus,
156 unsigned int devfn,
157 int where, int size, u32 val)
158{
159 struct device_node *busdn, *dn;
160
161 if (bus->self)
162 busdn = pci_device_to_OF_node(bus->self);
163 else
164 busdn = bus->sysdata; /* must be a phb */
165
166 /* Search only direct children of the bus */
167 for (dn = busdn->child; dn; dn = dn->sibling) {
168 struct pci_dn *pdn = PCI_DN(dn);
169 if (pdn && pdn->devfn == devfn
170 && of_device_available(dn))
171 return rtas_write_config(pdn, where, size, val);
172 }
173 return PCIBIOS_DEVICE_NOT_FOUND;
174}
175
176struct pci_ops rtas_pci_ops = {
177 rtas_pci_read_config,
178 rtas_pci_write_config
179};
180
181int is_python(struct device_node *dev)
182{
183 char *model = (char *)get_property(dev, "model", NULL);
184
185 if (model && strstr(model, "Python"))
186 return 1;
187
188 return 0;
189}
190
191static int get_phb_reg_prop(struct device_node *dev,
192 unsigned int addr_size_words,
193 struct reg_property64 *reg)
194{
195 unsigned int *ui_ptr = NULL, len;
196
197 /* Found a PHB, now figure out where his registers are mapped. */
198 ui_ptr = (unsigned int *)get_property(dev, "reg", &len);
199 if (ui_ptr == NULL)
200 return 1;
201
202 if (addr_size_words == 1) {
203 reg->address = ((struct reg_property32 *)ui_ptr)->address;
204 reg->size = ((struct reg_property32 *)ui_ptr)->size;
205 } else {
206 *reg = *((struct reg_property64 *)ui_ptr);
207 }
208
209 return 0;
210}
211
212static void python_countermeasures(struct device_node *dev,
213 unsigned int addr_size_words)
214{
215 struct reg_property64 reg_struct;
216 void __iomem *chip_regs;
217 volatile u32 val;
218
219 if (get_phb_reg_prop(dev, addr_size_words, &reg_struct))
220 return;
221
222 /* Python's register file is 1 MB in size. */
223 chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000);
224
225 /*
226 * Firmware doesn't always clear this bit which is critical
227 * for good performance - Anton
228 */
229
230#define PRG_CL_RESET_VALID 0x00010000
231
232 val = in_be32(chip_regs + 0xf6030);
233 if (val & PRG_CL_RESET_VALID) {
234 printk(KERN_INFO "Python workaround: ");
235 val &= ~PRG_CL_RESET_VALID;
236 out_be32(chip_regs + 0xf6030, val);
237 /*
238 * We must read it back for changes to
239 * take effect
240 */
241 val = in_be32(chip_regs + 0xf6030);
242 printk("reg0: %x\n", val);
243 }
244
245 iounmap(chip_regs);
246}
247
248void __init init_pci_config_tokens (void)
249{
250 read_pci_config = rtas_token("read-pci-config");
251 write_pci_config = rtas_token("write-pci-config");
252 ibm_read_pci_config = rtas_token("ibm,read-pci-config");
253 ibm_write_pci_config = rtas_token("ibm,write-pci-config");
254}
255
256unsigned long __devinit get_phb_buid (struct device_node *phb)
257{
258 int addr_cells;
259 unsigned int *buid_vals;
260 unsigned int len;
261 unsigned long buid;
262
263 if (ibm_read_pci_config == -1) return 0;
264
265 /* PHB's will always be children of the root node,
266 * or so it is promised by the current firmware. */
267 if (phb->parent == NULL)
268 return 0;
269 if (phb->parent->parent)
270 return 0;
271
272 buid_vals = (unsigned int *) get_property(phb, "reg", &len);
273 if (buid_vals == NULL)
274 return 0;
275
276 addr_cells = prom_n_addr_cells(phb);
277 if (addr_cells == 1) {
278 buid = (unsigned long) buid_vals[0];
279 } else {
280 buid = (((unsigned long)buid_vals[0]) << 32UL) |
281 (((unsigned long)buid_vals[1]) & 0xffffffff);
282 }
283 return buid;
284}
285
286static int phb_set_bus_ranges(struct device_node *dev,
287 struct pci_controller *phb)
288{
289 int *bus_range;
290 unsigned int len;
291
292 bus_range = (int *) get_property(dev, "bus-range", &len);
293 if (bus_range == NULL || len < 2 * sizeof(int)) {
294 return 1;
295 }
296
297 phb->first_busno = bus_range[0];
298 phb->last_busno = bus_range[1];
299
300 return 0;
301}
302
303static int __devinit setup_phb(struct device_node *dev,
304 struct pci_controller *phb,
305 unsigned int addr_size_words)
306{
307 pci_setup_pci_controller(phb);
308
309 if (is_python(dev))
310 python_countermeasures(dev, addr_size_words);
311
312 if (phb_set_bus_ranges(dev, phb))
313 return 1;
314
315 phb->arch_data = dev;
316 phb->ops = &rtas_pci_ops;
317 phb->buid = get_phb_buid(dev);
318
319 return 0;
320}
321
322static void __devinit add_linux_pci_domain(struct device_node *dev,
323 struct pci_controller *phb,
324 struct property *of_prop)
325{
326 memset(of_prop, 0, sizeof(struct property));
327 of_prop->name = "linux,pci-domain";
328 of_prop->length = sizeof(phb->global_number);
329 of_prop->value = (unsigned char *)&of_prop[1];
330 memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
331 prom_add_property(dev, of_prop);
332}
333
334static struct pci_controller * __init alloc_phb(struct device_node *dev,
335 unsigned int addr_size_words)
336{
337 struct pci_controller *phb;
338 struct property *of_prop;
339
340 phb = alloc_bootmem(sizeof(struct pci_controller));
341 if (phb == NULL)
342 return NULL;
343
344 of_prop = alloc_bootmem(sizeof(struct property) +
345 sizeof(phb->global_number));
346 if (!of_prop)
347 return NULL;
348
349 if (setup_phb(dev, phb, addr_size_words))
350 return NULL;
351
352 add_linux_pci_domain(dev, phb, of_prop);
353
354 return phb;
355}
356
357static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)
358{
359 struct pci_controller *phb;
360
361 phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
362 GFP_KERNEL);
363 if (phb == NULL)
364 return NULL;
365
366 if (setup_phb(dev, phb, addr_size_words))
367 return NULL;
368
369 phb->is_dynamic = 1;
370
371 /* TODO: linux,pci-domain? */
372
373 return phb;
374}
375
376unsigned long __init find_and_init_phbs(void)
377{
378 struct device_node *node;
379 struct pci_controller *phb;
380 unsigned int root_size_cells = 0;
381 unsigned int index;
382 unsigned int *opprop = NULL;
383 struct device_node *root = of_find_node_by_path("/");
384
385 if (ppc64_interrupt_controller == IC_OPEN_PIC) {
386 opprop = (unsigned int *)get_property(root,
387 "platform-open-pic", NULL);
388 }
389
390 root_size_cells = prom_n_size_cells(root);
391
392 index = 0;
393
394 for (node = of_get_next_child(root, NULL);
395 node != NULL;
396 node = of_get_next_child(root, node)) {
397 if (node->type == NULL || strcmp(node->type, "pci") != 0)
398 continue;
399
400 phb = alloc_phb(node, root_size_cells);
401 if (!phb)
402 continue;
403
404 pci_process_bridge_OF_ranges(phb, node, 0);
405 pci_setup_phb_io(phb, index == 0);
406#ifdef CONFIG_PPC_PSERIES
407 if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
408 int addr = root_size_cells * (index + 2) - 1;
409 mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
410 }
411#endif
412 index++;
413 }
414
415 of_node_put(root);
416 pci_devs_phb_init();
417
418 /*
419 * pci_probe_only and pci_assign_all_buses can be set via properties
420 * in chosen.
421 */
422 if (of_chosen) {
423 int *prop;
424
425 prop = (int *)get_property(of_chosen, "linux,pci-probe-only",
426 NULL);
427 if (prop)
428 pci_probe_only = *prop;
429
430 prop = (int *)get_property(of_chosen,
431 "linux,pci-assign-all-buses", NULL);
432 if (prop)
433 pci_assign_all_buses = *prop;
434 }
435
436 return 0;
437}
438
439struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
440{
441 struct device_node *root = of_find_node_by_path("/");
442 unsigned int root_size_cells = 0;
443 struct pci_controller *phb;
444 int primary;
445
446 root_size_cells = prom_n_size_cells(root);
447
448 primary = list_empty(&hose_list);
449 phb = alloc_phb_dynamic(dn, root_size_cells);
450 if (!phb)
451 return NULL;
452
453 pci_process_bridge_OF_ranges(phb, dn, primary);
454
455 pci_setup_phb_io_dynamic(phb, primary);
456 of_node_put(root);
457
458 pci_devs_phb_init_dynamic(phb);
459 scan_phb(phb);
460
461 return phb;
462}
463EXPORT_SYMBOL(init_phb_dynamic);
464
465/* RPA-specific bits for removing PHBs */
466int pcibios_remove_root_bus(struct pci_controller *phb)
467{
468 struct pci_bus *b = phb->bus;
469 struct resource *res;
470 int rc, i;
471
472 res = b->resource[0];
473 if (!res->flags) {
474 printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,
475 b->name);
476 return 1;
477 }
478
479 rc = unmap_bus_range(b);
480 if (rc) {
481 printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
482 __FUNCTION__, b->name);
483 return 1;
484 }
485
486 if (release_resource(res)) {
487 printk(KERN_ERR "%s: failed to release IO on bus %s\n",
488 __FUNCTION__, b->name);
489 return 1;
490 }
491
492 for (i = 1; i < 3; ++i) {
493 res = b->resource[i];
494 if (!res->flags && i == 0) {
495 printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
496 __FUNCTION__, b->name);
497 return 1;
498 }
499 if (res->flags && release_resource(res)) {
500 printk(KERN_ERR
501 "%s: failed to release IO %d on bus %s\n",
502 __FUNCTION__, i, b->name);
503 return 1;
504 }
505 }
506
507 list_del(&phb->list_node);
508 if (phb->is_dynamic)
509 kfree(phb);
510
511 return 0;
512}
513EXPORT_SYMBOL(pcibios_remove_root_bus);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index e22856ecb5a0..bae4bff138f1 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -33,6 +33,7 @@
33#include <asm/io.h> 33#include <asm/io.h>
34#include <asm/prom.h> 34#include <asm/prom.h>
35#include <asm/processor.h> 35#include <asm/processor.h>
36#include <asm/systemcfg.h>
36#include <asm/pgtable.h> 37#include <asm/pgtable.h>
37#include <asm/smp.h> 38#include <asm/smp.h>
38#include <asm/elf.h> 39#include <asm/elf.h>
@@ -51,6 +52,9 @@
51#include <asm/page.h> 52#include <asm/page.h>
52#include <asm/mmu.h> 53#include <asm/mmu.h>
53#include <asm/lmb.h> 54#include <asm/lmb.h>
55#include <asm/xmon.h>
56
57#include "setup.h"
54 58
55#undef DEBUG 59#undef DEBUG
56 60
@@ -60,6 +64,13 @@
60#define DBG(fmt...) 64#define DBG(fmt...)
61#endif 65#endif
62 66
67#ifdef CONFIG_PPC_MULTIPLATFORM
68int _machine = 0;
69EXPORT_SYMBOL(_machine);
70#endif
71
72unsigned long klimit = (unsigned long) _end;
73
63/* 74/*
64 * This still seems to be needed... -- paulus 75 * This still seems to be needed... -- paulus
65 */ 76 */
@@ -510,8 +521,8 @@ void __init smp_setup_cpu_maps(void)
510 * On pSeries LPAR, we need to know how many cpus 521 * On pSeries LPAR, we need to know how many cpus
511 * could possibly be added to this partition. 522 * could possibly be added to this partition.
512 */ 523 */
513 if (systemcfg->platform == PLATFORM_PSERIES_LPAR && 524 if (_machine == PLATFORM_PSERIES_LPAR &&
514 (dn = of_find_node_by_path("/rtas"))) { 525 (dn = of_find_node_by_path("/rtas"))) {
515 int num_addr_cell, num_size_cell, maxcpus; 526 int num_addr_cell, num_size_cell, maxcpus;
516 unsigned int *ireg; 527 unsigned int *ireg;
517 528
@@ -555,7 +566,27 @@ void __init smp_setup_cpu_maps(void)
555 cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); 566 cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
556 } 567 }
557 568
558 systemcfg->processorCount = num_present_cpus(); 569 _systemcfg->processorCount = num_present_cpus();
559#endif /* CONFIG_PPC64 */ 570#endif /* CONFIG_PPC64 */
560} 571}
561#endif /* CONFIG_SMP */ 572#endif /* CONFIG_SMP */
573
574#ifdef CONFIG_XMON
575static int __init early_xmon(char *p)
576{
577 /* ensure xmon is enabled */
578 if (p) {
579 if (strncmp(p, "on", 2) == 0)
580 xmon_init(1);
581 if (strncmp(p, "off", 3) == 0)
582 xmon_init(0);
583 if (strncmp(p, "early", 5) != 0)
584 return 0;
585 }
586 xmon_init(1);
587 debugger(NULL);
588
589 return 0;
590}
591early_param("xmon", early_xmon);
592#endif
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h
new file mode 100644
index 000000000000..2ebba755272e
--- /dev/null
+++ b/arch/powerpc/kernel/setup.h
@@ -0,0 +1,6 @@
1#ifndef _POWERPC_KERNEL_SETUP_H
2#define _POWERPC_KERNEL_SETUP_H
3
4void check_for_initrd(void);
5
6#endif /* _POWERPC_KERNEL_SETUP_H */
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 3af2631e3fab..c98cfcc9cd9a 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -40,6 +40,8 @@
40#include <asm/xmon.h> 40#include <asm/xmon.h>
41#include <asm/time.h> 41#include <asm/time.h>
42 42
43#include "setup.h"
44
43#define DBG(fmt...) 45#define DBG(fmt...)
44 46
45#if defined CONFIG_KGDB 47#if defined CONFIG_KGDB
@@ -70,8 +72,6 @@ unsigned int DMA_MODE_WRITE;
70int have_of = 1; 72int have_of = 1;
71 73
72#ifdef CONFIG_PPC_MULTIPLATFORM 74#ifdef CONFIG_PPC_MULTIPLATFORM
73int _machine = 0;
74
75extern void prep_init(void); 75extern void prep_init(void);
76extern void pmac_init(void); 76extern void pmac_init(void);
77extern void chrp_init(void); 77extern void chrp_init(void);
@@ -279,7 +279,6 @@ arch_initcall(ppc_init);
279/* Warning, IO base is not yet inited */ 279/* Warning, IO base is not yet inited */
280void __init setup_arch(char **cmdline_p) 280void __init setup_arch(char **cmdline_p)
281{ 281{
282 extern char *klimit;
283 extern void do_init_bootmem(void); 282 extern void do_init_bootmem(void);
284 283
285 /* so udelay does something sensible, assume <= 1000 bogomips */ 284 /* so udelay does something sensible, assume <= 1000 bogomips */
@@ -303,14 +302,9 @@ void __init setup_arch(char **cmdline_p)
303 pmac_feature_init(); /* New cool way */ 302 pmac_feature_init(); /* New cool way */
304#endif 303#endif
305 304
306#ifdef CONFIG_XMON 305#ifdef CONFIG_XMON_DEFAULT
307 xmon_map_scc(); 306 xmon_init(1);
308 if (strstr(cmd_line, "xmon")) { 307#endif
309 xmon_init(1);
310 debugger(NULL);
311 }
312#endif /* CONFIG_XMON */
313 if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
314 308
315#if defined(CONFIG_KGDB) 309#if defined(CONFIG_KGDB)
316 if (ppc_md.kgdb_map_scc) 310 if (ppc_md.kgdb_map_scc)
@@ -343,7 +337,7 @@ void __init setup_arch(char **cmdline_p)
343 init_mm.start_code = PAGE_OFFSET; 337 init_mm.start_code = PAGE_OFFSET;
344 init_mm.end_code = (unsigned long) _etext; 338 init_mm.end_code = (unsigned long) _etext;
345 init_mm.end_data = (unsigned long) _edata; 339 init_mm.end_data = (unsigned long) _edata;
346 init_mm.brk = (unsigned long) klimit; 340 init_mm.brk = klimit;
347 341
348 /* Save unparsed command line copy for /proc/cmdline */ 342 /* Save unparsed command line copy for /proc/cmdline */
349 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); 343 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 0471e843b6c5..6791668213e7 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -61,6 +61,8 @@
61#include <asm/xmon.h> 61#include <asm/xmon.h>
62#include <asm/udbg.h> 62#include <asm/udbg.h>
63 63
64#include "setup.h"
65
64#ifdef DEBUG 66#ifdef DEBUG
65#define DBG(fmt...) udbg_printf(fmt) 67#define DBG(fmt...) udbg_printf(fmt)
66#else 68#else
@@ -94,15 +96,6 @@ extern void udbg_init_maple_realmode(void);
94 do { udbg_putc = call_rtas_display_status_delay; } while(0) 96 do { udbg_putc = call_rtas_display_status_delay; } while(0)
95#endif 97#endif
96 98
97/* extern void *stab; */
98extern unsigned long klimit;
99
100extern void mm_init_ppc64(void);
101extern void stab_initialize(unsigned long stab);
102extern void htab_initialize(void);
103extern void early_init_devtree(void *flat_dt);
104extern void unflatten_device_tree(void);
105
106int have_of = 1; 99int have_of = 1;
107int boot_cpuid = 0; 100int boot_cpuid = 0;
108int boot_cpuid_phys = 0; 101int boot_cpuid_phys = 0;
@@ -254,11 +247,10 @@ void __init early_setup(unsigned long dt_ptr)
254 * Iterate all ppc_md structures until we find the proper 247 * Iterate all ppc_md structures until we find the proper
255 * one for the current machine type 248 * one for the current machine type
256 */ 249 */
257 DBG("Probing machine type for platform %x...\n", 250 DBG("Probing machine type for platform %x...\n", _machine);
258 systemcfg->platform);
259 251
260 for (mach = machines; *mach; mach++) { 252 for (mach = machines; *mach; mach++) {
261 if ((*mach)->probe(systemcfg->platform)) 253 if ((*mach)->probe(_machine))
262 break; 254 break;
263 } 255 }
264 /* What can we do if we didn't find ? */ 256 /* What can we do if we didn't find ? */
@@ -290,6 +282,28 @@ void __init early_setup(unsigned long dt_ptr)
290 DBG(" <- early_setup()\n"); 282 DBG(" <- early_setup()\n");
291} 283}
292 284
285#ifdef CONFIG_SMP
286void early_setup_secondary(void)
287{
288 struct paca_struct *lpaca = get_paca();
289
290 /* Mark enabled in PACA */
291 lpaca->proc_enabled = 0;
292
293 /* Initialize hash table for that CPU */
294 htab_initialize_secondary();
295
296 /* Initialize STAB/SLB. We use a virtual address as it works
297 * in real mode on pSeries and we want a virutal address on
298 * iSeries anyway
299 */
300 if (cpu_has_feature(CPU_FTR_SLB))
301 slb_initialize();
302 else
303 stab_initialize(lpaca->stab_addr);
304}
305
306#endif /* CONFIG_SMP */
293 307
294#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) 308#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
295void smp_release_cpus(void) 309void smp_release_cpus(void)
@@ -315,7 +329,8 @@ void smp_release_cpus(void)
315#endif /* CONFIG_SMP || CONFIG_KEXEC */ 329#endif /* CONFIG_SMP || CONFIG_KEXEC */
316 330
317/* 331/*
318 * Initialize some remaining members of the ppc64_caches and systemcfg structures 332 * Initialize some remaining members of the ppc64_caches and systemcfg
333 * structures
319 * (at least until we get rid of them completely). This is mostly some 334 * (at least until we get rid of them completely). This is mostly some
320 * cache informations about the CPU that will be used by cache flush 335 * cache informations about the CPU that will be used by cache flush
321 * routines and/or provided to userland 336 * routines and/or provided to userland
@@ -340,7 +355,7 @@ static void __init initialize_cache_info(void)
340 const char *dc, *ic; 355 const char *dc, *ic;
341 356
342 /* Then read cache informations */ 357 /* Then read cache informations */
343 if (systemcfg->platform == PLATFORM_POWERMAC) { 358 if (_machine == PLATFORM_POWERMAC) {
344 dc = "d-cache-block-size"; 359 dc = "d-cache-block-size";
345 ic = "i-cache-block-size"; 360 ic = "i-cache-block-size";
346 } else { 361 } else {
@@ -360,8 +375,8 @@ static void __init initialize_cache_info(void)
360 DBG("Argh, can't find dcache properties ! " 375 DBG("Argh, can't find dcache properties ! "
361 "sizep: %p, lsizep: %p\n", sizep, lsizep); 376 "sizep: %p, lsizep: %p\n", sizep, lsizep);
362 377
363 systemcfg->dcache_size = ppc64_caches.dsize = size; 378 _systemcfg->dcache_size = ppc64_caches.dsize = size;
364 systemcfg->dcache_line_size = 379 _systemcfg->dcache_line_size =
365 ppc64_caches.dline_size = lsize; 380 ppc64_caches.dline_size = lsize;
366 ppc64_caches.log_dline_size = __ilog2(lsize); 381 ppc64_caches.log_dline_size = __ilog2(lsize);
367 ppc64_caches.dlines_per_page = PAGE_SIZE / lsize; 382 ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
@@ -378,8 +393,8 @@ static void __init initialize_cache_info(void)
378 DBG("Argh, can't find icache properties ! " 393 DBG("Argh, can't find icache properties ! "
379 "sizep: %p, lsizep: %p\n", sizep, lsizep); 394 "sizep: %p, lsizep: %p\n", sizep, lsizep);
380 395
381 systemcfg->icache_size = ppc64_caches.isize = size; 396 _systemcfg->icache_size = ppc64_caches.isize = size;
382 systemcfg->icache_line_size = 397 _systemcfg->icache_line_size =
383 ppc64_caches.iline_size = lsize; 398 ppc64_caches.iline_size = lsize;
384 ppc64_caches.log_iline_size = __ilog2(lsize); 399 ppc64_caches.log_iline_size = __ilog2(lsize);
385 ppc64_caches.ilines_per_page = PAGE_SIZE / lsize; 400 ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
@@ -387,10 +402,12 @@ static void __init initialize_cache_info(void)
387 } 402 }
388 403
389 /* Add an eye catcher and the systemcfg layout version number */ 404 /* Add an eye catcher and the systemcfg layout version number */
390 strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); 405 strcpy(_systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
391 systemcfg->version.major = SYSTEMCFG_MAJOR; 406 _systemcfg->version.major = SYSTEMCFG_MAJOR;
392 systemcfg->version.minor = SYSTEMCFG_MINOR; 407 _systemcfg->version.minor = SYSTEMCFG_MINOR;
393 systemcfg->processor = mfspr(SPRN_PVR); 408 _systemcfg->processor = mfspr(SPRN_PVR);
409 _systemcfg->platform = _machine;
410 _systemcfg->physicalMemorySize = lmb_phys_mem_size();
394 411
395 DBG(" <- initialize_cache_info()\n"); 412 DBG(" <- initialize_cache_info()\n");
396} 413}
@@ -479,10 +496,10 @@ void __init setup_system(void)
479 printk("-----------------------------------------------------\n"); 496 printk("-----------------------------------------------------\n");
480 printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); 497 printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
481 printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); 498 printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller);
482 printk("systemcfg = 0x%p\n", systemcfg); 499 printk("systemcfg = 0x%p\n", _systemcfg);
483 printk("systemcfg->platform = 0x%x\n", systemcfg->platform); 500 printk("systemcfg->platform = 0x%x\n", _systemcfg->platform);
484 printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount); 501 printk("systemcfg->processorCount = 0x%lx\n", _systemcfg->processorCount);
485 printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); 502 printk("systemcfg->physicalMemorySize = 0x%lx\n", _systemcfg->physicalMemorySize);
486 printk("ppc64_caches.dcache_line_size = 0x%x\n", 503 printk("ppc64_caches.dcache_line_size = 0x%x\n",
487 ppc64_caches.dline_size); 504 ppc64_caches.dline_size);
488 printk("ppc64_caches.icache_line_size = 0x%x\n", 505 printk("ppc64_caches.icache_line_size = 0x%x\n",
@@ -564,12 +581,12 @@ void __init setup_syscall_map(void)
564 for (i = 0; i < __NR_syscalls; i++) { 581 for (i = 0; i < __NR_syscalls; i++) {
565 if (sys_call_table[i*2] != sys_ni_syscall) { 582 if (sys_call_table[i*2] != sys_ni_syscall) {
566 count64++; 583 count64++;
567 systemcfg->syscall_map_64[i >> 5] |= 584 _systemcfg->syscall_map_64[i >> 5] |=
568 0x80000000UL >> (i & 0x1f); 585 0x80000000UL >> (i & 0x1f);
569 } 586 }
570 if (sys_call_table[i*2+1] != sys_ni_syscall) { 587 if (sys_call_table[i*2+1] != sys_ni_syscall) {
571 count32++; 588 count32++;
572 systemcfg->syscall_map_32[i >> 5] |= 589 _systemcfg->syscall_map_32[i >> 5] |=
573 0x80000000UL >> (i & 0x1f); 590 0x80000000UL >> (i & 0x1f);
574 } 591 }
575 } 592 }
@@ -858,26 +875,6 @@ int check_legacy_ioport(unsigned long base_port)
858} 875}
859EXPORT_SYMBOL(check_legacy_ioport); 876EXPORT_SYMBOL(check_legacy_ioport);
860 877
861#ifdef CONFIG_XMON
862static int __init early_xmon(char *p)
863{
864 /* ensure xmon is enabled */
865 if (p) {
866 if (strncmp(p, "on", 2) == 0)
867 xmon_init(1);
868 if (strncmp(p, "off", 3) == 0)
869 xmon_init(0);
870 if (strncmp(p, "early", 5) != 0)
871 return 0;
872 }
873 xmon_init(1);
874 debugger(NULL);
875
876 return 0;
877}
878early_param("xmon", early_xmon);
879#endif
880
881void cpu_die(void) 878void cpu_die(void)
882{ 879{
883 if (ppc_md.cpu_die) 880 if (ppc_md.cpu_die)
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 081d931eae48..a7c4515f320f 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -42,6 +42,7 @@
42 42
43#include <asm/uaccess.h> 43#include <asm/uaccess.h>
44#include <asm/cacheflush.h> 44#include <asm/cacheflush.h>
45#include <asm/sigcontext.h>
45#ifdef CONFIG_PPC64 46#ifdef CONFIG_PPC64
46#include "ppc32.h" 47#include "ppc32.h"
47#include <asm/unistd.h> 48#include <asm/unistd.h>
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 36d67a8d7cbb..e28a139c29d0 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -44,6 +44,7 @@
44#include <asm/cputable.h> 44#include <asm/cputable.h>
45#include <asm/system.h> 45#include <asm/system.h>
46#include <asm/mpic.h> 46#include <asm/mpic.h>
47#include <asm/systemcfg.h>
47#ifdef CONFIG_PPC64 48#ifdef CONFIG_PPC64
48#include <asm/paca.h> 49#include <asm/paca.h>
49#endif 50#endif
@@ -368,9 +369,11 @@ int generic_cpu_disable(void)
368 if (cpu == boot_cpuid) 369 if (cpu == boot_cpuid)
369 return -EBUSY; 370 return -EBUSY;
370 371
371 systemcfg->processorCount--;
372 cpu_clear(cpu, cpu_online_map); 372 cpu_clear(cpu, cpu_online_map);
373#ifdef CONFIG_PPC64
374 _systemcfg->processorCount--;
373 fixup_irqs(cpu_online_map); 375 fixup_irqs(cpu_online_map);
376#endif
374 return 0; 377 return 0;
375} 378}
376 379
@@ -388,9 +391,11 @@ int generic_cpu_enable(unsigned int cpu)
388 while (!cpu_online(cpu)) 391 while (!cpu_online(cpu))
389 cpu_relax(); 392 cpu_relax();
390 393
394#ifdef CONFIG_PPC64
391 fixup_irqs(cpu_online_map); 395 fixup_irqs(cpu_online_map);
392 /* counter the irq disable in fixup_irqs */ 396 /* counter the irq disable in fixup_irqs */
393 local_irq_enable(); 397 local_irq_enable();
398#endif
394 return 0; 399 return 0;
395} 400}
396 401
@@ -419,7 +424,9 @@ void generic_mach_cpu_die(void)
419 while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) 424 while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
420 cpu_relax(); 425 cpu_relax();
421 426
427#ifdef CONFIG_PPC64
422 flush_tlb_pending(); 428 flush_tlb_pending();
429#endif
423 cpu_set(cpu, cpu_online_map); 430 cpu_set(cpu, cpu_online_map);
424 local_irq_enable(); 431 local_irq_enable();
425} 432}
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index a8210ed5c686..9c921d1c4084 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -52,7 +52,6 @@
52#include <asm/semaphore.h> 52#include <asm/semaphore.h>
53#include <asm/time.h> 53#include <asm/time.h>
54#include <asm/mmu_context.h> 54#include <asm/mmu_context.h>
55#include <asm/systemcfg.h>
56#include <asm/ppc-pci.h> 55#include <asm/ppc-pci.h>
57 56
58/* readdir & getdents */ 57/* readdir & getdents */
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
new file mode 100644
index 000000000000..850af198fb5f
--- /dev/null
+++ b/arch/powerpc/kernel/sysfs.c
@@ -0,0 +1,384 @@
1#include <linux/config.h>
2#include <linux/sysdev.h>
3#include <linux/cpu.h>
4#include <linux/smp.h>
5#include <linux/percpu.h>
6#include <linux/init.h>
7#include <linux/sched.h>
8#include <linux/module.h>
9#include <linux/nodemask.h>
10#include <linux/cpumask.h>
11#include <linux/notifier.h>
12
13#include <asm/current.h>
14#include <asm/processor.h>
15#include <asm/cputable.h>
16#include <asm/firmware.h>
17#include <asm/hvcall.h>
18#include <asm/prom.h>
19#include <asm/systemcfg.h>
20#include <asm/paca.h>
21#include <asm/lppaca.h>
22#include <asm/machdep.h>
23#include <asm/smp.h>
24
25static DEFINE_PER_CPU(struct cpu, cpu_devices);
26
27/* SMT stuff */
28
29#ifdef CONFIG_PPC_MULTIPLATFORM
30/* default to snooze disabled */
31DEFINE_PER_CPU(unsigned long, smt_snooze_delay);
32
33static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf,
34 size_t count)
35{
36 struct cpu *cpu = container_of(dev, struct cpu, sysdev);
37 ssize_t ret;
38 unsigned long snooze;
39
40 ret = sscanf(buf, "%lu", &snooze);
41 if (ret != 1)
42 return -EINVAL;
43
44 per_cpu(smt_snooze_delay, cpu->sysdev.id) = snooze;
45
46 return count;
47}
48
49static ssize_t show_smt_snooze_delay(struct sys_device *dev, char *buf)
50{
51 struct cpu *cpu = container_of(dev, struct cpu, sysdev);
52
53 return sprintf(buf, "%lu\n", per_cpu(smt_snooze_delay, cpu->sysdev.id));
54}
55
56static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
57 store_smt_snooze_delay);
58
59/* Only parse OF options if the matching cmdline option was not specified */
60static int smt_snooze_cmdline;
61
62static int __init smt_setup(void)
63{
64 struct device_node *options;
65 unsigned int *val;
66 unsigned int cpu;
67
68 if (!cpu_has_feature(CPU_FTR_SMT))
69 return 1;
70
71 options = find_path_device("/options");
72 if (!options)
73 return 1;
74
75 val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay",
76 NULL);
77 if (!smt_snooze_cmdline && val) {
78 for_each_cpu(cpu)
79 per_cpu(smt_snooze_delay, cpu) = *val;
80 }
81
82 return 1;
83}
84__initcall(smt_setup);
85
86static int __init setup_smt_snooze_delay(char *str)
87{
88 unsigned int cpu;
89 int snooze;
90
91 if (!cpu_has_feature(CPU_FTR_SMT))
92 return 1;
93
94 smt_snooze_cmdline = 1;
95
96 if (get_option(&str, &snooze)) {
97 for_each_cpu(cpu)
98 per_cpu(smt_snooze_delay, cpu) = snooze;
99 }
100
101 return 1;
102}
103__setup("smt-snooze-delay=", setup_smt_snooze_delay);
104
105#endif /* CONFIG_PPC_MULTIPLATFORM */
106
107/*
108 * Enabling PMCs will slow partition context switch times so we only do
109 * it the first time we write to the PMCs.
110 */
111
112static DEFINE_PER_CPU(char, pmcs_enabled);
113
114void ppc64_enable_pmcs(void)
115{
116 /* Only need to enable them once */
117 if (__get_cpu_var(pmcs_enabled))
118 return;
119
120 __get_cpu_var(pmcs_enabled) = 1;
121
122 if (ppc_md.enable_pmcs)
123 ppc_md.enable_pmcs();
124}
125EXPORT_SYMBOL(ppc64_enable_pmcs);
126
127/* XXX convert to rusty's on_one_cpu */
128static unsigned long run_on_cpu(unsigned long cpu,
129 unsigned long (*func)(unsigned long),
130 unsigned long arg)
131{
132 cpumask_t old_affinity = current->cpus_allowed;
133 unsigned long ret;
134
135 /* should return -EINVAL to userspace */
136 if (set_cpus_allowed(current, cpumask_of_cpu(cpu)))
137 return 0;
138
139 ret = func(arg);
140
141 set_cpus_allowed(current, old_affinity);
142
143 return ret;
144}
145
146#define SYSFS_PMCSETUP(NAME, ADDRESS) \
147static unsigned long read_##NAME(unsigned long junk) \
148{ \
149 return mfspr(ADDRESS); \
150} \
151static unsigned long write_##NAME(unsigned long val) \
152{ \
153 ppc64_enable_pmcs(); \
154 mtspr(ADDRESS, val); \
155 return 0; \
156} \
157static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
158{ \
159 struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
160 unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \
161 return sprintf(buf, "%lx\n", val); \
162} \
163static ssize_t __attribute_used__ \
164 store_##NAME(struct sys_device *dev, const char *buf, size_t count) \
165{ \
166 struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
167 unsigned long val; \
168 int ret = sscanf(buf, "%lx", &val); \
169 if (ret != 1) \
170 return -EINVAL; \
171 run_on_cpu(cpu->sysdev.id, write_##NAME, val); \
172 return count; \
173}
174
175SYSFS_PMCSETUP(mmcr0, SPRN_MMCR0);
176SYSFS_PMCSETUP(mmcr1, SPRN_MMCR1);
177SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
178SYSFS_PMCSETUP(pmc1, SPRN_PMC1);
179SYSFS_PMCSETUP(pmc2, SPRN_PMC2);
180SYSFS_PMCSETUP(pmc3, SPRN_PMC3);
181SYSFS_PMCSETUP(pmc4, SPRN_PMC4);
182SYSFS_PMCSETUP(pmc5, SPRN_PMC5);
183SYSFS_PMCSETUP(pmc6, SPRN_PMC6);
184SYSFS_PMCSETUP(pmc7, SPRN_PMC7);
185SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
186SYSFS_PMCSETUP(purr, SPRN_PURR);
187
188static SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0);
189static SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1);
190static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
191static SYSDEV_ATTR(pmc1, 0600, show_pmc1, store_pmc1);
192static SYSDEV_ATTR(pmc2, 0600, show_pmc2, store_pmc2);
193static SYSDEV_ATTR(pmc3, 0600, show_pmc3, store_pmc3);
194static SYSDEV_ATTR(pmc4, 0600, show_pmc4, store_pmc4);
195static SYSDEV_ATTR(pmc5, 0600, show_pmc5, store_pmc5);
196static SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6);
197static SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7);
198static SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8);
199static SYSDEV_ATTR(purr, 0600, show_purr, NULL);
200
201static void register_cpu_online(unsigned int cpu)
202{
203 struct cpu *c = &per_cpu(cpu_devices, cpu);
204 struct sys_device *s = &c->sysdev;
205
206#ifndef CONFIG_PPC_ISERIES
207 if (cpu_has_feature(CPU_FTR_SMT))
208 sysdev_create_file(s, &attr_smt_snooze_delay);
209#endif
210
211 /* PMC stuff */
212
213 sysdev_create_file(s, &attr_mmcr0);
214 sysdev_create_file(s, &attr_mmcr1);
215
216 if (cpu_has_feature(CPU_FTR_MMCRA))
217 sysdev_create_file(s, &attr_mmcra);
218
219 if (cur_cpu_spec->num_pmcs >= 1)
220 sysdev_create_file(s, &attr_pmc1);
221 if (cur_cpu_spec->num_pmcs >= 2)
222 sysdev_create_file(s, &attr_pmc2);
223 if (cur_cpu_spec->num_pmcs >= 3)
224 sysdev_create_file(s, &attr_pmc3);
225 if (cur_cpu_spec->num_pmcs >= 4)
226 sysdev_create_file(s, &attr_pmc4);
227 if (cur_cpu_spec->num_pmcs >= 5)
228 sysdev_create_file(s, &attr_pmc5);
229 if (cur_cpu_spec->num_pmcs >= 6)
230 sysdev_create_file(s, &attr_pmc6);
231 if (cur_cpu_spec->num_pmcs >= 7)
232 sysdev_create_file(s, &attr_pmc7);
233 if (cur_cpu_spec->num_pmcs >= 8)
234 sysdev_create_file(s, &attr_pmc8);
235
236 if (cpu_has_feature(CPU_FTR_SMT))
237 sysdev_create_file(s, &attr_purr);
238}
239
240#ifdef CONFIG_HOTPLUG_CPU
241static void unregister_cpu_online(unsigned int cpu)
242{
243 struct cpu *c = &per_cpu(cpu_devices, cpu);
244 struct sys_device *s = &c->sysdev;
245
246 BUG_ON(c->no_control);
247
248#ifndef CONFIG_PPC_ISERIES
249 if (cpu_has_feature(CPU_FTR_SMT))
250 sysdev_remove_file(s, &attr_smt_snooze_delay);
251#endif
252
253 /* PMC stuff */
254
255 sysdev_remove_file(s, &attr_mmcr0);
256 sysdev_remove_file(s, &attr_mmcr1);
257
258 if (cpu_has_feature(CPU_FTR_MMCRA))
259 sysdev_remove_file(s, &attr_mmcra);
260
261 if (cur_cpu_spec->num_pmcs >= 1)
262 sysdev_remove_file(s, &attr_pmc1);
263 if (cur_cpu_spec->num_pmcs >= 2)
264 sysdev_remove_file(s, &attr_pmc2);
265 if (cur_cpu_spec->num_pmcs >= 3)
266 sysdev_remove_file(s, &attr_pmc3);
267 if (cur_cpu_spec->num_pmcs >= 4)
268 sysdev_remove_file(s, &attr_pmc4);
269 if (cur_cpu_spec->num_pmcs >= 5)
270 sysdev_remove_file(s, &attr_pmc5);
271 if (cur_cpu_spec->num_pmcs >= 6)
272 sysdev_remove_file(s, &attr_pmc6);
273 if (cur_cpu_spec->num_pmcs >= 7)
274 sysdev_remove_file(s, &attr_pmc7);
275 if (cur_cpu_spec->num_pmcs >= 8)
276 sysdev_remove_file(s, &attr_pmc8);
277
278 if (cpu_has_feature(CPU_FTR_SMT))
279 sysdev_remove_file(s, &attr_purr);
280}
281#endif /* CONFIG_HOTPLUG_CPU */
282
283static int __devinit sysfs_cpu_notify(struct notifier_block *self,
284 unsigned long action, void *hcpu)
285{
286 unsigned int cpu = (unsigned int)(long)hcpu;
287
288 switch (action) {
289 case CPU_ONLINE:
290 register_cpu_online(cpu);
291 break;
292#ifdef CONFIG_HOTPLUG_CPU
293 case CPU_DEAD:
294 unregister_cpu_online(cpu);
295 break;
296#endif
297 }
298 return NOTIFY_OK;
299}
300
301static struct notifier_block __devinitdata sysfs_cpu_nb = {
302 .notifier_call = sysfs_cpu_notify,
303};
304
305/* NUMA stuff */
306
307#ifdef CONFIG_NUMA
308static struct node node_devices[MAX_NUMNODES];
309
310static void register_nodes(void)
311{
312 int i;
313
314 for (i = 0; i < MAX_NUMNODES; i++) {
315 if (node_online(i)) {
316 int p_node = parent_node(i);
317 struct node *parent = NULL;
318
319 if (p_node != i)
320 parent = &node_devices[p_node];
321
322 register_node(&node_devices[i], i, parent);
323 }
324 }
325}
326#else
327static void register_nodes(void)
328{
329 return;
330}
331#endif
332
333/* Only valid if CPU is present. */
334static ssize_t show_physical_id(struct sys_device *dev, char *buf)
335{
336 struct cpu *cpu = container_of(dev, struct cpu, sysdev);
337
338 return sprintf(buf, "%d\n", get_hard_smp_processor_id(cpu->sysdev.id));
339}
340static SYSDEV_ATTR(physical_id, 0444, show_physical_id, NULL);
341
342static int __init topology_init(void)
343{
344 int cpu;
345 struct node *parent = NULL;
346
347 register_nodes();
348
349 register_cpu_notifier(&sysfs_cpu_nb);
350
351 for_each_cpu(cpu) {
352 struct cpu *c = &per_cpu(cpu_devices, cpu);
353
354#ifdef CONFIG_NUMA
355 /* The node to which a cpu belongs can't be known
356 * until the cpu is made present.
357 */
358 parent = NULL;
359 if (cpu_present(cpu))
360 parent = &node_devices[cpu_to_node(cpu)];
361#endif
362 /*
363 * For now, we just see if the system supports making
364 * the RTAS calls for CPU hotplug. But, there may be a
365 * more comprehensive way to do this for an individual
366 * CPU. For instance, the boot cpu might never be valid
367 * for hotplugging.
368 */
369 if (!ppc_md.cpu_die)
370 c->no_control = 1;
371
372 if (cpu_online(cpu) || (c->no_control == 0)) {
373 register_cpu(c, cpu, parent);
374
375 sysdev_create_file(&c->sysdev, &attr_physical_id);
376 }
377
378 if (cpu_online(cpu))
379 register_cpu_online(cpu);
380 }
381
382 return 0;
383}
384__initcall(topology_init);
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index a6282b625b44..260b6ecd26a9 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -271,13 +271,13 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec,
271 * tb_to_xs and stamp_xsec values are consistent. If not, then it 271 * tb_to_xs and stamp_xsec values are consistent. If not, then it
272 * loops back and reads them again until this criteria is met. 272 * loops back and reads them again until this criteria is met.
273 */ 273 */
274 ++(systemcfg->tb_update_count); 274 ++(_systemcfg->tb_update_count);
275 smp_wmb(); 275 smp_wmb();
276 systemcfg->tb_orig_stamp = new_tb_stamp; 276 _systemcfg->tb_orig_stamp = new_tb_stamp;
277 systemcfg->stamp_xsec = new_stamp_xsec; 277 _systemcfg->stamp_xsec = new_stamp_xsec;
278 systemcfg->tb_to_xs = new_tb_to_xs; 278 _systemcfg->tb_to_xs = new_tb_to_xs;
279 smp_wmb(); 279 smp_wmb();
280 ++(systemcfg->tb_update_count); 280 ++(_systemcfg->tb_update_count);
281#endif 281#endif
282} 282}
283 283
@@ -357,8 +357,9 @@ static void iSeries_tb_recal(void)
357 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; 357 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
358 tb_to_xs = divres.result_low; 358 tb_to_xs = divres.result_low;
359 do_gtod.varp->tb_to_xs = tb_to_xs; 359 do_gtod.varp->tb_to_xs = tb_to_xs;
360 systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; 360 _systemcfg->tb_ticks_per_sec =
361 systemcfg->tb_to_xs = tb_to_xs; 361 tb_ticks_per_sec;
362 _systemcfg->tb_to_xs = tb_to_xs;
362 } 363 }
363 else { 364 else {
364 printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" 365 printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
@@ -483,6 +484,8 @@ void __init smp_space_timers(unsigned int max_cpus)
483 unsigned long offset = tb_ticks_per_jiffy / max_cpus; 484 unsigned long offset = tb_ticks_per_jiffy / max_cpus;
484 unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); 485 unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid);
485 486
487 /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */
488 previous_tb -= tb_ticks_per_jiffy;
486 for_each_cpu(i) { 489 for_each_cpu(i) {
487 if (i != boot_cpuid) { 490 if (i != boot_cpuid) {
488 previous_tb += offset; 491 previous_tb += offset;
@@ -559,8 +562,8 @@ int do_settimeofday(struct timespec *tv)
559 update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); 562 update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
560 563
561#ifdef CONFIG_PPC64 564#ifdef CONFIG_PPC64
562 systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; 565 _systemcfg->tz_minuteswest = sys_tz.tz_minuteswest;
563 systemcfg->tz_dsttime = sys_tz.tz_dsttime; 566 _systemcfg->tz_dsttime = sys_tz.tz_dsttime;
564#endif 567#endif
565 568
566 write_sequnlock_irqrestore(&xtime_lock, flags); 569 write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -711,11 +714,11 @@ void __init time_init(void)
711 do_gtod.varp->tb_to_xs = tb_to_xs; 714 do_gtod.varp->tb_to_xs = tb_to_xs;
712 do_gtod.tb_to_us = tb_to_us; 715 do_gtod.tb_to_us = tb_to_us;
713#ifdef CONFIG_PPC64 716#ifdef CONFIG_PPC64
714 systemcfg->tb_orig_stamp = tb_last_jiffy; 717 _systemcfg->tb_orig_stamp = tb_last_jiffy;
715 systemcfg->tb_update_count = 0; 718 _systemcfg->tb_update_count = 0;
716 systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; 719 _systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
717 systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; 720 _systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
718 systemcfg->tb_to_xs = tb_to_xs; 721 _systemcfg->tb_to_xs = tb_to_xs;
719#endif 722#endif
720 723
721 time_freq = 0; 724 time_freq = 0;
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 0578f8387603..2020bb7648fb 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -129,7 +129,7 @@ int die(const char *str, struct pt_regs *regs, long err)
129 nl = 1; 129 nl = 1;
130#endif 130#endif
131#ifdef CONFIG_PPC64 131#ifdef CONFIG_PPC64
132 switch (systemcfg->platform) { 132 switch (_machine) {
133 case PLATFORM_PSERIES: 133 case PLATFORM_PSERIES:
134 printk("PSERIES "); 134 printk("PSERIES ");
135 nl = 1; 135 nl = 1;