aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-10 08:50:37 -0400
committerPaul Mackerras <paulus@samba.org>2005-10-10 08:50:37 -0400
commit40ef8cbc6d360e564573eb19582249c35d8ba330 (patch)
treeabba70b7da8bef93a87431691dc8df79eb4425d5
parentbc6f8a4b199156897f6eb5b70bf5c1a4773f4e2b (diff)
powerpc: Get 64-bit configs to compile with ARCH=powerpc
This is a bunch of mostly small fixes that are needed to get ARCH=powerpc to compile for 64-bit. This adds setup_64.c from arch/ppc64/kernel/setup.c and locks.c from arch/ppc64/lib/locks.c. Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/Makefile15
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kernel/btext.c3
-rw-r--r--arch/powerpc/kernel/head_64.S1
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c101
-rw-r--r--arch/powerpc/kernel/prom.c6
-rw-r--r--arch/powerpc/kernel/setup_64.c1324
-rw-r--r--arch/powerpc/lib/Makefile4
-rw-r--r--arch/powerpc/lib/locks.c95
-rw-r--r--arch/ppc64/Kconfig3
-rw-r--r--arch/ppc64/kernel/Makefile64
-rw-r--r--arch/ppc64/kernel/asm-offsets.c1
-rw-r--r--arch/ppc64/kernel/bpa_iommu.c2
-rw-r--r--arch/ppc64/kernel/bpa_setup.c1
-rw-r--r--arch/ppc64/kernel/maple_setup.c1
-rw-r--r--arch/ppc64/kernel/pmac_setup.c1
-rw-r--r--include/asm-powerpc/hardirq.h3
-rw-r--r--include/asm-powerpc/hw_irq.h1
-rw-r--r--include/asm-powerpc/ppc_asm.h92
-rw-r--r--include/asm-powerpc/prom.h3
-rw-r--r--include/asm-powerpc/system.h3
-rw-r--r--include/asm-ppc64/pci-bridge.h10
22 files changed, 1631 insertions, 104 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index bc063edd6de0..47a8eb6e7e39 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -10,6 +10,12 @@ CFLAGS_prom_init.o += -fPIC
10CFLAGS_btext.o += -fPIC 10CFLAGS_btext.o += -fPIC
11endif 11endif
12 12
13obj-y := semaphore.o traps.o
14obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
15obj-$(CONFIG_POWER4) += idle_power4.o
16
17ifeq ($(CONFIG_PPC_MERGE),y)
18
13extra-$(CONFIG_PPC_STD_MMU) := head_32.o 19extra-$(CONFIG_PPC_STD_MMU) := head_32.o
14extra-$(CONFIG_PPC64) := head_64.o 20extra-$(CONFIG_PPC64) := head_64.o
15extra-$(CONFIG_40x) := head_4xx.o 21extra-$(CONFIG_40x) := head_4xx.o
@@ -21,15 +27,12 @@ extra-$(CONFIG_PPC64) += entry_64.o
21extra-$(CONFIG_PPC_FPU) += fpu.o 27extra-$(CONFIG_PPC_FPU) += fpu.o
22extra-y += vmlinux.lds 28extra-y += vmlinux.lds
23 29
24obj-y += traps.o prom.o semaphore.o 30obj-y += process.o init_task.o \
31 prom.o systbl.o
25obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o 32obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o
26obj-$(CONFIG_PPC64) += idle_power4.o 33obj-$(CONFIG_PPC64) += setup_64.o misc_64.o
27obj-$(CONFIG_PPC64) += misc_64.o
28ifeq ($(CONFIG_PPC32),y)
29obj-$(CONFIG_PPC_OF) += prom_init.o of_device.o 34obj-$(CONFIG_PPC_OF) += prom_init.o of_device.o
30obj-$(CONFIG_MODULES) += ppc_ksyms.o 35obj-$(CONFIG_MODULES) += ppc_ksyms.o
31endif
32obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
33obj-$(CONFIG_BOOTX_TEXT) += btext.o 36obj-$(CONFIG_BOOTX_TEXT) += btext.o
34 37
35ifeq ($(CONFIG_PPC_ISERIES),y) 38ifeq ($(CONFIG_PPC_ISERIES),y)
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 3a247c033e8b..ddf0c81e1958 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -111,6 +111,7 @@ int main(void)
111 DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); 111 DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
112 DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); 112 DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
113 DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); 113 DEFINE(PLATFORM, offsetof(struct systemcfg, platform));
114 DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
114 115
115 /* paca */ 116 /* paca */
116 DEFINE(PACA_SIZE, sizeof(struct paca_struct)); 117 DEFINE(PACA_SIZE, sizeof(struct paca_struct));
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 44f5d98e27c0..bdfba92b2b38 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -50,7 +50,7 @@ static unsigned char vga_font[cmapsz];
50int boot_text_mapped; 50int boot_text_mapped;
51int force_printk_to_btext = 0; 51int force_printk_to_btext = 0;
52 52
53 53#ifdef CONFIG_PPC32
54/* Calc BAT values for mapping the display and store them 54/* Calc BAT values for mapping the display and store them
55 * in disp_BAT. Those values are then used from head.S to map 55 * in disp_BAT. Those values are then used from head.S to map
56 * the display during identify_machine() and MMU_Init() 56 * the display during identify_machine() and MMU_Init()
@@ -93,6 +93,7 @@ btext_prepare_BAT(void)
93 } 93 }
94 logicalDisplayBase = (void *) (vaddr + lowbits); 94 logicalDisplayBase = (void *) (vaddr + lowbits);
95} 95}
96#endif
96 97
97/* This function will enable the early boot text when doing OF booting. This 98/* This function will enable the early boot text when doing OF booting. This
98 * way, xmon output should work too 99 * way, xmon output should work too
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 3fcac3c37b9b..a4ceb9ae20fc 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -746,6 +746,7 @@ bad_stack:
746 * any task or sent any task a signal, you should use 746 * any task or sent any task a signal, you should use
747 * ret_from_except or ret_from_except_lite instead of this. 747 * ret_from_except or ret_from_except_lite instead of this.
748 */ 748 */
749 .globl fast_exception_return
749fast_exception_return: 750fast_exception_return:
750 ld r12,_MSR(r1) 751 ld r12,_MSR(r1)
751 ld r11,_NIP(r1) 752 ld r11,_NIP(r1)
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 91a562e3257b..010554e5fe48 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -51,6 +51,7 @@
51#include <asm/commproc.h> 51#include <asm/commproc.h>
52#endif 52#endif
53 53
54#ifdef CONFIG_PPC32
54extern void transfer_to_handler(void); 55extern void transfer_to_handler(void);
55extern void do_IRQ(struct pt_regs *regs); 56extern void do_IRQ(struct pt_regs *regs);
56extern void machine_check_exception(struct pt_regs *regs); 57extern void machine_check_exception(struct pt_regs *regs);
@@ -61,14 +62,12 @@ extern int do_signal(sigset_t *, struct pt_regs *);
61extern int pmac_newworld; 62extern int pmac_newworld;
62extern int sys_sigreturn(struct pt_regs *regs); 63extern int sys_sigreturn(struct pt_regs *regs);
63 64
64long long __ashrdi3(long long, int);
65long long __ashldi3(long long, int);
66long long __lshrdi3(long long, int);
67
68extern unsigned long mm_ptov (unsigned long paddr);
69
70EXPORT_SYMBOL(clear_pages); 65EXPORT_SYMBOL(clear_pages);
71EXPORT_SYMBOL(clear_user_page); 66EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
67EXPORT_SYMBOL(DMA_MODE_READ);
68EXPORT_SYMBOL(DMA_MODE_WRITE);
69EXPORT_SYMBOL(__div64_32);
70
72EXPORT_SYMBOL(do_signal); 71EXPORT_SYMBOL(do_signal);
73EXPORT_SYMBOL(transfer_to_handler); 72EXPORT_SYMBOL(transfer_to_handler);
74EXPORT_SYMBOL(do_IRQ); 73EXPORT_SYMBOL(do_IRQ);
@@ -77,12 +76,8 @@ EXPORT_SYMBOL(alignment_exception);
77EXPORT_SYMBOL(program_check_exception); 76EXPORT_SYMBOL(program_check_exception);
78EXPORT_SYMBOL(single_step_exception); 77EXPORT_SYMBOL(single_step_exception);
79EXPORT_SYMBOL(sys_sigreturn); 78EXPORT_SYMBOL(sys_sigreturn);
80EXPORT_SYMBOL(ppc_n_lost_interrupts); 79#endif
81EXPORT_SYMBOL(ppc_lost_interrupts);
82 80
83EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
84EXPORT_SYMBOL(DMA_MODE_READ);
85EXPORT_SYMBOL(DMA_MODE_WRITE);
86#if defined(CONFIG_PPC_PREP) 81#if defined(CONFIG_PPC_PREP)
87EXPORT_SYMBOL(_prep_type); 82EXPORT_SYMBOL(_prep_type);
88EXPORT_SYMBOL(ucSystemType); 83EXPORT_SYMBOL(ucSystemType);
@@ -110,7 +105,6 @@ EXPORT_SYMBOL(strnlen);
110EXPORT_SYMBOL(strcmp); 105EXPORT_SYMBOL(strcmp);
111EXPORT_SYMBOL(strncmp); 106EXPORT_SYMBOL(strncmp);
112EXPORT_SYMBOL(strcasecmp); 107EXPORT_SYMBOL(strcasecmp);
113EXPORT_SYMBOL(__div64_32);
114 108
115EXPORT_SYMBOL(csum_partial); 109EXPORT_SYMBOL(csum_partial);
116EXPORT_SYMBOL(csum_partial_copy_generic); 110EXPORT_SYMBOL(csum_partial_copy_generic);
@@ -132,21 +126,21 @@ EXPORT_SYMBOL(_insw_ns);
132EXPORT_SYMBOL(_outsw_ns); 126EXPORT_SYMBOL(_outsw_ns);
133EXPORT_SYMBOL(_insl_ns); 127EXPORT_SYMBOL(_insl_ns);
134EXPORT_SYMBOL(_outsl_ns); 128EXPORT_SYMBOL(_outsl_ns);
135EXPORT_SYMBOL(iopa);
136EXPORT_SYMBOL(mm_ptov);
137EXPORT_SYMBOL(ioremap); 129EXPORT_SYMBOL(ioremap);
138#ifdef CONFIG_44x 130#ifdef CONFIG_44x
139EXPORT_SYMBOL(ioremap64); 131EXPORT_SYMBOL(ioremap64);
140#endif 132#endif
141EXPORT_SYMBOL(__ioremap); 133EXPORT_SYMBOL(__ioremap);
142EXPORT_SYMBOL(iounmap); 134EXPORT_SYMBOL(iounmap);
135#ifdef CONFIG_PPC32
143EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ 136EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */
137#endif
144 138
145#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) 139#if defined(CONFIG_PPC32) && (defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE))
146EXPORT_SYMBOL(ppc_ide_md); 140EXPORT_SYMBOL(ppc_ide_md);
147#endif 141#endif
148 142
149#ifdef CONFIG_PCI 143#if defined(CONFIG_PCI) && defined(CONFIG_PPC32)
150EXPORT_SYMBOL(isa_io_base); 144EXPORT_SYMBOL(isa_io_base);
151EXPORT_SYMBOL(isa_mem_base); 145EXPORT_SYMBOL(isa_mem_base);
152EXPORT_SYMBOL(pci_dram_offset); 146EXPORT_SYMBOL(pci_dram_offset);
@@ -168,31 +162,31 @@ EXPORT_SYMBOL(flush_dcache_all);
168EXPORT_SYMBOL(start_thread); 162EXPORT_SYMBOL(start_thread);
169EXPORT_SYMBOL(kernel_thread); 163EXPORT_SYMBOL(kernel_thread);
170 164
171EXPORT_SYMBOL(flush_instruction_cache);
172EXPORT_SYMBOL(giveup_fpu); 165EXPORT_SYMBOL(giveup_fpu);
166#ifdef CONFIG_ALTIVEC
167EXPORT_SYMBOL(giveup_altivec);
168#endif /* CONFIG_ALTIVEC */
169#ifdef CONFIG_SPE
170EXPORT_SYMBOL(giveup_spe);
171#endif /* CONFIG_SPE */
172
173#ifdef CONFIG_PPC64 173#ifdef CONFIG_PPC64
174EXPORT_SYMBOL(__flush_icache_range); 174EXPORT_SYMBOL(__flush_icache_range);
175#else 175#else
176EXPORT_SYMBOL(flush_instruction_cache);
176EXPORT_SYMBOL(flush_icache_range); 177EXPORT_SYMBOL(flush_icache_range);
177#endif
178EXPORT_SYMBOL(flush_dcache_range);
179EXPORT_SYMBOL(flush_icache_user_range);
180EXPORT_SYMBOL(flush_dcache_page);
181EXPORT_SYMBOL(flush_tlb_kernel_range); 178EXPORT_SYMBOL(flush_tlb_kernel_range);
182EXPORT_SYMBOL(flush_tlb_page); 179EXPORT_SYMBOL(flush_tlb_page);
183EXPORT_SYMBOL(_tlbie); 180EXPORT_SYMBOL(_tlbie);
184#ifdef CONFIG_ALTIVEC 181#endif
185EXPORT_SYMBOL(giveup_altivec); 182EXPORT_SYMBOL(flush_dcache_range);
186#endif /* CONFIG_ALTIVEC */ 183
187#ifdef CONFIG_SPE
188EXPORT_SYMBOL(giveup_spe);
189#endif /* CONFIG_SPE */
190#ifdef CONFIG_SMP 184#ifdef CONFIG_SMP
191EXPORT_SYMBOL(smp_call_function); 185EXPORT_SYMBOL(smp_call_function);
186#ifdef CONFIG_PPC32
192EXPORT_SYMBOL(smp_hw_index); 187EXPORT_SYMBOL(smp_hw_index);
193#endif 188#endif
194 189#endif
195EXPORT_SYMBOL(ppc_md);
196 190
197#ifdef CONFIG_ADB 191#ifdef CONFIG_ADB
198EXPORT_SYMBOL(adb_request); 192EXPORT_SYMBOL(adb_request);
@@ -205,25 +199,27 @@ EXPORT_SYMBOL(adb_try_handler_change);
205EXPORT_SYMBOL(cuda_request); 199EXPORT_SYMBOL(cuda_request);
206EXPORT_SYMBOL(cuda_poll); 200EXPORT_SYMBOL(cuda_poll);
207#endif /* CONFIG_ADB_CUDA */ 201#endif /* CONFIG_ADB_CUDA */
208#ifdef CONFIG_PPC_MULTIPLATFORM 202#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32)
209EXPORT_SYMBOL(_machine); 203EXPORT_SYMBOL(_machine);
210#endif 204#endif
211#ifdef CONFIG_PPC_PMAC 205#ifdef CONFIG_PPC_PMAC
212EXPORT_SYMBOL(sys_ctrler); 206EXPORT_SYMBOL(sys_ctrler);
213EXPORT_SYMBOL(pmac_newworld);
214#endif 207#endif
215#ifdef CONFIG_VT 208#ifdef CONFIG_VT
216EXPORT_SYMBOL(kd_mksound); 209EXPORT_SYMBOL(kd_mksound);
217#endif 210#endif
218EXPORT_SYMBOL(to_tm); 211EXPORT_SYMBOL(to_tm);
219 212
220EXPORT_SYMBOL(pm_power_off); 213#ifdef CONFIG_PPC32
221 214long long __ashrdi3(long long, int);
215long long __ashldi3(long long, int);
216long long __lshrdi3(long long, int);
222EXPORT_SYMBOL(__ashrdi3); 217EXPORT_SYMBOL(__ashrdi3);
223EXPORT_SYMBOL(__ashldi3); 218EXPORT_SYMBOL(__ashldi3);
224EXPORT_SYMBOL(__lshrdi3); 219EXPORT_SYMBOL(__lshrdi3);
220#endif
221
225EXPORT_SYMBOL(memcpy); 222EXPORT_SYMBOL(memcpy);
226EXPORT_SYMBOL(cacheable_memcpy);
227EXPORT_SYMBOL(memset); 223EXPORT_SYMBOL(memset);
228EXPORT_SYMBOL(memmove); 224EXPORT_SYMBOL(memmove);
229EXPORT_SYMBOL(memscan); 225EXPORT_SYMBOL(memscan);
@@ -234,17 +230,14 @@ EXPORT_SYMBOL(memchr);
234EXPORT_SYMBOL(screen_info); 230EXPORT_SYMBOL(screen_info);
235#endif 231#endif
236 232
233#ifdef CONFIG_PPC32
234EXPORT_SYMBOL(pm_power_off);
237EXPORT_SYMBOL(__delay); 235EXPORT_SYMBOL(__delay);
238EXPORT_SYMBOL(timer_interrupt); 236EXPORT_SYMBOL(timer_interrupt);
239EXPORT_SYMBOL(irq_desc); 237EXPORT_SYMBOL(irq_desc);
240EXPORT_SYMBOL(tb_ticks_per_jiffy); 238EXPORT_SYMBOL(tb_ticks_per_jiffy);
241EXPORT_SYMBOL(get_wchan);
242EXPORT_SYMBOL(console_drivers); 239EXPORT_SYMBOL(console_drivers);
243 240EXPORT_SYMBOL(cacheable_memcpy);
244#ifdef CONFIG_PPC_ISERIES
245EXPORT_SYMBOL(local_irq_disable);
246EXPORT_SYMBOL(local_irq_enable);
247EXPORT_SYMBOL(local_get_flags);
248#endif 241#endif
249 242
250#ifdef CONFIG_XMON 243#ifdef CONFIG_XMON
@@ -255,22 +248,6 @@ EXPORT_SYMBOL(__up);
255EXPORT_SYMBOL(__down); 248EXPORT_SYMBOL(__down);
256EXPORT_SYMBOL(__down_interruptible); 249EXPORT_SYMBOL(__down_interruptible);
257 250
258#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
259extern void (*debugger)(struct pt_regs *regs);
260extern int (*debugger_bpt)(struct pt_regs *regs);
261extern int (*debugger_sstep)(struct pt_regs *regs);
262extern int (*debugger_iabr_match)(struct pt_regs *regs);
263extern int (*debugger_dabr_match)(struct pt_regs *regs);
264extern void (*debugger_fault_handler)(struct pt_regs *regs);
265
266EXPORT_SYMBOL(debugger);
267EXPORT_SYMBOL(debugger_bpt);
268EXPORT_SYMBOL(debugger_sstep);
269EXPORT_SYMBOL(debugger_iabr_match);
270EXPORT_SYMBOL(debugger_dabr_match);
271EXPORT_SYMBOL(debugger_fault_handler);
272#endif
273
274#ifdef CONFIG_8xx 251#ifdef CONFIG_8xx
275EXPORT_SYMBOL(cpm_install_handler); 252EXPORT_SYMBOL(cpm_install_handler);
276EXPORT_SYMBOL(cpm_free_handler); 253EXPORT_SYMBOL(cpm_free_handler);
@@ -280,22 +257,24 @@ EXPORT_SYMBOL(cpm_free_handler);
280EXPORT_SYMBOL(__res); 257EXPORT_SYMBOL(__res);
281#endif 258#endif
282 259
260#ifdef CONFIG_PPC32
283EXPORT_SYMBOL(next_mmu_context); 261EXPORT_SYMBOL(next_mmu_context);
284EXPORT_SYMBOL(set_context); 262EXPORT_SYMBOL(set_context);
285EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */
286EXPORT_SYMBOL(disarm_decr); 263EXPORT_SYMBOL(disarm_decr);
287#ifdef CONFIG_PPC_STD_MMU 264#endif
265
266#ifdef CONFIG_PPC_STD_MMU_32
288extern long mol_trampoline; 267extern long mol_trampoline;
289EXPORT_SYMBOL(mol_trampoline); /* For MOL */ 268EXPORT_SYMBOL(mol_trampoline); /* For MOL */
290EXPORT_SYMBOL(flush_hash_pages); /* For MOL */ 269EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
270EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */
291#ifdef CONFIG_SMP 271#ifdef CONFIG_SMP
292extern int mmu_hash_lock; 272extern int mmu_hash_lock;
293EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */ 273EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
294#endif /* CONFIG_SMP */ 274#endif /* CONFIG_SMP */
295extern long *intercept_table; 275extern long *intercept_table;
296EXPORT_SYMBOL(intercept_table); 276EXPORT_SYMBOL(intercept_table);
297#endif /* CONFIG_PPC_STD_MMU */ 277#endif /* CONFIG_PPC_STD_MMU_32 */
298EXPORT_SYMBOL(cur_cpu_spec);
299#ifdef CONFIG_PPC_PMAC 278#ifdef CONFIG_PPC_PMAC
300extern unsigned long agp_special_page; 279extern unsigned long agp_special_page;
301EXPORT_SYMBOL(agp_special_page); 280EXPORT_SYMBOL(agp_special_page);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index dc3d24ea3bff..ce0dff1caa80 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -47,6 +47,10 @@
47#include <asm/sections.h> 47#include <asm/sections.h>
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>
51#ifdef CONFIG_PPC64
52#include <asm/systemcfg.h>
53#endif
50 54
51#ifdef DEBUG 55#ifdef DEBUG
52#define DBG(fmt...) printk(KERN_ERR fmt) 56#define DBG(fmt...) printk(KERN_ERR fmt)
@@ -1072,7 +1076,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
1072 } else { 1076 } else {
1073 /* Check if it's the boot-cpu, set it's hw index in paca now */ 1077 /* Check if it's the boot-cpu, set it's hw index in paca now */
1074 if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { 1078 if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) {
1075 u32 *prop = get_flat_dt_prop(node, "reg", NULL); 1079 prop = get_flat_dt_prop(node, "reg", NULL);
1076 set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); 1080 set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop);
1077 boot_cpuid_phys = get_hard_smp_processor_id(0); 1081 boot_cpuid_phys = get_hard_smp_processor_id(0);
1078 } 1082 }
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
new file mode 100644
index 000000000000..212b00823f82
--- /dev/null
+++ b/arch/powerpc/kernel/setup_64.c
@@ -0,0 +1,1324 @@
1/*
2 *
3 * Common boot and setup code.
4 *
5 * Copyright (C) 2001 PPC64 Team, IBM Corp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#undef DEBUG
14
15#include <linux/config.h>
16#include <linux/module.h>
17#include <linux/string.h>
18#include <linux/sched.h>
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/reboot.h>
22#include <linux/delay.h>
23#include <linux/initrd.h>
24#include <linux/ide.h>
25#include <linux/seq_file.h>
26#include <linux/ioport.h>
27#include <linux/console.h>
28#include <linux/utsname.h>
29#include <linux/tty.h>
30#include <linux/root_dev.h>
31#include <linux/notifier.h>
32#include <linux/cpu.h>
33#include <linux/unistd.h>
34#include <linux/serial.h>
35#include <linux/serial_8250.h>
36#include <asm/io.h>
37#include <asm/prom.h>
38#include <asm/processor.h>
39#include <asm/pgtable.h>
40#include <asm/bootinfo.h>
41#include <asm/smp.h>
42#include <asm/elf.h>
43#include <asm/machdep.h>
44#include <asm/paca.h>
45#include <asm/ppcdebug.h>
46#include <asm/time.h>
47#include <asm/cputable.h>
48#include <asm/sections.h>
49#include <asm/btext.h>
50#include <asm/nvram.h>
51#include <asm/setup.h>
52#include <asm/system.h>
53#include <asm/rtas.h>
54#include <asm/iommu.h>
55#include <asm/serial.h>
56#include <asm/cache.h>
57#include <asm/page.h>
58#include <asm/mmu.h>
59#include <asm/lmb.h>
60#include <asm/iSeries/ItLpNaca.h>
61#include <asm/firmware.h>
62#include <asm/systemcfg.h>
63
64#ifdef DEBUG
65#define DBG(fmt...) udbg_printf(fmt)
66#else
67#define DBG(fmt...)
68#endif
69
70/*
71 * Here are some early debugging facilities. You can enable one
72 * but your kernel will not boot on anything else if you do so
73 */
74
75/* This one is for use on LPAR machines that support an HVC console
76 * on vterm 0
77 */
78extern void udbg_init_debug_lpar(void);
79/* This one is for use on Apple G5 machines
80 */
81extern void udbg_init_pmac_realmode(void);
82/* That's RTAS panel debug */
83extern void call_rtas_display_status_delay(unsigned char c);
84/* Here's maple real mode debug */
85extern void udbg_init_maple_realmode(void);
86
87#define EARLY_DEBUG_INIT() do {} while(0)
88
89#if 0
90#define EARLY_DEBUG_INIT() udbg_init_debug_lpar()
91#define EARLY_DEBUG_INIT() udbg_init_maple_realmode()
92#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
93#define EARLY_DEBUG_INIT() \
94 do { udbg_putc = call_rtas_display_status_delay; } while(0)
95#endif
96
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
106extern void smp_release_cpus(void);
107
108int have_of = 1;
109int boot_cpuid = 0;
110int boot_cpuid_phys = 0;
111dev_t boot_dev;
112u64 ppc64_pft_size;
113
114struct ppc64_caches ppc64_caches;
115EXPORT_SYMBOL_GPL(ppc64_caches);
116
117/*
118 * These are used in binfmt_elf.c to put aux entries on the stack
119 * for each elf executable being started.
120 */
121int dcache_bsize;
122int icache_bsize;
123int ucache_bsize;
124
125/* The main machine-dep calls structure
126 */
127struct machdep_calls ppc_md;
128EXPORT_SYMBOL(ppc_md);
129
130#ifdef CONFIG_MAGIC_SYSRQ
131unsigned long SYSRQ_KEY;
132#endif /* CONFIG_MAGIC_SYSRQ */
133
134
135static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
136static struct notifier_block ppc64_panic_block = {
137 .notifier_call = ppc64_panic_event,
138 .priority = INT_MIN /* may not return; must be done last */
139};
140
141/*
142 * Perhaps we can put the pmac screen_info[] here
143 * on pmac as well so we don't need the ifdef's.
144 * Until we get multiple-console support in here
145 * that is. -- Cort
146 * Maybe tie it to serial consoles, since this is really what
147 * these processors use on existing boards. -- Dan
148 */
149struct screen_info screen_info = {
150 .orig_x = 0,
151 .orig_y = 25,
152 .orig_video_cols = 80,
153 .orig_video_lines = 25,
154 .orig_video_isVGA = 1,
155 .orig_video_points = 16
156};
157
158#ifdef CONFIG_SMP
159
160static int smt_enabled_cmdline;
161
162/* Look for ibm,smt-enabled OF option */
163static void check_smt_enabled(void)
164{
165 struct device_node *dn;
166 char *smt_option;
167
168 /* Allow the command line to overrule the OF option */
169 if (smt_enabled_cmdline)
170 return;
171
172 dn = of_find_node_by_path("/options");
173
174 if (dn) {
175 smt_option = (char *)get_property(dn, "ibm,smt-enabled", NULL);
176
177 if (smt_option) {
178 if (!strcmp(smt_option, "on"))
179 smt_enabled_at_boot = 1;
180 else if (!strcmp(smt_option, "off"))
181 smt_enabled_at_boot = 0;
182 }
183 }
184}
185
186/* Look for smt-enabled= cmdline option */
187static int __init early_smt_enabled(char *p)
188{
189 smt_enabled_cmdline = 1;
190
191 if (!p)
192 return 0;
193
194 if (!strcmp(p, "on") || !strcmp(p, "1"))
195 smt_enabled_at_boot = 1;
196 else if (!strcmp(p, "off") || !strcmp(p, "0"))
197 smt_enabled_at_boot = 0;
198
199 return 0;
200}
201early_param("smt-enabled", early_smt_enabled);
202
203/**
204 * setup_cpu_maps - initialize the following cpu maps:
205 * cpu_possible_map
206 * cpu_present_map
207 * cpu_sibling_map
208 *
209 * Having the possible map set up early allows us to restrict allocations
210 * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
211 *
212 * We do not initialize the online map here; cpus set their own bits in
213 * cpu_online_map as they come up.
214 *
215 * This function is valid only for Open Firmware systems. finish_device_tree
216 * must be called before using this.
217 *
218 * While we're here, we may as well set the "physical" cpu ids in the paca.
219 */
220static void __init setup_cpu_maps(void)
221{
222 struct device_node *dn = NULL;
223 int cpu = 0;
224 int swap_cpuid = 0;
225
226 check_smt_enabled();
227
228 while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
229 u32 *intserv;
230 int j, len = sizeof(u32), nthreads;
231
232 intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s",
233 &len);
234 if (!intserv)
235 intserv = (u32 *)get_property(dn, "reg", NULL);
236
237 nthreads = len / sizeof(u32);
238
239 for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
240 cpu_set(cpu, cpu_present_map);
241 set_hard_smp_processor_id(cpu, intserv[j]);
242
243 if (intserv[j] == boot_cpuid_phys)
244 swap_cpuid = cpu;
245 cpu_set(cpu, cpu_possible_map);
246 cpu++;
247 }
248 }
249
250 /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
251 * boot cpu is logical 0.
252 */
253 if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
254 u32 tmp;
255 tmp = get_hard_smp_processor_id(0);
256 set_hard_smp_processor_id(0, boot_cpuid_phys);
257 set_hard_smp_processor_id(swap_cpuid, tmp);
258 }
259
260 /*
261 * On pSeries LPAR, we need to know how many cpus
262 * could possibly be added to this partition.
263 */
264 if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
265 (dn = of_find_node_by_path("/rtas"))) {
266 int num_addr_cell, num_size_cell, maxcpus;
267 unsigned int *ireg;
268
269 num_addr_cell = prom_n_addr_cells(dn);
270 num_size_cell = prom_n_size_cells(dn);
271
272 ireg = (unsigned int *)
273 get_property(dn, "ibm,lrdr-capacity", NULL);
274
275 if (!ireg)
276 goto out;
277
278 maxcpus = ireg[num_addr_cell + num_size_cell];
279
280 /* Double maxcpus for processors which have SMT capability */
281 if (cpu_has_feature(CPU_FTR_SMT))
282 maxcpus *= 2;
283
284 if (maxcpus > NR_CPUS) {
285 printk(KERN_WARNING
286 "Partition configured for %d cpus, "
287 "operating system maximum is %d.\n",
288 maxcpus, NR_CPUS);
289 maxcpus = NR_CPUS;
290 } else
291 printk(KERN_INFO "Partition configured for %d cpus.\n",
292 maxcpus);
293
294 for (cpu = 0; cpu < maxcpus; cpu++)
295 cpu_set(cpu, cpu_possible_map);
296 out:
297 of_node_put(dn);
298 }
299
300 /*
301 * Do the sibling map; assume only two threads per processor.
302 */
303 for_each_cpu(cpu) {
304 cpu_set(cpu, cpu_sibling_map[cpu]);
305 if (cpu_has_feature(CPU_FTR_SMT))
306 cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
307 }
308
309 systemcfg->processorCount = num_present_cpus();
310}
311#endif /* CONFIG_SMP */
312
313extern struct machdep_calls pSeries_md;
314extern struct machdep_calls pmac_md;
315extern struct machdep_calls maple_md;
316extern struct machdep_calls bpa_md;
317extern struct machdep_calls iseries_md;
318
319/* Ultimately, stuff them in an elf section like initcalls... */
320static struct machdep_calls __initdata *machines[] = {
321#ifdef CONFIG_PPC_PSERIES
322 &pSeries_md,
323#endif /* CONFIG_PPC_PSERIES */
324#ifdef CONFIG_PPC_PMAC
325 &pmac_md,
326#endif /* CONFIG_PPC_PMAC */
327#ifdef CONFIG_PPC_MAPLE
328 &maple_md,
329#endif /* CONFIG_PPC_MAPLE */
330#ifdef CONFIG_PPC_BPA
331 &bpa_md,
332#endif
333#ifdef CONFIG_PPC_ISERIES
334 &iseries_md,
335#endif
336 NULL
337};
338
339/*
340 * Early initialization entry point. This is called by head.S
341 * with MMU translation disabled. We rely on the "feature" of
342 * the CPU that ignores the top 2 bits of the address in real
343 * mode so we can access kernel globals normally provided we
344 * only toy with things in the RMO region. From here, we do
345 * some early parsing of the device-tree to setup out LMB
346 * data structures, and allocate & initialize the hash table
347 * and segment tables so we can start running with translation
348 * enabled.
349 *
350 * It is this function which will call the probe() callback of
351 * the various platform types and copy the matching one to the
352 * global ppc_md structure. Your platform can eventually do
353 * some very early initializations from the probe() routine, but
354 * this is not recommended, be very careful as, for example, the
355 * device-tree is not accessible via normal means at this point.
356 */
357
358void __init early_setup(unsigned long dt_ptr)
359{
360 struct paca_struct *lpaca = get_paca();
361 static struct machdep_calls **mach;
362
363 /*
364 * Enable early debugging if any specified (see top of
365 * this file)
366 */
367 EARLY_DEBUG_INIT();
368
369 DBG(" -> early_setup()\n");
370
371 /*
372 * Fill the default DBG level (do we want to keep
373 * that old mecanism around forever ?)
374 */
375 ppcdbg_initialize();
376
377 /*
378 * Do early initializations using the flattened device
379 * tree, like retreiving the physical memory map or
380 * calculating/retreiving the hash table size
381 */
382 early_init_devtree(__va(dt_ptr));
383
384 /*
385 * Iterate all ppc_md structures until we find the proper
386 * one for the current machine type
387 */
388 DBG("Probing machine type for platform %x...\n",
389 systemcfg->platform);
390
391 for (mach = machines; *mach; mach++) {
392 if ((*mach)->probe(systemcfg->platform))
393 break;
394 }
395 /* What can we do if we didn't find ? */
396 if (*mach == NULL) {
397 DBG("No suitable machine found !\n");
398 for (;;);
399 }
400 ppc_md = **mach;
401
402 DBG("Found, Initializing memory management...\n");
403
404 /*
405 * Initialize stab / SLB management
406 */
407 if (!firmware_has_feature(FW_FEATURE_ISERIES))
408 stab_initialize(lpaca->stab_real);
409
410 /*
411 * Initialize the MMU Hash table and create the linear mapping
412 * of memory
413 */
414 htab_initialize();
415
416 DBG(" <- early_setup()\n");
417}
418
419
420/*
421 * Initialize some remaining members of the ppc64_caches and systemcfg structures
422 * (at least until we get rid of them completely). This is mostly some
423 * cache informations about the CPU that will be used by cache flush
424 * routines and/or provided to userland
425 */
426static void __init initialize_cache_info(void)
427{
428 struct device_node *np;
429 unsigned long num_cpus = 0;
430
431 DBG(" -> initialize_cache_info()\n");
432
433 for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
434 num_cpus += 1;
435
436 /* We're assuming *all* of the CPUs have the same
437 * d-cache and i-cache sizes... -Peter
438 */
439
440 if ( num_cpus == 1 ) {
441 u32 *sizep, *lsizep;
442 u32 size, lsize;
443 const char *dc, *ic;
444
445 /* Then read cache informations */
446 if (systemcfg->platform == PLATFORM_POWERMAC) {
447 dc = "d-cache-block-size";
448 ic = "i-cache-block-size";
449 } else {
450 dc = "d-cache-line-size";
451 ic = "i-cache-line-size";
452 }
453
454 size = 0;
455 lsize = cur_cpu_spec->dcache_bsize;
456 sizep = (u32 *)get_property(np, "d-cache-size", NULL);
457 if (sizep != NULL)
458 size = *sizep;
459 lsizep = (u32 *) get_property(np, dc, NULL);
460 if (lsizep != NULL)
461 lsize = *lsizep;
462 if (sizep == 0 || lsizep == 0)
463 DBG("Argh, can't find dcache properties ! "
464 "sizep: %p, lsizep: %p\n", sizep, lsizep);
465
466 systemcfg->dcache_size = ppc64_caches.dsize = size;
467 systemcfg->dcache_line_size =
468 ppc64_caches.dline_size = lsize;
469 ppc64_caches.log_dline_size = __ilog2(lsize);
470 ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
471
472 size = 0;
473 lsize = cur_cpu_spec->icache_bsize;
474 sizep = (u32 *)get_property(np, "i-cache-size", NULL);
475 if (sizep != NULL)
476 size = *sizep;
477 lsizep = (u32 *)get_property(np, ic, NULL);
478 if (lsizep != NULL)
479 lsize = *lsizep;
480 if (sizep == 0 || lsizep == 0)
481 DBG("Argh, can't find icache properties ! "
482 "sizep: %p, lsizep: %p\n", sizep, lsizep);
483
484 systemcfg->icache_size = ppc64_caches.isize = size;
485 systemcfg->icache_line_size =
486 ppc64_caches.iline_size = lsize;
487 ppc64_caches.log_iline_size = __ilog2(lsize);
488 ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
489 }
490 }
491
492 /* Add an eye catcher and the systemcfg layout version number */
493 strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
494 systemcfg->version.major = SYSTEMCFG_MAJOR;
495 systemcfg->version.minor = SYSTEMCFG_MINOR;
496 systemcfg->processor = mfspr(SPRN_PVR);
497
498 DBG(" <- initialize_cache_info()\n");
499}
500
501static void __init check_for_initrd(void)
502{
503#ifdef CONFIG_BLK_DEV_INITRD
504 u64 *prop;
505
506 DBG(" -> check_for_initrd()\n");
507
508 if (of_chosen) {
509 prop = (u64 *)get_property(of_chosen,
510 "linux,initrd-start", NULL);
511 if (prop != NULL) {
512 initrd_start = (unsigned long)__va(*prop);
513 prop = (u64 *)get_property(of_chosen,
514 "linux,initrd-end", NULL);
515 if (prop != NULL) {
516 initrd_end = (unsigned long)__va(*prop);
517 initrd_below_start_ok = 1;
518 } else
519 initrd_start = 0;
520 }
521 }
522
523 /* If we were passed an initrd, set the ROOT_DEV properly if the values
524 * look sensible. If not, clear initrd reference.
525 */
526 if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
527 initrd_end > initrd_start)
528 ROOT_DEV = Root_RAM0;
529 else
530 initrd_start = initrd_end = 0;
531
532 if (initrd_start)
533 printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end);
534
535 DBG(" <- check_for_initrd()\n");
536#endif /* CONFIG_BLK_DEV_INITRD */
537}
538
539/*
540 * Do some initial setup of the system. The parameters are those which
541 * were passed in from the bootloader.
542 */
543void __init setup_system(void)
544{
545 DBG(" -> setup_system()\n");
546
547 /*
548 * Unflatten the device-tree passed by prom_init or kexec
549 */
550 unflatten_device_tree();
551
552 /*
553 * Fill the ppc64_caches & systemcfg structures with informations
554 * retreived from the device-tree. Need to be called before
555 * finish_device_tree() since the later requires some of the
556 * informations filled up here to properly parse the interrupt
557 * tree.
558 * It also sets up the cache line sizes which allows to call
559 * routines like flush_icache_range (used by the hash init
560 * later on).
561 */
562 initialize_cache_info();
563
564#ifdef CONFIG_PPC_RTAS
565 /*
566 * Initialize RTAS if available
567 */
568 rtas_initialize();
569#endif /* CONFIG_PPC_RTAS */
570 printk("%s:%d rtas.dev=%p (@ %p)\n", __FILE__, __LINE__, rtas.dev,
571 &rtas.dev);
572
573 /*
574 * Check if we have an initrd provided via the device-tree
575 */
576 check_for_initrd();
577 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
578
579 /*
580 * Do some platform specific early initializations, that includes
581 * setting up the hash table pointers. It also sets up some interrupt-mapping
582 * related options that will be used by finish_device_tree()
583 */
584 ppc_md.init_early();
585 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
586
587 /*
588 * "Finish" the device-tree, that is do the actual parsing of
589 * some of the properties like the interrupt map
590 */
591 finish_device_tree();
592 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
593
594 /*
595 * Initialize xmon
596 */
597#ifdef CONFIG_XMON_DEFAULT
598 xmon_init(1);
599#endif
600 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
601 /*
602 * Register early console
603 */
604 register_early_udbg_console();
605 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
606
607 /* Save unparsed command line copy for /proc/cmdline */
608 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
609
610 parse_early_param();
611 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
612
613#ifdef CONFIG_SMP
614 /*
615 * iSeries has already initialized the cpu maps at this point.
616 */
617 setup_cpu_maps();
618 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
619
620 /* Release secondary cpus out of their spinloops at 0x60 now that
621 * we can map physical -> logical CPU ids
622 */
623 smp_release_cpus();
624 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
625#endif
626
627 printk("Starting Linux PPC64 %s\n", system_utsname.version);
628
629 printk("-----------------------------------------------------\n");
630 printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
631 printk("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch);
632 printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller);
633 printk("systemcfg = 0x%p\n", systemcfg);
634 printk("systemcfg->platform = 0x%x\n", systemcfg->platform);
635 printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount);
636 printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
637 printk("ppc64_caches.dcache_line_size = 0x%x\n",
638 ppc64_caches.dline_size);
639 printk("ppc64_caches.icache_line_size = 0x%x\n",
640 ppc64_caches.iline_size);
641 printk("htab_address = 0x%p\n", htab_address);
642 printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
643 printk("-----------------------------------------------------\n");
644 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
645
646 mm_init_ppc64();
647 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
648
649 DBG(" <- setup_system()\n");
650}
651
652/* also used by kexec */
653void machine_shutdown(void)
654{
655 if (ppc_md.nvram_sync)
656 ppc_md.nvram_sync();
657}
658
659void machine_restart(char *cmd)
660{
661 machine_shutdown();
662 ppc_md.restart(cmd);
663#ifdef CONFIG_SMP
664 smp_send_stop();
665#endif
666 printk(KERN_EMERG "System Halted, OK to turn off power\n");
667 local_irq_disable();
668 while (1) ;
669}
670
671void machine_power_off(void)
672{
673 machine_shutdown();
674 ppc_md.power_off();
675#ifdef CONFIG_SMP
676 smp_send_stop();
677#endif
678 printk(KERN_EMERG "System Halted, OK to turn off power\n");
679 local_irq_disable();
680 while (1) ;
681}
682/* Used by the G5 thermal driver */
683EXPORT_SYMBOL_GPL(machine_power_off);
684
685void machine_halt(void)
686{
687 machine_shutdown();
688 ppc_md.halt();
689#ifdef CONFIG_SMP
690 smp_send_stop();
691#endif
692 printk(KERN_EMERG "System Halted, OK to turn off power\n");
693 local_irq_disable();
694 while (1) ;
695}
696
697static int ppc64_panic_event(struct notifier_block *this,
698 unsigned long event, void *ptr)
699{
700 ppc_md.panic((char *)ptr); /* May not return */
701 return NOTIFY_DONE;
702}
703
704
705#ifdef CONFIG_SMP
706DEFINE_PER_CPU(unsigned int, pvr);
707#endif
708
709static int show_cpuinfo(struct seq_file *m, void *v)
710{
711 unsigned long cpu_id = (unsigned long)v - 1;
712 unsigned int pvr;
713 unsigned short maj;
714 unsigned short min;
715
716 if (cpu_id == NR_CPUS) {
717 seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
718
719 if (ppc_md.get_cpuinfo != NULL)
720 ppc_md.get_cpuinfo(m);
721
722 return 0;
723 }
724
725 /* We only show online cpus: disable preempt (overzealous, I
726 * knew) to prevent cpu going down. */
727 preempt_disable();
728 if (!cpu_online(cpu_id)) {
729 preempt_enable();
730 return 0;
731 }
732
733#ifdef CONFIG_SMP
734 pvr = per_cpu(pvr, cpu_id);
735#else
736 pvr = mfspr(SPRN_PVR);
737#endif
738 maj = (pvr >> 8) & 0xFF;
739 min = pvr & 0xFF;
740
741 seq_printf(m, "processor\t: %lu\n", cpu_id);
742 seq_printf(m, "cpu\t\t: ");
743
744 if (cur_cpu_spec->pvr_mask)
745 seq_printf(m, "%s", cur_cpu_spec->cpu_name);
746 else
747 seq_printf(m, "unknown (%08x)", pvr);
748
749#ifdef CONFIG_ALTIVEC
750 if (cpu_has_feature(CPU_FTR_ALTIVEC))
751 seq_printf(m, ", altivec supported");
752#endif /* CONFIG_ALTIVEC */
753
754 seq_printf(m, "\n");
755
756 /*
757 * Assume here that all clock rates are the same in a
758 * smp system. -- Cort
759 */
760 seq_printf(m, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,
761 ppc_proc_freq % 1000000);
762
763 seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
764
765 preempt_enable();
766 return 0;
767}
768
769static void *c_start(struct seq_file *m, loff_t *pos)
770{
771 return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;
772}
773static void *c_next(struct seq_file *m, void *v, loff_t *pos)
774{
775 ++*pos;
776 return c_start(m, pos);
777}
778static void c_stop(struct seq_file *m, void *v)
779{
780}
781struct seq_operations cpuinfo_op = {
782 .start =c_start,
783 .next = c_next,
784 .stop = c_stop,
785 .show = show_cpuinfo,
786};
787
788/*
789 * These three variables are used to save values passed to us by prom_init()
790 * via the device tree. The TCE variables are needed because with a memory_limit
791 * in force we may need to explicitly map the TCE are at the top of RAM.
792 */
793unsigned long memory_limit;
794unsigned long tce_alloc_start;
795unsigned long tce_alloc_end;
796
797#ifdef CONFIG_PPC_ISERIES
798/*
799 * On iSeries we just parse the mem=X option from the command line.
800 * On pSeries it's a bit more complicated, see prom_init_mem()
801 */
802static int __init early_parsemem(char *p)
803{
804 if (!p)
805 return 0;
806
807 memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
808
809 return 0;
810}
811early_param("mem", early_parsemem);
812#endif /* CONFIG_PPC_ISERIES */
813
814#ifdef CONFIG_PPC_MULTIPLATFORM
815static int __init set_preferred_console(void)
816{
817 struct device_node *prom_stdout = NULL;
818 char *name;
819 u32 *spd;
820 int offset = 0;
821
822 DBG(" -> set_preferred_console()\n");
823
824 /* The user has requested a console so this is already set up. */
825 if (strstr(saved_command_line, "console=")) {
826 DBG(" console was specified !\n");
827 return -EBUSY;
828 }
829
830 if (!of_chosen) {
831 DBG(" of_chosen is NULL !\n");
832 return -ENODEV;
833 }
834 /* We are getting a weird phandle from OF ... */
835 /* ... So use the full path instead */
836 name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
837 if (name == NULL) {
838 DBG(" no linux,stdout-path !\n");
839 return -ENODEV;
840 }
841 prom_stdout = of_find_node_by_path(name);
842 if (!prom_stdout) {
843 DBG(" can't find stdout package %s !\n", name);
844 return -ENODEV;
845 }
846 DBG("stdout is %s\n", prom_stdout->full_name);
847
848 name = (char *)get_property(prom_stdout, "name", NULL);
849 if (!name) {
850 DBG(" stdout package has no name !\n");
851 goto not_found;
852 }
853 spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
854
855 if (0)
856 ;
857#ifdef CONFIG_SERIAL_8250_CONSOLE
858 else if (strcmp(name, "serial") == 0) {
859 int i;
860 u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
861 if (i > 8) {
862 switch (reg[1]) {
863 case 0x3f8:
864 offset = 0;
865 break;
866 case 0x2f8:
867 offset = 1;
868 break;
869 case 0x898:
870 offset = 2;
871 break;
872 case 0x890:
873 offset = 3;
874 break;
875 default:
876 /* We dont recognise the serial port */
877 goto not_found;
878 }
879 }
880 }
881#endif /* CONFIG_SERIAL_8250_CONSOLE */
882#ifdef CONFIG_PPC_PSERIES
883 else if (strcmp(name, "vty") == 0) {
884 u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL);
885 char *compat = (char *)get_property(prom_stdout, "compatible", NULL);
886
887 if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) {
888 /* Host Virtual Serial Interface */
889 int offset;
890 switch (reg[0]) {
891 case 0x30000000:
892 offset = 0;
893 break;
894 case 0x30000001:
895 offset = 1;
896 break;
897 default:
898 goto not_found;
899 }
900 of_node_put(prom_stdout);
901 DBG("Found hvsi console at offset %d\n", offset);
902 return add_preferred_console("hvsi", offset, NULL);
903 } else {
904 /* pSeries LPAR virtual console */
905 of_node_put(prom_stdout);
906 DBG("Found hvc console\n");
907 return add_preferred_console("hvc", 0, NULL);
908 }
909 }
910#endif /* CONFIG_PPC_PSERIES */
911#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
912 else if (strcmp(name, "ch-a") == 0)
913 offset = 0;
914 else if (strcmp(name, "ch-b") == 0)
915 offset = 1;
916#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
917 else
918 goto not_found;
919 of_node_put(prom_stdout);
920
921 DBG("Found serial console at ttyS%d\n", offset);
922
923 if (spd) {
924 static char __initdata opt[16];
925 sprintf(opt, "%d", *spd);
926 return add_preferred_console("ttyS", offset, opt);
927 } else
928 return add_preferred_console("ttyS", offset, NULL);
929
930 not_found:
931 DBG("No preferred console found !\n");
932 of_node_put(prom_stdout);
933 return -ENODEV;
934}
935console_initcall(set_preferred_console);
936#endif /* CONFIG_PPC_MULTIPLATFORM */
937
938#ifdef CONFIG_IRQSTACKS
939static void __init irqstack_early_init(void)
940{
941 unsigned int i;
942
943 /*
944 * interrupt stacks must be under 256MB, we cannot afford to take
945 * SLB misses on them.
946 */
947 for_each_cpu(i) {
948 softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
949 THREAD_SIZE, 0x10000000));
950 hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
951 THREAD_SIZE, 0x10000000));
952 }
953}
954#else
955#define irqstack_early_init()
956#endif
957
958/*
959 * Stack space used when we detect a bad kernel stack pointer, and
960 * early in SMP boots before relocation is enabled.
961 */
962static void __init emergency_stack_init(void)
963{
964 unsigned long limit;
965 unsigned int i;
966
967 /*
968 * Emergency stacks must be under 256MB, we cannot afford to take
969 * SLB misses on them. The ABI also requires them to be 128-byte
970 * aligned.
971 *
972 * Since we use these as temporary stacks during secondary CPU
973 * bringup, we need to get at them in real mode. This means they
974 * must also be within the RMO region.
975 */
976 limit = min(0x10000000UL, lmb.rmo_size);
977
978 for_each_cpu(i)
979 paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128,
980 limit)) + PAGE_SIZE;
981}
982
983/*
984 * Called from setup_arch to initialize the bitmap of available
985 * syscalls in the systemcfg page
986 */
987void __init setup_syscall_map(void)
988{
989 unsigned int i, count64 = 0, count32 = 0;
990 extern unsigned long *sys_call_table;
991 extern unsigned long sys_ni_syscall;
992
993
994 for (i = 0; i < __NR_syscalls; i++) {
995 if (sys_call_table[i*2] != sys_ni_syscall) {
996 count64++;
997 systemcfg->syscall_map_64[i >> 5] |=
998 0x80000000UL >> (i & 0x1f);
999 }
1000 if (sys_call_table[i*2+1] != sys_ni_syscall) {
1001 count32++;
1002 systemcfg->syscall_map_32[i >> 5] |=
1003 0x80000000UL >> (i & 0x1f);
1004 }
1005 }
1006 printk(KERN_INFO "Syscall map setup, %d 32-bit and %d 64-bit syscalls\n",
1007 count32, count64);
1008}
1009
1010/*
1011 * Called into from start_kernel, after lock_kernel has been called.
1012 * Initializes bootmem, which is unsed to manage page allocation until
1013 * mem_init is called.
1014 */
1015void __init setup_arch(char **cmdline_p)
1016{
1017 extern void do_init_bootmem(void);
1018
1019 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
1020 ppc64_boot_msg(0x12, "Setup Arch");
1021
1022 *cmdline_p = cmd_line;
1023
1024 /*
1025 * Set cache line size based on type of cpu as a default.
1026 * Systems with OF can look in the properties on the cpu node(s)
1027 * for a possibly more accurate value.
1028 */
1029 dcache_bsize = ppc64_caches.dline_size;
1030 icache_bsize = ppc64_caches.iline_size;
1031
1032 /* reboot on panic */
1033 panic_timeout = 180;
1034 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
1035
1036 if (ppc_md.panic)
1037 notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
1038
1039 init_mm.start_code = PAGE_OFFSET;
1040 init_mm.end_code = (unsigned long) _etext;
1041 init_mm.end_data = (unsigned long) _edata;
1042 init_mm.brk = klimit;
1043
1044 irqstack_early_init();
1045 emergency_stack_init();
1046
1047 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
1048 stabs_alloc();
1049
1050 /* set up the bootmem stuff with available memory */
1051 do_init_bootmem();
1052 sparse_init();
1053
1054 printk("%s:%d rtas.dev=%p\n", __FILE__, __LINE__, rtas.dev);
1055 /* initialize the syscall map in systemcfg */
1056 setup_syscall_map();
1057
1058 ppc_md.setup_arch();
1059
1060 /* Use the default idle loop if the platform hasn't provided one. */
1061 if (NULL == ppc_md.idle_loop) {
1062 ppc_md.idle_loop = default_idle;
1063 printk(KERN_INFO "Using default idle loop\n");
1064 }
1065
1066 paging_init();
1067 ppc64_boot_msg(0x15, "Setup Done");
1068}
1069
1070
1071/* ToDo: do something useful if ppc_md is not yet setup. */
1072#define PPC64_LINUX_FUNCTION 0x0f000000
1073#define PPC64_IPL_MESSAGE 0xc0000000
1074#define PPC64_TERM_MESSAGE 0xb0000000
1075
1076static void ppc64_do_msg(unsigned int src, const char *msg)
1077{
1078 if (ppc_md.progress) {
1079 char buf[128];
1080
1081 sprintf(buf, "%08X\n", src);
1082 ppc_md.progress(buf, 0);
1083 snprintf(buf, 128, "%s", msg);
1084 ppc_md.progress(buf, 0);
1085 }
1086}
1087
1088/* Print a boot progress message. */
1089void ppc64_boot_msg(unsigned int src, const char *msg)
1090{
1091 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);
1092 printk("[boot]%04x %s\n", src, msg);
1093}
1094
1095/* Print a termination message (print only -- does not stop the kernel) */
1096void ppc64_terminate_msg(unsigned int src, const char *msg)
1097{
1098 ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
1099 printk("[terminate]%04x %s\n", src, msg);
1100}
1101
1102/* This should only be called on processor 0 during calibrate decr */
1103void __init setup_default_decr(void)
1104{
1105 struct paca_struct *lpaca = get_paca();
1106
1107 lpaca->default_decr = tb_ticks_per_jiffy;
1108 lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
1109}
1110
1111#ifndef CONFIG_PPC_ISERIES
1112/*
1113 * This function can be used by platforms to "find" legacy serial ports.
1114 * It works for "serial" nodes under an "isa" node, and will try to
1115 * respect the "ibm,aix-loc" property if any. It works with up to 8
1116 * ports.
1117 */
1118
1119#define MAX_LEGACY_SERIAL_PORTS 8
1120static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
1121static unsigned int old_serial_count;
1122
1123void __init generic_find_legacy_serial_ports(u64 *physport,
1124 unsigned int *default_speed)
1125{
1126 struct device_node *np;
1127 u32 *sizeprop;
1128
1129 struct isa_reg_property {
1130 u32 space;
1131 u32 address;
1132 u32 size;
1133 };
1134 struct pci_reg_property {
1135 struct pci_address addr;
1136 u32 size_hi;
1137 u32 size_lo;
1138 };
1139
1140 DBG(" -> generic_find_legacy_serial_port()\n");
1141
1142 *physport = 0;
1143 if (default_speed)
1144 *default_speed = 0;
1145
1146 np = of_find_node_by_path("/");
1147 if (!np)
1148 return;
1149
1150 /* First fill our array */
1151 for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
1152 struct device_node *isa, *pci;
1153 struct isa_reg_property *reg;
1154 unsigned long phys_size, addr_size, io_base;
1155 u32 *rangesp;
1156 u32 *interrupts, *clk, *spd;
1157 char *typep;
1158 int index, rlen, rentsize;
1159
1160 /* Ok, first check if it's under an "isa" parent */
1161 isa = of_get_parent(np);
1162 if (!isa || strcmp(isa->name, "isa")) {
1163 DBG("%s: no isa parent found\n", np->full_name);
1164 continue;
1165 }
1166
1167 /* Now look for an "ibm,aix-loc" property that gives us ordering
1168 * if any...
1169 */
1170 typep = (char *)get_property(np, "ibm,aix-loc", NULL);
1171
1172 /* Get the ISA port number */
1173 reg = (struct isa_reg_property *)get_property(np, "reg", NULL);
1174 if (reg == NULL)
1175 goto next_port;
1176 /* We assume the interrupt number isn't translated ... */
1177 interrupts = (u32 *)get_property(np, "interrupts", NULL);
1178 /* get clock freq. if present */
1179 clk = (u32 *)get_property(np, "clock-frequency", NULL);
1180 /* get default speed if present */
1181 spd = (u32 *)get_property(np, "current-speed", NULL);
1182 /* Default to locate at end of array */
1183 index = old_serial_count; /* end of the array by default */
1184
1185 /* If we have a location index, then use it */
1186 if (typep && *typep == 'S') {
1187 index = simple_strtol(typep+1, NULL, 0) - 1;
1188 /* if index is out of range, use end of array instead */
1189 if (index >= MAX_LEGACY_SERIAL_PORTS)
1190 index = old_serial_count;
1191 /* if our index is still out of range, that mean that
1192 * array is full, we could scan for a free slot but that
1193 * make little sense to bother, just skip the port
1194 */
1195 if (index >= MAX_LEGACY_SERIAL_PORTS)
1196 goto next_port;
1197 if (index >= old_serial_count)
1198 old_serial_count = index + 1;
1199 /* Check if there is a port who already claimed our slot */
1200 if (serial_ports[index].iobase != 0) {
1201 /* if we still have some room, move it, else override */
1202 if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) {
1203 DBG("Moved legacy port %d -> %d\n", index,
1204 old_serial_count);
1205 serial_ports[old_serial_count++] =
1206 serial_ports[index];
1207 } else {
1208 DBG("Replacing legacy port %d\n", index);
1209 }
1210 }
1211 }
1212 if (index >= MAX_LEGACY_SERIAL_PORTS)
1213 goto next_port;
1214 if (index >= old_serial_count)
1215 old_serial_count = index + 1;
1216
1217 /* Now fill the entry */
1218 memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port));
1219 serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16;
1220 serial_ports[index].iobase = reg->address;
1221 serial_ports[index].irq = interrupts ? interrupts[0] : 0;
1222 serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
1223
1224 DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
1225 index,
1226 serial_ports[index].iobase,
1227 serial_ports[index].irq,
1228 serial_ports[index].uartclk);
1229
1230 /* Get phys address of IO reg for port 1 */
1231 if (index != 0)
1232 goto next_port;
1233
1234 pci = of_get_parent(isa);
1235 if (!pci) {
1236 DBG("%s: no pci parent found\n", np->full_name);
1237 goto next_port;
1238 }
1239
1240 rangesp = (u32 *)get_property(pci, "ranges", &rlen);
1241 if (rangesp == NULL) {
1242 of_node_put(pci);
1243 goto next_port;
1244 }
1245 rlen /= 4;
1246
1247 /* we need the #size-cells of the PCI bridge node itself */
1248 phys_size = 1;
1249 sizeprop = (u32 *)get_property(pci, "#size-cells", NULL);
1250 if (sizeprop != NULL)
1251 phys_size = *sizeprop;
1252 /* we need the parent #addr-cells */
1253 addr_size = prom_n_addr_cells(pci);
1254 rentsize = 3 + addr_size + phys_size;
1255 io_base = 0;
1256 for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) {
1257 if (((rangesp[0] >> 24) & 0x3) != 1)
1258 continue; /* not IO space */
1259 io_base = rangesp[3];
1260 if (addr_size == 2)
1261 io_base = (io_base << 32) | rangesp[4];
1262 }
1263 if (io_base != 0) {
1264 *physport = io_base + reg->address;
1265 if (default_speed && spd)
1266 *default_speed = *spd;
1267 }
1268 of_node_put(pci);
1269 next_port:
1270 of_node_put(isa);
1271 }
1272
1273 DBG(" <- generic_find_legacy_serial_port()\n");
1274}
1275
1276static struct platform_device serial_device = {
1277 .name = "serial8250",
1278 .id = PLAT8250_DEV_PLATFORM,
1279 .dev = {
1280 .platform_data = serial_ports,
1281 },
1282};
1283
1284static int __init serial_dev_init(void)
1285{
1286 return platform_device_register(&serial_device);
1287}
1288arch_initcall(serial_dev_init);
1289
1290#endif /* CONFIG_PPC_ISERIES */
1291
1292int check_legacy_ioport(unsigned long base_port)
1293{
1294 if (ppc_md.check_legacy_ioport == NULL)
1295 return 0;
1296 return ppc_md.check_legacy_ioport(base_port);
1297}
1298EXPORT_SYMBOL(check_legacy_ioport);
1299
1300#ifdef CONFIG_XMON
1301static int __init early_xmon(char *p)
1302{
1303 /* ensure xmon is enabled */
1304 if (p) {
1305 if (strncmp(p, "on", 2) == 0)
1306 xmon_init(1);
1307 if (strncmp(p, "off", 3) == 0)
1308 xmon_init(0);
1309 if (strncmp(p, "early", 5) != 0)
1310 return 0;
1311 }
1312 xmon_init(1);
1313 debugger(NULL);
1314
1315 return 0;
1316}
1317early_param("xmon", early_xmon);
1318#endif
1319
1320void cpu_die(void)
1321{
1322 if (ppc_md.cpu_die)
1323 ppc_md.cpu_die();
1324}
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index a8cedb96de5f..30367a0237dd 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -7,3 +7,7 @@ obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o
7obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o memcpy_64.o \ 7obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o memcpy_64.o \
8 usercopy_64.o sstep.o checksum_64.o mem_64.o 8 usercopy_64.o sstep.o checksum_64.o mem_64.o
9obj-$(CONFIG_PPC_ISERIES) += e2a.o 9obj-$(CONFIG_PPC_ISERIES) += e2a.o
10ifeq ($(CONFIG_PPC64),y)
11obj-$(CONFIG_SMP) += locks.o
12endif
13
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c
new file mode 100644
index 000000000000..4b8c5ad5e7dc
--- /dev/null
+++ b/arch/powerpc/lib/locks.c
@@ -0,0 +1,95 @@
1/*
2 * Spin and read/write lock operations.
3 *
4 * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM
5 * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
6 * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM
7 * Rework to support virtual processors
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/spinlock.h>
18#include <linux/module.h>
19#include <linux/stringify.h>
20
21/* waiting for a spinlock... */
22#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
23#include <asm/hvcall.h>
24#include <asm/iSeries/HvCall.h>
25
26void __spin_yield(raw_spinlock_t *lock)
27{
28 unsigned int lock_value, holder_cpu, yield_count;
29 struct paca_struct *holder_paca;
30
31 lock_value = lock->slock;
32 if (lock_value == 0)
33 return;
34 holder_cpu = lock_value & 0xffff;
35 BUG_ON(holder_cpu >= NR_CPUS);
36 holder_paca = &paca[holder_cpu];
37 yield_count = holder_paca->lppaca.yield_count;
38 if ((yield_count & 1) == 0)
39 return; /* virtual cpu is currently running */
40 rmb();
41 if (lock->slock != lock_value)
42 return; /* something has changed */
43#ifdef CONFIG_PPC_ISERIES
44 HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
45 ((u64)holder_cpu << 32) | yield_count);
46#else
47 plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
48 yield_count);
49#endif
50}
51
52/*
53 * Waiting for a read lock or a write lock on a rwlock...
54 * This turns out to be the same for read and write locks, since
55 * we only know the holder if it is write-locked.
56 */
57void __rw_yield(raw_rwlock_t *rw)
58{
59 int lock_value;
60 unsigned int holder_cpu, yield_count;
61 struct paca_struct *holder_paca;
62
63 lock_value = rw->lock;
64 if (lock_value >= 0)
65 return; /* no write lock at present */
66 holder_cpu = lock_value & 0xffff;
67 BUG_ON(holder_cpu >= NR_CPUS);
68 holder_paca = &paca[holder_cpu];
69 yield_count = holder_paca->lppaca.yield_count;
70 if ((yield_count & 1) == 0)
71 return; /* virtual cpu is currently running */
72 rmb();
73 if (rw->lock != lock_value)
74 return; /* something has changed */
75#ifdef CONFIG_PPC_ISERIES
76 HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
77 ((u64)holder_cpu << 32) | yield_count);
78#else
79 plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
80 yield_count);
81#endif
82}
83#endif
84
85void __raw_spin_unlock_wait(raw_spinlock_t *lock)
86{
87 while (lock->slock) {
88 HMT_low();
89 if (SHARED_PROCESSOR)
90 __spin_yield(lock);
91 }
92 HMT_medium();
93}
94
95EXPORT_SYMBOL(__raw_spin_unlock_wait);
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 246212115a48..e656e02d9dd1 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -186,6 +186,9 @@ config BOOTX_TEXT
186 Say Y here to see progress messages from the boot firmware in text 186 Say Y here to see progress messages from the boot firmware in text
187 mode. Requires an Open Firmware compatible video card. 187 mode. Requires an Open Firmware compatible video card.
188 188
189config POWER4
190 def_bool y
191
189config POWER4_ONLY 192config POWER4_ONLY
190 bool "Optimize for POWER4" 193 bool "Optimize for POWER4"
191 default n 194 default n
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 79366e4a9e5c..5c598892f891 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -2,14 +2,14 @@
2# Makefile for the linux ppc64 kernel. 2# Makefile for the linux ppc64 kernel.
3# 3#
4 4
5EXTRA_CFLAGS += -mno-minimal-toc
6ifneq ($(CONFIG_PPC_MERGE),y) 5ifneq ($(CONFIG_PPC_MERGE),y)
6
7EXTRA_CFLAGS += -mno-minimal-toc
7extra-y := head.o vmlinux.lds 8extra-y := head.o vmlinux.lds
8endif
9 9
10obj-y := setup.o entry.o irq.o idle.o dma.o \ 10obj-y := setup.o entry.o irq.o idle.o dma.o \
11 time.o process.o signal.o syscalls.o misc.o ptrace.o \ 11 time.o process.o signal.o syscalls.o misc.o ptrace.o \
12 align.o semaphore.o bitops.o pacaData.o \ 12 align.o bitops.o pacaData.o \
13 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ 13 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
14 ptrace32.o signal32.o rtc.o init_task.o \ 14 ptrace32.o signal32.o rtc.o init_task.o \
15 cputable.o cpu_setup_power4.o \ 15 cputable.o cpu_setup_power4.o \
@@ -43,7 +43,6 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
43obj-$(CONFIG_BOOTX_TEXT) += btext.o 43obj-$(CONFIG_BOOTX_TEXT) += btext.o
44obj-$(CONFIG_HVCS) += hvcserver.o 44obj-$(CONFIG_HVCS) += hvcserver.o
45 45
46vio-obj-$(CONFIG_PPC_PSERIES) += pSeries_vio.o
47obj-$(CONFIG_IBMVIO) += vio.o $(vio-obj-y) 46obj-$(CONFIG_IBMVIO) += vio.o $(vio-obj-y)
48obj-$(CONFIG_XICS) += xics.o 47obj-$(CONFIG_XICS) += xics.o
49obj-$(CONFIG_MPIC) += mpic.o 48obj-$(CONFIG_MPIC) += mpic.o
@@ -59,8 +58,6 @@ obj-$(CONFIG_U3_DART) += u3_iommu.o
59 58
60ifdef CONFIG_SMP 59ifdef CONFIG_SMP
61obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o 60obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o
62obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o
63obj-$(CONFIG_PPC_BPA) += pSeries_smp.o
64obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o 61obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o
65endif 62endif
66 63
@@ -68,9 +65,62 @@ obj-$(CONFIG_KPROBES) += kprobes.o
68 65
69CFLAGS_ioctl32.o += -Ifs/ 66CFLAGS_ioctl32.o += -Ifs/
70 67
71ifneq ($(CONFIG_PPC_MERGE),y)
72ifeq ($(CONFIG_PPC_ISERIES),y) 68ifeq ($(CONFIG_PPC_ISERIES),y)
73arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s 69arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s
74AFLAGS_head.o += -Iarch/powerpc/kernel 70AFLAGS_head.o += -Iarch/powerpc/kernel
75endif 71endif
72
73else
74
75# Things still needed from here by the merged ppc code
76
77obj-y := irq.o idle.o dma.o \
78 time.o signal.o syscalls.o ptrace.o \
79 align.o bitops.o pacaData.o \
80 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
81 ptrace32.o signal32.o rtc.o \
82 cputable.o cpu_setup_power4.o \
83 iommu.o sysfs.o vdso.o pmc.o firmware.o
84obj-y += vdso32/ vdso64/
85
86pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o
87
88obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y)
89
90obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o
91
92obj-$(CONFIG_PPC_PSERIES) += rtasd.o ras.o udbg_16550.o
93
94obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \
95 bpa_iic.o spider-pic.o
96
97obj-$(CONFIG_KEXEC) += machine_kexec.o
98obj-$(CONFIG_EEH) += eeh.o
99obj-$(CONFIG_PROC_FS) += proc_ppc64.o
100obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
101obj-$(CONFIG_SMP) += smp.o
102obj-$(CONFIG_MODULES) += module.o
103obj-$(CONFIG_PPC_RTAS) += rtas.o rtas_pci.o
104obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
105obj-$(CONFIG_SCANLOG) += scanlog.o
106obj-$(CONFIG_LPARCFG) += lparcfg.o
107obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
108obj-$(CONFIG_HVCS) += hvcserver.o
109
110obj-$(CONFIG_IBMVIO) += vio.o
111obj-$(CONFIG_XICS) += xics.o
112
113obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o \
114 udbg_16550.o
115
116obj-$(CONFIG_U3_DART) += u3_iommu.o
117
118ifdef CONFIG_SMP
119obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o
120endif
121
122obj-$(CONFIG_KPROBES) += kprobes.o
123
124CFLAGS_ioctl32.o += -Ifs/
125
76endif 126endif
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index 1ff4fa05a973..1378fbbe1e57 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -77,6 +77,7 @@ int main(void)
77 DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); 77 DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
78 DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); 78 DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
79 DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); 79 DEFINE(PLATFORM, offsetof(struct systemcfg, platform));
80 DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
80 81
81 /* paca */ 82 /* paca */
82 DEFINE(PACA_SIZE, sizeof(struct paca_struct)); 83 DEFINE(PACA_SIZE, sizeof(struct paca_struct));
diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c
index 0cc463f24539..45ebe5486c40 100644
--- a/arch/ppc64/kernel/bpa_iommu.c
+++ b/arch/ppc64/kernel/bpa_iommu.c
@@ -99,7 +99,7 @@ get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_
99 break; 99 break;
100 100
101 default: /* not a known compile time constant */ 101 default: /* not a known compile time constant */
102 BUILD_BUG_ON(1); 102 BUG_ON(1);
103 break; 103 break;
104 } 104 }
105 105
diff --git a/arch/ppc64/kernel/bpa_setup.c b/arch/ppc64/kernel/bpa_setup.c
index 9f915f4222b1..017cf23e91fa 100644
--- a/arch/ppc64/kernel/bpa_setup.c
+++ b/arch/ppc64/kernel/bpa_setup.c
@@ -44,6 +44,7 @@
44#include <asm/nvram.h> 44#include <asm/nvram.h>
45#include <asm/cputable.h> 45#include <asm/cputable.h>
46#include <asm/ppc-pci.h> 46#include <asm/ppc-pci.h>
47#include <asm/irq.h>
47 48
48#include "bpa_iic.h" 49#include "bpa_iic.h"
49#include "bpa_iommu.h" 50#include "bpa_iommu.h"
diff --git a/arch/ppc64/kernel/maple_setup.c b/arch/ppc64/kernel/maple_setup.c
index 2a7fae01eee1..22987675f544 100644
--- a/arch/ppc64/kernel/maple_setup.c
+++ b/arch/ppc64/kernel/maple_setup.c
@@ -60,6 +60,7 @@
60#include <asm/of_device.h> 60#include <asm/of_device.h>
61#include <asm/lmb.h> 61#include <asm/lmb.h>
62#include <asm/mpic.h> 62#include <asm/mpic.h>
63#include <asm/udbg.h>
63 64
64#ifdef DEBUG 65#ifdef DEBUG
65#define DBG(fmt...) udbg_printf(fmt) 66#define DBG(fmt...) udbg_printf(fmt)
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index 497c3cd95bc3..be4c1693d149 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -73,6 +73,7 @@
73#include <asm/smu.h> 73#include <asm/smu.h>
74#include <asm/pmc.h> 74#include <asm/pmc.h>
75#include <asm/mpic.h> 75#include <asm/mpic.h>
76#include <asm/udbg.h>
76 77
77#include "pmac.h" 78#include "pmac.h"
78 79
diff --git a/include/asm-powerpc/hardirq.h b/include/asm-powerpc/hardirq.h
index 2c0a31b1008d..3b3e3b49ec12 100644
--- a/include/asm-powerpc/hardirq.h
+++ b/include/asm-powerpc/hardirq.h
@@ -1,6 +1,9 @@
1#ifndef _ASM_POWERPC_HARDIRQ_H 1#ifndef _ASM_POWERPC_HARDIRQ_H
2#define _ASM_POWERPC_HARDIRQ_H 2#define _ASM_POWERPC_HARDIRQ_H
3 3
4#include <asm/irq.h>
5#include <asm/bug.h>
6
4/* The __last_jiffy_stamp field is needed to ensure that no decrementer 7/* The __last_jiffy_stamp field is needed to ensure that no decrementer
5 * interrupt is lost on SMP machines. Since on most CPUs it is in the same 8 * interrupt is lost on SMP machines. Since on most CPUs it is in the same
6 * cache line as local_irq_count, it is cheap to access and is also used on UP 9 * cache line as local_irq_count, it is cheap to access and is also used on UP
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index 605a65e42063..c37b31b96337 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -10,7 +10,6 @@
10#include <linux/errno.h> 10#include <linux/errno.h>
11#include <asm/ptrace.h> 11#include <asm/ptrace.h>
12#include <asm/processor.h> 12#include <asm/processor.h>
13#include <asm/irq.h>
14 13
15extern void timer_interrupt(struct pt_regs *); 14extern void timer_interrupt(struct pt_regs *);
16extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); 15extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h
index 6cd52c130332..e4350e406d2a 100644
--- a/include/asm-powerpc/ppc_asm.h
+++ b/include/asm-powerpc/ppc_asm.h
@@ -1,10 +1,12 @@
1/* 1/*
2 * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. 2 * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
3 */ 3 */
4
5#ifndef _ASM_POWERPC_PPC_ASM_H 4#ifndef _ASM_POWERPC_PPC_ASM_H
6#define _ASM_POWERPC_PPC_ASM_H 5#define _ASM_POWERPC_PPC_ASM_H
7 6
7#include <linux/stringify.h>
8#include <linux/config.h>
9
8#ifdef __ASSEMBLY__ 10#ifdef __ASSEMBLY__
9 11
10/* 12/*
@@ -87,6 +89,66 @@
87#define RFDI .long 0x4c00004e /* rfdi instruction */ 89#define RFDI .long 0x4c00004e /* rfdi instruction */
88#define RFMCI .long 0x4c00004c /* rfmci instruction */ 90#define RFMCI .long 0x4c00004c /* rfmci instruction */
89 91
92#ifdef CONFIG_PPC64
93
94#define XGLUE(a,b) a##b
95#define GLUE(a,b) XGLUE(a,b)
96
97#define _GLOBAL(name) \
98 .section ".text"; \
99 .align 2 ; \
100 .globl name; \
101 .globl GLUE(.,name); \
102 .section ".opd","aw"; \
103name: \
104 .quad GLUE(.,name); \
105 .quad .TOC.@tocbase; \
106 .quad 0; \
107 .previous; \
108 .type GLUE(.,name),@function; \
109GLUE(.,name):
110
111#define _KPROBE(name) \
112 .section ".kprobes.text","a"; \
113 .align 2 ; \
114 .globl name; \
115 .globl GLUE(.,name); \
116 .section ".opd","aw"; \
117name: \
118 .quad GLUE(.,name); \
119 .quad .TOC.@tocbase; \
120 .quad 0; \
121 .previous; \
122 .type GLUE(.,name),@function; \
123GLUE(.,name):
124
125#define _STATIC(name) \
126 .section ".text"; \
127 .align 2 ; \
128 .section ".opd","aw"; \
129name: \
130 .quad GLUE(.,name); \
131 .quad .TOC.@tocbase; \
132 .quad 0; \
133 .previous; \
134 .type GLUE(.,name),@function; \
135GLUE(.,name):
136
137#else /* 32-bit */
138
139#define _GLOBAL(n) \
140 .text; \
141 .stabs __stringify(n:F-1),N_FUN,0,0,n;\
142 .globl n; \
143n:
144
145#define _KPROBE(n) \
146 .section ".kprobes.text","a"; \
147 .globl n; \
148n:
149
150#endif
151
90/* 152/*
91 * LOADADDR( rn, name ) 153 * LOADADDR( rn, name )
92 * loads the address of 'name' into 'rn' 154 * loads the address of 'name' into 'rn'
@@ -251,31 +313,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
251 .previous 313 .previous
252#endif 314#endif
253 315
254/* 316#ifdef CONFIG_PPC64
255 * On 64-bit cpus, we use the rfid instruction instead of rfi, but 317#define RFI rfid
256 * we then have to make sure we preserve the top 32 bits except for 318#define MTMSRD(r) mtmsrd r
257 * the 64-bit mode bit, which we clear.
258 */
259#if defined(CONFIG_PPC64BRIDGE)
260#define FIX_SRR1(ra, rb) \
261 mr rb,ra; \
262 mfmsr ra; \
263 clrldi ra,ra,1; /* turn off 64-bit mode */ \
264 rldimi ra,rb,0,32
265#define RFI .long 0x4c000024 /* rfid instruction */
266#define MTMSRD(r) .long (0x7c000164 + ((r) << 21)) /* mtmsrd */
267#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */
268#elif defined(CONFIG_PPC64)
269/* Insert the high 32 bits of the MSR into what will be the new
270 MSR (via SRR1 and rfid) This preserves the MSR.SF and MSR.ISF
271 bits. */
272
273#define FIX_SRR1(ra, rb) \
274 mr rb,ra; \
275 mfmsr ra; \
276 rldimi ra,rb,0,32
277
278#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */
279 319
280#else 320#else
281#define FIX_SRR1(ra, rb) 321#define FIX_SRR1(ra, rb)
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 194b56ee1693..efc40980cb48 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -196,6 +196,7 @@ extern int prom_n_intr_cells(struct device_node* np);
196extern void prom_get_irq_senses(unsigned char *senses, int off, int max); 196extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
197extern void prom_add_property(struct device_node* np, struct property* prop); 197extern void prom_add_property(struct device_node* np, struct property* prop);
198 198
199#ifdef CONFIG_PPC32
199/* 200/*
200 * PCI <-> OF matching functions 201 * PCI <-> OF matching functions
201 * (XXX should these be here?) 202 * (XXX should these be here?)
@@ -207,6 +208,8 @@ extern int pci_device_from_OF_node(struct device_node *node,
207extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int); 208extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
208extern struct device_node* pci_device_to_OF_node(struct pci_dev *); 209extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
209extern void pci_create_OF_bus_map(void); 210extern void pci_create_OF_bus_map(void);
211#endif
212
210extern struct resource *request_OF_resource(struct device_node* node, 213extern struct resource *request_OF_resource(struct device_node* node,
211 int index, const char* name_postfix); 214 int index, const char* name_postfix);
212extern int release_OF_resource(struct device_node* node, int index); 215extern int release_OF_resource(struct device_node* node, int index);
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 66866f7301a9..6463453b61a3 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -9,6 +9,7 @@
9 9
10#include <asm/hw_irq.h> 10#include <asm/hw_irq.h>
11#include <asm/ppc_asm.h> 11#include <asm/ppc_asm.h>
12#include <asm/atomic.h>
12 13
13/* 14/*
14 * Memory barrier. 15 * Memory barrier.
@@ -127,6 +128,7 @@ extern void flush_fp_to_thread(struct task_struct *);
127extern void enable_kernel_altivec(void); 128extern void enable_kernel_altivec(void);
128extern void giveup_altivec(struct task_struct *); 129extern void giveup_altivec(struct task_struct *);
129extern void load_up_altivec(struct task_struct *); 130extern void load_up_altivec(struct task_struct *);
131extern int emulate_altivec(struct pt_regs *);
130extern void giveup_spe(struct task_struct *); 132extern void giveup_spe(struct task_struct *);
131extern void load_up_spe(struct task_struct *); 133extern void load_up_spe(struct task_struct *);
132extern int fix_alignment(struct pt_regs *); 134extern int fix_alignment(struct pt_regs *);
@@ -176,6 +178,7 @@ extern struct task_struct *_switch(struct thread_struct *prev,
176 struct thread_struct *next); 178 struct thread_struct *next);
177 179
178extern unsigned int rtas_data; 180extern unsigned int rtas_data;
181extern int mem_init_done; /* set on boot once kmalloc can be called */
179 182
180/* 183/*
181 * Atomic exchange 184 * Atomic exchange
diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
index 8ca5fce626bb..c342c9eb07a4 100644
--- a/include/asm-ppc64/pci-bridge.h
+++ b/include/asm-ppc64/pci-bridge.h
@@ -106,6 +106,16 @@ static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
106 return fetch_dev_dn(dev); 106 return fetch_dev_dn(dev);
107} 107}
108 108
109static inline int pci_device_from_OF_node(struct device_node *np,
110 u8 *bus, u8 *devfn)
111{
112 if (!PCI_DN(np))
113 return -ENODEV;
114 *bus = PCI_DN(np)->busno;
115 *devfn = PCI_DN(np)->devfn;
116 return 0;
117}
118
109static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) 119static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
110{ 120{
111 if (bus->self) 121 if (bus->self)