aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-01-12 13:21:22 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-12 13:21:22 -0500
commit45bfe98bd790b5ded00462cd582effcfb42263cc (patch)
treed4a1f2c5303dda106635b615f8f40ea9104bf25e /arch
parent9f5974c8734d83d4ab7096ed98136a82f41210d6 (diff)
parent624cee31bcb14bfd85559fbec5dd7bb833542965 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
Fix up delete/modify conflict of arch/ppc/kernel/process.c by hand (it's gone, gone, gone). Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/Makefile6
-rw-r--r--arch/powerpc/kernel/pci_64.c5
-rw-r--r--arch/powerpc/kernel/process.c8
-rw-r--r--arch/powerpc/kernel/prom.c28
-rw-r--r--arch/powerpc/kernel/prom_init.c8
-rw-r--r--arch/powerpc/kernel/signal_32.c21
-rw-r--r--arch/powerpc/kernel/signal_64.c20
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c2
-rw-r--r--arch/powerpc/platforms/cell/setup.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/syscalls.c4
-rw-r--r--arch/powerpc/platforms/iseries/Makefile4
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c2
-rw-r--r--arch/powerpc/platforms/iseries/iommu.h35
-rw-r--r--arch/powerpc/platforms/iseries/irq.c19
-rw-r--r--arch/powerpc/platforms/iseries/lpardata.c5
-rw-r--r--arch/powerpc/platforms/iseries/lpevents.c12
-rw-r--r--arch/powerpc/platforms/iseries/mf.c16
-rw-r--r--arch/powerpc/platforms/iseries/pci.c1
-rw-r--r--arch/powerpc/platforms/iseries/vio.c2
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c12
-rw-r--r--arch/powerpc/platforms/powermac/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c5
-rw-r--r--arch/powerpc/platforms/pseries/hvcserver.c4
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c2
-rw-r--r--arch/powerpc/platforms/pseries/scanlog.c4
-rw-r--r--arch/powerpc/platforms/pseries/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/smp.c4
-rw-r--r--arch/powerpc/platforms/pseries/xics.c2
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c1
-rw-r--r--arch/powerpc/xmon/xmon.c14
-rw-r--r--arch/ppc/kernel/Makefile1
-rw-r--r--arch/ppc/kernel/process.c851
32 files changed, 148 insertions, 956 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index bbfa1bdceb4d..a94699d8dc52 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -11,7 +11,8 @@ CFLAGS_btext.o += -fPIC
11endif 11endif
12 12
13obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ 13obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
14 irq.o align.o signal_32.o pmc.o vdso.o 14 irq.o align.o signal_32.o pmc.o vdso.o \
15 init_task.o process.o
15obj-y += vdso32/ 16obj-y += vdso32/
16obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ 17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
17 signal_64.o ptrace32.o systbl.o \ 18 signal_64.o ptrace32.o systbl.o \
@@ -44,8 +45,7 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
44extra-$(CONFIG_8xx) := head_8xx.o 45extra-$(CONFIG_8xx) := head_8xx.o
45extra-y += vmlinux.lds 46extra-y += vmlinux.lds
46 47
47obj-y += process.o init_task.o time.o \ 48obj-y += time.o prom.o traps.o setup-common.o udbg.o
48 prom.o traps.o setup-common.o udbg.o
49obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o 49obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o
50obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o 50obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
51obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o 51obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 24fe70f40b66..c367520bc1c3 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -53,6 +53,7 @@ EXPORT_SYMBOL(io_page_mask);
53#ifdef CONFIG_PPC_MULTIPLATFORM 53#ifdef CONFIG_PPC_MULTIPLATFORM
54static void fixup_resource(struct resource *res, struct pci_dev *dev); 54static void fixup_resource(struct resource *res, struct pci_dev *dev);
55static void do_bus_setup(struct pci_bus *bus); 55static void do_bus_setup(struct pci_bus *bus);
56static void phbs_remap_io(void);
56#endif 57#endif
57 58
58/* pci_io_base -- the base address from which io bars are offsets. 59/* pci_io_base -- the base address from which io bars are offsets.
@@ -251,6 +252,7 @@ void pcibios_free_controller(struct pci_controller *phb)
251 kfree(phb); 252 kfree(phb);
252} 253}
253 254
255#ifndef CONFIG_PPC_ISERIES
254void __devinit pcibios_claim_one_bus(struct pci_bus *b) 256void __devinit pcibios_claim_one_bus(struct pci_bus *b)
255{ 257{
256 struct pci_dev *dev; 258 struct pci_dev *dev;
@@ -275,7 +277,6 @@ void __devinit pcibios_claim_one_bus(struct pci_bus *b)
275EXPORT_SYMBOL_GPL(pcibios_claim_one_bus); 277EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
276#endif 278#endif
277 279
278#ifndef CONFIG_PPC_ISERIES
279static void __init pcibios_claim_of_setup(void) 280static void __init pcibios_claim_of_setup(void)
280{ 281{
281 struct pci_bus *b; 282 struct pci_bus *b;
@@ -1218,7 +1219,7 @@ int remap_bus_range(struct pci_bus *bus)
1218} 1219}
1219EXPORT_SYMBOL(remap_bus_range); 1220EXPORT_SYMBOL(remap_bus_range);
1220 1221
1221void phbs_remap_io(void) 1222static void phbs_remap_io(void)
1222{ 1223{
1223 struct pci_controller *hose, *tmp; 1224 struct pci_controller *hose, *tmp;
1224 1225
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 1f816f0d7740..57703994a063 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -201,13 +201,13 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
201} 201}
202#endif /* CONFIG_SPE */ 202#endif /* CONFIG_SPE */
203 203
204#ifndef CONFIG_SMP
204/* 205/*
205 * If we are doing lazy switching of CPU state (FP, altivec or SPE), 206 * If we are doing lazy switching of CPU state (FP, altivec or SPE),
206 * and the current task has some state, discard it. 207 * and the current task has some state, discard it.
207 */ 208 */
208static inline void discard_lazy_cpu_state(void) 209void discard_lazy_cpu_state(void)
209{ 210{
210#ifndef CONFIG_SMP
211 preempt_disable(); 211 preempt_disable();
212 if (last_task_used_math == current) 212 if (last_task_used_math == current)
213 last_task_used_math = NULL; 213 last_task_used_math = NULL;
@@ -220,9 +220,10 @@ static inline void discard_lazy_cpu_state(void)
220 last_task_used_spe = NULL; 220 last_task_used_spe = NULL;
221#endif 221#endif
222 preempt_enable(); 222 preempt_enable();
223#endif /* CONFIG_SMP */
224} 223}
224#endif /* CONFIG_SMP */
225 225
226#ifdef CONFIG_PPC_MERGE /* XXX for now */
226int set_dabr(unsigned long dabr) 227int set_dabr(unsigned long dabr)
227{ 228{
228 if (ppc_md.set_dabr) 229 if (ppc_md.set_dabr)
@@ -231,6 +232,7 @@ int set_dabr(unsigned long dabr)
231 mtspr(SPRN_DABR, dabr); 232 mtspr(SPRN_DABR, dabr);
232 return 0; 233 return 0;
233} 234}
235#endif
234 236
235#ifdef CONFIG_PPC64 237#ifdef CONFIG_PPC64
236DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); 238DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 34ab0daec3a7..02e2115323e4 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1100,17 +1100,37 @@ static int __init early_init_dt_scan_memory(unsigned long node,
1100 1100
1101static void __init early_reserve_mem(void) 1101static void __init early_reserve_mem(void)
1102{ 1102{
1103 unsigned long base, size; 1103 u64 base, size;
1104 unsigned long *reserve_map; 1104 u64 *reserve_map;
1105 1105
1106 reserve_map = (unsigned long *)(((unsigned long)initial_boot_params) + 1106 reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
1107 initial_boot_params->off_mem_rsvmap); 1107 initial_boot_params->off_mem_rsvmap);
1108#ifdef CONFIG_PPC32
1109 /*
1110 * Handle the case where we might be booting from an old kexec
1111 * image that setup the mem_rsvmap as pairs of 32-bit values
1112 */
1113 if (*reserve_map > 0xffffffffull) {
1114 u32 base_32, size_32;
1115 u32 *reserve_map_32 = (u32 *)reserve_map;
1116
1117 while (1) {
1118 base_32 = *(reserve_map_32++);
1119 size_32 = *(reserve_map_32++);
1120 if (size_32 == 0)
1121 break;
1122 DBG("reserving: %lx -> %lx\n", base_32, size_32);
1123 lmb_reserve(base_32, size_32);
1124 }
1125 return;
1126 }
1127#endif
1108 while (1) { 1128 while (1) {
1109 base = *(reserve_map++); 1129 base = *(reserve_map++);
1110 size = *(reserve_map++); 1130 size = *(reserve_map++);
1111 if (size == 0) 1131 if (size == 0)
1112 break; 1132 break;
1113 DBG("reserving: %lx -> %lx\n", base, size); 1133 DBG("reserving: %llx -> %llx\n", base, size);
1114 lmb_reserve(base, size); 1134 lmb_reserve(base, size);
1115 } 1135 }
1116 1136
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index e381f2fc121c..d963a12ec640 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -137,8 +137,8 @@ struct prom_t {
137}; 137};
138 138
139struct mem_map_entry { 139struct mem_map_entry {
140 unsigned long base; 140 u64 base;
141 unsigned long size; 141 u64 size;
142}; 142};
143 143
144typedef u32 cell_t; 144typedef u32 cell_t;
@@ -897,9 +897,9 @@ static unsigned long __init prom_next_cell(int s, cell_t **cellp)
897 * If problems seem to show up, it would be a good start to track 897 * If problems seem to show up, it would be a good start to track
898 * them down. 898 * them down.
899 */ 899 */
900static void reserve_mem(unsigned long base, unsigned long size) 900static void reserve_mem(u64 base, u64 size)
901{ 901{
902 unsigned long top = base + size; 902 u64 top = base + size;
903 unsigned long cnt = RELOC(mem_reserve_cnt); 903 unsigned long cnt = RELOC(mem_reserve_cnt);
904 904
905 if (size == 0) 905 if (size == 0)
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index d3f0b6d452fb..177bba78fb0b 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -497,6 +497,15 @@ static long restore_user_regs(struct pt_regs *regs,
497 if (err) 497 if (err)
498 return 1; 498 return 1;
499 499
500 /*
501 * Do this before updating the thread state in
502 * current->thread.fpr/vr/evr. That way, if we get preempted
503 * and another task grabs the FPU/Altivec/SPE, it won't be
504 * tempted to save the current CPU state into the thread_struct
505 * and corrupt what we are writing there.
506 */
507 discard_lazy_cpu_state();
508
500 /* force the process to reload the FP registers from 509 /* force the process to reload the FP registers from
501 current->thread when it next does FP instructions */ 510 current->thread when it next does FP instructions */
502 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); 511 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
@@ -538,18 +547,6 @@ static long restore_user_regs(struct pt_regs *regs,
538 return 1; 547 return 1;
539#endif /* CONFIG_SPE */ 548#endif /* CONFIG_SPE */
540 549
541#ifndef CONFIG_SMP
542 preempt_disable();
543 if (last_task_used_math == current)
544 last_task_used_math = NULL;
545 if (last_task_used_altivec == current)
546 last_task_used_altivec = NULL;
547#ifdef CONFIG_SPE
548 if (last_task_used_spe == current)
549 last_task_used_spe = NULL;
550#endif
551 preempt_enable();
552#endif
553 return 0; 550 return 0;
554} 551}
555 552
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 5462bef898f6..7b9d999e2115 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -207,10 +207,20 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
207 207
208 if (!sig) 208 if (!sig)
209 regs->gpr[13] = save_r13; 209 regs->gpr[13] = save_r13;
210 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
211 if (set != NULL) 210 if (set != NULL)
212 err |= __get_user(set->sig[0], &sc->oldmask); 211 err |= __get_user(set->sig[0], &sc->oldmask);
213 212
213 /*
214 * Do this before updating the thread state in
215 * current->thread.fpr/vr. That way, if we get preempted
216 * and another task grabs the FPU/Altivec, it won't be
217 * tempted to save the current CPU state into the thread_struct
218 * and corrupt what we are writing there.
219 */
220 discard_lazy_cpu_state();
221
222 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
223
214#ifdef CONFIG_ALTIVEC 224#ifdef CONFIG_ALTIVEC
215 err |= __get_user(v_regs, &sc->v_regs); 225 err |= __get_user(v_regs, &sc->v_regs);
216 err |= __get_user(msr, &sc->gp_regs[PT_MSR]); 226 err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
@@ -229,14 +239,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
229 current->thread.vrsave = 0; 239 current->thread.vrsave = 0;
230#endif /* CONFIG_ALTIVEC */ 240#endif /* CONFIG_ALTIVEC */
231 241
232#ifndef CONFIG_SMP
233 preempt_disable();
234 if (last_task_used_math == current)
235 last_task_used_math = NULL;
236 if (last_task_used_altivec == current)
237 last_task_used_altivec = NULL;
238 preempt_enable();
239#endif
240 /* Force reload of FP/VEC */ 242 /* Force reload of FP/VEC */
241 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); 243 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
242 244
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 85152544c153..e0e051c675dd 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -142,7 +142,7 @@ static void cbe_idle(void)
142 } 142 }
143} 143}
144 144
145int cbe_system_reset_exception(struct pt_regs *regs) 145static int cbe_system_reset_exception(struct pt_regs *regs)
146{ 146{
147 switch (regs->msr & SRR1_WAKEMASK) { 147 switch (regs->msr & SRR1_WAKEMASK) {
148 case SRR1_WAKEEE: 148 case SRR1_WAKEEE:
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 18e25e65c04b..b33a4443f5a9 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -57,7 +57,7 @@
57#define DBG(fmt...) 57#define DBG(fmt...)
58#endif 58#endif
59 59
60void cell_show_cpuinfo(struct seq_file *m) 60static void cell_show_cpuinfo(struct seq_file *m)
61{ 61{
62 struct device_node *root; 62 struct device_node *root;
63 const char *model = ""; 63 const char *model = "";
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index d549aa7ebea6..e6565a949ddc 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -29,7 +29,9 @@
29 * value of the spu_status register after the SPU has stopped. 29 * value of the spu_status register after the SPU has stopped.
30 * 30 *
31 */ 31 */
32long do_spu_run(struct file *filp, __u32 __user *unpc, __u32 __user *ustatus) 32static long do_spu_run(struct file *filp,
33 __u32 __user *unpc,
34 __u32 __user *ustatus)
33{ 35{
34 long ret; 36 long ret;
35 struct spufs_inode_info *i; 37 struct spufs_inode_info *i;
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 127b465308be..ce8c0b943fa0 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,8 +1,8 @@
1EXTRA_CFLAGS += -mno-minimal-toc 1EXTRA_CFLAGS += -mno-minimal-toc
2 2
3obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ 3obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \
4 hvcall.o proc.o htab.o iommu.o misc.o 4 hvcall.o proc.o htab.o iommu.o misc.o irq.o
5obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o 5obj-$(CONFIG_PCI) += pci.o vpdinfo.o
6obj-$(CONFIG_IBMVIO) += vio.o 6obj-$(CONFIG_IBMVIO) += vio.o
7obj-$(CONFIG_SMP) += smp.o 7obj-$(CONFIG_SMP) += smp.o
8obj-$(CONFIG_VIOPATH) += viopath.o 8obj-$(CONFIG_VIOPATH) += viopath.o
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 2b54eeb2c899..bea0b703f409 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -34,6 +34,8 @@
34#include <asm/pci-bridge.h> 34#include <asm/pci-bridge.h>
35#include <asm/iseries/hv_call_xm.h> 35#include <asm/iseries/hv_call_xm.h>
36 36
37#include "iommu.h"
38
37extern struct list_head iSeries_Global_Device_List; 39extern struct list_head iSeries_Global_Device_List;
38 40
39 41
diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h
new file mode 100644
index 000000000000..cb5658fbe657
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/iommu.h
@@ -0,0 +1,35 @@
1#ifndef _PLATFORMS_ISERIES_IOMMU_H
2#define _PLATFORMS_ISERIES_IOMMU_H
3
4/*
5 * Copyright (C) 2005 Stephen Rothwell, IBM Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the:
19 * Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330,
21 * Boston, MA 02111-1307 USA
22 */
23
24struct device_node;
25struct iommu_table;
26
27/* Creates table for an individual device node */
28extern void iommu_devnode_init_iSeries(struct device_node *dn);
29
30/* Get table parameters from HV */
31extern void iommu_table_getparms_iSeries(unsigned long busno,
32 unsigned char slotno, unsigned char virtbus,
33 struct iommu_table *tbl);
34
35#endif /* _PLATFORMS_ISERIES_IOMMU_H */
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 42e978e4897a..83442ea77476 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -48,6 +48,8 @@
48extern void iSeries_smp_message_recv(struct pt_regs *); 48extern void iSeries_smp_message_recv(struct pt_regs *);
49#endif 49#endif
50 50
51#ifdef CONFIG_PCI
52
51enum pci_event_type { 53enum pci_event_type {
52 pe_bus_created = 0, /* PHB has been created */ 54 pe_bus_created = 0, /* PHB has been created */
53 pe_bus_error = 1, /* PHB has failed */ 55 pe_bus_error = 1, /* PHB has failed */
@@ -147,20 +149,11 @@ static void int_received(struct pci_event *event, struct pt_regs *regs)
147static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs) 149static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs)
148{ 150{
149 if (event && (event->xType == HvLpEvent_Type_PciIo)) { 151 if (event && (event->xType == HvLpEvent_Type_PciIo)) {
150 switch (event->xFlags.xFunction) { 152 if (hvlpevent_is_int(event))
151 case HvLpEvent_Function_Int:
152 int_received((struct pci_event *)event, regs); 153 int_received((struct pci_event *)event, regs);
153 break; 154 else
154 case HvLpEvent_Function_Ack:
155 printk(KERN_ERR 155 printk(KERN_ERR
156 "pci_event_handler: unexpected ack received\n"); 156 "pci_event_handler: unexpected ack received\n");
157 break;
158 default:
159 printk(KERN_ERR
160 "pci_event_handler: unexpected event function %d\n",
161 (int)event->xFlags.xFunction);
162 break;
163 }
164 } else if (event) 157 } else if (event)
165 printk(KERN_ERR 158 printk(KERN_ERR
166 "pci_event_handler: Unrecognized PCI event type 0x%x\n", 159 "pci_event_handler: Unrecognized PCI event type 0x%x\n",
@@ -334,6 +327,8 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
334 return virtirq; 327 return virtirq;
335} 328}
336 329
330#endif /* CONFIG_PCI */
331
337/* 332/*
338 * Get the next pending IRQ. 333 * Get the next pending IRQ.
339 */ 334 */
@@ -353,6 +348,7 @@ int iSeries_get_irq(struct pt_regs *regs)
353 if (hvlpevent_is_pending()) 348 if (hvlpevent_is_pending())
354 process_hvlpevents(regs); 349 process_hvlpevents(regs);
355 350
351#ifdef CONFIG_PCI
356 if (num_pending_irqs) { 352 if (num_pending_irqs) {
357 spin_lock(&pending_irqs_lock); 353 spin_lock(&pending_irqs_lock);
358 for (irq = 0; irq < NR_IRQS; irq++) { 354 for (irq = 0; irq < NR_IRQS; irq++) {
@@ -366,6 +362,7 @@ int iSeries_get_irq(struct pt_regs *regs)
366 if (irq >= NR_IRQS) 362 if (irq >= NR_IRQS)
367 irq = -2; 363 irq = -2;
368 } 364 }
365#endif
369 366
370 return irq; 367 return irq;
371} 368}
diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c
index ea72385aaf0a..438e2dba63b5 100644
--- a/arch/powerpc/platforms/iseries/lpardata.c
+++ b/arch/powerpc/platforms/iseries/lpardata.c
@@ -93,10 +93,7 @@ struct ItLpNaca itLpNaca = {
93 .xPirEnvironMode = 0, /* Piranha stuff */ 93 .xPirEnvironMode = 0, /* Piranha stuff */
94 .xPirConsoleMode = 0, 94 .xPirConsoleMode = 0,
95 .xPirDasdMode = 0, 95 .xPirDasdMode = 0,
96 .xLparInstalled = 0, 96 .flags = 0,
97 .xSysPartitioned = 0,
98 .xHwSyncedTBs = 0,
99 .xIntProcUtilHmt = 0,
100 .xSpVpdFormat = 0, 97 .xSpVpdFormat = 0,
101 .xIntProcRatio = 0, 98 .xIntProcRatio = 0,
102 .xPlicVrmIndex = 0, /* VRM index of PLIC */ 99 .xPlicVrmIndex = 0, /* VRM index of PLIC */
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index e9fb98bf895f..0b885300d1d1 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -53,7 +53,7 @@ static struct HvLpEvent * get_next_hvlpevent(void)
53 struct HvLpEvent * event; 53 struct HvLpEvent * event;
54 event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; 54 event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
55 55
56 if (event->xFlags.xValid) { 56 if (hvlpevent_is_valid(event)) {
57 /* rmb() needed only for weakly consistent machines (regatta) */ 57 /* rmb() needed only for weakly consistent machines (regatta) */
58 rmb(); 58 rmb();
59 /* Set pointer to next potential event */ 59 /* Set pointer to next potential event */
@@ -84,7 +84,7 @@ int hvlpevent_is_pending(void)
84 84
85 next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; 85 next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
86 86
87 return next_event->xFlags.xValid | 87 return hvlpevent_is_valid(next_event) ||
88 hvlpevent_queue.xPlicOverflowIntPending; 88 hvlpevent_queue.xPlicOverflowIntPending;
89} 89}
90 90
@@ -101,18 +101,18 @@ static void hvlpevent_clear_valid(struct HvLpEvent * event)
101 switch (extra) { 101 switch (extra) {
102 case 3: 102 case 3:
103 tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign); 103 tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign);
104 tmp->xFlags.xValid = 0; 104 hvlpevent_invalidate(tmp);
105 case 2: 105 case 2:
106 tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign); 106 tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign);
107 tmp->xFlags.xValid = 0; 107 hvlpevent_invalidate(tmp);
108 case 1: 108 case 1:
109 tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign); 109 tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign);
110 tmp->xFlags.xValid = 0; 110 hvlpevent_invalidate(tmp);
111 } 111 }
112 112
113 mb(); 113 mb();
114 114
115 event->xFlags.xValid = 0; 115 hvlpevent_invalidate(event);
116} 116}
117 117
118void process_hvlpevents(struct pt_regs *regs) 118void process_hvlpevents(struct pt_regs *regs)
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 49e7e4b85847..a41d8b78c0cd 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -251,10 +251,7 @@ static struct pending_event *new_pending_event(void)
251 } 251 }
252 memset(ev, 0, sizeof(struct pending_event)); 252 memset(ev, 0, sizeof(struct pending_event));
253 hev = &ev->event.hp_lp_event; 253 hev = &ev->event.hp_lp_event;
254 hev->xFlags.xValid = 1; 254 hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK | HV_LP_EVENT_INT;
255 hev->xFlags.xAckType = HvLpEvent_AckType_ImmediateAck;
256 hev->xFlags.xAckInd = HvLpEvent_AckInd_DoAck;
257 hev->xFlags.xFunction = HvLpEvent_Function_Int;
258 hev->xType = HvLpEvent_Type_MachineFac; 255 hev->xType = HvLpEvent_Type_MachineFac;
259 hev->xSourceLp = HvLpConfig_getLpIndex(); 256 hev->xSourceLp = HvLpConfig_getLpIndex();
260 hev->xTargetLp = primary_lp; 257 hev->xTargetLp = primary_lp;
@@ -518,17 +515,10 @@ static void handle_ack(struct io_mf_lp_event *event)
518static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs) 515static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs)
519{ 516{
520 if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) { 517 if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) {
521 switch(event->xFlags.xFunction) { 518 if (hvlpevent_is_ack(event))
522 case HvLpEvent_Function_Ack:
523 handle_ack((struct io_mf_lp_event *)event); 519 handle_ack((struct io_mf_lp_event *)event);
524 break; 520 else
525 case HvLpEvent_Function_Int:
526 handle_int((struct io_mf_lp_event *)event); 521 handle_int((struct io_mf_lp_event *)event);
527 break;
528 default:
529 printk(KERN_ERR "mf.c: non ack/int event received\n");
530 break;
531 }
532 } else 522 } else
533 printk(KERN_ERR "mf.c: alien event received\n"); 523 printk(KERN_ERR "mf.c: alien event received\n");
534} 524}
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index dafc518fbb83..a19833b880e4 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -43,6 +43,7 @@
43#include "irq.h" 43#include "irq.h"
44#include "pci.h" 44#include "pci.h"
45#include "call_pci.h" 45#include "call_pci.h"
46#include "iommu.h"
46 47
47extern unsigned long io_page_mask; 48extern unsigned long io_page_mask;
48 49
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index 384360ee06ec..ad36ab0639f0 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -22,6 +22,8 @@
22#include <asm/iseries/hv_lp_config.h> 22#include <asm/iseries/hv_lp_config.h>
23#include <asm/iseries/hv_call_xm.h> 23#include <asm/iseries/hv_call_xm.h>
24 24
25#include "iommu.h"
26
25struct device *iSeries_vio_dev = &vio_bus_device.dev; 27struct device *iSeries_vio_dev = &vio_bus_device.dev;
26EXPORT_SYMBOL(iSeries_vio_dev); 28EXPORT_SYMBOL(iSeries_vio_dev);
27 29
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 842672695598..622a30149b48 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -270,7 +270,7 @@ static void handleMonitorEvent(struct HvLpEvent *event)
270 * First see if this is just a normal monitor message from the 270 * First see if this is just a normal monitor message from the
271 * other partition 271 * other partition
272 */ 272 */
273 if (event->xFlags.xFunction == HvLpEvent_Function_Int) { 273 if (hvlpevent_is_int(event)) {
274 remoteLp = event->xSourceLp; 274 remoteLp = event->xSourceLp;
275 if (!viopathStatus[remoteLp].isActive) 275 if (!viopathStatus[remoteLp].isActive)
276 sendMonMsg(remoteLp); 276 sendMonMsg(remoteLp);
@@ -331,13 +331,12 @@ static void handleConfig(struct HvLpEvent *event)
331{ 331{
332 if (!event) 332 if (!event)
333 return; 333 return;
334 if (event->xFlags.xFunction == HvLpEvent_Function_Int) { 334 if (hvlpevent_is_int(event)) {
335 printk(VIOPATH_KERN_WARN 335 printk(VIOPATH_KERN_WARN
336 "unexpected config request from partition %d", 336 "unexpected config request from partition %d",
337 event->xSourceLp); 337 event->xSourceLp);
338 338
339 if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && 339 if (hvlpevent_need_ack(event)) {
340 (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
341 event->xRc = HvLpEvent_Rc_InvalidSubtype; 340 event->xRc = HvLpEvent_Rc_InvalidSubtype;
342 HvCallEvent_ackLpEvent(event); 341 HvCallEvent_ackLpEvent(event);
343 } 342 }
@@ -377,7 +376,7 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
377 int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK) 376 int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK)
378 >> VIOMAJOR_SUBTYPE_SHIFT; 377 >> VIOMAJOR_SUBTYPE_SHIFT;
379 378
380 if (event->xFlags.xFunction == HvLpEvent_Function_Int) { 379 if (hvlpevent_is_int(event)) {
381 remoteLp = event->xSourceLp; 380 remoteLp = event->xSourceLp;
382 /* 381 /*
383 * The isActive is checked because if the hosting partition 382 * The isActive is checked because if the hosting partition
@@ -436,8 +435,7 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
436 "unexpected virtual io event subtype %d from partition %d\n", 435 "unexpected virtual io event subtype %d from partition %d\n",
437 event->xSubtype, remoteLp); 436 event->xSubtype, remoteLp);
438 /* No handler. Ack if necessary */ 437 /* No handler. Ack if necessary */
439 if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && 438 if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
440 (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
441 event->xRc = HvLpEvent_Rc_InvalidSubtype; 439 event->xRc = HvLpEvent_Rc_InvalidSubtype;
442 HvCallEvent_ackLpEvent(event); 440 HvCallEvent_ackLpEvent(event);
443 } 441 }
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 3b1a9d4fcbc6..89c4c3636161 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -278,7 +278,7 @@ static void __init l2cr_init(void)
278} 278}
279#endif 279#endif
280 280
281void __init pmac_setup_arch(void) 281static void __init pmac_setup_arch(void)
282{ 282{
283 struct device_node *cpu, *ic; 283 struct device_node *cpu, *ic;
284 int *fp; 284 int *fp;
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 17cea7f2afd3..83578313ee7e 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -208,10 +208,11 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
208{ 208{
209 while (dn) { 209 while (dn) {
210 if (PCI_DN(dn)) { 210 if (PCI_DN(dn)) {
211 PCI_DN(dn)->eeh_mode |= mode_flag;
212
213 /* Mark the pci device driver too */ 211 /* Mark the pci device driver too */
214 struct pci_dev *dev = PCI_DN(dn)->pcidev; 212 struct pci_dev *dev = PCI_DN(dn)->pcidev;
213
214 PCI_DN(dn)->eeh_mode |= mode_flag;
215
215 if (dev && dev->driver) 216 if (dev && dev->driver)
216 dev->error_state = pci_channel_io_frozen; 217 dev->error_state = pci_channel_io_frozen;
217 218
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c
index 4d584172055a..22bfb5c89db9 100644
--- a/arch/powerpc/platforms/pseries/hvcserver.c
+++ b/arch/powerpc/platforms/pseries/hvcserver.c
@@ -40,7 +40,7 @@ MODULE_VERSION(HVCS_ARCH_VERSION);
40 * functions aren't performance sensitive, so this conversion isn't an 40 * functions aren't performance sensitive, so this conversion isn't an
41 * issue. 41 * issue.
42 */ 42 */
43int hvcs_convert(long to_convert) 43static int hvcs_convert(long to_convert)
44{ 44{
45 switch (to_convert) { 45 switch (to_convert) {
46 case H_Success: 46 case H_Success:
@@ -91,7 +91,7 @@ int hvcs_free_partner_info(struct list_head *head)
91EXPORT_SYMBOL(hvcs_free_partner_info); 91EXPORT_SYMBOL(hvcs_free_partner_info);
92 92
93/* Helper function for hvcs_get_partner_info */ 93/* Helper function for hvcs_get_partner_info */
94int hvcs_next_partner(uint32_t unit_address, 94static int hvcs_next_partner(uint32_t unit_address,
95 unsigned long last_p_partition_ID, 95 unsigned long last_p_partition_ID,
96 unsigned long last_p_unit_address, unsigned long *pi_buff) 96 unsigned long last_p_unit_address, unsigned long *pi_buff)
97 97
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 169f9148789c..48cfbfc43f99 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -51,8 +51,6 @@
51 51
52#define DBG(fmt...) 52#define DBG(fmt...)
53 53
54extern int is_python(struct device_node *);
55
56static void tce_build_pSeries(struct iommu_table *tbl, long index, 54static void tce_build_pSeries(struct iommu_table *tbl, long index,
57 long npages, unsigned long uaddr, 55 long npages, unsigned long uaddr,
58 enum dma_data_direction direction) 56 enum dma_data_direction direction)
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 2edc947f7c44..50643496eb63 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -192,7 +192,7 @@ struct file_operations scanlog_fops = {
192 .release = scanlog_release, 192 .release = scanlog_release,
193}; 193};
194 194
195int __init scanlog_init(void) 195static int __init scanlog_init(void)
196{ 196{
197 struct proc_dir_entry *ent; 197 struct proc_dir_entry *ent;
198 198
@@ -222,7 +222,7 @@ int __init scanlog_init(void)
222 return 0; 222 return 0;
223} 223}
224 224
225void __exit scanlog_cleanup(void) 225static void __exit scanlog_cleanup(void)
226{ 226{
227 if (proc_ppc64_scan_log_dump) { 227 if (proc_ppc64_scan_log_dump) {
228 kfree(proc_ppc64_scan_log_dump->data); 228 kfree(proc_ppc64_scan_log_dump->data);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 8903cf63236a..68b7f086d63d 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -86,7 +86,7 @@ static void pseries_dedicated_idle(void);
86 86
87struct mpic *pSeries_mpic; 87struct mpic *pSeries_mpic;
88 88
89void pSeries_show_cpuinfo(struct seq_file *m) 89static void pSeries_show_cpuinfo(struct seq_file *m)
90{ 90{
91 struct device_node *root; 91 struct device_node *root;
92 const char *model = ""; 92 const char *model = "";
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 2f543cea9787..8e6b1ed1396e 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -93,7 +93,7 @@ static int query_cpu_stopped(unsigned int pcpu)
93 return cpu_status; 93 return cpu_status;
94} 94}
95 95
96int pSeries_cpu_disable(void) 96static int pSeries_cpu_disable(void)
97{ 97{
98 int cpu = smp_processor_id(); 98 int cpu = smp_processor_id();
99 99
@@ -109,7 +109,7 @@ int pSeries_cpu_disable(void)
109 return 0; 109 return 0;
110} 110}
111 111
112void pSeries_cpu_die(unsigned int cpu) 112static void pSeries_cpu_die(unsigned int cpu)
113{ 113{
114 int tries; 114 int tries;
115 int cpu_status; 115 int cpu_status;
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 0c0cfa32eb58..fd823c7c9ac8 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -381,7 +381,7 @@ int xics_get_irq(struct pt_regs *regs)
381 381
382#ifdef CONFIG_SMP 382#ifdef CONFIG_SMP
383 383
384irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) 384static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
385{ 385{
386 int cpu = smp_processor_id(); 386 int cpu = smp_processor_id();
387 387
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index e00b46b9514e..977de9db8754 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -139,7 +139,6 @@ static void dart_build(struct iommu_table *tbl, long index,
139 139
140 *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); 140 *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
141 141
142 rpn++;
143 uaddr += DART_PAGE_SIZE; 142 uaddr += DART_PAGE_SIZE;
144 } 143 }
145 144
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 22612ed5379c..7d02fa2a8990 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -311,7 +311,7 @@ static void release_output_lock(void)
311} 311}
312#endif 312#endif
313 313
314int xmon_core(struct pt_regs *regs, int fromipi) 314static int xmon_core(struct pt_regs *regs, int fromipi)
315{ 315{
316 int cmd = 0; 316 int cmd = 0;
317 unsigned long msr; 317 unsigned long msr;
@@ -528,7 +528,7 @@ xmon_irq(int irq, void *d, struct pt_regs *regs)
528 return IRQ_HANDLED; 528 return IRQ_HANDLED;
529} 529}
530 530
531int xmon_bpt(struct pt_regs *regs) 531static int xmon_bpt(struct pt_regs *regs)
532{ 532{
533 struct bpt *bp; 533 struct bpt *bp;
534 unsigned long offset; 534 unsigned long offset;
@@ -554,7 +554,7 @@ int xmon_bpt(struct pt_regs *regs)
554 return 1; 554 return 1;
555} 555}
556 556
557int xmon_sstep(struct pt_regs *regs) 557static int xmon_sstep(struct pt_regs *regs)
558{ 558{
559 if (user_mode(regs)) 559 if (user_mode(regs))
560 return 0; 560 return 0;
@@ -562,7 +562,7 @@ int xmon_sstep(struct pt_regs *regs)
562 return 1; 562 return 1;
563} 563}
564 564
565int xmon_dabr_match(struct pt_regs *regs) 565static int xmon_dabr_match(struct pt_regs *regs)
566{ 566{
567 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) 567 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
568 return 0; 568 return 0;
@@ -572,7 +572,7 @@ int xmon_dabr_match(struct pt_regs *regs)
572 return 1; 572 return 1;
573} 573}
574 574
575int xmon_iabr_match(struct pt_regs *regs) 575static int xmon_iabr_match(struct pt_regs *regs)
576{ 576{
577 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF)) 577 if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
578 return 0; 578 return 0;
@@ -582,7 +582,7 @@ int xmon_iabr_match(struct pt_regs *regs)
582 return 1; 582 return 1;
583} 583}
584 584
585int xmon_ipi(struct pt_regs *regs) 585static int xmon_ipi(struct pt_regs *regs)
586{ 586{
587#ifdef CONFIG_SMP 587#ifdef CONFIG_SMP
588 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon)) 588 if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
@@ -591,7 +591,7 @@ int xmon_ipi(struct pt_regs *regs)
591 return 0; 591 return 0;
592} 592}
593 593
594int xmon_fault_handler(struct pt_regs *regs) 594static int xmon_fault_handler(struct pt_regs *regs)
595{ 595{
596 struct bpt *bp; 596 struct bpt *bp;
597 unsigned long offset; 597 unsigned long offset;
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index e6c1d615bb86..ca0201300868 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -13,7 +13,6 @@ extra-$(CONFIG_POWER4) += idle_power4.o
13extra-y += vmlinux.lds 13extra-y += vmlinux.lds
14 14
15obj-y := entry.o traps.o idle.o time.o misc.o \ 15obj-y := entry.o traps.o idle.o time.o misc.o \
16 process.o \
17 setup.o \ 16 setup.o \
18 ppc_htab.o 17 ppc_htab.o
19obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o 18obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
deleted file mode 100644
index a76b504299ca..000000000000
--- a/arch/ppc/kernel/process.c
+++ /dev/null
@@ -1,851 +0,0 @@
1/*
2 * arch/ppc/kernel/process.c
3 *
4 * Derived from "arch/i386/kernel/process.c"
5 * Copyright (C) 1995 Linus Torvalds
6 *
7 * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and
8 * Paul Mackerras (paulus@cs.anu.edu.au)
9 *
10 * PowerPC version
11 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 *
18 */
19
20#include <linux/config.h>
21#include <linux/errno.h>
22#include <linux/sched.h>
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/smp.h>
26#include <linux/smp_lock.h>
27#include <linux/stddef.h>
28#include <linux/unistd.h>
29#include <linux/ptrace.h>
30#include <linux/slab.h>
31#include <linux/user.h>
32#include <linux/elf.h>
33#include <linux/init.h>
34#include <linux/prctl.h>
35#include <linux/init_task.h>
36#include <linux/module.h>
37#include <linux/kallsyms.h>
38#include <linux/mqueue.h>
39#include <linux/hardirq.h>
40
41#include <asm/pgtable.h>
42#include <asm/uaccess.h>
43#include <asm/system.h>
44#include <asm/io.h>
45#include <asm/processor.h>
46#include <asm/mmu.h>
47#include <asm/prom.h>
48
49extern unsigned long _get_SP(void);
50
51struct task_struct *last_task_used_math = NULL;
52struct task_struct *last_task_used_altivec = NULL;
53struct task_struct *last_task_used_spe = NULL;
54
55static struct fs_struct init_fs = INIT_FS;
56static struct files_struct init_files = INIT_FILES;
57static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
58static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
59struct mm_struct init_mm = INIT_MM(init_mm);
60EXPORT_SYMBOL(init_mm);
61
62/* this is 8kB-aligned so we can get to the thread_info struct
63 at the base of it from the stack pointer with 1 integer instruction. */
64union thread_union init_thread_union
65 __attribute__((__section__(".data.init_task"))) =
66{ INIT_THREAD_INFO(init_task) };
67
68/* initial task structure */
69struct task_struct init_task = INIT_TASK(init_task);
70EXPORT_SYMBOL(init_task);
71
72/* only used to get secondary processor up */
73struct task_struct *current_set[NR_CPUS] = {&init_task, };
74
75#undef SHOW_TASK_SWITCHES
76#undef CHECK_STACK
77
78#if defined(CHECK_STACK)
79unsigned long
80kernel_stack_top(struct task_struct *tsk)
81{
82 return ((unsigned long)tsk) + sizeof(union task_union);
83}
84
85unsigned long
86task_top(struct task_struct *tsk)
87{
88 return ((unsigned long)tsk) + sizeof(struct thread_info);
89}
90
91/* check to make sure the kernel stack is healthy */
92int check_stack(struct task_struct *tsk)
93{
94 unsigned long stack_top = kernel_stack_top(tsk);
95 unsigned long tsk_top = task_top(tsk);
96 int ret = 0;
97
98#if 0
99 /* check thread magic */
100 if ( tsk->thread.magic != THREAD_MAGIC )
101 {
102 ret |= 1;
103 printk("thread.magic bad: %08x\n", tsk->thread.magic);
104 }
105#endif
106
107 if ( !tsk )
108 printk("check_stack(): tsk bad tsk %p\n",tsk);
109
110 /* check if stored ksp is bad */
111 if ( (tsk->thread.ksp > stack_top) || (tsk->thread.ksp < tsk_top) )
112 {
113 printk("stack out of bounds: %s/%d\n"
114 " tsk_top %08lx ksp %08lx stack_top %08lx\n",
115 tsk->comm,tsk->pid,
116 tsk_top, tsk->thread.ksp, stack_top);
117 ret |= 2;
118 }
119
120 /* check if stack ptr RIGHT NOW is bad */
121 if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) )
122 {
123 printk("current stack ptr out of bounds: %s/%d\n"
124 " tsk_top %08lx sp %08lx stack_top %08lx\n",
125 current->comm,current->pid,
126 tsk_top, _get_SP(), stack_top);
127 ret |= 4;
128 }
129
130#if 0
131 /* check amount of free stack */
132 for ( i = (unsigned long *)task_top(tsk) ; i < kernel_stack_top(tsk) ; i++ )
133 {
134 if ( !i )
135 printk("check_stack(): i = %p\n", i);
136 if ( *i != 0 )
137 {
138 /* only notify if it's less than 900 bytes */
139 if ( (i - (unsigned long *)task_top(tsk)) < 900 )
140 printk("%d bytes free on stack\n",
141 i - task_top(tsk));
142 break;
143 }
144 }
145#endif
146
147 if (ret)
148 {
149 panic("bad kernel stack");
150 }
151 return(ret);
152}
153#endif /* defined(CHECK_STACK) */
154
155/*
156 * Make sure the floating-point register state in the
157 * the thread_struct is up to date for task tsk.
158 */
159void flush_fp_to_thread(struct task_struct *tsk)
160{
161 if (tsk->thread.regs) {
162 /*
163 * We need to disable preemption here because if we didn't,
164 * another process could get scheduled after the regs->msr
165 * test but before we have finished saving the FP registers
166 * to the thread_struct. That process could take over the
167 * FPU, and then when we get scheduled again we would store
168 * bogus values for the remaining FP registers.
169 */
170 preempt_disable();
171 if (tsk->thread.regs->msr & MSR_FP) {
172#ifdef CONFIG_SMP
173 /*
174 * This should only ever be called for current or
175 * for a stopped child process. Since we save away
176 * the FP register state on context switch on SMP,
177 * there is something wrong if a stopped child appears
178 * to still have its FP state in the CPU registers.
179 */
180 BUG_ON(tsk != current);
181#endif
182 giveup_fpu(current);
183 }
184 preempt_enable();
185 }
186}
187
188void enable_kernel_fp(void)
189{
190 WARN_ON(preemptible());
191
192#ifdef CONFIG_SMP
193 if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
194 giveup_fpu(current);
195 else
196 giveup_fpu(NULL); /* just enables FP for kernel */
197#else
198 giveup_fpu(last_task_used_math);
199#endif /* CONFIG_SMP */
200}
201EXPORT_SYMBOL(enable_kernel_fp);
202
203int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
204{
205 preempt_disable();
206 if (tsk->thread.regs && (tsk->thread.regs->msr & MSR_FP))
207 giveup_fpu(tsk);
208 preempt_enable();
209 memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
210 return 1;
211}
212
213#ifdef CONFIG_ALTIVEC
214void enable_kernel_altivec(void)
215{
216 WARN_ON(preemptible());
217
218#ifdef CONFIG_SMP
219 if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
220 giveup_altivec(current);
221 else
222 giveup_altivec(NULL); /* just enable AltiVec for kernel - force */
223#else
224 giveup_altivec(last_task_used_altivec);
225#endif /* __SMP __ */
226}
227EXPORT_SYMBOL(enable_kernel_altivec);
228
229/*
230 * Make sure the VMX/Altivec register state in the
231 * the thread_struct is up to date for task tsk.
232 */
233void flush_altivec_to_thread(struct task_struct *tsk)
234{
235 if (tsk->thread.regs) {
236 preempt_disable();
237 if (tsk->thread.regs->msr & MSR_VEC) {
238#ifdef CONFIG_SMP
239 BUG_ON(tsk != current);
240#endif
241 giveup_altivec(current);
242 }
243 preempt_enable();
244 }
245}
246
247int dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
248{
249 if (regs->msr & MSR_VEC)
250 giveup_altivec(current);
251 memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
252 return 1;
253}
254#endif /* CONFIG_ALTIVEC */
255
256#ifdef CONFIG_SPE
257void
258enable_kernel_spe(void)
259{
260 WARN_ON(preemptible());
261
262#ifdef CONFIG_SMP
263 if (current->thread.regs && (current->thread.regs->msr & MSR_SPE))
264 giveup_spe(current);
265 else
266 giveup_spe(NULL); /* just enable SPE for kernel - force */
267#else
268 giveup_spe(last_task_used_spe);
269#endif /* __SMP __ */
270}
271EXPORT_SYMBOL(enable_kernel_spe);
272
273void flush_spe_to_thread(struct task_struct *tsk)
274{
275 if (tsk->thread.regs) {
276 preempt_disable();
277 if (tsk->thread.regs->msr & MSR_SPE) {
278#ifdef CONFIG_SMP
279 BUG_ON(tsk != current);
280#endif
281 giveup_spe(current);
282 }
283 preempt_enable();
284 }
285}
286
287int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
288{
289 if (regs->msr & MSR_SPE)
290 giveup_spe(current);
291 /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
292 memcpy(evrregs, &current->thread.evr[0], sizeof(u32) * 35);
293 return 1;
294}
295#endif /* CONFIG_SPE */
296
297struct task_struct *__switch_to(struct task_struct *prev,
298 struct task_struct *new)
299{
300 struct thread_struct *new_thread, *old_thread;
301 unsigned long s;
302 struct task_struct *last;
303
304 local_irq_save(s);
305#ifdef CHECK_STACK
306 check_stack(prev);
307 check_stack(new);
308#endif
309
310#ifdef CONFIG_SMP
311 /* avoid complexity of lazy save/restore of fpu
312 * by just saving it every time we switch out if
313 * this task used the fpu during the last quantum.
314 *
315 * If it tries to use the fpu again, it'll trap and
316 * reload its fp regs. So we don't have to do a restore
317 * every switch, just a save.
318 * -- Cort
319 */
320 if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
321 giveup_fpu(prev);
322#ifdef CONFIG_ALTIVEC
323 /*
324 * If the previous thread used altivec in the last quantum
325 * (thus changing altivec regs) then save them.
326 * We used to check the VRSAVE register but not all apps
327 * set it, so we don't rely on it now (and in fact we need
328 * to save & restore VSCR even if VRSAVE == 0). -- paulus
329 *
330 * On SMP we always save/restore altivec regs just to avoid the
331 * complexity of changing processors.
332 * -- Cort
333 */
334 if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)))
335 giveup_altivec(prev);
336#endif /* CONFIG_ALTIVEC */
337#ifdef CONFIG_SPE
338 /*
339 * If the previous thread used spe in the last quantum
340 * (thus changing spe regs) then save them.
341 *
342 * On SMP we always save/restore spe regs just to avoid the
343 * complexity of changing processors.
344 */
345 if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE)))
346 giveup_spe(prev);
347#endif /* CONFIG_SPE */
348#endif /* CONFIG_SMP */
349
350#ifdef CONFIG_ALTIVEC
351 /* Avoid the trap. On smp this this never happens since
352 * we don't set last_task_used_altivec -- Cort
353 */
354 if (new->thread.regs && last_task_used_altivec == new)
355 new->thread.regs->msr |= MSR_VEC;
356#endif
357#ifdef CONFIG_SPE
358 /* Avoid the trap. On smp this this never happens since
359 * we don't set last_task_used_spe
360 */
361 if (new->thread.regs && last_task_used_spe == new)
362 new->thread.regs->msr |= MSR_SPE;
363#endif /* CONFIG_SPE */
364 new_thread = &new->thread;
365 old_thread = &current->thread;
366 last = _switch(old_thread, new_thread);
367 local_irq_restore(s);
368 return last;
369}
370
371void show_regs(struct pt_regs * regs)
372{
373 int i, trap;
374
375 printk("NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n",
376 regs->nip, regs->link, regs->gpr[1], regs, regs->trap,
377 print_tainted());
378 printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
379 regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
380 regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
381 regs->msr&MSR_IR ? 1 : 0,
382 regs->msr&MSR_DR ? 1 : 0);
383 trap = TRAP(regs);
384 if (trap == 0x300 || trap == 0x600)
385 printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr);
386 printk("TASK = %p[%d] '%s' THREAD: %p\n",
387 current, current->pid, current->comm, task_thread_info(current));
388 printk("Last syscall: %ld ", current->thread.last_syscall);
389
390#ifdef CONFIG_SMP
391 printk(" CPU: %d", smp_processor_id());
392#endif /* CONFIG_SMP */
393
394 for (i = 0; i < 32; i++) {
395 long r;
396 if ((i % 8) == 0)
397 printk("\n" KERN_INFO "GPR%02d: ", i);
398 if (__get_user(r, &regs->gpr[i]))
399 break;
400 printk("%08lX ", r);
401 if (i == 12 && !FULL_REGS(regs))
402 break;
403 }
404 printk("\n");
405#ifdef CONFIG_KALLSYMS
406 /*
407 * Lookup NIP late so we have the best change of getting the
408 * above info out without failing
409 */
410 printk("NIP [%08lx] ", regs->nip);
411 print_symbol("%s\n", regs->nip);
412 printk("LR [%08lx] ", regs->link);
413 print_symbol("%s\n", regs->link);
414#endif
415 show_stack(current, (unsigned long *) regs->gpr[1]);
416}
417
418void exit_thread(void)
419{
420 preempt_disable();
421 if (last_task_used_math == current)
422 last_task_used_math = NULL;
423 if (last_task_used_altivec == current)
424 last_task_used_altivec = NULL;
425#ifdef CONFIG_SPE
426 if (last_task_used_spe == current)
427 last_task_used_spe = NULL;
428#endif
429 preempt_enable();
430}
431
432void flush_thread(void)
433{
434 preempt_disable();
435 if (last_task_used_math == current)
436 last_task_used_math = NULL;
437 if (last_task_used_altivec == current)
438 last_task_used_altivec = NULL;
439#ifdef CONFIG_SPE
440 if (last_task_used_spe == current)
441 last_task_used_spe = NULL;
442#endif
443 preempt_enable();
444}
445
446void
447release_thread(struct task_struct *t)
448{
449}
450
451/*
452 * This gets called before we allocate a new thread and copy
453 * the current task into it.
454 */
455void prepare_to_copy(struct task_struct *tsk)
456{
457 struct pt_regs *regs = tsk->thread.regs;
458
459 if (regs == NULL)
460 return;
461 preempt_disable();
462 if (regs->msr & MSR_FP)
463 giveup_fpu(current);
464#ifdef CONFIG_ALTIVEC
465 if (regs->msr & MSR_VEC)
466 giveup_altivec(current);
467#endif /* CONFIG_ALTIVEC */
468#ifdef CONFIG_SPE
469 if (regs->msr & MSR_SPE)
470 giveup_spe(current);
471#endif /* CONFIG_SPE */
472 preempt_enable();
473}
474
475/*
476 * Copy a thread..
477 */
478int
479copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
480 unsigned long unused,
481 struct task_struct *p, struct pt_regs *regs)
482{
483 struct pt_regs *childregs, *kregs;
484 extern void ret_from_fork(void);
485 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
486 unsigned long childframe;
487
488 CHECK_FULL_REGS(regs);
489 /* Copy registers */
490 sp -= sizeof(struct pt_regs);
491 childregs = (struct pt_regs *) sp;
492 *childregs = *regs;
493 if ((childregs->msr & MSR_PR) == 0) {
494 /* for kernel thread, set `current' and stackptr in new task */
495 childregs->gpr[1] = sp + sizeof(struct pt_regs);
496 childregs->gpr[2] = (unsigned long) p;
497 p->thread.regs = NULL; /* no user register state */
498 } else {
499 childregs->gpr[1] = usp;
500 p->thread.regs = childregs;
501 if (clone_flags & CLONE_SETTLS)
502 childregs->gpr[2] = childregs->gpr[6];
503 }
504 childregs->gpr[3] = 0; /* Result from fork() */
505 sp -= STACK_FRAME_OVERHEAD;
506 childframe = sp;
507
508 /*
509 * The way this works is that at some point in the future
510 * some task will call _switch to switch to the new task.
511 * That will pop off the stack frame created below and start
512 * the new task running at ret_from_fork. The new task will
513 * do some house keeping and then return from the fork or clone
514 * system call, using the stack frame created above.
515 */
516 sp -= sizeof(struct pt_regs);
517 kregs = (struct pt_regs *) sp;
518 sp -= STACK_FRAME_OVERHEAD;
519 p->thread.ksp = sp;
520 kregs->nip = (unsigned long)ret_from_fork;
521
522 p->thread.last_syscall = -1;
523
524 return 0;
525}
526
527/*
528 * Set up a thread for executing a new program
529 */
530void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
531{
532 set_fs(USER_DS);
533 memset(regs->gpr, 0, sizeof(regs->gpr));
534 regs->ctr = 0;
535 regs->link = 0;
536 regs->xer = 0;
537 regs->ccr = 0;
538 regs->mq = 0;
539 regs->nip = nip;
540 regs->gpr[1] = sp;
541 regs->msr = MSR_USER;
542 preempt_disable();
543 if (last_task_used_math == current)
544 last_task_used_math = NULL;
545 if (last_task_used_altivec == current)
546 last_task_used_altivec = NULL;
547#ifdef CONFIG_SPE
548 if (last_task_used_spe == current)
549 last_task_used_spe = NULL;
550#endif
551 preempt_enable();
552 memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
553 current->thread.fpscr.val = 0;
554#ifdef CONFIG_ALTIVEC
555 memset(current->thread.vr, 0, sizeof(current->thread.vr));
556 memset(&current->thread.vscr, 0, sizeof(current->thread.vscr));
557 current->thread.vrsave = 0;
558 current->thread.used_vr = 0;
559#endif /* CONFIG_ALTIVEC */
560#ifdef CONFIG_SPE
561 memset(current->thread.evr, 0, sizeof(current->thread.evr));
562 current->thread.acc = 0;
563 current->thread.spefscr = 0;
564 current->thread.used_spe = 0;
565#endif /* CONFIG_SPE */
566}
567
568#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \
569 | PR_FP_EXC_RES | PR_FP_EXC_INV)
570
571int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
572{
573 struct pt_regs *regs = tsk->thread.regs;
574
575 /* This is a bit hairy. If we are an SPE enabled processor
576 * (have embedded fp) we store the IEEE exception enable flags in
577 * fpexc_mode. fpexc_mode is also used for setting FP exception
578 * mode (asyn, precise, disabled) for 'Classic' FP. */
579 if (val & PR_FP_EXC_SW_ENABLE) {
580#ifdef CONFIG_SPE
581 tsk->thread.fpexc_mode = val &
582 (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT);
583#else
584 return -EINVAL;
585#endif
586 } else {
587 /* on a CONFIG_SPE this does not hurt us. The bits that
588 * __pack_fe01 use do not overlap with bits used for
589 * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits
590 * on CONFIG_SPE implementations are reserved so writing to
591 * them does not change anything */
592 if (val > PR_FP_EXC_PRECISE)
593 return -EINVAL;
594 tsk->thread.fpexc_mode = __pack_fe01(val);
595 if (regs != NULL && (regs->msr & MSR_FP) != 0)
596 regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
597 | tsk->thread.fpexc_mode;
598 }
599 return 0;
600}
601
602int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
603{
604 unsigned int val;
605
606 if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
607#ifdef CONFIG_SPE
608 val = tsk->thread.fpexc_mode;
609#else
610 return -EINVAL;
611#endif
612 else
613 val = __unpack_fe01(tsk->thread.fpexc_mode);
614 return put_user(val, (unsigned int __user *) adr);
615}
616
617int sys_clone(unsigned long clone_flags, unsigned long usp,
618 int __user *parent_tidp, void __user *child_threadptr,
619 int __user *child_tidp, int p6,
620 struct pt_regs *regs)
621{
622 CHECK_FULL_REGS(regs);
623 if (usp == 0)
624 usp = regs->gpr[1]; /* stack pointer for child */
625 return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
626}
627
628int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
629 unsigned long p4, unsigned long p5, unsigned long p6,
630 struct pt_regs *regs)
631{
632 CHECK_FULL_REGS(regs);
633 return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
634}
635
636int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
637 unsigned long p4, unsigned long p5, unsigned long p6,
638 struct pt_regs *regs)
639{
640 CHECK_FULL_REGS(regs);
641 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],
642 regs, 0, NULL, NULL);
643}
644
645int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
646 unsigned long a3, unsigned long a4, unsigned long a5,
647 struct pt_regs *regs)
648{
649 int error;
650 char * filename;
651
652 filename = getname((char __user *) a0);
653 error = PTR_ERR(filename);
654 if (IS_ERR(filename))
655 goto out;
656 preempt_disable();
657 if (regs->msr & MSR_FP)
658 giveup_fpu(current);
659#ifdef CONFIG_ALTIVEC
660 if (regs->msr & MSR_VEC)
661 giveup_altivec(current);
662#endif /* CONFIG_ALTIVEC */
663#ifdef CONFIG_SPE
664 if (regs->msr & MSR_SPE)
665 giveup_spe(current);
666#endif /* CONFIG_SPE */
667 preempt_enable();
668 error = do_execve(filename, (char __user *__user *) a1,
669 (char __user *__user *) a2, regs);
670 if (error == 0) {
671 task_lock(current);
672 current->ptrace &= ~PT_DTRACE;
673 task_unlock(current);
674 }
675 putname(filename);
676out:
677 return error;
678}
679
680void dump_stack(void)
681{
682 show_stack(current, NULL);
683}
684
685EXPORT_SYMBOL(dump_stack);
686
687void show_stack(struct task_struct *tsk, unsigned long *stack)
688{
689 unsigned long sp, stack_top, prev_sp, ret;
690 int count = 0;
691 unsigned long next_exc = 0;
692 struct pt_regs *regs;
693 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
694
695 sp = (unsigned long) stack;
696 if (tsk == NULL)
697 tsk = current;
698 if (sp == 0) {
699 if (tsk == current)
700 asm("mr %0,1" : "=r" (sp));
701 else
702 sp = tsk->thread.ksp;
703 }
704
705 prev_sp = (unsigned long) end_of_stack(tsk);
706 stack_top = (unsigned long) task_stack_page(tsk) + THREAD_SIZE;
707 while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) {
708 if (count == 0) {
709 printk("Call trace:");
710#ifdef CONFIG_KALLSYMS
711 printk("\n");
712#endif
713 } else {
714 if (next_exc) {
715 ret = next_exc;
716 next_exc = 0;
717 } else
718 ret = *(unsigned long *)(sp + 4);
719 printk(" [%08lx] ", ret);
720#ifdef CONFIG_KALLSYMS
721 print_symbol("%s", ret);
722 printk("\n");
723#endif
724 if (ret == (unsigned long) &ret_from_except
725 || ret == (unsigned long) &ret_from_except_full
726 || ret == (unsigned long) &ret_from_syscall) {
727 /* sp + 16 points to an exception frame */
728 regs = (struct pt_regs *) (sp + 16);
729 if (sp + 16 + sizeof(*regs) <= stack_top)
730 next_exc = regs->nip;
731 }
732 }
733 ++count;
734 sp = *(unsigned long *)sp;
735 }
736#ifndef CONFIG_KALLSYMS
737 if (count > 0)
738 printk("\n");
739#endif
740}
741
742#if 0
743/*
744 * Low level print for debugging - Cort
745 */
746int __init ll_printk(const char *fmt, ...)
747{
748 va_list args;
749 char buf[256];
750 int i;
751
752 va_start(args, fmt);
753 i=vsprintf(buf,fmt,args);
754 ll_puts(buf);
755 va_end(args);
756 return i;
757}
758
759int lines = 24, cols = 80;
760int orig_x = 0, orig_y = 0;
761
762void puthex(unsigned long val)
763{
764 unsigned char buf[10];
765 int i;
766 for (i = 7; i >= 0; i--)
767 {
768 buf[i] = "0123456789ABCDEF"[val & 0x0F];
769 val >>= 4;
770 }
771 buf[8] = '\0';
772 prom_print(buf);
773}
774
775void __init ll_puts(const char *s)
776{
777 int x,y;
778 char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000;
779 char c;
780 extern int mem_init_done;
781
782 if ( mem_init_done ) /* assume this means we can printk */
783 {
784 printk(s);
785 return;
786 }
787
788#if 0
789 if ( have_of )
790 {
791 prom_print(s);
792 return;
793 }
794#endif
795
796 /*
797 * can't ll_puts on chrp without openfirmware yet.
798 * vidmem just needs to be setup for it.
799 * -- Cort
800 */
801 if ( _machine != _MACH_prep )
802 return;
803 x = orig_x;
804 y = orig_y;
805
806 while ( ( c = *s++ ) != '\0' ) {
807 if ( c == '\n' ) {
808 x = 0;
809 if ( ++y >= lines ) {
810 /*scroll();*/
811 /*y--;*/
812 y = 0;
813 }
814 } else {
815 vidmem [ ( x + cols * y ) * 2 ] = c;
816 if ( ++x >= cols ) {
817 x = 0;
818 if ( ++y >= lines ) {
819 /*scroll();*/
820 /*y--;*/
821 y = 0;
822 }
823 }
824 }
825 }
826
827 orig_x = x;
828 orig_y = y;
829}
830#endif
831
832unsigned long get_wchan(struct task_struct *p)
833{
834 unsigned long ip, sp;
835 unsigned long stack_page = (unsigned long) task_stack_page(p);
836 int count = 0;
837 if (!p || p == current || p->state == TASK_RUNNING)
838 return 0;
839 sp = p->thread.ksp;
840 do {
841 sp = *(unsigned long *)sp;
842 if (sp < stack_page || sp >= stack_page + 8188)
843 return 0;
844 if (count > 0) {
845 ip = *(unsigned long *)(sp + 4);
846 if (!in_sched_functions(ip))
847 return ip;
848 }
849 } while (count++ < 16);
850 return 0;
851}