aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@austin.ibm.com>2005-06-02 13:12:57 -0400
committerDave Kleikamp <shaggy@austin.ibm.com>2005-06-02 13:12:57 -0400
commit7078253c085c037c070ca4e8bc9e9e7f18aa1e84 (patch)
treeeaf56c1a77b0de6ee82e23cee4433b2c4a47e67e /arch
parent259692bd5a2b2c2d351dd90748ba4126bc2a21b9 (diff)
parent1e86d1c648508fd50e6c9960576b87906a7906ad (diff)
Merge with /home/shaggy/git/linus-clean/
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/osf_sys.c7
-rw-r--r--arch/arm/Kconfig20
-rw-r--r--arch/arm/kernel/entry-armv.S14
-rw-r--r--arch/arm/kernel/head.S3
-rw-r--r--arch/arm/kernel/process.c25
-rw-r--r--arch/arm/kernel/sys_arm.c2
-rw-r--r--arch/arm/kernel/traps.c14
-rw-r--r--arch/arm/kernel/vmlinux.lds.S3
-rw-r--r--arch/arm/mach-clps711x/Kconfig3
-rw-r--r--arch/arm/mach-footbridge/Kconfig12
-rw-r--r--arch/arm/mach-imx/Kconfig1
-rw-r--r--arch/arm/mach-s3c2410/clock.c2
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.c6
-rw-r--r--arch/arm/mm/Kconfig23
-rw-r--r--arch/arm/mm/copypage-v4mc.S80
-rw-r--r--arch/arm/mm/copypage-v4mc.c111
-rw-r--r--arch/arm/mm/copypage-v6.c28
-rw-r--r--arch/arm/mm/flush.c37
-rw-r--r--arch/arm/mm/mm-armv.c27
-rw-r--r--arch/h8300/kernel/process.c2
-rw-r--r--arch/i386/Kconfig22
-rw-r--r--arch/i386/Makefile6
-rw-r--r--arch/i386/boot/bootsect.S2
-rw-r--r--arch/i386/boot/video.S18
-rw-r--r--arch/i386/kernel/acpi/boot.c2
-rw-r--r--arch/i386/kernel/cpu/amd.c12
-rw-r--r--arch/i386/kernel/cpu/common.c4
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig14
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Makefile1
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c58
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.c11
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c113
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.h15
-rw-r--r--arch/i386/kernel/cpu/cpufreq/sc520_freq.c186
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c6
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.c6
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-smi.c3
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c2
-rw-r--r--arch/i386/kernel/cpu/mtrr/cyrix.c4
-rw-r--r--arch/i386/kernel/i386_ksyms.c4
-rw-r--r--arch/i386/kernel/kprobes.c7
-rw-r--r--arch/i386/kernel/process.c13
-rw-r--r--arch/i386/kernel/setup.c2
-rw-r--r--arch/i386/kernel/smpboot.c5
-rw-r--r--arch/i386/kernel/timers/common.c6
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c20
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c17
-rw-r--r--arch/i386/mm/ioremap.c10
-rw-r--r--arch/i386/pci/fixup.c2
-rw-r--r--arch/i386/pci/irq.c5
-rw-r--r--arch/ia64/Kconfig4
-rw-r--r--arch/ia64/ia32/ia32_ioctl.c1
-rw-r--r--arch/ia64/ia32/sys_ia32.c2
-rw-r--r--arch/ia64/kernel/entry.S4
-rw-r--r--arch/ia64/kernel/mca.c8
-rw-r--r--arch/ia64/kernel/minstate.h3
-rw-r--r--arch/ia64/kernel/perfmon.c175
-rw-r--r--arch/ia64/kernel/ptrace.c20
-rw-r--r--arch/ia64/kernel/smpboot.c2
-rw-r--r--arch/ia64/kernel/sys_ia64.c7
-rw-r--r--arch/ia64/sn/kernel/setup.c2
-rw-r--r--arch/mips/vr41xx/common/pmu.c55
-rw-r--r--arch/ppc/Kconfig10
-rw-r--r--arch/ppc/boot/images/Makefile3
-rw-r--r--arch/ppc/configs/mpc8555_cds_defconfig117
-rw-r--r--arch/ppc/kernel/head_44x.S15
-rw-r--r--arch/ppc/kernel/head_fsl_booke.S15
-rw-r--r--arch/ppc/kernel/setup.c41
-rw-r--r--arch/ppc/kernel/traps.c7
-rw-r--r--arch/ppc/kernel/vmlinux.lds.S2
-rw-r--r--arch/ppc/lib/string.S7
-rw-r--r--arch/ppc/mm/init.c1
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.c1
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.h7
-rw-r--r--arch/ppc/platforms/85xx/mpc8540_ads.c3
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c143
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.h3
-rw-r--r--arch/ppc/platforms/85xx/sbc8560.c3
-rw-r--r--arch/ppc/platforms/pmac_cpufreq.c36
-rw-r--r--arch/ppc/platforms/pq2ads.h41
-rw-r--r--arch/ppc/syslib/Makefile4
-rw-r--r--arch/ppc/syslib/ipic.c2
-rw-r--r--arch/ppc/syslib/m8260_pci.c193
-rw-r--r--arch/ppc/syslib/m8260_pci.h76
-rw-r--r--arch/ppc/syslib/m8260_pci_erratum9.c10
-rw-r--r--arch/ppc/syslib/m8260_setup.c11
-rw-r--r--arch/ppc/syslib/m82xx_pci.c383
-rw-r--r--arch/ppc/syslib/m82xx_pci.h92
-rw-r--r--arch/ppc/syslib/mpc83xx_devices.c1
-rw-r--r--arch/ppc/syslib/mpc85xx_devices.c1
-rw-r--r--arch/ppc/syslib/open_pic.c6
-rw-r--r--arch/ppc/syslib/ppc83xx_setup.c28
-rw-r--r--arch/ppc/syslib/ppc85xx_setup.c16
-rw-r--r--arch/ppc/syslib/prom_init.c10
-rw-r--r--arch/ppc64/Kconfig5
-rw-r--r--arch/ppc64/Kconfig.debug3
-rw-r--r--arch/ppc64/boot/main.c1
-rw-r--r--arch/ppc64/boot/start.c654
-rw-r--r--arch/ppc64/kernel/mf.c85
-rw-r--r--arch/ppc64/kernel/misc.S2
-rw-r--r--arch/ppc64/kernel/pSeries_reconfig.c8
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c7
-rw-r--r--arch/ppc64/kernel/pci.c2
-rw-r--r--arch/ppc64/kernel/pmac_smp.c28
-rw-r--r--arch/ppc64/kernel/prom.c2
-rw-r--r--arch/ppc64/kernel/prom_init.c154
-rw-r--r--arch/ppc64/kernel/rtc.c39
-rw-r--r--arch/ppc64/kernel/signal.c6
-rw-r--r--arch/ppc64/kernel/time.c3
-rw-r--r--arch/ppc64/kernel/xics.c16
-rw-r--r--arch/ppc64/mm/hash_native.c3
-rw-r--r--arch/ppc64/mm/hash_utils.c11
-rw-r--r--arch/ppc64/mm/imalloc.c5
-rw-r--r--arch/ppc64/mm/init.c3
-rw-r--r--arch/ppc64/mm/stab.c5
-rw-r--r--arch/sparc/kernel/process.c5
-rw-r--r--arch/sparc64/kernel/pci_iommu.c221
-rw-r--r--arch/sparc64/kernel/pci_psycho.c2
-rw-r--r--arch/sparc64/kernel/pci_sabre.c2
-rw-r--r--arch/sparc64/kernel/pci_schizo.c2
-rw-r--r--arch/sparc64/kernel/process.c4
-rw-r--r--arch/sparc64/kernel/sbus.c41
-rw-r--r--arch/sparc64/kernel/setup.c11
-rw-r--r--arch/sparc64/kernel/smp.c3
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c2
-rw-r--r--arch/sparc64/kernel/traps.c19
-rw-r--r--arch/sparc64/mm/init.c2
-rw-r--r--arch/um/Kconfig.debug4
-rw-r--r--arch/um/Kconfig_x86_644
-rw-r--r--arch/um/Makefile80
-rw-r--r--arch/um/Makefile-i3864
-rw-r--r--arch/um/Makefile-x86_644
-rw-r--r--arch/um/drivers/chan_kern.c22
-rw-r--r--arch/um/drivers/line.c41
-rw-r--r--arch/um/drivers/mcast_kern.c4
-rw-r--r--arch/um/drivers/mcast_user.c47
-rw-r--r--arch/um/drivers/random.c16
-rw-r--r--arch/um/drivers/ssl.c1
-rw-r--r--arch/um/drivers/stdio_console.c1
-rw-r--r--arch/um/drivers/ubd_kern.c303
-rw-r--r--arch/um/drivers/xterm_kern.c1
-rw-r--r--arch/um/include/2_5compat.h24
-rw-r--r--arch/um/include/common-offsets.h14
-rw-r--r--arch/um/include/kern_util.h7
-rw-r--r--arch/um/include/os.h1
-rw-r--r--arch/um/include/skas_ptrace.h15
-rw-r--r--arch/um/include/sysdep-i386/checksum.h39
-rw-r--r--arch/um/include/sysdep-i386/faultinfo.h29
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h23
-rw-r--r--arch/um/include/sysdep-i386/sigcontext.h19
-rw-r--r--arch/um/include/sysdep-i386/signal.h2
-rw-r--r--arch/um/include/sysdep-i386/skas_ptrace.h22
-rw-r--r--arch/um/include/sysdep-ia64/skas_ptrace.h22
-rw-r--r--arch/um/include/sysdep-ppc/skas_ptrace.h22
-rw-r--r--arch/um/include/sysdep-x86_64/checksum.h26
-rw-r--r--arch/um/include/sysdep-x86_64/faultinfo.h29
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h78
-rw-r--r--arch/um/include/sysdep-x86_64/sigcontext.h15
-rw-r--r--arch/um/include/sysdep-x86_64/signal.h2
-rw-r--r--arch/um/include/sysdep-x86_64/skas_ptrace.h22
-rw-r--r--arch/um/include/sysrq.h3
-rw-r--r--arch/um/include/user_util.h1
-rw-r--r--arch/um/kernel/Makefile14
-rw-r--r--arch/um/kernel/checksum.c36
-rw-r--r--arch/um/kernel/exec_kern.c1
-rw-r--r--arch/um/kernel/initrd.c (renamed from arch/um/kernel/initrd_kern.c)21
-rw-r--r--arch/um/kernel/initrd_user.c46
-rw-r--r--arch/um/kernel/irq.c1
-rw-r--r--arch/um/kernel/irq_user.c10
-rw-r--r--arch/um/kernel/ksyms.c4
-rw-r--r--arch/um/kernel/main.c40
-rw-r--r--arch/um/kernel/mem.c40
-rw-r--r--arch/um/kernel/process.c2
-rw-r--r--arch/um/kernel/process_kern.c56
-rw-r--r--arch/um/kernel/ptrace.c117
-rw-r--r--arch/um/kernel/sigio_user.c1
-rw-r--r--arch/um/kernel/skas/include/mode_kern-skas.h1
-rw-r--r--arch/um/kernel/skas/include/skas.h3
-rw-r--r--arch/um/kernel/skas/include/uaccess-skas.h4
-rw-r--r--arch/um/kernel/skas/process.c68
-rw-r--r--arch/um/kernel/skas/process_kern.c4
-rw-r--r--arch/um/kernel/skas/trap_user.c24
-rw-r--r--arch/um/kernel/skas/uaccess.c7
-rw-r--r--arch/um/kernel/skas/util/Makefile1
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs-i386.c46
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs-x86_64.c60
-rw-r--r--arch/um/kernel/syscall_kern.c1
-rw-r--r--arch/um/kernel/sysrq.c21
-rw-r--r--arch/um/kernel/time_kern.c18
-rw-r--r--arch/um/kernel/trap_kern.c64
-rw-r--r--arch/um/kernel/trap_user.c13
-rw-r--r--arch/um/kernel/tt/Makefile1
-rw-r--r--arch/um/kernel/tt/include/mode_kern-tt.h1
-rw-r--r--arch/um/kernel/tt/include/uaccess-tt.h4
-rw-r--r--arch/um/kernel/tt/ksyms.c1
-rw-r--r--arch/um/kernel/tt/mem.c8
-rw-r--r--arch/um/kernel/tt/process_kern.c26
-rw-r--r--arch/um/kernel/tt/syscall_user.c4
-rw-r--r--arch/um/kernel/tt/tracer.c8
-rw-r--r--arch/um/kernel/tt/trap_user.c6
-rw-r--r--arch/um/kernel/um_arch.c13
-rw-r--r--arch/um/kernel/uml.lds.S2
-rw-r--r--arch/um/kernel/vmlinux.lds.S6
-rw-r--r--arch/um/os-Linux/process.c5
-rw-r--r--arch/um/os-Linux/signal.c4
-rw-r--r--arch/um/os-Linux/util/Makefile2
-rw-r--r--arch/um/os-Linux/util/mk_user_constants.c10
-rw-r--r--arch/um/scripts/Makefile.rules25
-rw-r--r--arch/um/sys-i386/Makefile13
-rw-r--r--arch/um/sys-i386/checksum.S6
-rw-r--r--arch/um/sys-i386/delay.c26
-rw-r--r--arch/um/sys-i386/kernel-offsets.c25
-rw-r--r--arch/um/sys-i386/ksyms.c8
-rw-r--r--arch/um/sys-i386/ldt.c5
-rw-r--r--arch/um/sys-i386/ptrace.c40
-rw-r--r--arch/um/sys-i386/signal.c17
-rw-r--r--arch/um/sys-i386/sysrq.c80
-rw-r--r--arch/um/sys-i386/user-offsets.c69
-rw-r--r--arch/um/sys-i386/util/Makefile7
-rw-r--r--arch/um/sys-i386/util/mk_sc.c75
-rw-r--r--arch/um/sys-i386/util/mk_thread.c22
-rw-r--r--arch/um/sys-i386/util/mk_thread_kern.c22
-rw-r--r--arch/um/sys-i386/util/mk_thread_user.c30
-rw-r--r--arch/um/sys-ppc/ptrace.c40
-rw-r--r--arch/um/sys-ppc/sysrq.c14
-rw-r--r--arch/um/sys-x86_64/Makefile22
-rw-r--r--arch/um/sys-x86_64/delay.c39
-rw-r--r--arch/um/sys-x86_64/kernel-offsets.c24
-rw-r--r--arch/um/sys-x86_64/ksyms.c19
-rw-r--r--arch/um/sys-x86_64/ptrace.c53
-rw-r--r--arch/um/sys-x86_64/signal.c12
-rw-r--r--arch/um/sys-x86_64/syscalls.c21
-rw-r--r--arch/um/sys-x86_64/sysrq.c11
-rw-r--r--arch/um/sys-x86_64/um_module.c19
-rw-r--r--arch/um/sys-x86_64/user-offsets.c86
-rw-r--r--arch/um/sys-x86_64/util/Makefile6
-rw-r--r--arch/um/sys-x86_64/util/mk_sc.c79
-rw-r--r--arch/um/sys-x86_64/util/mk_thread.c20
-rw-r--r--arch/um/sys-x86_64/util/mk_thread_kern.c21
-rw-r--r--arch/um/sys-x86_64/util/mk_thread_user.c30
-rw-r--r--arch/um/util/Makefile7
-rw-r--r--arch/um/util/mk_constants.c32
-rw-r--r--arch/um/util/mk_constants_kern.c28
-rw-r--r--arch/um/util/mk_constants_user.c28
-rw-r--r--arch/um/util/mk_task.c (renamed from arch/um/util/mk_task_user.c)18
-rw-r--r--arch/um/util/mk_task_kern.c17
-rw-r--r--arch/x86_64/Kconfig17
-rw-r--r--arch/x86_64/boot/bootsect.S4
-rw-r--r--arch/x86_64/defconfig58
-rw-r--r--arch/x86_64/kernel/Makefile1
-rw-r--r--arch/x86_64/kernel/apic.c5
-rw-r--r--arch/x86_64/kernel/entry.S11
-rw-r--r--arch/x86_64/kernel/io_apic.c82
-rw-r--r--arch/x86_64/kernel/kprobes.c7
-rw-r--r--arch/x86_64/kernel/module.c4
-rw-r--r--arch/x86_64/kernel/mpparse.c23
-rw-r--r--arch/x86_64/kernel/nmi.c248
-rw-r--r--arch/x86_64/kernel/pmtimer.c101
-rw-r--r--arch/x86_64/kernel/ptrace.c17
-rw-r--r--arch/x86_64/kernel/setup.c30
-rw-r--r--arch/x86_64/kernel/signal.c5
-rw-r--r--arch/x86_64/kernel/smpboot.c263
-rw-r--r--arch/x86_64/kernel/time.c64
-rw-r--r--arch/x86_64/kernel/traps.c2
-rw-r--r--arch/x86_64/kernel/vsyscall.c5
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c16
-rw-r--r--arch/x86_64/mm/fault.c11
-rw-r--r--arch/x86_64/mm/ioremap.c29
268 files changed, 4448 insertions, 3366 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 64e450dddb49..167fd89f8707 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1150,16 +1150,13 @@ osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remai
1150 if (get_tv32(&tmp, sleep)) 1150 if (get_tv32(&tmp, sleep))
1151 goto fault; 1151 goto fault;
1152 1152
1153 ticks = tmp.tv_usec; 1153 ticks = timeval_to_jiffies(&tmp);
1154 ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
1155 ticks += tmp.tv_sec * HZ;
1156 1154
1157 current->state = TASK_INTERRUPTIBLE; 1155 current->state = TASK_INTERRUPTIBLE;
1158 ticks = schedule_timeout(ticks); 1156 ticks = schedule_timeout(ticks);
1159 1157
1160 if (remain) { 1158 if (remain) {
1161 tmp.tv_sec = ticks / HZ; 1159 jiffies_to_timeval(ticks, &tmp);
1162 tmp.tv_usec = ticks % HZ;
1163 if (put_tv32(remain, &tmp)) 1160 if (put_tv32(remain, &tmp))
1164 goto fault; 1161 goto fault;
1165 } 1162 }
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8bfcb37460fa..bf397a9f8ac2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -85,6 +85,7 @@ choice
85config ARCH_CLPS7500 85config ARCH_CLPS7500
86 bool "Cirrus-CL-PS7500FE" 86 bool "Cirrus-CL-PS7500FE"
87 select TIMER_ACORN 87 select TIMER_ACORN
88 select ISA
88 89
89config ARCH_CLPS711X 90config ARCH_CLPS711X
90 bool "CLPS711x/EP721x-based" 91 bool "CLPS711x/EP721x-based"
@@ -96,6 +97,7 @@ config ARCH_CO285
96 97
97config ARCH_EBSA110 98config ARCH_EBSA110
98 bool "EBSA-110" 99 bool "EBSA-110"
100 select ISA
99 help 101 help
100 This is an evaluation board for the StrongARM processor available 102 This is an evaluation board for the StrongARM processor available
101 from Digital. It has limited hardware on-board, including an onboard 103 from Digital. It has limited hardware on-board, including an onboard
@@ -120,13 +122,16 @@ config ARCH_INTEGRATOR
120 122
121config ARCH_IOP3XX 123config ARCH_IOP3XX
122 bool "IOP3xx-based" 124 bool "IOP3xx-based"
125 select PCI
123 126
124config ARCH_IXP4XX 127config ARCH_IXP4XX
125 bool "IXP4xx-based" 128 bool "IXP4xx-based"
126 select DMABOUNCE 129 select DMABOUNCE
130 select PCI
127 131
128config ARCH_IXP2000 132config ARCH_IXP2000
129 bool "IXP2400/2800-based" 133 bool "IXP2400/2800-based"
134 select PCI
130 135
131config ARCH_L7200 136config ARCH_L7200
132 bool "LinkUp-L7200" 137 bool "LinkUp-L7200"
@@ -155,6 +160,8 @@ config ARCH_RPC
155 160
156config ARCH_SA1100 161config ARCH_SA1100
157 bool "SA1100-based" 162 bool "SA1100-based"
163 select ISA
164 select DISCONTIGMEM
158 165
159config ARCH_S3C2410 166config ARCH_S3C2410
160 bool "Samsung S3C2410" 167 bool "Samsung S3C2410"
@@ -165,6 +172,9 @@ config ARCH_S3C2410
165 172
166config ARCH_SHARK 173config ARCH_SHARK
167 bool "Shark" 174 bool "Shark"
175 select ISA
176 select ISA_DMA
177 select PCI
168 178
169config ARCH_LH7A40X 179config ARCH_LH7A40X
170 bool "Sharp LH7A40X" 180 bool "Sharp LH7A40X"
@@ -252,8 +262,6 @@ config ARM_AMBA
252 262
253config ISA 263config ISA
254 bool 264 bool
255 depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS
256 default y
257 help 265 help
258 Find out whether you have ISA slots on your motherboard. ISA is the 266 Find out whether you have ISA slots on your motherboard. ISA is the
259 name of a bus system, i.e. the way the CPU talks to the other stuff 267 name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -263,8 +271,6 @@ config ISA
263 271
264config ISA_DMA 272config ISA_DMA
265 bool 273 bool
266 depends on FOOTBRIDGE_HOST || ARCH_SHARK
267 default y
268 274
269config ISA_DMA_API 275config ISA_DMA_API
270 bool 276 bool
@@ -272,7 +278,6 @@ config ISA_DMA_API
272 278
273config PCI 279config PCI
274 bool "PCI support" if ARCH_INTEGRATOR_AP 280 bool "PCI support" if ARCH_INTEGRATOR_AP
275 default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_IXP2000
276 help 281 help
277 Find out whether you have a PCI motherboard. PCI is the name of a 282 Find out whether you have a PCI motherboard. PCI is the name of a
278 bus system, i.e. the way the CPU talks to the other stuff inside 283 bus system, i.e. the way the CPU talks to the other stuff inside
@@ -300,7 +305,7 @@ menu "Kernel Features"
300 305
301config SMP 306config SMP
302 bool "Symmetric Multi-Processing (EXPERIMENTAL)" 307 bool "Symmetric Multi-Processing (EXPERIMENTAL)"
303 depends on EXPERIMENTAL && n 308 depends on EXPERIMENTAL #&& n
304 help 309 help
305 This enables support for systems with more than one CPU. If you have 310 This enables support for systems with more than one CPU. If you have
306 a system with only one CPU, like most personal computers, say N. If 311 a system with only one CPU, like most personal computers, say N. If
@@ -340,8 +345,7 @@ config PREEMPT
340 345
341config DISCONTIGMEM 346config DISCONTIGMEM
342 bool 347 bool
343 depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) 348 default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
344 default y
345 help 349 help
346 Say Y to support efficient handling of discontiguous physical memory, 350 Say Y to support efficient handling of discontiguous physical memory,
347 for architectures which are either NUMA (Non-Uniform Memory Access) 351 for architectures which are either NUMA (Non-Uniform Memory Access)
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 080df907f242..4eb36155dc93 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -17,8 +17,8 @@
17 17
18#include <asm/glue.h> 18#include <asm/glue.h>
19#include <asm/vfpmacros.h> 19#include <asm/vfpmacros.h>
20#include <asm/hardware.h> @ should be moved into entry-macro.S 20#include <asm/hardware.h> /* should be moved into entry-macro.S */
21#include <asm/arch/irqs.h> @ should be moved into entry-macro.S 21#include <asm/arch/irqs.h> /* should be moved into entry-macro.S */
22#include <asm/arch/entry-macro.S> 22#include <asm/arch/entry-macro.S>
23 23
24#include "entry-header.S" 24#include "entry-header.S"
@@ -505,9 +505,9 @@ ENTRY(__switch_to)
505 mra r4, r5, acc0 505 mra r4, r5, acc0
506 stmia ip, {r4, r5} 506 stmia ip, {r4, r5}
507#endif 507#endif
508#ifdef CONFIG_HAS_TLS_REG 508#if defined(CONFIG_HAS_TLS_REG)
509 mcr p15, 0, r3, c13, c0, 3 @ set TLS register 509 mcr p15, 0, r3, c13, c0, 3 @ set TLS register
510#else 510#elif !defined(CONFIG_TLS_REG_EMUL)
511 mov r4, #0xffff0fff 511 mov r4, #0xffff0fff
512 str r3, [r4, #-15] @ TLS val at 0xffff0ff0 512 str r3, [r4, #-15] @ TLS val at 0xffff0ff0
513#endif 513#endif
@@ -690,11 +690,7 @@ __kuser_cmpxchg: @ 0xffff0fc0
690 690
691__kuser_get_tls: @ 0xffff0fe0 691__kuser_get_tls: @ 0xffff0fe0
692 692
693#ifndef CONFIG_HAS_TLS_REG 693#if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL)
694
695#ifdef CONFIG_SMP /* sanity check */
696#error "CONFIG_SMP without CONFIG_HAS_TLS_REG is wrong"
697#endif
698 694
699 ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0 695 ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0
700 mov pc, lr 696 mov pc, lr
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 171b3e811c71..4733877296d4 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -19,6 +19,7 @@
19#include <asm/procinfo.h> 19#include <asm/procinfo.h>
20#include <asm/ptrace.h> 20#include <asm/ptrace.h>
21#include <asm/constants.h> 21#include <asm/constants.h>
22#include <asm/thread_info.h>
22#include <asm/system.h> 23#include <asm/system.h>
23 24
24#define PROCINFO_MMUFLAGS 8 25#define PROCINFO_MMUFLAGS 8
@@ -131,7 +132,7 @@ __switch_data:
131 .long processor_id @ r4 132 .long processor_id @ r4
132 .long __machine_arch_type @ r5 133 .long __machine_arch_type @ r5
133 .long cr_alignment @ r6 134 .long cr_alignment @ r6
134 .long init_thread_union+8192 @ sp 135 .long init_thread_union + THREAD_START_SP @ sp
135 136
136/* 137/*
137 * The following fragment of code is executed with the MMU on, and uses 138 * The following fragment of code is executed with the MMU on, and uses
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 26eacd3e5def..8f146a4b4752 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -256,8 +256,6 @@ static unsigned long *thread_info_head;
256static unsigned int nr_thread_info; 256static unsigned int nr_thread_info;
257 257
258#define EXTRA_TASK_STRUCT 4 258#define EXTRA_TASK_STRUCT 4
259#define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
260#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
261 259
262struct thread_info *alloc_thread_info(struct task_struct *task) 260struct thread_info *alloc_thread_info(struct task_struct *task)
263{ 261{
@@ -274,17 +272,16 @@ struct thread_info *alloc_thread_info(struct task_struct *task)
274 } 272 }
275 273
276 if (!thread) 274 if (!thread)
277 thread = ll_alloc_task_struct(); 275 thread = (struct thread_info *)
276 __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
278 277
279#ifdef CONFIG_MAGIC_SYSRQ 278#ifdef CONFIG_DEBUG_STACK_USAGE
280 /* 279 /*
281 * The stack must be cleared if you want SYSRQ-T to 280 * The stack must be cleared if you want SYSRQ-T to
282 * give sensible stack usage information 281 * give sensible stack usage information
283 */ 282 */
284 if (thread) { 283 if (thread)
285 char *p = (char *)thread; 284 memzero(thread, THREAD_SIZE);
286 memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);
287 }
288#endif 285#endif
289 return thread; 286 return thread;
290} 287}
@@ -297,7 +294,7 @@ void free_thread_info(struct thread_info *thread)
297 thread_info_head = p; 294 thread_info_head = p;
298 nr_thread_info += 1; 295 nr_thread_info += 1;
299 } else 296 } else
300 ll_free_task_struct(thread); 297 free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
301} 298}
302 299
303/* 300/*
@@ -350,7 +347,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start,
350 struct thread_info *thread = p->thread_info; 347 struct thread_info *thread = p->thread_info;
351 struct pt_regs *childregs; 348 struct pt_regs *childregs;
352 349
353 childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1; 350 childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_START_SP)) - 1;
354 *childregs = *regs; 351 *childregs = *regs;
355 childregs->ARM_r0 = 0; 352 childregs->ARM_r0 = 0;
356 childregs->ARM_sp = stack_start; 353 childregs->ARM_sp = stack_start;
@@ -447,15 +444,17 @@ EXPORT_SYMBOL(kernel_thread);
447unsigned long get_wchan(struct task_struct *p) 444unsigned long get_wchan(struct task_struct *p)
448{ 445{
449 unsigned long fp, lr; 446 unsigned long fp, lr;
450 unsigned long stack_page; 447 unsigned long stack_start, stack_end;
451 int count = 0; 448 int count = 0;
452 if (!p || p == current || p->state == TASK_RUNNING) 449 if (!p || p == current || p->state == TASK_RUNNING)
453 return 0; 450 return 0;
454 451
455 stack_page = 4096 + (unsigned long)p->thread_info; 452 stack_start = (unsigned long)(p->thread_info + 1);
453 stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE;
454
456 fp = thread_saved_fp(p); 455 fp = thread_saved_fp(p);
457 do { 456 do {
458 if (fp < stack_page || fp > 4092+stack_page) 457 if (fp < stack_start || fp > stack_end)
459 return 0; 458 return 0;
460 lr = pc_pointer (((unsigned long *)fp)[-1]); 459 lr = pc_pointer (((unsigned long *)fp)[-1]);
461 if (!in_sched_functions(lr)) 460 if (!in_sched_functions(lr))
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index ef32577da304..f897ce2ccf0d 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -302,7 +302,7 @@ long execve(const char *filename, char **argv, char **envp)
302 "b ret_to_user" 302 "b ret_to_user"
303 : 303 :
304 : "r" (current_thread_info()), 304 : "r" (current_thread_info()),
305 "Ir" (THREAD_SIZE - 8 - sizeof(regs)), 305 "Ir" (THREAD_START_SP - sizeof(regs)),
306 "r" (&regs), 306 "r" (&regs),
307 "Ir" (sizeof(regs)) 307 "Ir" (sizeof(regs))
308 : "r0", "r1", "r2", "r3", "ip", "memory"); 308 : "r0", "r1", "r2", "r3", "ip", "memory");
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 3a001fe5540b..14df16b983f4 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -218,7 +218,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
218 tsk->comm, tsk->pid, tsk->thread_info + 1); 218 tsk->comm, tsk->pid, tsk->thread_info + 1);
219 219
220 if (!user_mode(regs) || in_interrupt()) { 220 if (!user_mode(regs) || in_interrupt()) {
221 dump_mem("Stack: ", regs->ARM_sp, 8192+(unsigned long)tsk->thread_info); 221 dump_mem("Stack: ", regs->ARM_sp,
222 THREAD_SIZE + (unsigned long)tsk->thread_info);
222 dump_backtrace(regs, tsk); 223 dump_backtrace(regs, tsk);
223 dump_instr(regs); 224 dump_instr(regs);
224 } 225 }
@@ -450,9 +451,9 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
450 451
451 case NR(set_tls): 452 case NR(set_tls):
452 thread->tp_value = regs->ARM_r0; 453 thread->tp_value = regs->ARM_r0;
453#ifdef CONFIG_HAS_TLS_REG 454#if defined(CONFIG_HAS_TLS_REG)
454 asm ("mcr p15, 0, %0, c13, c0, 3" : : "r" (regs->ARM_r0) ); 455 asm ("mcr p15, 0, %0, c13, c0, 3" : : "r" (regs->ARM_r0) );
455#else 456#elif !defined(CONFIG_TLS_REG_EMUL)
456 /* 457 /*
457 * User space must never try to access this directly. 458 * User space must never try to access this directly.
458 * Expect your app to break eventually if you do so. 459 * Expect your app to break eventually if you do so.
@@ -497,11 +498,14 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
497 return 0; 498 return 0;
498} 499}
499 500
500#if defined(CONFIG_CPU_32v6) && !defined(CONFIG_HAS_TLS_REG) 501#ifdef CONFIG_TLS_REG_EMUL
501 502
502/* 503/*
503 * We might be running on an ARMv6+ processor which should have the TLS 504 * We might be running on an ARMv6+ processor which should have the TLS
504 * register, but for some reason we can't use it and have to emulate it. 505 * register but for some reason we can't use it, or maybe an SMP system
506 * using a pre-ARMv6 processor (there are apparently a few prototypes like
507 * that in existence) and therefore access to that register must be
508 * emulated.
505 */ 509 */
506 510
507static int get_tp_trap(struct pt_regs *regs, unsigned int instr) 511static int get_tp_trap(struct pt_regs *regs, unsigned int instr)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index a39c6a42d68a..ad2d66c93a5c 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -5,6 +5,7 @@
5 5
6#include <asm-generic/vmlinux.lds.h> 6#include <asm-generic/vmlinux.lds.h>
7#include <linux/config.h> 7#include <linux/config.h>
8#include <asm/thread_info.h>
8 9
9OUTPUT_ARCH(arm) 10OUTPUT_ARCH(arm)
10ENTRY(stext) 11ENTRY(stext)
@@ -103,7 +104,7 @@ SECTIONS
103 __data_loc = ALIGN(4); /* location in binary */ 104 __data_loc = ALIGN(4); /* location in binary */
104 . = DATAADDR; 105 . = DATAADDR;
105#else 106#else
106 . = ALIGN(8192); 107 . = ALIGN(THREAD_SIZE);
107 __data_loc = .; 108 __data_loc = .;
108#endif 109#endif
109 110
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index f6e676322ca9..45c930ccd064 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -10,6 +10,7 @@ config ARCH_AUTCPU12
10 10
11config ARCH_CDB89712 11config ARCH_CDB89712
12 bool "CDB89712" 12 bool "CDB89712"
13 select ISA
13 help 14 help
14 This is an evaluation board from Cirrus for the CS89712 processor. 15 This is an evaluation board from Cirrus for the CS89712 processor.
15 The board includes 2 serial ports, Ethernet, IRDA, and expansion 16 The board includes 2 serial ports, Ethernet, IRDA, and expansion
@@ -26,6 +27,8 @@ config ARCH_CLEP7312
26 27
27config ARCH_EDB7211 28config ARCH_EDB7211
28 bool "EDB7211" 29 bool "EDB7211"
30 select ISA
31 select DISCONTIGMEM
29 help 32 help
30 Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211 33 Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
31 evaluation board. 34 evaluation board.
diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
index 1090c680b6dd..324d9edeec38 100644
--- a/arch/arm/mach-footbridge/Kconfig
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -5,6 +5,9 @@ menu "Footbridge Implementations"
5config ARCH_CATS 5config ARCH_CATS
6 bool "CATS" 6 bool "CATS"
7 select FOOTBRIDGE_HOST 7 select FOOTBRIDGE_HOST
8 select ISA
9 select ISA_DMA
10 select PCI
8 help 11 help
9 Say Y here if you intend to run this kernel on the CATS. 12 Say Y here if you intend to run this kernel on the CATS.
10 13
@@ -13,6 +16,9 @@ config ARCH_CATS
13config ARCH_PERSONAL_SERVER 16config ARCH_PERSONAL_SERVER
14 bool "Compaq Personal Server" 17 bool "Compaq Personal Server"
15 select FOOTBRIDGE_HOST 18 select FOOTBRIDGE_HOST
19 select ISA
20 select ISA_DMA
21 select PCI
16 ---help--- 22 ---help---
17 Say Y here if you intend to run this kernel on the Compaq 23 Say Y here if you intend to run this kernel on the Compaq
18 Personal Server. 24 Personal Server.
@@ -42,6 +48,9 @@ config ARCH_EBSA285_HOST
42 bool "EBSA285 (host mode)" 48 bool "EBSA285 (host mode)"
43 select ARCH_EBSA285 49 select ARCH_EBSA285
44 select FOOTBRIDGE_HOST 50 select FOOTBRIDGE_HOST
51 select ISA
52 select ISA_DMA
53 select PCI
45 help 54 help
46 Say Y here if you intend to run this kernel on the EBSA285 card 55 Say Y here if you intend to run this kernel on the EBSA285 card
47 in host ("central function") mode. 56 in host ("central function") mode.
@@ -51,6 +60,9 @@ config ARCH_EBSA285_HOST
51config ARCH_NETWINDER 60config ARCH_NETWINDER
52 bool "NetWinder" 61 bool "NetWinder"
53 select FOOTBRIDGE_HOST 62 select FOOTBRIDGE_HOST
63 select ISA
64 select ISA_DMA
65 select PCI
54 help 66 help
55 Say Y here if you intend to run this kernel on the Rebel.COM 67 Say Y here if you intend to run this kernel on the Rebel.COM
56 NetWinder. Information about this machine can be found at: 68 NetWinder. Information about this machine can be found at:
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index ec85813ee5dc..cddd194ac6eb 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -4,6 +4,7 @@ menu "IMX Implementations"
4config ARCH_MX1ADS 4config ARCH_MX1ADS
5 bool "mx1ads" 5 bool "mx1ads"
6 depends on ARCH_IMX 6 depends on ARCH_IMX
7 select ISA
7 help 8 help
8 Say Y here if you are using the Motorola MX1ADS board 9 Say Y here if you are using the Motorola MX1ADS board
9 10
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index e23f534d4e1d..8d986b8401c2 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -478,7 +478,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
478{ 478{
479 unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); 479 unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
480 480
481 s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2; 481 s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate);
482 482
483 printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n", 483 printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
484 print_mhz(s3c2440_clk_upll.rate)); 484 print_mhz(s3c2440_clk_upll.rate));
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
index 9a8cc5ae2255..d4c8281b55f6 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2410/s3c2440.c
@@ -192,9 +192,11 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
192 192
193 iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc)); 193 iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
194 iotable_init(mach_desc, size); 194 iotable_init(mach_desc, size);
195
195 /* rename any peripherals used differing from the s3c2410 */ 196 /* rename any peripherals used differing from the s3c2410 */
196 197
197 s3c_device_i2c.name = "s3c2440-i2c"; 198 s3c_device_i2c.name = "s3c2440-i2c";
199 s3c_device_nand.name = "s3c2440-nand";
198 200
199 /* change irq for watchdog */ 201 /* change irq for watchdog */
200 202
@@ -225,7 +227,7 @@ void __init s3c2440_init_clocks(int xtal)
225 break; 227 break;
226 228
227 case S3C2440_CLKDIVN_HDIVN_2: 229 case S3C2440_CLKDIVN_HDIVN_2:
228 hdiv = 1; 230 hdiv = 2;
229 break; 231 break;
230 232
231 case S3C2440_CLKDIVN_HDIVN_4_8: 233 case S3C2440_CLKDIVN_HDIVN_4_8:
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 27892e34b060..48bac7da8c70 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -410,17 +410,22 @@ config CPU_BPREDICT_DISABLE
410 help 410 help
411 Say Y here to disable branch prediction. If unsure, say N. 411 Say Y here to disable branch prediction. If unsure, say N.
412 412
413config TLS_REG_EMUL
414 bool
415 default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
416 help
417 An SMP system using a pre-ARMv6 processor (there are apparently
418 a few prototypes like that in existence) and therefore access to
419 that required register must be emulated.
420
413config HAS_TLS_REG 421config HAS_TLS_REG
414 bool 422 bool
415 depends on CPU_32v6 && !CPU_32v5 && !CPU_32v4 && !CPU_32v3 423 depends on !TLS_REG_EMUL
416 default y 424 default y if SMP || CPU_32v7
417 help 425 help
418 This selects support for the CP15 thread register. 426 This selects support for the CP15 thread register.
419 It is defined to be available on ARMv6 or later. However 427 It is defined to be available on some ARMv6 processors (including
420 if the kernel is configured to support multiple CPUs including 428 all SMP capable ARMv6's) or later processors. User space may
421 a pre-ARMv6 processors, or if a given ARMv6 processor doesn't 429 assume directly accessing that register and always obtain the
422 implement the thread register for some reason, then access to 430 expected value only on ARMv7 and above.
423 this register from user space must be trapped and emulated.
424 If user space is relying on the __kuser_get_tls code then
425 there should not be any impact.
426 431
diff --git a/arch/arm/mm/copypage-v4mc.S b/arch/arm/mm/copypage-v4mc.S
deleted file mode 100644
index 305af3dab3d8..000000000000
--- a/arch/arm/mm/copypage-v4mc.S
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * linux/arch/arm/lib/copy_page-armv4mc.S
3 *
4 * Copyright (C) 1995-2001 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ASM optimised string functions
11 */
12#include <linux/linkage.h>
13#include <linux/init.h>
14#include <asm/constants.h>
15
16 .text
17 .align 5
18/*
19 * ARMv4 mini-dcache optimised copy_user_page
20 *
21 * We flush the destination cache lines just before we write the data into the
22 * corresponding address. Since the Dcache is read-allocate, this removes the
23 * Dcache aliasing issue. The writes will be forwarded to the write buffer,
24 * and merged as appropriate.
25 *
26 * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
27 * instruction. If your processor does not supply this, you have to write your
28 * own copy_user_page that does the right thing.
29 */
30ENTRY(v4_mc_copy_user_page)
31 stmfd sp!, {r4, lr} @ 2
32 mov r4, r0
33 mov r0, r1
34 bl map_page_minicache
35 mov r1, #PAGE_SZ/64 @ 1
36 ldmia r0!, {r2, r3, ip, lr} @ 4
371: mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line
38 stmia r4!, {r2, r3, ip, lr} @ 4
39 ldmia r0!, {r2, r3, ip, lr} @ 4+1
40 stmia r4!, {r2, r3, ip, lr} @ 4
41 ldmia r0!, {r2, r3, ip, lr} @ 4
42 mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line
43 stmia r4!, {r2, r3, ip, lr} @ 4
44 ldmia r0!, {r2, r3, ip, lr} @ 4
45 subs r1, r1, #1 @ 1
46 stmia r4!, {r2, r3, ip, lr} @ 4
47 ldmneia r0!, {r2, r3, ip, lr} @ 4
48 bne 1b @ 1
49 ldmfd sp!, {r4, pc} @ 3
50
51 .align 5
52/*
53 * ARMv4 optimised clear_user_page
54 *
55 * Same story as above.
56 */
57ENTRY(v4_mc_clear_user_page)
58 str lr, [sp, #-4]!
59 mov r1, #PAGE_SZ/64 @ 1
60 mov r2, #0 @ 1
61 mov r3, #0 @ 1
62 mov ip, #0 @ 1
63 mov lr, #0 @ 1
641: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
65 stmia r0!, {r2, r3, ip, lr} @ 4
66 stmia r0!, {r2, r3, ip, lr} @ 4
67 mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
68 stmia r0!, {r2, r3, ip, lr} @ 4
69 stmia r0!, {r2, r3, ip, lr} @ 4
70 subs r1, r1, #1 @ 1
71 bne 1b @ 1
72 ldr pc, [sp], #4
73
74 __INITDATA
75
76 .type v4_mc_user_fns, #object
77ENTRY(v4_mc_user_fns)
78 .long v4_mc_clear_user_page
79 .long v4_mc_copy_user_page
80 .size v4_mc_user_fns, . - v4_mc_user_fns
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
new file mode 100644
index 000000000000..fc69dccdace1
--- /dev/null
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -0,0 +1,111 @@
1/*
2 * linux/arch/arm/lib/copypage-armv4mc.S
3 *
4 * Copyright (C) 1995-2005 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This handles the mini data cache, as found on SA11x0 and XScale
11 * processors. When we copy a user page page, we map it in such a way
12 * that accesses to this page will not touch the main data cache, but
13 * will be cached in the mini data cache. This prevents us thrashing
14 * the main data cache on page faults.
15 */
16#include <linux/init.h>
17#include <linux/mm.h>
18
19#include <asm/page.h>
20#include <asm/pgtable.h>
21#include <asm/tlbflush.h>
22
23/*
24 * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
25 * specific hacks for copying pages efficiently.
26 */
27#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
28 L_PTE_CACHEABLE)
29
30#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
31
32static DEFINE_SPINLOCK(minicache_lock);
33
34/*
35 * ARMv4 mini-dcache optimised copy_user_page
36 *
37 * We flush the destination cache lines just before we write the data into the
38 * corresponding address. Since the Dcache is read-allocate, this removes the
39 * Dcache aliasing issue. The writes will be forwarded to the write buffer,
40 * and merged as appropriate.
41 *
42 * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
43 * instruction. If your processor does not supply this, you have to write your
44 * own copy_user_page that does the right thing.
45 */
46static void __attribute__((naked))
47mc_copy_user_page(void *from, void *to)
48{
49 asm volatile(
50 "stmfd sp!, {r4, lr} @ 2\n\
51 mov r4, %2 @ 1\n\
52 ldmia %0!, {r2, r3, ip, lr} @ 4\n\
531: mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\
54 stmia %1!, {r2, r3, ip, lr} @ 4\n\
55 ldmia %0!, {r2, r3, ip, lr} @ 4+1\n\
56 stmia %1!, {r2, r3, ip, lr} @ 4\n\
57 ldmia %0!, {r2, r3, ip, lr} @ 4\n\
58 mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\
59 stmia %1!, {r2, r3, ip, lr} @ 4\n\
60 ldmia %0!, {r2, r3, ip, lr} @ 4\n\
61 subs r4, r4, #1 @ 1\n\
62 stmia %1!, {r2, r3, ip, lr} @ 4\n\
63 ldmneia %0!, {r2, r3, ip, lr} @ 4\n\
64 bne 1b @ 1\n\
65 ldmfd sp!, {r4, pc} @ 3"
66 :
67 : "r" (from), "r" (to), "I" (PAGE_SIZE / 64));
68}
69
70void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
71{
72 spin_lock(&minicache_lock);
73
74 set_pte(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
75 flush_tlb_kernel_page(0xffff8000);
76
77 mc_copy_user_page((void *)0xffff8000, kto);
78
79 spin_unlock(&minicache_lock);
80}
81
82/*
83 * ARMv4 optimised clear_user_page
84 */
85void __attribute__((naked))
86v4_mc_clear_user_page(void *kaddr, unsigned long vaddr)
87{
88 asm volatile(
89 "str lr, [sp, #-4]!\n\
90 mov r1, %0 @ 1\n\
91 mov r2, #0 @ 1\n\
92 mov r3, #0 @ 1\n\
93 mov ip, #0 @ 1\n\
94 mov lr, #0 @ 1\n\
951: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
96 stmia r0!, {r2, r3, ip, lr} @ 4\n\
97 stmia r0!, {r2, r3, ip, lr} @ 4\n\
98 mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
99 stmia r0!, {r2, r3, ip, lr} @ 4\n\
100 stmia r0!, {r2, r3, ip, lr} @ 4\n\
101 subs r1, r1, #1 @ 1\n\
102 bne 1b @ 1\n\
103 ldr pc, [sp], #4"
104 :
105 : "I" (PAGE_SIZE / 64));
106}
107
108struct cpu_user_fns v4_mc_user_fns __initdata = {
109 .cpu_clear_user_page = v4_mc_clear_user_page,
110 .cpu_copy_user_page = v4_mc_copy_user_page,
111};
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index 694ac8208858..a8c00236bd3d 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -26,8 +26,8 @@
26#define to_address (0xffffc000) 26#define to_address (0xffffc000)
27#define to_pgprot PAGE_KERNEL 27#define to_pgprot PAGE_KERNEL
28 28
29static pte_t *from_pte; 29#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
30static pte_t *to_pte; 30
31static DEFINE_SPINLOCK(v6_lock); 31static DEFINE_SPINLOCK(v6_lock);
32 32
33#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT) 33#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
@@ -74,8 +74,8 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
74 */ 74 */
75 spin_lock(&v6_lock); 75 spin_lock(&v6_lock);
76 76
77 set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot)); 77 set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
78 set_pte(to_pte + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot)); 78 set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
79 79
80 from = from_address + (offset << PAGE_SHIFT); 80 from = from_address + (offset << PAGE_SHIFT);
81 to = to_address + (offset << PAGE_SHIFT); 81 to = to_address + (offset << PAGE_SHIFT);
@@ -114,7 +114,7 @@ void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
114 */ 114 */
115 spin_lock(&v6_lock); 115 spin_lock(&v6_lock);
116 116
117 set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot)); 117 set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
118 flush_tlb_kernel_page(to); 118 flush_tlb_kernel_page(to);
119 clear_page((void *)to); 119 clear_page((void *)to);
120 120
@@ -129,21 +129,6 @@ struct cpu_user_fns v6_user_fns __initdata = {
129static int __init v6_userpage_init(void) 129static int __init v6_userpage_init(void)
130{ 130{
131 if (cache_is_vipt_aliasing()) { 131 if (cache_is_vipt_aliasing()) {
132 pgd_t *pgd;
133 pmd_t *pmd;
134
135 pgd = pgd_offset_k(from_address);
136 pmd = pmd_alloc(&init_mm, pgd, from_address);
137 if (!pmd)
138 BUG();
139 from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
140 if (!from_pte)
141 BUG();
142
143 to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
144 if (!to_pte)
145 BUG();
146
147 cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing; 132 cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing;
148 cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing; 133 cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing;
149 } 134 }
@@ -151,5 +136,4 @@ static int __init v6_userpage_init(void)
151 return 0; 136 return 0;
152} 137}
153 138
154__initcall(v6_userpage_init); 139core_initcall(v6_userpage_init);
155
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index c6de48d89503..4085ed983e46 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -13,6 +13,29 @@
13 13
14#include <asm/cacheflush.h> 14#include <asm/cacheflush.h>
15#include <asm/system.h> 15#include <asm/system.h>
16#include <asm/tlbflush.h>
17
18#ifdef CONFIG_CPU_CACHE_VIPT
19#define ALIAS_FLUSH_START 0xffff4000
20
21#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
22
23static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
24{
25 unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
26
27 set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL));
28 flush_tlb_kernel_page(to);
29
30 asm( "mcrr p15, 0, %1, %0, c14\n"
31 " mcrr p15, 0, %1, %0, c5\n"
32 :
33 : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES)
34 : "cc");
35}
36#else
37#define flush_pfn_alias(pfn,vaddr) do { } while (0)
38#endif
16 39
17static void __flush_dcache_page(struct address_space *mapping, struct page *page) 40static void __flush_dcache_page(struct address_space *mapping, struct page *page)
18{ 41{
@@ -37,6 +60,18 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
37 return; 60 return;
38 61
39 /* 62 /*
63 * This is a page cache page. If we have a VIPT cache, we
64 * only need to do one flush - which would be at the relevant
65 * userspace colour, which is congruent with page->index.
66 */
67 if (cache_is_vipt()) {
68 if (cache_is_vipt_aliasing())
69 flush_pfn_alias(page_to_pfn(page),
70 page->index << PAGE_CACHE_SHIFT);
71 return;
72 }
73
74 /*
40 * There are possible user space mappings of this page: 75 * There are possible user space mappings of this page:
41 * - VIVT cache: we need to also write back and invalidate all user 76 * - VIVT cache: we need to also write back and invalidate all user
42 * data in the current VM view associated with this page. 77 * data in the current VM view associated with this page.
@@ -57,8 +92,6 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
57 continue; 92 continue;
58 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; 93 offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
59 flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page)); 94 flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page));
60 if (cache_is_vipt())
61 break;
62 } 95 }
63 flush_dcache_mmap_unlock(mapping); 96 flush_dcache_mmap_unlock(mapping);
64} 97}
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 585dfb8e20b9..2c2b93d77d43 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -37,6 +37,8 @@ pgprot_t pgprot_kernel;
37 37
38EXPORT_SYMBOL(pgprot_kernel); 38EXPORT_SYMBOL(pgprot_kernel);
39 39
40pmd_t *top_pmd;
41
40struct cachepolicy { 42struct cachepolicy {
41 const char policy[16]; 43 const char policy[16];
42 unsigned int cr_mask; 44 unsigned int cr_mask;
@@ -142,6 +144,16 @@ __setup("noalign", noalign_setup);
142 144
143#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD) 145#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
144 146
147static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
148{
149 return pmd_offset(pgd, virt);
150}
151
152static inline pmd_t *pmd_off_k(unsigned long virt)
153{
154 return pmd_off(pgd_offset_k(virt), virt);
155}
156
145/* 157/*
146 * need to get a 16k page for level 1 158 * need to get a 16k page for level 1
147 */ 159 */
@@ -220,7 +232,7 @@ void free_pgd_slow(pgd_t *pgd)
220 return; 232 return;
221 233
222 /* pgd is always present and good */ 234 /* pgd is always present and good */
223 pmd = (pmd_t *)pgd; 235 pmd = pmd_off(pgd, 0);
224 if (pmd_none(*pmd)) 236 if (pmd_none(*pmd))
225 goto free; 237 goto free;
226 if (pmd_bad(*pmd)) { 238 if (pmd_bad(*pmd)) {
@@ -246,9 +258,8 @@ free:
246static inline void 258static inline void
247alloc_init_section(unsigned long virt, unsigned long phys, int prot) 259alloc_init_section(unsigned long virt, unsigned long phys, int prot)
248{ 260{
249 pmd_t *pmdp; 261 pmd_t *pmdp = pmd_off_k(virt);
250 262
251 pmdp = pmd_offset(pgd_offset_k(virt), virt);
252 if (virt & (1 << 20)) 263 if (virt & (1 << 20))
253 pmdp++; 264 pmdp++;
254 265
@@ -283,11 +294,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
283static inline void 294static inline void
284alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot) 295alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
285{ 296{
286 pmd_t *pmdp; 297 pmd_t *pmdp = pmd_off_k(virt);
287 pte_t *ptep; 298 pte_t *ptep;
288 299
289 pmdp = pmd_offset(pgd_offset_k(virt), virt);
290
291 if (pmd_none(*pmdp)) { 300 if (pmd_none(*pmdp)) {
292 unsigned long pmdval; 301 unsigned long pmdval;
293 ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * 302 ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
@@ -310,7 +319,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
310 */ 319 */
311static inline void clear_mapping(unsigned long virt) 320static inline void clear_mapping(unsigned long virt)
312{ 321{
313 pmd_clear(pmd_offset(pgd_offset_k(virt), virt)); 322 pmd_clear(pmd_off_k(virt));
314} 323}
315 324
316struct mem_types { 325struct mem_types {
@@ -578,7 +587,7 @@ void setup_mm_for_reboot(char mode)
578 PMD_TYPE_SECT; 587 PMD_TYPE_SECT;
579 if (cpu_arch <= CPU_ARCH_ARMv5) 588 if (cpu_arch <= CPU_ARCH_ARMv5)
580 pmdval |= PMD_BIT4; 589 pmdval |= PMD_BIT4;
581 pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT); 590 pmd = pmd_off(pgd, i << PGDIR_SHIFT);
582 pmd[0] = __pmd(pmdval); 591 pmd[0] = __pmd(pmdval);
583 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); 592 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
584 flush_pmd_entry(pmd); 593 flush_pmd_entry(pmd);
@@ -675,6 +684,8 @@ void __init memtable_init(struct meminfo *mi)
675 684
676 flush_cache_all(); 685 flush_cache_all();
677 flush_tlb_all(); 686 flush_tlb_all();
687
688 top_pmd = pmd_off_k(0xffff0000);
678} 689}
679 690
680/* 691/*
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index 134aec1c6d19..b5f83e9f04db 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -54,7 +54,7 @@ asmlinkage void ret_from_fork(void);
54void default_idle(void) 54void default_idle(void)
55{ 55{
56 while(1) { 56 while(1) {
57 if (need_resched()) { 57 if (!need_resched()) {
58 local_irq_enable(); 58 local_irq_enable();
59 __asm__("sleep"); 59 __asm__("sleep");
60 local_irq_disable(); 60 local_irq_disable();
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index fee589119606..dfd904f6883b 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -183,7 +183,7 @@ config M386
183 - "Winchip-C6" for original IDT Winchip. 183 - "Winchip-C6" for original IDT Winchip.
184 - "Winchip-2" for IDT Winchip 2. 184 - "Winchip-2" for IDT Winchip 2.
185 - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. 185 - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
186 - "MediaGX/Geode" for Cyrix MediaGX aka Geode. 186 - "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
187 - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. 187 - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
188 - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). 188 - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
189 189
@@ -311,12 +311,10 @@ config MWINCHIP3D
311 stores for this CPU, which can increase performance of some 311 stores for this CPU, which can increase performance of some
312 operations. 312 operations.
313 313
314config MGEODE 314config MGEODEGX1
315 bool "MediaGX/Geode" 315 bool "GeodeGX1"
316 help 316 help
317 Select this for a Cyrix MediaGX aka Geode chip. Linux and GCC 317 Select this for a Geode GX1 (Cyrix MediaGX) chip.
318 treat this chip as a 586TSC with some extended instructions
319 and alignment reqirements.
320 318
321config MCYRIXIII 319config MCYRIXIII
322 bool "CyrixIII/VIA-C3" 320 bool "CyrixIII/VIA-C3"
@@ -368,7 +366,7 @@ config X86_L1_CACHE_SHIFT
368 int 366 int
369 default "7" if MPENTIUM4 || X86_GENERIC 367 default "7" if MPENTIUM4 || X86_GENERIC
370 default "4" if X86_ELAN || M486 || M386 368 default "4" if X86_ELAN || M486 || M386
371 default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE 369 default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1
372 default "6" if MK7 || MK8 || MPENTIUMM 370 default "6" if MK7 || MK8 || MPENTIUMM
373 371
374config RWSEM_GENERIC_SPINLOCK 372config RWSEM_GENERIC_SPINLOCK
@@ -387,7 +385,7 @@ config GENERIC_CALIBRATE_DELAY
387 385
388config X86_PPRO_FENCE 386config X86_PPRO_FENCE
389 bool 387 bool
390 depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODE 388 depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1
391 default y 389 default y
392 390
393config X86_F00F_BUG 391config X86_F00F_BUG
@@ -417,7 +415,7 @@ config X86_POPAD_OK
417 415
418config X86_ALIGNMENT_16 416config X86_ALIGNMENT_16
419 bool 417 bool
420 depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODE 418 depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
421 default y 419 default y
422 420
423config X86_GOOD_APIC 421config X86_GOOD_APIC
@@ -442,7 +440,7 @@ config X86_USE_3DNOW
442 440
443config X86_OOSTORE 441config X86_OOSTORE
444 bool 442 bool
445 depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MGEODE) && MTRR 443 depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
446 default y 444 default y
447 445
448config HPET_TIMER 446config HPET_TIMER
@@ -578,7 +576,7 @@ config X86_VISWS_APIC
578 576
579config X86_TSC 577config X86_TSC
580 bool 578 bool
581 depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODE) && !X86_NUMAQ 579 depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ
582 default y 580 default y
583 581
584config X86_MCE 582config X86_MCE
@@ -1165,7 +1163,7 @@ config PCI_DIRECT
1165 1163
1166config PCI_MMCONFIG 1164config PCI_MMCONFIG
1167 bool 1165 bool
1168 depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI)) 1166 depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
1169 select ACPI_BOOT 1167 select ACPI_BOOT
1170 default y 1168 default y
1171 1169
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 04783ceb050c..1c36ca332a96 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -14,7 +14,7 @@
14# 19990713 Artur Skawina <skawina@geocities.com> 14# 19990713 Artur Skawina <skawina@geocities.com>
15# Added '-march' and '-mpreferred-stack-boundary' support 15# Added '-march' and '-mpreferred-stack-boundary' support
16# 16#
17# Kianusch Sayah Karadji <kianusch@sk-tech.net> 17# 20050320 Kianusch Sayah Karadji <kianusch@sk-tech.net>
18# Added support for GEODE CPU 18# Added support for GEODE CPU
19 19
20LDFLAGS := -m elf_i386 20LDFLAGS := -m elf_i386
@@ -54,8 +54,8 @@ cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686)
54# AMD Elan support 54# AMD Elan support
55cflags-$(CONFIG_X86_ELAN) += -march=i486 55cflags-$(CONFIG_X86_ELAN) += -march=i486
56 56
57# MediaGX aka Geode support 57# Geode GX1 support
58cflags-$(CONFIG_MGEODE) += $(call cc-option,-march=pentium-mmx,-march=i586) 58cflags-$(CONFIG_MGEODEGX1) += $(call cc-option,-march=pentium-mmx,-march=i486)
59 59
60# -mregparm=3 works ok on gcc-3.0 and later 60# -mregparm=3 works ok on gcc-3.0 and later
61# 61#
diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
index ba9fe14db6a9..011b7a4993d4 100644
--- a/arch/i386/boot/bootsect.S
+++ b/arch/i386/boot/bootsect.S
@@ -83,7 +83,7 @@ bugger_off_msg:
83 .ascii "\n" 83 .ascii "\n"
84 .ascii "Remove disk and press any key to reboot . . .\r\n" 84 .ascii "Remove disk and press any key to reboot . . .\r\n"
85 .byte 0 85 .byte 0
86 86
87 87
88 # Kernel attributes; used by setup 88 # Kernel attributes; used by setup
89 89
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 925d3f5a3824..0587477c99f2 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -1924,36 +1924,36 @@ skip10: movb %ah, %al
1924 ret 1924 ret
1925 1925
1926store_edid: 1926store_edid:
1927 pushw %es # just save all registers 1927 pushw %es # just save all registers
1928 pushw %ax 1928 pushw %ax
1929 pushw %bx 1929 pushw %bx
1930 pushw %cx 1930 pushw %cx
1931 pushw %dx 1931 pushw %dx
1932 pushw %di 1932 pushw %di
1933 1933
1934 pushw %fs 1934 pushw %fs
1935 popw %es 1935 popw %es
1936 1936
1937 movl $0x13131313, %eax # memset block with 0x13 1937 movl $0x13131313, %eax # memset block with 0x13
1938 movw $32, %cx 1938 movw $32, %cx
1939 movw $0x140, %di 1939 movw $0x140, %di
1940 cld 1940 cld
1941 rep 1941 rep
1942 stosl 1942 stosl
1943 1943
1944 movw $0x4f15, %ax # do VBE/DDC 1944 movw $0x4f15, %ax # do VBE/DDC
1945 movw $0x01, %bx 1945 movw $0x01, %bx
1946 movw $0x00, %cx 1946 movw $0x00, %cx
1947 movw $0x01, %dx 1947 movw $0x01, %dx
1948 movw $0x140, %di 1948 movw $0x140, %di
1949 int $0x10 1949 int $0x10
1950 1950
1951 popw %di # restore all registers 1951 popw %di # restore all registers
1952 popw %dx 1952 popw %dx
1953 popw %cx 1953 popw %cx
1954 popw %bx 1954 popw %bx
1955 popw %ax 1955 popw %ax
1956 popw %es 1956 popw %es
1957 ret 1957 ret
1958 1958
1959# VIDEO_SELECT-only variables 1959# VIDEO_SELECT-only variables
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 53eb5cfd5b63..848bb97af7ca 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -650,7 +650,7 @@ acpi_find_rsdp (void)
650 */ 650 */
651 rsdp_phys = acpi_scan_rsdp (0, 0x400); 651 rsdp_phys = acpi_scan_rsdp (0, 0x400);
652 if (!rsdp_phys) 652 if (!rsdp_phys)
653 rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF); 653 rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000);
654 654
655 return rsdp_phys; 655 return rsdp_phys;
656} 656}
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 16dbc4151be4..73aeaf5a9d4e 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -24,9 +24,6 @@ __asm__(".align 4\nvide: ret");
24 24
25static void __init init_amd(struct cpuinfo_x86 *c) 25static void __init init_amd(struct cpuinfo_x86 *c)
26{ 26{
27#ifdef CONFIG_X86_SMP
28 int cpu = c == &boot_cpu_data ? 0 : c - cpu_data;
29#endif
30 u32 l, h; 27 u32 l, h;
31 int mbytes = num_physpages >> (20-PAGE_SHIFT); 28 int mbytes = num_physpages >> (20-PAGE_SHIFT);
32 int r; 29 int r;
@@ -198,14 +195,19 @@ static void __init init_amd(struct cpuinfo_x86 *c)
198 c->x86_num_cores = 1; 195 c->x86_num_cores = 1;
199 } 196 }
200 197
201#ifdef CONFIG_X86_SMP 198#ifdef CONFIG_X86_HT
202 /* 199 /*
203 * On a AMD dual core setup the lower bits of the APIC id 200 * On a AMD dual core setup the lower bits of the APIC id
204 * distingush the cores. Assumes number of cores is a power 201 * distingush the cores. Assumes number of cores is a power
205 * of two. 202 * of two.
206 */ 203 */
207 if (c->x86_num_cores > 1) { 204 if (c->x86_num_cores > 1) {
208 cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1); 205 int cpu = smp_processor_id();
206 unsigned bits = 0;
207 while ((1 << bits) < c->x86_num_cores)
208 bits++;
209 cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
210 phys_proc_id[cpu] >>= bits;
209 printk(KERN_INFO "CPU %d(%d) -> Core %d\n", 211 printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
210 cpu, c->x86_num_cores, cpu_core_id[cpu]); 212 cpu, c->x86_num_cores, cpu_core_id[cpu]);
211 } 213 }
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 6be0310e3cd3..d199e525680a 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -243,6 +243,10 @@ static void __init early_cpu_detect(void)
243 } 243 }
244 244
245 early_intel_workaround(c); 245 early_intel_workaround(c);
246
247#ifdef CONFIG_X86_HT
248 phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
249#endif
246} 250}
247 251
248void __init generic_identify(struct cpuinfo_x86 * c) 252void __init generic_identify(struct cpuinfo_x86 * c)
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index f25ffd74235c..0f1eb507233b 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ
23 If in doubt, say N. 23 If in doubt, say N.
24 24
25config ELAN_CPUFREQ 25config ELAN_CPUFREQ
26 tristate "AMD Elan" 26 tristate "AMD Elan SC400 and SC410"
27 select CPU_FREQ_TABLE 27 select CPU_FREQ_TABLE
28 depends on X86_ELAN 28 depends on X86_ELAN
29 ---help--- 29 ---help---
@@ -38,6 +38,18 @@ config ELAN_CPUFREQ
38 38
39 If in doubt, say N. 39 If in doubt, say N.
40 40
41config SC520_CPUFREQ
42 tristate "AMD Elan SC520"
43 select CPU_FREQ_TABLE
44 depends on X86_ELAN
45 ---help---
46 This adds the CPUFreq driver for AMD Elan SC520 processor.
47
48 For details, take a look at <file:Documentation/cpu-freq/>.
49
50 If in doubt, say N.
51
52
41config X86_POWERNOW_K6 53config X86_POWERNOW_K6
42 tristate "AMD Mobile K6-2/K6-3 PowerNow!" 54 tristate "AMD Mobile K6-2/K6-3 PowerNow!"
43 select CPU_FREQ_TABLE 55 select CPU_FREQ_TABLE
diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile
index a922e97aeedd..2e894f1c8910 100644
--- a/arch/i386/kernel/cpu/cpufreq/Makefile
+++ b/arch/i386/kernel/cpu/cpufreq/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
3obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o 3obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
4obj-$(CONFIG_X86_LONGHAUL) += longhaul.o 4obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
5obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o 5obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
6obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o
6obj-$(CONFIG_X86_LONGRUN) += longrun.o 7obj-$(CONFIG_X86_LONGRUN) += longrun.o
7obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o 8obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
8obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o 9obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index ab0f9f5aac11..04e3563da4fe 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,6 +29,7 @@
29#include <linux/cpufreq.h> 29#include <linux/cpufreq.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/pci.h>
32 33
33#include <asm/msr.h> 34#include <asm/msr.h>
34#include <asm/timex.h> 35#include <asm/timex.h>
@@ -119,7 +120,13 @@ static int longhaul_get_cpu_mult(void)
119static void do_powersaver(union msr_longhaul *longhaul, 120static void do_powersaver(union msr_longhaul *longhaul,
120 unsigned int clock_ratio_index) 121 unsigned int clock_ratio_index)
121{ 122{
123 struct pci_dev *dev;
124 unsigned long flags;
125 unsigned int tmp_mask;
122 int version; 126 int version;
127 int i;
128 u16 pci_cmd;
129 u16 cmd_state[64];
123 130
124 switch (cpu_model) { 131 switch (cpu_model) {
125 case CPU_EZRA_T: 132 case CPU_EZRA_T:
@@ -137,17 +144,58 @@ static void do_powersaver(union msr_longhaul *longhaul,
137 longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; 144 longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
138 longhaul->bits.EnableSoftBusRatio = 1; 145 longhaul->bits.EnableSoftBusRatio = 1;
139 longhaul->bits.RevisionKey = 0; 146 longhaul->bits.RevisionKey = 0;
140 local_irq_disable(); 147
141 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 148 preempt_disable();
149 local_irq_save(flags);
150
151 /*
152 * get current pci bus master state for all devices
153 * and clear bus master bit
154 */
155 dev = NULL;
156 i = 0;
157 do {
158 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
159 if (dev != NULL) {
160 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
161 cmd_state[i++] = pci_cmd;
162 pci_cmd &= ~PCI_COMMAND_MASTER;
163 pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
164 }
165 } while (dev != NULL);
166
167 tmp_mask=inb(0x21); /* works on C3. save mask. */
168 outb(0xFE,0x21); /* TMR0 only */
169 outb(0xFF,0x80); /* delay */
170
142 local_irq_enable(); 171 local_irq_enable();
172
173 __hlt();
174 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
143 __hlt(); 175 __hlt();
144 176
177 local_irq_disable();
178
179 outb(tmp_mask,0x21); /* restore mask */
180
181 /* restore pci bus master state for all devices */
182 dev = NULL;
183 i = 0;
184 do {
185 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
186 if (dev != NULL) {
187 pci_cmd = cmd_state[i++];
188 pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
189 }
190 } while (dev != NULL);
191 local_irq_restore(flags);
192 preempt_enable();
193
194 /* disable bus ratio bit */
145 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); 195 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
146 longhaul->bits.EnableSoftBusRatio = 0; 196 longhaul->bits.EnableSoftBusRatio = 0;
147 longhaul->bits.RevisionKey = version; 197 longhaul->bits.RevisionKey = version;
148 local_irq_disable();
149 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 198 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
150 local_irq_enable();
151} 199}
152 200
153/** 201/**
@@ -578,7 +626,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
578 longhaul_setup_voltagescaling(); 626 longhaul_setup_voltagescaling();
579 627
580 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 628 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
581 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 629 policy->cpuinfo.transition_latency = 200000; /* nsec */
582 policy->cur = calc_speed(longhaul_get_cpu_mult()); 630 policy->cur = calc_speed(longhaul_get_cpu_mult());
583 631
584 ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); 632 ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 913f652623d9..5c530064eb74 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -23,6 +23,7 @@
23#include <linux/dmi.h> 23#include <linux/dmi.h>
24 24
25#include <asm/msr.h> 25#include <asm/msr.h>
26#include <asm/timer.h>
26#include <asm/timex.h> 27#include <asm/timex.h>
27#include <asm/io.h> 28#include <asm/io.h>
28#include <asm/system.h> 29#include <asm/system.h>
@@ -586,13 +587,17 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
586 587
587 rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); 588 rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
588 589
589 /* A K7 with powernow technology is set to max frequency by BIOS */ 590 /* recalibrate cpu_khz */
590 fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID]; 591 result = recalibrate_cpu_khz();
592 if (result)
593 return result;
594
595 fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
591 if (!fsb) { 596 if (!fsb) {
592 printk(KERN_WARNING PFX "can not determine bus frequency\n"); 597 printk(KERN_WARNING PFX "can not determine bus frequency\n");
593 return -EINVAL; 598 return -EINVAL;
594 } 599 }
595 dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000); 600 dprintk("FSB: %3dMHz\n", fsb/1000);
596 601
597 if (dmi_check_system(powernow_dmi_table) || acpi_force) { 602 if (dmi_check_system(powernow_dmi_table) || acpi_force) {
598 printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n"); 603 printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index a65ff7e32e5d..10cc096c0ade 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -4,7 +4,7 @@
4 * GNU general public license version 2. See "COPYING" or 4 * GNU general public license version 2. See "COPYING" or
5 * http://www.gnu.org/licenses/gpl.html 5 * http://www.gnu.org/licenses/gpl.html
6 * 6 *
7 * Support : paul.devriendt@amd.com 7 * Support : mark.langsdorf@amd.com
8 * 8 *
9 * Based on the powernow-k7.c module written by Dave Jones. 9 * Based on the powernow-k7.c module written by Dave Jones.
10 * (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs 10 * (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs
@@ -15,12 +15,13 @@
15 * 15 *
16 * Valuable input gratefully received from Dave Jones, Pavel Machek, 16 * Valuable input gratefully received from Dave Jones, Pavel Machek,
17 * Dominik Brodowski, and others. 17 * Dominik Brodowski, and others.
18 * Originally developed by Paul Devriendt.
18 * Processor information obtained from Chapter 9 (Power and Thermal Management) 19 * Processor information obtained from Chapter 9 (Power and Thermal Management)
19 * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD 20 * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
20 * Opteron Processors" available for download from www.amd.com 21 * Opteron Processors" available for download from www.amd.com
21 * 22 *
22 * Tables for specific CPUs can be infrerred from 23 * Tables for specific CPUs can be infrerred from
23 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf 24 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
24 */ 25 */
25 26
26#include <linux/kernel.h> 27#include <linux/kernel.h>
@@ -30,6 +31,7 @@
30#include <linux/cpufreq.h> 31#include <linux/cpufreq.h>
31#include <linux/slab.h> 32#include <linux/slab.h>
32#include <linux/string.h> 33#include <linux/string.h>
34#include <linux/cpumask.h>
33 35
34#include <asm/msr.h> 36#include <asm/msr.h>
35#include <asm/io.h> 37#include <asm/io.h>
@@ -42,7 +44,7 @@
42 44
43#define PFX "powernow-k8: " 45#define PFX "powernow-k8: "
44#define BFX PFX "BIOS error: " 46#define BFX PFX "BIOS error: "
45#define VERSION "version 1.00.09e" 47#define VERSION "version 1.40.2"
46#include "powernow-k8.h" 48#include "powernow-k8.h"
47 49
48/* serialize freq changes */ 50/* serialize freq changes */
@@ -50,6 +52,10 @@ static DECLARE_MUTEX(fidvid_sem);
50 52
51static struct powernow_k8_data *powernow_data[NR_CPUS]; 53static struct powernow_k8_data *powernow_data[NR_CPUS];
52 54
55#ifndef CONFIG_SMP
56static cpumask_t cpu_core_map[1];
57#endif
58
53/* Return a frequency in MHz, given an input fid */ 59/* Return a frequency in MHz, given an input fid */
54static u32 find_freq_from_fid(u32 fid) 60static u32 find_freq_from_fid(u32 fid)
55{ 61{
@@ -274,11 +280,18 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
274{ 280{
275 u32 rvosteps = data->rvo; 281 u32 rvosteps = data->rvo;
276 u32 savefid = data->currfid; 282 u32 savefid = data->currfid;
283 u32 maxvid, lo;
277 284
278 dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n", 285 dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
279 smp_processor_id(), 286 smp_processor_id(),
280 data->currfid, data->currvid, reqvid, data->rvo); 287 data->currfid, data->currvid, reqvid, data->rvo);
281 288
289 rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
290 maxvid = 0x1f & (maxvid >> 16);
291 dprintk("ph1 maxvid=0x%x\n", maxvid);
292 if (reqvid < maxvid) /* lower numbers are higher voltages */
293 reqvid = maxvid;
294
282 while (data->currvid > reqvid) { 295 while (data->currvid > reqvid) {
283 dprintk("ph1: curr 0x%x, req vid 0x%x\n", 296 dprintk("ph1: curr 0x%x, req vid 0x%x\n",
284 data->currvid, reqvid); 297 data->currvid, reqvid);
@@ -286,8 +299,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
286 return 1; 299 return 1;
287 } 300 }
288 301
289 while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) { 302 while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
290 if (data->currvid == 0) { 303 if (data->currvid == maxvid) {
291 rvosteps = 0; 304 rvosteps = 0;
292 } else { 305 } else {
293 dprintk("ph1: changing vid for rvo, req 0x%x\n", 306 dprintk("ph1: changing vid for rvo, req 0x%x\n",
@@ -671,7 +684,7 @@ static int find_psb_table(struct powernow_k8_data *data)
671 * BIOS and Kernel Developer's Guide, which is available on 684 * BIOS and Kernel Developer's Guide, which is available on
672 * www.amd.com 685 * www.amd.com
673 */ 686 */
674 printk(KERN_ERR PFX "BIOS error - no PSB\n"); 687 printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
675 return -ENODEV; 688 return -ENODEV;
676} 689}
677 690
@@ -695,7 +708,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
695 struct cpufreq_frequency_table *powernow_table; 708 struct cpufreq_frequency_table *powernow_table;
696 709
697 if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { 710 if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
698 dprintk("register performance failed\n"); 711 dprintk("register performance failed: bad ACPI data\n");
699 return -EIO; 712 return -EIO;
700 } 713 }
701 714
@@ -746,22 +759,23 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
746 continue; 759 continue;
747 } 760 }
748 761
749 if (fid < HI_FID_TABLE_BOTTOM) { 762 /* verify only 1 entry from the lo frequency table */
750 if (cntlofreq) { 763 if (fid < HI_FID_TABLE_BOTTOM) {
751 /* if both entries are the same, ignore this 764 if (cntlofreq) {
752 * one... 765 /* if both entries are the same, ignore this
753 */ 766 * one...
754 if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || 767 */
755 (powernow_table[i].index != powernow_table[cntlofreq].index)) { 768 if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
756 printk(KERN_ERR PFX "Too many lo freq table entries\n"); 769 (powernow_table[i].index != powernow_table[cntlofreq].index)) {
757 goto err_out_mem; 770 printk(KERN_ERR PFX "Too many lo freq table entries\n");
758 } 771 goto err_out_mem;
759 772 }
760 dprintk("double low frequency table entry, ignoring it.\n"); 773
761 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; 774 dprintk("double low frequency table entry, ignoring it.\n");
762 continue; 775 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
763 } else 776 continue;
764 cntlofreq = i; 777 } else
778 cntlofreq = i;
765 } 779 }
766 780
767 if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { 781 if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
@@ -816,7 +830,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
816{ 830{
817 u32 fid; 831 u32 fid;
818 u32 vid; 832 u32 vid;
819 int res; 833 int res, i;
820 struct cpufreq_freqs freqs; 834 struct cpufreq_freqs freqs;
821 835
822 dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); 836 dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
@@ -841,7 +855,8 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
841 } 855 }
842 856
843 if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) { 857 if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
844 printk("ignoring illegal change in lo freq table-%x to 0x%x\n", 858 printk(KERN_ERR PFX
859 "ignoring illegal change in lo freq table-%x to 0x%x\n",
845 data->currfid, fid); 860 data->currfid, fid);
846 return 1; 861 return 1;
847 } 862 }
@@ -850,18 +865,20 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
850 smp_processor_id(), fid, vid); 865 smp_processor_id(), fid, vid);
851 866
852 freqs.cpu = data->cpu; 867 freqs.cpu = data->cpu;
853
854 freqs.old = find_khz_freq_from_fid(data->currfid); 868 freqs.old = find_khz_freq_from_fid(data->currfid);
855 freqs.new = find_khz_freq_from_fid(fid); 869 freqs.new = find_khz_freq_from_fid(fid);
856 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 870 for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
871 freqs.cpu = i;
872 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
873 }
857 874
858 down(&fidvid_sem);
859 res = transition_fid_vid(data, fid, vid); 875 res = transition_fid_vid(data, fid, vid);
860 up(&fidvid_sem);
861 876
862 freqs.new = find_khz_freq_from_fid(data->currfid); 877 freqs.new = find_khz_freq_from_fid(data->currfid);
863 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 878 for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
864 879 freqs.cpu = i;
880 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
881 }
865 return res; 882 return res;
866} 883}
867 884
@@ -874,6 +891,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
874 u32 checkvid = data->currvid; 891 u32 checkvid = data->currvid;
875 unsigned int newstate; 892 unsigned int newstate;
876 int ret = -EIO; 893 int ret = -EIO;
894 int i;
877 895
878 /* only run on specific CPU from here on */ 896 /* only run on specific CPU from here on */
879 oldmask = current->cpus_allowed; 897 oldmask = current->cpus_allowed;
@@ -902,22 +920,41 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
902 data->currfid, data->currvid); 920 data->currfid, data->currvid);
903 921
904 if ((checkvid != data->currvid) || (checkfid != data->currfid)) { 922 if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
905 printk(KERN_ERR PFX 923 printk(KERN_INFO PFX
906 "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n", 924 "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
907 checkfid, data->currfid, checkvid, data->currvid); 925 checkfid, data->currfid, checkvid, data->currvid);
908 } 926 }
909 927
910 if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) 928 if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
911 goto err_out; 929 goto err_out;
912 930
931 down(&fidvid_sem);
932
933 for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
934 /* make sure the sibling is initialized */
935 if (!powernow_data[i]) {
936 ret = 0;
937 up(&fidvid_sem);
938 goto err_out;
939 }
940 }
941
913 powernow_k8_acpi_pst_values(data, newstate); 942 powernow_k8_acpi_pst_values(data, newstate);
914 943
915 if (transition_frequency(data, newstate)) { 944 if (transition_frequency(data, newstate)) {
916 printk(KERN_ERR PFX "transition frequency failed\n"); 945 printk(KERN_ERR PFX "transition frequency failed\n");
917 ret = 1; 946 ret = 1;
947 up(&fidvid_sem);
918 goto err_out; 948 goto err_out;
919 } 949 }
920 950
951 /* Update all the fid/vids of our siblings */
952 for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
953 powernow_data[i]->currvid = data->currvid;
954 powernow_data[i]->currfid = data->currfid;
955 }
956 up(&fidvid_sem);
957
921 pol->cur = find_khz_freq_from_fid(data->currfid); 958 pol->cur = find_khz_freq_from_fid(data->currfid);
922 ret = 0; 959 ret = 0;
923 960
@@ -962,7 +999,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
962 */ 999 */
963 1000
964 if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { 1001 if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
965 printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n"); 1002 printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
966 kfree(data); 1003 kfree(data);
967 return -ENODEV; 1004 return -ENODEV;
968 } 1005 }
@@ -1003,6 +1040,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
1003 schedule(); 1040 schedule();
1004 1041
1005 pol->governor = CPUFREQ_DEFAULT_GOVERNOR; 1042 pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
1043 pol->cpus = cpu_core_map[pol->cpu];
1006 1044
1007 /* Take a crude guess here. 1045 /* Take a crude guess here.
1008 * That guess was in microseconds, so multiply with 1000 */ 1046 * That guess was in microseconds, so multiply with 1000 */
@@ -1069,7 +1107,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
1069 return 0; 1107 return 0;
1070 } 1108 }
1071 preempt_disable(); 1109 preempt_disable();
1072 1110
1073 if (query_current_values_with_pending_wait(data)) 1111 if (query_current_values_with_pending_wait(data))
1074 goto out; 1112 goto out;
1075 1113
@@ -1127,9 +1165,10 @@ static void __exit powernowk8_exit(void)
1127 cpufreq_unregister_driver(&cpufreq_amd64_driver); 1165 cpufreq_unregister_driver(&cpufreq_amd64_driver);
1128} 1166}
1129 1167
1130MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>"); 1168MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
1131MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver."); 1169MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
1132MODULE_LICENSE("GPL"); 1170MODULE_LICENSE("GPL");
1133 1171
1134late_initcall(powernowk8_init); 1172late_initcall(powernowk8_init);
1135module_exit(powernowk8_exit); 1173module_exit(powernowk8_exit);
1174
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index 63ebc8470f52..9ed5bf221cb7 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -174,3 +174,18 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
174static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid); 174static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
175 175
176static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index); 176static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
177
178#ifndef for_each_cpu_mask
179#define for_each_cpu_mask(i,mask) for (i=0;i<1;i++)
180#endif
181
182#ifdef CONFIG_SMP
183static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
184{
185}
186#else
187static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
188{
189 cpu_set(0, cpu_sharedcore_mask[0]);
190}
191#endif
diff --git a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
new file mode 100644
index 000000000000..ef457d50f4ac
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
@@ -0,0 +1,186 @@
1/*
2 * sc520_freq.c: cpufreq driver for the AMD Elan sc520
3 *
4 * Copyright (C) 2005 Sean Young <sean@mess.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 * Based on elanfreq.c
12 *
13 * 2005-03-30: - initial revision
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/init.h>
19
20#include <linux/delay.h>
21#include <linux/cpufreq.h>
22
23#include <asm/msr.h>
24#include <asm/timex.h>
25#include <asm/io.h>
26
27#define MMCR_BASE 0xfffef000 /* The default base address */
28#define OFFS_CPUCTL 0x2 /* CPU Control Register */
29
30static __u8 __iomem *cpuctl;
31
32#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "sc520_freq", msg)
33
34static struct cpufreq_frequency_table sc520_freq_table[] = {
35 {0x01, 100000},
36 {0x02, 133000},
37 {0, CPUFREQ_TABLE_END},
38};
39
40static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
41{
42 u8 clockspeed_reg = *cpuctl;
43
44 switch (clockspeed_reg & 0x03) {
45 default:
46 printk(KERN_ERR "sc520_freq: error: cpuctl register has unexpected value %02x\n", clockspeed_reg);
47 case 0x01:
48 return 100000;
49 case 0x02:
50 return 133000;
51 }
52}
53
54static void sc520_freq_set_cpu_state (unsigned int state)
55{
56
57 struct cpufreq_freqs freqs;
58 u8 clockspeed_reg;
59
60 freqs.old = sc520_freq_get_cpu_frequency(0);
61 freqs.new = sc520_freq_table[state].frequency;
62 freqs.cpu = 0; /* AMD Elan is UP */
63
64 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
65
66 dprintk("attempting to set frequency to %i kHz\n",
67 sc520_freq_table[state].frequency);
68
69 local_irq_disable();
70
71 clockspeed_reg = *cpuctl & ~0x03;
72 *cpuctl = clockspeed_reg | sc520_freq_table[state].index;
73
74 local_irq_enable();
75
76 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
77};
78
79static int sc520_freq_verify (struct cpufreq_policy *policy)
80{
81 return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]);
82}
83
84static int sc520_freq_target (struct cpufreq_policy *policy,
85 unsigned int target_freq,
86 unsigned int relation)
87{
88 unsigned int newstate = 0;
89
90 if (cpufreq_frequency_table_target(policy, sc520_freq_table, target_freq, relation, &newstate))
91 return -EINVAL;
92
93 sc520_freq_set_cpu_state(newstate);
94
95 return 0;
96}
97
98
99/*
100 * Module init and exit code
101 */
102
103static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
104{
105 struct cpuinfo_x86 *c = cpu_data;
106 int result;
107
108 /* capability check */
109 if (c->x86_vendor != X86_VENDOR_AMD ||
110 c->x86 != 4 || c->x86_model != 9)
111 return -ENODEV;
112
113 /* cpuinfo and default policy values */
114 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
115 policy->cpuinfo.transition_latency = 1000000; /* 1ms */
116 policy->cur = sc520_freq_get_cpu_frequency(0);
117
118 result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
119 if (result)
120 return (result);
121
122 cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu);
123
124 return 0;
125}
126
127
128static int sc520_freq_cpu_exit(struct cpufreq_policy *policy)
129{
130 cpufreq_frequency_table_put_attr(policy->cpu);
131 return 0;
132}
133
134
135static struct freq_attr* sc520_freq_attr[] = {
136 &cpufreq_freq_attr_scaling_available_freqs,
137 NULL,
138};
139
140
141static struct cpufreq_driver sc520_freq_driver = {
142 .get = sc520_freq_get_cpu_frequency,
143 .verify = sc520_freq_verify,
144 .target = sc520_freq_target,
145 .init = sc520_freq_cpu_init,
146 .exit = sc520_freq_cpu_exit,
147 .name = "sc520_freq",
148 .owner = THIS_MODULE,
149 .attr = sc520_freq_attr,
150};
151
152
153static int __init sc520_freq_init(void)
154{
155 struct cpuinfo_x86 *c = cpu_data;
156
157 /* Test if we have the right hardware */
158 if(c->x86_vendor != X86_VENDOR_AMD ||
159 c->x86 != 4 || c->x86_model != 9) {
160 dprintk("no Elan SC520 processor found!\n");
161 return -ENODEV;
162 }
163 cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
164 if(!cpuctl) {
165 printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
166 return -ENOMEM;
167 }
168
169 return cpufreq_register_driver(&sc520_freq_driver);
170}
171
172
173static void __exit sc520_freq_exit(void)
174{
175 cpufreq_unregister_driver(&sc520_freq_driver);
176 iounmap(cpuctl);
177}
178
179
180MODULE_LICENSE("GPL");
181MODULE_AUTHOR("Sean Young <sean@mess.org>");
182MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU");
183
184module_init(sc520_freq_init);
185module_exit(sc520_freq_exit);
186
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 07d5612dc00f..7dcbf70fc16f 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -54,6 +54,8 @@ enum {
54 CPU_DOTHAN_A1, 54 CPU_DOTHAN_A1,
55 CPU_DOTHAN_A2, 55 CPU_DOTHAN_A2,
56 CPU_DOTHAN_B0, 56 CPU_DOTHAN_B0,
57 CPU_MP4HT_D0,
58 CPU_MP4HT_E0,
57}; 59};
58 60
59static const struct cpu_id cpu_ids[] = { 61static const struct cpu_id cpu_ids[] = {
@@ -61,6 +63,8 @@ static const struct cpu_id cpu_ids[] = {
61 [CPU_DOTHAN_A1] = { 6, 13, 1 }, 63 [CPU_DOTHAN_A1] = { 6, 13, 1 },
62 [CPU_DOTHAN_A2] = { 6, 13, 2 }, 64 [CPU_DOTHAN_A2] = { 6, 13, 2 },
63 [CPU_DOTHAN_B0] = { 6, 13, 6 }, 65 [CPU_DOTHAN_B0] = { 6, 13, 6 },
66 [CPU_MP4HT_D0] = {15, 3, 4 },
67 [CPU_MP4HT_E0] = {15, 4, 1 },
64}; 68};
65#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0])) 69#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0]))
66 70
@@ -226,6 +230,8 @@ static struct cpu_model models[] =
226 { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, 230 { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
227 { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, 231 { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
228 { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL }, 232 { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
233 { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL },
234 { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL },
229 235
230 { NULL, } 236 { NULL, }
231}; 237};
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index 8ba430a9c3a2..d368b3f5fce8 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
336 if (!prev_speed) 336 if (!prev_speed)
337 return -EIO; 337 return -EIO;
338 338
339 dprintk("previous seped is %u\n", prev_speed); 339 dprintk("previous speed is %u\n", prev_speed);
340 340
341 local_irq_save(flags); 341 local_irq_save(flags);
342 342
@@ -348,7 +348,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
348 goto out; 348 goto out;
349 } 349 }
350 350
351 dprintk("low seped is %u\n", *low_speed); 351 dprintk("low speed is %u\n", *low_speed);
352 352
353 /* switch to high state */ 353 /* switch to high state */
354 set_state(SPEEDSTEP_HIGH); 354 set_state(SPEEDSTEP_HIGH);
@@ -358,7 +358,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
358 goto out; 358 goto out;
359 } 359 }
360 360
361 dprintk("high seped is %u\n", *high_speed); 361 dprintk("high speed is %u\n", *high_speed);
362 362
363 if (*low_speed == *high_speed) { 363 if (*low_speed == *high_speed) {
364 ret = -ENODEV; 364 ret = -ENODEV;
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index 79440b3f087e..b25fb6b635ae 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -357,6 +357,9 @@ static int __init speedstep_init(void)
357 case SPEEDSTEP_PROCESSOR_PIII_C: 357 case SPEEDSTEP_PROCESSOR_PIII_C:
358 case SPEEDSTEP_PROCESSOR_PIII_C_EARLY: 358 case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
359 break; 359 break;
360 case SPEEDSTEP_PROCESSOR_P4M:
361 printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n");
362 break;
360 default: 363 default:
361 speedstep_processor = 0; 364 speedstep_processor = 0;
362 } 365 }
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index aeb5b4ef8c8b..a710dc4eb20e 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -118,7 +118,7 @@ struct _cpuid4_info {
118}; 118};
119 119
120#define MAX_CACHE_LEAVES 4 120#define MAX_CACHE_LEAVES 4
121static unsigned short __devinitdata num_cache_leaves; 121static unsigned short num_cache_leaves;
122 122
123static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) 123static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
124{ 124{
diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c
index 933b0dd62f48..9027a987006b 100644
--- a/arch/i386/kernel/cpu/mtrr/cyrix.c
+++ b/arch/i386/kernel/cpu/mtrr/cyrix.c
@@ -218,12 +218,12 @@ typedef struct {
218 mtrr_type type; 218 mtrr_type type;
219} arr_state_t; 219} arr_state_t;
220 220
221static arr_state_t arr_state[8] __initdata = { 221static arr_state_t arr_state[8] __devinitdata = {
222 {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, 222 {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
223 {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL} 223 {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
224}; 224};
225 225
226static unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 }; 226static unsigned char ccr_state[7] __devinitdata = { 0, 0, 0, 0, 0, 0, 0 };
227 227
228static void cyrix_set_all(void) 228static void cyrix_set_all(void)
229{ 229{
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 14ec354bec92..903190a4b3ff 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -169,10 +169,6 @@ EXPORT_SYMBOL(rtc_lock);
169EXPORT_SYMBOL_GPL(set_nmi_callback); 169EXPORT_SYMBOL_GPL(set_nmi_callback);
170EXPORT_SYMBOL_GPL(unset_nmi_callback); 170EXPORT_SYMBOL_GPL(unset_nmi_callback);
171 171
172#undef memcmp
173extern int memcmp(const void *,const void *,__kernel_size_t);
174EXPORT_SYMBOL(memcmp);
175
176EXPORT_SYMBOL(register_die_notifier); 172EXPORT_SYMBOL(register_die_notifier);
177#ifdef CONFIG_HAVE_DEC_LOCK 173#ifdef CONFIG_HAVE_DEC_LOCK
178EXPORT_SYMBOL(_atomic_dec_and_lock); 174EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 671681659243..59ff9b455069 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -217,6 +217,13 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs)
217 *tos &= ~(TF_MASK | IF_MASK); 217 *tos &= ~(TF_MASK | IF_MASK);
218 *tos |= kprobe_old_eflags; 218 *tos |= kprobe_old_eflags;
219 break; 219 break;
220 case 0xc3: /* ret/lret */
221 case 0xcb:
222 case 0xc2:
223 case 0xca:
224 regs->eflags &= ~TF_MASK;
225 /* eip is already adjusted, no more changes required*/
226 return;
220 case 0xe8: /* call relative - Fix return addr */ 227 case 0xe8: /* call relative - Fix return addr */
221 *tos = orig_eip + (*tos - copy_eip); 228 *tos = orig_eip + (*tos - copy_eip);
222 break; 229 break;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 85bd56d44314..96e3ea6b17c7 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -400,11 +400,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
400 int err; 400 int err;
401 401
402 childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; 402 childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
403 *childregs = *regs;
404 childregs->eax = 0;
405 childregs->esp = esp;
406
407 p->thread.esp = (unsigned long) childregs;
408 /* 403 /*
409 * The below -8 is to reserve 8 bytes on top of the ring0 stack. 404 * The below -8 is to reserve 8 bytes on top of the ring0 stack.
410 * This is necessary to guarantee that the entire "struct pt_regs" 405 * This is necessary to guarantee that the entire "struct pt_regs"
@@ -415,7 +410,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
415 * "struct pt_regs" is possible, but they may contain the 410 * "struct pt_regs" is possible, but they may contain the
416 * completely wrong values. 411 * completely wrong values.
417 */ 412 */
418 p->thread.esp0 = (unsigned long) (childregs+1) - 8; 413 childregs = (struct pt_regs *) ((unsigned long) childregs - 8);
414 *childregs = *regs;
415 childregs->eax = 0;
416 childregs->esp = esp;
417
418 p->thread.esp = (unsigned long) childregs;
419 p->thread.esp0 = (unsigned long) (childregs+1);
419 420
420 p->thread.eip = (unsigned long) ret_from_fork; 421 p->thread.eip = (unsigned long) ret_from_fork;
421 422
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 945ec73163c8..2bfbddebdbf8 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -1502,11 +1502,13 @@ void __init setup_arch(char **cmdline_p)
1502 if (efi_enabled) 1502 if (efi_enabled)
1503 efi_map_memmap(); 1503 efi_map_memmap();
1504 1504
1505#ifdef CONFIG_ACPI_BOOT
1505 /* 1506 /*
1506 * Parse the ACPI tables for possible boot-time SMP configuration. 1507 * Parse the ACPI tables for possible boot-time SMP configuration.
1507 */ 1508 */
1508 acpi_boot_table_init(); 1509 acpi_boot_table_init();
1509 acpi_boot_init(); 1510 acpi_boot_init();
1511#endif
1510 1512
1511#ifdef CONFIG_X86_LOCAL_APIC 1513#ifdef CONFIG_X86_LOCAL_APIC
1512 if (smp_found_config) 1514 if (smp_found_config)
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index cbea7ac582e5..bc1bb6919e6a 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -888,6 +888,7 @@ void *xquad_portio;
888 888
889cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; 889cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
890cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; 890cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
891EXPORT_SYMBOL(cpu_core_map);
891 892
892static void __init smp_boot_cpus(unsigned int max_cpus) 893static void __init smp_boot_cpus(unsigned int max_cpus)
893{ 894{
@@ -1073,8 +1074,10 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
1073 cpu_set(cpu, cpu_sibling_map[cpu]); 1074 cpu_set(cpu, cpu_sibling_map[cpu]);
1074 } 1075 }
1075 1076
1076 if (siblings != smp_num_siblings) 1077 if (siblings != smp_num_siblings) {
1077 printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); 1078 printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
1079 smp_num_siblings = siblings;
1080 }
1078 1081
1079 if (c->x86_num_cores > 1) { 1082 if (c->x86_num_cores > 1) {
1080 for (i = 0; i < NR_CPUS; i++) { 1083 for (i = 0; i < NR_CPUS; i++) {
diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c
index f7f90005e22e..8e201219f525 100644
--- a/arch/i386/kernel/timers/common.c
+++ b/arch/i386/kernel/timers/common.c
@@ -6,6 +6,7 @@
6#include <linux/timex.h> 6#include <linux/timex.h>
7#include <linux/errno.h> 7#include <linux/errno.h>
8#include <linux/jiffies.h> 8#include <linux/jiffies.h>
9#include <linux/module.h>
9 10
10#include <asm/io.h> 11#include <asm/io.h>
11#include <asm/timer.h> 12#include <asm/timer.h>
@@ -24,7 +25,7 @@
24 25
25#define CALIBRATE_TIME (5 * 1000020/HZ) 26#define CALIBRATE_TIME (5 * 1000020/HZ)
26 27
27unsigned long __init calibrate_tsc(void) 28unsigned long calibrate_tsc(void)
28{ 29{
29 mach_prepare_counter(); 30 mach_prepare_counter();
30 31
@@ -139,7 +140,7 @@ bad_calibration:
139#endif 140#endif
140 141
141/* calculate cpu_khz */ 142/* calculate cpu_khz */
142void __init init_cpu_khz(void) 143void init_cpu_khz(void)
143{ 144{
144 if (cpu_has_tsc) { 145 if (cpu_has_tsc) {
145 unsigned long tsc_quotient = calibrate_tsc(); 146 unsigned long tsc_quotient = calibrate_tsc();
@@ -158,3 +159,4 @@ void __init init_cpu_khz(void)
158 } 159 }
159 } 160 }
160} 161}
162
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 7926d967be00..180444d87824 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -320,6 +320,26 @@ core_initcall(cpufreq_tsc);
320static inline void cpufreq_delayed_get(void) { return; } 320static inline void cpufreq_delayed_get(void) { return; }
321#endif 321#endif
322 322
323int recalibrate_cpu_khz(void)
324{
325#ifndef CONFIG_SMP
326 unsigned long cpu_khz_old = cpu_khz;
327
328 if (cpu_has_tsc) {
329 init_cpu_khz();
330 cpu_data[0].loops_per_jiffy =
331 cpufreq_scale(cpu_data[0].loops_per_jiffy,
332 cpu_khz_old,
333 cpu_khz);
334 return 0;
335 } else
336 return -ENODEV;
337#else
338 return -ENODEV;
339#endif
340}
341EXPORT_SYMBOL(recalibrate_cpu_khz);
342
323static void mark_offset_tsc(void) 343static void mark_offset_tsc(void)
324{ 344{
325 unsigned long lost,delay; 345 unsigned long lost,delay;
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 903d739ca74a..a6e0ddd65bd0 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -97,7 +97,6 @@ static void ack_vic_irq(unsigned int irq);
97static void vic_enable_cpi(void); 97static void vic_enable_cpi(void);
98static void do_boot_cpu(__u8 cpuid); 98static void do_boot_cpu(__u8 cpuid);
99static void do_quad_bootstrap(void); 99static void do_quad_bootstrap(void);
100static inline void wrapper_smp_local_timer_interrupt(struct pt_regs *);
101 100
102int hard_smp_processor_id(void); 101int hard_smp_processor_id(void);
103 102
@@ -126,6 +125,14 @@ send_QIC_CPI(__u32 cpuset, __u8 cpi)
126} 125}
127 126
128static inline void 127static inline void
128wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
129{
130 irq_enter();
131 smp_local_timer_interrupt(regs);
132 irq_exit();
133}
134
135static inline void
129send_one_CPI(__u8 cpu, __u8 cpi) 136send_one_CPI(__u8 cpu, __u8 cpi)
130{ 137{
131 if(voyager_quad_processors & (1<<cpu)) 138 if(voyager_quad_processors & (1<<cpu))
@@ -1249,14 +1256,6 @@ smp_vic_timer_interrupt(struct pt_regs *regs)
1249 smp_local_timer_interrupt(regs); 1256 smp_local_timer_interrupt(regs);
1250} 1257}
1251 1258
1252static inline void
1253wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
1254{
1255 irq_enter();
1256 smp_local_timer_interrupt(regs);
1257 irq_exit();
1258}
1259
1260/* local (per CPU) timer interrupt. It does both profiling and 1259/* local (per CPU) timer interrupt. It does both profiling and
1261 * process statistics/rescheduling. 1260 * process statistics/rescheduling.
1262 * 1261 *
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index db06f7399913..ab542792b27b 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -238,19 +238,21 @@ void iounmap(volatile void __iomem *addr)
238 addr < phys_to_virt(ISA_END_ADDRESS)) 238 addr < phys_to_virt(ISA_END_ADDRESS))
239 return; 239 return;
240 240
241 p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr)); 241 write_lock(&vmlist_lock);
242 p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
242 if (!p) { 243 if (!p) {
243 printk("__iounmap: bad address %p\n", addr); 244 printk("iounmap: bad address %p\n", addr);
244 return; 245 goto out_unlock;
245 } 246 }
246 247
247 if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) { 248 if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
248 /* p->size includes the guard page, but cpa doesn't like that */
249 change_page_attr(virt_to_page(__va(p->phys_addr)), 249 change_page_attr(virt_to_page(__va(p->phys_addr)),
250 p->size >> PAGE_SHIFT, 250 p->size >> PAGE_SHIFT,
251 PAGE_KERNEL); 251 PAGE_KERNEL);
252 global_flush_tlb(); 252 global_flush_tlb();
253 } 253 }
254out_unlock:
255 write_unlock(&vmlist_lock);
254 kfree(p); 256 kfree(p);
255} 257}
256 258
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index be52c5ac4e05..8e8e895e1b5a 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci
253#define MAX_PCIEROOT 6 253#define MAX_PCIEROOT 6
254static int quirk_aspm_offset[MAX_PCIEROOT << 3]; 254static int quirk_aspm_offset[MAX_PCIEROOT << 3];
255 255
256#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b) 256#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))
257 257
258static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) 258static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
259{ 259{
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index d6598da4b67b..da21b1d07c15 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -1029,7 +1029,6 @@ void pcibios_penalize_isa_irq(int irq)
1029static int pirq_enable_irq(struct pci_dev *dev) 1029static int pirq_enable_irq(struct pci_dev *dev)
1030{ 1030{
1031 u8 pin; 1031 u8 pin;
1032 extern int via_interrupt_line_quirk;
1033 struct pci_dev *temp_dev; 1032 struct pci_dev *temp_dev;
1034 1033
1035 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); 1034 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
@@ -1084,10 +1083,6 @@ static int pirq_enable_irq(struct pci_dev *dev)
1084 printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 1083 printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
1085 'A' + pin, pci_name(dev), msg); 1084 'A' + pin, pci_name(dev), msg);
1086 } 1085 }
1087 /* VIA bridges use interrupt line for apic/pci steering across
1088 the V-Link */
1089 else if (via_interrupt_line_quirk)
1090 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15);
1091 return 0; 1086 return 0;
1092} 1087}
1093 1088
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index ce13ad689d19..3ad2c4af099c 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -46,6 +46,10 @@ config GENERIC_IOMAP
46 bool 46 bool
47 default y 47 default y
48 48
49config SCHED_NO_NO_OMIT_FRAME_POINTER
50 bool
51 default y
52
49choice 53choice
50 prompt "System type" 54 prompt "System type"
51 default IA64_GENERIC 55 default IA64_GENERIC
diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
index 9845dabe2613..164b211f4174 100644
--- a/arch/ia64/ia32/ia32_ioctl.c
+++ b/arch/ia64/ia32/ia32_ioctl.c
@@ -13,7 +13,6 @@
13 13
14#define INCLUDES 14#define INCLUDES
15#include "compat_ioctl.c" 15#include "compat_ioctl.c"
16#include <asm/ioctl32.h>
17 16
18#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) 17#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
19 18
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 247a21c64aea..c1e20d65dd6c 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
2427{ 2427{
2428 struct epoll_event *events64 = NULL; 2428 struct epoll_event *events64 = NULL;
2429 mm_segment_t old_fs = get_fs(); 2429 mm_segment_t old_fs = get_fs();
2430 int error, numevents, size; 2430 int numevents, size;
2431 int evt_idx; 2431 int evt_idx;
2432 int do_free_pages = 0; 2432 int do_free_pages = 0;
2433 2433
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 81c45d447394..d99316c9be28 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1182,7 +1182,7 @@ ENTRY(notify_resume_user)
1182 ;; 1182 ;;
1183(pNonSys) mov out2=0 // out2==0 => not a syscall 1183(pNonSys) mov out2=0 // out2==0 => not a syscall
1184 .fframe 16 1184 .fframe 16
1185 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) 1185 .spillsp ar.unat, 16
1186 st8 [sp]=r9,-16 // allocate space for ar.unat and save it 1186 st8 [sp]=r9,-16 // allocate space for ar.unat and save it
1187 st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch 1187 st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch
1188 .body 1188 .body
@@ -1208,7 +1208,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend)
1208 adds out2=8,sp // out2=&sigscratch->ar_pfs 1208 adds out2=8,sp // out2=&sigscratch->ar_pfs
1209 ;; 1209 ;;
1210 .fframe 16 1210 .fframe 16
1211 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) 1211 .spillsp ar.unat, 16
1212 st8 [sp]=r9,-16 // allocate space for ar.unat and save it 1212 st8 [sp]=r9,-16 // allocate space for ar.unat and save it
1213 st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch 1213 st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
1214 .body 1214 .body
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 4d6c7b8f667b..736e328b5e61 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
1103 return IRQ_HANDLED; 1103 return IRQ_HANDLED;
1104} 1104}
1105 1105
1106#endif /* CONFIG_ACPI */
1107
1108/* 1106/*
1109 * ia64_mca_cpe_poll 1107 * ia64_mca_cpe_poll
1110 * 1108 *
@@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy)
1122 platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); 1120 platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
1123} 1121}
1124 1122
1123#endif /* CONFIG_ACPI */
1124
1125/* 1125/*
1126 * C portion of the OS INIT handler 1126 * C portion of the OS INIT handler
1127 * 1127 *
@@ -1390,8 +1390,7 @@ ia64_mca_init(void)
1390 register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); 1390 register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
1391 1391
1392#ifdef CONFIG_ACPI 1392#ifdef CONFIG_ACPI
1393 /* Setup the CPEI/P vector and handler */ 1393 /* Setup the CPEI/P handler */
1394 cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
1395 register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); 1394 register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
1396#endif 1395#endif
1397 1396
@@ -1436,6 +1435,7 @@ ia64_mca_late_init(void)
1436 1435
1437#ifdef CONFIG_ACPI 1436#ifdef CONFIG_ACPI
1438 /* Setup the CPEI/P vector and handler */ 1437 /* Setup the CPEI/P vector and handler */
1438 cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
1439 init_timer(&cpe_poll_timer); 1439 init_timer(&cpe_poll_timer);
1440 cpe_poll_timer.function = ia64_mca_cpe_poll; 1440 cpe_poll_timer.function = ia64_mca_cpe_poll;
1441 1441
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index 1dbc7b2497c9..f6d8a010d99b 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -41,7 +41,7 @@
41(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \ 41(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \
42(pKStk) ld8 r3 = [r3];; \ 42(pKStk) ld8 r3 = [r3];; \
43(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \ 43(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \
44(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \ 44(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
45(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ 45(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
46(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ 46(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \
47 ;; \ 47 ;; \
@@ -50,7 +50,6 @@
50(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ 50(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
51(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \ 51(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \
52 ;; \ 52 ;; \
53(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
54(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ 53(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
55 ;; \ 54 ;; \
56(pUStk) mov r18=ar.bsp; \ 55(pUStk) mov r18=ar.bsp; \
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 71c101601e3e..6407bff6bfd7 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -11,7 +11,7 @@
11 * Version Perfmon-2.x is a rewrite of perfmon-1.x 11 * Version Perfmon-2.x is a rewrite of perfmon-1.x
12 * by Stephane Eranian, Hewlett Packard Co. 12 * by Stephane Eranian, Hewlett Packard Co.
13 * 13 *
14 * Copyright (C) 1999-2003, 2005 Hewlett Packard Co 14 * Copyright (C) 1999-2005 Hewlett Packard Co
15 * Stephane Eranian <eranian@hpl.hp.com> 15 * Stephane Eranian <eranian@hpl.hp.com>
16 * David Mosberger-Tang <davidm@hpl.hp.com> 16 * David Mosberger-Tang <davidm@hpl.hp.com>
17 * 17 *
@@ -497,6 +497,9 @@ typedef struct {
497static pfm_stats_t pfm_stats[NR_CPUS]; 497static pfm_stats_t pfm_stats[NR_CPUS];
498static pfm_session_t pfm_sessions; /* global sessions information */ 498static pfm_session_t pfm_sessions; /* global sessions information */
499 499
500static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED;
501static pfm_intr_handler_desc_t *pfm_alt_intr_handler;
502
500static struct proc_dir_entry *perfmon_dir; 503static struct proc_dir_entry *perfmon_dir;
501static pfm_uuid_t pfm_null_uuid = {0,}; 504static pfm_uuid_t pfm_null_uuid = {0,};
502 505
@@ -606,6 +609,7 @@ DEFINE_PER_CPU(unsigned long, pfm_syst_info);
606DEFINE_PER_CPU(struct task_struct *, pmu_owner); 609DEFINE_PER_CPU(struct task_struct *, pmu_owner);
607DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); 610DEFINE_PER_CPU(pfm_context_t *, pmu_ctx);
608DEFINE_PER_CPU(unsigned long, pmu_activation_number); 611DEFINE_PER_CPU(unsigned long, pmu_activation_number);
612EXPORT_PER_CPU_SYMBOL_GPL(pfm_syst_info);
609 613
610 614
611/* forward declaration */ 615/* forward declaration */
@@ -1325,7 +1329,7 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
1325error_conflict: 1329error_conflict:
1326 DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n", 1330 DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n",
1327 pfm_sessions.pfs_sys_session[cpu]->pid, 1331 pfm_sessions.pfs_sys_session[cpu]->pid,
1328 smp_processor_id())); 1332 cpu));
1329abort: 1333abort:
1330 UNLOCK_PFS(flags); 1334 UNLOCK_PFS(flags);
1331 1335
@@ -5555,26 +5559,32 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
5555 int ret; 5559 int ret;
5556 5560
5557 this_cpu = get_cpu(); 5561 this_cpu = get_cpu();
5558 min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min; 5562 if (likely(!pfm_alt_intr_handler)) {
5559 max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max; 5563 min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
5564 max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
5560 5565
5561 start_cycles = ia64_get_itc(); 5566 start_cycles = ia64_get_itc();
5562 5567
5563 ret = pfm_do_interrupt_handler(irq, arg, regs); 5568 ret = pfm_do_interrupt_handler(irq, arg, regs);
5564 5569
5565 total_cycles = ia64_get_itc(); 5570 total_cycles = ia64_get_itc();
5566 5571
5567 /* 5572 /*
5568 * don't measure spurious interrupts 5573 * don't measure spurious interrupts
5569 */ 5574 */
5570 if (likely(ret == 0)) { 5575 if (likely(ret == 0)) {
5571 total_cycles -= start_cycles; 5576 total_cycles -= start_cycles;
5572 5577
5573 if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles; 5578 if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles;
5574 if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles; 5579 if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles;
5575 5580
5576 pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles; 5581 pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
5582 }
5583 }
5584 else {
5585 (*pfm_alt_intr_handler->handler)(irq, arg, regs);
5577 } 5586 }
5587
5578 put_cpu_no_resched(); 5588 put_cpu_no_resched();
5579 return IRQ_HANDLED; 5589 return IRQ_HANDLED;
5580} 5590}
@@ -6425,6 +6435,141 @@ static struct irqaction perfmon_irqaction = {
6425 .name = "perfmon" 6435 .name = "perfmon"
6426}; 6436};
6427 6437
6438static void
6439pfm_alt_save_pmu_state(void *data)
6440{
6441 struct pt_regs *regs;
6442
6443 regs = ia64_task_regs(current);
6444
6445 DPRINT(("called\n"));
6446
6447 /*
6448 * should not be necessary but
6449 * let's take not risk
6450 */
6451 pfm_clear_psr_up();
6452 pfm_clear_psr_pp();
6453 ia64_psr(regs)->pp = 0;
6454
6455 /*
6456 * This call is required
6457 * May cause a spurious interrupt on some processors
6458 */
6459 pfm_freeze_pmu();
6460
6461 ia64_srlz_d();
6462}
6463
6464void
6465pfm_alt_restore_pmu_state(void *data)
6466{
6467 struct pt_regs *regs;
6468
6469 regs = ia64_task_regs(current);
6470
6471 DPRINT(("called\n"));
6472
6473 /*
6474 * put PMU back in state expected
6475 * by perfmon
6476 */
6477 pfm_clear_psr_up();
6478 pfm_clear_psr_pp();
6479 ia64_psr(regs)->pp = 0;
6480
6481 /*
6482 * perfmon runs with PMU unfrozen at all times
6483 */
6484 pfm_unfreeze_pmu();
6485
6486 ia64_srlz_d();
6487}
6488
6489int
6490pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
6491{
6492 int ret, i;
6493 int reserve_cpu;
6494
6495 /* some sanity checks */
6496 if (hdl == NULL || hdl->handler == NULL) return -EINVAL;
6497
6498 /* do the easy test first */
6499 if (pfm_alt_intr_handler) return -EBUSY;
6500
6501 /* one at a time in the install or remove, just fail the others */
6502 if (!spin_trylock(&pfm_alt_install_check)) {
6503 return -EBUSY;
6504 }
6505
6506 /* reserve our session */
6507 for_each_online_cpu(reserve_cpu) {
6508 ret = pfm_reserve_session(NULL, 1, reserve_cpu);
6509 if (ret) goto cleanup_reserve;
6510 }
6511
6512 /* save the current system wide pmu states */
6513 ret = on_each_cpu(pfm_alt_save_pmu_state, NULL, 0, 1);
6514 if (ret) {
6515 DPRINT(("on_each_cpu() failed: %d\n", ret));
6516 goto cleanup_reserve;
6517 }
6518
6519 /* officially change to the alternate interrupt handler */
6520 pfm_alt_intr_handler = hdl;
6521
6522 spin_unlock(&pfm_alt_install_check);
6523
6524 return 0;
6525
6526cleanup_reserve:
6527 for_each_online_cpu(i) {
6528 /* don't unreserve more than we reserved */
6529 if (i >= reserve_cpu) break;
6530
6531 pfm_unreserve_session(NULL, 1, i);
6532 }
6533
6534 spin_unlock(&pfm_alt_install_check);
6535
6536 return ret;
6537}
6538EXPORT_SYMBOL_GPL(pfm_install_alt_pmu_interrupt);
6539
6540int
6541pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
6542{
6543 int i;
6544 int ret;
6545
6546 if (hdl == NULL) return -EINVAL;
6547
6548 /* cannot remove someone else's handler! */
6549 if (pfm_alt_intr_handler != hdl) return -EINVAL;
6550
6551 /* one at a time in the install or remove, just fail the others */
6552 if (!spin_trylock(&pfm_alt_install_check)) {
6553 return -EBUSY;
6554 }
6555
6556 pfm_alt_intr_handler = NULL;
6557
6558 ret = on_each_cpu(pfm_alt_restore_pmu_state, NULL, 0, 1);
6559 if (ret) {
6560 DPRINT(("on_each_cpu() failed: %d\n", ret));
6561 }
6562
6563 for_each_online_cpu(i) {
6564 pfm_unreserve_session(NULL, 1, i);
6565 }
6566
6567 spin_unlock(&pfm_alt_install_check);
6568
6569 return 0;
6570}
6571EXPORT_SYMBOL_GPL(pfm_remove_alt_pmu_interrupt);
6572
6428/* 6573/*
6429 * perfmon initialization routine, called from the initcall() table 6574 * perfmon initialization routine, called from the initcall() table
6430 */ 6575 */
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 907464ee7273..08c8a5eb25ab 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -692,16 +692,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt,
692 unsigned long cfm) 692 unsigned long cfm)
693{ 693{
694 struct unw_frame_info info, prev_info; 694 struct unw_frame_info info, prev_info;
695 unsigned long ip, pr; 695 unsigned long ip, sp, pr;
696 696
697 unw_init_from_blocked_task(&info, child); 697 unw_init_from_blocked_task(&info, child);
698 while (1) { 698 while (1) {
699 prev_info = info; 699 prev_info = info;
700 if (unw_unwind(&info) < 0) 700 if (unw_unwind(&info) < 0)
701 return; 701 return;
702 if (unw_get_rp(&info, &ip) < 0) 702
703 unw_get_sp(&info, &sp);
704 if ((long)((unsigned long)child + IA64_STK_OFFSET - sp)
705 < IA64_PT_REGS_SIZE) {
706 dprintk("ptrace.%s: ran off the top of the kernel "
707 "stack\n", __FUNCTION__);
708 return;
709 }
710 if (unw_get_pr (&prev_info, &pr) < 0) {
711 unw_get_rp(&prev_info, &ip);
712 dprintk("ptrace.%s: failed to read "
713 "predicate register (ip=0x%lx)\n",
714 __FUNCTION__, ip);
703 return; 715 return;
704 if (ip < FIXADDR_USER_END) 716 }
717 if (unw_is_intr_frame(&info)
718 && (pr & (1UL << PRED_USER_STACK)))
705 break; 719 break;
706 } 720 }
707 721
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 0d5ee57c9865..3865f088ffa2 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -624,7 +624,7 @@ static struct {
624 __u16 thread_id; 624 __u16 thread_id;
625 __u16 proc_fixed_addr; 625 __u16 proc_fixed_addr;
626 __u8 valid; 626 __u8 valid;
627}mt_info[NR_CPUS] __devinit; 627} mt_info[NR_CPUS] __devinitdata;
628 628
629#ifdef CONFIG_HOTPLUG_CPU 629#ifdef CONFIG_HOTPLUG_CPU
630static inline void 630static inline void
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index a8cf6d8a509c..770fab37928e 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -182,13 +182,6 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un
182 } 182 }
183 } 183 }
184 184
185 /*
186 * A zero mmap always succeeds in Linux, independent of whether or not the
187 * remaining arguments are valid.
188 */
189 if (len == 0)
190 goto out;
191
192 /* Careful about overflows.. */ 185 /* Careful about overflows.. */
193 len = PAGE_ALIGN(len); 186 len = PAGE_ALIGN(len);
194 if (!len || len > TASK_SIZE) { 187 if (!len || len > TASK_SIZE) {
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 4fb44984afe6..e64cb8175f7a 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -271,6 +271,8 @@ void __init sn_setup(char **cmdline_p)
271 int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); 271 int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
272 extern void sn_cpu_init(void); 272 extern void sn_cpu_init(void);
273 273
274 ia64_sn_plat_set_error_handling_features();
275
274 /* 276 /*
275 * If the generic code has enabled vga console support - lets 277 * If the generic code has enabled vga console support - lets
276 * get rid of it again. This is a kludge for the fact that ACPI 278 * get rid of it again. This is a kludge for the fact that ACPI
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
index c5f1043de938..53166f3598b2 100644
--- a/arch/mips/vr41xx/common/pmu.c
+++ b/arch/mips/vr41xx/common/pmu.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * pmu.c, Power Management Unit routines for NEC VR4100 series. 2 * pmu.c, Power Management Unit routines for NEC VR4100 series.
3 * 3 *
4 * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp> 4 * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -17,7 +17,9 @@
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
20#include <linux/errno.h>
20#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/ioport.h>
21#include <linux/kernel.h> 23#include <linux/kernel.h>
22#include <linux/smp.h> 24#include <linux/smp.h>
23#include <linux/types.h> 25#include <linux/types.h>
@@ -27,20 +29,31 @@
27#include <asm/reboot.h> 29#include <asm/reboot.h>
28#include <asm/system.h> 30#include <asm/system.h>
29 31
30#define PMUCNT2REG KSEG1ADDR(0x0f0000c6) 32#define PMU_TYPE1_BASE 0x0b0000a0UL
33#define PMU_TYPE1_SIZE 0x0eUL
34
35#define PMU_TYPE2_BASE 0x0f0000c0UL
36#define PMU_TYPE2_SIZE 0x10UL
37
38#define PMUCNT2REG 0x06
31 #define SOFTRST 0x0010 39 #define SOFTRST 0x0010
32 40
41static void __iomem *pmu_base;
42
43#define pmu_read(offset) readw(pmu_base + (offset))
44#define pmu_write(offset, value) writew((value), pmu_base + (offset))
45
33static inline void software_reset(void) 46static inline void software_reset(void)
34{ 47{
35 uint16_t val; 48 uint16_t pmucnt2;
36 49
37 switch (current_cpu_data.cputype) { 50 switch (current_cpu_data.cputype) {
38 case CPU_VR4122: 51 case CPU_VR4122:
39 case CPU_VR4131: 52 case CPU_VR4131:
40 case CPU_VR4133: 53 case CPU_VR4133:
41 val = readw(PMUCNT2REG); 54 pmucnt2 = pmu_read(PMUCNT2REG);
42 val |= SOFTRST; 55 pmucnt2 |= SOFTRST;
43 writew(val, PMUCNT2REG); 56 pmu_write(PMUCNT2REG, pmucnt2);
44 break; 57 break;
45 default: 58 default:
46 break; 59 break;
@@ -71,6 +84,34 @@ static void vr41xx_power_off(void)
71 84
72static int __init vr41xx_pmu_init(void) 85static int __init vr41xx_pmu_init(void)
73{ 86{
87 unsigned long start, size;
88
89 switch (current_cpu_data.cputype) {
90 case CPU_VR4111:
91 case CPU_VR4121:
92 start = PMU_TYPE1_BASE;
93 size = PMU_TYPE1_SIZE;
94 break;
95 case CPU_VR4122:
96 case CPU_VR4131:
97 case CPU_VR4133:
98 start = PMU_TYPE2_BASE;
99 size = PMU_TYPE2_SIZE;
100 break;
101 default:
102 printk("Unexpected CPU of NEC VR4100 series\n");
103 return -ENODEV;
104 }
105
106 if (request_mem_region(start, size, "PMU") == NULL)
107 return -EBUSY;
108
109 pmu_base = ioremap(start, size);
110 if (pmu_base == NULL) {
111 release_mem_region(start, size);
112 return -EBUSY;
113 }
114
74 _machine_restart = vr41xx_restart; 115 _machine_restart = vr41xx_restart;
75 _machine_halt = vr41xx_halt; 116 _machine_halt = vr41xx_halt;
76 _machine_power_off = vr41xx_power_off; 117 _machine_power_off = vr41xx_power_off;
@@ -78,4 +119,4 @@ static int __init vr41xx_pmu_init(void)
78 return 0; 119 return 0;
79} 120}
80 121
81early_initcall(vr41xx_pmu_init); 122core_initcall(vr41xx_pmu_init);
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index ff04dcd30200..6e6377a69d5b 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -43,6 +43,10 @@ config GENERIC_NVRAM
43 bool 43 bool
44 default y 44 default y
45 45
46config SCHED_NO_NO_OMIT_FRAME_POINTER
47 bool
48 default y
49
46source "init/Kconfig" 50source "init/Kconfig"
47 51
48menu "Processor" 52menu "Processor"
@@ -73,9 +77,11 @@ config 44x
73 bool "44x" 77 bool "44x"
74 78
75config POWER3 79config POWER3
80 select PPC_FPU
76 bool "POWER3" 81 bool "POWER3"
77 82
78config POWER4 83config POWER4
84 select PPC_FPU
79 bool "POWER4 and 970 (G5)" 85 bool "POWER4 and 970 (G5)"
80 86
81config 8xx 87config 8xx
@@ -1137,12 +1143,12 @@ config PCI_QSPAN
1137 1143
1138config PCI_8260 1144config PCI_8260
1139 bool 1145 bool
1140 depends on PCI && 8260 && !8272 1146 depends on PCI && 8260
1141 default y 1147 default y
1142 1148
1143config 8260_PCI9 1149config 8260_PCI9
1144 bool " Enable workaround for MPC826x erratum PCI 9" 1150 bool " Enable workaround for MPC826x erratum PCI 9"
1145 depends on PCI_8260 1151 depends on PCI_8260 && !ADS8272
1146 default y 1152 default y
1147 1153
1148choice 1154choice
diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
index f850fb0fb511..c9ac5f5fa9e4 100644
--- a/arch/ppc/boot/images/Makefile
+++ b/arch/ppc/boot/images/Makefile
@@ -22,7 +22,8 @@ targets += uImage
22$(obj)/uImage: $(obj)/vmlinux.gz 22$(obj)/uImage: $(obj)/vmlinux.gz
23 $(Q)rm -f $@ 23 $(Q)rm -f $@
24 $(call if_changed,uimage) 24 $(call if_changed,uimage)
25 @echo ' Image: $@' $(if $(wildcard $@),'is ready','not made') 25 @echo -n ' Image: $@ '
26 @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
26 27
27# Files generated that shall be removed upon make clean 28# Files generated that shall be removed upon make clean
28clean-files := sImage vmapus vmlinux* miboot* zImage* uImage 29clean-files := sImage vmapus vmlinux* miboot* zImage* uImage
diff --git a/arch/ppc/configs/mpc8555_cds_defconfig b/arch/ppc/configs/mpc8555_cds_defconfig
index 728bd9e1a8fa..15abebf46b96 100644
--- a/arch/ppc/configs/mpc8555_cds_defconfig
+++ b/arch/ppc/configs/mpc8555_cds_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.11-rc1 3# Linux kernel version: 2.6.12-rc4
4# Thu Jan 20 01:25:35 2005 4# Tue May 17 11:56:01 2005
5# 5#
6CONFIG_MMU=y 6CONFIG_MMU=y
7CONFIG_GENERIC_HARDIRQS=y 7CONFIG_GENERIC_HARDIRQS=y
@@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y
11CONFIG_PPC=y 11CONFIG_PPC=y
12CONFIG_PPC32=y 12CONFIG_PPC32=y
13CONFIG_GENERIC_NVRAM=y 13CONFIG_GENERIC_NVRAM=y
14CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
14 15
15# 16#
16# Code maturity level options 17# Code maturity level options
@@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y
18CONFIG_EXPERIMENTAL=y 19CONFIG_EXPERIMENTAL=y
19CONFIG_CLEAN_COMPILE=y 20CONFIG_CLEAN_COMPILE=y
20CONFIG_BROKEN_ON_SMP=y 21CONFIG_BROKEN_ON_SMP=y
22CONFIG_INIT_ENV_ARG_LIMIT=32
21 23
22# 24#
23# General setup 25# General setup
@@ -29,12 +31,14 @@ CONFIG_SYSVIPC=y
29# CONFIG_BSD_PROCESS_ACCT is not set 31# CONFIG_BSD_PROCESS_ACCT is not set
30CONFIG_SYSCTL=y 32CONFIG_SYSCTL=y
31# CONFIG_AUDIT is not set 33# CONFIG_AUDIT is not set
32CONFIG_LOG_BUF_SHIFT=14
33# CONFIG_HOTPLUG is not set 34# CONFIG_HOTPLUG is not set
34CONFIG_KOBJECT_UEVENT=y 35CONFIG_KOBJECT_UEVENT=y
35# CONFIG_IKCONFIG is not set 36# CONFIG_IKCONFIG is not set
36CONFIG_EMBEDDED=y 37CONFIG_EMBEDDED=y
37# CONFIG_KALLSYMS is not set 38# CONFIG_KALLSYMS is not set
39CONFIG_PRINTK=y
40CONFIG_BUG=y
41CONFIG_BASE_FULL=y
38CONFIG_FUTEX=y 42CONFIG_FUTEX=y
39# CONFIG_EPOLL is not set 43# CONFIG_EPOLL is not set
40# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 44# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +48,7 @@ CONFIG_CC_ALIGN_LABELS=0
44CONFIG_CC_ALIGN_LOOPS=0 48CONFIG_CC_ALIGN_LOOPS=0
45CONFIG_CC_ALIGN_JUMPS=0 49CONFIG_CC_ALIGN_JUMPS=0
46# CONFIG_TINY_SHMEM is not set 50# CONFIG_TINY_SHMEM is not set
51CONFIG_BASE_SMALL=0
47 52
48# 53#
49# Loadable module support 54# Loadable module support
@@ -62,10 +67,12 @@ CONFIG_CC_ALIGN_JUMPS=0
62CONFIG_E500=y 67CONFIG_E500=y
63CONFIG_BOOKE=y 68CONFIG_BOOKE=y
64CONFIG_FSL_BOOKE=y 69CONFIG_FSL_BOOKE=y
70# CONFIG_PHYS_64BIT is not set
65CONFIG_SPE=y 71CONFIG_SPE=y
66CONFIG_MATH_EMULATION=y 72CONFIG_MATH_EMULATION=y
67# CONFIG_CPU_FREQ is not set 73# CONFIG_CPU_FREQ is not set
68CONFIG_PPC_GEN550=y 74CONFIG_PPC_GEN550=y
75# CONFIG_PM is not set
69CONFIG_85xx=y 76CONFIG_85xx=y
70CONFIG_PPC_INDIRECT_PCI_BE=y 77CONFIG_PPC_INDIRECT_PCI_BE=y
71 78
@@ -76,6 +83,7 @@ CONFIG_PPC_INDIRECT_PCI_BE=y
76CONFIG_MPC8555_CDS=y 83CONFIG_MPC8555_CDS=y
77# CONFIG_MPC8560_ADS is not set 84# CONFIG_MPC8560_ADS is not set
78# CONFIG_SBC8560 is not set 85# CONFIG_SBC8560 is not set
86# CONFIG_STX_GP3 is not set
79CONFIG_MPC8555=y 87CONFIG_MPC8555=y
80CONFIG_85xx_PCI2=y 88CONFIG_85xx_PCI2=y
81 89
@@ -90,6 +98,7 @@ CONFIG_CPM2=y
90CONFIG_BINFMT_ELF=y 98CONFIG_BINFMT_ELF=y
91# CONFIG_BINFMT_MISC is not set 99# CONFIG_BINFMT_MISC is not set
92# CONFIG_CMDLINE_BOOL is not set 100# CONFIG_CMDLINE_BOOL is not set
101CONFIG_ISA_DMA_API=y
93 102
94# 103#
95# Bus options 104# Bus options
@@ -105,10 +114,6 @@ CONFIG_PCI_NAMES=y
105# CONFIG_PCCARD is not set 114# CONFIG_PCCARD is not set
106 115
107# 116#
108# PC-card bridges
109#
110
111#
112# Advanced setup 117# Advanced setup
113# 118#
114# CONFIG_ADVANCED_OPTIONS is not set 119# CONFIG_ADVANCED_OPTIONS is not set
@@ -180,7 +185,59 @@ CONFIG_IOSCHED_CFQ=y
180# 185#
181# ATA/ATAPI/MFM/RLL support 186# ATA/ATAPI/MFM/RLL support
182# 187#
183# CONFIG_IDE is not set 188CONFIG_IDE=y
189CONFIG_BLK_DEV_IDE=y
190
191#
192# Please see Documentation/ide.txt for help/info on IDE drives
193#
194# CONFIG_BLK_DEV_IDE_SATA is not set
195CONFIG_BLK_DEV_IDEDISK=y
196# CONFIG_IDEDISK_MULTI_MODE is not set
197# CONFIG_BLK_DEV_IDECD is not set
198# CONFIG_BLK_DEV_IDETAPE is not set
199# CONFIG_BLK_DEV_IDEFLOPPY is not set
200# CONFIG_IDE_TASK_IOCTL is not set
201
202#
203# IDE chipset support/bugfixes
204#
205CONFIG_IDE_GENERIC=y
206CONFIG_BLK_DEV_IDEPCI=y
207CONFIG_IDEPCI_SHARE_IRQ=y
208# CONFIG_BLK_DEV_OFFBOARD is not set
209CONFIG_BLK_DEV_GENERIC=y
210# CONFIG_BLK_DEV_OPTI621 is not set
211# CONFIG_BLK_DEV_SL82C105 is not set
212CONFIG_BLK_DEV_IDEDMA_PCI=y
213# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
214CONFIG_IDEDMA_PCI_AUTO=y
215# CONFIG_IDEDMA_ONLYDISK is not set
216# CONFIG_BLK_DEV_AEC62XX is not set
217# CONFIG_BLK_DEV_ALI15X3 is not set
218# CONFIG_BLK_DEV_AMD74XX is not set
219# CONFIG_BLK_DEV_CMD64X is not set
220# CONFIG_BLK_DEV_TRIFLEX is not set
221# CONFIG_BLK_DEV_CY82C693 is not set
222# CONFIG_BLK_DEV_CS5520 is not set
223# CONFIG_BLK_DEV_CS5530 is not set
224# CONFIG_BLK_DEV_HPT34X is not set
225# CONFIG_BLK_DEV_HPT366 is not set
226# CONFIG_BLK_DEV_SC1200 is not set
227# CONFIG_BLK_DEV_PIIX is not set
228# CONFIG_BLK_DEV_NS87415 is not set
229# CONFIG_BLK_DEV_PDC202XX_OLD is not set
230# CONFIG_BLK_DEV_PDC202XX_NEW is not set
231# CONFIG_BLK_DEV_SVWKS is not set
232# CONFIG_BLK_DEV_SIIMAGE is not set
233# CONFIG_BLK_DEV_SLC90E66 is not set
234# CONFIG_BLK_DEV_TRM290 is not set
235CONFIG_BLK_DEV_VIA82CXXX=y
236# CONFIG_IDE_ARM is not set
237CONFIG_BLK_DEV_IDEDMA=y
238# CONFIG_IDEDMA_IVB is not set
239CONFIG_IDEDMA_AUTO=y
240# CONFIG_BLK_DEV_HD is not set
184 241
185# 242#
186# SCSI device support 243# SCSI device support
@@ -220,7 +277,6 @@ CONFIG_NET=y
220# 277#
221CONFIG_PACKET=y 278CONFIG_PACKET=y
222# CONFIG_PACKET_MMAP is not set 279# CONFIG_PACKET_MMAP is not set
223# CONFIG_NETLINK_DEV is not set
224CONFIG_UNIX=y 280CONFIG_UNIX=y
225# CONFIG_NET_KEY is not set 281# CONFIG_NET_KEY is not set
226CONFIG_INET=y 282CONFIG_INET=y
@@ -370,14 +426,6 @@ CONFIG_INPUT=y
370# CONFIG_INPUT_EVBUG is not set 426# CONFIG_INPUT_EVBUG is not set
371 427
372# 428#
373# Input I/O drivers
374#
375# CONFIG_GAMEPORT is not set
376CONFIG_SOUND_GAMEPORT=y
377# CONFIG_SERIO is not set
378# CONFIG_SERIO_I8042 is not set
379
380#
381# Input Device Drivers 429# Input Device Drivers
382# 430#
383# CONFIG_INPUT_KEYBOARD is not set 431# CONFIG_INPUT_KEYBOARD is not set
@@ -387,6 +435,13 @@ CONFIG_SOUND_GAMEPORT=y
387# CONFIG_INPUT_MISC is not set 435# CONFIG_INPUT_MISC is not set
388 436
389# 437#
438# Hardware I/O ports
439#
440# CONFIG_SERIO is not set
441# CONFIG_GAMEPORT is not set
442CONFIG_SOUND_GAMEPORT=y
443
444#
390# Character devices 445# Character devices
391# 446#
392# CONFIG_VT is not set 447# CONFIG_VT is not set
@@ -406,6 +461,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
406CONFIG_SERIAL_CORE=y 461CONFIG_SERIAL_CORE=y
407CONFIG_SERIAL_CORE_CONSOLE=y 462CONFIG_SERIAL_CORE_CONSOLE=y
408# CONFIG_SERIAL_CPM is not set 463# CONFIG_SERIAL_CPM is not set
464# CONFIG_SERIAL_JSM is not set
409CONFIG_UNIX98_PTYS=y 465CONFIG_UNIX98_PTYS=y
410CONFIG_LEGACY_PTYS=y 466CONFIG_LEGACY_PTYS=y
411CONFIG_LEGACY_PTY_COUNT=256 467CONFIG_LEGACY_PTY_COUNT=256
@@ -434,6 +490,11 @@ CONFIG_GEN_RTC=y
434# CONFIG_RAW_DRIVER is not set 490# CONFIG_RAW_DRIVER is not set
435 491
436# 492#
493# TPM devices
494#
495# CONFIG_TCG_TPM is not set
496
497#
437# I2C support 498# I2C support
438# 499#
439CONFIG_I2C=y 500CONFIG_I2C=y
@@ -456,11 +517,11 @@ CONFIG_I2C_CHARDEV=y
456# CONFIG_I2C_AMD8111 is not set 517# CONFIG_I2C_AMD8111 is not set
457# CONFIG_I2C_I801 is not set 518# CONFIG_I2C_I801 is not set
458# CONFIG_I2C_I810 is not set 519# CONFIG_I2C_I810 is not set
520# CONFIG_I2C_PIIX4 is not set
459# CONFIG_I2C_ISA is not set 521# CONFIG_I2C_ISA is not set
460CONFIG_I2C_MPC=y 522CONFIG_I2C_MPC=y
461# CONFIG_I2C_NFORCE2 is not set 523# CONFIG_I2C_NFORCE2 is not set
462# CONFIG_I2C_PARPORT_LIGHT is not set 524# CONFIG_I2C_PARPORT_LIGHT is not set
463# CONFIG_I2C_PIIX4 is not set
464# CONFIG_I2C_PROSAVAGE is not set 525# CONFIG_I2C_PROSAVAGE is not set
465# CONFIG_I2C_SAVAGE4 is not set 526# CONFIG_I2C_SAVAGE4 is not set
466# CONFIG_SCx200_ACB is not set 527# CONFIG_SCx200_ACB is not set
@@ -483,7 +544,9 @@ CONFIG_I2C_MPC=y
483# CONFIG_SENSORS_ASB100 is not set 544# CONFIG_SENSORS_ASB100 is not set
484# CONFIG_SENSORS_DS1621 is not set 545# CONFIG_SENSORS_DS1621 is not set
485# CONFIG_SENSORS_FSCHER is not set 546# CONFIG_SENSORS_FSCHER is not set
547# CONFIG_SENSORS_FSCPOS is not set
486# CONFIG_SENSORS_GL518SM is not set 548# CONFIG_SENSORS_GL518SM is not set
549# CONFIG_SENSORS_GL520SM is not set
487# CONFIG_SENSORS_IT87 is not set 550# CONFIG_SENSORS_IT87 is not set
488# CONFIG_SENSORS_LM63 is not set 551# CONFIG_SENSORS_LM63 is not set
489# CONFIG_SENSORS_LM75 is not set 552# CONFIG_SENSORS_LM75 is not set
@@ -494,9 +557,11 @@ CONFIG_I2C_MPC=y
494# CONFIG_SENSORS_LM85 is not set 557# CONFIG_SENSORS_LM85 is not set
495# CONFIG_SENSORS_LM87 is not set 558# CONFIG_SENSORS_LM87 is not set
496# CONFIG_SENSORS_LM90 is not set 559# CONFIG_SENSORS_LM90 is not set
560# CONFIG_SENSORS_LM92 is not set
497# CONFIG_SENSORS_MAX1619 is not set 561# CONFIG_SENSORS_MAX1619 is not set
498# CONFIG_SENSORS_PC87360 is not set 562# CONFIG_SENSORS_PC87360 is not set
499# CONFIG_SENSORS_SMSC47B397 is not set 563# CONFIG_SENSORS_SMSC47B397 is not set
564# CONFIG_SENSORS_SIS5595 is not set
500# CONFIG_SENSORS_SMSC47M1 is not set 565# CONFIG_SENSORS_SMSC47M1 is not set
501# CONFIG_SENSORS_VIA686A is not set 566# CONFIG_SENSORS_VIA686A is not set
502# CONFIG_SENSORS_W83781D is not set 567# CONFIG_SENSORS_W83781D is not set
@@ -506,10 +571,12 @@ CONFIG_I2C_MPC=y
506# 571#
507# Other I2C Chip support 572# Other I2C Chip support
508# 573#
574# CONFIG_SENSORS_DS1337 is not set
509# CONFIG_SENSORS_EEPROM is not set 575# CONFIG_SENSORS_EEPROM is not set
510# CONFIG_SENSORS_PCF8574 is not set 576# CONFIG_SENSORS_PCF8574 is not set
511# CONFIG_SENSORS_PCF8591 is not set 577# CONFIG_SENSORS_PCF8591 is not set
512# CONFIG_SENSORS_RTC8564 is not set 578# CONFIG_SENSORS_RTC8564 is not set
579# CONFIG_SENSORS_M41T00 is not set
513# CONFIG_I2C_DEBUG_CORE is not set 580# CONFIG_I2C_DEBUG_CORE is not set
514# CONFIG_I2C_DEBUG_ALGO is not set 581# CONFIG_I2C_DEBUG_ALGO is not set
515# CONFIG_I2C_DEBUG_BUS is not set 582# CONFIG_I2C_DEBUG_BUS is not set
@@ -538,7 +605,6 @@ CONFIG_I2C_MPC=y
538# Graphics support 605# Graphics support
539# 606#
540# CONFIG_FB is not set 607# CONFIG_FB is not set
541# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
542 608
543# 609#
544# Sound 610# Sound
@@ -548,13 +614,9 @@ CONFIG_I2C_MPC=y
548# 614#
549# USB support 615# USB support
550# 616#
551# CONFIG_USB is not set
552CONFIG_USB_ARCH_HAS_HCD=y 617CONFIG_USB_ARCH_HAS_HCD=y
553CONFIG_USB_ARCH_HAS_OHCI=y 618CONFIG_USB_ARCH_HAS_OHCI=y
554 619# CONFIG_USB is not set
555#
556# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
557#
558 620
559# 621#
560# USB Gadget Support 622# USB Gadget Support
@@ -585,6 +647,10 @@ CONFIG_JBD=y
585CONFIG_FS_MBCACHE=y 647CONFIG_FS_MBCACHE=y
586# CONFIG_REISERFS_FS is not set 648# CONFIG_REISERFS_FS is not set
587# CONFIG_JFS_FS is not set 649# CONFIG_JFS_FS is not set
650
651#
652# XFS support
653#
588# CONFIG_XFS_FS is not set 654# CONFIG_XFS_FS is not set
589# CONFIG_MINIX_FS is not set 655# CONFIG_MINIX_FS is not set
590# CONFIG_ROMFS_FS is not set 656# CONFIG_ROMFS_FS is not set
@@ -646,7 +712,6 @@ CONFIG_NFS_FS=y
646# CONFIG_NFSD is not set 712# CONFIG_NFSD is not set
647CONFIG_ROOT_NFS=y 713CONFIG_ROOT_NFS=y
648CONFIG_LOCKD=y 714CONFIG_LOCKD=y
649# CONFIG_EXPORTFS is not set
650CONFIG_SUNRPC=y 715CONFIG_SUNRPC=y
651# CONFIG_RPCSEC_GSS_KRB5 is not set 716# CONFIG_RPCSEC_GSS_KRB5 is not set
652# CONFIG_RPCSEC_GSS_SPKM3 is not set 717# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -698,7 +763,9 @@ CONFIG_CRC32=y
698# 763#
699# Kernel hacking 764# Kernel hacking
700# 765#
766# CONFIG_PRINTK_TIME is not set
701# CONFIG_DEBUG_KERNEL is not set 767# CONFIG_DEBUG_KERNEL is not set
768CONFIG_LOG_BUF_SHIFT=14
702# CONFIG_KGDB_CONSOLE is not set 769# CONFIG_KGDB_CONSOLE is not set
703# CONFIG_SERIAL_TEXT_DEBUG is not set 770# CONFIG_SERIAL_TEXT_DEBUG is not set
704 771
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 9b6a8e513657..6c7ae6052464 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -330,8 +330,9 @@ interrupt_base:
330 /* If we are faulting a kernel address, we have to use the 330 /* If we are faulting a kernel address, we have to use the
331 * kernel page tables. 331 * kernel page tables.
332 */ 332 */
333 andis. r11, r10, 0x8000 333 lis r11, TASK_SIZE@h
334 beq 3f 334 cmplw r10, r11
335 blt+ 3f
335 lis r11, swapper_pg_dir@h 336 lis r11, swapper_pg_dir@h
336 ori r11, r11, swapper_pg_dir@l 337 ori r11, r11, swapper_pg_dir@l
337 338
@@ -464,8 +465,9 @@ interrupt_base:
464 /* If we are faulting a kernel address, we have to use the 465 /* If we are faulting a kernel address, we have to use the
465 * kernel page tables. 466 * kernel page tables.
466 */ 467 */
467 andis. r11, r10, 0x8000 468 lis r11, TASK_SIZE@h
468 beq 3f 469 cmplw r10, r11
470 blt+ 3f
469 lis r11, swapper_pg_dir@h 471 lis r11, swapper_pg_dir@h
470 ori r11, r11, swapper_pg_dir@l 472 ori r11, r11, swapper_pg_dir@l
471 473
@@ -533,8 +535,9 @@ interrupt_base:
533 /* If we are faulting a kernel address, we have to use the 535 /* If we are faulting a kernel address, we have to use the
534 * kernel page tables. 536 * kernel page tables.
535 */ 537 */
536 andis. r11, r10, 0x8000 538 lis r11, TASK_SIZE@h
537 beq 3f 539 cmplw r10, r11
540 blt+ 3f
538 lis r11, swapper_pg_dir@h 541 lis r11, swapper_pg_dir@h
539 ori r11, r11, swapper_pg_dir@l 542 ori r11, r11, swapper_pg_dir@l
540 543
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
index f22ddce36135..ce36e88ba627 100644
--- a/arch/ppc/kernel/head_fsl_booke.S
+++ b/arch/ppc/kernel/head_fsl_booke.S
@@ -232,7 +232,8 @@ skpinv: addi r6,r6,1 /* Increment */
232 tlbwe 232 tlbwe
233 233
234/* 7. Jump to KERNELBASE mapping */ 234/* 7. Jump to KERNELBASE mapping */
235 li r7,0 235 lis r7,MSR_KERNEL@h
236 ori r7,r7,MSR_KERNEL@l
236 bl 1f /* Find our address */ 237 bl 1f /* Find our address */
2371: mflr r9 2381: mflr r9
238 rlwimi r6,r9,0,20,31 239 rlwimi r6,r9,0,20,31
@@ -293,6 +294,18 @@ skpinv: addi r6,r6,1 /* Increment */
293 mtspr SPRN_HID0, r2 294 mtspr SPRN_HID0, r2
294#endif 295#endif
295 296
297#if !defined(CONFIG_BDI_SWITCH)
298 /*
299 * The Abatron BDI JTAG debugger does not tolerate others
300 * mucking with the debug registers.
301 */
302 lis r2,DBCR0_IDM@h
303 mtspr SPRN_DBCR0,r2
304 /* clear any residual debug events */
305 li r2,-1
306 mtspr SPRN_DBSR,r2
307#endif
308
296 /* 309 /*
297 * This is where the main kernel code starts. 310 * This is where the main kernel code starts.
298 */ 311 */
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index e97ce635b99e..5c20266e3b1f 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -221,27 +221,26 @@ int show_cpuinfo(struct seq_file *m, void *v)
221 return err; 221 return err;
222 } 222 }
223 223
224 switch (PVR_VER(pvr)) { 224 /* If we are a Freescale core do a simple check so
225 case 0x0020: /* 403 family */ 225 * we dont have to keep adding cases in the future */
226 maj = PVR_MAJ(pvr) + 1; 226 if ((PVR_VER(pvr) & 0x8000) == 0x8000) {
227 min = PVR_MIN(pvr);
228 break;
229 case 0x1008: /* 740P/750P ?? */
230 maj = ((pvr >> 8) & 0xFF) - 1;
231 min = pvr & 0xFF;
232 break;
233 case 0x8083: /* e300 */
234 maj = PVR_MAJ(pvr);
235 min = PVR_MIN(pvr);
236 break;
237 case 0x8020: /* e500 */
238 maj = PVR_MAJ(pvr); 227 maj = PVR_MAJ(pvr);
239 min = PVR_MIN(pvr); 228 min = PVR_MIN(pvr);
240 break; 229 } else {
241 default: 230 switch (PVR_VER(pvr)) {
242 maj = (pvr >> 8) & 0xFF; 231 case 0x0020: /* 403 family */
243 min = pvr & 0xFF; 232 maj = PVR_MAJ(pvr) + 1;
244 break; 233 min = PVR_MIN(pvr);
234 break;
235 case 0x1008: /* 740P/750P ?? */
236 maj = ((pvr >> 8) & 0xFF) - 1;
237 min = pvr & 0xFF;
238 break;
239 default:
240 maj = (pvr >> 8) & 0xFF;
241 min = pvr & 0xFF;
242 break;
243 }
245 } 244 }
246 245
247 seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n", 246 seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
@@ -500,7 +499,7 @@ static int __init set_preferred_console(void)
500{ 499{
501 struct device_node *prom_stdout; 500 struct device_node *prom_stdout;
502 char *name; 501 char *name;
503 int offset; 502 int offset = 0;
504 503
505 if (of_stdout_device == NULL) 504 if (of_stdout_device == NULL)
506 return -ENODEV; 505 return -ENODEV;
@@ -754,6 +753,8 @@ void __init setup_arch(char **cmdline_p)
754 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); 753 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
755 *cmdline_p = cmd_line; 754 *cmdline_p = cmd_line;
756 755
756 parse_early_param();
757
757 /* set up the bootmem stuff with available memory */ 758 /* set up the bootmem stuff with available memory */
758 do_init_bootmem(); 759 do_init_bootmem();
759 if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); 760 if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index f8e7e324a173..c65731e8bc65 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -408,12 +408,7 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
408 408
409 /* Early out if we are an invalid form of lswx */ 409 /* Early out if we are an invalid form of lswx */
410 if ((instword & INST_STRING_MASK) == INST_LSWX) 410 if ((instword & INST_STRING_MASK) == INST_LSWX)
411 if ((rA >= rT) || (NB_RB >= rT) || (rT == rA) || (rT == NB_RB)) 411 if ((rT == rA) || (rT == NB_RB))
412 return -EINVAL;
413
414 /* Early out if we are an invalid form of lswi */
415 if ((instword & INST_STRING_MASK) == INST_LSWI)
416 if ((rA >= rT) || (rT == rA))
417 return -EINVAL; 412 return -EINVAL;
418 413
419 EA = (rA == 0) ? 0 : regs->gpr[rA]; 414 EA = (rA == 0) ? 0 : regs->gpr[rA];
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 0c0e714b84de..9353584fb710 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -145,6 +145,7 @@ SECTIONS
145 __init_end = .; 145 __init_end = .;
146 146
147 . = ALIGN(4096); 147 . = ALIGN(4096);
148 _sextratext = .;
148 __pmac_begin = .; 149 __pmac_begin = .;
149 .pmac.text : { *(.pmac.text) } 150 .pmac.text : { *(.pmac.text) }
150 .pmac.data : { *(.pmac.data) } 151 .pmac.data : { *(.pmac.data) }
@@ -171,6 +172,7 @@ SECTIONS
171 .openfirmware.data : { *(.openfirmware.data) } 172 .openfirmware.data : { *(.openfirmware.data) }
172 . = ALIGN(4096); 173 . = ALIGN(4096);
173 __openfirmware_end = .; 174 __openfirmware_end = .;
175 _eextratext = .;
174 176
175 __bss_start = .; 177 __bss_start = .;
176 .bss : 178 .bss :
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
index 8d08a2eb225e..36c9b97fd92a 100644
--- a/arch/ppc/lib/string.S
+++ b/arch/ppc/lib/string.S
@@ -446,6 +446,7 @@ _GLOBAL(__copy_tofrom_user)
446#ifdef CONFIG_8xx 446#ifdef CONFIG_8xx
447 /* Don't use prefetch on 8xx */ 447 /* Don't use prefetch on 8xx */
448 mtctr r0 448 mtctr r0
449 li r0,0
44953: COPY_16_BYTES_WITHEX(0) 45053: COPY_16_BYTES_WITHEX(0)
450 bdnz 53b 451 bdnz 53b
451 452
@@ -564,7 +565,9 @@ _GLOBAL(__copy_tofrom_user)
564/* or write fault in cacheline loop */ 565/* or write fault in cacheline loop */
565105: li r9,1 566105: li r9,1
56692: li r3,LG_CACHELINE_BYTES 56792: li r3,LG_CACHELINE_BYTES
567 b 99f 568 mfctr r8
569 add r0,r0,r8
570 b 106f
568/* read fault in final word loop */ 571/* read fault in final word loop */
569108: li r9,0 572108: li r9,0
570 b 93f 573 b 93f
@@ -585,7 +588,7 @@ _GLOBAL(__copy_tofrom_user)
585 * r5 + (ctr << r3), and r9 is 0 for read or 1 for write. 588 * r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
586 */ 589 */
58799: mfctr r0 59099: mfctr r0
588 slw r3,r0,r3 591106: slw r3,r0,r3
589 add. r3,r3,r5 592 add. r3,r3,r5
590 beq 120f /* shouldn't happen */ 593 beq 120f /* shouldn't happen */
591 cmpwi 0,r9,0 594 cmpwi 0,r9,0
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index be02a7fec2b7..363c157e3617 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -179,6 +179,7 @@ void free_initmem(void)
179 if (!have_of) 179 if (!have_of)
180 FREESEC(openfirmware); 180 FREESEC(openfirmware);
181 printk("\n"); 181 printk("\n");
182 ppc_md.progress = NULL;
182#undef FREESEC 183#undef FREESEC
183} 184}
184 185
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
index b3b0f51979d2..e6348b5a1ddc 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -127,7 +127,6 @@ mpc834x_sys_map_io(void)
127{ 127{
128 /* we steal the lowest ioremap addr for virt space */ 128 /* we steal the lowest ioremap addr for virt space */
129 io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO); 129 io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
130 io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
131} 130}
132 131
133int 132int
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
index f4d055ae19c1..a2f6e49d7151 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.h
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
@@ -26,9 +26,14 @@
26#define VIRT_IMMRBAR ((uint)0xfe000000) 26#define VIRT_IMMRBAR ((uint)0xfe000000)
27 27
28#define BCSR_PHYS_ADDR ((uint)0xf8000000) 28#define BCSR_PHYS_ADDR ((uint)0xf8000000)
29#define BCSR_VIRT_ADDR ((uint)0xfe100000)
30#define BCSR_SIZE ((uint)(32 * 1024)) 29#define BCSR_SIZE ((uint)(32 * 1024))
31 30
31#define BCSR_MISC_REG2_OFF 0x07
32#define BCSR_MISC_REG2_PORESET 0x01
33
34#define BCSR_MISC_REG3_OFF 0x08
35#define BCSR_MISC_REG3_CNFLOCK 0x80
36
32#ifdef CONFIG_PCI 37#ifdef CONFIG_PCI
33/* PCI interrupt controller */ 38/* PCI interrupt controller */
34#define PIRQA MPC83xx_IRQ_IRQ4 39#define PIRQA MPC83xx_IRQ_IRQ4
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index 4d857d6d633d..583838ab02d8 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -210,6 +210,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
210#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) 210#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
211 ppc_md.progress = gen550_progress; 211 ppc_md.progress = gen550_progress;
212#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ 212#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
213#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
214 ppc_md.early_serial_map = mpc85xx_early_serial_map;
215#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
213 216
214 if (ppc_md.progress) 217 if (ppc_md.progress)
215 ppc_md.progress("mpc8540ads_init(): exit", 0); 218 ppc_md.progress("mpc8540ads_init(): exit", 0);
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 6c020d67ad70..e7cfa498568c 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -44,6 +44,7 @@
44#include <asm/machdep.h> 44#include <asm/machdep.h>
45#include <asm/prom.h> 45#include <asm/prom.h>
46#include <asm/open_pic.h> 46#include <asm/open_pic.h>
47#include <asm/i8259.h>
47#include <asm/bootinfo.h> 48#include <asm/bootinfo.h>
48#include <asm/pci-bridge.h> 49#include <asm/pci-bridge.h>
49#include <asm/mpc85xx.h> 50#include <asm/mpc85xx.h>
@@ -181,6 +182,7 @@ void __init
181mpc85xx_cds_init_IRQ(void) 182mpc85xx_cds_init_IRQ(void)
182{ 183{
183 bd_t *binfo = (bd_t *) __res; 184 bd_t *binfo = (bd_t *) __res;
185 int i;
184 186
185 /* Determine the Physical Address of the OpenPIC regs */ 187 /* Determine the Physical Address of the OpenPIC regs */
186 phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET; 188 phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
@@ -198,6 +200,15 @@ mpc85xx_cds_init_IRQ(void)
198 */ 200 */
199 openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); 201 openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
200 202
203#ifdef CONFIG_PCI
204 openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq);
205
206 for (i = 0; i < NUM_8259_INTERRUPTS; i++)
207 irq_desc[i].handler = &i8259_pic;
208
209 i8259_init(0);
210#endif
211
201#ifdef CONFIG_CPM2 212#ifdef CONFIG_CPM2
202 /* Setup CPM2 PIC */ 213 /* Setup CPM2 PIC */
203 cpm2_init_IRQ(); 214 cpm2_init_IRQ();
@@ -231,7 +242,7 @@ mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
231 * interrupt on slot */ 242 * interrupt on slot */
232 { 243 {
233 { 0, 1, 2, 3 }, /* 16 - PMC */ 244 { 0, 1, 2, 3 }, /* 16 - PMC */
234 { 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */ 245 { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
235 { 0, 1, 2, 3 }, /* 18 - Slot 1 */ 246 { 0, 1, 2, 3 }, /* 18 - Slot 1 */
236 { 1, 2, 3, 0 }, /* 19 - Slot 2 */ 247 { 1, 2, 3, 0 }, /* 19 - Slot 2 */
237 { 2, 3, 0, 1 }, /* 20 - Slot 3 */ 248 { 2, 3, 0, 1 }, /* 20 - Slot 3 */
@@ -280,13 +291,135 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
280 return PCIBIOS_DEVICE_NOT_FOUND; 291 return PCIBIOS_DEVICE_NOT_FOUND;
281#endif 292#endif
282 /* We explicitly do not go past the Tundra 320 Bridge */ 293 /* We explicitly do not go past the Tundra 320 Bridge */
283 if (bus == 1) 294 if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
284 return PCIBIOS_DEVICE_NOT_FOUND; 295 return PCIBIOS_DEVICE_NOT_FOUND;
285 if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) 296 if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
286 return PCIBIOS_DEVICE_NOT_FOUND; 297 return PCIBIOS_DEVICE_NOT_FOUND;
287 else 298 else
288 return PCIBIOS_SUCCESSFUL; 299 return PCIBIOS_SUCCESSFUL;
289} 300}
301
302void __init
303mpc85xx_cds_enable_via(struct pci_controller *hose)
304{
305 u32 pci_class;
306 u16 vid, did;
307
308 early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class);
309 if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI)
310 return;
311
312 /* Configure P2P so that we can reach bus 1 */
313 early_write_config_byte(hose, 0, 0x88, PCI_PRIMARY_BUS, 0);
314 early_write_config_byte(hose, 0, 0x88, PCI_SECONDARY_BUS, 1);
315 early_write_config_byte(hose, 0, 0x88, PCI_SUBORDINATE_BUS, 0xff);
316
317 early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid);
318 early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did);
319
320 if ((vid != PCI_VENDOR_ID_VIA) ||
321 (did != PCI_DEVICE_ID_VIA_82C686))
322 return;
323
324 /* Enable USB and IDE functions */
325 early_write_config_byte(hose, 1, 0x10, 0x48, 0x08);
326}
327
328void __init
329mpc85xx_cds_fixup_via(struct pci_controller *hose)
330{
331 u32 pci_class;
332 u16 vid, did;
333
334 early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class);
335 if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI)
336 return;
337
338 /*
339 * Force the backplane P2P bridge to have a window
340 * open from 0x00000000-0x00001fff in PCI I/O space.
341 * This allows legacy I/O (i8259, etc) on the VIA
342 * southbridge to be accessed.
343 */
344 early_write_config_byte(hose, 0, 0x88, PCI_IO_BASE, 0x00);
345 early_write_config_word(hose, 0, 0x88, PCI_IO_BASE_UPPER16, 0x0000);
346 early_write_config_byte(hose, 0, 0x88, PCI_IO_LIMIT, 0x10);
347 early_write_config_word(hose, 0, 0x88, PCI_IO_LIMIT_UPPER16, 0x0000);
348
349 early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid);
350 early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did);
351 if ((vid != PCI_VENDOR_ID_VIA) ||
352 (did != PCI_DEVICE_ID_VIA_82C686))
353 return;
354
355 /*
356 * Since the P2P window was forced to cover the fixed
357 * legacy I/O addresses, it is necessary to manually
358 * place the base addresses for the IDE and USB functions
359 * within this window.
360 */
361 /* Function 1, IDE */
362 early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_0, 0x1ff8);
363 early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_1, 0x1ff4);
364 early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_2, 0x1fe8);
365 early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_3, 0x1fe4);
366 early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_4, 0x1fd0);
367
368 /* Function 2, USB ports 0-1 */
369 early_write_config_dword(hose, 1, 0x12, PCI_BASE_ADDRESS_4, 0x1fa0);
370
371 /* Function 3, USB ports 2-3 */
372 early_write_config_dword(hose, 1, 0x13, PCI_BASE_ADDRESS_4, 0x1f80);
373
374 /* Function 5, Power Management */
375 early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_0, 0x1e00);
376 early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_1, 0x1dfc);
377 early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_2, 0x1df8);
378
379 /* Function 6, AC97 Interface */
380 early_write_config_dword(hose, 1, 0x16, PCI_BASE_ADDRESS_0, 0x1c00);
381}
382
383void __init
384mpc85xx_cds_pcibios_fixup(void)
385{
386 struct pci_dev *dev = NULL;
387 u_char c;
388
389 if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
390 PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
391 /*
392 * U-Boot does not set the enable bits
393 * for the IDE device. Force them on here.
394 */
395 pci_read_config_byte(dev, 0x40, &c);
396 c |= 0x03; /* IDE: Chip Enable Bits */
397 pci_write_config_byte(dev, 0x40, c);
398
399 /*
400 * Since only primary interface works, force the
401 * IDE function to standard primary IDE interrupt
402 * w/ 8259 offset
403 */
404 dev->irq = 14;
405 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
406 }
407
408 /*
409 * Force legacy USB interrupt routing
410 */
411 if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
412 PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
413 dev->irq = 10;
414 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
415 }
416
417 if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
418 PCI_DEVICE_ID_VIA_82C586_2, dev))) {
419 dev->irq = 11;
420 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
421 }
422}
290#endif /* CONFIG_PCI */ 423#endif /* CONFIG_PCI */
291 424
292TODC_ALLOC(); 425TODC_ALLOC();
@@ -328,6 +461,9 @@ mpc85xx_cds_setup_arch(void)
328 loops_per_jiffy = freq / HZ; 461 loops_per_jiffy = freq / HZ;
329 462
330#ifdef CONFIG_PCI 463#ifdef CONFIG_PCI
464 /* VIA IDE configuration */
465 ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
466
331 /* setup PCI host bridges */ 467 /* setup PCI host bridges */
332 mpc85xx_setup_hose(); 468 mpc85xx_setup_hose();
333#endif 469#endif
@@ -459,6 +595,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
459#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) 595#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
460 ppc_md.progress = gen550_progress; 596 ppc_md.progress = gen550_progress;
461#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ 597#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
598#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
599 ppc_md.early_serial_map = mpc85xx_early_serial_map;
600#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
462 601
463 if (ppc_md.progress) 602 if (ppc_md.progress)
464 ppc_md.progress("mpc85xx_cds_init(): exit", 0); 603 ppc_md.progress("mpc85xx_cds_init(): exit", 0);
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
index 7627d77504bd..12b292c6ae32 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
@@ -77,4 +77,7 @@
77 77
78#define MPC85XX_PCI2_IO_SIZE 0x01000000 78#define MPC85XX_PCI2_IO_SIZE 0x01000000
79 79
80#define NR_8259_INTS 16
81#define CPM_IRQ_OFFSET NR_8259_INTS
82
80#endif /* __MACH_MPC85XX_CDS_H__ */ 83#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index 9ab05e590c3e..7b9e1543e175 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -221,6 +221,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
221#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) 221#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
222 ppc_md.progress = gen550_progress; 222 ppc_md.progress = gen550_progress;
223#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ 223#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
224#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
225 ppc_md.early_serial_map = sbc8560_early_serial_map;
226#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
224 227
225 if (ppc_md.progress) 228 if (ppc_md.progress)
226 ppc_md.progress("sbc8560_init(): exit", 0); 229 ppc_md.progress("sbc8560_init(): exit", 0);
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
index f7fb2786cd50..937f46df711e 100644
--- a/arch/ppc/platforms/pmac_cpufreq.c
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -85,14 +85,11 @@ static int no_schedule;
85static int has_cpu_l2lve; 85static int has_cpu_l2lve;
86 86
87 87
88#define PMAC_CPU_LOW_SPEED 1
89#define PMAC_CPU_HIGH_SPEED 0
90
91/* There are only two frequency states for each processor. Values 88/* There are only two frequency states for each processor. Values
92 * are in kHz for the time being. 89 * are in kHz for the time being.
93 */ 90 */
94#define CPUFREQ_HIGH PMAC_CPU_HIGH_SPEED 91#define CPUFREQ_HIGH 0
95#define CPUFREQ_LOW PMAC_CPU_LOW_SPEED 92#define CPUFREQ_LOW 1
96 93
97static struct cpufreq_frequency_table pmac_cpu_freqs[] = { 94static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
98 {CPUFREQ_HIGH, 0}, 95 {CPUFREQ_HIGH, 0},
@@ -100,6 +97,11 @@ static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
100 {0, CPUFREQ_TABLE_END}, 97 {0, CPUFREQ_TABLE_END},
101}; 98};
102 99
100static struct freq_attr* pmac_cpu_freqs_attr[] = {
101 &cpufreq_freq_attr_scaling_available_freqs,
102 NULL,
103};
104
103static inline void local_delay(unsigned long ms) 105static inline void local_delay(unsigned long ms)
104{ 106{
105 if (no_schedule) 107 if (no_schedule)
@@ -269,6 +271,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
269#ifdef DEBUG_FREQ 271#ifdef DEBUG_FREQ
270 printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); 272 printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
271#endif 273#endif
274 pmu_suspend();
275
272 /* Disable all interrupt sources on openpic */ 276 /* Disable all interrupt sources on openpic */
273 pic_prio = openpic_get_priority(); 277 pic_prio = openpic_get_priority();
274 openpic_set_priority(0xf); 278 openpic_set_priority(0xf);
@@ -343,6 +347,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
343 debug_calc_bogomips(); 347 debug_calc_bogomips();
344#endif 348#endif
345 349
350 pmu_resume();
351
346 preempt_enable(); 352 preempt_enable();
347 353
348 return 0; 354 return 0;
@@ -355,7 +361,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
355 static unsigned long prev_l3cr; 361 static unsigned long prev_l3cr;
356 362
357 freqs.old = cur_freq; 363 freqs.old = cur_freq;
358 freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; 364 freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
359 freqs.cpu = smp_processor_id(); 365 freqs.cpu = smp_processor_id();
360 366
361 if (freqs.old == freqs.new) 367 if (freqs.old == freqs.new)
@@ -363,7 +369,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
363 369
364 if (notify) 370 if (notify)
365 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 371 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
366 if (speed_mode == PMAC_CPU_LOW_SPEED && 372 if (speed_mode == CPUFREQ_LOW &&
367 cpu_has_feature(CPU_FTR_L3CR)) { 373 cpu_has_feature(CPU_FTR_L3CR)) {
368 l3cr = _get_L3CR(); 374 l3cr = _get_L3CR();
369 if (l3cr & L3CR_L3E) { 375 if (l3cr & L3CR_L3E) {
@@ -371,8 +377,8 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
371 _set_L3CR(0); 377 _set_L3CR(0);
372 } 378 }
373 } 379 }
374 set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED); 380 set_speed_proc(speed_mode == CPUFREQ_LOW);
375 if (speed_mode == PMAC_CPU_HIGH_SPEED && 381 if (speed_mode == CPUFREQ_HIGH &&
376 cpu_has_feature(CPU_FTR_L3CR)) { 382 cpu_has_feature(CPU_FTR_L3CR)) {
377 l3cr = _get_L3CR(); 383 l3cr = _get_L3CR();
378 if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) 384 if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
@@ -380,7 +386,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
380 } 386 }
381 if (notify) 387 if (notify)
382 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 388 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
383 cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; 389 cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
384 390
385 return 0; 391 return 0;
386} 392}
@@ -423,7 +429,8 @@ static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
423 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 429 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
424 policy->cur = cur_freq; 430 policy->cur = cur_freq;
425 431
426 return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]); 432 cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
433 return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
427} 434}
428 435
429static u32 __pmac read_gpio(struct device_node *np) 436static u32 __pmac read_gpio(struct device_node *np)
@@ -457,7 +464,7 @@ static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state)
457 no_schedule = 1; 464 no_schedule = 1;
458 sleep_freq = cur_freq; 465 sleep_freq = cur_freq;
459 if (cur_freq == low_freq) 466 if (cur_freq == low_freq)
460 do_set_cpu_speed(PMAC_CPU_HIGH_SPEED, 0); 467 do_set_cpu_speed(CPUFREQ_HIGH, 0);
461 return 0; 468 return 0;
462} 469}
463 470
@@ -473,8 +480,8 @@ static int __pmac pmac_cpufreq_resume(struct cpufreq_policy *policy)
473 * is that we force a switch to whatever it was, which is 480 * is that we force a switch to whatever it was, which is
474 * probably high speed due to our suspend() routine 481 * probably high speed due to our suspend() routine
475 */ 482 */
476 do_set_cpu_speed(sleep_freq == low_freq ? PMAC_CPU_LOW_SPEED 483 do_set_cpu_speed(sleep_freq == low_freq ?
477 : PMAC_CPU_HIGH_SPEED, 0); 484 CPUFREQ_LOW : CPUFREQ_HIGH, 0);
478 485
479 no_schedule = 0; 486 no_schedule = 0;
480 return 0; 487 return 0;
@@ -488,6 +495,7 @@ static struct cpufreq_driver pmac_cpufreq_driver = {
488 .suspend = pmac_cpufreq_suspend, 495 .suspend = pmac_cpufreq_suspend,
489 .resume = pmac_cpufreq_resume, 496 .resume = pmac_cpufreq_resume,
490 .flags = CPUFREQ_PM_NO_WARN, 497 .flags = CPUFREQ_PM_NO_WARN,
498 .attr = pmac_cpu_freqs_attr,
491 .name = "powermac", 499 .name = "powermac",
492 .owner = THIS_MODULE, 500 .owner = THIS_MODULE,
493}; 501};
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
index cf5e5dd06d63..067d9a5aebc1 100644
--- a/arch/ppc/platforms/pq2ads.h
+++ b/arch/ppc/platforms/pq2ads.h
@@ -49,10 +49,10 @@
49/* PCI interrupt controller */ 49/* PCI interrupt controller */
50#define PCI_INT_STAT_REG 0xF8200000 50#define PCI_INT_STAT_REG 0xF8200000
51#define PCI_INT_MASK_REG 0xF8200004 51#define PCI_INT_MASK_REG 0xF8200004
52#define PIRQA (NR_SIU_INTS + 0) 52#define PIRQA (NR_CPM_INTS + 0)
53#define PIRQB (NR_SIU_INTS + 1) 53#define PIRQB (NR_CPM_INTS + 1)
54#define PIRQC (NR_SIU_INTS + 2) 54#define PIRQC (NR_CPM_INTS + 2)
55#define PIRQD (NR_SIU_INTS + 3) 55#define PIRQD (NR_CPM_INTS + 3)
56 56
57/* 57/*
58 * PCI memory map definitions for MPC8266ADS-PCI. 58 * PCI memory map definitions for MPC8266ADS-PCI.
@@ -68,28 +68,23 @@
68 * 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory 68 * 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory
69 */ 69 */
70 70
71/* window for a PCI master to access MPC8266 memory */ 71/* All the other PCI memory map definitions reside at syslib/m82xx_pci.h
72#define PCI_SLV_MEM_LOCAL 0x00000000 /* Local base */ 72 Here we should redefine what is unique for this board */
73#define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */ 73#define M82xx_PCI_SLAVE_MEM_LOCAL 0x00000000 /* Local base */
74#define M82xx_PCI_SLAVE_MEM_BUS 0x00000000 /* PCI base */
75#define M82xx_PCI_SLAVE_MEM_SIZE 0x10000000 /* 256 Mb */
74 76
75/* window for the processor to access PCI memory with prefetching */ 77#define M82xx_PCI_SLAVE_SEC_WND_SIZE ~(0x40000000 - 1U) /* 2 x 512Mb */
76#define PCI_MSTR_MEM_LOCAL 0x80000000 /* Local base */ 78#define M82xx_PCI_SLAVE_SEC_WND_BASE 0x80000000 /* PCI Memory base */
77#define PCI_MSTR_MEM_BUS 0x80000000 /* PCI base */
78#define PCI_MSTR_MEM_SIZE 0x20000000 /* 512MB */
79 79
80/* window for the processor to access PCI memory without prefetching */ 80#if defined(CONFIG_ADS8272)
81#define PCI_MSTR_MEMIO_LOCAL 0xA0000000 /* Local base */ 81#define PCI_INT_TO_SIU SIU_INT_IRQ2
82#define PCI_MSTR_MEMIO_BUS 0xA0000000 /* PCI base */ 82#elif defined(CONFIG_PQ2FADS)
83#define PCI_MSTR_MEMIO_SIZE 0x20000000 /* 512MB */ 83#define PCI_INT_TO_SIU SIU_INT_IRQ6
84#else
85#warning PCI Bridge will be without interrupts support
86#endif
84 87
85/* window for the processor to access PCI I/O */
86#define PCI_MSTR_IO_LOCAL 0xF4000000 /* Local base */
87#define PCI_MSTR_IO_BUS 0x00000000 /* PCI base */
88#define PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */
89
90#define _IO_BASE PCI_MSTR_IO_LOCAL
91#define _ISA_MEM_BASE PCI_MSTR_MEMIO_LOCAL
92#define PCI_DRAM_OFFSET PCI_SLV_MEM_BUS
93#endif /* CONFIG_PCI */ 88#endif /* CONFIG_PCI */
94 89
95#endif /* __MACH_ADS8260_DEFS */ 90#endif /* __MACH_ADS8260_DEFS */
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index dd418ea3426c..96acf85800d4 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -81,7 +81,7 @@ obj-$(CONFIG_SBC82xx) += todc_time.o
81obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \ 81obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
82 todc_time.o 82 todc_time.o
83obj-$(CONFIG_8260) += m8260_setup.o 83obj-$(CONFIG_8260) += m8260_setup.o
84obj-$(CONFIG_PCI_8260) += m8260_pci.o indirect_pci.o 84obj-$(CONFIG_PCI_8260) += m82xx_pci.o indirect_pci.o pci_auto.o
85obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o 85obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o
86obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o 86obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
87ifeq ($(CONFIG_PPC_GEN550),y) 87ifeq ($(CONFIG_PPC_GEN550),y)
@@ -97,7 +97,7 @@ obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o
97obj-$(CONFIG_40x) += dcr.o 97obj-$(CONFIG_40x) += dcr.o
98obj-$(CONFIG_BOOKE) += dcr.o 98obj-$(CONFIG_BOOKE) += dcr.o
99obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \ 99obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \
100 ppc_sys.o mpc85xx_sys.o \ 100 ppc_sys.o i8259.o mpc85xx_sys.o \
101 mpc85xx_devices.o 101 mpc85xx_devices.o
102ifeq ($(CONFIG_85xx),y) 102ifeq ($(CONFIG_85xx),y)
103obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o 103obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
index acb2cde3171f..580ed658e872 100644
--- a/arch/ppc/syslib/ipic.c
+++ b/arch/ppc/syslib/ipic.c
@@ -479,7 +479,7 @@ void __init ipic_init(phys_addr_t phys_addr,
479 temp = 0; 479 temp = 0;
480 for (i = 0 ; i < senses_count ; i++) { 480 for (i = 0 ; i < senses_count ; i++) {
481 if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { 481 if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
482 temp |= 1 << (16 - i); 482 temp |= 1 << (15 - i);
483 if (i != 0) 483 if (i != 0)
484 irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; 484 irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
485 else 485 else
diff --git a/arch/ppc/syslib/m8260_pci.c b/arch/ppc/syslib/m8260_pci.c
deleted file mode 100644
index 057cc3f8ff37..000000000000
--- a/arch/ppc/syslib/m8260_pci.c
+++ /dev/null
@@ -1,193 +0,0 @@
1/*
2 * (C) Copyright 2003
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * (C) Copyright 2004 Red Hat, Inc.
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#include <linux/kernel.h>
27#include <linux/init.h>
28#include <linux/pci.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
31
32#include <asm/byteorder.h>
33#include <asm/io.h>
34#include <asm/irq.h>
35#include <asm/uaccess.h>
36#include <asm/machdep.h>
37#include <asm/pci-bridge.h>
38#include <asm/immap_cpm2.h>
39#include <asm/mpc8260.h>
40
41#include "m8260_pci.h"
42
43
44/* PCI bus configuration registers.
45 */
46
47static void __init m8260_setup_pci(struct pci_controller *hose)
48{
49 volatile cpm2_map_t *immap = cpm2_immr;
50 unsigned long pocmr;
51 u16 tempShort;
52
53#ifndef CONFIG_ATC /* already done in U-Boot */
54 /*
55 * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
56 * and local bus for PCI (SIUMCR [LBPC]).
57 */
58 immap->im_siu_conf.siu_82xx.sc_siumcr = 0x00640000;
59#endif
60
61 /* Make PCI lowest priority */
62 /* Each 4 bits is a device bus request and the MS 4bits
63 is highest priority */
64 /* Bus 4bit value
65 --- ----------
66 CPM high 0b0000
67 CPM middle 0b0001
68 CPM low 0b0010
69 PCI reguest 0b0011
70 Reserved 0b0100
71 Reserved 0b0101
72 Internal Core 0b0110
73 External Master 1 0b0111
74 External Master 2 0b1000
75 External Master 3 0b1001
76 The rest are reserved */
77 immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
78
79 /* Park bus on core while modifying PCI Bus accesses */
80 immap->im_siu_conf.siu_82xx.sc_ppc_acr = 0x6;
81
82 /*
83 * Set up master window that allows the CPU to access PCI space. This
84 * window is set up using the first SIU PCIBR registers.
85 */
86 immap->im_memctl.memc_pcimsk0 = MPC826x_PCI_MASK;
87 immap->im_memctl.memc_pcibr0 = MPC826x_PCI_BASE | PCIBR_ENABLE;
88
89 /* Disable machine check on no response or target abort */
90 immap->im_pci.pci_emr = cpu_to_le32(0x1fe7);
91 /* Release PCI RST (by default the PCI RST signal is held low) */
92 immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
93
94 /* give it some time */
95 mdelay(1);
96
97 /*
98 * Set up master window that allows the CPU to access PCI Memory (prefetch)
99 * space. This window is set up using the first set of Outbound ATU registers.
100 */
101 immap->im_pci.pci_potar0 = cpu_to_le32(MPC826x_PCI_LOWER_MEM >> 12);
102 immap->im_pci.pci_pobar0 = cpu_to_le32((MPC826x_PCI_LOWER_MEM - MPC826x_PCI_MEM_OFFSET) >> 12);
103 pocmr = ((MPC826x_PCI_UPPER_MEM - MPC826x_PCI_LOWER_MEM) >> 12) ^ 0xfffff;
104 immap->im_pci.pci_pocmr0 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PREFETCH_EN);
105
106 /*
107 * Set up master window that allows the CPU to access PCI Memory (non-prefetch)
108 * space. This window is set up using the second set of Outbound ATU registers.
109 */
110 immap->im_pci.pci_potar1 = cpu_to_le32(MPC826x_PCI_LOWER_MMIO >> 12);
111 immap->im_pci.pci_pobar1 = cpu_to_le32((MPC826x_PCI_LOWER_MMIO - MPC826x_PCI_MMIO_OFFSET) >> 12);
112 pocmr = ((MPC826x_PCI_UPPER_MMIO - MPC826x_PCI_LOWER_MMIO) >> 12) ^ 0xfffff;
113 immap->im_pci.pci_pocmr1 = cpu_to_le32(pocmr | POCMR_ENABLE);
114
115 /*
116 * Set up master window that allows the CPU to access PCI IO space. This window
117 * is set up using the third set of Outbound ATU registers.
118 */
119 immap->im_pci.pci_potar2 = cpu_to_le32(MPC826x_PCI_IO_BASE >> 12);
120 immap->im_pci.pci_pobar2 = cpu_to_le32(MPC826x_PCI_LOWER_IO >> 12);
121 pocmr = ((MPC826x_PCI_UPPER_IO - MPC826x_PCI_LOWER_IO) >> 12) ^ 0xfffff;
122 immap->im_pci.pci_pocmr2 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PCI_IO);
123
124 /*
125 * Set up slave window that allows PCI masters to access MPC826x local memory.
126 * This window is set up using the first set of Inbound ATU registers
127 */
128
129 immap->im_pci.pci_pitar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_LOCAL >> 12);
130 immap->im_pci.pci_pibar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_BUS >> 12);
131 pocmr = ((MPC826x_PCI_SLAVE_MEM_SIZE-1) >> 12) ^ 0xfffff;
132 immap->im_pci.pci_picmr0 = cpu_to_le32(pocmr | PICMR_ENABLE | PICMR_PREFETCH_EN);
133
134 /* See above for description - puts PCI request as highest priority */
135 immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
136
137 /* Park the bus on the PCI */
138 immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
139
140 /* Host mode - specify the bridge as a host-PCI bridge */
141 early_write_config_word(hose, 0, 0, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_HOST);
142
143 /* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */
144 early_read_config_word(hose, 0, 0, PCI_COMMAND, &tempShort);
145 early_write_config_word(hose, 0, 0, PCI_COMMAND,
146 tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
147}
148
149void __init m8260_find_bridges(void)
150{
151 extern int pci_assign_all_busses;
152 struct pci_controller * hose;
153
154 pci_assign_all_busses = 1;
155
156 hose = pcibios_alloc_controller();
157
158 if (!hose)
159 return;
160
161 ppc_md.pci_swizzle = common_swizzle;
162
163 hose->first_busno = 0;
164 hose->bus_offset = 0;
165 hose->last_busno = 0xff;
166
167 setup_m8260_indirect_pci(hose,
168 (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
169 (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
170
171 m8260_setup_pci(hose);
172 hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET;
173
174 hose->io_base_virt = ioremap(MPC826x_PCI_IO_BASE,
175 MPC826x_PCI_IO_SIZE);
176 isa_io_base = (unsigned long) hose->io_base_virt;
177
178 /* setup resources */
179 pci_init_resource(&hose->mem_resources[0],
180 MPC826x_PCI_LOWER_MEM,
181 MPC826x_PCI_UPPER_MEM,
182 IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
183
184 pci_init_resource(&hose->mem_resources[1],
185 MPC826x_PCI_LOWER_MMIO,
186 MPC826x_PCI_UPPER_MMIO,
187 IORESOURCE_MEM, "PCI memory");
188
189 pci_init_resource(&hose->io_resource,
190 MPC826x_PCI_LOWER_IO,
191 MPC826x_PCI_UPPER_IO,
192 IORESOURCE_IO, "PCI I/O");
193}
diff --git a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h
deleted file mode 100644
index d1352120acd7..000000000000
--- a/arch/ppc/syslib/m8260_pci.h
+++ /dev/null
@@ -1,76 +0,0 @@
1
2#ifndef _PPC_KERNEL_M8260_PCI_H
3#define _PPC_KERNEL_M8260_PCI_H
4
5#include <asm/m8260_pci.h>
6
7/*
8 * Local->PCI map (from CPU) controlled by
9 * MPC826x master window
10 *
11 * 0x80000000 - 0xBFFFFFFF Total CPU2PCI space PCIBR0
12 *
13 * 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1)
14 * 0xA0000000 - 0xAFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2)
15 * 0xB0000000 - 0xB0FFFFFF 32-bit PCI IO (Outbound ATU #3)
16 *
17 * PCI->Local map (from PCI)
18 * MPC826x slave window controlled by
19 *
20 * 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1)
21 */
22
23/*
24 * Slave window that allows PCI masters to access MPC826x local memory.
25 * This window is set up using the first set of Inbound ATU registers
26 */
27
28#ifndef MPC826x_PCI_SLAVE_MEM_LOCAL
29#define MPC826x_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart)
30#define MPC826x_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart)
31#define MPC826x_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize)
32#endif
33
34/*
35 * This is the window that allows the CPU to access PCI address space.
36 * It will be setup with the SIU PCIBR0 register. All three PCI master
37 * windows, which allow the CPU to access PCI prefetch, non prefetch,
38 * and IO space (see below), must all fit within this window.
39 */
40#ifndef MPC826x_PCI_BASE
41#define MPC826x_PCI_BASE 0x80000000
42#define MPC826x_PCI_MASK 0xc0000000
43#endif
44
45#ifndef MPC826x_PCI_LOWER_MEM
46#define MPC826x_PCI_LOWER_MEM 0x80000000
47#define MPC826x_PCI_UPPER_MEM 0x9fffffff
48#define MPC826x_PCI_MEM_OFFSET 0x00000000
49#endif
50
51#ifndef MPC826x_PCI_LOWER_MMIO
52#define MPC826x_PCI_LOWER_MMIO 0xa0000000
53#define MPC826x_PCI_UPPER_MMIO 0xafffffff
54#define MPC826x_PCI_MMIO_OFFSET 0x00000000
55#endif
56
57#ifndef MPC826x_PCI_LOWER_IO
58#define MPC826x_PCI_LOWER_IO 0x00000000
59#define MPC826x_PCI_UPPER_IO 0x00ffffff
60#define MPC826x_PCI_IO_BASE 0xb0000000
61#define MPC826x_PCI_IO_SIZE 0x01000000
62#endif
63
64#ifndef _IO_BASE
65#define _IO_BASE isa_io_base
66#endif
67
68#ifdef CONFIG_8260_PCI9
69struct pci_controller;
70extern void setup_m8260_indirect_pci(struct pci_controller* hose,
71 u32 cfg_addr, u32 cfg_data);
72#else
73#define setup_m8260_indirect_pci setup_indirect_pci
74#endif
75
76#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/ppc/syslib/m8260_pci_erratum9.c b/arch/ppc/syslib/m8260_pci_erratum9.c
index 9c0582d639e0..1dc7e4e1d491 100644
--- a/arch/ppc/syslib/m8260_pci_erratum9.c
+++ b/arch/ppc/syslib/m8260_pci_erratum9.c
@@ -31,7 +31,7 @@
31#include <asm/immap_cpm2.h> 31#include <asm/immap_cpm2.h>
32#include <asm/cpm2.h> 32#include <asm/cpm2.h>
33 33
34#include "m8260_pci.h" 34#include "m82xx_pci.h"
35 35
36#ifdef CONFIG_8260_PCI9 36#ifdef CONFIG_8260_PCI9
37/*#include <asm/mpc8260_pci9.h>*/ /* included in asm/io.h */ 37/*#include <asm/mpc8260_pci9.h>*/ /* included in asm/io.h */
@@ -248,11 +248,11 @@ EXPORT_SYMBOL(idma_pci9_read_le);
248 248
249static inline int is_pci_mem(unsigned long addr) 249static inline int is_pci_mem(unsigned long addr)
250{ 250{
251 if (addr >= MPC826x_PCI_LOWER_MMIO && 251 if (addr >= M82xx_PCI_LOWER_MMIO &&
252 addr <= MPC826x_PCI_UPPER_MMIO) 252 addr <= M82xx_PCI_UPPER_MMIO)
253 return 1; 253 return 1;
254 if (addr >= MPC826x_PCI_LOWER_MEM && 254 if (addr >= M82xx_PCI_LOWER_MEM &&
255 addr <= MPC826x_PCI_UPPER_MEM) 255 addr <= M82xx_PCI_UPPER_MEM)
256 return 1; 256 return 1;
257 return 0; 257 return 0;
258} 258}
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
index 23ea3f694de2..fda75d79050c 100644
--- a/arch/ppc/syslib/m8260_setup.c
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -34,7 +34,8 @@
34unsigned char __res[sizeof(bd_t)]; 34unsigned char __res[sizeof(bd_t)];
35 35
36extern void cpm2_reset(void); 36extern void cpm2_reset(void);
37extern void m8260_find_bridges(void); 37extern void pq2_find_bridges(void);
38extern void pq2pci_init_irq(void);
38extern void idma_pci9_init(void); 39extern void idma_pci9_init(void);
39 40
40/* Place-holder for board-specific init */ 41/* Place-holder for board-specific init */
@@ -56,7 +57,7 @@ m8260_setup_arch(void)
56 idma_pci9_init(); 57 idma_pci9_init();
57#endif 58#endif
58#ifdef CONFIG_PCI_8260 59#ifdef CONFIG_PCI_8260
59 m8260_find_bridges(); 60 pq2_find_bridges();
60#endif 61#endif
61#ifdef CONFIG_BLK_DEV_INITRD 62#ifdef CONFIG_BLK_DEV_INITRD
62 if (initrd_start) 63 if (initrd_start)
@@ -173,6 +174,12 @@ m8260_init_IRQ(void)
173 * in case the boot rom changed something on us. 174 * in case the boot rom changed something on us.
174 */ 175 */
175 cpm2_immr->im_intctl.ic_siprr = 0x05309770; 176 cpm2_immr->im_intctl.ic_siprr = 0x05309770;
177
178#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS))
179 /* Initialize stuff for the 82xx CPLD IC and install demux */
180 pq2pci_init_irq();
181#endif
182
176} 183}
177 184
178/* 185/*
diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c
new file mode 100644
index 000000000000..5e7a7edcea74
--- /dev/null
+++ b/arch/ppc/syslib/m82xx_pci.c
@@ -0,0 +1,383 @@
1/*
2 *
3 * (C) Copyright 2003
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 *
6 * (C) Copyright 2004 Red Hat, Inc.
7 *
8 * 2005 (c) MontaVista Software, Inc.
9 * Vitaly Bordug <vbordug@ru.mvista.com>
10 *
11 * See file CREDITS for list of people who contributed to this
12 * project.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 * MA 02111-1307 USA
28 */
29
30#include <linux/kernel.h>
31#include <linux/init.h>
32#include <linux/pci.h>
33#include <linux/slab.h>
34#include <linux/delay.h>
35#include <linux/irq.h>
36#include <linux/interrupt.h>
37
38#include <asm/byteorder.h>
39#include <asm/io.h>
40#include <asm/irq.h>
41#include <asm/uaccess.h>
42#include <asm/machdep.h>
43#include <asm/pci-bridge.h>
44#include <asm/immap_cpm2.h>
45#include <asm/mpc8260.h>
46#include <asm/cpm2.h>
47
48#include "m82xx_pci.h"
49
50/*
51 * Interrupt routing
52 */
53
54static inline int
55pq2pci_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
56{
57 static char pci_irq_table[][4] =
58 /*
59 * PCI IDSEL/INTPIN->INTLINE
60 * A B C D
61 */
62 {
63 { PIRQA, PIRQB, PIRQC, PIRQD }, /* IDSEL 22 - PCI slot 0 */
64 { PIRQD, PIRQA, PIRQB, PIRQC }, /* IDSEL 23 - PCI slot 1 */
65 { PIRQC, PIRQD, PIRQA, PIRQB }, /* IDSEL 24 - PCI slot 2 */
66 };
67
68 const long min_idsel = 22, max_idsel = 24, irqs_per_slot = 4;
69 return PCI_IRQ_TABLE_LOOKUP;
70}
71
72static void
73pq2pci_mask_irq(unsigned int irq)
74{
75 int bit = irq - NR_CPM_INTS;
76
77 *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
78 return;
79}
80
81static void
82pq2pci_unmask_irq(unsigned int irq)
83{
84 int bit = irq - NR_CPM_INTS;
85
86 *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
87 return;
88}
89
90static void
91pq2pci_mask_and_ack(unsigned int irq)
92{
93 int bit = irq - NR_CPM_INTS;
94
95 *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
96 return;
97}
98
99static void
100pq2pci_end_irq(unsigned int irq)
101{
102 int bit = irq - NR_CPM_INTS;
103
104 *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
105 return;
106}
107
108struct hw_interrupt_type pq2pci_ic = {
109 "PQ2 PCI",
110 NULL,
111 NULL,
112 pq2pci_unmask_irq,
113 pq2pci_mask_irq,
114 pq2pci_mask_and_ack,
115 pq2pci_end_irq,
116 0
117};
118
119static irqreturn_t
120pq2pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
121{
122 unsigned long stat, mask, pend;
123 int bit;
124
125 for(;;) {
126 stat = *(volatile unsigned long *) PCI_INT_STAT_REG;
127 mask = *(volatile unsigned long *) PCI_INT_MASK_REG;
128 pend = stat & ~mask & 0xf0000000;
129 if (!pend)
130 break;
131 for (bit = 0; pend != 0; ++bit, pend <<= 1) {
132 if (pend & 0x80000000)
133 __do_IRQ(NR_CPM_INTS + bit, regs);
134 }
135 }
136
137 return IRQ_HANDLED;
138}
139
140static struct irqaction pq2pci_irqaction = {
141 .handler = pq2pci_irq_demux,
142 .flags = SA_INTERRUPT,
143 .mask = CPU_MASK_NONE,
144 .name = "PQ2 PCI cascade",
145};
146
147
148void
149pq2pci_init_irq(void)
150{
151 int irq;
152 volatile cpm2_map_t *immap = cpm2_immr;
153#if defined CONFIG_ADS8272
154 /* configure chip select for PCI interrupt controller */
155 immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801;
156 immap->im_memctl.memc_or3 = 0xffff8010;
157#elif defined CONFIG_PQ2FADS
158 immap->im_memctl.memc_br8 = PCI_INT_STAT_REG | 0x00001801;
159 immap->im_memctl.memc_or8 = 0xffff8010;
160#endif
161 for (irq = NR_CPM_INTS; irq < NR_CPM_INTS + 4; irq++)
162 irq_desc[irq].handler = &pq2pci_ic;
163
164 /* make PCI IRQ level sensitive */
165 immap->im_intctl.ic_siexr &=
166 ~(1 << (14 - (PCI_INT_TO_SIU - SIU_INT_IRQ1)));
167
168 /* mask all PCI interrupts */
169 *(volatile unsigned long *) PCI_INT_MASK_REG |= 0xfff00000;
170
171 /* install the demultiplexer for the PCI cascade interrupt */
172 setup_irq(PCI_INT_TO_SIU, &pq2pci_irqaction);
173 return;
174}
175
176static int
177pq2pci_exclude_device(u_char bus, u_char devfn)
178{
179 return PCIBIOS_SUCCESSFUL;
180}
181
182/* PCI bus configuration registers.
183 */
184static void
185pq2ads_setup_pci(struct pci_controller *hose)
186{
187 __u32 val;
188 volatile cpm2_map_t *immap = cpm2_immr;
189 bd_t* binfo = (bd_t*) __res;
190 u32 sccr = immap->im_clkrst.car_sccr;
191 uint pci_div,freq,time;
192 /* PCI int lowest prio */
193 /* Each 4 bits is a device bus request and the MS 4bits
194 is highest priority */
195 /* Bus 4bit value
196 --- ----------
197 CPM high 0b0000
198 CPM middle 0b0001
199 CPM low 0b0010
200 PCI reguest 0b0011
201 Reserved 0b0100
202 Reserved 0b0101
203 Internal Core 0b0110
204 External Master 1 0b0111
205 External Master 2 0b1000
206 External Master 3 0b1001
207 The rest are reserved
208 */
209 immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
210 /* park bus on core */
211 immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_CORE;
212 /*
213 * Set up master windows that allow the CPU to access PCI space. These
214 * windows are set up using the two SIU PCIBR registers.
215 */
216
217 immap->im_memctl.memc_pcimsk0 = M82xx_PCI_PRIM_WND_SIZE;
218 immap->im_memctl.memc_pcibr0 = M82xx_PCI_PRIM_WND_BASE | PCIBR_ENABLE;
219
220#ifdef M82xx_PCI_SEC_WND_SIZE
221 immap->im_memctl.memc_pcimsk1 = M82xx_PCI_SEC_WND_SIZE;
222 immap->im_memctl.memc_pcibr1 = M82xx_PCI_SEC_WND_BASE | PCIBR_ENABLE;
223#endif
224
225#if defined CONFIG_ADS8272
226 immap->im_siu_conf.siu_82xx.sc_siumcr =
227 (immap->im_siu_conf.siu_82xx.sc_siumcr &
228 ~(SIUMCR_BBD | SIUMCR_ESE | SIUMCR_PBSE |
229 SIUMCR_CDIS | SIUMCR_DPPC11 | SIUMCR_L2CPC11 |
230 SIUMCR_LBPC11 | SIUMCR_APPC11 |
231 SIUMCR_CS10PC11 | SIUMCR_BCTLC11 | SIUMCR_MMR11)) |
232 SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 |
233 SIUMCR_APPC10 | SIUMCR_CS10PC00 |
234 SIUMCR_BCTLC00 | SIUMCR_MMR11 ;
235
236#elif defined CONFIG_PQ2FADS
237 /*
238 * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
239 * and local bus for PCI (SIUMCR [LBPC]).
240 */
241 immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
242 ~(SIUMCR_L2PC11 | SIUMCR_LBPC11 | SIUMCR_CS10PC11 | SIUMCR_APPC11) |
243 SIUMCR_BBD | SIUMCR_LBPC01 | SIUMCR_DPPC11 | SIUMCR_APPC10;
244#endif
245 /* Enable PCI */
246 immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
247
248 pci_div = ( (sccr & SCCR_PCI_MODCK) ? 2 : 1) *
249 ( ( (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT) + 1);
250 freq = (uint)((2*binfo->bi_cpmfreq)/(pci_div));
251 time = (int)666666/freq;
252 /* due to PCI Local Bus spec, some devices needs to wait such a long
253 time after RST deassertion. More specifically, 0.508s for 66MHz & twice more for 33 */
254 printk("%s: The PCI bus is %d Mhz.\nWaiting %s after deasserting RST...\n",__FILE__,freq,
255 (time==1) ? "0.5 seconds":"1 second" );
256
257 {
258 int i;
259 for(i=0;i<(500*time);i++)
260 udelay(1000);
261 }
262
263 /* setup ATU registers */
264 immap->im_pci.pci_pocmr0 = cpu_to_le32(POCMR_ENABLE | POCMR_PCI_IO |
265 ((~(M82xx_PCI_IO_SIZE - 1U)) >> POTA_ADDR_SHIFT));
266 immap->im_pci.pci_potar0 = cpu_to_le32(M82xx_PCI_LOWER_IO >> POTA_ADDR_SHIFT);
267 immap->im_pci.pci_pobar0 = cpu_to_le32(M82xx_PCI_IO_BASE >> POTA_ADDR_SHIFT);
268
269 /* Set-up non-prefetchable window */
270 immap->im_pci.pci_pocmr1 = cpu_to_le32(POCMR_ENABLE | ((~(M82xx_PCI_MMIO_SIZE-1U)) >> POTA_ADDR_SHIFT));
271 immap->im_pci.pci_potar1 = cpu_to_le32(M82xx_PCI_LOWER_MMIO >> POTA_ADDR_SHIFT);
272 immap->im_pci.pci_pobar1 = cpu_to_le32((M82xx_PCI_LOWER_MMIO - M82xx_PCI_MMIO_OFFSET) >> POTA_ADDR_SHIFT);
273
274 /* Set-up prefetchable window */
275 immap->im_pci.pci_pocmr2 = cpu_to_le32(POCMR_ENABLE |POCMR_PREFETCH_EN |
276 (~(M82xx_PCI_MEM_SIZE-1U) >> POTA_ADDR_SHIFT));
277 immap->im_pci.pci_potar2 = cpu_to_le32(M82xx_PCI_LOWER_MEM >> POTA_ADDR_SHIFT);
278 immap->im_pci.pci_pobar2 = cpu_to_le32((M82xx_PCI_LOWER_MEM - M82xx_PCI_MEM_OFFSET) >> POTA_ADDR_SHIFT);
279
280 /* Inbound transactions from PCI memory space */
281 immap->im_pci.pci_picmr0 = cpu_to_le32(PICMR_ENABLE | PICMR_PREFETCH_EN |
282 ((~(M82xx_PCI_SLAVE_MEM_SIZE-1U)) >> PITA_ADDR_SHIFT));
283 immap->im_pci.pci_pibar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_BUS >> PITA_ADDR_SHIFT);
284 immap->im_pci.pci_pitar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_LOCAL>> PITA_ADDR_SHIFT);
285
286#if defined CONFIG_ADS8272
287 /* PCI int highest prio */
288 immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745;
289#elif defined CONFIG_PQ2FADS
290 immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
291#endif
292 /* park bus on PCI */
293 immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
294
295 /* Enable bus mastering and inbound memory transactions */
296 early_read_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, &val);
297 val &= 0xffff0000;
298 val |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
299 early_write_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, val);
300
301}
302
303void __init pq2_find_bridges(void)
304{
305 extern int pci_assign_all_busses;
306 struct pci_controller * hose;
307 int host_bridge;
308
309 pci_assign_all_busses = 1;
310
311 hose = pcibios_alloc_controller();
312
313 if (!hose)
314 return;
315
316 ppc_md.pci_swizzle = common_swizzle;
317
318 hose->first_busno = 0;
319 hose->bus_offset = 0;
320 hose->last_busno = 0xff;
321
322#ifdef CONFIG_ADS8272
323 hose->set_cfg_type = 1;
324#endif
325
326 setup_m8260_indirect_pci(hose,
327 (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
328 (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
329
330 /* Make sure it is a supported bridge */
331 early_read_config_dword(hose,
332 0,
333 PCI_DEVFN(0,0),
334 PCI_VENDOR_ID,
335 &host_bridge);
336 switch (host_bridge) {
337 case PCI_DEVICE_ID_MPC8265:
338 break;
339 case PCI_DEVICE_ID_MPC8272:
340 break;
341 default:
342 printk("Attempting to use unrecognized host bridge ID"
343 " 0x%08x.\n", host_bridge);
344 break;
345 }
346
347 pq2ads_setup_pci(hose);
348
349 hose->io_space.start = M82xx_PCI_LOWER_IO;
350 hose->io_space.end = M82xx_PCI_UPPER_IO;
351 hose->mem_space.start = M82xx_PCI_LOWER_MEM;
352 hose->mem_space.end = M82xx_PCI_UPPER_MMIO;
353 hose->pci_mem_offset = M82xx_PCI_MEM_OFFSET;
354
355 isa_io_base =
356 (unsigned long) ioremap(M82xx_PCI_IO_BASE,
357 M82xx_PCI_IO_SIZE);
358 hose->io_base_virt = (void *) isa_io_base;
359
360 /* setup resources */
361 pci_init_resource(&hose->mem_resources[0],
362 M82xx_PCI_LOWER_MEM,
363 M82xx_PCI_UPPER_MEM,
364 IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
365
366 pci_init_resource(&hose->mem_resources[1],
367 M82xx_PCI_LOWER_MMIO,
368 M82xx_PCI_UPPER_MMIO,
369 IORESOURCE_MEM, "PCI memory");
370
371 pci_init_resource(&hose->io_resource,
372 M82xx_PCI_LOWER_IO,
373 M82xx_PCI_UPPER_IO,
374 IORESOURCE_IO | 1, "PCI I/O");
375
376 ppc_md.pci_exclude_device = pq2pci_exclude_device;
377 hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
378
379 ppc_md.pci_map_irq = pq2pci_map_irq;
380 ppc_md.pcibios_fixup = NULL;
381 ppc_md.pcibios_fixup_bus = NULL;
382
383}
diff --git a/arch/ppc/syslib/m82xx_pci.h b/arch/ppc/syslib/m82xx_pci.h
new file mode 100644
index 000000000000..924f73f8e595
--- /dev/null
+++ b/arch/ppc/syslib/m82xx_pci.h
@@ -0,0 +1,92 @@
1
2#ifndef _PPC_KERNEL_M82XX_PCI_H
3#define _PPC_KERNEL_M82XX_PCI_H
4
5#include <asm/m8260_pci.h>
6/*
7 * Local->PCI map (from CPU) controlled by
8 * MPC826x master window
9 *
10 * 0xF6000000 - 0xF7FFFFFF IO space
11 * 0x80000000 - 0xBFFFFFFF CPU2PCI memory space PCIBR0
12 *
13 * 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1)
14 * 0xA0000000 - 0xBFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2)
15 * 0xF6000000 - 0xF7FFFFFF 32-bit PCI IO (Outbound ATU #3)
16 *
17 * PCI->Local map (from PCI)
18 * MPC826x slave window controlled by
19 *
20 * 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1)
21 */
22
23/*
24 * Slave window that allows PCI masters to access MPC826x local memory.
25 * This window is set up using the first set of Inbound ATU registers
26 */
27
28#ifndef M82xx_PCI_SLAVE_MEM_LOCAL
29#define M82xx_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart)
30#define M82xx_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart)
31#define M82xx_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize)
32#endif
33
34/*
35 * This is the window that allows the CPU to access PCI address space.
36 * It will be setup with the SIU PCIBR0 register. All three PCI master
37 * windows, which allow the CPU to access PCI prefetch, non prefetch,
38 * and IO space (see below), must all fit within this window.
39 */
40
41#ifndef M82xx_PCI_LOWER_MEM
42#define M82xx_PCI_LOWER_MEM 0x80000000
43#define M82xx_PCI_UPPER_MEM 0x9fffffff
44#define M82xx_PCI_MEM_OFFSET 0x00000000
45#define M82xx_PCI_MEM_SIZE 0x20000000
46#endif
47
48#ifndef M82xx_PCI_LOWER_MMIO
49#define M82xx_PCI_LOWER_MMIO 0xa0000000
50#define M82xx_PCI_UPPER_MMIO 0xafffffff
51#define M82xx_PCI_MMIO_OFFSET 0x00000000
52#define M82xx_PCI_MMIO_SIZE 0x20000000
53#endif
54
55#ifndef M82xx_PCI_LOWER_IO
56#define M82xx_PCI_LOWER_IO 0x00000000
57#define M82xx_PCI_UPPER_IO 0x01ffffff
58#define M82xx_PCI_IO_BASE 0xf6000000
59#define M82xx_PCI_IO_SIZE 0x02000000
60#endif
61
62#ifndef M82xx_PCI_PRIM_WND_SIZE
63#define M82xx_PCI_PRIM_WND_SIZE ~(M82xx_PCI_IO_SIZE - 1U)
64#define M82xx_PCI_PRIM_WND_BASE (M82xx_PCI_IO_BASE)
65#endif
66
67#ifndef M82xx_PCI_SEC_WND_SIZE
68#define M82xx_PCI_SEC_WND_SIZE ~(M82xx_PCI_MEM_SIZE + M82xx_PCI_MMIO_SIZE - 1U)
69#define M82xx_PCI_SEC_WND_BASE (M82xx_PCI_LOWER_MEM)
70#endif
71
72#ifndef POTA_ADDR_SHIFT
73#define POTA_ADDR_SHIFT 12
74#endif
75
76#ifndef PITA_ADDR_SHIFT
77#define PITA_ADDR_SHIFT 12
78#endif
79
80#ifndef _IO_BASE
81#define _IO_BASE isa_io_base
82#endif
83
84#ifdef CONFIG_8260_PCI9
85struct pci_controller;
86extern void setup_m8260_indirect_pci(struct pci_controller* hose,
87 u32 cfg_addr, u32 cfg_data);
88#else
89#define setup_m8260_indirect_pci setup_indirect_pci
90#endif
91
92#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
index 5c1a919eaabf..75c8e9834ae7 100644
--- a/arch/ppc/syslib/mpc83xx_devices.c
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
61 .iotype = UPIO_MEM, 61 .iotype = UPIO_MEM,
62 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, 62 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
63 }, 63 },
64 { },
64}; 65};
65 66
66struct platform_device ppc_sys_platform_devices[] = { 67struct platform_device ppc_sys_platform_devices[] = {
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index a231795ee26f..1e658ef57e75 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
61 .iotype = UPIO_MEM, 61 .iotype = UPIO_MEM,
62 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ, 62 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
63 }, 63 },
64 { },
64}; 65};
65 66
66struct platform_device ppc_sys_platform_devices[] = { 67struct platform_device ppc_sys_platform_devices[] = {
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 7619e16fccae..000ba47c67cb 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -275,7 +275,7 @@ static void __init openpic_enable_sie(void)
275} 275}
276#endif 276#endif
277 277
278#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PM) 278#if defined(CONFIG_EPIC_SERIAL_MODE)
279static void openpic_reset(void) 279static void openpic_reset(void)
280{ 280{
281 openpic_setfield(&OpenPIC->Global.Global_Configuration0, 281 openpic_setfield(&OpenPIC->Global.Global_Configuration0,
@@ -557,12 +557,10 @@ static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
557 */ 557 */
558void openpic_cause_IPI(u_int ipi, cpumask_t cpumask) 558void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
559{ 559{
560 cpumask_t phys;
561 DECL_THIS_CPU; 560 DECL_THIS_CPU;
562 561
563 CHECK_THIS_CPU; 562 CHECK_THIS_CPU;
564 check_arg_ipi(ipi); 563 check_arg_ipi(ipi);
565 phys = physmask(cpumask);
566 openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), 564 openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
567 cpus_addr(physmask(cpumask))[0]); 565 cpus_addr(physmask(cpumask))[0]);
568} 566}
@@ -995,8 +993,6 @@ int openpic_resume(struct sys_device *sysdev)
995 return 0; 993 return 0;
996 } 994 }
997 995
998 openpic_reset();
999
1000 /* OpenPIC sometimes seem to need some time to be fully back up... */ 996 /* OpenPIC sometimes seem to need some time to be fully back up... */
1001 do { 997 do {
1002 openpic_set_spurious(OPENPIC_VEC_SPURIOUS); 998 openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
index c28f9d679484..843cf8873e60 100644
--- a/arch/ppc/syslib/ppc83xx_setup.c
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -29,6 +29,7 @@
29#include <asm/mmu.h> 29#include <asm/mmu.h>
30#include <asm/ppc_sys.h> 30#include <asm/ppc_sys.h>
31#include <asm/kgdb.h> 31#include <asm/kgdb.h>
32#include <asm/delay.h>
32 33
33#include <syslib/ppc83xx_setup.h> 34#include <syslib/ppc83xx_setup.h>
34 35
@@ -117,7 +118,34 @@ mpc83xx_early_serial_map(void)
117void 118void
118mpc83xx_restart(char *cmd) 119mpc83xx_restart(char *cmd)
119{ 120{
121 volatile unsigned char __iomem *reg;
122 unsigned char tmp;
123
124 reg = ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
125
120 local_irq_disable(); 126 local_irq_disable();
127
128 /*
129 * Unlock the BCSR bits so a PRST will update the contents.
130 * Otherwise the reset asserts but doesn't clear.
131 */
132 tmp = in_8(reg + BCSR_MISC_REG3_OFF);
133 tmp |= BCSR_MISC_REG3_CNFLOCK; /* low true, high false */
134 out_8(reg + BCSR_MISC_REG3_OFF, tmp);
135
136 /*
137 * Trigger a reset via a low->high transition of the
138 * PORESET bit.
139 */
140 tmp = in_8(reg + BCSR_MISC_REG2_OFF);
141 tmp &= ~BCSR_MISC_REG2_PORESET;
142 out_8(reg + BCSR_MISC_REG2_OFF, tmp);
143
144 udelay(1);
145
146 tmp |= BCSR_MISC_REG2_PORESET;
147 out_8(reg + BCSR_MISC_REG2_OFF, tmp);
148
121 for(;;); 149 for(;;);
122} 150}
123 151
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
index 152c3ef1312a..f3277f469e78 100644
--- a/arch/ppc/syslib/ppc85xx_setup.c
+++ b/arch/ppc/syslib/ppc85xx_setup.c
@@ -132,6 +132,12 @@ mpc85xx_halt(void)
132} 132}
133 133
134#ifdef CONFIG_PCI 134#ifdef CONFIG_PCI
135
136#if defined(CONFIG_MPC8555_CDS)
137extern void mpc85xx_cds_enable_via(struct pci_controller *hose);
138extern void mpc85xx_cds_fixup_via(struct pci_controller *hose);
139#endif
140
135static void __init 141static void __init
136mpc85xx_setup_pci1(struct pci_controller *hose) 142mpc85xx_setup_pci1(struct pci_controller *hose)
137{ 143{
@@ -302,8 +308,18 @@ mpc85xx_setup_hose(void)
302 308
303 ppc_md.pci_exclude_device = mpc85xx_exclude_device; 309 ppc_md.pci_exclude_device = mpc85xx_exclude_device;
304 310
311#if defined(CONFIG_MPC8555_CDS)
312 /* Pre pciauto_bus_scan VIA init */
313 mpc85xx_cds_enable_via(hose_a);
314#endif
315
305 hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno); 316 hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
306 317
318#if defined(CONFIG_MPC8555_CDS)
319 /* Post pciauto_bus_scan VIA fixup */
320 mpc85xx_cds_fixup_via(hose_a);
321#endif
322
307#ifdef CONFIG_85xx_PCI2 323#ifdef CONFIG_85xx_PCI2
308 hose_b = pcibios_alloc_controller(); 324 hose_b = pcibios_alloc_controller();
309 325
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
index 2cee87137f2e..7f15136830f4 100644
--- a/arch/ppc/syslib/prom_init.c
+++ b/arch/ppc/syslib/prom_init.c
@@ -626,8 +626,18 @@ inspect_node(phandle node, struct device_node *dad,
626 l = call_prom("package-to-path", 3, 1, node, 626 l = call_prom("package-to-path", 3, 1, node,
627 mem_start, mem_end - mem_start); 627 mem_start, mem_end - mem_start);
628 if (l >= 0) { 628 if (l >= 0) {
629 char *p, *ep;
630
629 np->full_name = PTRUNRELOC((char *) mem_start); 631 np->full_name = PTRUNRELOC((char *) mem_start);
630 *(char *)(mem_start + l) = 0; 632 *(char *)(mem_start + l) = 0;
633 /* Fixup an Apple bug where they have bogus \0 chars in the
634 * middle of the path in some properties
635 */
636 for (p = (char *)mem_start, ep = p + l; p < ep; p++)
637 if ((*p) == '\0') {
638 memmove(p, p+1, ep - p);
639 ep--;
640 }
631 mem_start = ALIGNUL(mem_start + l + 1); 641 mem_start = ALIGNUL(mem_start + l + 1);
632 } 642 }
633 643
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index f5508abf1188..5cb343883e4d 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -40,6 +40,10 @@ config COMPAT
40 bool 40 bool
41 default y 41 default y
42 42
43config SCHED_NO_NO_OMIT_FRAME_POINTER
44 bool
45 default y
46
43# We optimistically allocate largepages from the VM, so make the limit 47# We optimistically allocate largepages from the VM, so make the limit
44# large enough (16MB). This badly named config option is actually 48# large enough (16MB). This badly named config option is actually
45# max order + 1 49# max order + 1
@@ -258,6 +262,7 @@ config PPC_RTAS
258config RTAS_PROC 262config RTAS_PROC
259 bool "Proc interface to RTAS" 263 bool "Proc interface to RTAS"
260 depends on PPC_RTAS 264 depends on PPC_RTAS
265 default y
261 266
262config RTAS_FLASH 267config RTAS_FLASH
263 tristate "Firmware flash interface" 268 tristate "Firmware flash interface"
diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
index e341a129da80..46b1ce58da3b 100644
--- a/arch/ppc64/Kconfig.debug
+++ b/arch/ppc64/Kconfig.debug
@@ -5,6 +5,9 @@ source "lib/Kconfig.debug"
5config DEBUG_STACKOVERFLOW 5config DEBUG_STACKOVERFLOW
6 bool "Check for stack overflows" 6 bool "Check for stack overflows"
7 depends on DEBUG_KERNEL 7 depends on DEBUG_KERNEL
8 help
9 This option will cause messages to be printed if free stack space
10 drops below a certain limit.
8 11
9config KPROBES 12config KPROBES
10 bool "Kprobes" 13 bool "Kprobes"
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index b0fa86ad8b1b..da12ea2ca464 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -14,7 +14,6 @@
14#include <linux/string.h> 14#include <linux/string.h>
15#include <asm/processor.h> 15#include <asm/processor.h>
16#include <asm/page.h> 16#include <asm/page.h>
17#include <asm/bootinfo.h>
18 17
19extern void *finddevice(const char *); 18extern void *finddevice(const char *);
20extern int getprop(void *, const char *, void *, int); 19extern int getprop(void *, const char *, void *, int);
diff --git a/arch/ppc64/boot/start.c b/arch/ppc64/boot/start.c
deleted file mode 100644
index ea247e79b55e..000000000000
--- a/arch/ppc64/boot/start.c
+++ /dev/null
@@ -1,654 +0,0 @@
1/*
2 * Copyright (C) Paul Mackerras 1997.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <stdarg.h>
10#include <linux/types.h>
11#include <linux/string.h>
12#include <linux/ctype.h>
13
14#include <asm/div64.h>
15
16int (*prom)(void *);
17
18void *chosen_handle;
19void *stdin;
20void *stdout;
21void *stderr;
22
23void exit(void);
24void *finddevice(const char *name);
25int getprop(void *phandle, const char *name, void *buf, int buflen);
26void chrpboot(int a1, int a2, void *prom); /* in main.c */
27
28void printk(char *fmt, ...);
29
30void
31start(int a1, int a2, void *promptr)
32{
33 prom = (int (*)(void *)) promptr;
34 chosen_handle = finddevice("/chosen");
35 if (chosen_handle == (void *) -1)
36 exit();
37 if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
38 exit();
39 stderr = stdout;
40 if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
41 exit();
42
43 chrpboot(a1, a2, promptr);
44 for (;;)
45 exit();
46}
47
48int
49write(void *handle, void *ptr, int nb)
50{
51 struct prom_args {
52 char *service;
53 int nargs;
54 int nret;
55 void *ihandle;
56 void *addr;
57 int len;
58 int actual;
59 } args;
60
61 args.service = "write";
62 args.nargs = 3;
63 args.nret = 1;
64 args.ihandle = handle;
65 args.addr = ptr;
66 args.len = nb;
67 args.actual = -1;
68 (*prom)(&args);
69 return args.actual;
70}
71
72int
73read(void *handle, void *ptr, int nb)
74{
75 struct prom_args {
76 char *service;
77 int nargs;
78 int nret;
79 void *ihandle;
80 void *addr;
81 int len;
82 int actual;
83 } args;
84
85 args.service = "read";
86 args.nargs = 3;
87 args.nret = 1;
88 args.ihandle = handle;
89 args.addr = ptr;
90 args.len = nb;
91 args.actual = -1;
92 (*prom)(&args);
93 return args.actual;
94}
95
96void
97exit()
98{
99 struct prom_args {
100 char *service;
101 } args;
102
103 for (;;) {
104 args.service = "exit";
105 (*prom)(&args);
106 }
107}
108
109void
110pause(void)
111{
112 struct prom_args {
113 char *service;
114 } args;
115
116 args.service = "enter";
117 (*prom)(&args);
118}
119
120void *
121finddevice(const char *name)
122{
123 struct prom_args {
124 char *service;
125 int nargs;
126 int nret;
127 const char *devspec;
128 void *phandle;
129 } args;
130
131 args.service = "finddevice";
132 args.nargs = 1;
133 args.nret = 1;
134 args.devspec = name;
135 args.phandle = (void *) -1;
136 (*prom)(&args);
137 return args.phandle;
138}
139
140void *
141claim(unsigned long virt, unsigned long size, unsigned long align)
142{
143 struct prom_args {
144 char *service;
145 int nargs;
146 int nret;
147 unsigned int virt;
148 unsigned int size;
149 unsigned int align;
150 void *ret;
151 } args;
152
153 args.service = "claim";
154 args.nargs = 3;
155 args.nret = 1;
156 args.virt = virt;
157 args.size = size;
158 args.align = align;
159 (*prom)(&args);
160 return args.ret;
161}
162
163int
164getprop(void *phandle, const char *name, void *buf, int buflen)
165{
166 struct prom_args {
167 char *service;
168 int nargs;
169 int nret;
170 void *phandle;
171 const char *name;
172 void *buf;
173 int buflen;
174 int size;
175 } args;
176
177 args.service = "getprop";
178 args.nargs = 4;
179 args.nret = 1;
180 args.phandle = phandle;
181 args.name = name;
182 args.buf = buf;
183 args.buflen = buflen;
184 args.size = -1;
185 (*prom)(&args);
186 return args.size;
187}
188
189int
190putc(int c, void *f)
191{
192 char ch = c;
193
194 if (c == '\n')
195 putc('\r', f);
196 return write(f, &ch, 1) == 1? c: -1;
197}
198
199int
200putchar(int c)
201{
202 return putc(c, stdout);
203}
204
205int
206fputs(char *str, void *f)
207{
208 int n = strlen(str);
209
210 return write(f, str, n) == n? 0: -1;
211}
212
213int
214readchar(void)
215{
216 char ch;
217
218 for (;;) {
219 switch (read(stdin, &ch, 1)) {
220 case 1:
221 return ch;
222 case -1:
223 printk("read(stdin) returned -1\r\n");
224 return -1;
225 }
226 }
227}
228
229static char line[256];
230static char *lineptr;
231static int lineleft;
232
233int
234getchar(void)
235{
236 int c;
237
238 if (lineleft == 0) {
239 lineptr = line;
240 for (;;) {
241 c = readchar();
242 if (c == -1 || c == 4)
243 break;
244 if (c == '\r' || c == '\n') {
245 *lineptr++ = '\n';
246 putchar('\n');
247 break;
248 }
249 switch (c) {
250 case 0177:
251 case '\b':
252 if (lineptr > line) {
253 putchar('\b');
254 putchar(' ');
255 putchar('\b');
256 --lineptr;
257 }
258 break;
259 case 'U' & 0x1F:
260 while (lineptr > line) {
261 putchar('\b');
262 putchar(' ');
263 putchar('\b');
264 --lineptr;
265 }
266 break;
267 default:
268 if (lineptr >= &line[sizeof(line) - 1])
269 putchar('\a');
270 else {
271 putchar(c);
272 *lineptr++ = c;
273 }
274 }
275 }
276 lineleft = lineptr - line;
277 lineptr = line;
278 }
279 if (lineleft == 0)
280 return -1;
281 --lineleft;
282 return *lineptr++;
283}
284
285
286
287/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
288unsigned char _ctype[] = {
289_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
290_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
291_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
292_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
293_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
294_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
295_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
296_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
297_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
298_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
299_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
300_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
301_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
302_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
303_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
304_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
3050,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
307_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
308_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
309_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
310_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
311_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
312_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
313
314size_t strnlen(const char * s, size_t count)
315{
316 const char *sc;
317
318 for (sc = s; count-- && *sc != '\0'; ++sc)
319 /* nothing */;
320 return sc - s;
321}
322
323unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
324{
325 unsigned long result = 0,value;
326
327 if (!base) {
328 base = 10;
329 if (*cp == '0') {
330 base = 8;
331 cp++;
332 if ((*cp == 'x') && isxdigit(cp[1])) {
333 cp++;
334 base = 16;
335 }
336 }
337 }
338 while (isxdigit(*cp) &&
339 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
340 result = result*base + value;
341 cp++;
342 }
343 if (endp)
344 *endp = (char *)cp;
345 return result;
346}
347
348long simple_strtol(const char *cp,char **endp,unsigned int base)
349{
350 if(*cp=='-')
351 return -simple_strtoul(cp+1,endp,base);
352 return simple_strtoul(cp,endp,base);
353}
354
355static int skip_atoi(const char **s)
356{
357 int i=0;
358
359 while (isdigit(**s))
360 i = i*10 + *((*s)++) - '0';
361 return i;
362}
363
364#define ZEROPAD 1 /* pad with zero */
365#define SIGN 2 /* unsigned/signed long */
366#define PLUS 4 /* show plus */
367#define SPACE 8 /* space if plus */
368#define LEFT 16 /* left justified */
369#define SPECIAL 32 /* 0x */
370#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
371
372static char * number(char * str, long long num, int base, int size, int precision, int type)
373{
374 char c,sign,tmp[66];
375 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
376 int i;
377
378 if (type & LARGE)
379 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
380 if (type & LEFT)
381 type &= ~ZEROPAD;
382 if (base < 2 || base > 36)
383 return 0;
384 c = (type & ZEROPAD) ? '0' : ' ';
385 sign = 0;
386 if (type & SIGN) {
387 if (num < 0) {
388 sign = '-';
389 num = -num;
390 size--;
391 } else if (type & PLUS) {
392 sign = '+';
393 size--;
394 } else if (type & SPACE) {
395 sign = ' ';
396 size--;
397 }
398 }
399 if (type & SPECIAL) {
400 if (base == 16)
401 size -= 2;
402 else if (base == 8)
403 size--;
404 }
405 i = 0;
406 if (num == 0)
407 tmp[i++]='0';
408 else while (num != 0)
409 tmp[i++] = digits[do_div(num,base)];
410 if (i > precision)
411 precision = i;
412 size -= precision;
413 if (!(type&(ZEROPAD+LEFT)))
414 while(size-->0)
415 *str++ = ' ';
416 if (sign)
417 *str++ = sign;
418 if (type & SPECIAL) {
419 if (base==8)
420 *str++ = '0';
421 else if (base==16) {
422 *str++ = '0';
423 *str++ = digits[33];
424 }
425 }
426 if (!(type & LEFT))
427 while (size-- > 0)
428 *str++ = c;
429 while (i < precision--)
430 *str++ = '0';
431 while (i-- > 0)
432 *str++ = tmp[i];
433 while (size-- > 0)
434 *str++ = ' ';
435 return str;
436}
437
438/* Forward decl. needed for IP address printing stuff... */
439int sprintf(char * buf, const char *fmt, ...);
440
441int vsprintf(char *buf, const char *fmt, va_list args)
442{
443 int len;
444 unsigned long long num;
445 int i, base;
446 char * str;
447 const char *s;
448
449 int flags; /* flags to number() */
450
451 int field_width; /* width of output field */
452 int precision; /* min. # of digits for integers; max
453 number of chars for from string */
454 int qualifier; /* 'h', 'l', or 'L' for integer fields */
455 /* 'z' support added 23/7/1999 S.H. */
456 /* 'z' changed to 'Z' --davidm 1/25/99 */
457
458
459 for (str=buf ; *fmt ; ++fmt) {
460 if (*fmt != '%') {
461 *str++ = *fmt;
462 continue;
463 }
464
465 /* process flags */
466 flags = 0;
467 repeat:
468 ++fmt; /* this also skips first '%' */
469 switch (*fmt) {
470 case '-': flags |= LEFT; goto repeat;
471 case '+': flags |= PLUS; goto repeat;
472 case ' ': flags |= SPACE; goto repeat;
473 case '#': flags |= SPECIAL; goto repeat;
474 case '0': flags |= ZEROPAD; goto repeat;
475 }
476
477 /* get field width */
478 field_width = -1;
479 if (isdigit(*fmt))
480 field_width = skip_atoi(&fmt);
481 else if (*fmt == '*') {
482 ++fmt;
483 /* it's the next argument */
484 field_width = va_arg(args, int);
485 if (field_width < 0) {
486 field_width = -field_width;
487 flags |= LEFT;
488 }
489 }
490
491 /* get the precision */
492 precision = -1;
493 if (*fmt == '.') {
494 ++fmt;
495 if (isdigit(*fmt))
496 precision = skip_atoi(&fmt);
497 else if (*fmt == '*') {
498 ++fmt;
499 /* it's the next argument */
500 precision = va_arg(args, int);
501 }
502 if (precision < 0)
503 precision = 0;
504 }
505
506 /* get the conversion qualifier */
507 qualifier = -1;
508 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
509 qualifier = *fmt;
510 ++fmt;
511 }
512
513 /* default base */
514 base = 10;
515
516 switch (*fmt) {
517 case 'c':
518 if (!(flags & LEFT))
519 while (--field_width > 0)
520 *str++ = ' ';
521 *str++ = (unsigned char) va_arg(args, int);
522 while (--field_width > 0)
523 *str++ = ' ';
524 continue;
525
526 case 's':
527 s = va_arg(args, char *);
528 if (!s)
529 s = "<NULL>";
530
531 len = strnlen(s, precision);
532
533 if (!(flags & LEFT))
534 while (len < field_width--)
535 *str++ = ' ';
536 for (i = 0; i < len; ++i)
537 *str++ = *s++;
538 while (len < field_width--)
539 *str++ = ' ';
540 continue;
541
542 case 'p':
543 if (field_width == -1) {
544 field_width = 2*sizeof(void *);
545 flags |= ZEROPAD;
546 }
547 str = number(str,
548 (unsigned long) va_arg(args, void *), 16,
549 field_width, precision, flags);
550 continue;
551
552
553 case 'n':
554 if (qualifier == 'l') {
555 long * ip = va_arg(args, long *);
556 *ip = (str - buf);
557 } else if (qualifier == 'Z') {
558 size_t * ip = va_arg(args, size_t *);
559 *ip = (str - buf);
560 } else {
561 int * ip = va_arg(args, int *);
562 *ip = (str - buf);
563 }
564 continue;
565
566 case '%':
567 *str++ = '%';
568 continue;
569
570 /* integer number formats - set up the flags and "break" */
571 case 'o':
572 base = 8;
573 break;
574
575 case 'X':
576 flags |= LARGE;
577 case 'x':
578 base = 16;
579 break;
580
581 case 'd':
582 case 'i':
583 flags |= SIGN;
584 case 'u':
585 break;
586
587 default:
588 *str++ = '%';
589 if (*fmt)
590 *str++ = *fmt;
591 else
592 --fmt;
593 continue;
594 }
595 if (qualifier == 'L')
596 num = va_arg(args, long long);
597 else if (qualifier == 'l') {
598 num = va_arg(args, unsigned long);
599 if (flags & SIGN)
600 num = (signed long) num;
601 } else if (qualifier == 'Z') {
602 num = va_arg(args, size_t);
603 } else if (qualifier == 'h') {
604 num = (unsigned short) va_arg(args, int);
605 if (flags & SIGN)
606 num = (signed short) num;
607 } else {
608 num = va_arg(args, unsigned int);
609 if (flags & SIGN)
610 num = (signed int) num;
611 }
612 str = number(str, num, base, field_width, precision, flags);
613 }
614 *str = '\0';
615 return str-buf;
616}
617
618int sprintf(char * buf, const char *fmt, ...)
619{
620 va_list args;
621 int i;
622
623 va_start(args, fmt);
624 i=vsprintf(buf,fmt,args);
625 va_end(args);
626 return i;
627}
628
629static char sprint_buf[1024];
630
631void
632printk(char *fmt, ...)
633{
634 va_list args;
635 int n;
636
637 va_start(args, fmt);
638 n = vsprintf(sprint_buf, fmt, args);
639 va_end(args);
640 write(stdout, sprint_buf, n);
641}
642
643int
644printf(char *fmt, ...)
645{
646 va_list args;
647 int n;
648
649 va_start(args, fmt);
650 n = vsprintf(sprint_buf, fmt, args);
651 va_end(args);
652 write(stdout, sprint_buf, n);
653 return n;
654}
diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
index 1bd52ece497c..5aca7e8005a8 100644
--- a/arch/ppc64/kernel/mf.c
+++ b/arch/ppc64/kernel/mf.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * mf.c 2 * mf.c
3 * Copyright (C) 2001 Troy D. Armstrong IBM Corporation 3 * Copyright (C) 2001 Troy D. Armstrong IBM Corporation
4 * Copyright (C) 2004 Stephen Rothwell IBM Corporation 4 * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation
5 * 5 *
6 * This modules exists as an interface between a Linux secondary partition 6 * This modules exists as an interface between a Linux secondary partition
7 * running on an iSeries and the primary partition's Virtual Service 7 * running on an iSeries and the primary partition's Virtual Service
@@ -36,10 +36,12 @@
36 36
37#include <asm/time.h> 37#include <asm/time.h>
38#include <asm/uaccess.h> 38#include <asm/uaccess.h>
39#include <asm/paca.h>
39#include <asm/iSeries/vio.h> 40#include <asm/iSeries/vio.h>
40#include <asm/iSeries/mf.h> 41#include <asm/iSeries/mf.h>
41#include <asm/iSeries/HvLpConfig.h> 42#include <asm/iSeries/HvLpConfig.h>
42#include <asm/iSeries/ItSpCommArea.h> 43#include <asm/iSeries/ItSpCommArea.h>
44#include <asm/iSeries/ItLpQueue.h>
43 45
44/* 46/*
45 * This is the structure layout for the Machine Facilites LPAR event 47 * This is the structure layout for the Machine Facilites LPAR event
@@ -696,36 +698,23 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
696 complete(&rtc->com); 698 complete(&rtc->com);
697} 699}
698 700
699int mf_get_rtc(struct rtc_time *tm) 701static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
700{ 702{
701 struct ce_msg_comp_data ce_complete;
702 struct rtc_time_data rtc_data;
703 int rc;
704
705 memset(&ce_complete, 0, sizeof(ce_complete));
706 memset(&rtc_data, 0, sizeof(rtc_data));
707 init_completion(&rtc_data.com);
708 ce_complete.handler = &get_rtc_time_complete;
709 ce_complete.token = &rtc_data;
710 rc = signal_ce_msg_simple(0x40, &ce_complete);
711 if (rc)
712 return rc;
713 wait_for_completion(&rtc_data.com);
714 tm->tm_wday = 0; 703 tm->tm_wday = 0;
715 tm->tm_yday = 0; 704 tm->tm_yday = 0;
716 tm->tm_isdst = 0; 705 tm->tm_isdst = 0;
717 if (rtc_data.rc) { 706 if (rc) {
718 tm->tm_sec = 0; 707 tm->tm_sec = 0;
719 tm->tm_min = 0; 708 tm->tm_min = 0;
720 tm->tm_hour = 0; 709 tm->tm_hour = 0;
721 tm->tm_mday = 15; 710 tm->tm_mday = 15;
722 tm->tm_mon = 5; 711 tm->tm_mon = 5;
723 tm->tm_year = 52; 712 tm->tm_year = 52;
724 return rtc_data.rc; 713 return rc;
725 } 714 }
726 715
727 if ((rtc_data.ce_msg.ce_msg[2] == 0xa9) || 716 if ((ce_msg[2] == 0xa9) ||
728 (rtc_data.ce_msg.ce_msg[2] == 0xaf)) { 717 (ce_msg[2] == 0xaf)) {
729 /* TOD clock is not set */ 718 /* TOD clock is not set */
730 tm->tm_sec = 1; 719 tm->tm_sec = 1;
731 tm->tm_min = 1; 720 tm->tm_min = 1;
@@ -736,7 +725,6 @@ int mf_get_rtc(struct rtc_time *tm)
736 mf_set_rtc(tm); 725 mf_set_rtc(tm);
737 } 726 }
738 { 727 {
739 u8 *ce_msg = rtc_data.ce_msg.ce_msg;
740 u8 year = ce_msg[5]; 728 u8 year = ce_msg[5];
741 u8 sec = ce_msg[6]; 729 u8 sec = ce_msg[6];
742 u8 min = ce_msg[7]; 730 u8 min = ce_msg[7];
@@ -765,6 +753,63 @@ int mf_get_rtc(struct rtc_time *tm)
765 return 0; 753 return 0;
766} 754}
767 755
756int mf_get_rtc(struct rtc_time *tm)
757{
758 struct ce_msg_comp_data ce_complete;
759 struct rtc_time_data rtc_data;
760 int rc;
761
762 memset(&ce_complete, 0, sizeof(ce_complete));
763 memset(&rtc_data, 0, sizeof(rtc_data));
764 init_completion(&rtc_data.com);
765 ce_complete.handler = &get_rtc_time_complete;
766 ce_complete.token = &rtc_data;
767 rc = signal_ce_msg_simple(0x40, &ce_complete);
768 if (rc)
769 return rc;
770 wait_for_completion(&rtc_data.com);
771 return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
772}
773
774struct boot_rtc_time_data {
775 int busy;
776 struct ce_msg_data ce_msg;
777 int rc;
778};
779
780static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
781{
782 struct boot_rtc_time_data *rtc = token;
783
784 memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
785 rtc->rc = 0;
786 rtc->busy = 0;
787}
788
789int mf_get_boot_rtc(struct rtc_time *tm)
790{
791 struct ce_msg_comp_data ce_complete;
792 struct boot_rtc_time_data rtc_data;
793 int rc;
794
795 memset(&ce_complete, 0, sizeof(ce_complete));
796 memset(&rtc_data, 0, sizeof(rtc_data));
797 rtc_data.busy = 1;
798 ce_complete.handler = &get_boot_rtc_time_complete;
799 ce_complete.token = &rtc_data;
800 rc = signal_ce_msg_simple(0x40, &ce_complete);
801 if (rc)
802 return rc;
803 /* We need to poll here as we are not yet taking interrupts */
804 while (rtc_data.busy) {
805 extern unsigned long lpevent_count;
806 struct ItLpQueue *lpq = get_paca()->lpqueue_ptr;
807 if (lpq && ItLpQueue_isLpIntPending(lpq))
808 lpevent_count += ItLpQueue_process(lpq, NULL);
809 }
810 return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
811}
812
768int mf_set_rtc(struct rtc_time *tm) 813int mf_set_rtc(struct rtc_time *tm)
769{ 814{
770 char ce_time[12]; 815 char ce_time[12];
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index 90b41f48d21c..b944717c1dbd 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -32,7 +32,7 @@
32 .text 32 .text
33 33
34/* 34/*
35 * Returns (address we're running at) - (address we were linked at) 35 * Returns (address we were linked at) - (address we are running at)
36 * for use before the text and data are mapped to KERNELBASE. 36 * for use before the text and data are mapped to KERNELBASE.
37 */ 37 */
38 38
diff --git a/arch/ppc64/kernel/pSeries_reconfig.c b/arch/ppc64/kernel/pSeries_reconfig.c
index cb5443f2e49b..dc2a69d412a2 100644
--- a/arch/ppc64/kernel/pSeries_reconfig.c
+++ b/arch/ppc64/kernel/pSeries_reconfig.c
@@ -47,14 +47,6 @@ static void remove_node_proc_entries(struct device_node *np)
47 remove_proc_entry(pp->name, np->pde); 47 remove_proc_entry(pp->name, np->pde);
48 pp = pp->next; 48 pp = pp->next;
49 } 49 }
50
51 /* Assuming that symlinks have the same parent directory as
52 * np->pde.
53 */
54 if (np->name_link)
55 remove_proc_entry(np->name_link->name, parent->pde);
56 if (np->addr_link)
57 remove_proc_entry(np->addr_link->name, parent->pde);
58 if (np->pde) 50 if (np->pde)
59 remove_proc_entry(np->pde->name, parent->pde); 51 remove_proc_entry(np->pde->name, parent->pde);
60} 52}
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index c60d8cb2b84d..fbad349ec58c 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -326,13 +326,6 @@ static void __devinit smp_xics_setup_cpu(int cpu)
326 326
327 cpu_clear(cpu, of_spin_map); 327 cpu_clear(cpu, of_spin_map);
328 328
329 /*
330 * Put the calling processor into the GIQ. This is really only
331 * necessary from a secondary thread as the OF start-cpu interface
332 * performs this function for us on primary threads.
333 */
334 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
335 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
336} 329}
337 330
338static DEFINE_SPINLOCK(timebase_lock); 331static DEFINE_SPINLOCK(timebase_lock);
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index be3cc387c1ec..d786d4b6af0b 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -438,7 +438,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
438 int i; 438 int i;
439 439
440 if (page_is_ram(offset >> PAGE_SHIFT)) 440 if (page_is_ram(offset >> PAGE_SHIFT))
441 return prot; 441 return __pgprot(prot);
442 442
443 prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; 443 prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
444 444
diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
index c27588ede2fe..a23de37227bf 100644
--- a/arch/ppc64/kernel/pmac_smp.c
+++ b/arch/ppc64/kernel/pmac_smp.c
@@ -68,6 +68,7 @@ extern struct smp_ops_t *smp_ops;
68 68
69static void (*pmac_tb_freeze)(int freeze); 69static void (*pmac_tb_freeze)(int freeze);
70static struct device_node *pmac_tb_clock_chip_host; 70static struct device_node *pmac_tb_clock_chip_host;
71static u8 pmac_tb_pulsar_addr;
71static DEFINE_SPINLOCK(timebase_lock); 72static DEFINE_SPINLOCK(timebase_lock);
72static unsigned long timebase; 73static unsigned long timebase;
73 74
@@ -106,12 +107,9 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
106 u8 data; 107 u8 data;
107 int rc; 108 int rc;
108 109
109 /* Strangely, the device-tree says address is 0xd2, but darwin
110 * accesses 0xd0 ...
111 */
112 pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined); 110 pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
113 rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, 111 rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
114 0xd4 | pmac_low_i2c_read, 112 pmac_tb_pulsar_addr | pmac_low_i2c_read,
115 0x2e, &data, 1); 113 0x2e, &data, 1);
116 if (rc != 0) 114 if (rc != 0)
117 goto bail; 115 goto bail;
@@ -120,7 +118,7 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
120 118
121 pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub); 119 pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
122 rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, 120 rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
123 0xd4 | pmac_low_i2c_write, 121 pmac_tb_pulsar_addr | pmac_low_i2c_write,
124 0x2e, &data, 1); 122 0x2e, &data, 1);
125 bail: 123 bail:
126 if (rc != 0) { 124 if (rc != 0) {
@@ -185,6 +183,12 @@ static int __init smp_core99_probe(void)
185 if (ncpus <= 1) 183 if (ncpus <= 1)
186 return 1; 184 return 1;
187 185
186 /* HW sync only on these platforms */
187 if (!machine_is_compatible("PowerMac7,2") &&
188 !machine_is_compatible("PowerMac7,3") &&
189 !machine_is_compatible("RackMac3,1"))
190 goto nohwsync;
191
188 /* Look for the clock chip */ 192 /* Look for the clock chip */
189 for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) { 193 for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) {
190 struct device_node *p = of_get_parent(cc); 194 struct device_node *p = of_get_parent(cc);
@@ -198,11 +202,18 @@ static int __init smp_core99_probe(void)
198 goto next; 202 goto next;
199 switch (*reg) { 203 switch (*reg) {
200 case 0xd2: 204 case 0xd2:
201 pmac_tb_freeze = smp_core99_cypress_tb_freeze; 205 if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
202 printk(KERN_INFO "Timebase clock is Cypress chip\n"); 206 pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
207 pmac_tb_pulsar_addr = 0xd2;
208 printk(KERN_INFO "Timebase clock is Pulsar chip\n");
209 } else if (device_is_compatible(cc, "cy28508")) {
210 pmac_tb_freeze = smp_core99_cypress_tb_freeze;
211 printk(KERN_INFO "Timebase clock is Cypress chip\n");
212 }
203 break; 213 break;
204 case 0xd4: 214 case 0xd4:
205 pmac_tb_freeze = smp_core99_pulsar_tb_freeze; 215 pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
216 pmac_tb_pulsar_addr = 0xd4;
206 printk(KERN_INFO "Timebase clock is Pulsar chip\n"); 217 printk(KERN_INFO "Timebase clock is Pulsar chip\n");
207 break; 218 break;
208 } 219 }
@@ -210,12 +221,15 @@ static int __init smp_core99_probe(void)
210 pmac_tb_clock_chip_host = p; 221 pmac_tb_clock_chip_host = p;
211 smp_ops->give_timebase = smp_core99_give_timebase; 222 smp_ops->give_timebase = smp_core99_give_timebase;
212 smp_ops->take_timebase = smp_core99_take_timebase; 223 smp_ops->take_timebase = smp_core99_take_timebase;
224 of_node_put(cc);
225 of_node_put(p);
213 break; 226 break;
214 } 227 }
215 next: 228 next:
216 of_node_put(p); 229 of_node_put(p);
217 } 230 }
218 231
232 nohwsync:
219 mpic_request_ipis(); 233 mpic_request_ipis();
220 234
221 return ncpus; 235 return ncpus;
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index fe2946c58314..eb6538b58008 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -834,7 +834,7 @@ void __init unflatten_device_tree(void)
834{ 834{
835 unsigned long start, mem, size; 835 unsigned long start, mem, size;
836 struct device_node **allnextp = &allnodes; 836 struct device_node **allnextp = &allnodes;
837 char *p; 837 char *p = NULL;
838 int l = 0; 838 int l = 0;
839 839
840 DBG(" -> unflatten_device_tree()\n"); 840 DBG(" -> unflatten_device_tree()\n");
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index 35ec42de962e..1ac531ba7056 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -211,13 +211,23 @@ struct {
211 */ 211 */
212#define ADDR(x) (u32) ((unsigned long)(x) - offset) 212#define ADDR(x) (u32) ((unsigned long)(x) - offset)
213 213
214/*
215 * Error results ... some OF calls will return "-1" on error, some
216 * will return 0, some will return either. To simplify, here are
217 * macros to use with any ihandle or phandle return value to check if
218 * it is valid
219 */
220
221#define PROM_ERROR (-1u)
222#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
223#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
224
225
214/* This is the one and *ONLY* place where we actually call open 226/* This is the one and *ONLY* place where we actually call open
215 * firmware from, since we need to make sure we're running in 32b 227 * firmware from, since we need to make sure we're running in 32b
216 * mode when we do. We switch back to 64b mode upon return. 228 * mode when we do. We switch back to 64b mode upon return.
217 */ 229 */
218 230
219#define PROM_ERROR (-1)
220
221static int __init call_prom(const char *service, int nargs, int nret, ...) 231static int __init call_prom(const char *service, int nargs, int nret, ...)
222{ 232{
223 int i; 233 int i;
@@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void)
587{ 597{
588 unsigned long offset = reloc_offset(); 598 unsigned long offset = reloc_offset();
589 ihandle elfloader; 599 ihandle elfloader;
590 int ret;
591 600
592 elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); 601 elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
593 if (elfloader == 0) { 602 if (elfloader == 0) {
594 prom_printf("couldn't open /packages/elf-loader\n"); 603 prom_printf("couldn't open /packages/elf-loader\n");
595 return; 604 return;
596 } 605 }
597 ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"), 606 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
598 elfloader, ADDR(&fake_elf)); 607 elfloader, ADDR(&fake_elf));
599 call_prom("close", 1, 0, elfloader); 608 call_prom("close", 1, 0, elfloader);
600} 609}
@@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align)
646 base = _ALIGN_UP(base + 0x100000, align)) { 655 base = _ALIGN_UP(base + 0x100000, align)) {
647 prom_debug(" trying: 0x%x\n\r", base); 656 prom_debug(" trying: 0x%x\n\r", base);
648 addr = (unsigned long)prom_claim(base, size, 0); 657 addr = (unsigned long)prom_claim(base, size, 0);
649 if ((int)addr != PROM_ERROR) 658 if (addr != PROM_ERROR)
650 break; 659 break;
651 addr = 0; 660 addr = 0;
652 if (align == 0) 661 if (align == 0)
@@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align,
708 for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { 717 for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) {
709 prom_debug(" trying: 0x%x\n\r", base); 718 prom_debug(" trying: 0x%x\n\r", base);
710 addr = (unsigned long)prom_claim(base, size, 0); 719 addr = (unsigned long)prom_claim(base, size, 0);
711 if ((int)addr != PROM_ERROR) 720 if (addr != PROM_ERROR)
712 break; 721 break;
713 addr = 0; 722 addr = 0;
714 } 723 }
@@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void)
902{ 911{
903 unsigned long offset = reloc_offset(); 912 unsigned long offset = reloc_offset();
904 struct prom_t *_prom = PTRRELOC(&prom); 913 struct prom_t *_prom = PTRRELOC(&prom);
905 phandle prom_rtas, rtas_node; 914 phandle rtas_node;
915 ihandle rtas_inst;
906 u32 base, entry = 0; 916 u32 base, entry = 0;
907 u32 size = 0; 917 u32 size = 0;
908 918
909 prom_debug("prom_instantiate_rtas: start...\n"); 919 prom_debug("prom_instantiate_rtas: start...\n");
910 920
911 prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); 921 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
912 prom_debug("prom_rtas: %x\n", prom_rtas); 922 prom_debug("rtas_node: %x\n", rtas_node);
913 if (prom_rtas == (phandle) -1) 923 if (!PHANDLE_VALID(rtas_node))
914 return; 924 return;
915 925
916 prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); 926 prom_getprop(rtas_node, "rtas-size", &size, sizeof(size));
917 if (size == 0) 927 if (size == 0)
918 return; 928 return;
919 929
@@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void)
922 prom_printf("RTAS allocation failed !\n"); 932 prom_printf("RTAS allocation failed !\n");
923 return; 933 return;
924 } 934 }
925 prom_printf("instantiating rtas at 0x%x", base);
926 935
927 rtas_node = call_prom("open", 1, 1, ADDR("/rtas")); 936 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
928 prom_printf("..."); 937 if (!IHANDLE_VALID(rtas_inst)) {
938 prom_printf("opening rtas package failed");
939 return;
940 }
941
942 prom_printf("instantiating rtas at 0x%x ...", base);
929 943
930 if (call_prom("call-method", 3, 2, 944 if (call_prom("call-method", 3, 2,
931 ADDR("instantiate-rtas"), 945 ADDR("instantiate-rtas"),
932 rtas_node, base) != PROM_ERROR) { 946 rtas_inst, base) != PROM_ERROR) {
933 entry = (long)_prom->args.rets[1]; 947 entry = (long)_prom->args.rets[1];
934 } 948 }
935 if (entry == 0) { 949 if (entry == 0) {
@@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void)
940 954
941 reserve_mem(base, size); 955 reserve_mem(base, size);
942 956
943 prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base)); 957 prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
944 prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry)); 958 prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
945 959
946 prom_debug("rtas base = 0x%x\n", base); 960 prom_debug("rtas base = 0x%x\n", base);
947 prom_debug("rtas entry = 0x%x\n", entry); 961 prom_debug("rtas entry = 0x%x\n", entry);
@@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void)
1062 1076
1063 prom_printf("opening PHB %s", path); 1077 prom_printf("opening PHB %s", path);
1064 phb_node = call_prom("open", 1, 1, path); 1078 phb_node = call_prom("open", 1, 1, path);
1065 if ( (long)phb_node <= 0) 1079 if (phb_node == 0)
1066 prom_printf("... failed\n"); 1080 prom_printf("... failed\n");
1067 else 1081 else
1068 prom_printf("... done\n"); 1082 prom_printf("... done\n");
@@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp)
1279 1293
1280 /* get a handle for the stdout device */ 1294 /* get a handle for the stdout device */
1281 _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); 1295 _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
1282 if ((long)_prom->chosen <= 0) 1296 if (!PHANDLE_VALID(_prom->chosen))
1283 prom_panic("cannot find chosen"); /* msg won't be printed :( */ 1297 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1284 1298
1285 /* get device tree root */ 1299 /* get device tree root */
1286 _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); 1300 _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
1287 if ((long)_prom->root <= 0) 1301 if (!PHANDLE_VALID(_prom->root))
1288 prom_panic("cannot find device tree root"); /* msg won't be printed :( */ 1302 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
1289} 1303}
1290 1304
@@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void)
1356 } 1370 }
1357 /* Default to pSeries. We need to know if we are running LPAR */ 1371 /* Default to pSeries. We need to know if we are running LPAR */
1358 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); 1372 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1359 if (rtas != (phandle) -1) { 1373 if (!PHANDLE_VALID(rtas)) {
1360 unsigned long x; 1374 int x = prom_getproplen(rtas, "ibm,hypertas-functions");
1361 x = prom_getproplen(rtas, "ibm,hypertas-functions");
1362 if (x != PROM_ERROR) { 1375 if (x != PROM_ERROR) {
1363 prom_printf("Hypertas detected, assuming LPAR !\n"); 1376 prom_printf("Hypertas detected, assuming LPAR !\n");
1364 return PLATFORM_PSERIES_LPAR; 1377 return PLATFORM_PSERIES_LPAR;
@@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void)
1426 * leave some room at the end of the path for appending extra 1439 * leave some room at the end of the path for appending extra
1427 * arguments 1440 * arguments
1428 */ 1441 */
1429 if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0) 1442 if (call_prom("package-to-path", 3, 1, node, path,
1443 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
1430 continue; 1444 continue;
1431 prom_printf("found display : %s, opening ... ", path); 1445 prom_printf("found display : %s, opening ... ", path);
1432 1446
1433 ih = call_prom("open", 1, 1, path); 1447 ih = call_prom("open", 1, 1, path);
1434 if (ih == (ihandle)0 || ih == (ihandle)-1) { 1448 if (ih == 0) {
1435 prom_printf("failed\n"); 1449 prom_printf("failed\n");
1436 continue; 1450 continue;
1437 } 1451 }
@@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str)
1514 return 0; 1528 return 0;
1515} 1529}
1516 1530
1531/*
1532 * The Open Firmware 1275 specification states properties must be 31 bytes or
1533 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
1534 */
1535#define MAX_PROPERTY_NAME 64
1536
1517static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, 1537static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1518 unsigned long *mem_end) 1538 unsigned long *mem_end)
1519{ 1539{
@@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1527 /* get and store all property names */ 1547 /* get and store all property names */
1528 prev_name = RELOC(""); 1548 prev_name = RELOC("");
1529 for (;;) { 1549 for (;;) {
1530 1550 int rc;
1531 /* 32 is max len of name including nul. */ 1551
1532 namep = make_room(mem_start, mem_end, 32, 1); 1552 /* 64 is max len of name including nul. */
1533 if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) { 1553 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
1554 rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
1555 if (rc != 1) {
1534 /* No more nodes: unwind alloc */ 1556 /* No more nodes: unwind alloc */
1535 *mem_start = (unsigned long)namep; 1557 *mem_start = (unsigned long)namep;
1536 break; 1558 break;
@@ -1555,18 +1577,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1555 } 1577 }
1556} 1578}
1557 1579
1558/*
1559 * The Open Firmware 1275 specification states properties must be 31 bytes or
1560 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
1561 */
1562#define MAX_PROPERTY_NAME 64
1563
1564static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, 1580static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1565 unsigned long *mem_end) 1581 unsigned long *mem_end)
1566{ 1582{
1567 int l, align; 1583 int l, align;
1568 phandle child; 1584 phandle child;
1569 char *namep, *prev_name, *sstart; 1585 char *namep, *prev_name, *sstart, *p, *ep;
1570 unsigned long soff; 1586 unsigned long soff;
1571 unsigned char *valp; 1587 unsigned char *valp;
1572 unsigned long offset = reloc_offset(); 1588 unsigned long offset = reloc_offset();
@@ -1588,6 +1604,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1588 call_prom("package-to-path", 3, 1, node, namep, l); 1604 call_prom("package-to-path", 3, 1, node, namep, l);
1589 } 1605 }
1590 namep[l] = '\0'; 1606 namep[l] = '\0';
1607 /* Fixup an Apple bug where they have bogus \0 chars in the
1608 * middle of the path in some properties
1609 */
1610 for (p = namep, ep = namep + l; p < ep; p++)
1611 if (*p == '\0') {
1612 memmove(p, p+1, ep - p);
1613 ep--; l--;
1614 }
1591 *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); 1615 *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
1592 } 1616 }
1593 1617
@@ -1599,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1599 prev_name = RELOC(""); 1623 prev_name = RELOC("");
1600 sstart = (char *)RELOC(dt_string_start); 1624 sstart = (char *)RELOC(dt_string_start);
1601 for (;;) { 1625 for (;;) {
1602 if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0) 1626 int rc;
1627
1628 rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
1629 if (rc != 1)
1603 break; 1630 break;
1604 1631
1605 /* find string offset */ 1632 /* find string offset */
@@ -1615,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1615 l = call_prom("getproplen", 2, 1, node, pname); 1642 l = call_prom("getproplen", 2, 1, node, pname);
1616 1643
1617 /* sanity checks */ 1644 /* sanity checks */
1618 if (l < 0) 1645 if (l == PROM_ERROR)
1619 continue; 1646 continue;
1620 if (l > MAX_PROPERTY_LENGTH) { 1647 if (l > MAX_PROPERTY_LENGTH) {
1621 prom_printf("WARNING: ignoring large property "); 1648 prom_printf("WARNING: ignoring large property ");
@@ -1750,7 +1777,45 @@ static void __init flatten_device_tree(void)
1750 prom_printf("Device tree struct 0x%x -> 0x%x\n", 1777 prom_printf("Device tree struct 0x%x -> 0x%x\n",
1751 RELOC(dt_struct_start), RELOC(dt_struct_end)); 1778 RELOC(dt_struct_start), RELOC(dt_struct_end));
1752 1779
1753 } 1780}
1781
1782
1783static void __init fixup_device_tree(void)
1784{
1785 unsigned long offset = reloc_offset();
1786 phandle u3, i2c, mpic;
1787 u32 u3_rev;
1788 u32 interrupts[2];
1789 u32 parent;
1790
1791 /* Some G5s have a missing interrupt definition, fix it up here */
1792 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
1793 if (!PHANDLE_VALID(u3))
1794 return;
1795 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
1796 if (!PHANDLE_VALID(i2c))
1797 return;
1798 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
1799 if (!PHANDLE_VALID(mpic))
1800 return;
1801
1802 /* check if proper rev of u3 */
1803 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
1804 == PROM_ERROR)
1805 return;
1806 if (u3_rev != 0x35)
1807 return;
1808 /* does it need fixup ? */
1809 if (prom_getproplen(i2c, "interrupts") > 0)
1810 return;
1811 /* interrupt on this revision of u3 is number 0 and level */
1812 interrupts[0] = 0;
1813 interrupts[1] = 1;
1814 prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
1815 parent = (u32)mpic;
1816 prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
1817}
1818
1754 1819
1755static void __init prom_find_boot_cpu(void) 1820static void __init prom_find_boot_cpu(void)
1756{ 1821{
@@ -1844,6 +1909,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
1844 &getprop_rval, sizeof(getprop_rval)); 1909 &getprop_rval, sizeof(getprop_rval));
1845 1910
1846 /* 1911 /*
1912 * On pSeries, inform the firmware about our capabilities
1913 */
1914 if (RELOC(of_platform) & PLATFORM_PSERIES)
1915 prom_send_capabilities();
1916
1917 /*
1847 * On pSeries, copy the CPU hold code 1918 * On pSeries, copy the CPU hold code
1848 */ 1919 */
1849 if (RELOC(of_platform) & PLATFORM_PSERIES) 1920 if (RELOC(of_platform) & PLATFORM_PSERIES)
@@ -1920,6 +1991,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
1920 } 1991 }
1921 1992
1922 /* 1993 /*
1994 * Fixup any known bugs in the device-tree
1995 */
1996 fixup_device_tree();
1997
1998 /*
1923 * Now finally create the flattened device-tree 1999 * Now finally create the flattened device-tree
1924 */ 2000 */
1925 prom_printf("copying OF device tree ...\n"); 2001 prom_printf("copying OF device tree ...\n");
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index 3e70b91375fc..67989055a9fe 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -292,47 +292,10 @@ int iSeries_set_rtc_time(struct rtc_time *tm)
292 292
293void iSeries_get_boot_time(struct rtc_time *tm) 293void iSeries_get_boot_time(struct rtc_time *tm)
294{ 294{
295 unsigned long time;
296 static unsigned long lastsec = 1;
297
298 u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart));
299 u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1);
300 int year = 1970;
301 int year1 = ( dataWord1 >> 24 ) & 0x000000FF;
302 int year2 = ( dataWord1 >> 16 ) & 0x000000FF;
303 int sec = ( dataWord1 >> 8 ) & 0x000000FF;
304 int min = dataWord1 & 0x000000FF;
305 int hour = ( dataWord2 >> 24 ) & 0x000000FF;
306 int day = ( dataWord2 >> 8 ) & 0x000000FF;
307 int mon = dataWord2 & 0x000000FF;
308
309 if ( piranha_simulator ) 295 if ( piranha_simulator )
310 return; 296 return;
311 297
312 BCD_TO_BIN(sec); 298 mf_get_boot_rtc(tm);
313 BCD_TO_BIN(min);
314 BCD_TO_BIN(hour);
315 BCD_TO_BIN(day);
316 BCD_TO_BIN(mon);
317 BCD_TO_BIN(year1);
318 BCD_TO_BIN(year2);
319 year = year1 * 100 + year2;
320
321 time = mktime(year, mon, day, hour, min, sec);
322 time += ( jiffies / HZ );
323
324 /* Now THIS is a nasty hack!
325 * It ensures that the first two calls get different answers.
326 * That way the loop in init_time (time.c) will not think
327 * the clock is stuck.
328 */
329 if ( lastsec ) {
330 time -= lastsec;
331 --lastsec;
332 }
333
334 to_tm(time, tm);
335 tm->tm_year -= 1900;
336 tm->tm_mon -= 1; 299 tm->tm_mon -= 1;
337} 300}
338#endif 301#endif
diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
index a95a2b49a1d5..bf782276984c 100644
--- a/arch/ppc64/kernel/signal.c
+++ b/arch/ppc64/kernel/signal.c
@@ -42,11 +42,7 @@
42 42
43#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 43#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
44 44
45#ifndef MIN 45#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
46#define MIN(a,b) (((a) < (b)) ? (a) : (b))
47#endif
48
49#define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs))
50#define FP_REGS_SIZE sizeof(elf_fpregset_t) 46#define FP_REGS_SIZE sizeof(elf_fpregset_t)
51 47
52#define TRAMP_TRACEBACK 3 48#define TRAMP_TRACEBACK 3
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 772a465b49f9..33364a7d2cd2 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -325,9 +325,7 @@ int timer_interrupt(struct pt_regs * regs)
325 325
326 irq_enter(); 326 irq_enter();
327 327
328#ifndef CONFIG_PPC_ISERIES
329 profile_tick(CPU_PROFILING, regs); 328 profile_tick(CPU_PROFILING, regs);
330#endif
331 329
332 lpaca->lppaca.int_dword.fields.decr_int = 0; 330 lpaca->lppaca.int_dword.fields.decr_int = 0;
333 331
@@ -515,6 +513,7 @@ void __init time_init(void)
515 do_gtod.varp = &do_gtod.vars[0]; 513 do_gtod.varp = &do_gtod.vars[0];
516 do_gtod.var_idx = 0; 514 do_gtod.var_idx = 0;
517 do_gtod.varp->tb_orig_stamp = tb_last_stamp; 515 do_gtod.varp->tb_orig_stamp = tb_last_stamp;
516 get_paca()->next_jiffy_update_tb = tb_last_stamp + tb_ticks_per_jiffy;
518 do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; 517 do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
519 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; 518 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
520 do_gtod.varp->tb_to_xs = tb_to_xs; 519 do_gtod.varp->tb_to_xs = tb_to_xs;
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index eedd1d3c2a10..879f39b90a33 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -432,6 +432,7 @@ void xics_cause_IPI(int cpu)
432{ 432{
433 ops->qirr_info(cpu, IPI_PRIORITY); 433 ops->qirr_info(cpu, IPI_PRIORITY);
434} 434}
435#endif /* CONFIG_SMP */
435 436
436void xics_setup_cpu(void) 437void xics_setup_cpu(void)
437{ 438{
@@ -439,9 +440,17 @@ void xics_setup_cpu(void)
439 440
440 ops->cppr_info(cpu, 0xff); 441 ops->cppr_info(cpu, 0xff);
441 iosync(); 442 iosync();
442}
443 443
444#endif /* CONFIG_SMP */ 444 /*
445 * Put the calling processor into the GIQ. This is really only
446 * necessary from a secondary thread as the OF start-cpu interface
447 * performs this function for us on primary threads.
448 *
449 * XXX: undo of teardown on kexec needs this too, as may hotplug
450 */
451 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
452 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
453}
445 454
446void xics_init_IRQ(void) 455void xics_init_IRQ(void)
447{ 456{
@@ -563,8 +572,7 @@ nextnode:
563 for (; i < NR_IRQS; ++i) 572 for (; i < NR_IRQS; ++i)
564 get_irq_desc(i)->handler = &xics_pic; 573 get_irq_desc(i)->handler = &xics_pic;
565 574
566 ops->cppr_info(boot_cpuid, 0xff); 575 xics_setup_cpu();
567 iosync();
568 576
569 ppc64_boot_msg(0x21, "XICS Done"); 577 ppc64_boot_msg(0x21, "XICS Done");
570} 578}
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index 144657e0c3d5..52b6b9305341 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -320,8 +320,7 @@ static void native_flush_hash_range(unsigned long context,
320 320
321 j = 0; 321 j = 0;
322 for (i = 0; i < number; i++) { 322 for (i = 0; i < number; i++) {
323 if ((batch->addr[i] >= USER_START) && 323 if (batch->addr[i] < KERNELBASE)
324 (batch->addr[i] <= USER_END))
325 vsid = get_vsid(context, batch->addr[i]); 324 vsid = get_vsid(context, batch->addr[i]);
326 else 325 else
327 vsid = get_kernel_vsid(batch->addr[i]); 326 vsid = get_kernel_vsid(batch->addr[i]);
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index e48be12f518c..0a0f97008d02 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -298,24 +298,23 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
298 int local = 0; 298 int local = 0;
299 cpumask_t tmp; 299 cpumask_t tmp;
300 300
301 if ((ea & ~REGION_MASK) > EADDR_MASK)
302 return 1;
303
301 switch (REGION_ID(ea)) { 304 switch (REGION_ID(ea)) {
302 case USER_REGION_ID: 305 case USER_REGION_ID:
303 user_region = 1; 306 user_region = 1;
304 mm = current->mm; 307 mm = current->mm;
305 if ((ea > USER_END) || (! mm)) 308 if (! mm)
306 return 1; 309 return 1;
307 310
308 vsid = get_vsid(mm->context.id, ea); 311 vsid = get_vsid(mm->context.id, ea);
309 break; 312 break;
310 case IO_REGION_ID: 313 case IO_REGION_ID:
311 if (ea > IMALLOC_END)
312 return 1;
313 mm = &ioremap_mm; 314 mm = &ioremap_mm;
314 vsid = get_kernel_vsid(ea); 315 vsid = get_kernel_vsid(ea);
315 break; 316 break;
316 case VMALLOC_REGION_ID: 317 case VMALLOC_REGION_ID:
317 if (ea > VMALLOC_END)
318 return 1;
319 mm = &init_mm; 318 mm = &init_mm;
320 vsid = get_kernel_vsid(ea); 319 vsid = get_kernel_vsid(ea);
321 break; 320 break;
@@ -362,7 +361,7 @@ void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
362 unsigned long vsid, vpn, va, hash, secondary, slot; 361 unsigned long vsid, vpn, va, hash, secondary, slot;
363 unsigned long huge = pte_huge(pte); 362 unsigned long huge = pte_huge(pte);
364 363
365 if ((ea >= USER_START) && (ea <= USER_END)) 364 if (ea < KERNELBASE)
366 vsid = get_vsid(context, ea); 365 vsid = get_vsid(context, ea);
367 else 366 else
368 vsid = get_kernel_vsid(ea); 367 vsid = get_kernel_vsid(ea);
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index 9d92b0d9cde5..cb8727f3267a 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -14,6 +14,7 @@
14#include <asm/pgalloc.h> 14#include <asm/pgalloc.h>
15#include <asm/pgtable.h> 15#include <asm/pgtable.h>
16#include <asm/semaphore.h> 16#include <asm/semaphore.h>
17#include <asm/imalloc.h>
17 18
18static DECLARE_MUTEX(imlist_sem); 19static DECLARE_MUTEX(imlist_sem);
19struct vm_struct * imlist = NULL; 20struct vm_struct * imlist = NULL;
@@ -23,11 +24,11 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
23 unsigned long addr; 24 unsigned long addr;
24 struct vm_struct **p, *tmp; 25 struct vm_struct **p, *tmp;
25 26
26 addr = IMALLOC_START; 27 addr = ioremap_bot;
27 for (p = &imlist; (tmp = *p) ; p = &tmp->next) { 28 for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
28 if (size + addr < (unsigned long) tmp->addr) 29 if (size + addr < (unsigned long) tmp->addr)
29 break; 30 break;
30 if ((unsigned long)tmp->addr >= IMALLOC_START) 31 if ((unsigned long)tmp->addr >= ioremap_bot)
31 addr = tmp->size + (unsigned long) tmp->addr; 32 addr = tmp->size + (unsigned long) tmp->addr;
32 if (addr > IMALLOC_END-size) 33 if (addr > IMALLOC_END-size)
33 return 1; 34 return 1;
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index cf33d7ec2e29..4b42aff74d73 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -64,6 +64,7 @@
64#include <asm/iommu.h> 64#include <asm/iommu.h>
65#include <asm/abs_addr.h> 65#include <asm/abs_addr.h>
66#include <asm/vdso.h> 66#include <asm/vdso.h>
67#include <asm/imalloc.h>
67 68
68int mem_init_done; 69int mem_init_done;
69unsigned long ioremap_bot = IMALLOC_BASE; 70unsigned long ioremap_bot = IMALLOC_BASE;
@@ -668,7 +669,7 @@ void __init paging_init(void)
668 zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT; 669 zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
669 zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT; 670 zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
670 671
671 free_area_init_node(0, &contig_page_data, zones_size, 672 free_area_init_node(0, NODE_DATA(0), zones_size,
672 __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size); 673 __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
673} 674}
674#endif /* CONFIG_DISCONTIGMEM */ 675#endif /* CONFIG_DISCONTIGMEM */
diff --git a/arch/ppc64/mm/stab.c b/arch/ppc64/mm/stab.c
index 31491131d5e4..df4bbe14153c 100644
--- a/arch/ppc64/mm/stab.c
+++ b/arch/ppc64/mm/stab.c
@@ -19,6 +19,11 @@
19#include <asm/paca.h> 19#include <asm/paca.h>
20#include <asm/cputable.h> 20#include <asm/cputable.h>
21 21
22struct stab_entry {
23 unsigned long esid_data;
24 unsigned long vsid_data;
25};
26
22/* Both the segment table and SLB code uses the following cache */ 27/* Both the segment table and SLB code uses the following cache */
23#define NR_STAB_CACHE_ENTRIES 8 28#define NR_STAB_CACHE_ENTRIES 8
24DEFINE_PER_CPU(long, stab_cache_ptr); 29DEFINE_PER_CPU(long, stab_cache_ptr);
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 066e253f9c12..2c216ffeea90 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -83,9 +83,6 @@ void default_idle(void)
83 */ 83 */
84void cpu_idle(void) 84void cpu_idle(void)
85{ 85{
86 if (current->pid != 0)
87 goto out;
88
89 /* endless idle loop with no priority at all */ 86 /* endless idle loop with no priority at all */
90 for (;;) { 87 for (;;) {
91 if (ARCH_SUN4C_SUN4) { 88 if (ARCH_SUN4C_SUN4) {
@@ -126,8 +123,6 @@ void cpu_idle(void)
126 schedule(); 123 schedule();
127 check_pgt_cache(); 124 check_pgt_cache();
128 } 125 }
129out:
130 return;
131} 126}
132 127
133#else 128#else
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 292983413ae2..2803bc7c2c79 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -8,6 +8,7 @@
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/sched.h> 9#include <linux/sched.h>
10#include <linux/mm.h> 10#include <linux/mm.h>
11#include <linux/delay.h>
11 12
12#include <asm/pbm.h> 13#include <asm/pbm.h>
13 14
@@ -195,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
195 return NULL; 196 return NULL;
196} 197}
197 198
199static int iommu_alloc_ctx(struct pci_iommu *iommu)
200{
201 int lowest = iommu->ctx_lowest_free;
202 int sz = IOMMU_NUM_CTXS - lowest;
203 int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest);
204
205 if (unlikely(n == sz)) {
206 n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1);
207 if (unlikely(n == lowest)) {
208 printk(KERN_WARNING "IOMMU: Ran out of contexts.\n");
209 n = 0;
210 }
211 }
212 if (n)
213 __set_bit(n, iommu->ctx_bitmap);
214
215 return n;
216}
217
218static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
219{
220 if (likely(ctx)) {
221 __clear_bit(ctx, iommu->ctx_bitmap);
222 if (ctx < iommu->ctx_lowest_free)
223 iommu->ctx_lowest_free = ctx;
224 }
225}
226
198/* Allocate and map kernel buffer of size SIZE using consistent mode 227/* Allocate and map kernel buffer of size SIZE using consistent mode
199 * DMA for PCI device PDEV. Return non-NULL cpu-side address if 228 * DMA for PCI device PDEV. Return non-NULL cpu-side address if
200 * successful and set *DMA_ADDRP to the PCI side dma address. 229 * successful and set *DMA_ADDRP to the PCI side dma address.
@@ -235,7 +264,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
235 npages = size >> IO_PAGE_SHIFT; 264 npages = size >> IO_PAGE_SHIFT;
236 ctx = 0; 265 ctx = 0;
237 if (iommu->iommu_ctxflush) 266 if (iommu->iommu_ctxflush)
238 ctx = iommu->iommu_cur_ctx++; 267 ctx = iommu_alloc_ctx(iommu);
239 first_page = __pa(first_page); 268 first_page = __pa(first_page);
240 while (npages--) { 269 while (npages--) {
241 iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) | 270 iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) |
@@ -316,6 +345,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
316 } 345 }
317 } 346 }
318 347
348 iommu_free_ctx(iommu, ctx);
349
319 spin_unlock_irqrestore(&iommu->lock, flags); 350 spin_unlock_irqrestore(&iommu->lock, flags);
320 351
321 order = get_order(size); 352 order = get_order(size);
@@ -359,7 +390,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct
359 base_paddr = __pa(oaddr & IO_PAGE_MASK); 390 base_paddr = __pa(oaddr & IO_PAGE_MASK);
360 ctx = 0; 391 ctx = 0;
361 if (iommu->iommu_ctxflush) 392 if (iommu->iommu_ctxflush)
362 ctx = iommu->iommu_cur_ctx++; 393 ctx = iommu_alloc_ctx(iommu);
363 if (strbuf->strbuf_enabled) 394 if (strbuf->strbuf_enabled)
364 iopte_protection = IOPTE_STREAMING(ctx); 395 iopte_protection = IOPTE_STREAMING(ctx);
365 else 396 else
@@ -379,6 +410,70 @@ bad:
379 return PCI_DMA_ERROR_CODE; 410 return PCI_DMA_ERROR_CODE;
380} 411}
381 412
413static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
414{
415 int limit;
416
417 if (strbuf->strbuf_ctxflush &&
418 iommu->iommu_ctxflush) {
419 unsigned long matchreg, flushreg;
420 u64 val;
421
422 flushreg = strbuf->strbuf_ctxflush;
423 matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
424
425 pci_iommu_write(flushreg, ctx);
426 val = pci_iommu_read(matchreg);
427 val &= 0xffff;
428 if (!val)
429 goto do_flush_sync;
430
431 while (val) {
432 if (val & 0x1)
433 pci_iommu_write(flushreg, ctx);
434 val >>= 1;
435 }
436 val = pci_iommu_read(matchreg);
437 if (unlikely(val)) {
438 printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
439 "timeout matchreg[%lx] ctx[%lx]\n",
440 val, ctx);
441 goto do_page_flush;
442 }
443 } else {
444 unsigned long i;
445
446 do_page_flush:
447 for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
448 pci_iommu_write(strbuf->strbuf_pflush, vaddr);
449 }
450
451do_flush_sync:
452 /* If the device could not have possibly put dirty data into
453 * the streaming cache, no flush-flag synchronization needs
454 * to be performed.
455 */
456 if (direction == PCI_DMA_TODEVICE)
457 return;
458
459 PCI_STC_FLUSHFLAG_INIT(strbuf);
460 pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
461 (void) pci_iommu_read(iommu->write_complete_reg);
462
463 limit = 100000;
464 while (!PCI_STC_FLUSHFLAG_SET(strbuf)) {
465 limit--;
466 if (!limit)
467 break;
468 udelay(1);
469 membar("#LoadLoad");
470 }
471 if (!limit)
472 printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
473 "vaddr[%08x] ctx[%lx] npages[%ld]\n",
474 vaddr, ctx, npages);
475}
476
382/* Unmap a single streaming mode DMA translation. */ 477/* Unmap a single streaming mode DMA translation. */
383void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) 478void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
384{ 479{
@@ -386,7 +481,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
386 struct pci_iommu *iommu; 481 struct pci_iommu *iommu;
387 struct pci_strbuf *strbuf; 482 struct pci_strbuf *strbuf;
388 iopte_t *base; 483 iopte_t *base;
389 unsigned long flags, npages, i, ctx; 484 unsigned long flags, npages, ctx;
390 485
391 if (direction == PCI_DMA_NONE) 486 if (direction == PCI_DMA_NONE)
392 BUG(); 487 BUG();
@@ -414,29 +509,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
414 ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; 509 ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
415 510
416 /* Step 1: Kick data out of streaming buffers if necessary. */ 511 /* Step 1: Kick data out of streaming buffers if necessary. */
417 if (strbuf->strbuf_enabled) { 512 if (strbuf->strbuf_enabled)
418 u32 vaddr = bus_addr; 513 pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
419
420 PCI_STC_FLUSHFLAG_INIT(strbuf);
421 if (strbuf->strbuf_ctxflush &&
422 iommu->iommu_ctxflush) {
423 unsigned long matchreg, flushreg;
424
425 flushreg = strbuf->strbuf_ctxflush;
426 matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
427 do {
428 pci_iommu_write(flushreg, ctx);
429 } while(((long)pci_iommu_read(matchreg)) < 0L);
430 } else {
431 for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
432 pci_iommu_write(strbuf->strbuf_pflush, vaddr);
433 }
434
435 pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
436 (void) pci_iommu_read(iommu->write_complete_reg);
437 while (!PCI_STC_FLUSHFLAG_SET(strbuf))
438 membar("#LoadLoad");
439 }
440 514
441 /* Step 2: Clear out first TSB entry. */ 515 /* Step 2: Clear out first TSB entry. */
442 iopte_make_dummy(iommu, base); 516 iopte_make_dummy(iommu, base);
@@ -444,6 +518,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
444 free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, 518 free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
445 npages, ctx); 519 npages, ctx);
446 520
521 iommu_free_ctx(iommu, ctx);
522
447 spin_unlock_irqrestore(&iommu->lock, flags); 523 spin_unlock_irqrestore(&iommu->lock, flags);
448} 524}
449 525
@@ -583,7 +659,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int
583 /* Step 4: Choose a context if necessary. */ 659 /* Step 4: Choose a context if necessary. */
584 ctx = 0; 660 ctx = 0;
585 if (iommu->iommu_ctxflush) 661 if (iommu->iommu_ctxflush)
586 ctx = iommu->iommu_cur_ctx++; 662 ctx = iommu_alloc_ctx(iommu);
587 663
588 /* Step 5: Create the mappings. */ 664 /* Step 5: Create the mappings. */
589 if (strbuf->strbuf_enabled) 665 if (strbuf->strbuf_enabled)
@@ -647,29 +723,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
647 ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; 723 ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
648 724
649 /* Step 1: Kick data out of streaming buffers if necessary. */ 725 /* Step 1: Kick data out of streaming buffers if necessary. */
650 if (strbuf->strbuf_enabled) { 726 if (strbuf->strbuf_enabled)
651 u32 vaddr = (u32) bus_addr; 727 pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
652
653 PCI_STC_FLUSHFLAG_INIT(strbuf);
654 if (strbuf->strbuf_ctxflush &&
655 iommu->iommu_ctxflush) {
656 unsigned long matchreg, flushreg;
657
658 flushreg = strbuf->strbuf_ctxflush;
659 matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
660 do {
661 pci_iommu_write(flushreg, ctx);
662 } while(((long)pci_iommu_read(matchreg)) < 0L);
663 } else {
664 for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
665 pci_iommu_write(strbuf->strbuf_pflush, vaddr);
666 }
667
668 pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
669 (void) pci_iommu_read(iommu->write_complete_reg);
670 while (!PCI_STC_FLUSHFLAG_SET(strbuf))
671 membar("#LoadLoad");
672 }
673 728
674 /* Step 2: Clear out first TSB entry. */ 729 /* Step 2: Clear out first TSB entry. */
675 iopte_make_dummy(iommu, base); 730 iopte_make_dummy(iommu, base);
@@ -677,6 +732,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
677 free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, 732 free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
678 npages, ctx); 733 npages, ctx);
679 734
735 iommu_free_ctx(iommu, ctx);
736
680 spin_unlock_irqrestore(&iommu->lock, flags); 737 spin_unlock_irqrestore(&iommu->lock, flags);
681} 738}
682 739
@@ -715,28 +772,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size
715 } 772 }
716 773
717 /* Step 2: Kick data out of streaming buffers. */ 774 /* Step 2: Kick data out of streaming buffers. */
718 PCI_STC_FLUSHFLAG_INIT(strbuf); 775 pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
719 if (iommu->iommu_ctxflush &&
720 strbuf->strbuf_ctxflush) {
721 unsigned long matchreg, flushreg;
722
723 flushreg = strbuf->strbuf_ctxflush;
724 matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
725 do {
726 pci_iommu_write(flushreg, ctx);
727 } while(((long)pci_iommu_read(matchreg)) < 0L);
728 } else {
729 unsigned long i;
730
731 for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
732 pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
733 }
734
735 /* Step 3: Perform flush synchronization sequence. */
736 pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
737 (void) pci_iommu_read(iommu->write_complete_reg);
738 while (!PCI_STC_FLUSHFLAG_SET(strbuf))
739 membar("#LoadLoad");
740 776
741 spin_unlock_irqrestore(&iommu->lock, flags); 777 spin_unlock_irqrestore(&iommu->lock, flags);
742} 778}
@@ -749,7 +785,8 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
749 struct pcidev_cookie *pcp; 785 struct pcidev_cookie *pcp;
750 struct pci_iommu *iommu; 786 struct pci_iommu *iommu;
751 struct pci_strbuf *strbuf; 787 struct pci_strbuf *strbuf;
752 unsigned long flags, ctx; 788 unsigned long flags, ctx, npages, i;
789 u32 bus_addr;
753 790
754 pcp = pdev->sysdata; 791 pcp = pdev->sysdata;
755 iommu = pcp->pbm->iommu; 792 iommu = pcp->pbm->iommu;
@@ -772,36 +809,14 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
772 } 809 }
773 810
774 /* Step 2: Kick data out of streaming buffers. */ 811 /* Step 2: Kick data out of streaming buffers. */
775 PCI_STC_FLUSHFLAG_INIT(strbuf); 812 bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
776 if (iommu->iommu_ctxflush && 813 for(i = 1; i < nelems; i++)
777 strbuf->strbuf_ctxflush) { 814 if (!sglist[i].dma_length)
778 unsigned long matchreg, flushreg; 815 break;
779 816 i--;
780 flushreg = strbuf->strbuf_ctxflush; 817 npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
781 matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); 818 - bus_addr) >> IO_PAGE_SHIFT;
782 do { 819 pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
783 pci_iommu_write(flushreg, ctx);
784 } while (((long)pci_iommu_read(matchreg)) < 0L);
785 } else {
786 unsigned long i, npages;
787 u32 bus_addr;
788
789 bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
790
791 for(i = 1; i < nelems; i++)
792 if (!sglist[i].dma_length)
793 break;
794 i--;
795 npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT;
796 for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
797 pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
798 }
799
800 /* Step 3: Perform flush synchronization sequence. */
801 pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
802 (void) pci_iommu_read(iommu->write_complete_reg);
803 while (!PCI_STC_FLUSHFLAG_SET(strbuf))
804 membar("#LoadLoad");
805 820
806 spin_unlock_irqrestore(&iommu->lock, flags); 821 spin_unlock_irqrestore(&iommu->lock, flags);
807} 822}
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 3567fa879e1f..534320ef0db2 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
1212 1212
1213 /* Setup initial software IOMMU state. */ 1213 /* Setup initial software IOMMU state. */
1214 spin_lock_init(&iommu->lock); 1214 spin_lock_init(&iommu->lock);
1215 iommu->iommu_cur_ctx = 0; 1215 iommu->ctx_lowest_free = 1;
1216 1216
1217 /* Register addresses. */ 1217 /* Register addresses. */
1218 iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; 1218 iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 5525d1ec4af8..53d333b4a4e8 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1265,7 +1265,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
1265 1265
1266 /* Setup initial software IOMMU state. */ 1266 /* Setup initial software IOMMU state. */
1267 spin_lock_init(&iommu->lock); 1267 spin_lock_init(&iommu->lock);
1268 iommu->iommu_cur_ctx = 0; 1268 iommu->ctx_lowest_free = 1;
1269 1269
1270 /* Register addresses. */ 1270 /* Register addresses. */
1271 iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; 1271 iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index e93fcadc3722..5753175b94e6 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -1753,7 +1753,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
1753 1753
1754 /* Setup initial software IOMMU state. */ 1754 /* Setup initial software IOMMU state. */
1755 spin_lock_init(&iommu->lock); 1755 spin_lock_init(&iommu->lock);
1756 iommu->iommu_cur_ctx = 0; 1756 iommu->ctx_lowest_free = 1;
1757 1757
1758 /* Register addresses, SCHIZO has iommu ctx flushing. */ 1758 /* Register addresses, SCHIZO has iommu ctx flushing. */
1759 iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; 1759 iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 26d3ec41da1c..a0cd2b2494d6 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -62,9 +62,6 @@ void default_idle(void)
62 */ 62 */
63void cpu_idle(void) 63void cpu_idle(void)
64{ 64{
65 if (current->pid != 0)
66 return;
67
68 /* endless idle loop with no priority at all */ 65 /* endless idle loop with no priority at all */
69 for (;;) { 66 for (;;) {
70 /* If current->work.need_resched is zero we should really 67 /* If current->work.need_resched is zero we should really
@@ -80,7 +77,6 @@ void cpu_idle(void)
80 schedule(); 77 schedule();
81 check_pgt_cache(); 78 check_pgt_cache();
82 } 79 }
83 return;
84} 80}
85 81
86#else 82#else
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 14d9c3a21b9a..89f5e019f24c 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -117,19 +117,42 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages
117 117
118#define STRBUF_TAG_VALID 0x02UL 118#define STRBUF_TAG_VALID 0x02UL
119 119
120static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) 120static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction)
121{ 121{
122 iommu->strbuf_flushflag = 0UL; 122 unsigned long n;
123 while (npages--) 123 int limit;
124 upa_writeq(base + (npages << IO_PAGE_SHIFT), 124
125 n = npages;
126 while (n--)
127 upa_writeq(base + (n << IO_PAGE_SHIFT),
125 iommu->strbuf_regs + STRBUF_PFLUSH); 128 iommu->strbuf_regs + STRBUF_PFLUSH);
126 129
130 /* If the device could not have possibly put dirty data into
131 * the streaming cache, no flush-flag synchronization needs
132 * to be performed.
133 */
134 if (direction == SBUS_DMA_TODEVICE)
135 return;
136
137 iommu->strbuf_flushflag = 0UL;
138
127 /* Whoopee cushion! */ 139 /* Whoopee cushion! */
128 upa_writeq(__pa(&iommu->strbuf_flushflag), 140 upa_writeq(__pa(&iommu->strbuf_flushflag),
129 iommu->strbuf_regs + STRBUF_FSYNC); 141 iommu->strbuf_regs + STRBUF_FSYNC);
130 upa_readq(iommu->sbus_control_reg); 142 upa_readq(iommu->sbus_control_reg);
131 while (iommu->strbuf_flushflag == 0UL) 143
144 limit = 100000;
145 while (iommu->strbuf_flushflag == 0UL) {
146 limit--;
147 if (!limit)
148 break;
149 udelay(1);
132 membar("#LoadLoad"); 150 membar("#LoadLoad");
151 }
152 if (!limit)
153 printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
154 "vaddr[%08x] npages[%ld]\n",
155 base, npages);
133} 156}
134 157
135static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) 158static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
@@ -406,7 +429,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size,
406 429
407 spin_lock_irqsave(&iommu->lock, flags); 430 spin_lock_irqsave(&iommu->lock, flags);
408 free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); 431 free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
409 strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); 432 sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction);
410 spin_unlock_irqrestore(&iommu->lock, flags); 433 spin_unlock_irqrestore(&iommu->lock, flags);
411} 434}
412 435
@@ -569,7 +592,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int
569 iommu = sdev->bus->iommu; 592 iommu = sdev->bus->iommu;
570 spin_lock_irqsave(&iommu->lock, flags); 593 spin_lock_irqsave(&iommu->lock, flags);
571 free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); 594 free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
572 strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); 595 sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction);
573 spin_unlock_irqrestore(&iommu->lock, flags); 596 spin_unlock_irqrestore(&iommu->lock, flags);
574} 597}
575 598
@@ -581,7 +604,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t
581 size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); 604 size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
582 605
583 spin_lock_irqsave(&iommu->lock, flags); 606 spin_lock_irqsave(&iommu->lock, flags);
584 strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); 607 sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction);
585 spin_unlock_irqrestore(&iommu->lock, flags); 608 spin_unlock_irqrestore(&iommu->lock, flags);
586} 609}
587 610
@@ -605,7 +628,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int
605 size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; 628 size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
606 629
607 spin_lock_irqsave(&iommu->lock, flags); 630 spin_lock_irqsave(&iommu->lock, flags);
608 strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); 631 sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction);
609 spin_unlock_irqrestore(&iommu->lock, flags); 632 spin_unlock_irqrestore(&iommu->lock, flags);
610} 633}
611 634
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 12c3d84b7460..b7e6a91952b2 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -383,6 +383,17 @@ static void __init process_switch(char c)
383 /* Use PROM debug console. */ 383 /* Use PROM debug console. */
384 register_console(&prom_debug_console); 384 register_console(&prom_debug_console);
385 break; 385 break;
386 case 'P':
387 /* Force UltraSPARC-III P-Cache on. */
388 if (tlb_type != cheetah) {
389 printk("BOOT: Ignoring P-Cache force option.\n");
390 break;
391 }
392 cheetah_pcache_forced_on = 1;
393 add_taint(TAINT_MACHINE_CHECK);
394 cheetah_enable_pcache();
395 break;
396
386 default: 397 default:
387 printk("Unknown boot switch (-%c)\n", c); 398 printk("Unknown boot switch (-%c)\n", c);
388 break; 399 break;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 6dff06a44e76..e5b9c7a27789 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -123,6 +123,9 @@ void __init smp_callin(void)
123 123
124 smp_setup_percpu_timer(); 124 smp_setup_percpu_timer();
125 125
126 if (cheetah_pcache_forced_on)
127 cheetah_enable_pcache();
128
126 local_irq_enable(); 129 local_irq_enable();
127 130
128 calibrate_delay(); 131 calibrate_delay();
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index cad5a1122800..e78cc53594fa 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -278,7 +278,7 @@ EXPORT_SYMBOL(verify_compat_iovec);
278 278
279EXPORT_SYMBOL(dump_thread); 279EXPORT_SYMBOL(dump_thread);
280EXPORT_SYMBOL(dump_fpu); 280EXPORT_SYMBOL(dump_fpu);
281EXPORT_SYMBOL(__pte_alloc_one_kernel); 281EXPORT_SYMBOL(pte_alloc_one_kernel);
282#ifndef CONFIG_SMP 282#ifndef CONFIG_SMP
283EXPORT_SYMBOL(pgt_quicklists); 283EXPORT_SYMBOL(pgt_quicklists);
284#endif 284#endif
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 56b203a2af69..a9f4596d7c2b 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -421,6 +421,25 @@ asmlinkage void cee_log(unsigned long ce_status,
421 } 421 }
422} 422}
423 423
424int cheetah_pcache_forced_on;
425
426void cheetah_enable_pcache(void)
427{
428 unsigned long dcr;
429
430 printk("CHEETAH: Enabling P-Cache on cpu %d.\n",
431 smp_processor_id());
432
433 __asm__ __volatile__("ldxa [%%g0] %1, %0"
434 : "=r" (dcr)
435 : "i" (ASI_DCU_CONTROL_REG));
436 dcr |= (DCU_PE | DCU_HPE | DCU_SPE | DCU_SL);
437 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
438 "membar #Sync"
439 : /* no outputs */
440 : "r" (dcr), "i" (ASI_DCU_CONTROL_REG));
441}
442
424/* Cheetah error trap handling. */ 443/* Cheetah error trap handling. */
425static unsigned long ecache_flush_physbase; 444static unsigned long ecache_flush_physbase;
426static unsigned long ecache_flush_linesize; 445static unsigned long ecache_flush_linesize;
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index db6fa77b4dab..9c5222075da9 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1114,7 +1114,7 @@ struct pgtable_cache_struct pgt_quicklists;
1114#else 1114#else
1115#define DC_ALIAS_SHIFT 0 1115#define DC_ALIAS_SHIFT 0
1116#endif 1116#endif
1117pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) 1117pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
1118{ 1118{
1119 struct page *page; 1119 struct page *page;
1120 unsigned long color; 1120 unsigned long color;
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index b89989de364d..bd41e4286d0d 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -2,10 +2,6 @@ menu "Kernel hacking"
2 2
3source "lib/Kconfig.debug" 3source "lib/Kconfig.debug"
4 4
5config FRAME_POINTER
6 bool
7 default y if DEBUG_INFO
8
9config PT_PROXY 5config PT_PROXY
10 bool "Enable ptrace proxy" 6 bool "Enable ptrace proxy"
11 depends on XTERM_CHAN && DEBUG_INFO && MODE_TT 7 depends on XTERM_CHAN && DEBUG_INFO && MODE_TT
diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64
index fd8d7e8982b1..f162f50f0b17 100644
--- a/arch/um/Kconfig_x86_64
+++ b/arch/um/Kconfig_x86_64
@@ -6,6 +6,10 @@ config 64BIT
6 bool 6 bool
7 default y 7 default y
8 8
9config TOP_ADDR
10 hex
11 default 0x80000000
12
9config 3_LEVEL_PGTABLES 13config 3_LEVEL_PGTABLES
10 bool 14 bool
11 default y 15 default y
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 97bca6b5ca95..f2a0c40a9204 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -17,7 +17,7 @@ core-y += $(ARCH_DIR)/kernel/ \
17 17
18# Have to precede the include because the included Makefiles reference them. 18# Have to precede the include because the included Makefiles reference them.
19SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \ 19SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \
20 arch-signal.h module.h vm-flags.h 20 module.h vm-flags.h elf.h
21SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) 21SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
22 22
23# XXX: The "os" symlink is only used by arch/um/include/os.h, which includes 23# XXX: The "os" symlink is only used by arch/um/include/os.h, which includes
@@ -44,6 +44,11 @@ ifneq ($(MAKEFILES-INCL),)
44endif 44endif
45 45
46ARCH_INCLUDE := -I$(ARCH_DIR)/include 46ARCH_INCLUDE := -I$(ARCH_DIR)/include
47ifneq ($(KBUILD_SRC),)
48ARCH_INCLUDE += -I$(ARCH_DIR)/include2
49ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include
50MRPROPER_DIRS += $(ARCH_DIR)/include2
51endif
47SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) 52SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
48 53
49include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) 54include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -94,17 +99,18 @@ define archhelp
94 echo ' find in the kernel root.' 99 echo ' find in the kernel root.'
95endef 100endef
96 101
102ifneq ($(KBUILD_SRC),)
103$(shell mkdir -p $(ARCH_DIR) && ln -fsn $(srctree)/$(ARCH_DIR)/Kconfig_$(SUBARCH) $(ARCH_DIR)/Kconfig_arch)
104CLEAN_FILES += $(ARCH_DIR)/Kconfig_arch
105else
97$(shell cd $(ARCH_DIR) && ln -sf Kconfig_$(SUBARCH) Kconfig_arch) 106$(shell cd $(ARCH_DIR) && ln -sf Kconfig_$(SUBARCH) Kconfig_arch)
107endif
98 108
99prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \ 109prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
100 $(ARCH_DIR)/kernel/vmlinux.lds.S
101 110
102LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static 111LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
103LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib 112LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
104 113
105LD_SCRIPT-$(CONFIG_LD_SCRIPT_STATIC) := uml.lds.S
106LD_SCRIPT-$(CONFIG_LD_SCRIPT_DYN) := dyn.lds.S
107
108CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT 114CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT
109CONFIG_KERNEL_STACK_ORDER ?= 2 115CONFIG_KERNEL_STACK_ORDER ?= 2
110STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) 116STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
@@ -126,7 +132,7 @@ define cmd_vmlinux__
126 $(CC) $(CFLAGS_vmlinux) -o $@ \ 132 $(CC) $(CFLAGS_vmlinux) -o $@ \
127 -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \ 133 -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
128 -Wl,--start-group $(vmlinux-main) -Wl,--end-group \ 134 -Wl,--start-group $(vmlinux-main) -Wl,--end-group \
129 -L/usr/lib -lutil \ 135 -lutil \
130 $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) \ 136 $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) \
131 FORCE ,$^) ; rm -f linux 137 FORCE ,$^) ; rm -f linux
132endef 138endef
@@ -145,31 +151,42 @@ archclean:
145 @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ 151 @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
146 -o -name '*.gcov' \) -type f -print | xargs rm -f 152 -o -name '*.gcov' \) -type f -print | xargs rm -f
147 153
148#We need to re-preprocess this when the symlink dest changes.
149#So we touch it when needed.
150$(ARCH_DIR)/kernel/vmlinux.lds.S: FORCE
151 $(Q)if [ "$(shell readlink $@)" != "$(LD_SCRIPT-y)" ]; then \
152 echo ' SYMLINK $@'; \
153 ln -sf $(LD_SCRIPT-y) $@; \
154 touch $@; \
155 fi;
156
157$(SYMLINK_HEADERS): 154$(SYMLINK_HEADERS):
158 @echo ' SYMLINK $@' 155 @echo ' SYMLINK $@'
156ifneq ($(KBUILD_SRC),)
157 ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
158else
159 $(Q)cd $(TOPDIR)/$(dir $@) ; \ 159 $(Q)cd $(TOPDIR)/$(dir $@) ; \
160 ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@) 160 ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
161endif
161 162
162include/asm-um/arch: 163include/asm-um/arch:
163 @echo ' SYMLINK $@' 164 @echo ' SYMLINK $@'
165ifneq ($(KBUILD_SRC),)
166 $(Q)mkdir -p include/asm-um
167 $(Q)ln -fsn $(srctree)/include/asm-$(SUBARCH) include/asm-um/arch
168else
164 $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch 169 $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
170endif
165 171
166$(ARCH_DIR)/include/sysdep: 172$(ARCH_DIR)/include/sysdep:
167 @echo ' SYMLINK $@' 173 @echo ' SYMLINK $@'
174ifneq ($(KBUILD_SRC),)
175 $(Q)mkdir -p $(ARCH_DIR)/include
176 $(Q)mkdir -p $(ARCH_DIR)/include2
177 $(Q)ln -fsn sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep
178 $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include2/sysdep
179else
168 $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep 180 $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
181endif
169 182
170$(ARCH_DIR)/os: 183$(ARCH_DIR)/os:
171 @echo ' SYMLINK $@' 184 @echo ' SYMLINK $@'
185ifneq ($(KBUILD_SRC),)
186 $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/os-$(OS) $(ARCH_DIR)/os
187else
172 $(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os 188 $(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os
189endif
173 190
174# Generated files 191# Generated files
175define filechk_umlconfig 192define filechk_umlconfig
@@ -179,10 +196,31 @@ endef
179$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h 196$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
180 $(call filechk,umlconfig) 197 $(call filechk,umlconfig)
181 198
199$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
200 $(CC) $(USER_CFLAGS) -S -o $@ $<
201
202$(ARCH_DIR)/user-offsets.h: $(ARCH_DIR)/user-offsets.s
203 $(call filechk,gen-asm-offsets)
204
205CLEAN_FILES += $(ARCH_DIR)/user-offsets.s $(ARCH_DIR)/user-offsets.h
206
207$(ARCH_DIR)/kernel-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/kernel-offsets.c \
208 $(ARCH_SYMLINKS) \
209 $(SYS_DIR)/sc.h \
210 include/asm include/linux/version.h \
211 include/config/MARKER \
212 $(ARCH_DIR)/include/user_constants.h
213 $(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $<
214
215$(ARCH_DIR)/kernel-offsets.h: $(ARCH_DIR)/kernel-offsets.s
216 $(call filechk,gen-asm-offsets)
217
218CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s $(ARCH_DIR)/kernel-offsets.h
219
182$(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task 220$(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task
183 $(call filechk,gen_header) 221 $(call filechk,gen_header)
184 222
185$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/os/util/mk_user_constants 223$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/os-$(OS)/util/mk_user_constants
186 $(call filechk,gen_header) 224 $(call filechk,gen_header)
187 225
188$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants 226$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants
@@ -191,20 +229,20 @@ $(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants
191$(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs 229$(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs
192 $(call filechk,gen_header) 230 $(call filechk,gen_header)
193 231
194$(ARCH_DIR)/os/util/mk_user_constants: $(ARCH_DIR)/os/util FORCE ; 232$(ARCH_DIR)/os-$(OS)/util/mk_user_constants: $(ARCH_DIR)/os-$(OS)/util FORCE ;
195 233
196$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/util \ 234$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/util \
197 FORCE ; 235 FORCE ;
198 236
199$(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ; 237$(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ;
200 238
201$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h FORCE 239$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h $(ARCH_DIR)/kernel-offsets.h FORCE
202 $(Q)$(MAKE) $(build)=$@ 240 $(Q)$(MAKE) $(build)=$@
203 241
204$(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE 242$(ARCH_DIR)/kernel/skas/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
205 $(Q)$(MAKE) $(build)=$@ 243 $(Q)$(MAKE) $(build)=$@
206 244
207$(ARCH_DIR)/os/util: scripts_basic FORCE 245$(ARCH_DIR)/os-$(OS)/util: scripts_basic FORCE
208 $(Q)$(MAKE) $(build)=$@ 246 $(Q)$(MAKE) $(build)=$@
209 247
210export SUBARCH USER_CFLAGS OS 248export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index f9e3c0f06541..29e182d5a83a 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -32,10 +32,10 @@ $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
32$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 32$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
33 $(call filechk,gen_header) 33 $(call filechk,gen_header)
34 34
35$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE 35$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
36 $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ 36 $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
37 37
38$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE 38$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_DIR)/kernel-offsets.h FORCE
39 $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ 39 $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
40 40
41$(SYS_UTIL_DIR): scripts_basic include/asm FORCE 41$(SYS_UTIL_DIR): scripts_basic include/asm FORCE
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index a77971133e91..32144562c279 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -23,10 +23,10 @@ $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
23$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 23$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
24 $(call filechk,gen_header) 24 $(call filechk,gen_header)
25 25
26$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE 26$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
27 $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ 27 $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
28 28
29$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE 29$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(GEN_HEADERS) $(ARCH_DIR)/kernel-offsets.h FORCE
30 $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ 30 $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
31 31
32CLEAN_FILES += $(SYS_HEADERS) 32CLEAN_FILES += $(SYS_HEADERS)
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 0150038af795..14a12d6b3df6 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -20,9 +20,17 @@
20#include "os.h" 20#include "os.h"
21 21
22#ifdef CONFIG_NOCONFIG_CHAN 22#ifdef CONFIG_NOCONFIG_CHAN
23
24/* The printk's here are wrong because we are complaining that there is no
25 * output device, but printk is printing to that output device. The user will
26 * never see the error. printf would be better, except it can't run on a
27 * kernel stack because it will overflow it.
28 * Use printk for now since that will avoid crashing.
29 */
30
23static void *not_configged_init(char *str, int device, struct chan_opts *opts) 31static void *not_configged_init(char *str, int device, struct chan_opts *opts)
24{ 32{
25 printf(KERN_ERR "Using a channel type which is configured out of " 33 printk(KERN_ERR "Using a channel type which is configured out of "
26 "UML\n"); 34 "UML\n");
27 return(NULL); 35 return(NULL);
28} 36}
@@ -30,27 +38,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
30static int not_configged_open(int input, int output, int primary, void *data, 38static int not_configged_open(int input, int output, int primary, void *data,
31 char **dev_out) 39 char **dev_out)
32{ 40{
33 printf(KERN_ERR "Using a channel type which is configured out of " 41 printk(KERN_ERR "Using a channel type which is configured out of "
34 "UML\n"); 42 "UML\n");
35 return(-ENODEV); 43 return(-ENODEV);
36} 44}
37 45
38static void not_configged_close(int fd, void *data) 46static void not_configged_close(int fd, void *data)
39{ 47{
40 printf(KERN_ERR "Using a channel type which is configured out of " 48 printk(KERN_ERR "Using a channel type which is configured out of "
41 "UML\n"); 49 "UML\n");
42} 50}
43 51
44static int not_configged_read(int fd, char *c_out, void *data) 52static int not_configged_read(int fd, char *c_out, void *data)
45{ 53{
46 printf(KERN_ERR "Using a channel type which is configured out of " 54 printk(KERN_ERR "Using a channel type which is configured out of "
47 "UML\n"); 55 "UML\n");
48 return(-EIO); 56 return(-EIO);
49} 57}
50 58
51static int not_configged_write(int fd, const char *buf, int len, void *data) 59static int not_configged_write(int fd, const char *buf, int len, void *data)
52{ 60{
53 printf(KERN_ERR "Using a channel type which is configured out of " 61 printk(KERN_ERR "Using a channel type which is configured out of "
54 "UML\n"); 62 "UML\n");
55 return(-EIO); 63 return(-EIO);
56} 64}
@@ -58,7 +66,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data)
58static int not_configged_console_write(int fd, const char *buf, int len, 66static int not_configged_console_write(int fd, const char *buf, int len,
59 void *data) 67 void *data)
60{ 68{
61 printf(KERN_ERR "Using a channel type which is configured out of " 69 printk(KERN_ERR "Using a channel type which is configured out of "
62 "UML\n"); 70 "UML\n");
63 return(-EIO); 71 return(-EIO);
64} 72}
@@ -66,7 +74,7 @@ static int not_configged_console_write(int fd, const char *buf, int len,
66static int not_configged_window_size(int fd, void *data, unsigned short *rows, 74static int not_configged_window_size(int fd, void *data, unsigned short *rows,
67 unsigned short *cols) 75 unsigned short *cols)
68{ 76{
69 printf(KERN_ERR "Using a channel type which is configured out of " 77 printk(KERN_ERR "Using a channel type which is configured out of "
70 "UML\n"); 78 "UML\n");
71 return(-ENODEV); 79 return(-ENODEV);
72} 80}
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index d0f97127adf6..025d3be8aca4 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -462,12 +462,15 @@ out:
462 return err; 462 return err;
463} 463}
464 464
465static void unregister_winch(struct tty_struct *tty);
466
465void line_close(struct tty_struct *tty, struct file * filp) 467void line_close(struct tty_struct *tty, struct file * filp)
466{ 468{
467 struct line *line = tty->driver_data; 469 struct line *line = tty->driver_data;
468 470
469 /* XXX: I assume this should be called in process context, not with interrupt 471 /* XXX: I assume this should be called in process context, not with
470 * disabled!*/ 472 * interrupts disabled!
473 */
471 spin_lock_irq(&line->lock); 474 spin_lock_irq(&line->lock);
472 475
473 /* We ignore the error anyway! */ 476 /* We ignore the error anyway! */
@@ -478,6 +481,12 @@ void line_close(struct tty_struct *tty, struct file * filp)
478 line_disable(tty, -1); 481 line_disable(tty, -1);
479 tty->driver_data = NULL; 482 tty->driver_data = NULL;
480 } 483 }
484
485 if((line->count == 0) && line->sigio){
486 unregister_winch(tty);
487 line->sigio = 0;
488 }
489
481 spin_unlock_irq(&line->lock); 490 spin_unlock_irq(&line->lock);
482} 491}
483 492
@@ -729,6 +738,34 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
729 up(&winch_handler_sem); 738 up(&winch_handler_sem);
730} 739}
731 740
741static void unregister_winch(struct tty_struct *tty)
742{
743 struct list_head *ele;
744 struct winch *winch, *found = NULL;
745
746 down(&winch_handler_sem);
747 list_for_each(ele, &winch_handlers){
748 winch = list_entry(ele, struct winch, list);
749 if(winch->tty == tty){
750 found = winch;
751 break;
752 }
753 }
754
755 if(found == NULL)
756 goto out;
757
758 if(winch->pid != -1)
759 os_kill_process(winch->pid, 1);
760
761 free_irq_by_irq_and_dev(WINCH_IRQ, winch);
762 free_irq(WINCH_IRQ, winch);
763 list_del(&winch->list);
764 kfree(winch);
765 out:
766 up(&winch_handler_sem);
767}
768
732static void winch_cleanup(void) 769static void winch_cleanup(void)
733{ 770{
734 struct list_head *ele; 771 struct list_head *ele;
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index faf714e87b5b..217438cdef33 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -73,7 +73,6 @@ int mcast_setup(char *str, char **mac_out, void *data)
73 struct mcast_init *init = data; 73 struct mcast_init *init = data;
74 char *port_str = NULL, *ttl_str = NULL, *remain; 74 char *port_str = NULL, *ttl_str = NULL, *remain;
75 char *last; 75 char *last;
76 int n;
77 76
78 *init = ((struct mcast_init) 77 *init = ((struct mcast_init)
79 { .addr = "239.192.168.1", 78 { .addr = "239.192.168.1",
@@ -89,13 +88,12 @@ int mcast_setup(char *str, char **mac_out, void *data)
89 } 88 }
90 89
91 if(port_str != NULL){ 90 if(port_str != NULL){
92 n = simple_strtoul(port_str, &last, 10); 91 init->port = simple_strtoul(port_str, &last, 10);
93 if((*last != '\0') || (last == port_str)){ 92 if((*last != '\0') || (last == port_str)){
94 printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", 93 printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
95 port_str); 94 port_str);
96 return(0); 95 return(0);
97 } 96 }
98 init->port = htons(n);
99 } 97 }
100 98
101 if(ttl_str != NULL){ 99 if(ttl_str != NULL){
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 0fe1d9fa9139..7a0d115b29d0 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -38,7 +38,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
38 } 38 }
39 sin->sin_family = AF_INET; 39 sin->sin_family = AF_INET;
40 sin->sin_addr.s_addr = in_aton(addr); 40 sin->sin_addr.s_addr = in_aton(addr);
41 sin->sin_port = port; 41 sin->sin_port = htons(port);
42 return(sin); 42 return(sin);
43} 43}
44 44
@@ -55,28 +55,25 @@ static int mcast_open(void *data)
55 struct mcast_data *pri = data; 55 struct mcast_data *pri = data;
56 struct sockaddr_in *sin = pri->mcast_addr; 56 struct sockaddr_in *sin = pri->mcast_addr;
57 struct ip_mreq mreq; 57 struct ip_mreq mreq;
58 int fd, yes = 1; 58 int fd = -EINVAL, yes = 1, err = -EINVAL;;
59 59
60 60
61 if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) { 61 if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
62 fd = -EINVAL;
63 goto out; 62 goto out;
64 }
65 63
66 fd = socket(AF_INET, SOCK_DGRAM, 0); 64 fd = socket(AF_INET, SOCK_DGRAM, 0);
65
67 if (fd < 0){ 66 if (fd < 0){
68 printk("mcast_open : data socket failed, errno = %d\n", 67 printk("mcast_open : data socket failed, errno = %d\n",
69 errno); 68 errno);
70 fd = -ENOMEM; 69 fd = -errno;
71 goto out; 70 goto out;
72 } 71 }
73 72
74 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { 73 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
75 printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", 74 printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
76 errno); 75 errno);
77 os_close_file(fd); 76 goto out_close;
78 fd = -EINVAL;
79 goto out;
80 } 77 }
81 78
82 /* set ttl according to config */ 79 /* set ttl according to config */
@@ -84,26 +81,20 @@ static int mcast_open(void *data)
84 sizeof(pri->ttl)) < 0) { 81 sizeof(pri->ttl)) < 0) {
85 printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", 82 printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
86 errno); 83 errno);
87 os_close_file(fd); 84 goto out_close;
88 fd = -EINVAL;
89 goto out;
90 } 85 }
91 86
92 /* set LOOP, so data does get fed back to local sockets */ 87 /* set LOOP, so data does get fed back to local sockets */
93 if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { 88 if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
94 printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", 89 printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
95 errno); 90 errno);
96 os_close_file(fd); 91 goto out_close;
97 fd = -EINVAL;
98 goto out;
99 } 92 }
100 93
101 /* bind socket to mcast address */ 94 /* bind socket to mcast address */
102 if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { 95 if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
103 printk("mcast_open : data bind failed, errno = %d\n", errno); 96 printk("mcast_open : data bind failed, errno = %d\n", errno);
104 os_close_file(fd); 97 goto out_close;
105 fd = -EINVAL;
106 goto out;
107 } 98 }
108 99
109 /* subscribe to the multicast group */ 100 /* subscribe to the multicast group */
@@ -117,12 +108,15 @@ static int mcast_open(void *data)
117 "interface on the host.\n"); 108 "interface on the host.\n");
118 printk("eth0 should be configured in order to use the " 109 printk("eth0 should be configured in order to use the "
119 "multicast transport.\n"); 110 "multicast transport.\n");
120 os_close_file(fd); 111 goto out_close;
121 fd = -EINVAL;
122 } 112 }
123 113
124 out: 114 out:
125 return(fd); 115 return fd;
116
117 out_close:
118 os_close_file(fd);
119 return err;
126} 120}
127 121
128static void mcast_close(int fd, void *data) 122static void mcast_close(int fd, void *data)
@@ -164,14 +158,3 @@ struct net_user_info mcast_user_info = {
164 .delete_address = NULL, 158 .delete_address = NULL,
165 .max_packet = MAX_PACKET - ETH_HEADER_OTHER 159 .max_packet = MAX_PACKET - ETH_HEADER_OTHER
166}; 160};
167
168/*
169 * Overrides for Emacs so that we follow Linus's tabbing style.
170 * Emacs will notice this stuff at the end of the file and automatically
171 * adjust the settings for this buffer only. This must remain at the end
172 * of the file.
173 * ---------------------------------------------------------------------------
174 * Local variables:
175 * c-file-style: "linux"
176 * End:
177 */
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index d43e9fab05a7..f9e22198e011 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -1,5 +1,10 @@
1/* Much of this ripped from hw_random.c */ 1/* Copyright (C) 2005 Jeff Dike <jdike@addtoit.com> */
2 2/* Much of this ripped from drivers/char/hw_random.c, see there for other
3 * copyright.
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 */
3#include <linux/module.h> 8#include <linux/module.h>
4#include <linux/fs.h> 9#include <linux/fs.h>
5#include <linux/miscdevice.h> 10#include <linux/miscdevice.h>
@@ -12,8 +17,6 @@
12 */ 17 */
13#define RNG_VERSION "1.0.0" 18#define RNG_VERSION "1.0.0"
14#define RNG_MODULE_NAME "random" 19#define RNG_MODULE_NAME "random"
15#define RNG_DRIVER_NAME RNG_MODULE_NAME " virtual driver " RNG_VERSION
16#define PFX RNG_MODULE_NAME ": "
17 20
18#define RNG_MISCDEV_MINOR 183 /* official */ 21#define RNG_MISCDEV_MINOR 183 /* official */
19 22
@@ -98,7 +101,7 @@ static int __init rng_init (void)
98 101
99 err = misc_register (&rng_miscdev); 102 err = misc_register (&rng_miscdev);
100 if (err) { 103 if (err) {
101 printk (KERN_ERR PFX "misc device register failed\n"); 104 printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
102 goto err_out_cleanup_hw; 105 goto err_out_cleanup_hw;
103 } 106 }
104 107
@@ -120,3 +123,6 @@ static void __exit rng_cleanup (void)
120 123
121module_init (rng_init); 124module_init (rng_init);
122module_exit (rng_cleanup); 125module_exit (rng_cleanup);
126
127MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");
128MODULE_LICENSE("GPL");
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index a2bac429f3d4..b32a77010fbe 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -22,7 +22,6 @@
22#include "init.h" 22#include "init.h"
23#include "irq_user.h" 23#include "irq_user.h"
24#include "mconsole_kern.h" 24#include "mconsole_kern.h"
25#include "2_5compat.h"
26 25
27static int ssl_version = 1; 26static int ssl_version = 1;
28 27
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 361d0be342b3..afbe1e71ed83 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -28,7 +28,6 @@
28#include "irq_user.h" 28#include "irq_user.h"
29#include "mconsole_kern.h" 29#include "mconsole_kern.h"
30#include "init.h" 30#include "init.h"
31#include "2_5compat.h"
32 31
33#define MAX_TTYS (16) 32#define MAX_TTYS (16)
34 33
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 9a56ff94308d..2a7f6892c55c 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -49,13 +49,12 @@
49#include "irq_user.h" 49#include "irq_user.h"
50#include "irq_kern.h" 50#include "irq_kern.h"
51#include "ubd_user.h" 51#include "ubd_user.h"
52#include "2_5compat.h"
53#include "os.h" 52#include "os.h"
54#include "mem.h" 53#include "mem.h"
55#include "mem_kern.h" 54#include "mem_kern.h"
56#include "cow.h" 55#include "cow.h"
57 56
58enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP }; 57enum ubd_req { UBD_READ, UBD_WRITE };
59 58
60struct io_thread_req { 59struct io_thread_req {
61 enum ubd_req op; 60 enum ubd_req op;
@@ -68,8 +67,6 @@ struct io_thread_req {
68 unsigned long sector_mask; 67 unsigned long sector_mask;
69 unsigned long long cow_offset; 68 unsigned long long cow_offset;
70 unsigned long bitmap_words[2]; 69 unsigned long bitmap_words[2];
71 int map_fd;
72 unsigned long long map_offset;
73 int error; 70 int error;
74}; 71};
75 72
@@ -122,10 +119,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
122 119
123#define MAX_DEV (8) 120#define MAX_DEV (8)
124 121
125/* Changed in early boot */
126static int ubd_do_mmap = 0;
127#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
128
129static struct block_device_operations ubd_blops = { 122static struct block_device_operations ubd_blops = {
130 .owner = THIS_MODULE, 123 .owner = THIS_MODULE,
131 .open = ubd_open, 124 .open = ubd_open,
@@ -175,12 +168,6 @@ struct ubd {
175 int no_cow; 168 int no_cow;
176 struct cow cow; 169 struct cow cow;
177 struct platform_device pdev; 170 struct platform_device pdev;
178
179 int map_writes;
180 int map_reads;
181 int nomap_writes;
182 int nomap_reads;
183 int write_maps;
184}; 171};
185 172
186#define DEFAULT_COW { \ 173#define DEFAULT_COW { \
@@ -200,11 +187,6 @@ struct ubd {
200 .openflags = OPEN_FLAGS, \ 187 .openflags = OPEN_FLAGS, \
201 .no_cow = 0, \ 188 .no_cow = 0, \
202 .cow = DEFAULT_COW, \ 189 .cow = DEFAULT_COW, \
203 .map_writes = 0, \
204 .map_reads = 0, \
205 .nomap_writes = 0, \
206 .nomap_reads = 0, \
207 .write_maps = 0, \
208} 190}
209 191
210struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; 192struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
@@ -314,13 +296,6 @@ static int ubd_setup_common(char *str, int *index_out)
314 int major; 296 int major;
315 297
316 str++; 298 str++;
317 if(!strcmp(str, "mmap")){
318 CHOOSE_MODE(printk("mmap not supported by the ubd "
319 "driver in tt mode\n"),
320 ubd_do_mmap = 1);
321 return(0);
322 }
323
324 if(!strcmp(str, "sync")){ 299 if(!strcmp(str, "sync")){
325 global_openflags = of_sync(global_openflags); 300 global_openflags = of_sync(global_openflags);
326 return(0); 301 return(0);
@@ -464,9 +439,9 @@ static int udb_setup(char *str)
464__setup("udb", udb_setup); 439__setup("udb", udb_setup);
465__uml_help(udb_setup, 440__uml_help(udb_setup,
466"udb\n" 441"udb\n"
467" This option is here solely to catch ubd -> udb typos, which can be\n\n" 442" This option is here solely to catch ubd -> udb typos, which can be\n"
468" to impossible to catch visually unless you specifically look for\n\n" 443" to impossible to catch visually unless you specifically look for\n"
469" them. The only result of any option starting with 'udb' is an error\n\n" 444" them. The only result of any option starting with 'udb' is an error\n"
470" in the boot output.\n\n" 445" in the boot output.\n\n"
471); 446);
472 447
@@ -524,7 +499,7 @@ static void ubd_handler(void)
524{ 499{
525 struct io_thread_req req; 500 struct io_thread_req req;
526 struct request *rq = elv_next_request(ubd_queue); 501 struct request *rq = elv_next_request(ubd_queue);
527 int n, err; 502 int n;
528 503
529 do_ubd = NULL; 504 do_ubd = NULL;
530 intr_count++; 505 intr_count++;
@@ -538,19 +513,6 @@ static void ubd_handler(void)
538 return; 513 return;
539 } 514 }
540 515
541 if((req.op != UBD_MMAP) &&
542 ((req.offset != ((__u64) (rq->sector)) << 9) ||
543 (req.length != (rq->current_nr_sectors) << 9)))
544 panic("I/O op mismatch");
545
546 if(req.map_fd != -1){
547 err = physmem_subst_mapping(req.buffer, req.map_fd,
548 req.map_offset, 1);
549 if(err)
550 printk("ubd_handler - physmem_subst_mapping failed, "
551 "err = %d\n", -err);
552 }
553
554 ubd_finish(rq, req.error); 516 ubd_finish(rq, req.error);
555 reactivate_fd(thread_fd, UBD_IRQ); 517 reactivate_fd(thread_fd, UBD_IRQ);
556 do_ubd_request(ubd_queue); 518 do_ubd_request(ubd_queue);
@@ -583,14 +545,10 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
583 545
584static void ubd_close(struct ubd *dev) 546static void ubd_close(struct ubd *dev)
585{ 547{
586 if(ubd_do_mmap)
587 physmem_forget_descriptor(dev->fd);
588 os_close_file(dev->fd); 548 os_close_file(dev->fd);
589 if(dev->cow.file == NULL) 549 if(dev->cow.file == NULL)
590 return; 550 return;
591 551
592 if(ubd_do_mmap)
593 physmem_forget_descriptor(dev->cow.fd);
594 os_close_file(dev->cow.fd); 552 os_close_file(dev->cow.fd);
595 vfree(dev->cow.bitmap); 553 vfree(dev->cow.bitmap);
596 dev->cow.bitmap = NULL; 554 dev->cow.bitmap = NULL;
@@ -1010,94 +968,13 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1010 req->bitmap_words, bitmap_len); 968 req->bitmap_words, bitmap_len);
1011} 969}
1012 970
1013static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
1014{
1015 __u64 sector;
1016 unsigned char *bitmap;
1017 int bit, i;
1018
1019 /* mmap must have been requested on the command line */
1020 if(!ubd_do_mmap)
1021 return(-1);
1022
1023 /* The buffer must be page aligned */
1024 if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
1025 return(-1);
1026
1027 /* The request must be a page long */
1028 if((req->current_nr_sectors << 9) != PAGE_SIZE)
1029 return(-1);
1030
1031 if(dev->cow.file == NULL)
1032 return(dev->fd);
1033
1034 sector = offset >> 9;
1035 bitmap = (unsigned char *) dev->cow.bitmap;
1036 bit = ubd_test_bit(sector, bitmap);
1037
1038 for(i = 1; i < req->current_nr_sectors; i++){
1039 if(ubd_test_bit(sector + i, bitmap) != bit)
1040 return(-1);
1041 }
1042
1043 if(bit || (rq_data_dir(req) == WRITE))
1044 offset += dev->cow.data_offset;
1045
1046 /* The data on disk must be page aligned */
1047 if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
1048 return(-1);
1049
1050 return(bit ? dev->fd : dev->cow.fd);
1051}
1052
1053static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
1054 struct request *req,
1055 struct io_thread_req *io_req)
1056{
1057 int err;
1058
1059 if(rq_data_dir(req) == WRITE){
1060 /* Writes are almost no-ops since the new data is already in the
1061 * host page cache
1062 */
1063 dev->map_writes++;
1064 if(dev->cow.file != NULL)
1065 cowify_bitmap(io_req->offset, io_req->length,
1066 &io_req->sector_mask, &io_req->cow_offset,
1067 dev->cow.bitmap, dev->cow.bitmap_offset,
1068 io_req->bitmap_words,
1069 dev->cow.bitmap_len);
1070 }
1071 else {
1072 int w;
1073
1074 if((dev->cow.file != NULL) && (fd == dev->cow.fd))
1075 w = 0;
1076 else w = dev->openflags.w;
1077
1078 if((dev->cow.file != NULL) && (fd == dev->fd))
1079 offset += dev->cow.data_offset;
1080
1081 err = physmem_subst_mapping(req->buffer, fd, offset, w);
1082 if(err){
1083 printk("physmem_subst_mapping failed, err = %d\n",
1084 -err);
1085 return(1);
1086 }
1087 dev->map_reads++;
1088 }
1089 io_req->op = UBD_MMAP;
1090 io_req->buffer = req->buffer;
1091 return(0);
1092}
1093
1094/* Called with ubd_io_lock held */ 971/* Called with ubd_io_lock held */
1095static int prepare_request(struct request *req, struct io_thread_req *io_req) 972static int prepare_request(struct request *req, struct io_thread_req *io_req)
1096{ 973{
1097 struct gendisk *disk = req->rq_disk; 974 struct gendisk *disk = req->rq_disk;
1098 struct ubd *dev = disk->private_data; 975 struct ubd *dev = disk->private_data;
1099 __u64 offset; 976 __u64 offset;
1100 int len, fd; 977 int len;
1101 978
1102 if(req->rq_status == RQ_INACTIVE) return(1); 979 if(req->rq_status == RQ_INACTIVE) return(1);
1103 980
@@ -1114,34 +991,12 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
1114 991
1115 io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; 992 io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
1116 io_req->fds[1] = dev->fd; 993 io_req->fds[1] = dev->fd;
1117 io_req->map_fd = -1;
1118 io_req->cow_offset = -1; 994 io_req->cow_offset = -1;
1119 io_req->offset = offset; 995 io_req->offset = offset;
1120 io_req->length = len; 996 io_req->length = len;
1121 io_req->error = 0; 997 io_req->error = 0;
1122 io_req->sector_mask = 0; 998 io_req->sector_mask = 0;
1123 999
1124 fd = mmap_fd(req, dev, io_req->offset);
1125 if(fd > 0){
1126 /* If mmapping is otherwise OK, but the first access to the
1127 * page is a write, then it's not mapped in yet. So we have
1128 * to write the data to disk first, then we can map the disk
1129 * page in and continue normally from there.
1130 */
1131 if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
1132 io_req->map_fd = dev->fd;
1133 io_req->map_offset = io_req->offset +
1134 dev->cow.data_offset;
1135 dev->write_maps++;
1136 }
1137 else return(prepare_mmap_request(dev, fd, io_req->offset, req,
1138 io_req));
1139 }
1140
1141 if(rq_data_dir(req) == READ)
1142 dev->nomap_reads++;
1143 else dev->nomap_writes++;
1144
1145 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; 1000 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
1146 io_req->offsets[0] = 0; 1001 io_req->offsets[0] = 0;
1147 io_req->offsets[1] = dev->cow.data_offset; 1002 io_req->offsets[1] = dev->cow.data_offset;
@@ -1229,143 +1084,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1229 return(-EINVAL); 1084 return(-EINVAL);
1230} 1085}
1231 1086
1232static int ubd_check_remapped(int fd, unsigned long address, int is_write,
1233 __u64 offset)
1234{
1235 __u64 bitmap_offset;
1236 unsigned long new_bitmap[2];
1237 int i, err, n;
1238
1239 /* If it's not a write access, we can't do anything about it */
1240 if(!is_write)
1241 return(0);
1242
1243 /* We have a write */
1244 for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
1245 struct ubd *dev = &ubd_dev[i];
1246
1247 if((dev->fd != fd) && (dev->cow.fd != fd))
1248 continue;
1249
1250 /* It's a write to a ubd device */
1251
1252 /* This should be impossible now */
1253 if(!dev->openflags.w){
1254 /* It's a write access on a read-only device - probably
1255 * shouldn't happen. If the kernel is trying to change
1256 * something with no intention of writing it back out,
1257 * then this message will clue us in that this needs
1258 * fixing
1259 */
1260 printk("Write access to mapped page from readonly ubd "
1261 "device %d\n", i);
1262 return(0);
1263 }
1264
1265 /* It's a write to a writeable ubd device - it must be COWed
1266 * because, otherwise, the page would have been mapped in
1267 * writeable
1268 */
1269
1270 if(!dev->cow.file)
1271 panic("Write fault on writeable non-COW ubd device %d",
1272 i);
1273
1274 /* It should also be an access to the backing file since the
1275 * COW pages should be mapped in read-write
1276 */
1277
1278 if(fd == dev->fd)
1279 panic("Write fault on a backing page of ubd "
1280 "device %d\n", i);
1281
1282 /* So, we do the write, copying the backing data to the COW
1283 * file...
1284 */
1285
1286 err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
1287 if(err < 0)
1288 panic("Couldn't seek to %lld in COW file of ubd "
1289 "device %d, err = %d",
1290 offset + dev->cow.data_offset, i, -err);
1291
1292 n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
1293 if(n != PAGE_SIZE)
1294 panic("Couldn't copy data to COW file of ubd "
1295 "device %d, err = %d", i, -n);
1296
1297 /* ... updating the COW bitmap... */
1298
1299 cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
1300 dev->cow.bitmap, dev->cow.bitmap_offset,
1301 new_bitmap, dev->cow.bitmap_len);
1302
1303 err = os_seek_file(dev->fd, bitmap_offset);
1304 if(err < 0)
1305 panic("Couldn't seek to %lld in COW file of ubd "
1306 "device %d, err = %d", bitmap_offset, i, -err);
1307
1308 n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
1309 if(n != sizeof(new_bitmap))
1310 panic("Couldn't update bitmap of ubd device %d, "
1311 "err = %d", i, -n);
1312
1313 /* Maybe we can map the COW page in, and maybe we can't. If
1314 * it is a pre-V3 COW file, we can't, since the alignment will
1315 * be wrong. If it is a V3 or later COW file which has been
1316 * moved to a system with a larger page size, then maybe we
1317 * can't, depending on the exact location of the page.
1318 */
1319
1320 offset += dev->cow.data_offset;
1321
1322 /* Remove the remapping, putting the original anonymous page
1323 * back. If the COW file can be mapped in, that is done.
1324 * Otherwise, the COW page is read in.
1325 */
1326
1327 if(!physmem_remove_mapping((void *) address))
1328 panic("Address 0x%lx not remapped by ubd device %d",
1329 address, i);
1330 if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
1331 physmem_subst_mapping((void *) address, dev->fd,
1332 offset, 1);
1333 else {
1334 err = os_seek_file(dev->fd, offset);
1335 if(err < 0)
1336 panic("Couldn't seek to %lld in COW file of "
1337 "ubd device %d, err = %d", offset, i,
1338 -err);
1339
1340 n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
1341 if(n != PAGE_SIZE)
1342 panic("Failed to read page from offset %llx of "
1343 "COW file of ubd device %d, err = %d",
1344 offset, i, -n);
1345 }
1346
1347 return(1);
1348 }
1349
1350 /* It's not a write on a ubd device */
1351 return(0);
1352}
1353
1354static struct remapper ubd_remapper = {
1355 .list = LIST_HEAD_INIT(ubd_remapper.list),
1356 .proc = ubd_check_remapped,
1357};
1358
1359static int ubd_remapper_setup(void)
1360{
1361 if(ubd_do_mmap)
1362 register_remapper(&ubd_remapper);
1363
1364 return(0);
1365}
1366
1367__initcall(ubd_remapper_setup);
1368
1369static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) 1087static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
1370{ 1088{
1371 struct uml_stat buf1, buf2; 1089 struct uml_stat buf1, buf2;
@@ -1568,15 +1286,6 @@ void do_io(struct io_thread_req *req)
1568 int err; 1286 int err;
1569 __u64 off; 1287 __u64 off;
1570 1288
1571 if(req->op == UBD_MMAP){
1572 /* Touch the page to force the host to do any necessary IO to
1573 * get it into memory
1574 */
1575 n = *((volatile int *) req->buffer);
1576 req->error = update_bitmap(req);
1577 return;
1578 }
1579
1580 nsectors = req->length / req->sectorsize; 1289 nsectors = req->length / req->sectorsize;
1581 start = 0; 1290 start = 0;
1582 do { 1291 do {
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index 7917b9d1cec8..a4fdf3584ad2 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -7,7 +7,6 @@
7#include "linux/slab.h" 7#include "linux/slab.h"
8#include "linux/signal.h" 8#include "linux/signal.h"
9#include "linux/interrupt.h" 9#include "linux/interrupt.h"
10#include "asm/semaphore.h"
11#include "asm/irq.h" 10#include "asm/irq.h"
12#include "irq_user.h" 11#include "irq_user.h"
13#include "irq_kern.h" 12#include "irq_kern.h"
diff --git a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h
deleted file mode 100644
index abdb015a4d71..000000000000
--- a/arch/um/include/2_5compat.h
+++ /dev/null
@@ -1,24 +0,0 @@
1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __2_5_COMPAT_H__
7#define __2_5_COMPAT_H__
8
9#define INIT_HARDSECT(arr, maj, sizes)
10
11#define SET_PRI(task) do ; while(0)
12
13#endif
14
15/*
16 * Overrides for Emacs so that we follow Linus's tabbing style.
17 * Emacs will notice this stuff at the end of the file and automatically
18 * adjust the settings for this buffer only. This must remain at the end
19 * of the file.
20 * ---------------------------------------------------------------------------
21 * Local variables:
22 * c-file-style: "linux"
23 * End:
24 */
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
new file mode 100644
index 000000000000..d705daa2d854
--- /dev/null
+++ b/arch/um/include/common-offsets.h
@@ -0,0 +1,14 @@
1/* for use by sys-$SUBARCH/kernel-offsets.c */
2
3OFFSET(TASK_REGS, task_struct, thread.regs);
4OFFSET(TASK_PID, task_struct, pid);
5DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
6DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
7DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
8DEFINE_STR(UM_KERN_ALERT, KERN_ALERT);
9DEFINE_STR(UM_KERN_CRIT, KERN_CRIT);
10DEFINE_STR(UM_KERN_ERR, KERN_ERR);
11DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
12DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
13DEFINE_STR(UM_KERN_INFO, KERN_INFO);
14DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 15389c886b41..e5fec5570199 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -8,6 +8,7 @@
8 8
9#include "linux/threads.h" 9#include "linux/threads.h"
10#include "sysdep/ptrace.h" 10#include "sysdep/ptrace.h"
11#include "sysdep/faultinfo.h"
11 12
12extern int ncpus; 13extern int ncpus;
13extern char *linux_prog; 14extern char *linux_prog;
@@ -31,8 +32,8 @@ extern int current_pid(void);
31extern unsigned long alloc_stack(int order, int atomic); 32extern unsigned long alloc_stack(int order, int atomic);
32extern int do_signal(void); 33extern int do_signal(void);
33extern int is_stack_fault(unsigned long sp); 34extern int is_stack_fault(unsigned long sp);
34extern unsigned long segv(unsigned long address, unsigned long ip, 35extern unsigned long segv(struct faultinfo fi, unsigned long ip,
35 int is_write, int is_user, void *sc); 36 int is_user, void *sc);
36extern int handle_page_fault(unsigned long address, unsigned long ip, 37extern int handle_page_fault(unsigned long address, unsigned long ip,
37 int is_write, int is_user, int *code_out); 38 int is_write, int is_user, int *code_out);
38extern void syscall_ready(void); 39extern void syscall_ready(void);
@@ -82,7 +83,7 @@ extern void timer_irq(union uml_pt_regs *regs);
82extern void unprotect_stack(unsigned long stack); 83extern void unprotect_stack(unsigned long stack);
83extern void do_uml_exitcalls(void); 84extern void do_uml_exitcalls(void);
84extern int attach_debugger(int idle_pid, int pid, int stop); 85extern int attach_debugger(int idle_pid, int pid, int stop);
85extern void bad_segv(unsigned long address, unsigned long ip, int is_write); 86extern void bad_segv(struct faultinfo fi, unsigned long ip);
86extern int config_gdb(char *str); 87extern int config_gdb(char *str);
87extern int remove_gdb(void); 88extern int remove_gdb(void);
88extern char *uml_strdup(char *string); 89extern char *uml_strdup(char *string);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 07340c8cf203..d246d5a24609 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -160,6 +160,7 @@ extern void os_kill_process(int pid, int reap_child);
160extern void os_kill_ptraced_process(int pid, int reap_child); 160extern void os_kill_ptraced_process(int pid, int reap_child);
161extern void os_usr1_process(int pid); 161extern void os_usr1_process(int pid);
162extern int os_getpid(void); 162extern int os_getpid(void);
163extern int os_getpgrp(void);
163 164
164extern int os_map_memory(void *virt, int fd, unsigned long long off, 165extern int os_map_memory(void *virt, int fd, unsigned long long off,
165 unsigned long len, int r, int w, int x); 166 unsigned long len, int r, int w, int x);
diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h
index cfb5fb4f5b91..cd2327d09c8d 100644
--- a/arch/um/include/skas_ptrace.h
+++ b/arch/um/include/skas_ptrace.h
@@ -6,22 +6,11 @@
6#ifndef __SKAS_PTRACE_H 6#ifndef __SKAS_PTRACE_H
7#define __SKAS_PTRACE_H 7#define __SKAS_PTRACE_H
8 8
9struct ptrace_faultinfo {
10 int is_write;
11 unsigned long addr;
12};
13
14struct ptrace_ldt {
15 int func;
16 void *ptr;
17 unsigned long bytecount;
18};
19
20#define PTRACE_FAULTINFO 52 9#define PTRACE_FAULTINFO 52
21#define PTRACE_SIGPENDING 53
22#define PTRACE_LDT 54
23#define PTRACE_SWITCH_MM 55 10#define PTRACE_SWITCH_MM 55
24 11
12#include "sysdep/skas_ptrace.h"
13
25#endif 14#endif
26 15
27/* 16/*
diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
index 3a2a45811aa3..764ba4db4788 100644
--- a/arch/um/include/sysdep-i386/checksum.h
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -24,19 +24,6 @@ unsigned int csum_partial(const unsigned char * buff, int len,
24 unsigned int sum); 24 unsigned int sum);
25 25
26/* 26/*
27 * the same as csum_partial, but copies from src while it
28 * checksums, and handles user-space pointer exceptions correctly, when needed.
29 *
30 * here even more important to align src and dst on a 32-bit (or even
31 * better 64-bit) boundary
32 */
33
34unsigned int csum_partial_copy_to(const unsigned char *src, unsigned char *dst,
35 int len, int sum, int *err_ptr);
36unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst,
37 int len, int sum, int *err_ptr);
38
39/*
40 * Note: when you get a NULL pointer exception here this means someone 27 * Note: when you get a NULL pointer exception here this means someone
41 * passed in an incorrect kernel address to one of these functions. 28 * passed in an incorrect kernel address to one of these functions.
42 * 29 *
@@ -52,11 +39,24 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
52 return(csum_partial(dst, len, sum)); 39 return(csum_partial(dst, len, sum));
53} 40}
54 41
42/*
43 * the same as csum_partial, but copies from src while it
44 * checksums, and handles user-space pointer exceptions correctly, when needed.
45 *
46 * here even more important to align src and dst on a 32-bit (or even
47 * better 64-bit) boundary
48 */
49
55static __inline__ 50static __inline__
56unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, 51unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
57 int len, int sum, int *err_ptr) 52 int len, int sum, int *err_ptr)
58{ 53{
59 return csum_partial_copy_from(src, dst, len, sum, err_ptr); 54 if(copy_from_user(dst, src, len)){
55 *err_ptr = -EFAULT;
56 return(-1);
57 }
58
59 return csum_partial(dst, len, sum);
60} 60}
61 61
62/* 62/*
@@ -67,7 +67,6 @@ unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char
67 */ 67 */
68 68
69#define csum_partial_copy_fromuser csum_partial_copy_from_user 69#define csum_partial_copy_fromuser csum_partial_copy_from_user
70unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst, int len, int sum);
71 70
72/* 71/*
73 * This is a version of ip_compute_csum() optimized for IP headers, 72 * This is a version of ip_compute_csum() optimized for IP headers,
@@ -196,8 +195,14 @@ static __inline__ unsigned int csum_and_copy_to_user(const unsigned char *src,
196 unsigned char *dst, 195 unsigned char *dst,
197 int len, int sum, int *err_ptr) 196 int len, int sum, int *err_ptr)
198{ 197{
199 if (access_ok(VERIFY_WRITE, dst, len)) 198 if (access_ok(VERIFY_WRITE, dst, len)){
200 return(csum_partial_copy_to(src, dst, len, sum, err_ptr)); 199 if(copy_to_user(dst, src, len)){
200 *err_ptr = -EFAULT;
201 return(-1);
202 }
203
204 return csum_partial(src, len, sum);
205 }
201 206
202 if (len) 207 if (len)
203 *err_ptr = -EFAULT; 208 *err_ptr = -EFAULT;
diff --git a/arch/um/include/sysdep-i386/faultinfo.h b/arch/um/include/sysdep-i386/faultinfo.h
new file mode 100644
index 000000000000..db437cc373bc
--- /dev/null
+++ b/arch/um/include/sysdep-i386/faultinfo.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
3 * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
4 * Licensed under the GPL
5 */
6
7#ifndef __FAULTINFO_I386_H
8#define __FAULTINFO_I386_H
9
10/* this structure contains the full arch-specific faultinfo
11 * from the traps.
12 * On i386, ptrace_faultinfo unfortunately doesn't provide
13 * all the info, since trap_no is missing.
14 * All common elements are defined at the same position in
15 * both structures, thus making it easy to copy the
16 * contents without knowledge about the structure elements.
17 */
18struct faultinfo {
19 int error_code; /* in ptrace_faultinfo misleadingly called is_write */
20 unsigned long cr2; /* in ptrace_faultinfo called addr */
21 int trap_no; /* missing in ptrace_faultinfo */
22};
23
24#define FAULT_WRITE(fi) ((fi).error_code & 2)
25#define FAULT_ADDRESS(fi) ((fi).cr2)
26
27#define PTRACE_FULL_FAULTINFO 0
28
29#endif
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index 661d495e2044..6eaeb9919983 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -53,17 +53,12 @@ extern int sysemu_supported;
53 53
54#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) 54#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
55 55
56#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
57
58#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
59
60#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
61
62#endif 56#endif
63#ifndef PTRACE_SYSEMU_SINGLESTEP 57#ifndef PTRACE_SYSEMU_SINGLESTEP
64#define PTRACE_SYSEMU_SINGLESTEP 32 58#define PTRACE_SYSEMU_SINGLESTEP 32
65#endif 59#endif
66 60
61#include "sysdep/faultinfo.h"
67#include "choose-mode.h" 62#include "choose-mode.h"
68 63
69union uml_pt_regs { 64union uml_pt_regs {
@@ -71,6 +66,7 @@ union uml_pt_regs {
71 struct tt_regs { 66 struct tt_regs {
72 long syscall; 67 long syscall;
73 void *sc; 68 void *sc;
69 struct faultinfo faultinfo;
74 } tt; 70 } tt;
75#endif 71#endif
76#ifdef UML_CONFIG_MODE_SKAS 72#ifdef UML_CONFIG_MODE_SKAS
@@ -78,9 +74,7 @@ union uml_pt_regs {
78 unsigned long regs[HOST_FRAME_SIZE]; 74 unsigned long regs[HOST_FRAME_SIZE];
79 unsigned long fp[HOST_FP_SIZE]; 75 unsigned long fp[HOST_FP_SIZE];
80 unsigned long xfp[HOST_XFP_SIZE]; 76 unsigned long xfp[HOST_XFP_SIZE];
81 unsigned long fault_addr; 77 struct faultinfo faultinfo;
82 unsigned long fault_type;
83 unsigned long trap_type;
84 long syscall; 78 long syscall;
85 int is_user; 79 int is_user;
86 } skas; 80 } skas;
@@ -217,15 +211,8 @@ struct syscall_args {
217#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) 211#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
218#define UPT_SYSCALL_RET(r) UPT_EAX(r) 212#define UPT_SYSCALL_RET(r) UPT_EAX(r)
219 213
220#define UPT_SEGV_IS_FIXABLE(r) \ 214#define UPT_FAULTINFO(r) \
221 CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ 215 CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
222 REGS_SEGV_IS_FIXABLE(&r->skas))
223
224#define UPT_FAULT_ADDR(r) \
225 __CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
226
227#define UPT_FAULT_WRITE(r) \
228 CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
229 216
230#endif 217#endif
231 218
diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
index dfee589de360..1fe729265167 100644
--- a/arch/um/include/sysdep-i386/sigcontext.h
+++ b/arch/um/include/sysdep-i386/sigcontext.h
@@ -13,15 +13,12 @@
13#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) 13#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc))
14#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result) 14#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result)
15 15
16#define SC_FAULT_ADDR(sc) SC_CR2(sc) 16#define GET_FAULTINFO_FROM_SC(fi,sc) \
17#define SC_FAULT_TYPE(sc) SC_ERR(sc) 17 { \
18 18 (fi).cr2 = SC_CR2(sc); \
19#define FAULT_WRITE(err) (err & 2) 19 (fi).error_code = SC_ERR(sc); \
20#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0) 20 (fi).trap_no = SC_TRAPNO(sc); \
21 21 }
22#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc)))
23
24#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc)
25 22
26/* ptrace expects that, at the start of a system call, %eax contains 23/* ptrace expects that, at the start of a system call, %eax contains
27 * -ENOSYS, so this makes it so. 24 * -ENOSYS, so this makes it so.
@@ -29,9 +26,7 @@
29#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) 26#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
30 27
31/* This is Page Fault */ 28/* This is Page Fault */
32#define SEGV_IS_FIXABLE(trap) (trap == 14) 29#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
33
34#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
35 30
36extern unsigned long *sc_sigmask(void *sc_ptr); 31extern unsigned long *sc_sigmask(void *sc_ptr);
37extern int sc_get_fpregs(unsigned long buf, void *sc_ptr); 32extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
diff --git a/arch/um/include/sysdep-i386/signal.h b/arch/um/include/sysdep-i386/signal.h
index b1e1f7a77499..07518b162136 100644
--- a/arch/um/include/sysdep-i386/signal.h
+++ b/arch/um/include/sysdep-i386/signal.h
@@ -8,6 +8,8 @@
8 8
9#include <signal.h> 9#include <signal.h>
10 10
11#define ARCH_SIGHDLR_PARAM int sig
12
11#define ARCH_GET_SIGCONTEXT(sc, sig) \ 13#define ARCH_GET_SIGCONTEXT(sc, sig) \
12 do sc = (struct sigcontext *) (&sig + 1); while(0) 14 do sc = (struct sigcontext *) (&sig + 1); while(0)
13 15
diff --git a/arch/um/include/sysdep-i386/skas_ptrace.h b/arch/um/include/sysdep-i386/skas_ptrace.h
new file mode 100644
index 000000000000..e27b8a791773
--- /dev/null
+++ b/arch/um/include/sysdep-i386/skas_ptrace.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SYSDEP_I386_SKAS_PTRACE_H
7#define __SYSDEP_I386_SKAS_PTRACE_H
8
9struct ptrace_faultinfo {
10 int is_write;
11 unsigned long addr;
12};
13
14struct ptrace_ldt {
15 int func;
16 void *ptr;
17 unsigned long bytecount;
18};
19
20#define PTRACE_LDT 54
21
22#endif
diff --git a/arch/um/include/sysdep-ia64/skas_ptrace.h b/arch/um/include/sysdep-ia64/skas_ptrace.h
new file mode 100644
index 000000000000..25a38e715702
--- /dev/null
+++ b/arch/um/include/sysdep-ia64/skas_ptrace.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SYSDEP_IA64_SKAS_PTRACE_H
7#define __SYSDEP_IA64_SKAS_PTRACE_H
8
9struct ptrace_faultinfo {
10 int is_write;
11 unsigned long addr;
12};
13
14struct ptrace_ldt {
15 int func;
16 void *ptr;
17 unsigned long bytecount;
18};
19
20#define PTRACE_LDT 54
21
22#endif
diff --git a/arch/um/include/sysdep-ppc/skas_ptrace.h b/arch/um/include/sysdep-ppc/skas_ptrace.h
new file mode 100644
index 000000000000..d9fbbac10de0
--- /dev/null
+++ b/arch/um/include/sysdep-ppc/skas_ptrace.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SYSDEP_PPC_SKAS_PTRACE_H
7#define __SYSDEP_PPC_SKAS_PTRACE_H
8
9struct ptrace_faultinfo {
10 int is_write;
11 unsigned long addr;
12};
13
14struct ptrace_ldt {
15 int func;
16 void *ptr;
17 unsigned long bytecount;
18};
19
20#define PTRACE_LDT 54
21
22#endif
diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h
index 572c6c19be33..ea97005af694 100644
--- a/arch/um/include/sysdep-x86_64/checksum.h
+++ b/arch/um/include/sysdep-x86_64/checksum.h
@@ -9,8 +9,6 @@
9#include "linux/in6.h" 9#include "linux/in6.h"
10#include "asm/uaccess.h" 10#include "asm/uaccess.h"
11 11
12extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len,
13 int sum, int *err_ptr);
14extern unsigned csum_partial(const unsigned char *buff, unsigned len, 12extern unsigned csum_partial(const unsigned char *buff, unsigned len,
15 unsigned sum); 13 unsigned sum);
16 14
@@ -31,10 +29,15 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
31} 29}
32 30
33static __inline__ 31static __inline__
34unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, 32unsigned int csum_partial_copy_from_user(const unsigned char *src,
35 int len, int sum, int *err_ptr) 33 unsigned char *dst, int len, int sum,
34 int *err_ptr)
36{ 35{
37 return csum_partial_copy_from(src, dst, len, sum, err_ptr); 36 if(copy_from_user(dst, src, len)){
37 *err_ptr = -EFAULT;
38 return(-1);
39 }
40 return csum_partial(dst, len, sum);
38} 41}
39 42
40/** 43/**
@@ -137,15 +140,6 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b)
137 return a; 140 return a;
138} 141}
139 142
140#endif 143extern unsigned short ip_compute_csum(unsigned char * buff, int len);
141 144
142/* 145#endif
143 * Overrides for Emacs so that we follow Linus's tabbing style.
144 * Emacs will notice this stuff at the end of the file and automatically
145 * adjust the settings for this buffer only. This must remain at the end
146 * of the file.
147 * ---------------------------------------------------------------------------
148 * Local variables:
149 * c-file-style: "linux"
150 * End:
151 */
diff --git a/arch/um/include/sysdep-x86_64/faultinfo.h b/arch/um/include/sysdep-x86_64/faultinfo.h
new file mode 100644
index 000000000000..cb917b0d5660
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/faultinfo.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
3 * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
4 * Licensed under the GPL
5 */
6
7#ifndef __FAULTINFO_X86_64_H
8#define __FAULTINFO_X86_64_H
9
10/* this structure contains the full arch-specific faultinfo
11 * from the traps.
12 * On i386, ptrace_faultinfo unfortunately doesn't provide
13 * all the info, since trap_no is missing.
14 * All common elements are defined at the same position in
15 * both structures, thus making it easy to copy the
16 * contents without knowledge about the structure elements.
17 */
18struct faultinfo {
19 int error_code; /* in ptrace_faultinfo misleadingly called is_write */
20 unsigned long cr2; /* in ptrace_faultinfo called addr */
21 int trap_no; /* missing in ptrace_faultinfo */
22};
23
24#define FAULT_WRITE(fi) ((fi).error_code & 2)
25#define FAULT_ADDRESS(fi) ((fi).cr2)
26
27#define PTRACE_FULL_FAULTINFO 1
28
29#endif
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 915c82daffbd..be8acd5efd97 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -9,6 +9,7 @@
9 9
10#include "uml-config.h" 10#include "uml-config.h"
11#include "user_constants.h" 11#include "user_constants.h"
12#include "sysdep/faultinfo.h"
12 13
13#define MAX_REG_OFFSET (UM_FRAME_SIZE) 14#define MAX_REG_OFFSET (UM_FRAME_SIZE)
14#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long)) 15#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
@@ -83,6 +84,7 @@ union uml_pt_regs {
83 long syscall; 84 long syscall;
84 unsigned long orig_rax; 85 unsigned long orig_rax;
85 void *sc; 86 void *sc;
87 struct faultinfo faultinfo;
86 } tt; 88 } tt;
87#endif 89#endif
88#ifdef UML_CONFIG_MODE_SKAS 90#ifdef UML_CONFIG_MODE_SKAS
@@ -90,9 +92,7 @@ union uml_pt_regs {
90 /* XXX */ 92 /* XXX */
91 unsigned long regs[27]; 93 unsigned long regs[27];
92 unsigned long fp[65]; 94 unsigned long fp[65];
93 unsigned long fault_addr; 95 struct faultinfo faultinfo;
94 unsigned long fault_type;
95 unsigned long trap_type;
96 long syscall; 96 long syscall;
97 int is_user; 97 int is_user;
98 } skas; 98 } skas;
@@ -135,6 +135,7 @@ extern int mode_tt;
135 __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) 135 __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
136#define UPT_SC(r) ((r)->tt.sc) 136#define UPT_SC(r) ((r)->tt.sc)
137#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) 137#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
138#define UPT_SYSCALL_RET(r) UPT_RAX(r)
138 139
139extern int user_context(unsigned long sp); 140extern int user_context(unsigned long sp);
140 141
@@ -196,32 +197,32 @@ struct syscall_args {
196 197
197 198
198#define UPT_SET(regs, reg, val) \ 199#define UPT_SET(regs, reg, val) \
199 ({ unsigned long val; \ 200 ({ unsigned long __upt_val = val; \
200 switch(reg){ \ 201 switch(reg){ \
201 case R8: UPT_R8(regs) = val; break; \ 202 case R8: UPT_R8(regs) = __upt_val; break; \
202 case R9: UPT_R9(regs) = val; break; \ 203 case R9: UPT_R9(regs) = __upt_val; break; \
203 case R10: UPT_R10(regs) = val; break; \ 204 case R10: UPT_R10(regs) = __upt_val; break; \
204 case R11: UPT_R11(regs) = val; break; \ 205 case R11: UPT_R11(regs) = __upt_val; break; \
205 case R12: UPT_R12(regs) = val; break; \ 206 case R12: UPT_R12(regs) = __upt_val; break; \
206 case R13: UPT_R13(regs) = val; break; \ 207 case R13: UPT_R13(regs) = __upt_val; break; \
207 case R14: UPT_R14(regs) = val; break; \ 208 case R14: UPT_R14(regs) = __upt_val; break; \
208 case R15: UPT_R15(regs) = val; break; \ 209 case R15: UPT_R15(regs) = __upt_val; break; \
209 case RIP: UPT_IP(regs) = val; break; \ 210 case RIP: UPT_IP(regs) = __upt_val; break; \
210 case RSP: UPT_SP(regs) = val; break; \ 211 case RSP: UPT_SP(regs) = __upt_val; break; \
211 case RAX: UPT_RAX(regs) = val; break; \ 212 case RAX: UPT_RAX(regs) = __upt_val; break; \
212 case RBX: UPT_RBX(regs) = val; break; \ 213 case RBX: UPT_RBX(regs) = __upt_val; break; \
213 case RCX: UPT_RCX(regs) = val; break; \ 214 case RCX: UPT_RCX(regs) = __upt_val; break; \
214 case RDX: UPT_RDX(regs) = val; break; \ 215 case RDX: UPT_RDX(regs) = __upt_val; break; \
215 case RSI: UPT_RSI(regs) = val; break; \ 216 case RSI: UPT_RSI(regs) = __upt_val; break; \
216 case RDI: UPT_RDI(regs) = val; break; \ 217 case RDI: UPT_RDI(regs) = __upt_val; break; \
217 case RBP: UPT_RBP(regs) = val; break; \ 218 case RBP: UPT_RBP(regs) = __upt_val; break; \
218 case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \ 219 case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
219 case CS: UPT_CS(regs) = val; break; \ 220 case CS: UPT_CS(regs) = __upt_val; break; \
220 case DS: UPT_DS(regs) = val; break; \ 221 case DS: UPT_DS(regs) = __upt_val; break; \
221 case ES: UPT_ES(regs) = val; break; \ 222 case ES: UPT_ES(regs) = __upt_val; break; \
222 case FS: UPT_FS(regs) = val; break; \ 223 case FS: UPT_FS(regs) = __upt_val; break; \
223 case GS: UPT_GS(regs) = val; break; \ 224 case GS: UPT_GS(regs) = __upt_val; break; \
224 case EFLAGS: UPT_EFLAGS(regs) = val; break; \ 225 case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
225 default : \ 226 default : \
226 panic("Bad register in UPT_SET : %d\n", reg); \ 227 panic("Bad register in UPT_SET : %d\n", reg); \
227 break; \ 228 break; \
@@ -241,24 +242,7 @@ struct syscall_args {
241 CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ 242 CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
242 REGS_SEGV_IS_FIXABLE(&r->skas)) 243 REGS_SEGV_IS_FIXABLE(&r->skas))
243 244
244#define UPT_FAULT_ADDR(r) \ 245#define UPT_FAULTINFO(r) \
245 __CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas)) 246 CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
246
247#define UPT_FAULT_WRITE(r) \
248 CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
249
250#define UPT_TRAP(r) __CHOOSE_MODE(SC_TRAP_TYPE(UPT_SC(r)), REGS_TRAP(&r->skas))
251#define UPT_ERR(r) __CHOOSE_MODE(SC_FAULT_TYPE(UPT_SC(r)), REGS_ERR(&r->skas))
252 247
253#endif 248#endif
254
255/*
256 * Overrides for Emacs so that we follow Linus's tabbing style.
257 * Emacs will notice this stuff at the end of the file and automatically
258 * adjust the settings for this buffer only. This must remain at the end
259 * of the file.
260 * ---------------------------------------------------------------------------
261 * Local variables:
262 * c-file-style: "linux"
263 * End:
264 */
diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h
index 1e38a54ff4cf..2a78260d15a0 100644
--- a/arch/um/include/sysdep-x86_64/sigcontext.h
+++ b/arch/um/include/sysdep-x86_64/sigcontext.h
@@ -17,11 +17,12 @@
17#define SC_FAULT_ADDR(sc) SC_CR2(sc) 17#define SC_FAULT_ADDR(sc) SC_CR2(sc)
18#define SC_FAULT_TYPE(sc) SC_ERR(sc) 18#define SC_FAULT_TYPE(sc) SC_ERR(sc)
19 19
20#define FAULT_WRITE(err) ((err) & 2) 20#define GET_FAULTINFO_FROM_SC(fi,sc) \
21 21 { \
22#define SC_FAULT_WRITE(sc) FAULT_WRITE(SC_FAULT_TYPE(sc)) 22 (fi).cr2 = SC_CR2(sc); \
23 23 (fi).error_code = SC_ERR(sc); \
24#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc) 24 (fi).trap_no = SC_TRAPNO(sc); \
25 }
25 26
26/* ptrace expects that, at the start of a system call, %eax contains 27/* ptrace expects that, at the start of a system call, %eax contains
27 * -ENOSYS, so this makes it so. 28 * -ENOSYS, so this makes it so.
@@ -29,8 +30,8 @@
29 30
30#define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0) 31#define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0)
31 32
32#define SEGV_IS_FIXABLE(trap) ((trap) == 14) 33/* This is Page Fault */
33#define SC_SEGV_IS_FIXABLE(sc) SEGV_IS_FIXABLE(SC_TRAP_TYPE(sc)) 34#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
34 35
35extern unsigned long *sc_sigmask(void *sc_ptr); 36extern unsigned long *sc_sigmask(void *sc_ptr);
36 37
diff --git a/arch/um/include/sysdep-x86_64/signal.h b/arch/um/include/sysdep-x86_64/signal.h
index e5e52756fab4..6142897af3d1 100644
--- a/arch/um/include/sysdep-x86_64/signal.h
+++ b/arch/um/include/sysdep-x86_64/signal.h
@@ -6,6 +6,8 @@
6#ifndef __X86_64_SIGNAL_H_ 6#ifndef __X86_64_SIGNAL_H_
7#define __X86_64_SIGNAL_H_ 7#define __X86_64_SIGNAL_H_
8 8
9#define ARCH_SIGHDLR_PARAM int sig
10
9#define ARCH_GET_SIGCONTEXT(sc, sig_addr) \ 11#define ARCH_GET_SIGCONTEXT(sc, sig_addr) \
10 do { \ 12 do { \
11 struct ucontext *__uc; \ 13 struct ucontext *__uc; \
diff --git a/arch/um/include/sysdep-x86_64/skas_ptrace.h b/arch/um/include/sysdep-x86_64/skas_ptrace.h
new file mode 100644
index 000000000000..95db4be786e4
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/skas_ptrace.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H
7#define __SYSDEP_X86_64_SKAS_PTRACE_H
8
9struct ptrace_faultinfo {
10 int is_write;
11 unsigned long addr;
12};
13
14struct ptrace_ldt {
15 int func;
16 void *ptr;
17 unsigned long bytecount;
18};
19
20#define PTRACE_LDT 54
21
22#endif
diff --git a/arch/um/include/sysrq.h b/arch/um/include/sysrq.h
index 2ce9423460b3..c8d332b56b98 100644
--- a/arch/um/include/sysrq.h
+++ b/arch/um/include/sysrq.h
@@ -1,6 +1,7 @@
1#ifndef __UM_SYSRQ_H 1#ifndef __UM_SYSRQ_H
2#define __UM_SYSRQ_H 2#define __UM_SYSRQ_H
3 3
4extern void show_trace(unsigned long *stack); 4struct task_struct;
5extern void show_trace(struct task_struct* task, unsigned long *stack);
5 6
6#endif 7#endif
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 103cd320386c..b8c5b8a95250 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -67,7 +67,6 @@ extern void *um_kmalloc(int size);
67extern int switcheroo(int fd, int prot, void *from, void *to, int size); 67extern int switcheroo(int fd, int prot, void *from, void *to, int size);
68extern void setup_machinename(char *machine_out); 68extern void setup_machinename(char *machine_out);
69extern void setup_hostinfo(void); 69extern void setup_hostinfo(void);
70extern void add_arg(char *arg);
71extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); 70extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
72extern void init_new_thread_signals(int altstack); 71extern void init_new_thread_signals(int altstack);
73extern void do_exec(int old_pid, int new_pid); 72extern void do_exec(int old_pid, int new_pid);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 246f0e7fb4cc..a8918e80df96 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -4,9 +4,9 @@
4# 4#
5 5
6extra-y := vmlinux.lds 6extra-y := vmlinux.lds
7clean-files := vmlinux.lds.S config.tmp 7clean-files :=
8 8
9obj-y = checksum.o config.o exec_kern.o exitcode.o \ 9obj-y = config.o exec_kern.o exitcode.o \
10 helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \ 10 helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
11 physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \ 11 physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
12 sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \ 12 sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
@@ -14,7 +14,7 @@ obj-y = checksum.o config.o exec_kern.o exitcode.o \
14 tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \ 14 tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
15 user_util.o 15 user_util.o
16 16
17obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o 17obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
18obj-$(CONFIG_GPROF) += gprof_syms.o 18obj-$(CONFIG_GPROF) += gprof_syms.o
19obj-$(CONFIG_GCOV) += gmon_syms.o 19obj-$(CONFIG_GCOV) += gmon_syms.o
20obj-$(CONFIG_TTY_LOG) += tty_log.o 20obj-$(CONFIG_TTY_LOG) += tty_log.o
@@ -23,18 +23,14 @@ obj-$(CONFIG_SYSCALL_DEBUG) += syscall_user.o
23obj-$(CONFIG_MODE_TT) += tt/ 23obj-$(CONFIG_MODE_TT) += tt/
24obj-$(CONFIG_MODE_SKAS) += skas/ 24obj-$(CONFIG_MODE_SKAS) += skas/
25 25
26# This needs be compiled with frame pointers regardless of how the rest of the
27# kernel is built.
28CFLAGS_frame.o := -fno-omit-frame-pointer
29
30user-objs-$(CONFIG_TTY_LOG) += tty_log.o 26user-objs-$(CONFIG_TTY_LOG) += tty_log.o
31 27
32USER_OBJS := $(user-objs-y) config.o helper.o main.o process.o tempfile.o \ 28USER_OBJS := $(user-objs-y) config.o helper.o main.o process.o tempfile.o \
33 time.o tty_log.o umid.o user_util.o frame.o 29 time.o tty_log.o umid.o user_util.o
34 30
35include arch/um/scripts/Makefile.rules 31include arch/um/scripts/Makefile.rules
36 32
37targets += config.c 33targets := config.c config.tmp
38 34
39# Be careful with the below Sed code - sed is pitfall-rich! 35# Be careful with the below Sed code - sed is pitfall-rich!
40# We use sed to lower build requirements, for "embedded" builders for instance. 36# We use sed to lower build requirements, for "embedded" builders for instance.
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
deleted file mode 100644
index e69b2be951d1..000000000000
--- a/arch/um/kernel/checksum.c
+++ /dev/null
@@ -1,36 +0,0 @@
1#include "asm/uaccess.h"
2#include "linux/errno.h"
3#include "linux/module.h"
4
5unsigned int arch_csum_partial(const unsigned char *buff, int len, int sum);
6
7unsigned int csum_partial(unsigned char *buff, int len, int sum)
8{
9 return arch_csum_partial(buff, len, sum);
10}
11
12EXPORT_SYMBOL(csum_partial);
13
14unsigned int csum_partial_copy_to(const unsigned char *src,
15 unsigned char __user *dst, int len, int sum,
16 int *err_ptr)
17{
18 if(copy_to_user(dst, src, len)){
19 *err_ptr = -EFAULT;
20 return(-1);
21 }
22
23 return(arch_csum_partial(src, len, sum));
24}
25
26unsigned int csum_partial_copy_from(const unsigned char __user *src,
27 unsigned char *dst, int len, int sum,
28 int *err_ptr)
29{
30 if(copy_from_user(dst, src, len)){
31 *err_ptr = -EFAULT;
32 return(-1);
33 }
34
35 return arch_csum_partial(dst, len, sum);
36}
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index 49ddabe69be7..efd222ffe20e 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -16,7 +16,6 @@
16#include "kern.h" 16#include "kern.h"
17#include "irq_user.h" 17#include "irq_user.h"
18#include "tlb.h" 18#include "tlb.h"
19#include "2_5compat.h"
20#include "os.h" 19#include "os.h"
21#include "time_user.h" 20#include "time_user.h"
22#include "choose-mode.h" 21#include "choose-mode.h"
diff --git a/arch/um/kernel/initrd_kern.c b/arch/um/kernel/initrd.c
index fc568af468b9..82ecf904b09c 100644
--- a/arch/um/kernel/initrd_kern.c
+++ b/arch/um/kernel/initrd.c
@@ -41,12 +41,31 @@ static int __init uml_initrd_setup(char *line, int *add)
41 return 0; 41 return 0;
42} 42}
43 43
44__uml_setup("initrd=", uml_initrd_setup, 44__uml_setup("initrd=", uml_initrd_setup,
45"initrd=<initrd image>\n" 45"initrd=<initrd image>\n"
46" This is used to boot UML from an initrd image. The argument is the\n" 46" This is used to boot UML from an initrd image. The argument is the\n"
47" name of the file containing the image.\n\n" 47" name of the file containing the image.\n\n"
48); 48);
49 49
50int load_initrd(char *filename, void *buf, int size)
51{
52 int fd, n;
53
54 fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
55 if(fd < 0){
56 printk("Opening '%s' failed - err = %d\n", filename, -fd);
57 return(-1);
58 }
59 n = os_read_file(fd, buf, size);
60 if(n != size){
61 printk("Read of %d bytes from '%s' failed, err = %d\n", size,
62 filename, -n);
63 return(-1);
64 }
65
66 os_close_file(fd);
67 return(0);
68}
50/* 69/*
51 * Overrides for Emacs so that we follow Linus's tabbing style. 70 * Overrides for Emacs so that we follow Linus's tabbing style.
52 * Emacs will notice this stuff at the end of the file and automatically 71 * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c
deleted file mode 100644
index cb90681e151c..000000000000
--- a/arch/um/kernel/initrd_user.c
+++ /dev/null
@@ -1,46 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <unistd.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <errno.h>
10
11#include "user_util.h"
12#include "kern_util.h"
13#include "user.h"
14#include "initrd.h"
15#include "os.h"
16
17int load_initrd(char *filename, void *buf, int size)
18{
19 int fd, n;
20
21 fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
22 if(fd < 0){
23 printk("Opening '%s' failed - err = %d\n", filename, -fd);
24 return(-1);
25 }
26 n = os_read_file(fd, buf, size);
27 if(n != size){
28 printk("Read of %d bytes from '%s' failed, err = %d\n", size,
29 filename, -n);
30 return(-1);
31 }
32
33 os_close_file(fd);
34 return(0);
35}
36
37/*
38 * Overrides for Emacs so that we follow Linus's tabbing style.
39 * Emacs will notice this stuff at the end of the file and automatically
40 * adjust the settings for this buffer only. This must remain at the end
41 * of the file.
42 * ---------------------------------------------------------------------------
43 * Local variables:
44 * c-file-style: "linux"
45 * End:
46 */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index d71e8f00810f..d44fb5282547 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -163,7 +163,6 @@ void __init init_IRQ(void)
163 irq_desc[i].handler = &SIGIO_irq_type; 163 irq_desc[i].handler = &SIGIO_irq_type;
164 enable_irq(i); 164 enable_irq(i);
165 } 165 }
166 init_irq_signals(0);
167} 166}
168 167
169/* 168/*
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index 6d6f9484b884..b3074cbaa479 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -236,9 +236,15 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
236 (*prev)->fd, pollfds[i].fd); 236 (*prev)->fd, pollfds[i].fd);
237 goto out; 237 goto out;
238 } 238 }
239 memcpy(&pollfds[i], &pollfds[i + 1], 239
240 (pollfds_num - i - 1) * sizeof(pollfds[0]));
241 pollfds_num--; 240 pollfds_num--;
241
242 /* This moves the *whole* array after pollfds[i] (though
243 * it doesn't spot as such)! */
244
245 memmove(&pollfds[i], &pollfds[i + 1],
246 (pollfds_num - i) * sizeof(pollfds[0]));
247
242 if(last_irq_ptr == &old_fd->next) 248 if(last_irq_ptr == &old_fd->next)
243 last_irq_ptr = prev; 249 last_irq_ptr = prev;
244 *prev = (*prev)->next; 250 *prev = (*prev)->next;
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index b41d3397d07b..99439fa15ef4 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -10,7 +10,6 @@
10#include "linux/spinlock.h" 10#include "linux/spinlock.h"
11#include "linux/highmem.h" 11#include "linux/highmem.h"
12#include "asm/current.h" 12#include "asm/current.h"
13#include "asm/delay.h"
14#include "asm/processor.h" 13#include "asm/processor.h"
15#include "asm/unistd.h" 14#include "asm/unistd.h"
16#include "asm/pgalloc.h" 15#include "asm/pgalloc.h"
@@ -28,8 +27,6 @@ EXPORT_SYMBOL(uml_physmem);
28EXPORT_SYMBOL(set_signals); 27EXPORT_SYMBOL(set_signals);
29EXPORT_SYMBOL(get_signals); 28EXPORT_SYMBOL(get_signals);
30EXPORT_SYMBOL(kernel_thread); 29EXPORT_SYMBOL(kernel_thread);
31EXPORT_SYMBOL(__const_udelay);
32EXPORT_SYMBOL(__udelay);
33EXPORT_SYMBOL(sys_waitpid); 30EXPORT_SYMBOL(sys_waitpid);
34EXPORT_SYMBOL(task_size); 31EXPORT_SYMBOL(task_size);
35EXPORT_SYMBOL(flush_tlb_range); 32EXPORT_SYMBOL(flush_tlb_range);
@@ -60,6 +57,7 @@ EXPORT_SYMBOL(copy_to_user_tt);
60EXPORT_SYMBOL(strncpy_from_user_skas); 57EXPORT_SYMBOL(strncpy_from_user_skas);
61EXPORT_SYMBOL(copy_to_user_skas); 58EXPORT_SYMBOL(copy_to_user_skas);
62EXPORT_SYMBOL(copy_from_user_skas); 59EXPORT_SYMBOL(copy_from_user_skas);
60EXPORT_SYMBOL(clear_user_skas);
63#endif 61#endif
64EXPORT_SYMBOL(uml_strdup); 62EXPORT_SYMBOL(uml_strdup);
65 63
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
index a17c49703f9b..e42e6364ca13 100644
--- a/arch/um/kernel/main.c
+++ b/arch/um/kernel/main.c
@@ -71,7 +71,7 @@ static __init void do_uml_initcalls(void)
71 71
72static void last_ditch_exit(int sig) 72static void last_ditch_exit(int sig)
73{ 73{
74 CHOOSE_MODE(kmalloc_ok = 0, (void) 0); 74 kmalloc_ok = 0;
75 signal(SIGINT, SIG_DFL); 75 signal(SIGINT, SIG_DFL);
76 signal(SIGTERM, SIG_DFL); 76 signal(SIGTERM, SIG_DFL);
77 signal(SIGHUP, SIG_DFL); 77 signal(SIGHUP, SIG_DFL);
@@ -87,7 +87,7 @@ int main(int argc, char **argv, char **envp)
87{ 87{
88 char **new_argv; 88 char **new_argv;
89 sigset_t mask; 89 sigset_t mask;
90 int ret, i; 90 int ret, i, err;
91 91
92 /* Enable all signals except SIGIO - in some environments, we can 92 /* Enable all signals except SIGIO - in some environments, we can
93 * enter with some signals blocked 93 * enter with some signals blocked
@@ -160,27 +160,29 @@ int main(int argc, char **argv, char **envp)
160 */ 160 */
161 change_sig(SIGPROF, 0); 161 change_sig(SIGPROF, 0);
162 162
163 /* Reboot */ 163 /* This signal stuff used to be in the reboot case. However,
164 if(ret){ 164 * sometimes a SIGVTALRM can come in when we're halting (reproducably
165 int err; 165 * when writing out gcov information, presumably because that takes
166 166 * some time) and cause a segfault.
167 printf("\n"); 167 */
168 168
169 /* stop timers and set SIG*ALRM to be ignored */ 169 /* stop timers and set SIG*ALRM to be ignored */
170 disable_timer(); 170 disable_timer();
171 171
172 /* disable SIGIO for the fds and set SIGIO to be ignored */ 172 /* disable SIGIO for the fds and set SIGIO to be ignored */
173 err = deactivate_all_fds(); 173 err = deactivate_all_fds();
174 if(err) 174 if(err)
175 printf("deactivate_all_fds failed, errno = %d\n", 175 printf("deactivate_all_fds failed, errno = %d\n", -err);
176 -err);
177 176
178 /* Let any pending signals fire now. This ensures 177 /* Let any pending signals fire now. This ensures
179 * that they won't be delivered after the exec, when 178 * that they won't be delivered after the exec, when
180 * they are definitely not expected. 179 * they are definitely not expected.
181 */ 180 */
182 unblock_signals(); 181 unblock_signals();
183 182
183 /* Reboot */
184 if(ret){
185 printf("\n");
184 execvp(new_argv[0], new_argv); 186 execvp(new_argv[0], new_argv);
185 perror("Failed to exec kernel"); 187 perror("Failed to exec kernel");
186 ret = 1; 188 ret = 1;
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index f156661781cb..c22825f13e40 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -100,12 +100,37 @@ void mem_init(void)
100#endif 100#endif
101} 101}
102 102
103/*
104 * Create a page table and place a pointer to it in a middle page
105 * directory entry.
106 */
107static void __init one_page_table_init(pmd_t *pmd)
108{
109 if (pmd_none(*pmd)) {
110 pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
111 set_pmd(pmd, __pmd(_KERNPG_TABLE +
112 (unsigned long) __pa(pte)));
113 if (pte != pte_offset_kernel(pmd, 0))
114 BUG();
115 }
116}
117
118static void __init one_md_table_init(pud_t *pud)
119{
120#ifdef CONFIG_3_LEVEL_PGTABLES
121 pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
122 set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
123 if (pmd_table != pmd_offset(pud, 0))
124 BUG();
125#endif
126}
127
103static void __init fixrange_init(unsigned long start, unsigned long end, 128static void __init fixrange_init(unsigned long start, unsigned long end,
104 pgd_t *pgd_base) 129 pgd_t *pgd_base)
105{ 130{
106 pgd_t *pgd; 131 pgd_t *pgd;
132 pud_t *pud;
107 pmd_t *pmd; 133 pmd_t *pmd;
108 pte_t *pte;
109 int i, j; 134 int i, j;
110 unsigned long vaddr; 135 unsigned long vaddr;
111 136
@@ -115,15 +140,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
115 pgd = pgd_base + i; 140 pgd = pgd_base + i;
116 141
117 for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { 142 for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
118 pmd = (pmd_t *)pgd; 143 pud = pud_offset(pgd, vaddr);
144 if (pud_none(*pud))
145 one_md_table_init(pud);
146 pmd = pmd_offset(pud, vaddr);
119 for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { 147 for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
120 if (pmd_none(*pmd)) { 148 one_page_table_init(pmd);
121 pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
122 set_pmd(pmd, __pmd(_KERNPG_TABLE +
123 (unsigned long) __pa(pte)));
124 if (pte != pte_offset_kernel(pmd, 0))
125 BUG();
126 }
127 vaddr += PMD_SIZE; 149 vaddr += PMD_SIZE;
128 } 150 }
129 j = 0; 151 j = 0;
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index f76a2692adca..51f8e5a8ac6a 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -65,8 +65,6 @@ void init_new_thread_signals(int altstack)
65 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); 65 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
66 set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, 66 set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
67 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); 67 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
68 set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags,
69 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
70 set_handler(SIGUSR2, (__sighandler_t) sig_handler, 68 set_handler(SIGUSR2, (__sighandler_t) sig_handler,
71 flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); 69 flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
72 signal(SIGHUP, SIG_IGN); 70 signal(SIGHUP, SIG_IGN);
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 7a943696f950..804c6bbdf67c 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -43,7 +43,6 @@
43#include "tlb.h" 43#include "tlb.h"
44#include "frame_kern.h" 44#include "frame_kern.h"
45#include "sigcontext.h" 45#include "sigcontext.h"
46#include "2_5compat.h"
47#include "os.h" 46#include "os.h"
48#include "mode.h" 47#include "mode.h"
49#include "mode_kern.h" 48#include "mode_kern.h"
@@ -55,18 +54,6 @@
55 */ 54 */
56struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; 55struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
57 56
58struct task_struct *get_task(int pid, int require)
59{
60 struct task_struct *ret;
61
62 read_lock(&tasklist_lock);
63 ret = find_task_by_pid(pid);
64 read_unlock(&tasklist_lock);
65
66 if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
67 return(ret);
68}
69
70int external_pid(void *t) 57int external_pid(void *t)
71{ 58{
72 struct task_struct *task = t ? t : current; 59 struct task_struct *task = t ? t : current;
@@ -115,16 +102,6 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
115 return(pid); 102 return(pid);
116} 103}
117 104
118void switch_mm(struct mm_struct *prev, struct mm_struct *next,
119 struct task_struct *tsk)
120{
121 int cpu = smp_processor_id();
122
123 if (prev != next)
124 cpu_clear(cpu, prev->cpu_vm_mask);
125 cpu_set(cpu, next->cpu_vm_mask);
126}
127
128void set_current(void *t) 105void set_current(void *t)
129{ 106{
130 struct task_struct *task = t; 107 struct task_struct *task = t;
@@ -152,7 +129,6 @@ void release_thread(struct task_struct *task)
152 129
153void exit_thread(void) 130void exit_thread(void)
154{ 131{
155 CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
156 unprotect_stack((unsigned long) current_thread); 132 unprotect_stack((unsigned long) current_thread);
157} 133}
158 134
@@ -200,7 +176,6 @@ void default_idle(void)
200 176
201 while(1){ 177 while(1){
202 /* endless idle loop with no priority at all */ 178 /* endless idle loop with no priority at all */
203 SET_PRI(current);
204 179
205 /* 180 /*
206 * although we are an idle CPU, we do not want to 181 * although we are an idle CPU, we do not want to
@@ -223,11 +198,6 @@ int page_size(void)
223 return(PAGE_SIZE); 198 return(PAGE_SIZE);
224} 199}
225 200
226unsigned long page_mask(void)
227{
228 return(PAGE_MASK);
229}
230
231void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 201void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
232 pte_t *pte_out) 202 pte_t *pte_out)
233{ 203{
@@ -360,11 +330,6 @@ char *uml_strdup(char *string)
360 return(new); 330 return(new);
361} 331}
362 332
363void *get_init_task(void)
364{
365 return(&init_thread_union.thread_info.task);
366}
367
368int copy_to_user_proc(void __user *to, void *from, int size) 333int copy_to_user_proc(void __user *to, void *from, int size)
369{ 334{
370 return(copy_to_user(to, from, size)); 335 return(copy_to_user(to, from, size));
@@ -476,21 +441,18 @@ int singlestepping(void * t)
476 return 2; 441 return 2;
477} 442}
478 443
444/*
445 * Only x86 and x86_64 have an arch_align_stack().
446 * All other arches have "#define arch_align_stack(x) (x)"
447 * in their asm/system.h
448 * As this is included in UML from asm-um/system-generic.h,
449 * we can use it to behave as the subarch does.
450 */
451#ifndef arch_align_stack
479unsigned long arch_align_stack(unsigned long sp) 452unsigned long arch_align_stack(unsigned long sp)
480{ 453{
481 if (randomize_va_space) 454 if (randomize_va_space)
482 sp -= get_random_int() % 8192; 455 sp -= get_random_int() % 8192;
483 return sp & ~0xf; 456 return sp & ~0xf;
484} 457}
485 458#endif
486
487/*
488 * Overrides for Emacs so that we follow Linus's tabbing style.
489 * Emacs will notice this stuff at the end of the file and automatically
490 * adjust the settings for this buffer only. This must remain at the end
491 * of the file.
492 * ---------------------------------------------------------------------------
493 * Local variables:
494 * c-file-style: "linux"
495 * End:
496 */
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 959b2d2490df..71af4d503899 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -19,15 +19,30 @@
19#include "skas_ptrace.h" 19#include "skas_ptrace.h"
20#include "sysdep/ptrace.h" 20#include "sysdep/ptrace.h"
21 21
22static inline void set_singlestepping(struct task_struct *child, int on)
23{
24 if (on)
25 child->ptrace |= PT_DTRACE;
26 else
27 child->ptrace &= ~PT_DTRACE;
28 child->thread.singlestep_syscall = 0;
29
30#ifdef SUBARCH_SET_SINGLESTEPPING
31 SUBARCH_SET_SINGLESTEPPING(child, on);
32#endif
33}
34
22/* 35/*
23 * Called by kernel/ptrace.c when detaching.. 36 * Called by kernel/ptrace.c when detaching..
24 */ 37 */
25void ptrace_disable(struct task_struct *child) 38void ptrace_disable(struct task_struct *child)
26{ 39{
27 child->ptrace &= ~PT_DTRACE; 40 set_singlestepping(child,0);
28 child->thread.singlestep_syscall = 0;
29} 41}
30 42
43extern int peek_user(struct task_struct * child, long addr, long data);
44extern int poke_user(struct task_struct * child, long addr, long data);
45
31long sys_ptrace(long request, long pid, long addr, long data) 46long sys_ptrace(long request, long pid, long addr, long data)
32{ 47{
33 struct task_struct *child; 48 struct task_struct *child;
@@ -67,6 +82,10 @@ long sys_ptrace(long request, long pid, long addr, long data)
67 goto out_tsk; 82 goto out_tsk;
68 } 83 }
69 84
85#ifdef SUBACH_PTRACE_SPECIAL
86 SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
87#endif
88
70 ret = ptrace_check_attach(child, request == PTRACE_KILL); 89 ret = ptrace_check_attach(child, request == PTRACE_KILL);
71 if (ret < 0) 90 if (ret < 0)
72 goto out_tsk; 91 goto out_tsk;
@@ -87,26 +106,9 @@ long sys_ptrace(long request, long pid, long addr, long data)
87 } 106 }
88 107
89 /* read the word at location addr in the USER area. */ 108 /* read the word at location addr in the USER area. */
90 case PTRACE_PEEKUSR: { 109 case PTRACE_PEEKUSR:
91 unsigned long tmp; 110 ret = peek_user(child, addr, data);
92 111 break;
93 ret = -EIO;
94 if ((addr & 3) || addr < 0)
95 break;
96
97 tmp = 0; /* Default return condition */
98 if(addr < MAX_REG_OFFSET){
99 tmp = getreg(child, addr);
100 }
101 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
102 (addr <= offsetof(struct user, u_debugreg[7]))){
103 addr -= offsetof(struct user, u_debugreg[0]);
104 addr = addr >> 2;
105 tmp = child->thread.arch.debugregs[addr];
106 }
107 ret = put_user(tmp, (unsigned long __user *) data);
108 break;
109 }
110 112
111 /* when I and D space are separate, this will have to be fixed. */ 113 /* when I and D space are separate, this will have to be fixed. */
112 case PTRACE_POKETEXT: /* write the word at location addr. */ 114 case PTRACE_POKETEXT: /* write the word at location addr. */
@@ -119,26 +121,8 @@ long sys_ptrace(long request, long pid, long addr, long data)
119 break; 121 break;
120 122
121 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ 123 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
122 ret = -EIO; 124 ret = poke_user(child, addr, data);
123 if ((addr & 3) || addr < 0) 125 break;
124 break;
125
126 if (addr < MAX_REG_OFFSET) {
127 ret = putreg(child, addr, data);
128 break;
129 }
130#if 0 /* XXX x86_64 */
131 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
132 (addr <= offsetof(struct user, u_debugreg[7]))){
133 addr -= offsetof(struct user, u_debugreg[0]);
134 addr = addr >> 2;
135 if((addr == 4) || (addr == 5)) break;
136 child->thread.arch.debugregs[addr] = data;
137 ret = 0;
138 }
139#endif
140
141 break;
142 126
143 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ 127 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
144 case PTRACE_CONT: { /* restart after signal. */ 128 case PTRACE_CONT: { /* restart after signal. */
@@ -146,8 +130,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
146 if (!valid_signal(data)) 130 if (!valid_signal(data))
147 break; 131 break;
148 132
149 child->ptrace &= ~PT_DTRACE; 133 set_singlestepping(child, 0);
150 child->thread.singlestep_syscall = 0;
151 if (request == PTRACE_SYSCALL) { 134 if (request == PTRACE_SYSCALL) {
152 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 135 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
153 } 136 }
@@ -170,8 +153,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
170 if (child->exit_state == EXIT_ZOMBIE) /* already dead */ 153 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
171 break; 154 break;
172 155
173 child->ptrace &= ~PT_DTRACE; 156 set_singlestepping(child, 0);
174 child->thread.singlestep_syscall = 0;
175 child->exit_code = SIGKILL; 157 child->exit_code = SIGKILL;
176 wake_up_process(child); 158 wake_up_process(child);
177 break; 159 break;
@@ -182,8 +164,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
182 if (!valid_signal(data)) 164 if (!valid_signal(data))
183 break; 165 break;
184 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 166 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
185 child->ptrace |= PT_DTRACE; 167 set_singlestepping(child, 1);
186 child->thread.singlestep_syscall = 0;
187 child->exit_code = data; 168 child->exit_code = data;
188 /* give it a chance to run. */ 169 /* give it a chance to run. */
189 wake_up_process(child); 170 wake_up_process(child);
@@ -250,23 +231,19 @@ long sys_ptrace(long request, long pid, long addr, long data)
250 break; 231 break;
251#endif 232#endif
252 case PTRACE_FAULTINFO: { 233 case PTRACE_FAULTINFO: {
253 struct ptrace_faultinfo fault; 234 /* Take the info from thread->arch->faultinfo,
254 235 * but transfer max. sizeof(struct ptrace_faultinfo).
255 fault = ((struct ptrace_faultinfo) 236 * On i386, ptrace_faultinfo is smaller!
256 { .is_write = child->thread.err, 237 */
257 .addr = child->thread.cr2 }); 238 ret = copy_to_user((unsigned long __user *) data,
258 ret = copy_to_user((unsigned long __user *) data, &fault, 239 &child->thread.arch.faultinfo,
259 sizeof(fault)); 240 sizeof(struct ptrace_faultinfo));
260 if(ret) 241 if(ret)
261 break; 242 break;
262 break; 243 break;
263 } 244 }
264 case PTRACE_SIGPENDING:
265 ret = copy_to_user((unsigned long __user *) data,
266 &child->pending.signal,
267 sizeof(child->pending.signal));
268 break;
269 245
246#ifdef PTRACE_LDT
270 case PTRACE_LDT: { 247 case PTRACE_LDT: {
271 struct ptrace_ldt ldt; 248 struct ptrace_ldt ldt;
272 249
@@ -282,6 +259,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
282 ret = -EIO; 259 ret = -EIO;
283 break; 260 break;
284 } 261 }
262#endif
285#ifdef CONFIG_PROC_MM 263#ifdef CONFIG_PROC_MM
286 case PTRACE_SWITCH_MM: { 264 case PTRACE_SWITCH_MM: {
287 struct mm_struct *old = child->mm; 265 struct mm_struct *old = child->mm;
@@ -344,11 +322,9 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
344 UPT_SYSCALL_ARG2(regs), 322 UPT_SYSCALL_ARG2(regs),
345 UPT_SYSCALL_ARG3(regs), 323 UPT_SYSCALL_ARG3(regs),
346 UPT_SYSCALL_ARG4(regs)); 324 UPT_SYSCALL_ARG4(regs));
347 else { 325 else audit_syscall_exit(current,
348 int res = UPT_SYSCALL_RET(regs); 326 AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
349 audit_syscall_exit(current, AUDITSC_RESULT(res), 327 UPT_SYSCALL_RET(regs));
350 res);
351 }
352 } 328 }
353 329
354 /* Fake a debug trap */ 330 /* Fake a debug trap */
@@ -378,14 +354,3 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
378 current->exit_code = 0; 354 current->exit_code = 0;
379 } 355 }
380} 356}
381
382/*
383 * Overrides for Emacs so that we follow Linus's tabbing style.
384 * Emacs will notice this stuff at the end of the file and automatically
385 * adjust the settings for this buffer only. This must remain at the end
386 * of the file.
387 * ---------------------------------------------------------------------------
388 * Local variables:
389 * c-file-style: "linux"
390 * End:
391 */
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 668df13d8c9d..e89218958f38 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -182,6 +182,7 @@ static int write_sigio_thread(void *unused)
182 int i, n, respond_fd; 182 int i, n, respond_fd;
183 char c; 183 char c;
184 184
185 signal(SIGWINCH, SIG_IGN);
185 fds = &current_poll; 186 fds = &current_poll;
186 while(1){ 187 while(1){
187 n = poll(fds->poll, fds->used, -1); 188 n = poll(fds->poll, fds->used, -1);
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h
index 94c564962378..e48490028111 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/kernel/skas/include/mode_kern-skas.h
@@ -18,7 +18,6 @@ extern int copy_thread_skas(int nr, unsigned long clone_flags,
18 unsigned long sp, unsigned long stack_top, 18 unsigned long sp, unsigned long stack_top,
19 struct task_struct *p, struct pt_regs *regs); 19 struct task_struct *p, struct pt_regs *regs);
20extern void release_thread_skas(struct task_struct *task); 20extern void release_thread_skas(struct task_struct *task);
21extern void exit_thread_skas(void);
22extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); 21extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
23extern void init_idle_skas(void); 22extern void init_idle_skas(void);
24extern void flush_tlb_kernel_range_skas(unsigned long start, 23extern void flush_tlb_kernel_range_skas(unsigned long start,
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index f0702c2c7204..96b51dba3471 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -27,9 +27,10 @@ extern void map(int fd, unsigned long virt, unsigned long len, int r, int w,
27extern int unmap(int fd, void *addr, unsigned long len); 27extern int unmap(int fd, void *addr, unsigned long len);
28extern int protect(int fd, unsigned long addr, unsigned long len, 28extern int protect(int fd, unsigned long addr, unsigned long len,
29 int r, int w, int x); 29 int r, int w, int x);
30extern void user_signal(int sig, union uml_pt_regs *regs); 30extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
31extern int new_mm(int from); 31extern int new_mm(int from);
32extern void start_userspace(int cpu); 32extern void start_userspace(int cpu);
33extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
33extern long execute_syscall_skas(void *r); 34extern long execute_syscall_skas(void *r);
34 35
35#endif 36#endif
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h
index c35620385da0..cd6c280482cb 100644
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ b/arch/um/kernel/skas/include/uaccess-skas.h
@@ -18,8 +18,8 @@
18 ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ 18 ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
19 ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) 19 ((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
20 20
21static inline int __deprecated verify_area_skas(int type, const void * addr, 21static inline int verify_area_skas(int type, const void * addr,
22 unsigned long size) 22 unsigned long size)
23{ 23{
24 return(access_ok_skas(type, addr, size) ? 0 : -EFAULT); 24 return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
25} 25}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index b4ffaaa81241..773cd2b525fc 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6#include <stdlib.h> 6#include <stdlib.h>
7#include <string.h>
7#include <unistd.h> 8#include <unistd.h>
8#include <errno.h> 9#include <errno.h>
9#include <signal.h> 10#include <signal.h>
@@ -27,27 +28,37 @@
27#include "chan_user.h" 28#include "chan_user.h"
28#include "signal_user.h" 29#include "signal_user.h"
29#include "registers.h" 30#include "registers.h"
31#include "process.h"
30 32
31int is_skas_winch(int pid, int fd, void *data) 33int is_skas_winch(int pid, int fd, void *data)
32{ 34{
33 if(pid != os_getpid()) 35 if(pid != os_getpgrp())
34 return(0); 36 return(0);
35 37
36 register_winch_irq(-1, fd, -1, data); 38 register_winch_irq(-1, fd, -1, data);
37 return(1); 39 return(1);
38} 40}
39 41
40static void handle_segv(int pid) 42void get_skas_faultinfo(int pid, struct faultinfo * fi)
41{ 43{
42 struct ptrace_faultinfo fault;
43 int err; 44 int err;
44 45
45 err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault); 46 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
46 if(err) 47 if(err)
47 panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n", 48 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
48 errno); 49 "errno = %d\n", errno);
50
51 /* Special handling for i386, which has different structs */
52 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
53 memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
54 sizeof(struct faultinfo) -
55 sizeof(struct ptrace_faultinfo));
56}
49 57
50 segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL); 58static void handle_segv(int pid, union uml_pt_regs * regs)
59{
60 get_skas_faultinfo(pid, &regs->skas.faultinfo);
61 segv(regs->skas.faultinfo, 0, 1, NULL);
51} 62}
52 63
53/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ 64/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
@@ -163,7 +174,7 @@ void userspace(union uml_pt_regs *regs)
163 if(WIFSTOPPED(status)){ 174 if(WIFSTOPPED(status)){
164 switch(WSTOPSIG(status)){ 175 switch(WSTOPSIG(status)){
165 case SIGSEGV: 176 case SIGSEGV:
166 handle_segv(pid); 177 handle_segv(pid, regs);
167 break; 178 break;
168 case SIGTRAP + 0x80: 179 case SIGTRAP + 0x80:
169 handle_trap(pid, regs, local_using_sysemu); 180 handle_trap(pid, regs, local_using_sysemu);
@@ -177,7 +188,7 @@ void userspace(union uml_pt_regs *regs)
177 case SIGBUS: 188 case SIGBUS:
178 case SIGFPE: 189 case SIGFPE:
179 case SIGWINCH: 190 case SIGWINCH:
180 user_signal(WSTOPSIG(status), regs); 191 user_signal(WSTOPSIG(status), regs, pid);
181 break; 192 break;
182 default: 193 default:
183 printk("userspace - child stopped with signal " 194 printk("userspace - child stopped with signal "
@@ -190,6 +201,11 @@ void userspace(union uml_pt_regs *regs)
190 } 201 }
191 } 202 }
192} 203}
204#define INIT_JMP_NEW_THREAD 0
205#define INIT_JMP_REMOVE_SIGSTACK 1
206#define INIT_JMP_CALLBACK 2
207#define INIT_JMP_HALT 3
208#define INIT_JMP_REBOOT 4
193 209
194void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, 210void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
195 void (*handler)(int)) 211 void (*handler)(int))
@@ -225,7 +241,7 @@ void thread_wait(void *sw, void *fb)
225 *switch_buf = &buf; 241 *switch_buf = &buf;
226 fork_buf = fb; 242 fork_buf = fb;
227 if(sigsetjmp(buf, 1) == 0) 243 if(sigsetjmp(buf, 1) == 0)
228 siglongjmp(*fork_buf, 1); 244 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
229} 245}
230 246
231void switch_threads(void *me, void *next) 247void switch_threads(void *me, void *next)
@@ -249,23 +265,31 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
249 sigjmp_buf **switch_buf = switch_buf_ptr; 265 sigjmp_buf **switch_buf = switch_buf_ptr;
250 int n; 266 int n;
251 267
268 set_handler(SIGWINCH, (__sighandler_t) sig_handler,
269 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
270 SIGVTALRM, -1);
271
252 *fork_buf_ptr = &initial_jmpbuf; 272 *fork_buf_ptr = &initial_jmpbuf;
253 n = sigsetjmp(initial_jmpbuf, 1); 273 n = sigsetjmp(initial_jmpbuf, 1);
254 if(n == 0) 274 switch(n){
255 new_thread_proc((void *) stack, new_thread_handler); 275 case INIT_JMP_NEW_THREAD:
256 else if(n == 1) 276 new_thread_proc((void *) stack, new_thread_handler);
257 remove_sigstack(); 277 break;
258 else if(n == 2){ 278 case INIT_JMP_REMOVE_SIGSTACK:
279 remove_sigstack();
280 break;
281 case INIT_JMP_CALLBACK:
259 (*cb_proc)(cb_arg); 282 (*cb_proc)(cb_arg);
260 siglongjmp(*cb_back, 1); 283 siglongjmp(*cb_back, 1);
261 } 284 break;
262 else if(n == 3){ 285 case INIT_JMP_HALT:
263 kmalloc_ok = 0; 286 kmalloc_ok = 0;
264 return(0); 287 return(0);
265 } 288 case INIT_JMP_REBOOT:
266 else if(n == 4){
267 kmalloc_ok = 0; 289 kmalloc_ok = 0;
268 return(1); 290 return(1);
291 default:
292 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
269 } 293 }
270 siglongjmp(**switch_buf, 1); 294 siglongjmp(**switch_buf, 1);
271} 295}
@@ -290,7 +314,7 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
290 314
291 block_signals(); 315 block_signals();
292 if(sigsetjmp(here, 1) == 0) 316 if(sigsetjmp(here, 1) == 0)
293 siglongjmp(initial_jmpbuf, 2); 317 siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK);
294 unblock_signals(); 318 unblock_signals();
295 319
296 cb_proc = NULL; 320 cb_proc = NULL;
@@ -301,13 +325,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
301void halt_skas(void) 325void halt_skas(void)
302{ 326{
303 block_signals(); 327 block_signals();
304 siglongjmp(initial_jmpbuf, 3); 328 siglongjmp(initial_jmpbuf, INIT_JMP_HALT);
305} 329}
306 330
307void reboot_skas(void) 331void reboot_skas(void)
308{ 332{
309 block_signals(); 333 block_signals();
310 siglongjmp(initial_jmpbuf, 4); 334 siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);
311} 335}
312 336
313void switch_mm_skas(int mm_fd) 337void switch_mm_skas(int mm_fd)
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 5d096ea63b97..ab5d3271da0b 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -83,10 +83,6 @@ void release_thread_skas(struct task_struct *task)
83{ 83{
84} 84}
85 85
86void exit_thread_skas(void)
87{
88}
89
90void fork_handler(int sig) 86void fork_handler(int sig)
91{ 87{
92 change_sig(SIGUSR1, 1); 88 change_sig(SIGUSR1, 1);
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c
index 8e9b46d4702e..0dee1d95c806 100644
--- a/arch/um/kernel/skas/trap_user.c
+++ b/arch/um/kernel/skas/trap_user.c
@@ -5,12 +5,15 @@
5 5
6#include <signal.h> 6#include <signal.h>
7#include <errno.h> 7#include <errno.h>
8#include "sysdep/ptrace.h"
9#include "signal_user.h" 8#include "signal_user.h"
10#include "user_util.h" 9#include "user_util.h"
11#include "kern_util.h" 10#include "kern_util.h"
12#include "task.h" 11#include "task.h"
13#include "sigcontext.h" 12#include "sigcontext.h"
13#include "skas.h"
14#include "ptrace_user.h"
15#include "sysdep/ptrace.h"
16#include "sysdep/ptrace_user.h"
14 17
15void sig_handler_common_skas(int sig, void *sc_ptr) 18void sig_handler_common_skas(int sig, void *sc_ptr)
16{ 19{
@@ -31,9 +34,11 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
31 r = &TASK_REGS(get_current())->skas; 34 r = &TASK_REGS(get_current())->skas;
32 save_user = r->is_user; 35 save_user = r->is_user;
33 r->is_user = 0; 36 r->is_user = 0;
34 r->fault_addr = SC_FAULT_ADDR(sc); 37 if ( sig == SIGFPE || sig == SIGSEGV ||
35 r->fault_type = SC_FAULT_TYPE(sc); 38 sig == SIGBUS || sig == SIGILL ||
36 r->trap_type = SC_TRAP_TYPE(sc); 39 sig == SIGTRAP ) {
40 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
41 }
37 42
38 change_sig(SIGUSR1, 1); 43 change_sig(SIGUSR1, 1);
39 info = &sig_info[sig]; 44 info = &sig_info[sig];
@@ -45,14 +50,17 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
45 r->is_user = save_user; 50 r->is_user = save_user;
46} 51}
47 52
48void user_signal(int sig, union uml_pt_regs *regs) 53extern int ptrace_faultinfo;
54
55void user_signal(int sig, union uml_pt_regs *regs, int pid)
49{ 56{
50 struct signal_info *info; 57 struct signal_info *info;
58 int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
59 (sig == SIGILL) || (sig == SIGTRAP));
51 60
52 regs->skas.is_user = 1; 61 regs->skas.is_user = 1;
53 regs->skas.fault_addr = 0; 62 if (segv)
54 regs->skas.fault_type = 0; 63 get_skas_faultinfo(pid, &regs->skas.faultinfo);
55 regs->skas.trap_type = 0;
56 info = &sig_info[sig]; 64 info = &sig_info[sig];
57 (*info->handler)(sig, regs); 65 (*info->handler)(sig, regs);
58 66
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index f7da9d027672..75195281081e 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -29,9 +29,12 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
29 if(IS_ERR(phys) || (is_write && !pte_write(pte))){ 29 if(IS_ERR(phys) || (is_write && !pte_write(pte))){
30 err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); 30 err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
31 if(err) 31 if(err)
32 return(0); 32 return(-1UL);
33 phys = um_virt_to_phys(current, virt, NULL); 33 phys = um_virt_to_phys(current, virt, NULL);
34 } 34 }
35 if(IS_ERR(phys))
36 phys = (void *) -1;
37
35 return((unsigned long) phys); 38 return((unsigned long) phys);
36} 39}
37 40
@@ -42,7 +45,7 @@ static int do_op(unsigned long addr, int len, int is_write,
42 int n; 45 int n;
43 46
44 addr = maybe_map(addr, is_write); 47 addr = maybe_map(addr, is_write);
45 if(addr == -1) 48 if(addr == -1UL)
46 return(-1); 49 return(-1);
47 50
48 page = phys_to_page(addr); 51 page = phys_to_page(addr);
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
index 17f5909d60f7..f7b7eba83340 100644
--- a/arch/um/kernel/skas/util/Makefile
+++ b/arch/um/kernel/skas/util/Makefile
@@ -2,3 +2,4 @@ hostprogs-y := mk_ptregs
2always := $(hostprogs-y) 2always := $(hostprogs-y)
3 3
4mk_ptregs-objs := mk_ptregs-$(SUBARCH).o 4mk_ptregs-objs := mk_ptregs-$(SUBARCH).o
5HOSTCFLAGS_mk_ptregs-$(SUBARCH).o := -I$(objtree)/arch/um
diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c
index 0788dd05bcac..1f96e1eeb8a7 100644
--- a/arch/um/kernel/skas/util/mk_ptregs-i386.c
+++ b/arch/um/kernel/skas/util/mk_ptregs-i386.c
@@ -1,8 +1,7 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <asm/ptrace.h> 2#include <user-offsets.h>
3#include <asm/user.h>
4 3
5#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val)) 4#define SHOW(name) printf("#define %s %d\n", #name, name)
6 5
7int main(int argc, char **argv) 6int main(int argc, char **argv)
8{ 7{
@@ -12,28 +11,27 @@ int main(int argc, char **argv)
12 printf("#ifndef __SKAS_PT_REGS_\n"); 11 printf("#ifndef __SKAS_PT_REGS_\n");
13 printf("#define __SKAS_PT_REGS_\n"); 12 printf("#define __SKAS_PT_REGS_\n");
14 printf("\n"); 13 printf("\n");
15 printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE); 14 SHOW(HOST_FRAME_SIZE);
16 printf("#define HOST_FP_SIZE %d\n", 15 SHOW(HOST_FP_SIZE);
17 sizeof(struct user_i387_struct) / sizeof(unsigned long)); 16 SHOW(HOST_XFP_SIZE);
18 printf("#define HOST_XFP_SIZE %d\n", 17
19 sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); 18 SHOW(HOST_IP);
19 SHOW(HOST_SP);
20 SHOW(HOST_EFLAGS);
21 SHOW(HOST_EAX);
22 SHOW(HOST_EBX);
23 SHOW(HOST_ECX);
24 SHOW(HOST_EDX);
25 SHOW(HOST_ESI);
26 SHOW(HOST_EDI);
27 SHOW(HOST_EBP);
28 SHOW(HOST_CS);
29 SHOW(HOST_SS);
30 SHOW(HOST_DS);
31 SHOW(HOST_FS);
32 SHOW(HOST_ES);
33 SHOW(HOST_GS);
20 34
21 PRINT_REG("IP", EIP);
22 PRINT_REG("SP", UESP);
23 PRINT_REG("EFLAGS", EFL);
24 PRINT_REG("EAX", EAX);
25 PRINT_REG("EBX", EBX);
26 PRINT_REG("ECX", ECX);
27 PRINT_REG("EDX", EDX);
28 PRINT_REG("ESI", ESI);
29 PRINT_REG("EDI", EDI);
30 PRINT_REG("EBP", EBP);
31 PRINT_REG("CS", CS);
32 PRINT_REG("SS", SS);
33 PRINT_REG("DS", DS);
34 PRINT_REG("FS", FS);
35 PRINT_REG("ES", ES);
36 PRINT_REG("GS", GS);
37 printf("\n"); 35 printf("\n");
38 printf("#endif\n"); 36 printf("#endif\n");
39 return(0); 37 return(0);
diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
index 67aee92a70ef..5fccbfe35f78 100644
--- a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
+++ b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
@@ -5,11 +5,10 @@
5 */ 5 */
6 6
7#include <stdio.h> 7#include <stdio.h>
8#define __FRAME_OFFSETS 8#include <user-offsets.h>
9#include <asm/ptrace.h>
10 9
11#define PRINT_REG(name, val) \ 10#define SHOW(name) \
12 printf("#define HOST_%s (%d / sizeof(unsigned long))\n", (name), (val)) 11 printf("#define %s (%d / sizeof(unsigned long))\n", #name, name)
13 12
14int main(int argc, char **argv) 13int main(int argc, char **argv)
15{ 14{
@@ -18,36 +17,35 @@ int main(int argc, char **argv)
18 printf("\n"); 17 printf("\n");
19 printf("#ifndef __SKAS_PT_REGS_\n"); 18 printf("#ifndef __SKAS_PT_REGS_\n");
20 printf("#define __SKAS_PT_REGS_\n"); 19 printf("#define __SKAS_PT_REGS_\n");
21 printf("#define HOST_FRAME_SIZE (%d / sizeof(unsigned long))\n", 20 SHOW(HOST_FRAME_SIZE);
22 FRAME_SIZE); 21 SHOW(HOST_RBX);
23 PRINT_REG("RBX", RBX); 22 SHOW(HOST_RCX);
24 PRINT_REG("RCX", RCX); 23 SHOW(HOST_RDI);
25 PRINT_REG("RDI", RDI); 24 SHOW(HOST_RSI);
26 PRINT_REG("RSI", RSI); 25 SHOW(HOST_RDX);
27 PRINT_REG("RDX", RDX); 26 SHOW(HOST_RBP);
28 PRINT_REG("RBP", RBP); 27 SHOW(HOST_RAX);
29 PRINT_REG("RAX", RAX); 28 SHOW(HOST_R8);
30 PRINT_REG("R8", R8); 29 SHOW(HOST_R9);
31 PRINT_REG("R9", R9); 30 SHOW(HOST_R10);
32 PRINT_REG("R10", R10); 31 SHOW(HOST_R11);
33 PRINT_REG("R11", R11); 32 SHOW(HOST_R12);
34 PRINT_REG("R12", R12); 33 SHOW(HOST_R13);
35 PRINT_REG("R13", R13); 34 SHOW(HOST_R14);
36 PRINT_REG("R14", R14); 35 SHOW(HOST_R15);
37 PRINT_REG("R15", R15); 36 SHOW(HOST_ORIG_RAX);
38 PRINT_REG("ORIG_RAX", ORIG_RAX); 37 SHOW(HOST_CS);
39 PRINT_REG("CS", CS); 38 SHOW(HOST_SS);
40 PRINT_REG("SS", SS); 39 SHOW(HOST_EFLAGS);
41 PRINT_REG("EFLAGS", EFLAGS);
42#if 0 40#if 0
43 PRINT_REG("FS", FS); 41 SHOW(HOST_FS);
44 PRINT_REG("GS", GS); 42 SHOW(HOST_GS);
45 PRINT_REG("DS", DS); 43 SHOW(HOST_DS);
46 PRINT_REG("ES", ES); 44 SHOW(HOST_ES);
47#endif 45#endif
48 46
49 PRINT_REG("IP", RIP); 47 SHOW(HOST_IP);
50 PRINT_REG("SP", RSP); 48 SHOW(HOST_SP);
51 printf("#define HOST_FP_SIZE 0\n"); 49 printf("#define HOST_FP_SIZE 0\n");
52 printf("#define HOST_XFP_SIZE 0\n"); 50 printf("#define HOST_XFP_SIZE 0\n");
53 printf("\n"); 51 printf("\n");
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index 42731e04f50f..b7a55251e897 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -17,7 +17,6 @@
17#include "linux/utime.h" 17#include "linux/utime.h"
18#include "asm/mman.h" 18#include "asm/mman.h"
19#include "asm/uaccess.h" 19#include "asm/uaccess.h"
20#include "asm/ipc.h"
21#include "kern_util.h" 20#include "kern_util.h"
22#include "user_util.h" 21#include "user_util.h"
23#include "sysdep/syscalls.h" 22#include "sysdep/syscalls.h"
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index e630438f9e73..f80850091e79 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -3,6 +3,7 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/config.h"
6#include "linux/sched.h" 7#include "linux/sched.h"
7#include "linux/kernel.h" 8#include "linux/kernel.h"
8#include "linux/module.h" 9#include "linux/module.h"
@@ -12,14 +13,14 @@
12#include "sysrq.h" 13#include "sysrq.h"
13#include "user_util.h" 14#include "user_util.h"
14 15
15void show_trace(unsigned long * stack) 16/* Catch non-i386 SUBARCH's. */
17#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
18void show_trace(struct task_struct *task, unsigned long * stack)
16{ 19{
17 /* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from
18 * arch/i386/kernel/traps.c, and then move this to sys-i386/sysrq.c.*/
19 unsigned long addr; 20 unsigned long addr;
20 21
21 if (!stack) { 22 if (!stack) {
22 stack = (unsigned long*) &stack; 23 stack = (unsigned long*) &stack;
23 WARN_ON(1); 24 WARN_ON(1);
24 } 25 }
25 26
@@ -35,6 +36,7 @@ void show_trace(unsigned long * stack)
35 } 36 }
36 printk("\n"); 37 printk("\n");
37} 38}
39#endif
38 40
39/* 41/*
40 * stack dumps generator - this is used by arch-independent code. 42 * stack dumps generator - this is used by arch-independent code.
@@ -44,7 +46,7 @@ void dump_stack(void)
44{ 46{
45 unsigned long stack; 47 unsigned long stack;
46 48
47 show_trace(&stack); 49 show_trace(current, &stack);
48} 50}
49EXPORT_SYMBOL(dump_stack); 51EXPORT_SYMBOL(dump_stack);
50 52
@@ -59,7 +61,11 @@ void show_stack(struct task_struct *task, unsigned long *esp)
59 int i; 61 int i;
60 62
61 if (esp == NULL) { 63 if (esp == NULL) {
62 if (task != current) { 64 if (task != current && task != NULL) {
65 /* XXX: Isn't this bogus? I.e. isn't this the
66 * *userspace* stack of this task? If not so, use this
67 * even when task == current (as in i386).
68 */
63 esp = (unsigned long *) KSTK_ESP(task); 69 esp = (unsigned long *) KSTK_ESP(task);
64 /* Which one? No actual difference - just coding style.*/ 70 /* Which one? No actual difference - just coding style.*/
65 //esp = (unsigned long *) PT_REGS_IP(&task->thread.regs); 71 //esp = (unsigned long *) PT_REGS_IP(&task->thread.regs);
@@ -77,5 +83,6 @@ void show_stack(struct task_struct *task, unsigned long *esp)
77 printk("%08lx ", *stack++); 83 printk("%08lx ", *stack++);
78 } 84 }
79 85
80 show_trace(esp); 86 printk("Call Trace: \n");
87 show_trace(current, esp);
81} 88}
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 2461cd73ca87..6516fc52afe0 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -48,8 +48,6 @@ static unsigned long long prev_usecs;
48static long long delta; /* Deviation per interval */ 48static long long delta; /* Deviation per interval */
49#endif 49#endif
50 50
51#define MILLION 1000000
52
53void timer_irq(union uml_pt_regs *regs) 51void timer_irq(union uml_pt_regs *regs)
54{ 52{
55 unsigned long long ticks = 0; 53 unsigned long long ticks = 0;
@@ -136,22 +134,6 @@ long um_stime(int __user *tptr)
136 return 0; 134 return 0;
137} 135}
138 136
139void __udelay(unsigned long usecs)
140{
141 int i, n;
142
143 n = (loops_per_jiffy * HZ * usecs) / MILLION;
144 for(i=0;i<n;i++) ;
145}
146
147void __const_udelay(unsigned long usecs)
148{
149 int i, n;
150
151 n = (loops_per_jiffy * HZ * usecs) / MILLION;
152 for(i=0;i<n;i++) ;
153}
154
155void timer_handler(int sig, union uml_pt_regs *regs) 137void timer_handler(int sig, union uml_pt_regs *regs)
156{ 138{
157 local_irq_disable(); 139 local_irq_disable();
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 47e766e6ba10..c20aef120598 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -23,7 +23,6 @@
23#include "kern.h" 23#include "kern.h"
24#include "chan_kern.h" 24#include "chan_kern.h"
25#include "mconsole_kern.h" 25#include "mconsole_kern.h"
26#include "2_5compat.h"
27#include "mem.h" 26#include "mem.h"
28#include "mem_kern.h" 27#include "mem_kern.h"
29 28
@@ -48,7 +47,7 @@ int handle_page_fault(unsigned long address, unsigned long ip,
48 goto good_area; 47 goto good_area;
49 else if(!(vma->vm_flags & VM_GROWSDOWN)) 48 else if(!(vma->vm_flags & VM_GROWSDOWN))
50 goto out; 49 goto out;
51 else if(!ARCH_IS_STACKGROW(address)) 50 else if(is_user && !ARCH_IS_STACKGROW(address))
52 goto out; 51 goto out;
53 else if(expand_stack(vma, address)) 52 else if(expand_stack(vma, address))
54 goto out; 53 goto out;
@@ -57,10 +56,11 @@ int handle_page_fault(unsigned long address, unsigned long ip,
57 *code_out = SEGV_ACCERR; 56 *code_out = SEGV_ACCERR;
58 if(is_write && !(vma->vm_flags & VM_WRITE)) 57 if(is_write && !(vma->vm_flags & VM_WRITE))
59 goto out; 58 goto out;
59
60 if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
61 goto out;
62
60 page = address & PAGE_MASK; 63 page = address & PAGE_MASK;
61 pgd = pgd_offset(mm, page);
62 pud = pud_offset(pgd, page);
63 pmd = pmd_offset(pud, page);
64 do { 64 do {
65 survive: 65 survive:
66 switch (handle_mm_fault(mm, vma, address, is_write)){ 66 switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -106,46 +106,24 @@ out_of_memory:
106 goto out; 106 goto out;
107} 107}
108 108
109LIST_HEAD(physmem_remappers); 109/*
110 110 * We give a *copy* of the faultinfo in the regs to segv.
111void register_remapper(struct remapper *info) 111 * This must be done, since nesting SEGVs could overwrite
112{ 112 * the info in the regs. A pointer to the info then would
113 list_add(&info->list, &physmem_remappers); 113 * give us bad data!
114} 114 */
115 115unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
116static int check_remapped_addr(unsigned long address, int is_write)
117{
118 struct remapper *remapper;
119 struct list_head *ele;
120 __u64 offset;
121 int fd;
122
123 fd = phys_mapping(__pa(address), &offset);
124 if(fd == -1)
125 return(0);
126
127 list_for_each(ele, &physmem_remappers){
128 remapper = list_entry(ele, struct remapper, list);
129 if((*remapper->proc)(fd, address, is_write, offset))
130 return(1);
131 }
132
133 return(0);
134}
135
136unsigned long segv(unsigned long address, unsigned long ip, int is_write,
137 int is_user, void *sc)
138{ 116{
139 struct siginfo si; 117 struct siginfo si;
140 void *catcher; 118 void *catcher;
141 int err; 119 int err;
120 int is_write = FAULT_WRITE(fi);
121 unsigned long address = FAULT_ADDRESS(fi);
142 122
143 if(!is_user && (address >= start_vm) && (address < end_vm)){ 123 if(!is_user && (address >= start_vm) && (address < end_vm)){
144 flush_tlb_kernel_vm(); 124 flush_tlb_kernel_vm();
145 return(0); 125 return(0);
146 } 126 }
147 else if(check_remapped_addr(address & PAGE_MASK, is_write))
148 return(0);
149 else if(current->mm == NULL) 127 else if(current->mm == NULL)
150 panic("Segfault with no mm"); 128 panic("Segfault with no mm");
151 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); 129 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
@@ -159,7 +137,7 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
159 } 137 }
160 else if(current->thread.fault_addr != NULL) 138 else if(current->thread.fault_addr != NULL)
161 panic("fault_addr set but no fault catcher"); 139 panic("fault_addr set but no fault catcher");
162 else if(arch_fixup(ip, sc)) 140 else if(!is_user && arch_fixup(ip, sc))
163 return(0); 141 return(0);
164 142
165 if(!is_user) 143 if(!is_user)
@@ -171,6 +149,7 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
171 si.si_errno = 0; 149 si.si_errno = 0;
172 si.si_code = BUS_ADRERR; 150 si.si_code = BUS_ADRERR;
173 si.si_addr = (void *)address; 151 si.si_addr = (void *)address;
152 current->thread.arch.faultinfo = fi;
174 force_sig_info(SIGBUS, &si, current); 153 force_sig_info(SIGBUS, &si, current);
175 } 154 }
176 else if(err == -ENOMEM){ 155 else if(err == -ENOMEM){
@@ -180,22 +159,20 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
180 else { 159 else {
181 si.si_signo = SIGSEGV; 160 si.si_signo = SIGSEGV;
182 si.si_addr = (void *) address; 161 si.si_addr = (void *) address;
183 current->thread.cr2 = address; 162 current->thread.arch.faultinfo = fi;
184 current->thread.err = is_write;
185 force_sig_info(SIGSEGV, &si, current); 163 force_sig_info(SIGSEGV, &si, current);
186 } 164 }
187 return(0); 165 return(0);
188} 166}
189 167
190void bad_segv(unsigned long address, unsigned long ip, int is_write) 168void bad_segv(struct faultinfo fi, unsigned long ip)
191{ 169{
192 struct siginfo si; 170 struct siginfo si;
193 171
194 si.si_signo = SIGSEGV; 172 si.si_signo = SIGSEGV;
195 si.si_code = SEGV_ACCERR; 173 si.si_code = SEGV_ACCERR;
196 si.si_addr = (void *) address; 174 si.si_addr = (void *) FAULT_ADDRESS(fi);
197 current->thread.cr2 = address; 175 current->thread.arch.faultinfo = fi;
198 current->thread.err = is_write;
199 force_sig_info(SIGSEGV, &si, current); 176 force_sig_info(SIGSEGV, &si, current);
200} 177}
201 178
@@ -204,6 +181,7 @@ void relay_signal(int sig, union uml_pt_regs *regs)
204 if(arch_handle_signal(sig, regs)) return; 181 if(arch_handle_signal(sig, regs)) return;
205 if(!UPT_IS_USER(regs)) 182 if(!UPT_IS_USER(regs))
206 panic("Kernel mode signal %d", sig); 183 panic("Kernel mode signal %d", sig);
184 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
207 force_sig(sig, current); 185 force_sig(sig, current);
208} 186}
209 187
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
index 50a4042a509f..f825a6eda3f5 100644
--- a/arch/um/kernel/trap_user.c
+++ b/arch/um/kernel/trap_user.c
@@ -54,23 +54,22 @@ struct {
54void segv_handler(int sig, union uml_pt_regs *regs) 54void segv_handler(int sig, union uml_pt_regs *regs)
55{ 55{
56 int index, max; 56 int index, max;
57 struct faultinfo * fi = UPT_FAULTINFO(regs);
57 58
58 if(UPT_IS_USER(regs) && !UPT_SEGV_IS_FIXABLE(regs)){ 59 if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
59 bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), 60 bad_segv(*fi, UPT_IP(regs));
60 UPT_FAULT_WRITE(regs));
61 return; 61 return;
62 } 62 }
63 max = sizeof(segfault_record)/sizeof(segfault_record[0]); 63 max = sizeof(segfault_record)/sizeof(segfault_record[0]);
64 index = next_trap_index(max); 64 index = next_trap_index(max);
65 65
66 nsegfaults++; 66 nsegfaults++;
67 segfault_record[index].address = UPT_FAULT_ADDR(regs); 67 segfault_record[index].address = FAULT_ADDRESS(*fi);
68 segfault_record[index].pid = os_getpid(); 68 segfault_record[index].pid = os_getpid();
69 segfault_record[index].is_write = UPT_FAULT_WRITE(regs); 69 segfault_record[index].is_write = FAULT_WRITE(*fi);
70 segfault_record[index].sp = UPT_SP(regs); 70 segfault_record[index].sp = UPT_SP(regs);
71 segfault_record[index].is_user = UPT_IS_USER(regs); 71 segfault_record[index].is_user = UPT_IS_USER(regs);
72 segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs), 72 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
73 UPT_IS_USER(regs), regs);
74} 73}
75 74
76void usr2_handler(int sig, union uml_pt_regs *regs) 75void usr2_handler(int sig, union uml_pt_regs *regs)
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index 3d5177df3504..c3faea21a996 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -4,6 +4,7 @@
4# 4#
5 5
6extra-y := unmap_fin.o 6extra-y := unmap_fin.o
7targets := unmap.o
7clean-files := unmap_tmp.o 8clean-files := unmap_tmp.o
8 9
9obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ 10obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
index 28aaab3448fa..e0ca0e0b2516 100644
--- a/arch/um/kernel/tt/include/mode_kern-tt.h
+++ b/arch/um/kernel/tt/include/mode_kern-tt.h
@@ -19,7 +19,6 @@ extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
19 unsigned long stack_top, struct task_struct *p, 19 unsigned long stack_top, struct task_struct *p,
20 struct pt_regs *regs); 20 struct pt_regs *regs);
21extern void release_thread_tt(struct task_struct *task); 21extern void release_thread_tt(struct task_struct *task);
22extern void exit_thread_tt(void);
23extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); 22extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
24extern void init_idle_tt(void); 23extern void init_idle_tt(void);
25extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end); 24extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h
index bb69d6b7d022..3fbb5fe26f49 100644
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ b/arch/um/kernel/tt/include/uaccess-tt.h
@@ -33,8 +33,8 @@ extern unsigned long uml_physmem;
33 (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ 33 (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
34 (under_task_size(addr, size) || is_stack(addr, size)))) 34 (under_task_size(addr, size) || is_stack(addr, size))))
35 35
36static inline int __deprecated verify_area_tt(int type, const void * addr, 36static inline int verify_area_tt(int type, const void * addr,
37 unsigned long size) 37 unsigned long size)
38{ 38{
39 return(access_ok_tt(type, addr, size) ? 0 : -EFAULT); 39 return(access_ok_tt(type, addr, size) ? 0 : -EFAULT);
40} 40}
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c
index 92ec85d67c7c..84a9385a8fef 100644
--- a/arch/um/kernel/tt/ksyms.c
+++ b/arch/um/kernel/tt/ksyms.c
@@ -12,6 +12,7 @@ EXPORT_SYMBOL(__do_copy_to_user);
12EXPORT_SYMBOL(__do_strncpy_from_user); 12EXPORT_SYMBOL(__do_strncpy_from_user);
13EXPORT_SYMBOL(__do_strnlen_user); 13EXPORT_SYMBOL(__do_strnlen_user);
14EXPORT_SYMBOL(__do_clear_user); 14EXPORT_SYMBOL(__do_clear_user);
15EXPORT_SYMBOL(clear_user_tt);
15 16
16EXPORT_SYMBOL(tracing_pid); 17EXPORT_SYMBOL(tracing_pid);
17EXPORT_SYMBOL(honeypot); 18EXPORT_SYMBOL(honeypot);
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
index 74346a04a2b2..bcb8796c3cb1 100644
--- a/arch/um/kernel/tt/mem.c
+++ b/arch/um/kernel/tt/mem.c
@@ -21,14 +21,8 @@ void before_mem_tt(unsigned long brk_start)
21 remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); 21 remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
22} 22}
23 23
24#ifdef CONFIG_HOST_2G_2G
25#define TOP 0x80000000
26#else
27#define TOP 0xc0000000
28#endif
29
30#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) 24#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
31#define START (TOP - SIZE) 25#define START (CONFIG_TOP_ADDR - SIZE)
32 26
33unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, 27unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
34 unsigned long *task_size_out) 28 unsigned long *task_size_out)
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index f19f7c18febe..776310fd5b8b 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -32,10 +32,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
32 unsigned long flags; 32 unsigned long flags;
33 int err, vtalrm, alrm, prof, cpu; 33 int err, vtalrm, alrm, prof, cpu;
34 char c; 34 char c;
35 /* jailing and SMP are incompatible, so this doesn't need to be
36 * made per-cpu
37 */
38 static int reading;
39 35
40 from = prev; 36 from = prev;
41 to = next; 37 to = next;
@@ -59,14 +55,11 @@ void *switch_to_tt(void *prev, void *next, void *last)
59 c = 0; 55 c = 0;
60 set_current(to); 56 set_current(to);
61 57
62 reading = 0;
63 err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); 58 err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
64 if(err != sizeof(c)) 59 if(err != sizeof(c))
65 panic("write of switch_pipe failed, err = %d", -err); 60 panic("write of switch_pipe failed, err = %d", -err);
66 61
67 reading = 1; 62 if(from->thread.mode.tt.switch_pipe[0] == -1)
68 if((from->exit_state == EXIT_ZOMBIE) ||
69 (from->exit_state == EXIT_DEAD))
70 os_kill_process(os_getpid(), 0); 63 os_kill_process(os_getpid(), 0);
71 64
72 err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); 65 err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
@@ -81,8 +74,7 @@ void *switch_to_tt(void *prev, void *next, void *last)
81 * in case it has not already killed itself. 74 * in case it has not already killed itself.
82 */ 75 */
83 prev_sched = current->thread.prev_sched; 76 prev_sched = current->thread.prev_sched;
84 if((prev_sched->exit_state == EXIT_ZOMBIE) || 77 if(prev_sched->thread.mode.tt.switch_pipe[0] == -1)
85 (prev_sched->exit_state == EXIT_DEAD))
86 os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1); 78 os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
87 79
88 change_sig(SIGVTALRM, vtalrm); 80 change_sig(SIGVTALRM, vtalrm);
@@ -101,14 +93,18 @@ void release_thread_tt(struct task_struct *task)
101{ 93{
102 int pid = task->thread.mode.tt.extern_pid; 94 int pid = task->thread.mode.tt.extern_pid;
103 95
96 /*
97 * We first have to kill the other process, before
98 * closing its switch_pipe. Else it might wake up
99 * and receive "EOF" before we could kill it.
100 */
104 if(os_getpid() != pid) 101 if(os_getpid() != pid)
105 os_kill_process(pid, 0); 102 os_kill_process(pid, 0);
106}
107 103
108void exit_thread_tt(void) 104 os_close_file(task->thread.mode.tt.switch_pipe[0]);
109{ 105 os_close_file(task->thread.mode.tt.switch_pipe[1]);
110 os_close_file(current->thread.mode.tt.switch_pipe[0]); 106 /* use switch_pipe as flag: thread is released */
111 os_close_file(current->thread.mode.tt.switch_pipe[1]); 107 task->thread.mode.tt.switch_pipe[0] = -1;
112} 108}
113 109
114void suspend_new_thread(int fd) 110void suspend_new_thread(int fd)
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
index e4e7e9c2224c..b218316cfdb2 100644
--- a/arch/um/kernel/tt/syscall_user.c
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -63,6 +63,10 @@ void do_syscall(void *task, int pid, int local_using_sysemu)
63 63
64 UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs); 64 UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs);
65 65
66#ifdef UPT_ORIGGPR2
67 UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs);
68#endif
69
66 if(((unsigned long *) PT_IP(proc_regs) >= &_stext) && 70 if(((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
67 ((unsigned long *) PT_IP(proc_regs) <= &_etext)) 71 ((unsigned long *) PT_IP(proc_regs) <= &_etext))
68 tracer_panic("I'm tracing myself and I can't get out"); 72 tracer_panic("I'm tracing myself and I can't get out");
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index 7b5d937e5955..d11e7399d7a1 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -26,6 +26,7 @@
26#include "kern_util.h" 26#include "kern_util.h"
27#include "chan_user.h" 27#include "chan_user.h"
28#include "ptrace_user.h" 28#include "ptrace_user.h"
29#include "irq_user.h"
29#include "mode.h" 30#include "mode.h"
30#include "tt.h" 31#include "tt.h"
31 32
@@ -33,7 +34,7 @@ static int tracer_winch[2];
33 34
34int is_tracer_winch(int pid, int fd, void *data) 35int is_tracer_winch(int pid, int fd, void *data)
35{ 36{
36 if(pid != tracing_pid) 37 if(pid != os_getpgrp())
37 return(0); 38 return(0);
38 39
39 register_winch_irq(tracer_winch[0], fd, -1, data); 40 register_winch_irq(tracer_winch[0], fd, -1, data);
@@ -89,8 +90,10 @@ void tracer_panic(char *format, ...)
89 90
90static void tracer_segv(int sig, struct sigcontext sc) 91static void tracer_segv(int sig, struct sigcontext sc)
91{ 92{
93 struct faultinfo fi;
94 GET_FAULTINFO_FROM_SC(fi, &sc);
92 printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n", 95 printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n",
93 SC_FAULT_ADDR(&sc), SC_IP(&sc)); 96 FAULT_ADDRESS(fi), SC_IP(&sc));
94 while(1) 97 while(1)
95 pause(); 98 pause();
96} 99}
@@ -117,6 +120,7 @@ static int signal_tramp(void *arg)
117 signal(SIGSEGV, (__sighandler_t) sig_handler); 120 signal(SIGSEGV, (__sighandler_t) sig_handler);
118 set_cmdline("(idle thread)"); 121 set_cmdline("(idle thread)");
119 set_init_pid(os_getpid()); 122 set_init_pid(os_getpid());
123 init_irq_signals(0);
120 proc = arg; 124 proc = arg;
121 return((*proc)(NULL)); 125 return((*proc)(NULL));
122} 126}
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index 92a3820ca543..fc108615beaf 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -7,6 +7,7 @@
7#include <errno.h> 7#include <errno.h>
8#include <signal.h> 8#include <signal.h>
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/sigcontext.h"
10#include "signal_user.h" 11#include "signal_user.h"
11#include "user_util.h" 12#include "user_util.h"
12#include "kern_util.h" 13#include "kern_util.h"
@@ -28,6 +29,11 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
28 change_sig(SIGSEGV, 1); 29 change_sig(SIGSEGV, 1);
29 30
30 r = &TASK_REGS(get_current())->tt; 31 r = &TASK_REGS(get_current())->tt;
32 if ( sig == SIGFPE || sig == SIGSEGV ||
33 sig == SIGBUS || sig == SIGILL ||
34 sig == SIGTRAP ) {
35 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
36 }
31 save_regs = *r; 37 save_regs = *r;
32 is_user = user_context(SC_SP(sc)); 38 is_user = user_context(SC_SP(sc));
33 r->sc = sc; 39 r->sc = sc;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 5c49d88eed3d..418427107b29 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -23,6 +23,7 @@
23#include "asm/ptrace.h" 23#include "asm/ptrace.h"
24#include "asm/elf.h" 24#include "asm/elf.h"
25#include "asm/user.h" 25#include "asm/user.h"
26#include "asm/setup.h"
26#include "ubd_user.h" 27#include "ubd_user.h"
27#include "asm/current.h" 28#include "asm/current.h"
28#include "asm/setup.h" 29#include "asm/setup.h"
@@ -42,9 +43,9 @@
42#define DEFAULT_COMMAND_LINE "root=98:0" 43#define DEFAULT_COMMAND_LINE "root=98:0"
43 44
44/* Changed in linux_main and setup_arch, which run before SMP is started */ 45/* Changed in linux_main and setup_arch, which run before SMP is started */
45char command_line[COMMAND_LINE_SIZE] = { 0 }; 46static char command_line[COMMAND_LINE_SIZE] = { 0 };
46 47
47void add_arg(char *arg) 48static void add_arg(char *arg)
48{ 49{
49 if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { 50 if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
50 printf("add_arg: Too many command line arguments!\n"); 51 printf("add_arg: Too many command line arguments!\n");
@@ -110,12 +111,6 @@ struct seq_operations cpuinfo_op = {
110 .show = show_cpuinfo, 111 .show = show_cpuinfo,
111}; 112};
112 113
113pte_t * __bad_pagetable(void)
114{
115 panic("Someone should implement __bad_pagetable");
116 return(NULL);
117}
118
119/* Set in linux_main */ 114/* Set in linux_main */
120unsigned long host_task_size; 115unsigned long host_task_size;
121unsigned long task_size; 116unsigned long task_size;
@@ -449,7 +444,7 @@ void __init setup_arch(char **cmdline_p)
449{ 444{
450 notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); 445 notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
451 paging_init(); 446 paging_init();
452 strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); 447 strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
453 *cmdline_p = command_line; 448 *cmdline_p = command_line;
454 setup_hostinfo(); 449 setup_hostinfo();
455} 450}
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 76eadb309189..dd5355500bdc 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -73,6 +73,8 @@ SECTIONS
73 73
74 .got : { *(.got.plt) *(.got) } 74 .got : { *(.got.plt) *(.got) }
75 .dynamic : { *(.dynamic) } 75 .dynamic : { *(.dynamic) }
76 .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
77 .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
76 /* We want the small data sections together, so single-instruction offsets 78 /* We want the small data sections together, so single-instruction offsets
77 can access them all, and initialized data all before uninitialized, so 79 can access them all, and initialized data all before uninitialized, so
78 we can shorten the on-disk segment size. */ 80 we can shorten the on-disk segment size. */
diff --git a/arch/um/kernel/vmlinux.lds.S b/arch/um/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..1660a769674b
--- /dev/null
+++ b/arch/um/kernel/vmlinux.lds.S
@@ -0,0 +1,6 @@
1#include <linux/config.h>
2#ifdef CONFIG_LD_SCRIPT_STATIC
3#include "uml.lds.S"
4#else
5#include "dyn.lds.S"
6#endif
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index ba9ca1cc790a..1e126bfd31a7 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -123,6 +123,11 @@ int os_getpid(void)
123 return(getpid()); 123 return(getpid());
124} 124}
125 125
126int os_getpgrp(void)
127{
128 return getpgrp();
129}
130
126int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, 131int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
127 int r, int w, int x) 132 int r, int w, int x)
128{ 133{
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 7eac1baf5975..c7bfd5ee3925 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -8,7 +8,7 @@
8#include "mode.h" 8#include "mode.h"
9#include "sysdep/signal.h" 9#include "sysdep/signal.h"
10 10
11void sig_handler(int sig) 11void sig_handler(ARCH_SIGHDLR_PARAM)
12{ 12{
13 struct sigcontext *sc; 13 struct sigcontext *sc;
14 14
@@ -19,7 +19,7 @@ void sig_handler(int sig)
19 19
20extern int timer_irq_inited; 20extern int timer_irq_inited;
21 21
22void alarm_handler(int sig) 22void alarm_handler(ARCH_SIGHDLR_PARAM)
23{ 23{
24 struct sigcontext *sc; 24 struct sigcontext *sc;
25 25
diff --git a/arch/um/os-Linux/util/Makefile b/arch/um/os-Linux/util/Makefile
index fb00ddf969bd..9778aed0c314 100644
--- a/arch/um/os-Linux/util/Makefile
+++ b/arch/um/os-Linux/util/Makefile
@@ -1,4 +1,4 @@
1hostprogs-y := mk_user_constants 1hostprogs-y := mk_user_constants
2always := $(hostprogs-y) 2always := $(hostprogs-y)
3 3
4mk_user_constants-objs := mk_user_constants.o 4HOSTCFLAGS_mk_user_constants.o := -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/util/mk_user_constants.c b/arch/um/os-Linux/util/mk_user_constants.c
index 0933518aa8bd..4838f30eecf0 100644
--- a/arch/um/os-Linux/util/mk_user_constants.c
+++ b/arch/um/os-Linux/util/mk_user_constants.c
@@ -1,11 +1,5 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <asm/types.h> 2#include <user-offsets.h>
3/* For some reason, x86_64 nowhere defines u64 and u32, even though they're
4 * used throughout the headers.
5 */
6typedef __u64 u64;
7typedef __u32 u32;
8#include <asm/user.h>
9 3
10int main(int argc, char **argv) 4int main(int argc, char **argv)
11{ 5{
@@ -20,7 +14,7 @@ int main(int argc, char **argv)
20 * x86_64 (216 vs 168 bytes). user_regs_struct is the correct size on 14 * x86_64 (216 vs 168 bytes). user_regs_struct is the correct size on
21 * both x86_64 and i386. 15 * both x86_64 and i386.
22 */ 16 */
23 printf("#define UM_FRAME_SIZE %d\n", (int) sizeof(struct user_regs_struct)); 17 printf("#define UM_FRAME_SIZE %d\n", __UM_FRAME_SIZE);
24 18
25 printf("\n"); 19 printf("\n");
26 printf("#endif\n"); 20 printf("#endif\n");
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 143f6fea0763..0b2491883d9c 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -2,12 +2,27 @@
2# arch/um: Generic definitions 2# arch/um: Generic definitions
3# =========================================================================== 3# ===========================================================================
4 4
5USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs)) 5USER_SINGLE_OBJS := \
6USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) 6 $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
7 7USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
8USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) 8USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
9 9
10$(USER_OBJS): c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@)) 10$(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \
11 $(CFLAGS_$(notdir $@))
11 12
12quiet_cmd_make_link = SYMLINK $@ 13quiet_cmd_make_link = SYMLINK $@
13cmd_make_link = rm -f $@; ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@ 14cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
15
16# this needs to be before the foreach, because targets does not accept
17# complete paths like $(obj)/$(f). To make sure this works, use a := assignment,
18# or we will get $(obj)/$(f) in the "targets" value.
19# Also, this forces you to use the := syntax when assigning to targets.
20# Otherwise the line below will cause an infinite loop (if you don't know why,
21# just do it).
22
23targets := $(targets) $(SYMLINKS)
24
25SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$(f))
26
27$(SYMLINKS): FORCE
28 $(call if_changed,make_link)
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 950781e354de..4351e5605506 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -7,24 +7,13 @@ obj-$(CONFIG_MODULES) += module.o
7 7
8USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o 8USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
9 9
10include arch/um/scripts/Makefile.rules
11
12SYMLINKS = bitops.c semaphore.c highmem.c module.c 10SYMLINKS = bitops.c semaphore.c highmem.c module.c
13 11
14# this needs to be before the foreach, because clean-files does not accept 12include arch/um/scripts/Makefile.rules
15# complete paths like $(src)/$f.
16clean-files := $(SYMLINKS)
17
18targets += $(SYMLINKS)
19
20SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$f)
21 13
22bitops.c-dir = lib 14bitops.c-dir = lib
23semaphore.c-dir = kernel 15semaphore.c-dir = kernel
24highmem.c-dir = mm 16highmem.c-dir = mm
25module.c-dir = kernel 17module.c-dir = kernel
26 18
27$(SYMLINKS): FORCE
28 $(call if_changed,make_link)
29
30subdir- := util 19subdir- := util
diff --git a/arch/um/sys-i386/checksum.S b/arch/um/sys-i386/checksum.S
index a11171fb6223..d98b2fff3d08 100644
--- a/arch/um/sys-i386/checksum.S
+++ b/arch/um/sys-i386/checksum.S
@@ -38,7 +38,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
38 38
39.text 39.text
40.align 4 40.align 4
41.globl arch_csum_partial 41.globl csum_partial
42 42
43#ifndef CONFIG_X86_USE_PPRO_CHECKSUM 43#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
44 44
@@ -49,7 +49,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
49 * Fortunately, it is easy to convert 2-byte alignment to 4-byte 49 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
50 * alignment for the unrolled loop. 50 * alignment for the unrolled loop.
51 */ 51 */
52arch_csum_partial: 52csum_partial:
53 pushl %esi 53 pushl %esi
54 pushl %ebx 54 pushl %ebx
55 movl 20(%esp),%eax # Function arg: unsigned int sum 55 movl 20(%esp),%eax # Function arg: unsigned int sum
@@ -119,7 +119,7 @@ arch_csum_partial:
119 119
120/* Version for PentiumII/PPro */ 120/* Version for PentiumII/PPro */
121 121
122arch_csum_partial: 122csum_partial:
123 pushl %esi 123 pushl %esi
124 pushl %ebx 124 pushl %ebx
125 movl 20(%esp),%eax # Function arg: unsigned int sum 125 movl 20(%esp),%eax # Function arg: unsigned int sum
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
index 20d37dbbaf08..2c11b9770e8b 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/um/sys-i386/delay.c
@@ -1,3 +1,8 @@
1#include <linux/module.h>
2#include <linux/kernel.h>
3#include <linux/delay.h>
4#include <asm/param.h>
5
1void __delay(unsigned long time) 6void __delay(unsigned long time)
2{ 7{
3 /* Stolen from the i386 __loop_delay */ 8 /* Stolen from the i386 __loop_delay */
@@ -12,3 +17,24 @@ void __delay(unsigned long time)
12 :"0" (time)); 17 :"0" (time));
13} 18}
14 19
20void __udelay(unsigned long usecs)
21{
22 int i, n;
23
24 n = (loops_per_jiffy * HZ * usecs) / MILLION;
25 for(i=0;i<n;i++)
26 cpu_relax();
27}
28
29EXPORT_SYMBOL(__udelay);
30
31void __const_udelay(unsigned long usecs)
32{
33 int i, n;
34
35 n = (loops_per_jiffy * HZ * usecs) / MILLION;
36 for(i=0;i<n;i++)
37 cpu_relax();
38}
39
40EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/um/sys-i386/kernel-offsets.c b/arch/um/sys-i386/kernel-offsets.c
new file mode 100644
index 000000000000..9f8ecd1fdd96
--- /dev/null
+++ b/arch/um/sys-i386/kernel-offsets.c
@@ -0,0 +1,25 @@
1#include <linux/config.h>
2#include <linux/stddef.h>
3#include <linux/sched.h>
4#include <linux/time.h>
5#include <asm/page.h>
6
7#define DEFINE(sym, val) \
8 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
9
10#define STR(x) #x
11#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
12
13#define BLANK() asm volatile("\n->" : : )
14
15#define OFFSET(sym, str, mem) \
16 DEFINE(sym, offsetof(struct str, mem));
17
18void foo(void)
19{
20 OFFSET(TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
21#ifdef CONFIG_MODE_TT
22 OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
23#endif
24#include <common-offsets.h>
25}
diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
index 74f70a120458..db524ab3f743 100644
--- a/arch/um/sys-i386/ksyms.c
+++ b/arch/um/sys-i386/ksyms.c
@@ -2,6 +2,7 @@
2#include "linux/in6.h" 2#include "linux/in6.h"
3#include "linux/rwsem.h" 3#include "linux/rwsem.h"
4#include "asm/byteorder.h" 4#include "asm/byteorder.h"
5#include "asm/delay.h"
5#include "asm/semaphore.h" 6#include "asm/semaphore.h"
6#include "asm/uaccess.h" 7#include "asm/uaccess.h"
7#include "asm/checksum.h" 8#include "asm/checksum.h"
@@ -13,5 +14,8 @@ EXPORT_SYMBOL(__down_failed_trylock);
13EXPORT_SYMBOL(__up_wakeup); 14EXPORT_SYMBOL(__up_wakeup);
14 15
15/* Networking helper routines. */ 16/* Networking helper routines. */
16EXPORT_SYMBOL(csum_partial_copy_from); 17EXPORT_SYMBOL(csum_partial);
17EXPORT_SYMBOL(csum_partial_copy_to); 18
19/* delay core functions */
20EXPORT_SYMBOL(__const_udelay);
21EXPORT_SYMBOL(__udelay);
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 31bcb2f997d4..dc755b0b9db8 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -25,7 +25,7 @@ int sys_modify_ldt_tt(int func, void __user *ptr, unsigned long bytecount)
25#endif 25#endif
26 26
27#ifdef CONFIG_MODE_SKAS 27#ifdef CONFIG_MODE_SKAS
28extern int userspace_pid; 28extern int userspace_pid[];
29 29
30#include "skas_ptrace.h" 30#include "skas_ptrace.h"
31 31
@@ -56,7 +56,8 @@ int sys_modify_ldt_skas(int func, void __user *ptr, unsigned long bytecount)
56 ldt = ((struct ptrace_ldt) { .func = func, 56 ldt = ((struct ptrace_ldt) { .func = func,
57 .ptr = buf, 57 .ptr = buf,
58 .bytecount = bytecount }); 58 .bytecount = bytecount });
59 res = ptrace(PTRACE_LDT, userspace_pid, 0, (unsigned long) &ldt); 59#warning Need to look up userspace_pid by cpu
60 res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt);
60 if(res < 0) 61 if(res < 0)
61 goto out; 62 goto out;
62 63
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index e470d28cdf84..e839ce65ad28 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -73,6 +73,25 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
73 return 0; 73 return 0;
74} 74}
75 75
76int poke_user(struct task_struct *child, long addr, long data)
77{
78 if ((addr & 3) || addr < 0)
79 return -EIO;
80
81 if (addr < MAX_REG_OFFSET)
82 return putreg(child, addr, data);
83
84 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
85 (addr <= offsetof(struct user, u_debugreg[7]))){
86 addr -= offsetof(struct user, u_debugreg[0]);
87 addr = addr >> 2;
88 if((addr == 4) || (addr == 5)) return -EIO;
89 child->thread.arch.debugregs[addr] = data;
90 return 0;
91 }
92 return -EIO;
93}
94
76unsigned long getreg(struct task_struct *child, int regno) 95unsigned long getreg(struct task_struct *child, int regno)
77{ 96{
78 unsigned long retval = ~0UL; 97 unsigned long retval = ~0UL;
@@ -93,6 +112,27 @@ unsigned long getreg(struct task_struct *child, int regno)
93 return retval; 112 return retval;
94} 113}
95 114
115int peek_user(struct task_struct *child, long addr, long data)
116{
117/* read the word at location addr in the USER area. */
118 unsigned long tmp;
119
120 if ((addr & 3) || addr < 0)
121 return -EIO;
122
123 tmp = 0; /* Default return condition */
124 if(addr < MAX_REG_OFFSET){
125 tmp = getreg(child, addr);
126 }
127 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
128 (addr <= offsetof(struct user, u_debugreg[7]))){
129 addr -= offsetof(struct user, u_debugreg[0]);
130 addr = addr >> 2;
131 tmp = child->thread.arch.debugregs[addr];
132 }
133 return put_user(tmp, (unsigned long *) data);
134}
135
96struct i387_fxsave_struct { 136struct i387_fxsave_struct {
97 unsigned short cwd; 137 unsigned short cwd;
98 unsigned short swd; 138 unsigned short swd;
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 76ba87254b25..03913ca5d256 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -47,9 +47,6 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
47 REGS_CS(regs->regs.skas.regs) = sc.cs; 47 REGS_CS(regs->regs.skas.regs) = sc.cs;
48 REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags; 48 REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags;
49 REGS_SS(regs->regs.skas.regs) = sc.ss; 49 REGS_SS(regs->regs.skas.regs) = sc.ss;
50 regs->regs.skas.fault_addr = sc.cr2;
51 regs->regs.skas.fault_type = FAULT_WRITE(sc.err);
52 regs->regs.skas.trap_type = sc.trapno;
53 50
54 err = restore_fp_registers(userspace_pid[0], fpregs); 51 err = restore_fp_registers(userspace_pid[0], fpregs);
55 if(err < 0){ 52 if(err < 0){
@@ -62,11 +59,11 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
62} 59}
63 60
64int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, 61int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
65 struct pt_regs *regs, unsigned long fault_addr, 62 struct pt_regs *regs)
66 int fault_type)
67{ 63{
68 struct sigcontext sc; 64 struct sigcontext sc;
69 unsigned long fpregs[HOST_FP_SIZE]; 65 unsigned long fpregs[HOST_FP_SIZE];
66 struct faultinfo * fi = &current->thread.arch.faultinfo;
70 int err; 67 int err;
71 68
72 sc.gs = REGS_GS(regs->regs.skas.regs); 69 sc.gs = REGS_GS(regs->regs.skas.regs);
@@ -86,9 +83,9 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
86 sc.eflags = REGS_EFLAGS(regs->regs.skas.regs); 83 sc.eflags = REGS_EFLAGS(regs->regs.skas.regs);
87 sc.esp_at_signal = regs->regs.skas.regs[UESP]; 84 sc.esp_at_signal = regs->regs.skas.regs[UESP];
88 sc.ss = regs->regs.skas.regs[SS]; 85 sc.ss = regs->regs.skas.regs[SS];
89 sc.cr2 = fault_addr; 86 sc.cr2 = fi->cr2;
90 sc.err = TO_SC_ERR(fault_type); 87 sc.err = fi->error_code;
91 sc.trapno = regs->regs.skas.trap_type; 88 sc.trapno = fi->trap_no;
92 89
93 err = save_fp_registers(userspace_pid[0], fpregs); 90 err = save_fp_registers(userspace_pid[0], fpregs);
94 if(err < 0){ 91 if(err < 0){
@@ -167,9 +164,7 @@ static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
167{ 164{
168 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 165 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
169 sizeof(*fp)), 166 sizeof(*fp)),
170 copy_sc_to_user_skas(to, fp, from, 167 copy_sc_to_user_skas(to, fp, from)));
171 current->thread.cr2,
172 current->thread.err)));
173} 168}
174 169
175static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp, 170static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
diff --git a/arch/um/sys-i386/sysrq.c b/arch/um/sys-i386/sysrq.c
index 281fc7b8ca00..e3706d15c4f5 100644
--- a/arch/um/sys-i386/sysrq.c
+++ b/arch/um/sys-i386/sysrq.c
@@ -3,12 +3,15 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/config.h"
6#include "linux/kernel.h" 7#include "linux/kernel.h"
7#include "linux/smp.h" 8#include "linux/smp.h"
8#include "linux/sched.h" 9#include "linux/sched.h"
10#include "linux/kallsyms.h"
9#include "asm/ptrace.h" 11#include "asm/ptrace.h"
10#include "sysrq.h" 12#include "sysrq.h"
11 13
14/* This is declared by <linux/sched.h> */
12void show_regs(struct pt_regs *regs) 15void show_regs(struct pt_regs *regs)
13{ 16{
14 printk("\n"); 17 printk("\n");
@@ -31,5 +34,80 @@ void show_regs(struct pt_regs *regs)
31 0xffff & PT_REGS_DS(regs), 34 0xffff & PT_REGS_DS(regs),
32 0xffff & PT_REGS_ES(regs)); 35 0xffff & PT_REGS_ES(regs));
33 36
34 show_trace((unsigned long *) &regs); 37 show_trace(NULL, (unsigned long *) &regs);
35} 38}
39
40/* Copied from i386. */
41static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
42{
43 return p > (void *)tinfo &&
44 p < (void *)tinfo + THREAD_SIZE - 3;
45}
46
47/* Adapted from i386 (we also print the address we read from). */
48static inline unsigned long print_context_stack(struct thread_info *tinfo,
49 unsigned long *stack, unsigned long ebp)
50{
51 unsigned long addr;
52
53#ifdef CONFIG_FRAME_POINTER
54 while (valid_stack_ptr(tinfo, (void *)ebp)) {
55 addr = *(unsigned long *)(ebp + 4);
56 printk("%08lx: [<%08lx>]", ebp + 4, addr);
57 print_symbol(" %s", addr);
58 printk("\n");
59 ebp = *(unsigned long *)ebp;
60 }
61#else
62 while (valid_stack_ptr(tinfo, stack)) {
63 addr = *stack;
64 if (__kernel_text_address(addr)) {
65 printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
66 print_symbol(" %s", addr);
67 printk("\n");
68 }
69 stack++;
70 }
71#endif
72 return ebp;
73}
74
75void show_trace(struct task_struct* task, unsigned long * stack)
76{
77 unsigned long ebp;
78 struct thread_info *context;
79
80 /* Turn this into BUG_ON if possible. */
81 if (!stack) {
82 stack = (unsigned long*) &stack;
83 printk("show_trace: got NULL stack, implicit assumption task == current");
84 WARN_ON(1);
85 }
86
87 if (!task)
88 task = current;
89
90 if (task != current) {
91 //ebp = (unsigned long) KSTK_EBP(task);
92 /* Which one? No actual difference - just coding style.*/
93 ebp = (unsigned long) PT_REGS_EBP(&task->thread.regs);
94 } else {
95 asm ("movl %%ebp, %0" : "=r" (ebp) : );
96 }
97
98 context = (struct thread_info *)
99 ((unsigned long)stack & (~(THREAD_SIZE - 1)));
100 print_context_stack(context, stack, ebp);
101
102 /*while (((long) stack & (THREAD_SIZE-1)) != 0) {
103 addr = *stack;
104 if (__kernel_text_address(addr)) {
105 printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
106 print_symbol(" %s", addr);
107 printk("\n");
108 }
109 stack++;
110 }*/
111 printk("\n");
112}
113
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
new file mode 100644
index 000000000000..3ceaabceb3d7
--- /dev/null
+++ b/arch/um/sys-i386/user-offsets.c
@@ -0,0 +1,69 @@
1#include <stdio.h>
2#include <signal.h>
3#include <asm/ptrace.h>
4#include <asm/user.h>
5#include <linux/stddef.h>
6
7#define DEFINE(sym, val) \
8 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
9
10#define OFFSET(sym, str, mem) \
11 DEFINE(sym, offsetof(struct str, mem));
12
13void foo(void)
14{
15 OFFSET(SC_IP, sigcontext, eip);
16 OFFSET(SC_SP, sigcontext, esp);
17 OFFSET(SC_FS, sigcontext, fs);
18 OFFSET(SC_GS, sigcontext, gs);
19 OFFSET(SC_DS, sigcontext, ds);
20 OFFSET(SC_ES, sigcontext, es);
21 OFFSET(SC_SS, sigcontext, ss);
22 OFFSET(SC_CS, sigcontext, cs);
23 OFFSET(SC_EFLAGS, sigcontext, eflags);
24 OFFSET(SC_EAX, sigcontext, eax);
25 OFFSET(SC_EBX, sigcontext, ebx);
26 OFFSET(SC_ECX, sigcontext, ecx);
27 OFFSET(SC_EDX, sigcontext, edx);
28 OFFSET(SC_EDI, sigcontext, edi);
29 OFFSET(SC_ESI, sigcontext, esi);
30 OFFSET(SC_EBP, sigcontext, ebp);
31 OFFSET(SC_TRAPNO, sigcontext, trapno);
32 OFFSET(SC_ERR, sigcontext, err);
33 OFFSET(SC_CR2, sigcontext, cr2);
34 OFFSET(SC_FPSTATE, sigcontext, fpstate);
35 OFFSET(SC_SIGMASK, sigcontext, oldmask);
36 OFFSET(SC_FP_CW, _fpstate, cw);
37 OFFSET(SC_FP_SW, _fpstate, sw);
38 OFFSET(SC_FP_TAG, _fpstate, tag);
39 OFFSET(SC_FP_IPOFF, _fpstate, ipoff);
40 OFFSET(SC_FP_CSSEL, _fpstate, cssel);
41 OFFSET(SC_FP_DATAOFF, _fpstate, dataoff);
42 OFFSET(SC_FP_DATASEL, _fpstate, datasel);
43 OFFSET(SC_FP_ST, _fpstate, _st);
44 OFFSET(SC_FXSR_ENV, _fpstate, _fxsr_env);
45
46 DEFINE(HOST_FRAME_SIZE, FRAME_SIZE);
47 DEFINE(HOST_FP_SIZE,
48 sizeof(struct user_i387_struct) / sizeof(unsigned long));
49 DEFINE(HOST_XFP_SIZE,
50 sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
51
52 DEFINE(HOST_IP, EIP);
53 DEFINE(HOST_SP, UESP);
54 DEFINE(HOST_EFLAGS, EFL);
55 DEFINE(HOST_EAX, EAX);
56 DEFINE(HOST_EBX, EBX);
57 DEFINE(HOST_ECX, ECX);
58 DEFINE(HOST_EDX, EDX);
59 DEFINE(HOST_ESI, ESI);
60 DEFINE(HOST_EDI, EDI);
61 DEFINE(HOST_EBP, EBP);
62 DEFINE(HOST_CS, CS);
63 DEFINE(HOST_SS, SS);
64 DEFINE(HOST_DS, DS);
65 DEFINE(HOST_FS, FS);
66 DEFINE(HOST_ES, ES);
67 DEFINE(HOST_GS, GS);
68 DEFINE(__UM_FRAME_SIZE, sizeof(struct user_regs_struct));
69}
diff --git a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile
index 34860f9ca7b0..bf61afd0b045 100644
--- a/arch/um/sys-i386/util/Makefile
+++ b/arch/um/sys-i386/util/Makefile
@@ -1,8 +1,5 @@
1
2hostprogs-y := mk_sc mk_thread 1hostprogs-y := mk_sc mk_thread
3always := $(hostprogs-y) 2always := $(hostprogs-y)
4 3
5mk_thread-objs := mk_thread_kern.o mk_thread_user.o 4HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um
6 5HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um
7HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS)
8HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS)
diff --git a/arch/um/sys-i386/util/mk_sc.c b/arch/um/sys-i386/util/mk_sc.c
index 85cbd30396f7..04c0d73433aa 100644
--- a/arch/um/sys-i386/util/mk_sc.c
+++ b/arch/um/sys-i386/util/mk_sc.c
@@ -1,52 +1,51 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <signal.h> 2#include <user-offsets.h>
3#include <linux/stddef.h>
4 3
5#define SC_OFFSET(name, field) \ 4#define SC_OFFSET(name, field) \
6 printf("#define " name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\ 5 printf("#define " #name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\
7 offsetof(struct sigcontext, field)) 6 name)
8 7
9#define SC_FP_OFFSET(name, field) \ 8#define SC_FP_OFFSET(name, field) \
10 printf("#define " name \ 9 printf("#define " #name \
11 "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ 10 "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
12 offsetof(struct _fpstate, field)) 11 name)
13 12
14#define SC_FP_OFFSET_PTR(name, field, type) \ 13#define SC_FP_OFFSET_PTR(name, field, type) \
15 printf("#define " name \ 14 printf("#define " #name \
16 "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ 15 "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
17 offsetof(struct _fpstate, field)) 16 name)
18 17
19int main(int argc, char **argv) 18int main(int argc, char **argv)
20{ 19{
21 SC_OFFSET("SC_IP", eip); 20 SC_OFFSET(SC_IP, eip);
22 SC_OFFSET("SC_SP", esp); 21 SC_OFFSET(SC_SP, esp);
23 SC_OFFSET("SC_FS", fs); 22 SC_OFFSET(SC_FS, fs);
24 SC_OFFSET("SC_GS", gs); 23 SC_OFFSET(SC_GS, gs);
25 SC_OFFSET("SC_DS", ds); 24 SC_OFFSET(SC_DS, ds);
26 SC_OFFSET("SC_ES", es); 25 SC_OFFSET(SC_ES, es);
27 SC_OFFSET("SC_SS", ss); 26 SC_OFFSET(SC_SS, ss);
28 SC_OFFSET("SC_CS", cs); 27 SC_OFFSET(SC_CS, cs);
29 SC_OFFSET("SC_EFLAGS", eflags); 28 SC_OFFSET(SC_EFLAGS, eflags);
30 SC_OFFSET("SC_EAX", eax); 29 SC_OFFSET(SC_EAX, eax);
31 SC_OFFSET("SC_EBX", ebx); 30 SC_OFFSET(SC_EBX, ebx);
32 SC_OFFSET("SC_ECX", ecx); 31 SC_OFFSET(SC_ECX, ecx);
33 SC_OFFSET("SC_EDX", edx); 32 SC_OFFSET(SC_EDX, edx);
34 SC_OFFSET("SC_EDI", edi); 33 SC_OFFSET(SC_EDI, edi);
35 SC_OFFSET("SC_ESI", esi); 34 SC_OFFSET(SC_ESI, esi);
36 SC_OFFSET("SC_EBP", ebp); 35 SC_OFFSET(SC_EBP, ebp);
37 SC_OFFSET("SC_TRAPNO", trapno); 36 SC_OFFSET(SC_TRAPNO, trapno);
38 SC_OFFSET("SC_ERR", err); 37 SC_OFFSET(SC_ERR, err);
39 SC_OFFSET("SC_CR2", cr2); 38 SC_OFFSET(SC_CR2, cr2);
40 SC_OFFSET("SC_FPSTATE", fpstate); 39 SC_OFFSET(SC_FPSTATE, fpstate);
41 SC_OFFSET("SC_SIGMASK", oldmask); 40 SC_OFFSET(SC_SIGMASK, oldmask);
42 SC_FP_OFFSET("SC_FP_CW", cw); 41 SC_FP_OFFSET(SC_FP_CW, cw);
43 SC_FP_OFFSET("SC_FP_SW", sw); 42 SC_FP_OFFSET(SC_FP_SW, sw);
44 SC_FP_OFFSET("SC_FP_TAG", tag); 43 SC_FP_OFFSET(SC_FP_TAG, tag);
45 SC_FP_OFFSET("SC_FP_IPOFF", ipoff); 44 SC_FP_OFFSET(SC_FP_IPOFF, ipoff);
46 SC_FP_OFFSET("SC_FP_CSSEL", cssel); 45 SC_FP_OFFSET(SC_FP_CSSEL, cssel);
47 SC_FP_OFFSET("SC_FP_DATAOFF", dataoff); 46 SC_FP_OFFSET(SC_FP_DATAOFF, dataoff);
48 SC_FP_OFFSET("SC_FP_DATASEL", datasel); 47 SC_FP_OFFSET(SC_FP_DATASEL, datasel);
49 SC_FP_OFFSET_PTR("SC_FP_ST", _st, "struct _fpstate"); 48 SC_FP_OFFSET_PTR(SC_FP_ST, _st, "struct _fpstate");
50 SC_FP_OFFSET_PTR("SC_FXSR_ENV", _fxsr_env, "void"); 49 SC_FP_OFFSET_PTR(SC_FXSR_ENV, _fxsr_env, "void");
51 return(0); 50 return(0);
52} 51}
diff --git a/arch/um/sys-i386/util/mk_thread.c b/arch/um/sys-i386/util/mk_thread.c
new file mode 100644
index 000000000000..7470d0dda67e
--- /dev/null
+++ b/arch/um/sys-i386/util/mk_thread.c
@@ -0,0 +1,22 @@
1#include <stdio.h>
2#include <kernel-offsets.h>
3
4int main(int argc, char **argv)
5{
6 printf("/*\n");
7 printf(" * Generated by mk_thread\n");
8 printf(" */\n");
9 printf("\n");
10 printf("#ifndef __UM_THREAD_H\n");
11 printf("#define __UM_THREAD_H\n");
12 printf("\n");
13 printf("#define TASK_DEBUGREGS(task) ((unsigned long *) "
14 "&(((char *) (task))[%d]))\n", TASK_DEBUGREGS);
15#ifdef TASK_EXTERN_PID
16 printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n",
17 TASK_EXTERN_PID);
18#endif
19 printf("\n");
20 printf("#endif\n");
21 return(0);
22}
diff --git a/arch/um/sys-i386/util/mk_thread_kern.c b/arch/um/sys-i386/util/mk_thread_kern.c
deleted file mode 100644
index 948b1ce85230..000000000000
--- a/arch/um/sys-i386/util/mk_thread_kern.c
+++ /dev/null
@@ -1,22 +0,0 @@
1#include "linux/config.h"
2#include "linux/stddef.h"
3#include "linux/sched.h"
4
5extern void print_head(void);
6extern void print_constant_ptr(char *name, int value);
7extern void print_constant(char *name, char *type, int value);
8extern void print_tail(void);
9
10#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field)
11
12int main(int argc, char **argv)
13{
14 print_head();
15 print_constant_ptr("TASK_DEBUGREGS", THREAD_OFFSET(arch.debugregs));
16#ifdef CONFIG_MODE_TT
17 print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid));
18#endif
19 print_tail();
20 return(0);
21}
22
diff --git a/arch/um/sys-i386/util/mk_thread_user.c b/arch/um/sys-i386/util/mk_thread_user.c
deleted file mode 100644
index 2620cd6aa1f1..000000000000
--- a/arch/um/sys-i386/util/mk_thread_user.c
+++ /dev/null
@@ -1,30 +0,0 @@
1#include <stdio.h>
2
3void print_head(void)
4{
5 printf("/*\n");
6 printf(" * Generated by mk_thread\n");
7 printf(" */\n");
8 printf("\n");
9 printf("#ifndef __UM_THREAD_H\n");
10 printf("#define __UM_THREAD_H\n");
11 printf("\n");
12}
13
14void print_constant_ptr(char *name, int value)
15{
16 printf("#define %s(task) ((unsigned long *) "
17 "&(((char *) (task))[%d]))\n", name, value);
18}
19
20void print_constant(char *name, char *type, int value)
21{
22 printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
23 value);
24}
25
26void print_tail(void)
27{
28 printf("\n");
29 printf("#endif\n");
30}
diff --git a/arch/um/sys-ppc/ptrace.c b/arch/um/sys-ppc/ptrace.c
index a971366d3277..8e71b47f2b8e 100644
--- a/arch/um/sys-ppc/ptrace.c
+++ b/arch/um/sys-ppc/ptrace.c
@@ -8,6 +8,25 @@ int putreg(struct task_struct *child, unsigned long regno,
8 return 0; 8 return 0;
9} 9}
10 10
11int poke_user(struct task_struct *child, long addr, long data)
12{
13 if ((addr & 3) || addr < 0)
14 return -EIO;
15
16 if (addr < MAX_REG_OFFSET)
17 return putreg(child, addr, data);
18
19 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
20 (addr <= offsetof(struct user, u_debugreg[7]))){
21 addr -= offsetof(struct user, u_debugreg[0]);
22 addr = addr >> 2;
23 if((addr == 4) || (addr == 5)) return -EIO;
24 child->thread.arch.debugregs[addr] = data;
25 return 0;
26 }
27 return -EIO;
28}
29
11unsigned long getreg(struct task_struct *child, unsigned long regno) 30unsigned long getreg(struct task_struct *child, unsigned long regno)
12{ 31{
13 unsigned long retval = ~0UL; 32 unsigned long retval = ~0UL;
@@ -16,6 +35,27 @@ unsigned long getreg(struct task_struct *child, unsigned long regno)
16 return retval; 35 return retval;
17} 36}
18 37
38int peek_user(struct task_struct *child, long addr, long data)
39{
40 /* read the word at location addr in the USER area. */
41 unsigned long tmp;
42
43 if ((addr & 3) || addr < 0)
44 return -EIO;
45
46 tmp = 0; /* Default return condition */
47 if(addr < MAX_REG_OFFSET){
48 tmp = getreg(child, addr);
49 }
50 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
51 (addr <= offsetof(struct user, u_debugreg[7]))){
52 addr -= offsetof(struct user, u_debugreg[0]);
53 addr = addr >> 2;
54 tmp = child->thread.arch.debugregs[addr];
55 }
56 return put_user(tmp, (unsigned long *) data);
57}
58
19/* 59/*
20 * Overrides for Emacs so that we follow Linus's tabbing style. 60 * Overrides for Emacs so that we follow Linus's tabbing style.
21 * Emacs will notice this stuff at the end of the file and automatically 61 * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/sys-ppc/sysrq.c b/arch/um/sys-ppc/sysrq.c
index 82d6e9335bb6..2f816f1a0ff4 100644
--- a/arch/um/sys-ppc/sysrq.c
+++ b/arch/um/sys-ppc/sysrq.c
@@ -27,17 +27,5 @@ void show_regs(struct pt_regs_subarch *regs)
27 0xffff & regs->xds, 0xffff & regs->xes); 27 0xffff & regs->xds, 0xffff & regs->xes);
28#endif 28#endif
29 29
30 show_trace(&regs->gpr[1]); 30 show_trace(current, &regs->gpr[1]);
31} 31}
32
33
34/*
35 * Overrides for Emacs so that we follow Linus's tabbing style.
36 * Emacs will notice this stuff at the end of the file and automatically
37 * adjust the settings for this buffer only. This must remain at the end
38 * of the file.
39 * ---------------------------------------------------------------------------
40 * Local variables:
41 * c-file-style: "linux"
42 * End:
43 */
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index d7ed2f7908df..608466ad6b22 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -4,24 +4,20 @@
4# Licensed under the GPL 4# Licensed under the GPL
5# 5#
6 6
7#XXX: why into lib-y?
7lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \ 8lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
8 ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \ 9 ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \
9 syscalls.o sysrq.o thunk.o syscall_table.o 10 syscalls.o sysrq.o thunk.o syscall_table.o
10 11
11USER_OBJS := ptrace_user.o sigcontext.o 12obj-y := ksyms.o
13obj-$(CONFIG_MODULES) += module.o um_module.o
12 14
13include arch/um/scripts/Makefile.rules 15USER_OBJS := ptrace_user.o sigcontext.o
14 16
15SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ 17SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
16 semaphore.c thunk.S 18 semaphore.c thunk.S module.c
17
18# this needs to be before the foreach, because clean-files does not accept
19# complete paths like $(src)/$f.
20clean-files := $(SYMLINKS)
21 19
22targets += $(SYMLINKS) 20include arch/um/scripts/Makefile.rules
23
24SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$f)
25 21
26bitops.c-dir = lib 22bitops.c-dir = lib
27csum-copy.S-dir = lib 23csum-copy.S-dir = lib
@@ -30,8 +26,6 @@ csum-wrappers.c-dir = lib
30memcpy.S-dir = lib 26memcpy.S-dir = lib
31semaphore.c-dir = kernel 27semaphore.c-dir = kernel
32thunk.S-dir = lib 28thunk.S-dir = lib
29module.c-dir = kernel
33 30
34$(SYMLINKS): FORCE 31subdir- := util
35 $(call if_changed,make_link)
36
37CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
index f3b5187942b4..137f4446b439 100644
--- a/arch/um/sys-x86_64/delay.c
+++ b/arch/um/sys-x86_64/delay.c
@@ -5,22 +5,37 @@
5 * Licensed under the GPL 5 * Licensed under the GPL
6 */ 6 */
7 7
8#include "asm/processor.h" 8#include <linux/module.h>
9#include <linux/delay.h>
10#include <asm/processor.h>
11#include <asm/param.h>
9 12
10void __delay(unsigned long loops) 13void __delay(unsigned long loops)
11{ 14{
12 unsigned long i; 15 unsigned long i;
13 16
14 for(i = 0; i < loops; i++) ; 17 for(i = 0; i < loops; i++)
18 cpu_relax();
15} 19}
16 20
17/* 21void __udelay(unsigned long usecs)
18 * Overrides for Emacs so that we follow Linus's tabbing style. 22{
19 * Emacs will notice this stuff at the end of the file and automatically 23 unsigned long i, n;
20 * adjust the settings for this buffer only. This must remain at the end 24
21 * of the file. 25 n = (loops_per_jiffy * HZ * usecs) / MILLION;
22 * --------------------------------------------------------------------------- 26 for(i=0;i<n;i++)
23 * Local variables: 27 cpu_relax();
24 * c-file-style: "linux" 28}
25 * End: 29
26 */ 30EXPORT_SYMBOL(__udelay);
31
32void __const_udelay(unsigned long usecs)
33{
34 unsigned long i, n;
35
36 n = (loops_per_jiffy * HZ * usecs) / MILLION;
37 for(i=0;i<n;i++)
38 cpu_relax();
39}
40
41EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/um/sys-x86_64/kernel-offsets.c b/arch/um/sys-x86_64/kernel-offsets.c
new file mode 100644
index 000000000000..220e875cbe29
--- /dev/null
+++ b/arch/um/sys-x86_64/kernel-offsets.c
@@ -0,0 +1,24 @@
1#include <linux/config.h>
2#include <linux/stddef.h>
3#include <linux/sched.h>
4#include <linux/time.h>
5#include <asm/page.h>
6
7#define DEFINE(sym, val) \
8 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
9
10#define DEFINE_STR1(x) #x
11#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
12
13#define BLANK() asm volatile("\n->" : : )
14
15#define OFFSET(sym, str, mem) \
16 DEFINE(sym, offsetof(struct str, mem));
17
18void foo(void)
19{
20#ifdef CONFIG_MODE_TT
21 OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
22#endif
23#include <common-offsets.h>
24}
diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
new file mode 100644
index 000000000000..859273808203
--- /dev/null
+++ b/arch/um/sys-x86_64/ksyms.c
@@ -0,0 +1,19 @@
1#include "linux/module.h"
2#include "linux/in6.h"
3#include "linux/rwsem.h"
4#include "asm/byteorder.h"
5#include "asm/semaphore.h"
6#include "asm/uaccess.h"
7#include "asm/checksum.h"
8#include "asm/errno.h"
9
10EXPORT_SYMBOL(__down_failed);
11EXPORT_SYMBOL(__down_failed_interruptible);
12EXPORT_SYMBOL(__down_failed_trylock);
13EXPORT_SYMBOL(__up_wakeup);
14
15/*XXX: we need them because they would be exported by x86_64 */
16EXPORT_SYMBOL(__memcpy);
17
18/* Networking helper routines. */
19EXPORT_SYMBOL(ip_compute_csum);
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 8c146b2a1e00..74eee5c7c6dd 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -5,10 +5,11 @@
5 */ 5 */
6 6
7#define __FRAME_OFFSETS 7#define __FRAME_OFFSETS
8#include "asm/ptrace.h" 8#include <asm/ptrace.h>
9#include "linux/sched.h" 9#include <linux/sched.h>
10#include "linux/errno.h" 10#include <linux/errno.h>
11#include "asm/elf.h" 11#include <asm/uaccess.h>
12#include <asm/elf.h>
12 13
13/* XXX x86_64 */ 14/* XXX x86_64 */
14unsigned long not_ss; 15unsigned long not_ss;
@@ -62,6 +63,27 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
62 return 0; 63 return 0;
63} 64}
64 65
66int poke_user(struct task_struct *child, long addr, long data)
67{
68 if ((addr & 3) || addr < 0)
69 return -EIO;
70
71 if (addr < MAX_REG_OFFSET)
72 return putreg(child, addr, data);
73
74#if 0 /* Need x86_64 debugregs handling */
75 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
76 (addr <= offsetof(struct user, u_debugreg[7]))){
77 addr -= offsetof(struct user, u_debugreg[0]);
78 addr = addr >> 2;
79 if((addr == 4) || (addr == 5)) return -EIO;
80 child->thread.arch.debugregs[addr] = data;
81 return 0;
82 }
83#endif
84 return -EIO;
85}
86
65unsigned long getreg(struct task_struct *child, int regno) 87unsigned long getreg(struct task_struct *child, int regno)
66{ 88{
67 unsigned long retval = ~0UL; 89 unsigned long retval = ~0UL;
@@ -84,6 +106,29 @@ unsigned long getreg(struct task_struct *child, int regno)
84 return retval; 106 return retval;
85} 107}
86 108
109int peek_user(struct task_struct *child, long addr, long data)
110{
111 /* read the word at location addr in the USER area. */
112 unsigned long tmp;
113
114 if ((addr & 3) || addr < 0)
115 return -EIO;
116
117 tmp = 0; /* Default return condition */
118 if(addr < MAX_REG_OFFSET){
119 tmp = getreg(child, addr);
120 }
121#if 0 /* Need x86_64 debugregs handling */
122 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
123 (addr <= offsetof(struct user, u_debugreg[7]))){
124 addr -= offsetof(struct user, u_debugreg[0]);
125 addr = addr >> 2;
126 tmp = child->thread.arch.debugregs[addr];
127 }
128#endif
129 return put_user(tmp, (unsigned long *) data);
130}
131
87void arch_switch(void) 132void arch_switch(void)
88{ 133{
89/* XXX 134/* XXX
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 5bc5a0d796e5..73a7926f7370 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -57,7 +57,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
57int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, 57int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
58 struct pt_regs *regs, unsigned long mask) 58 struct pt_regs *regs, unsigned long mask)
59{ 59{
60 unsigned long eflags; 60 struct faultinfo * fi = &current->thread.arch.faultinfo;
61 int err = 0; 61 int err = 0;
62 62
63 err |= __put_user(0, &to->gs); 63 err |= __put_user(0, &to->gs);
@@ -84,14 +84,16 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
84 err |= PUTREG(regs, R14, to, r14); 84 err |= PUTREG(regs, R14, to, r14);
85 err |= PUTREG(regs, R15, to, r15); 85 err |= PUTREG(regs, R15, to, r15);
86 err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ 86 err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
87 err |= __put_user(current->thread.err, &to->err); 87
88 err |= __put_user(current->thread.trap_no, &to->trapno); 88 err |= __put_user(fi->cr2, &to->cr2);
89 err |= __put_user(fi->error_code, &to->err);
90 err |= __put_user(fi->trap_no, &to->trapno);
91
89 err |= PUTREG(regs, RIP, to, rip); 92 err |= PUTREG(regs, RIP, to, rip);
90 err |= PUTREG(regs, EFLAGS, to, eflags); 93 err |= PUTREG(regs, EFLAGS, to, eflags);
91#undef PUTREG 94#undef PUTREG
92 95
93 err |= __put_user(mask, &to->oldmask); 96 err |= __put_user(mask, &to->oldmask);
94 err |= __put_user(current->thread.cr2, &to->cr2);
95 97
96 return(err); 98 return(err);
97} 99}
@@ -166,7 +168,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
166 168
167 frame = (struct rt_sigframe __user *) 169 frame = (struct rt_sigframe __user *)
168 round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8; 170 round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
169 frame -= 128; 171 ((unsigned char *) frame) -= 128;
170 172
171 if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) 173 if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
172 goto out; 174 goto out;
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index ab4b0abf8af3..6f44f40204ed 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -7,12 +7,15 @@
7#include "linux/linkage.h" 7#include "linux/linkage.h"
8#include "linux/slab.h" 8#include "linux/slab.h"
9#include "linux/shm.h" 9#include "linux/shm.h"
10#include "linux/utsname.h"
11#include "linux/personality.h"
10#include "asm/uaccess.h" 12#include "asm/uaccess.h"
11#define __FRAME_OFFSETS 13#define __FRAME_OFFSETS
12#include "asm/ptrace.h" 14#include "asm/ptrace.h"
13#include "asm/unistd.h" 15#include "asm/unistd.h"
14#include "asm/prctl.h" /* XXX This should get the constants from libc */ 16#include "asm/prctl.h" /* XXX This should get the constants from libc */
15#include "choose-mode.h" 17#include "choose-mode.h"
18#include "kern.h"
16 19
17asmlinkage long sys_uname64(struct new_utsname __user * name) 20asmlinkage long sys_uname64(struct new_utsname __user * name)
18{ 21{
@@ -42,6 +45,8 @@ long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
42#ifdef CONFIG_MODE_SKAS 45#ifdef CONFIG_MODE_SKAS
43extern int userspace_pid[]; 46extern int userspace_pid[];
44 47
48#include "skas_ptrace.h"
49
45long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) 50long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
46{ 51{
47 struct ptrace_ldt ldt; 52 struct ptrace_ldt ldt;
@@ -128,23 +133,27 @@ static long arch_prctl_tt(int code, unsigned long addr)
128 133
129#ifdef CONFIG_MODE_SKAS 134#ifdef CONFIG_MODE_SKAS
130 135
136/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */
131static long arch_prctl_skas(int code, unsigned long addr) 137static long arch_prctl_skas(int code, unsigned long addr)
132{ 138{
133 long ret = 0; 139 long ret = 0;
134 140
135 switch(code){ 141 switch(code){
136 case ARCH_SET_GS:
137 current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
138 break;
139 case ARCH_SET_FS: 142 case ARCH_SET_FS:
140 current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr; 143 current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
141 break; 144 break;
145 case ARCH_SET_GS:
146 current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
147 break;
142 case ARCH_GET_FS: 148 case ARCH_GET_FS:
143 ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr); 149 ret = put_user(current->thread.regs.regs.skas.
150 regs[FS_BASE / sizeof(unsigned long)],
151 (unsigned long __user *)addr);
144 break; 152 break;
145 case ARCH_GET_GS: 153 case ARCH_GET_GS:
146 ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \ 154 ret = put_user(current->thread.regs.regs.skas.
147long)], &addr); 155 regs[GS_BASE / sizeof(unsigned long)],
156 (unsigned long __user *)addr);
148 break; 157 break;
149 default: 158 default:
150 ret = -EINVAL; 159 ret = -EINVAL;
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
index ddf74691a610..d0a25af19a5b 100644
--- a/arch/um/sys-x86_64/sysrq.c
+++ b/arch/um/sys-x86_64/sysrq.c
@@ -36,14 +36,5 @@ void __show_regs(struct pt_regs * regs)
36void show_regs(struct pt_regs *regs) 36void show_regs(struct pt_regs *regs)
37{ 37{
38 __show_regs(regs); 38 __show_regs(regs);
39 show_trace((unsigned long *) &regs); 39 show_trace(current, (unsigned long *) &regs);
40} 40}
41
42/* Emacs will notice this stuff at the end of the file and automatically
43 * adjust the settings for this buffer only. This must remain at the end
44 * of the file.
45 * ---------------------------------------------------------------------------
46 * Local variables:
47 * c-file-style: "linux"
48 * End:
49 */
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c
new file mode 100644
index 000000000000..8b8eff1bd977
--- /dev/null
+++ b/arch/um/sys-x86_64/um_module.c
@@ -0,0 +1,19 @@
1#include <linux/vmalloc.h>
2#include <linux/moduleloader.h>
3
4/*Copied from i386 arch/i386/kernel/module.c */
5void *module_alloc(unsigned long size)
6{
7 if (size == 0)
8 return NULL;
9 return vmalloc_exec(size);
10}
11
12/* Free memory returned from module_alloc */
13void module_free(struct module *mod, void *module_region)
14{
15 vfree(module_region);
16 /* FIXME: If module_region == mod->init_region, trim exception
17 table entries. */
18}
19
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
new file mode 100644
index 000000000000..513d17ceafd4
--- /dev/null
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -0,0 +1,86 @@
1#include <stdio.h>
2#include <stddef.h>
3#include <signal.h>
4#define __FRAME_OFFSETS
5#include <asm/ptrace.h>
6#include <asm/types.h>
7/* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I
8 * refuse to include here, even though they're used throughout the headers.
9 * These are used in asm/user.h, and that include can't be avoided because of
10 * the sizeof(struct user_regs_struct) below.
11 */
12typedef __u64 u64;
13typedef __u32 u32;
14#include <asm/user.h>
15
16#define DEFINE(sym, val) \
17 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
18
19#define OFFSET(sym, str, mem) \
20 DEFINE(sym, offsetof(struct str, mem));
21
22void foo(void)
23{
24 OFFSET(SC_RBX, sigcontext, rbx);
25 OFFSET(SC_RCX, sigcontext, rcx);
26 OFFSET(SC_RDX, sigcontext, rdx);
27 OFFSET(SC_RSI, sigcontext, rsi);
28 OFFSET(SC_RDI, sigcontext, rdi);
29 OFFSET(SC_RBP, sigcontext, rbp);
30 OFFSET(SC_RAX, sigcontext, rax);
31 OFFSET(SC_R8, sigcontext, r8);
32 OFFSET(SC_R9, sigcontext, r9);
33 OFFSET(SC_R10, sigcontext, r10);
34 OFFSET(SC_R11, sigcontext, r11);
35 OFFSET(SC_R12, sigcontext, r12);
36 OFFSET(SC_R13, sigcontext, r13);
37 OFFSET(SC_R14, sigcontext, r14);
38 OFFSET(SC_R15, sigcontext, r15);
39 OFFSET(SC_IP, sigcontext, rip);
40 OFFSET(SC_SP, sigcontext, rsp);
41 OFFSET(SC_CR2, sigcontext, cr2);
42 OFFSET(SC_ERR, sigcontext, err);
43 OFFSET(SC_TRAPNO, sigcontext, trapno);
44 OFFSET(SC_CS, sigcontext, cs);
45 OFFSET(SC_FS, sigcontext, fs);
46 OFFSET(SC_GS, sigcontext, gs);
47 OFFSET(SC_EFLAGS, sigcontext, eflags);
48 OFFSET(SC_SIGMASK, sigcontext, oldmask);
49#if 0
50 OFFSET(SC_ORIG_RAX, sigcontext, orig_rax);
51 OFFSET(SC_DS, sigcontext, ds);
52 OFFSET(SC_ES, sigcontext, es);
53 OFFSET(SC_SS, sigcontext, ss);
54#endif
55
56 DEFINE(HOST_FRAME_SIZE, FRAME_SIZE);
57 DEFINE(HOST_RBX, RBX);
58 DEFINE(HOST_RCX, RCX);
59 DEFINE(HOST_RDI, RDI);
60 DEFINE(HOST_RSI, RSI);
61 DEFINE(HOST_RDX, RDX);
62 DEFINE(HOST_RBP, RBP);
63 DEFINE(HOST_RAX, RAX);
64 DEFINE(HOST_R8, R8);
65 DEFINE(HOST_R9, R9);
66 DEFINE(HOST_R10, R10);
67 DEFINE(HOST_R11, R11);
68 DEFINE(HOST_R12, R12);
69 DEFINE(HOST_R13, R13);
70 DEFINE(HOST_R14, R14);
71 DEFINE(HOST_R15, R15);
72 DEFINE(HOST_ORIG_RAX, ORIG_RAX);
73 DEFINE(HOST_CS, CS);
74 DEFINE(HOST_SS, SS);
75 DEFINE(HOST_EFLAGS, EFLAGS);
76#if 0
77 DEFINE(HOST_FS, FS);
78 DEFINE(HOST_GS, GS);
79 DEFINE(HOST_DS, DS);
80 DEFINE(HOST_ES, ES);
81#endif
82
83 DEFINE(HOST_IP, RIP);
84 DEFINE(HOST_SP, RSP);
85 DEFINE(__UM_FRAME_SIZE, sizeof(struct user_regs_struct));
86}
diff --git a/arch/um/sys-x86_64/util/Makefile b/arch/um/sys-x86_64/util/Makefile
index 002607980864..75b052cfc206 100644
--- a/arch/um/sys-x86_64/util/Makefile
+++ b/arch/um/sys-x86_64/util/Makefile
@@ -4,7 +4,5 @@
4hostprogs-y := mk_sc mk_thread 4hostprogs-y := mk_sc mk_thread
5always := $(hostprogs-y) 5always := $(hostprogs-y)
6 6
7mk_thread-objs := mk_thread_kern.o mk_thread_user.o 7HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um
8 8HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um
9HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS)
10HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS)
diff --git a/arch/um/sys-x86_64/util/mk_sc.c b/arch/um/sys-x86_64/util/mk_sc.c
index c236e213918d..7619bc377c1f 100644
--- a/arch/um/sys-x86_64/util/mk_sc.c
+++ b/arch/um/sys-x86_64/util/mk_sc.c
@@ -3,56 +3,45 @@
3 */ 3 */
4 4
5#include <stdio.h> 5#include <stdio.h>
6#include <signal.h> 6#include <user-offsets.h>
7#include <linux/stddef.h>
8 7
9#define SC_OFFSET(name, field) \ 8#define SC_OFFSET(name) \
10 printf("#define " name \ 9 printf("#define " #name \
11 "(sc) *((unsigned long *) &(((char *) (sc))[%ld]))\n",\ 10 "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\
12 offsetof(struct sigcontext, field)) 11 name)
13
14#define SC_FP_OFFSET(name, field) \
15 printf("#define " name \
16 "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%ld]))\n",\
17 offsetof(struct _fpstate, field))
18
19#define SC_FP_OFFSET_PTR(name, field, type) \
20 printf("#define " name \
21 "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
22 offsetof(struct _fpstate, field))
23 12
24int main(int argc, char **argv) 13int main(int argc, char **argv)
25{ 14{
26 SC_OFFSET("SC_RBX", rbx); 15 SC_OFFSET(SC_RBX);
27 SC_OFFSET("SC_RCX", rcx); 16 SC_OFFSET(SC_RCX);
28 SC_OFFSET("SC_RDX", rdx); 17 SC_OFFSET(SC_RDX);
29 SC_OFFSET("SC_RSI", rsi); 18 SC_OFFSET(SC_RSI);
30 SC_OFFSET("SC_RDI", rdi); 19 SC_OFFSET(SC_RDI);
31 SC_OFFSET("SC_RBP", rbp); 20 SC_OFFSET(SC_RBP);
32 SC_OFFSET("SC_RAX", rax); 21 SC_OFFSET(SC_RAX);
33 SC_OFFSET("SC_R8", r8); 22 SC_OFFSET(SC_R8);
34 SC_OFFSET("SC_R9", r9); 23 SC_OFFSET(SC_R9);
35 SC_OFFSET("SC_R10", r10); 24 SC_OFFSET(SC_R10);
36 SC_OFFSET("SC_R11", r11); 25 SC_OFFSET(SC_R11);
37 SC_OFFSET("SC_R12", r12); 26 SC_OFFSET(SC_R12);
38 SC_OFFSET("SC_R13", r13); 27 SC_OFFSET(SC_R13);
39 SC_OFFSET("SC_R14", r14); 28 SC_OFFSET(SC_R14);
40 SC_OFFSET("SC_R15", r15); 29 SC_OFFSET(SC_R15);
41 SC_OFFSET("SC_IP", rip); 30 SC_OFFSET(SC_IP);
42 SC_OFFSET("SC_SP", rsp); 31 SC_OFFSET(SC_SP);
43 SC_OFFSET("SC_CR2", cr2); 32 SC_OFFSET(SC_CR2);
44 SC_OFFSET("SC_ERR", err); 33 SC_OFFSET(SC_ERR);
45 SC_OFFSET("SC_TRAPNO", trapno); 34 SC_OFFSET(SC_TRAPNO);
46 SC_OFFSET("SC_CS", cs); 35 SC_OFFSET(SC_CS);
47 SC_OFFSET("SC_FS", fs); 36 SC_OFFSET(SC_FS);
48 SC_OFFSET("SC_GS", gs); 37 SC_OFFSET(SC_GS);
49 SC_OFFSET("SC_EFLAGS", eflags); 38 SC_OFFSET(SC_EFLAGS);
50 SC_OFFSET("SC_SIGMASK", oldmask); 39 SC_OFFSET(SC_SIGMASK);
51#if 0 40#if 0
52 SC_OFFSET("SC_ORIG_RAX", orig_rax); 41 SC_OFFSET(SC_ORIG_RAX);
53 SC_OFFSET("SC_DS", ds); 42 SC_OFFSET(SC_DS);
54 SC_OFFSET("SC_ES", es); 43 SC_OFFSET(SC_ES);
55 SC_OFFSET("SC_SS", ss); 44 SC_OFFSET(SC_SS);
56#endif 45#endif
57 return(0); 46 return(0);
58} 47}
diff --git a/arch/um/sys-x86_64/util/mk_thread.c b/arch/um/sys-x86_64/util/mk_thread.c
new file mode 100644
index 000000000000..15517396e9cf
--- /dev/null
+++ b/arch/um/sys-x86_64/util/mk_thread.c
@@ -0,0 +1,20 @@
1#include <stdio.h>
2#include <kernel-offsets.h>
3
4int main(int argc, char **argv)
5{
6 printf("/*\n");
7 printf(" * Generated by mk_thread\n");
8 printf(" */\n");
9 printf("\n");
10 printf("#ifndef __UM_THREAD_H\n");
11 printf("#define __UM_THREAD_H\n");
12 printf("\n");
13#ifdef TASK_EXTERN_PID
14 printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n",
15 TASK_EXTERN_PID);
16#endif
17 printf("\n");
18 printf("#endif\n");
19 return(0);
20}
diff --git a/arch/um/sys-x86_64/util/mk_thread_kern.c b/arch/um/sys-x86_64/util/mk_thread_kern.c
deleted file mode 100644
index a281673f02b2..000000000000
--- a/arch/um/sys-x86_64/util/mk_thread_kern.c
+++ /dev/null
@@ -1,21 +0,0 @@
1#include "linux/config.h"
2#include "linux/stddef.h"
3#include "linux/sched.h"
4
5extern void print_head(void);
6extern void print_constant_ptr(char *name, int value);
7extern void print_constant(char *name, char *type, int value);
8extern void print_tail(void);
9
10#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field)
11
12int main(int argc, char **argv)
13{
14 print_head();
15#ifdef CONFIG_MODE_TT
16 print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid));
17#endif
18 print_tail();
19 return(0);
20}
21
diff --git a/arch/um/sys-x86_64/util/mk_thread_user.c b/arch/um/sys-x86_64/util/mk_thread_user.c
deleted file mode 100644
index 7989725568b8..000000000000
--- a/arch/um/sys-x86_64/util/mk_thread_user.c
+++ /dev/null
@@ -1,30 +0,0 @@
1#include <stdio.h>
2
3void print_head(void)
4{
5 printf("/*\n");
6 printf(" * Generated by mk_thread\n");
7 printf(" */\n");
8 printf("\n");
9 printf("#ifndef __UM_THREAD_H\n");
10 printf("#define __UM_THREAD_H\n");
11 printf("\n");
12}
13
14void print_constant_ptr(char *name, int value)
15{
16 printf("#define %s(task) ((unsigned long *) "
17 "&(((char *) (task))[%d]))\n", name, value);
18}
19
20void print_constant(char *name, char *type, int value)
21{
22 printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
23 value);
24}
25
26void print_tail(void)
27{
28 printf("\n");
29 printf("#endif\n");
30}
diff --git a/arch/um/util/Makefile b/arch/um/util/Makefile
index e2ab71209f3f..4c7551c28033 100644
--- a/arch/um/util/Makefile
+++ b/arch/um/util/Makefile
@@ -1,8 +1,5 @@
1hostprogs-y := mk_task mk_constants 1hostprogs-y := mk_task mk_constants
2always := $(hostprogs-y) 2always := $(hostprogs-y)
3 3
4mk_task-objs := mk_task_user.o mk_task_kern.o 4HOSTCFLAGS_mk_task.o := -I$(objtree)/arch/um
5mk_constants-objs := mk_constants_user.o mk_constants_kern.o 5HOSTCFLAGS_mk_constants.o := -I$(objtree)/arch/um
6
7HOSTCFLAGS_mk_task_kern.o := $(CFLAGS) $(CPPFLAGS)
8HOSTCFLAGS_mk_constants_kern.o := $(CFLAGS) $(CPPFLAGS)
diff --git a/arch/um/util/mk_constants.c b/arch/um/util/mk_constants.c
new file mode 100644
index 000000000000..ab217becc36a
--- /dev/null
+++ b/arch/um/util/mk_constants.c
@@ -0,0 +1,32 @@
1#include <stdio.h>
2#include <kernel-offsets.h>
3
4#define SHOW_INT(sym) printf("#define %s %d\n", #sym, sym)
5#define SHOW_STR(sym) printf("#define %s %s\n", #sym, sym)
6
7int main(int argc, char **argv)
8{
9 printf("/*\n");
10 printf(" * Generated by mk_constants\n");
11 printf(" */\n");
12 printf("\n");
13 printf("#ifndef __UM_CONSTANTS_H\n");
14 printf("#define __UM_CONSTANTS_H\n");
15 printf("\n");
16
17 SHOW_INT(UM_KERN_PAGE_SIZE);
18
19 SHOW_STR(UM_KERN_EMERG);
20 SHOW_STR(UM_KERN_ALERT);
21 SHOW_STR(UM_KERN_CRIT);
22 SHOW_STR(UM_KERN_ERR);
23 SHOW_STR(UM_KERN_WARNING);
24 SHOW_STR(UM_KERN_NOTICE);
25 SHOW_STR(UM_KERN_INFO);
26 SHOW_STR(UM_KERN_DEBUG);
27
28 SHOW_INT(UM_NSEC_PER_SEC);
29 printf("\n");
30 printf("#endif\n");
31 return(0);
32}
diff --git a/arch/um/util/mk_constants_kern.c b/arch/um/util/mk_constants_kern.c
deleted file mode 100644
index cdcb1232a1ea..000000000000
--- a/arch/um/util/mk_constants_kern.c
+++ /dev/null
@@ -1,28 +0,0 @@
1#include "linux/kernel.h"
2#include "linux/stringify.h"
3#include "linux/time.h"
4#include "asm/page.h"
5
6extern void print_head(void);
7extern void print_constant_str(char *name, char *value);
8extern void print_constant_int(char *name, int value);
9extern void print_tail(void);
10
11int main(int argc, char **argv)
12{
13 print_head();
14 print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
15
16 print_constant_str("UM_KERN_EMERG", KERN_EMERG);
17 print_constant_str("UM_KERN_ALERT", KERN_ALERT);
18 print_constant_str("UM_KERN_CRIT", KERN_CRIT);
19 print_constant_str("UM_KERN_ERR", KERN_ERR);
20 print_constant_str("UM_KERN_WARNING", KERN_WARNING);
21 print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
22 print_constant_str("UM_KERN_INFO", KERN_INFO);
23 print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
24
25 print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC);
26 print_tail();
27 return(0);
28}
diff --git a/arch/um/util/mk_constants_user.c b/arch/um/util/mk_constants_user.c
deleted file mode 100644
index 8f4d7e50be7c..000000000000
--- a/arch/um/util/mk_constants_user.c
+++ /dev/null
@@ -1,28 +0,0 @@
1#include <stdio.h>
2
3void print_head(void)
4{
5 printf("/*\n");
6 printf(" * Generated by mk_constants\n");
7 printf(" */\n");
8 printf("\n");
9 printf("#ifndef __UM_CONSTANTS_H\n");
10 printf("#define __UM_CONSTANTS_H\n");
11 printf("\n");
12}
13
14void print_constant_str(char *name, char *value)
15{
16 printf("#define %s \"%s\"\n", name, value);
17}
18
19void print_constant_int(char *name, int value)
20{
21 printf("#define %s %d\n", name, value);
22}
23
24void print_tail(void)
25{
26 printf("\n");
27 printf("#endif\n");
28}
diff --git a/arch/um/util/mk_task_user.c b/arch/um/util/mk_task.c
index 9db849f3f3ac..36c9606505e2 100644
--- a/arch/um/util/mk_task_user.c
+++ b/arch/um/util/mk_task.c
@@ -1,18 +1,19 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <kernel-offsets.h>
2 3
3void print(char *name, char *type, int offset) 4void print_ptr(char *name, char *type, int offset)
4{ 5{
5 printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, 6 printf("#define %s(task) ((%s *) &(((char *) (task))[%d]))\n", name, type,
6 offset); 7 offset);
7} 8}
8 9
9void print_ptr(char *name, char *type, int offset) 10void print(char *name, char *type, int offset)
10{ 11{
11 printf("#define %s(task) ((%s *) &(((char *) (task))[%d]))\n", name, type, 12 printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
12 offset); 13 offset);
13} 14}
14 15
15void print_head(void) 16int main(int argc, char **argv)
16{ 17{
17 printf("/*\n"); 18 printf("/*\n");
18 printf(" * Generated by mk_task\n"); 19 printf(" * Generated by mk_task\n");
@@ -21,10 +22,9 @@ void print_head(void)
21 printf("#ifndef __TASK_H\n"); 22 printf("#ifndef __TASK_H\n");
22 printf("#define __TASK_H\n"); 23 printf("#define __TASK_H\n");
23 printf("\n"); 24 printf("\n");
24} 25 print_ptr("TASK_REGS", "union uml_pt_regs", TASK_REGS);
25 26 print("TASK_PID", "int", TASK_PID);
26void print_tail(void)
27{
28 printf("\n"); 27 printf("\n");
29 printf("#endif\n"); 28 printf("#endif\n");
29 return(0);
30} 30}
diff --git a/arch/um/util/mk_task_kern.c b/arch/um/util/mk_task_kern.c
deleted file mode 100644
index c218103315ed..000000000000
--- a/arch/um/util/mk_task_kern.c
+++ /dev/null
@@ -1,17 +0,0 @@
1#include "linux/sched.h"
2#include "linux/stddef.h"
3
4extern void print(char *name, char *type, int offset);
5extern void print_ptr(char *name, char *type, int offset);
6extern void print_head(void);
7extern void print_tail(void);
8
9int main(int argc, char **argv)
10{
11 print_head();
12 print_ptr("TASK_REGS", "union uml_pt_regs",
13 offsetof(struct task_struct, thread.regs));
14 print("TASK_PID", "int", offsetof(struct task_struct, pid));
15 print_tail();
16 return(0);
17}
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 44ee7f6acf7b..289f448ac89c 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -303,6 +303,21 @@ config HPET_TIMER
303 as it is off-chip. You can find the HPET spec at 303 as it is off-chip. You can find the HPET spec at
304 <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>. 304 <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>.
305 305
306config X86_PM_TIMER
307 bool "PM timer"
308 depends on ACPI
309 default y
310 help
311 Support the ACPI PM timer for time keeping. This is slow,
312 but is useful on some chipsets without HPET on systems with more
313 than one CPU. On a single processor or single socket multi core
314 system it is normally not required.
315 When the PM timer is active 64bit vsyscalls are disabled
316 and should not be enabled (/proc/sys/kernel/vsyscall64 should
317 not be changed).
318 The kernel selects the PM timer only as a last resort, so it is
319 useful to enable just in case.
320
306config HPET_EMULATE_RTC 321config HPET_EMULATE_RTC
307 bool "Provide RTC interrupt" 322 bool "Provide RTC interrupt"
308 depends on HPET_TIMER && RTC=y 323 depends on HPET_TIMER && RTC=y
@@ -407,7 +422,7 @@ config PCI_DIRECT
407 422
408config PCI_MMCONFIG 423config PCI_MMCONFIG
409 bool "Support mmconfig PCI config space access" 424 bool "Support mmconfig PCI config space access"
410 depends on PCI 425 depends on PCI && ACPI
411 select ACPI_BOOT 426 select ACPI_BOOT
412 427
413config UNORDERED_IO 428config UNORDERED_IO
diff --git a/arch/x86_64/boot/bootsect.S b/arch/x86_64/boot/bootsect.S
index bb15d406ee95..011b7a4993d4 100644
--- a/arch/x86_64/boot/bootsect.S
+++ b/arch/x86_64/boot/bootsect.S
@@ -63,7 +63,7 @@ msg_loop:
63 jz die 63 jz die
64 movb $0xe, %ah 64 movb $0xe, %ah
65 movw $7, %bx 65 movw $7, %bx
66 int $0x10 66 int $0x10
67 jmp msg_loop 67 jmp msg_loop
68 68
69die: 69die:
@@ -71,7 +71,7 @@ die:
71 xorw %ax, %ax 71 xorw %ax, %ax
72 int $0x16 72 int $0x16
73 int $0x19 73 int $0x19
74 74
75 # int 0x19 should never return. In case it does anyway, 75 # int 0x19 should never return. In case it does anyway,
76 # invoke the BIOS reset code... 76 # invoke the BIOS reset code...
77 ljmp $0xf000,$0xfff0 77 ljmp $0xf000,$0xfff0
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 9ce51dee30b3..569595b74c7c 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.11-bk7 3# Linux kernel version: 2.6.12-rc4
4# Sat Mar 12 23:43:44 2005 4# Fri May 13 06:39:11 2005
5# 5#
6CONFIG_X86_64=y 6CONFIG_X86_64=y
7CONFIG_64BIT=y 7CONFIG_64BIT=y
@@ -11,8 +11,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
11CONFIG_GENERIC_CALIBRATE_DELAY=y 11CONFIG_GENERIC_CALIBRATE_DELAY=y
12CONFIG_X86_CMPXCHG=y 12CONFIG_X86_CMPXCHG=y
13CONFIG_EARLY_PRINTK=y 13CONFIG_EARLY_PRINTK=y
14CONFIG_HPET_TIMER=y
15CONFIG_HPET_EMULATE_RTC=y
16CONFIG_GENERIC_ISA_DMA=y 14CONFIG_GENERIC_ISA_DMA=y
17CONFIG_GENERIC_IOMAP=y 15CONFIG_GENERIC_IOMAP=y
18 16
@@ -22,6 +20,7 @@ CONFIG_GENERIC_IOMAP=y
22CONFIG_EXPERIMENTAL=y 20CONFIG_EXPERIMENTAL=y
23CONFIG_CLEAN_COMPILE=y 21CONFIG_CLEAN_COMPILE=y
24CONFIG_LOCK_KERNEL=y 22CONFIG_LOCK_KERNEL=y
23CONFIG_INIT_ENV_ARG_LIMIT=32
25 24
26# 25#
27# General setup 26# General setup
@@ -33,7 +32,6 @@ CONFIG_POSIX_MQUEUE=y
33# CONFIG_BSD_PROCESS_ACCT is not set 32# CONFIG_BSD_PROCESS_ACCT is not set
34CONFIG_SYSCTL=y 33CONFIG_SYSCTL=y
35# CONFIG_AUDIT is not set 34# CONFIG_AUDIT is not set
36CONFIG_LOG_BUF_SHIFT=18
37# CONFIG_HOTPLUG is not set 35# CONFIG_HOTPLUG is not set
38CONFIG_KOBJECT_UEVENT=y 36CONFIG_KOBJECT_UEVENT=y
39CONFIG_IKCONFIG=y 37CONFIG_IKCONFIG=y
@@ -43,10 +41,11 @@ CONFIG_IKCONFIG_PROC=y
43CONFIG_KALLSYMS=y 41CONFIG_KALLSYMS=y
44CONFIG_KALLSYMS_ALL=y 42CONFIG_KALLSYMS_ALL=y
45# CONFIG_KALLSYMS_EXTRA_PASS is not set 43# CONFIG_KALLSYMS_EXTRA_PASS is not set
44CONFIG_PRINTK=y
45CONFIG_BUG=y
46CONFIG_BASE_FULL=y 46CONFIG_BASE_FULL=y
47CONFIG_FUTEX=y 47CONFIG_FUTEX=y
48CONFIG_EPOLL=y 48CONFIG_EPOLL=y
49# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
50CONFIG_SHMEM=y 49CONFIG_SHMEM=y
51CONFIG_CC_ALIGN_FUNCTIONS=0 50CONFIG_CC_ALIGN_FUNCTIONS=0
52CONFIG_CC_ALIGN_LABELS=0 51CONFIG_CC_ALIGN_LABELS=0
@@ -93,6 +92,9 @@ CONFIG_DISCONTIGMEM=y
93CONFIG_NUMA=y 92CONFIG_NUMA=y
94CONFIG_HAVE_DEC_LOCK=y 93CONFIG_HAVE_DEC_LOCK=y
95CONFIG_NR_CPUS=8 94CONFIG_NR_CPUS=8
95CONFIG_HPET_TIMER=y
96CONFIG_X86_PM_TIMER=y
97CONFIG_HPET_EMULATE_RTC=y
96CONFIG_GART_IOMMU=y 98CONFIG_GART_IOMMU=y
97CONFIG_SWIOTLB=y 99CONFIG_SWIOTLB=y
98CONFIG_X86_MCE=y 100CONFIG_X86_MCE=y
@@ -100,6 +102,7 @@ CONFIG_X86_MCE_INTEL=y
100CONFIG_SECCOMP=y 102CONFIG_SECCOMP=y
101CONFIG_GENERIC_HARDIRQS=y 103CONFIG_GENERIC_HARDIRQS=y
102CONFIG_GENERIC_IRQ_PROBE=y 104CONFIG_GENERIC_IRQ_PROBE=y
105CONFIG_ISA_DMA_API=y
103 106
104# 107#
105# Power management options 108# Power management options
@@ -129,7 +132,7 @@ CONFIG_ACPI_NUMA=y
129# CONFIG_ACPI_IBM is not set 132# CONFIG_ACPI_IBM is not set
130CONFIG_ACPI_TOSHIBA=y 133CONFIG_ACPI_TOSHIBA=y
131CONFIG_ACPI_BLACKLIST_YEAR=2001 134CONFIG_ACPI_BLACKLIST_YEAR=2001
132CONFIG_ACPI_DEBUG=y 135# CONFIG_ACPI_DEBUG is not set
133CONFIG_ACPI_BUS=y 136CONFIG_ACPI_BUS=y
134CONFIG_ACPI_EC=y 137CONFIG_ACPI_EC=y
135CONFIG_ACPI_POWER=y 138CONFIG_ACPI_POWER=y
@@ -141,6 +144,7 @@ CONFIG_ACPI_SYSTEM=y
141# CPU Frequency scaling 144# CPU Frequency scaling
142# 145#
143CONFIG_CPU_FREQ=y 146CONFIG_CPU_FREQ=y
147CONFIG_CPU_FREQ_TABLE=y
144# CONFIG_CPU_FREQ_DEBUG is not set 148# CONFIG_CPU_FREQ_DEBUG is not set
145CONFIG_CPU_FREQ_STAT=y 149CONFIG_CPU_FREQ_STAT=y
146# CONFIG_CPU_FREQ_STAT_DETAILS is not set 150# CONFIG_CPU_FREQ_STAT_DETAILS is not set
@@ -150,7 +154,6 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
150# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set 154# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
151CONFIG_CPU_FREQ_GOV_USERSPACE=y 155CONFIG_CPU_FREQ_GOV_USERSPACE=y
152CONFIG_CPU_FREQ_GOV_ONDEMAND=y 156CONFIG_CPU_FREQ_GOV_ONDEMAND=y
153CONFIG_CPU_FREQ_TABLE=y
154 157
155# 158#
156# CPUFreq processor drivers 159# CPUFreq processor drivers
@@ -164,6 +167,7 @@ CONFIG_X86_ACPI_CPUFREQ=y
164# shared options 167# shared options
165# 168#
166CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y 169CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
170# CONFIG_X86_SPEEDSTEP_LIB is not set
167 171
168# 172#
169# Bus options (PCI etc.) 173# Bus options (PCI etc.)
@@ -172,9 +176,11 @@ CONFIG_PCI=y
172CONFIG_PCI_DIRECT=y 176CONFIG_PCI_DIRECT=y
173CONFIG_PCI_MMCONFIG=y 177CONFIG_PCI_MMCONFIG=y
174CONFIG_UNORDERED_IO=y 178CONFIG_UNORDERED_IO=y
179# CONFIG_PCIEPORTBUS is not set
175CONFIG_PCI_MSI=y 180CONFIG_PCI_MSI=y
176# CONFIG_PCI_LEGACY_PROC is not set 181# CONFIG_PCI_LEGACY_PROC is not set
177# CONFIG_PCI_NAMES is not set 182# CONFIG_PCI_NAMES is not set
183# CONFIG_PCI_DEBUG is not set
178 184
179# 185#
180# PCCARD (PCMCIA/CardBus) support 186# PCCARD (PCMCIA/CardBus) support
@@ -182,10 +188,6 @@ CONFIG_PCI_MSI=y
182# CONFIG_PCCARD is not set 188# CONFIG_PCCARD is not set
183 189
184# 190#
185# PC-card bridges
186#
187
188#
189# PCI Hotplug Support 191# PCI Hotplug Support
190# 192#
191# CONFIG_HOTPLUG_PCI is not set 193# CONFIG_HOTPLUG_PCI is not set
@@ -254,7 +256,7 @@ CONFIG_LBD=y
254# IO Schedulers 256# IO Schedulers
255# 257#
256CONFIG_IOSCHED_NOOP=y 258CONFIG_IOSCHED_NOOP=y
257CONFIG_IOSCHED_AS=y 259# CONFIG_IOSCHED_AS is not set
258CONFIG_IOSCHED_DEADLINE=y 260CONFIG_IOSCHED_DEADLINE=y
259CONFIG_IOSCHED_CFQ=y 261CONFIG_IOSCHED_CFQ=y
260# CONFIG_ATA_OVER_ETH is not set 262# CONFIG_ATA_OVER_ETH is not set
@@ -308,7 +310,8 @@ CONFIG_BLK_DEV_AMD74XX=y
308CONFIG_BLK_DEV_PIIX=y 310CONFIG_BLK_DEV_PIIX=y
309# CONFIG_BLK_DEV_NS87415 is not set 311# CONFIG_BLK_DEV_NS87415 is not set
310# CONFIG_BLK_DEV_PDC202XX_OLD is not set 312# CONFIG_BLK_DEV_PDC202XX_OLD is not set
311# CONFIG_BLK_DEV_PDC202XX_NEW is not set 313CONFIG_BLK_DEV_PDC202XX_NEW=y
314# CONFIG_PDC202XX_FORCE is not set
312# CONFIG_BLK_DEV_SVWKS is not set 315# CONFIG_BLK_DEV_SVWKS is not set
313# CONFIG_BLK_DEV_SIIMAGE is not set 316# CONFIG_BLK_DEV_SIIMAGE is not set
314# CONFIG_BLK_DEV_SIS5513 is not set 317# CONFIG_BLK_DEV_SIS5513 is not set
@@ -353,7 +356,7 @@ CONFIG_BLK_DEV_SD=y
353# 356#
354# SCSI low-level drivers 357# SCSI low-level drivers
355# 358#
356CONFIG_BLK_DEV_3W_XXXX_RAID=y 359# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
357# CONFIG_SCSI_3W_9XXX is not set 360# CONFIG_SCSI_3W_9XXX is not set
358# CONFIG_SCSI_ACARD is not set 361# CONFIG_SCSI_ACARD is not set
359# CONFIG_SCSI_AACRAID is not set 362# CONFIG_SCSI_AACRAID is not set
@@ -384,7 +387,6 @@ CONFIG_SCSI_SATA_VIA=y
384# CONFIG_SCSI_BUSLOGIC is not set 387# CONFIG_SCSI_BUSLOGIC is not set
385# CONFIG_SCSI_DMX3191D is not set 388# CONFIG_SCSI_DMX3191D is not set
386# CONFIG_SCSI_EATA is not set 389# CONFIG_SCSI_EATA is not set
387# CONFIG_SCSI_EATA_PIO is not set
388# CONFIG_SCSI_FUTURE_DOMAIN is not set 390# CONFIG_SCSI_FUTURE_DOMAIN is not set
389# CONFIG_SCSI_GDTH is not set 391# CONFIG_SCSI_GDTH is not set
390# CONFIG_SCSI_IPS is not set 392# CONFIG_SCSI_IPS is not set
@@ -392,7 +394,6 @@ CONFIG_SCSI_SATA_VIA=y
392# CONFIG_SCSI_INIA100 is not set 394# CONFIG_SCSI_INIA100 is not set
393# CONFIG_SCSI_SYM53C8XX_2 is not set 395# CONFIG_SCSI_SYM53C8XX_2 is not set
394# CONFIG_SCSI_IPR is not set 396# CONFIG_SCSI_IPR is not set
395# CONFIG_SCSI_QLOGIC_ISP is not set
396# CONFIG_SCSI_QLOGIC_FC is not set 397# CONFIG_SCSI_QLOGIC_FC is not set
397# CONFIG_SCSI_QLOGIC_1280 is not set 398# CONFIG_SCSI_QLOGIC_1280 is not set
398CONFIG_SCSI_QLA2XXX=y 399CONFIG_SCSI_QLA2XXX=y
@@ -401,6 +402,7 @@ CONFIG_SCSI_QLA2XXX=y
401# CONFIG_SCSI_QLA2300 is not set 402# CONFIG_SCSI_QLA2300 is not set
402# CONFIG_SCSI_QLA2322 is not set 403# CONFIG_SCSI_QLA2322 is not set
403# CONFIG_SCSI_QLA6312 is not set 404# CONFIG_SCSI_QLA6312 is not set
405# CONFIG_SCSI_LPFC is not set
404# CONFIG_SCSI_DC395x is not set 406# CONFIG_SCSI_DC395x is not set
405# CONFIG_SCSI_DC390T is not set 407# CONFIG_SCSI_DC390T is not set
406# CONFIG_SCSI_DEBUG is not set 408# CONFIG_SCSI_DEBUG is not set
@@ -437,7 +439,6 @@ CONFIG_NET=y
437# 439#
438CONFIG_PACKET=y 440CONFIG_PACKET=y
439# CONFIG_PACKET_MMAP is not set 441# CONFIG_PACKET_MMAP is not set
440# CONFIG_NETLINK_DEV is not set
441CONFIG_UNIX=y 442CONFIG_UNIX=y
442# CONFIG_NET_KEY is not set 443# CONFIG_NET_KEY is not set
443CONFIG_INET=y 444CONFIG_INET=y
@@ -502,7 +503,7 @@ CONFIG_NETDEVICES=y
502# CONFIG_DUMMY is not set 503# CONFIG_DUMMY is not set
503# CONFIG_BONDING is not set 504# CONFIG_BONDING is not set
504# CONFIG_EQUALIZER is not set 505# CONFIG_EQUALIZER is not set
505# CONFIG_TUN is not set 506CONFIG_TUN=y
506 507
507# 508#
508# ARCnet devices 509# ARCnet devices
@@ -525,8 +526,7 @@ CONFIG_MII=y
525# CONFIG_HP100 is not set 526# CONFIG_HP100 is not set
526CONFIG_NET_PCI=y 527CONFIG_NET_PCI=y
527# CONFIG_PCNET32 is not set 528# CONFIG_PCNET32 is not set
528CONFIG_AMD8111_ETH=y 529# CONFIG_AMD8111_ETH is not set
529# CONFIG_AMD8111E_NAPI is not set
530# CONFIG_ADAPTEC_STARFIRE is not set 530# CONFIG_ADAPTEC_STARFIRE is not set
531# CONFIG_B44 is not set 531# CONFIG_B44 is not set
532CONFIG_FORCEDETH=y 532CONFIG_FORCEDETH=y
@@ -536,7 +536,7 @@ CONFIG_FORCEDETH=y
536# CONFIG_FEALNX is not set 536# CONFIG_FEALNX is not set
537# CONFIG_NATSEMI is not set 537# CONFIG_NATSEMI is not set
538# CONFIG_NE2K_PCI is not set 538# CONFIG_NE2K_PCI is not set
539CONFIG_8139CP=m 539CONFIG_8139CP=y
540CONFIG_8139TOO=y 540CONFIG_8139TOO=y
541# CONFIG_8139TOO_PIO is not set 541# CONFIG_8139TOO_PIO is not set
542# CONFIG_8139TOO_TUNE_TWISTER is not set 542# CONFIG_8139TOO_TUNE_TWISTER is not set
@@ -671,6 +671,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
671# 671#
672CONFIG_SERIAL_CORE=y 672CONFIG_SERIAL_CORE=y
673CONFIG_SERIAL_CORE_CONSOLE=y 673CONFIG_SERIAL_CORE_CONSOLE=y
674# CONFIG_SERIAL_JSM is not set
674CONFIG_UNIX98_PTYS=y 675CONFIG_UNIX98_PTYS=y
675CONFIG_LEGACY_PTYS=y 676CONFIG_LEGACY_PTYS=y
676CONFIG_LEGACY_PTY_COUNT=256 677CONFIG_LEGACY_PTY_COUNT=256
@@ -696,6 +697,7 @@ CONFIG_RTC=y
696# 697#
697CONFIG_AGP=y 698CONFIG_AGP=y
698CONFIG_AGP_AMD64=y 699CONFIG_AGP_AMD64=y
700CONFIG_AGP_INTEL=y
699# CONFIG_DRM is not set 701# CONFIG_DRM is not set
700# CONFIG_MWAVE is not set 702# CONFIG_MWAVE is not set
701CONFIG_RAW_DRIVER=y 703CONFIG_RAW_DRIVER=y
@@ -703,7 +705,7 @@ CONFIG_HPET=y
703# CONFIG_HPET_RTC_IRQ is not set 705# CONFIG_HPET_RTC_IRQ is not set
704CONFIG_HPET_MMAP=y 706CONFIG_HPET_MMAP=y
705CONFIG_MAX_RAW_DEVS=256 707CONFIG_MAX_RAW_DEVS=256
706CONFIG_HANGCHECK_TIMER=y 708# CONFIG_HANGCHECK_TIMER is not set
707 709
708# 710#
709# TPM devices 711# TPM devices
@@ -786,6 +788,8 @@ CONFIG_SOUND_ICH=y
786# 788#
787# USB support 789# USB support
788# 790#
791CONFIG_USB_ARCH_HAS_HCD=y
792CONFIG_USB_ARCH_HAS_OHCI=y
789CONFIG_USB=y 793CONFIG_USB=y
790# CONFIG_USB_DEBUG is not set 794# CONFIG_USB_DEBUG is not set
791 795
@@ -797,8 +801,6 @@ CONFIG_USB_DEVICEFS=y
797# CONFIG_USB_DYNAMIC_MINORS is not set 801# CONFIG_USB_DYNAMIC_MINORS is not set
798# CONFIG_USB_SUSPEND is not set 802# CONFIG_USB_SUSPEND is not set
799# CONFIG_USB_OTG is not set 803# CONFIG_USB_OTG is not set
800CONFIG_USB_ARCH_HAS_HCD=y
801CONFIG_USB_ARCH_HAS_OHCI=y
802 804
803# 805#
804# USB Host Controller Drivers 806# USB Host Controller Drivers
@@ -826,7 +828,6 @@ CONFIG_USB_PRINTER=y
826# 828#
827CONFIG_USB_STORAGE=y 829CONFIG_USB_STORAGE=y
828# CONFIG_USB_STORAGE_DEBUG is not set 830# CONFIG_USB_STORAGE_DEBUG is not set
829# CONFIG_USB_STORAGE_RW_DETECT is not set
830# CONFIG_USB_STORAGE_DATAFAB is not set 831# CONFIG_USB_STORAGE_DATAFAB is not set
831# CONFIG_USB_STORAGE_FREECOM is not set 832# CONFIG_USB_STORAGE_FREECOM is not set
832# CONFIG_USB_STORAGE_ISD200 is not set 833# CONFIG_USB_STORAGE_ISD200 is not set
@@ -965,7 +966,7 @@ CONFIG_AUTOFS_FS=y
965# CD-ROM/DVD Filesystems 966# CD-ROM/DVD Filesystems
966# 967#
967CONFIG_ISO9660_FS=y 968CONFIG_ISO9660_FS=y
968# CONFIG_JOLIET is not set 969CONFIG_JOLIET=y
969# CONFIG_ZISOFS is not set 970# CONFIG_ZISOFS is not set
970# CONFIG_UDF_FS is not set 971# CONFIG_UDF_FS is not set
971 972
@@ -1092,9 +1093,10 @@ CONFIG_OPROFILE=y
1092# 1093#
1093# Kernel hacking 1094# Kernel hacking
1094# 1095#
1096# CONFIG_PRINTK_TIME is not set
1095CONFIG_DEBUG_KERNEL=y 1097CONFIG_DEBUG_KERNEL=y
1096CONFIG_MAGIC_SYSRQ=y 1098CONFIG_MAGIC_SYSRQ=y
1097# CONFIG_PRINTK_TIME is not set 1099CONFIG_LOG_BUF_SHIFT=18
1098# CONFIG_SCHEDSTATS is not set 1100# CONFIG_SCHEDSTATS is not set
1099# CONFIG_DEBUG_SLAB is not set 1101# CONFIG_DEBUG_SLAB is not set
1100# CONFIG_DEBUG_SPINLOCK is not set 1102# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index 0a3318e08ab6..5ca4a4598fda 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
28obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o 28obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o
29obj-$(CONFIG_SWIOTLB) += swiotlb.o 29obj-$(CONFIG_SWIOTLB) += swiotlb.o
30obj-$(CONFIG_KPROBES) += kprobes.o 30obj-$(CONFIG_KPROBES) += kprobes.o
31obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
31 32
32obj-$(CONFIG_MODULES) += module.o 33obj-$(CONFIG_MODULES) += module.o
33 34
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 7e13545748e0..f8e6cc4fecd4 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -33,6 +33,7 @@
33#include <asm/mpspec.h> 33#include <asm/mpspec.h>
34#include <asm/pgalloc.h> 34#include <asm/pgalloc.h>
35#include <asm/mach_apic.h> 35#include <asm/mach_apic.h>
36#include <asm/nmi.h>
36 37
37int apic_verbosity; 38int apic_verbosity;
38 39
@@ -925,7 +926,7 @@ __init int oem_force_hpet_timer(void)
925 unsigned id; 926 unsigned id;
926 DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); 927 DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
927 928
928 bitmap_empty(clustermap, NUM_APIC_CLUSTERS); 929 bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
929 930
930 for (i = 0; i < NR_CPUS; i++) { 931 for (i = 0; i < NR_CPUS; i++) {
931 id = bios_cpu_apicid[i]; 932 id = bios_cpu_apicid[i];
@@ -1056,7 +1057,7 @@ int __init APIC_init_uniprocessor (void)
1056 nr_ioapics = 0; 1057 nr_ioapics = 0;
1057#endif 1058#endif
1058 setup_boot_APIC_clock(); 1059 setup_boot_APIC_clock();
1059 1060 check_nmi_watchdog();
1060 return 0; 1061 return 0;
1061} 1062}
1062 1063
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 1086b5fcac21..28817490fdc6 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -220,13 +220,18 @@ sysret_careful:
220 jmp sysret_check 220 jmp sysret_check
221 221
222 /* Handle a signal */ 222 /* Handle a signal */
223 /* edx: work flags (arg3) */
224sysret_signal: 223sysret_signal:
225 sti 224 sti
225 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
226 jz 1f
227
228 /* Really a signal */
229 /* edx: work flags (arg3) */
226 leaq do_notify_resume(%rip),%rax 230 leaq do_notify_resume(%rip),%rax
227 leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1 231 leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
228 xorl %esi,%esi # oldset -> arg2 232 xorl %esi,%esi # oldset -> arg2
229 call ptregscall_common 233 call ptregscall_common
2341: movl $_TIF_NEED_RESCHED,%edi
230 jmp sysret_check 235 jmp sysret_check
231 236
232 /* Do syscall tracing */ 237 /* Do syscall tracing */
@@ -484,6 +489,8 @@ retint_careful:
484 jmp retint_check 489 jmp retint_check
485 490
486retint_signal: 491retint_signal:
492 testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
493 jz retint_swapgs
487 sti 494 sti
488 SAVE_REST 495 SAVE_REST
489 movq $-1,ORIG_RAX(%rsp) 496 movq $-1,ORIG_RAX(%rsp)
@@ -492,8 +499,8 @@ retint_signal:
492 call do_notify_resume 499 call do_notify_resume
493 RESTORE_REST 500 RESTORE_REST
494 cli 501 cli
502 movl $_TIF_NEED_RESCHED,%edi
495 GET_THREAD_INFO(%rcx) 503 GET_THREAD_INFO(%rcx)
496 movl $_TIF_WORK_MASK,%edi
497 jmp retint_check 504 jmp retint_check
498 505
499#ifdef CONFIG_PREEMPT 506#ifdef CONFIG_PREEMPT
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 60be58617eb9..afd87e64d0a8 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -37,11 +37,14 @@
37#include <asm/desc.h> 37#include <asm/desc.h>
38#include <asm/proto.h> 38#include <asm/proto.h>
39#include <asm/mach_apic.h> 39#include <asm/mach_apic.h>
40#include <asm/acpi.h>
40 41
41#define __apicdebuginit __init 42#define __apicdebuginit __init
42 43
43int sis_apic_bug; /* not actually supported, dummy for compile */ 44int sis_apic_bug; /* not actually supported, dummy for compile */
44 45
46static int no_timer_check;
47
45static DEFINE_SPINLOCK(ioapic_lock); 48static DEFINE_SPINLOCK(ioapic_lock);
46 49
47/* 50/*
@@ -1601,7 +1604,7 @@ static inline void check_timer(void)
1601 * Ok, does IRQ0 through the IOAPIC work? 1604 * Ok, does IRQ0 through the IOAPIC work?
1602 */ 1605 */
1603 unmask_IO_APIC_irq(0); 1606 unmask_IO_APIC_irq(0);
1604 if (timer_irq_works()) { 1607 if (!no_timer_check && timer_irq_works()) {
1605 nmi_watchdog_default(); 1608 nmi_watchdog_default();
1606 if (nmi_watchdog == NMI_IO_APIC) { 1609 if (nmi_watchdog == NMI_IO_APIC) {
1607 disable_8259A_irq(0); 1610 disable_8259A_irq(0);
@@ -1671,6 +1674,13 @@ static inline void check_timer(void)
1671 panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n"); 1674 panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
1672} 1675}
1673 1676
1677static int __init notimercheck(char *s)
1678{
1679 no_timer_check = 1;
1680 return 1;
1681}
1682__setup("no_timer_check", notimercheck);
1683
1674/* 1684/*
1675 * 1685 *
1676 * IRQ's that are handled by the PIC in the MPS IOAPIC case. 1686 * IRQ's that are handled by the PIC in the MPS IOAPIC case.
@@ -1804,76 +1814,6 @@ device_initcall(ioapic_init_sysfs);
1804 1814
1805#define IO_APIC_MAX_ID 0xFE 1815#define IO_APIC_MAX_ID 0xFE
1806 1816
1807int __init io_apic_get_unique_id (int ioapic, int apic_id)
1808{
1809 union IO_APIC_reg_00 reg_00;
1810 static physid_mask_t apic_id_map;
1811 unsigned long flags;
1812 int i = 0;
1813
1814 /*
1815 * The P4 platform supports up to 256 APIC IDs on two separate APIC
1816 * buses (one for LAPICs, one for IOAPICs), where predecessors only
1817 * supports up to 16 on one shared APIC bus.
1818 *
1819 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
1820 * advantage of new APIC bus architecture.
1821 */
1822
1823 if (physids_empty(apic_id_map))
1824 apic_id_map = phys_cpu_present_map;
1825
1826 spin_lock_irqsave(&ioapic_lock, flags);
1827 reg_00.raw = io_apic_read(ioapic, 0);
1828 spin_unlock_irqrestore(&ioapic_lock, flags);
1829
1830 if (apic_id >= IO_APIC_MAX_ID) {
1831 apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
1832 "%d\n", ioapic, apic_id, reg_00.bits.ID);
1833 apic_id = reg_00.bits.ID;
1834 }
1835
1836 /*
1837 * Every APIC in a system must have a unique ID or we get lots of nice
1838 * 'stuck on smp_invalidate_needed IPI wait' messages.
1839 */
1840 if (physid_isset(apic_id, apic_id_map)) {
1841
1842 for (i = 0; i < IO_APIC_MAX_ID; i++) {
1843 if (!physid_isset(i, apic_id_map))
1844 break;
1845 }
1846
1847 if (i == IO_APIC_MAX_ID)
1848 panic("Max apic_id exceeded!\n");
1849
1850 apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
1851 "trying %d\n", ioapic, apic_id, i);
1852
1853 apic_id = i;
1854 }
1855
1856 physid_set(apic_id, apic_id_map);
1857
1858 if (reg_00.bits.ID != apic_id) {
1859 reg_00.bits.ID = apic_id;
1860
1861 spin_lock_irqsave(&ioapic_lock, flags);
1862 io_apic_write(ioapic, 0, reg_00.raw);
1863 reg_00.raw = io_apic_read(ioapic, 0);
1864 spin_unlock_irqrestore(&ioapic_lock, flags);
1865
1866 /* Sanity check */
1867 if (reg_00.bits.ID != apic_id)
1868 panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
1869 }
1870
1871 apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
1872
1873 return apic_id;
1874}
1875
1876
1877int __init io_apic_get_version (int ioapic) 1817int __init io_apic_get_version (int ioapic)
1878{ 1818{
1879 union IO_APIC_reg_01 reg_01; 1819 union IO_APIC_reg_01 reg_01;
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 4f2a852299b6..f77f8a0ff187 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -355,6 +355,13 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs)
355 *tos &= ~(TF_MASK | IF_MASK); 355 *tos &= ~(TF_MASK | IF_MASK);
356 *tos |= kprobe_old_rflags; 356 *tos |= kprobe_old_rflags;
357 break; 357 break;
358 case 0xc3: /* ret/lret */
359 case 0xcb:
360 case 0xc2:
361 case 0xca:
362 regs->eflags &= ~TF_MASK;
363 /* rip is already adjusted, no more changes required*/
364 return;
358 case 0xe8: /* call relative - Fix return addr */ 365 case 0xe8: /* call relative - Fix return addr */
359 *tos = orig_rip + (*tos - copy_rip); 366 *tos = orig_rip + (*tos - copy_rip);
360 break; 367 break;
diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c
index c2ffea8845ed..bac195c74bcc 100644
--- a/arch/x86_64/kernel/module.c
+++ b/arch/x86_64/kernel/module.c
@@ -30,9 +30,12 @@
30 30
31#define DEBUGP(fmt...) 31#define DEBUGP(fmt...)
32 32
33#ifndef CONFIG_UML
33void module_free(struct module *mod, void *module_region) 34void module_free(struct module *mod, void *module_region)
34{ 35{
35 vfree(module_region); 36 vfree(module_region);
37 /* FIXME: If module_region == mod->init_region, trim exception
38 table entries. */
36} 39}
37 40
38void *module_alloc(unsigned long size) 41void *module_alloc(unsigned long size)
@@ -51,6 +54,7 @@ void *module_alloc(unsigned long size)
51 54
52 return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC); 55 return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
53} 56}
57#endif
54 58
55/* We don't need anything special. */ 59/* We don't need anything special. */
56int module_frob_arch_sections(Elf_Ehdr *hdr, 60int module_frob_arch_sections(Elf_Ehdr *hdr,
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 7ec031c6ca10..61a63be6b294 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -30,6 +30,7 @@
30#include <asm/pgalloc.h> 30#include <asm/pgalloc.h>
31#include <asm/io_apic.h> 31#include <asm/io_apic.h>
32#include <asm/proto.h> 32#include <asm/proto.h>
33#include <asm/acpi.h>
33 34
34/* Have we found an MP table */ 35/* Have we found an MP table */
35int smp_found_config; 36int smp_found_config;
@@ -107,6 +108,7 @@ static int __init mpf_checksum(unsigned char *mp, int len)
107static void __init MP_processor_info (struct mpc_config_processor *m) 108static void __init MP_processor_info (struct mpc_config_processor *m)
108{ 109{
109 int ver; 110 int ver;
111 static int found_bsp=0;
110 112
111 if (!(m->mpc_cpuflag & CPU_ENABLED)) 113 if (!(m->mpc_cpuflag & CPU_ENABLED))
112 return; 114 return;
@@ -126,11 +128,6 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
126 " Processor ignored.\n", NR_CPUS); 128 " Processor ignored.\n", NR_CPUS);
127 return; 129 return;
128 } 130 }
129 if (num_processors >= maxcpus) {
130 printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
131 " Processor ignored.\n", maxcpus);
132 return;
133 }
134 131
135 num_processors++; 132 num_processors++;
136 133
@@ -150,7 +147,19 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
150 ver = 0x10; 147 ver = 0x10;
151 } 148 }
152 apic_version[m->mpc_apicid] = ver; 149 apic_version[m->mpc_apicid] = ver;
153 bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; 150 if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
151 /*
152 * bios_cpu_apicid is required to have processors listed
153 * in same order as logical cpu numbers. Hence the first
154 * entry is BSP, and so on.
155 */
156 bios_cpu_apicid[0] = m->mpc_apicid;
157 x86_cpu_to_apicid[0] = m->mpc_apicid;
158 found_bsp = 1;
159 } else {
160 bios_cpu_apicid[num_processors - found_bsp] = m->mpc_apicid;
161 x86_cpu_to_apicid[num_processors - found_bsp] = m->mpc_apicid;
162 }
154} 163}
155 164
156static void __init MP_bus_info (struct mpc_config_bus *m) 165static void __init MP_bus_info (struct mpc_config_bus *m)
@@ -759,7 +768,7 @@ void __init mp_register_ioapic (
759 mp_ioapics[idx].mpc_apicaddr = address; 768 mp_ioapics[idx].mpc_apicaddr = address;
760 769
761 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); 770 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
762 mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); 771 mp_ioapics[idx].mpc_apicid = id;
763 mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); 772 mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
764 773
765 /* 774 /*
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 61de0b34a01e..31c0f2e6ac91 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -33,6 +33,7 @@
33#include <asm/msr.h> 33#include <asm/msr.h>
34#include <asm/proto.h> 34#include <asm/proto.h>
35#include <asm/kdebug.h> 35#include <asm/kdebug.h>
36#include <asm/local.h>
36 37
37/* 38/*
38 * lapic_nmi_owner tracks the ownership of the lapic NMI hardware: 39 * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -59,7 +60,8 @@ int panic_on_timeout;
59 60
60unsigned int nmi_watchdog = NMI_DEFAULT; 61unsigned int nmi_watchdog = NMI_DEFAULT;
61static unsigned int nmi_hz = HZ; 62static unsigned int nmi_hz = HZ;
62unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ 63static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
64static unsigned int nmi_p4_cccr_val;
63 65
64/* Note that these events don't tick when the CPU idles. This means 66/* Note that these events don't tick when the CPU idles. This means
65 the frequency varies with CPU load. */ 67 the frequency varies with CPU load. */
@@ -71,61 +73,87 @@ unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
71#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76 73#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
72#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 74#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
73 75
74#define P6_EVNTSEL0_ENABLE (1 << 22) 76#define MSR_P4_MISC_ENABLE 0x1A0
75#define P6_EVNTSEL_INT (1 << 20) 77#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
76#define P6_EVNTSEL_OS (1 << 17) 78#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12)
77#define P6_EVNTSEL_USR (1 << 16) 79#define MSR_P4_PERFCTR0 0x300
78#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79 80#define MSR_P4_CCCR0 0x360
79#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED 81#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
82#define P4_ESCR_OS (1<<3)
83#define P4_ESCR_USR (1<<2)
84#define P4_CCCR_OVF_PMI0 (1<<26)
85#define P4_CCCR_OVF_PMI1 (1<<27)
86#define P4_CCCR_THRESHOLD(N) ((N)<<20)
87#define P4_CCCR_COMPLEMENT (1<<19)
88#define P4_CCCR_COMPARE (1<<18)
89#define P4_CCCR_REQUIRED (3<<16)
90#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
91#define P4_CCCR_ENABLE (1<<12)
92/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
93 CRU_ESCR0 (with any non-null event selector) through a complemented
94 max threshold. [IA32-Vol3, Section 14.9.9] */
95#define MSR_P4_IQ_COUNTER0 0x30C
96#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
97#define P4_NMI_IQ_CCCR0 \
98 (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
99 P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
100
101static __init inline int nmi_known_cpu(void)
102{
103 switch (boot_cpu_data.x86_vendor) {
104 case X86_VENDOR_AMD:
105 return boot_cpu_data.x86 == 15;
106 case X86_VENDOR_INTEL:
107 return boot_cpu_data.x86 == 15;
108 }
109 return 0;
110}
80 111
81/* Run after command line and cpu_init init, but before all other checks */ 112/* Run after command line and cpu_init init, but before all other checks */
82void __init nmi_watchdog_default(void) 113void __init nmi_watchdog_default(void)
83{ 114{
84 if (nmi_watchdog != NMI_DEFAULT) 115 if (nmi_watchdog != NMI_DEFAULT)
85 return; 116 return;
86 117 if (nmi_known_cpu())
87 /* For some reason the IO APIC watchdog doesn't work on the AMD 118 nmi_watchdog = NMI_LOCAL_APIC;
88 8111 chipset. For now switch to local APIC mode using 119 else
89 perfctr0 there. On Intel CPUs we don't have code to handle
90 the perfctr and the IO-APIC seems to work, so use that. */
91
92 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
93 nmi_watchdog = NMI_LOCAL_APIC;
94 printk(KERN_INFO
95 "Using local APIC NMI watchdog using perfctr0\n");
96 } else {
97 printk(KERN_INFO "Using IO APIC NMI watchdog\n");
98 nmi_watchdog = NMI_IO_APIC; 120 nmi_watchdog = NMI_IO_APIC;
99 }
100} 121}
101 122
102/* Why is there no CPUID flag for this? */ 123#ifdef CONFIG_SMP
103static __init int cpu_has_lapic(void) 124/* The performance counters used by NMI_LOCAL_APIC don't trigger when
125 * the CPU is idle. To make sure the NMI watchdog really ticks on all
126 * CPUs during the test make them busy.
127 */
128static __init void nmi_cpu_busy(void *data)
104{ 129{
105 switch (boot_cpu_data.x86_vendor) { 130 volatile int *endflag = data;
106 case X86_VENDOR_INTEL: 131 local_irq_enable();
107 case X86_VENDOR_AMD: 132 /* Intentionally don't use cpu_relax here. This is
108 return boot_cpu_data.x86 >= 6; 133 to make sure that the performance counter really ticks,
109 /* .... add more cpus here or find a different way to figure this out. */ 134 even if there is a simulator or similar that catches the
110 default: 135 pause instruction. On a real HT machine this is fine because
111 return 0; 136 all other CPUs are busy with "useless" delay loops and don't
112 } 137 care if they get somewhat less cycles. */
138 while (*endflag == 0)
139 barrier();
113} 140}
141#endif
114 142
115static int __init check_nmi_watchdog (void) 143int __init check_nmi_watchdog (void)
116{ 144{
117 int counts[NR_CPUS]; 145 volatile int endflag = 0;
146 int *counts;
118 int cpu; 147 int cpu;
119 148
120 if (nmi_watchdog == NMI_NONE) 149 counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
121 return 0; 150 if (!counts)
151 return -1;
122 152
123 if (nmi_watchdog == NMI_LOCAL_APIC && !cpu_has_lapic()) { 153 printk(KERN_INFO "testing NMI watchdog ... ");
124 nmi_watchdog = NMI_NONE;
125 return -1;
126 }
127 154
128 printk(KERN_INFO "Testing NMI watchdog ... "); 155 if (nmi_watchdog == NMI_LOCAL_APIC)
156 smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
129 157
130 for (cpu = 0; cpu < NR_CPUS; cpu++) 158 for (cpu = 0; cpu < NR_CPUS; cpu++)
131 counts[cpu] = cpu_pda[cpu].__nmi_count; 159 counts[cpu] = cpu_pda[cpu].__nmi_count;
@@ -133,15 +161,22 @@ static int __init check_nmi_watchdog (void)
133 mdelay((10*1000)/nmi_hz); // wait 10 ticks 161 mdelay((10*1000)/nmi_hz); // wait 10 ticks
134 162
135 for (cpu = 0; cpu < NR_CPUS; cpu++) { 163 for (cpu = 0; cpu < NR_CPUS; cpu++) {
164 if (!cpu_online(cpu))
165 continue;
136 if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) { 166 if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) {
137 printk("CPU#%d: NMI appears to be stuck (%d)!\n", 167 endflag = 1;
168 printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
138 cpu, 169 cpu,
170 counts[cpu],
139 cpu_pda[cpu].__nmi_count); 171 cpu_pda[cpu].__nmi_count);
140 nmi_active = 0; 172 nmi_active = 0;
141 lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG; 173 lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
174 nmi_perfctr_msr = 0;
175 kfree(counts);
142 return -1; 176 return -1;
143 } 177 }
144 } 178 }
179 endflag = 1;
145 printk("OK.\n"); 180 printk("OK.\n");
146 181
147 /* now that we know it works we can reduce NMI frequency to 182 /* now that we know it works we can reduce NMI frequency to
@@ -149,10 +184,9 @@ static int __init check_nmi_watchdog (void)
149 if (nmi_watchdog == NMI_LOCAL_APIC) 184 if (nmi_watchdog == NMI_LOCAL_APIC)
150 nmi_hz = 1; 185 nmi_hz = 1;
151 186
187 kfree(counts);
152 return 0; 188 return 0;
153} 189}
154/* Have this called later during boot so counters are updating */
155late_initcall(check_nmi_watchdog);
156 190
157int __init setup_nmi_watchdog(char *str) 191int __init setup_nmi_watchdog(char *str)
158{ 192{
@@ -170,7 +204,7 @@ int __init setup_nmi_watchdog(char *str)
170 204
171 if (nmi >= NMI_INVALID) 205 if (nmi >= NMI_INVALID)
172 return 0; 206 return 0;
173 nmi_watchdog = nmi; 207 nmi_watchdog = nmi;
174 return 1; 208 return 1;
175} 209}
176 210
@@ -185,7 +219,10 @@ static void disable_lapic_nmi_watchdog(void)
185 wrmsr(MSR_K7_EVNTSEL0, 0, 0); 219 wrmsr(MSR_K7_EVNTSEL0, 0, 0);
186 break; 220 break;
187 case X86_VENDOR_INTEL: 221 case X86_VENDOR_INTEL:
188 wrmsr(MSR_IA32_EVNTSEL0, 0, 0); 222 if (boot_cpu_data.x86 == 15) {
223 wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
224 wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
225 }
189 break; 226 break;
190 } 227 }
191 nmi_active = -1; 228 nmi_active = -1;
@@ -253,7 +290,7 @@ void enable_timer_nmi_watchdog(void)
253 290
254static int nmi_pm_active; /* nmi_active before suspend */ 291static int nmi_pm_active; /* nmi_active before suspend */
255 292
256static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state) 293static int lapic_nmi_suspend(struct sys_device *dev, u32 state)
257{ 294{
258 nmi_pm_active = nmi_active; 295 nmi_pm_active = nmi_active;
259 disable_lapic_nmi_watchdog(); 296 disable_lapic_nmi_watchdog();
@@ -300,22 +337,27 @@ late_initcall(init_lapic_nmi_sysfs);
300 * Original code written by Keith Owens. 337 * Original code written by Keith Owens.
301 */ 338 */
302 339
340static void clear_msr_range(unsigned int base, unsigned int n)
341{
342 unsigned int i;
343
344 for(i = 0; i < n; ++i)
345 wrmsr(base+i, 0, 0);
346}
347
303static void setup_k7_watchdog(void) 348static void setup_k7_watchdog(void)
304{ 349{
305 int i; 350 int i;
306 unsigned int evntsel; 351 unsigned int evntsel;
307 352
308 /* No check, so can start with slow frequency */
309 nmi_hz = 1;
310
311 /* XXX should check these in EFER */
312
313 nmi_perfctr_msr = MSR_K7_PERFCTR0; 353 nmi_perfctr_msr = MSR_K7_PERFCTR0;
314 354
315 for(i = 0; i < 4; ++i) { 355 for(i = 0; i < 4; ++i) {
316 /* Simulator may not support it */ 356 /* Simulator may not support it */
317 if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) 357 if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) {
358 nmi_perfctr_msr = 0;
318 return; 359 return;
360 }
319 wrmsrl(MSR_K7_PERFCTR0+i, 0UL); 361 wrmsrl(MSR_K7_PERFCTR0+i, 0UL);
320 } 362 }
321 363
@@ -325,12 +367,54 @@ static void setup_k7_watchdog(void)
325 | K7_NMI_EVENT; 367 | K7_NMI_EVENT;
326 368
327 wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); 369 wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
328 wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz*1000) / nmi_hz); 370 wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
329 apic_write(APIC_LVTPC, APIC_DM_NMI); 371 apic_write(APIC_LVTPC, APIC_DM_NMI);
330 evntsel |= K7_EVNTSEL_ENABLE; 372 evntsel |= K7_EVNTSEL_ENABLE;
331 wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); 373 wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
332} 374}
333 375
376
377static int setup_p4_watchdog(void)
378{
379 unsigned int misc_enable, dummy;
380
381 rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
382 if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
383 return 0;
384
385 nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
386 nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
387#ifdef CONFIG_SMP
388 if (smp_num_siblings == 2)
389 nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
390#endif
391
392 if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
393 clear_msr_range(0x3F1, 2);
394 /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
395 docs doesn't fully define it, so leave it alone for now. */
396 if (boot_cpu_data.x86_model >= 0x3) {
397 /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
398 clear_msr_range(0x3A0, 26);
399 clear_msr_range(0x3BC, 3);
400 } else {
401 clear_msr_range(0x3A0, 31);
402 }
403 clear_msr_range(0x3C0, 6);
404 clear_msr_range(0x3C8, 6);
405 clear_msr_range(0x3E0, 2);
406 clear_msr_range(MSR_P4_CCCR0, 18);
407 clear_msr_range(MSR_P4_PERFCTR0, 18);
408
409 wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
410 wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
411 Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
412 wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
413 apic_write(APIC_LVTPC, APIC_DM_NMI);
414 wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
415 return 1;
416}
417
334void setup_apic_nmi_watchdog(void) 418void setup_apic_nmi_watchdog(void)
335{ 419{
336 switch (boot_cpu_data.x86_vendor) { 420 switch (boot_cpu_data.x86_vendor) {
@@ -341,6 +425,13 @@ void setup_apic_nmi_watchdog(void)
341 return; 425 return;
342 setup_k7_watchdog(); 426 setup_k7_watchdog();
343 break; 427 break;
428 case X86_VENDOR_INTEL:
429 if (boot_cpu_data.x86 != 15)
430 return;
431 if (!setup_p4_watchdog())
432 return;
433 break;
434
344 default: 435 default:
345 return; 436 return;
346 } 437 }
@@ -355,56 +446,67 @@ void setup_apic_nmi_watchdog(void)
355 * 446 *
356 * as these watchdog NMI IRQs are generated on every CPU, we only 447 * as these watchdog NMI IRQs are generated on every CPU, we only
357 * have to check the current processor. 448 * have to check the current processor.
358 *
359 * since NMIs don't listen to _any_ locks, we have to be extremely
360 * careful not to rely on unsafe variables. The printk might lock
361 * up though, so we have to break up any console locks first ...
362 * [when there will be more tty-related locks, break them up
363 * here too!]
364 */ 449 */
365 450
366static unsigned int 451static DEFINE_PER_CPU(unsigned, last_irq_sum);
367 last_irq_sums [NR_CPUS], 452static DEFINE_PER_CPU(local_t, alert_counter);
368 alert_counter [NR_CPUS]; 453static DEFINE_PER_CPU(int, nmi_touch);
369 454
370void touch_nmi_watchdog (void) 455void touch_nmi_watchdog (void)
371{ 456{
372 int i; 457 int i;
373 458
374 /* 459 /*
375 * Just reset the alert counters, (other CPUs might be 460 * Tell other CPUs to reset their alert counters. We cannot
376 * spinning on locks we hold): 461 * do it ourselves because the alert count increase is not
462 * atomic.
377 */ 463 */
378 for (i = 0; i < NR_CPUS; i++) 464 for (i = 0; i < NR_CPUS; i++)
379 alert_counter[i] = 0; 465 per_cpu(nmi_touch, i) = 1;
380} 466}
381 467
382void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) 468void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
383{ 469{
384 int sum, cpu; 470 int sum;
471 int touched = 0;
385 472
386 cpu = safe_smp_processor_id();
387 sum = read_pda(apic_timer_irqs); 473 sum = read_pda(apic_timer_irqs);
388 if (last_irq_sums[cpu] == sum) { 474 if (__get_cpu_var(nmi_touch)) {
475 __get_cpu_var(nmi_touch) = 0;
476 touched = 1;
477 }
478 if (!touched && __get_cpu_var(last_irq_sum) == sum) {
389 /* 479 /*
390 * Ayiee, looks like this CPU is stuck ... 480 * Ayiee, looks like this CPU is stuck ...
391 * wait a few IRQs (5 seconds) before doing the oops ... 481 * wait a few IRQs (5 seconds) before doing the oops ...
392 */ 482 */
393 alert_counter[cpu]++; 483 local_inc(&__get_cpu_var(alert_counter));
394 if (alert_counter[cpu] == 5*nmi_hz) { 484 if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) {
395 if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) 485 if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
396 == NOTIFY_STOP) { 486 == NOTIFY_STOP) {
397 alert_counter[cpu] = 0; 487 local_set(&__get_cpu_var(alert_counter), 0);
398 return; 488 return;
399 } 489 }
400 die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs); 490 die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
401 } 491 }
402 } else { 492 } else {
403 last_irq_sums[cpu] = sum; 493 __get_cpu_var(last_irq_sum) = sum;
404 alert_counter[cpu] = 0; 494 local_set(&__get_cpu_var(alert_counter), 0);
405 } 495 }
406 if (nmi_perfctr_msr) 496 if (nmi_perfctr_msr) {
497 if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
498 /*
499 * P4 quirks:
500 * - An overflown perfctr will assert its interrupt
501 * until the OVF flag in its CCCR is cleared.
502 * - LVTPC is masked on interrupt and must be
503 * unmasked by the LVTPC handler.
504 */
505 wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
506 apic_write(APIC_LVTPC, APIC_DM_NMI);
507 }
407 wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1); 508 wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
509 }
408} 510}
409 511
410static int dummy_nmi_callback(struct pt_regs * regs, int cpu) 512static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
new file mode 100644
index 000000000000..feb5f108dd26
--- /dev/null
+++ b/arch/x86_64/kernel/pmtimer.c
@@ -0,0 +1,101 @@
1/* Ported over from i386 by AK, original copyright was:
2 *
3 * (C) Dominik Brodowski <linux@brodo.de> 2003
4 *
5 * Driver to use the Power Management Timer (PMTMR) available in some
6 * southbridges as primary timing source for the Linux kernel.
7 *
8 * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
9 * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
10 *
11 * This file is licensed under the GPL v2.
12 *
13 * Dropped all the hardware bug workarounds for now. Hopefully they
14 * are not needed on 64bit chipsets.
15 */
16
17#include <linux/jiffies.h>
18#include <linux/kernel.h>
19#include <linux/time.h>
20#include <linux/init.h>
21#include <linux/cpumask.h>
22#include <asm/io.h>
23#include <asm/proto.h>
24#include <asm/msr.h>
25#include <asm/vsyscall.h>
26
27/* The I/O port the PMTMR resides at.
28 * The location is detected during setup_arch(),
29 * in arch/i386/kernel/acpi/boot.c */
30u32 pmtmr_ioport;
31
32/* value of the Power timer at last timer interrupt */
33static u32 offset_delay;
34static u32 last_pmtmr_tick;
35
36#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
37
38static inline u32 cyc2us(u32 cycles)
39{
40 /* The Power Management Timer ticks at 3.579545 ticks per microsecond.
41 * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
42 *
43 * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
44 * easily be multiplied with 286 (=0x11E) without having to fear
45 * u32 overflows.
46 */
47 cycles *= 286;
48 return (cycles >> 10);
49}
50
51int pmtimer_mark_offset(void)
52{
53 static int first_run = 1;
54 unsigned long tsc;
55 u32 lost;
56
57 u32 tick = inl(pmtmr_ioport);
58 u32 delta;
59
60 delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK);
61
62 last_pmtmr_tick = tick;
63 monotonic_base += delta * NSEC_PER_USEC;
64
65 delta += offset_delay;
66
67 lost = delta / (USEC_PER_SEC / HZ);
68 offset_delay = delta % (USEC_PER_SEC / HZ);
69
70 rdtscll(tsc);
71 vxtime.last_tsc = tsc - offset_delay * cpu_khz;
72
73 /* don't calculate delay for first run,
74 or if we've got less then a tick */
75 if (first_run || (lost < 1)) {
76 first_run = 0;
77 offset_delay = 0;
78 }
79
80 return lost - 1;
81}
82
83unsigned int do_gettimeoffset_pm(void)
84{
85 u32 now, offset, delta = 0;
86
87 offset = last_pmtmr_tick;
88 now = inl(pmtmr_ioport);
89 delta = (now - offset) & ACPI_PM_MASK;
90
91 return offset_delay + cyc2us(delta);
92}
93
94
95static int __init nopmtimer_setup(char *s)
96{
97 pmtmr_ioport = 0;
98 return 0;
99}
100
101__setup("nopmtimer", nopmtimer_setup);
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index e26e86bb56fe..525f6a128a27 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -257,13 +257,13 @@ static int putreg(struct task_struct *child,
257 value &= 0xffff; 257 value &= 0xffff;
258 return 0; 258 return 0;
259 case offsetof(struct user_regs_struct,fs_base): 259 case offsetof(struct user_regs_struct,fs_base):
260 if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) 260 if (value >= TASK_SIZE)
261 return -EIO; 261 return -EIO;
262 child->thread.fs = value; 262 child->thread.fs = value;
263 return 0; 263 return 0;
264 case offsetof(struct user_regs_struct,gs_base): 264 case offsetof(struct user_regs_struct,gs_base):
265 if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) 265 if (value >= TASK_SIZE)
266 return -EIO; 266 return -EIO;
267 child->thread.gs = value; 267 child->thread.gs = value;
268 return 0; 268 return 0;
269 case offsetof(struct user_regs_struct, eflags): 269 case offsetof(struct user_regs_struct, eflags):
@@ -277,6 +277,11 @@ static int putreg(struct task_struct *child,
277 return -EIO; 277 return -EIO;
278 value &= 0xffff; 278 value &= 0xffff;
279 break; 279 break;
280 case offsetof(struct user_regs_struct, rip):
281 /* Check if the new RIP address is canonical */
282 if (value >= TASK_SIZE)
283 return -EIO;
284 break;
280 } 285 }
281 put_stack_long(child, regno - sizeof(struct pt_regs), value); 286 put_stack_long(child, regno - sizeof(struct pt_regs), value);
282 return 0; 287 return 0;
@@ -375,7 +380,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
375 break; 380 break;
376 381
377 switch (addr) { 382 switch (addr) {
378 case 0 ... sizeof(struct user_regs_struct): 383 case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
379 tmp = getreg(child, addr); 384 tmp = getreg(child, addr);
380 break; 385 break;
381 case offsetof(struct user, u_debugreg[0]): 386 case offsetof(struct user, u_debugreg[0]):
@@ -420,7 +425,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
420 break; 425 break;
421 426
422 switch (addr) { 427 switch (addr) {
423 case 0 ... sizeof(struct user_regs_struct): 428 case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
424 ret = putreg(child, addr, data); 429 ret = putreg(child, addr, data);
425 break; 430 break;
426 /* Disallows to set a breakpoint into the vsyscall */ 431 /* Disallows to set a breakpoint into the vsyscall */
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 2129cf9ba6b2..99f038ede23c 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -719,7 +719,6 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
719 } 719 }
720} 720}
721 721
722#ifdef CONFIG_SMP
723/* 722/*
724 * On a AMD dual core setup the lower bits of the APIC id distingush the cores. 723 * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
725 * Assumes number of cores is a power of two. 724 * Assumes number of cores is a power of two.
@@ -727,17 +726,26 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
727static void __init amd_detect_cmp(struct cpuinfo_x86 *c) 726static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
728{ 727{
729#ifdef CONFIG_SMP 728#ifdef CONFIG_SMP
730 int cpu = c->x86_apicid; 729 int cpu = smp_processor_id();
731 int node = 0; 730 int node = 0;
731 unsigned bits;
732 if (c->x86_num_cores == 1) 732 if (c->x86_num_cores == 1)
733 return; 733 return;
734 cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1); 734
735 bits = 0;
736 while ((1 << bits) < c->x86_num_cores)
737 bits++;
738
739 /* Low order bits define the core id (index of core in socket) */
740 cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
741 /* Convert the APIC ID into the socket ID */
742 phys_proc_id[cpu] >>= bits;
735 743
736#ifdef CONFIG_NUMA 744#ifdef CONFIG_NUMA
737 /* When an ACPI SRAT table is available use the mappings from SRAT 745 /* When an ACPI SRAT table is available use the mappings from SRAT
738 instead. */ 746 instead. */
739 if (acpi_numa <= 0) { 747 if (acpi_numa <= 0) {
740 node = cpu_core_id[cpu]; 748 node = phys_proc_id[cpu];
741 if (!node_online(node)) 749 if (!node_online(node))
742 node = first_node(node_online_map); 750 node = first_node(node_online_map);
743 cpu_to_node[cpu] = node; 751 cpu_to_node[cpu] = node;
@@ -745,15 +753,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
745 node = cpu_to_node[cpu]; 753 node = cpu_to_node[cpu];
746 } 754 }
747#endif 755#endif
756
748 printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", 757 printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
749 cpu, c->x86_num_cores, node, cpu_core_id[cpu]); 758 cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
750#endif 759#endif
751} 760}
752#else
753static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
754{
755}
756#endif
757 761
758static int __init init_amd(struct cpuinfo_x86 *c) 762static int __init init_amd(struct cpuinfo_x86 *c)
759{ 763{
@@ -925,7 +929,6 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
925 c->x86_clflush_size = 64; 929 c->x86_clflush_size = 64;
926 c->x86_cache_alignment = c->x86_clflush_size; 930 c->x86_cache_alignment = c->x86_clflush_size;
927 c->x86_num_cores = 1; 931 c->x86_num_cores = 1;
928 c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data;
929 c->extended_cpuid_level = 0; 932 c->extended_cpuid_level = 0;
930 memset(&c->x86_capability, 0, sizeof c->x86_capability); 933 memset(&c->x86_capability, 0, sizeof c->x86_capability);
931 934
@@ -954,11 +957,14 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
954 } 957 }
955 if (c->x86_capability[0] & (1<<19)) 958 if (c->x86_capability[0] & (1<<19))
956 c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; 959 c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
957 c->x86_apicid = misc >> 24;
958 } else { 960 } else {
959 /* Have CPUID level 0 only - unheard of */ 961 /* Have CPUID level 0 only - unheard of */
960 c->x86 = 4; 962 c->x86 = 4;
961 } 963 }
964
965#ifdef CONFIG_SMP
966 phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
967#endif
962} 968}
963 969
964/* 970/*
@@ -1088,7 +1094,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1088 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1094 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1089 1095
1090 /* Other (Linux-defined) */ 1096 /* Other (Linux-defined) */
1091 "cxmmx", NULL, "cyrix_arr", "centaur_mcr", "k8c+", 1097 "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
1092 "constant_tsc", NULL, NULL, 1098 "constant_tsc", NULL, NULL,
1093 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1099 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1094 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1100 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index d439ced150c6..429c0269dc4e 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -28,6 +28,7 @@
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/i387.h> 29#include <asm/i387.h>
30#include <asm/proto.h> 30#include <asm/proto.h>
31#include <asm/ia32_unistd.h>
31 32
32/* #define DEBUG_SIG 1 */ 33/* #define DEBUG_SIG 1 */
33 34
@@ -452,7 +453,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
452 regs->rip -= 2; 453 regs->rip -= 2;
453 } 454 }
454 if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) { 455 if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
455 regs->rax = __NR_restart_syscall; 456 regs->rax = test_thread_flag(TIF_IA32) ?
457 __NR_ia32_restart_syscall :
458 __NR_restart_syscall;
456 regs->rip -= 2; 459 regs->rip -= 2;
457 } 460 }
458 } 461 }
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 73f7e8b9543a..f1ec0f345941 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -56,6 +56,7 @@
56#include <asm/kdebug.h> 56#include <asm/kdebug.h>
57#include <asm/tlbflush.h> 57#include <asm/tlbflush.h>
58#include <asm/proto.h> 58#include <asm/proto.h>
59#include <asm/nmi.h>
59 60
60/* Change for real CPU hotplug. Note other files need to be fixed 61/* Change for real CPU hotplug. Note other files need to be fixed
61 first too. */ 62 first too. */
@@ -93,6 +94,7 @@ int smp_threads_ready;
93 94
94cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; 95cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
95cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; 96cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
97EXPORT_SYMBOL(cpu_core_map);
96 98
97/* 99/*
98 * Trampoline 80x86 program as an array. 100 * Trampoline 80x86 program as an array.
@@ -125,96 +127,210 @@ static void __cpuinit smp_store_cpu_info(int id)
125 127
126 *c = boot_cpu_data; 128 *c = boot_cpu_data;
127 identify_cpu(c); 129 identify_cpu(c);
130 print_cpu_info(c);
128} 131}
129 132
130/* 133/*
131 * Synchronize TSCs of CPUs 134 * New Funky TSC sync algorithm borrowed from IA64.
135 * Main advantage is that it doesn't reset the TSCs fully and
136 * in general looks more robust and it works better than my earlier
137 * attempts. I believe it was written by David Mosberger. Some minor
138 * adjustments for x86-64 by me -AK
132 * 139 *
133 * This new algorithm is less accurate than the old "zero TSCs" 140 * Original comment reproduced below.
134 * one, but we cannot zero TSCs anymore in the new hotplug CPU 141 *
135 * model. 142 * Synchronize TSC of the current (slave) CPU with the TSC of the
143 * MASTER CPU (normally the time-keeper CPU). We use a closed loop to
144 * eliminate the possibility of unaccounted-for errors (such as
145 * getting a machine check in the middle of a calibration step). The
146 * basic idea is for the slave to ask the master what itc value it has
147 * and to read its own itc before and after the master responds. Each
148 * iteration gives us three timestamps:
149 *
150 * slave master
151 *
152 * t0 ---\
153 * ---\
154 * --->
155 * tm
156 * /---
157 * /---
158 * t1 <---
159 *
160 *
161 * The goal is to adjust the slave's TSC such that tm falls exactly
162 * half-way between t0 and t1. If we achieve this, the clocks are
163 * synchronized provided the interconnect between the slave and the
164 * master is symmetric. Even if the interconnect were asymmetric, we
165 * would still know that the synchronization error is smaller than the
166 * roundtrip latency (t0 - t1).
167 *
168 * When the interconnect is quiet and symmetric, this lets us
169 * synchronize the TSC to within one or two cycles. However, we can
170 * only *guarantee* that the synchronization is accurate to within a
171 * round-trip time, which is typically in the range of several hundred
172 * cycles (e.g., ~500 cycles). In practice, this means that the TSCs
173 * are usually almost perfectly synchronized, but we shouldn't assume
174 * that the accuracy is much better than half a micro second or so.
175 *
176 * [there are other errors like the latency of RDTSC and of the
177 * WRMSR. These can also account to hundreds of cycles. So it's
178 * probably worse. It claims 153 cycles error on a dual Opteron,
179 * but I suspect the numbers are actually somewhat worse -AK]
136 */ 180 */
137 181
138static atomic_t __cpuinitdata tsc_flag; 182#define MASTER 0
183#define SLAVE (SMP_CACHE_BYTES/8)
184
185/* Intentionally don't use cpu_relax() while TSC synchronization
186 because we don't want to go into funky power save modi or cause
187 hypervisors to schedule us away. Going to sleep would likely affect
188 latency and low latency is the primary objective here. -AK */
189#define no_cpu_relax() barrier()
190
139static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock); 191static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock);
140static unsigned long long __cpuinitdata bp_tsc, ap_tsc; 192static volatile __cpuinitdata unsigned long go[SLAVE + 1];
193static int notscsync __cpuinitdata;
194
195#undef DEBUG_TSC_SYNC
141 196
142#define NR_LOOPS 5 197#define NUM_ROUNDS 64 /* magic value */
198#define NUM_ITERS 5 /* likewise */
143 199
144static void __cpuinit sync_tsc_bp_init(int init) 200/* Callback on boot CPU */
201static __cpuinit void sync_master(void *arg)
145{ 202{
146 if (init) 203 unsigned long flags, i;
147 _raw_spin_lock(&tsc_sync_lock); 204
148 else 205 if (smp_processor_id() != boot_cpu_id)
149 _raw_spin_unlock(&tsc_sync_lock); 206 return;
150 atomic_set(&tsc_flag, 0); 207
208 go[MASTER] = 0;
209
210 local_irq_save(flags);
211 {
212 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
213 while (!go[MASTER])
214 no_cpu_relax();
215 go[MASTER] = 0;
216 rdtscll(go[SLAVE]);
217 }
218 }
219 local_irq_restore(flags);
151} 220}
152 221
153/* 222/*
154 * Synchronize TSC on AP with BP. 223 * Return the number of cycles by which our tsc differs from the tsc
224 * on the master (time-keeper) CPU. A positive number indicates our
225 * tsc is ahead of the master, negative that it is behind.
155 */ 226 */
156static void __cpuinit __sync_tsc_ap(void) 227static inline long
228get_delta(long *rt, long *master)
157{ 229{
158 if (!cpu_has_tsc) 230 unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
159 return; 231 unsigned long tcenter, t0, t1, tm;
160 Dprintk("AP %d syncing TSC\n", smp_processor_id()); 232 int i;
161 233
162 while (atomic_read(&tsc_flag) != 0) 234 for (i = 0; i < NUM_ITERS; ++i) {
163 cpu_relax(); 235 rdtscll(t0);
164 atomic_inc(&tsc_flag); 236 go[MASTER] = 1;
165 mb(); 237 while (!(tm = go[SLAVE]))
166 _raw_spin_lock(&tsc_sync_lock); 238 no_cpu_relax();
167 wrmsrl(MSR_IA32_TSC, bp_tsc); 239 go[SLAVE] = 0;
168 _raw_spin_unlock(&tsc_sync_lock); 240 rdtscll(t1);
169 rdtscll(ap_tsc); 241
170 mb(); 242 if (t1 - t0 < best_t1 - best_t0)
171 atomic_inc(&tsc_flag); 243 best_t0 = t0, best_t1 = t1, best_tm = tm;
172 mb(); 244 }
245
246 *rt = best_t1 - best_t0;
247 *master = best_tm - best_t0;
248
249 /* average best_t0 and best_t1 without overflow: */
250 tcenter = (best_t0/2 + best_t1/2);
251 if (best_t0 % 2 + best_t1 % 2 == 2)
252 ++tcenter;
253 return tcenter - best_tm;
173} 254}
174 255
175static void __cpuinit sync_tsc_ap(void) 256static __cpuinit void sync_tsc(void)
176{ 257{
177 int i; 258 int i, done = 0;
178 for (i = 0; i < NR_LOOPS; i++) 259 long delta, adj, adjust_latency = 0;
179 __sync_tsc_ap(); 260 unsigned long flags, rt, master_time_stamp, bound;
261#if DEBUG_TSC_SYNC
262 static struct syncdebug {
263 long rt; /* roundtrip time */
264 long master; /* master's timestamp */
265 long diff; /* difference between midpoint and master's timestamp */
266 long lat; /* estimate of tsc adjustment latency */
267 } t[NUM_ROUNDS] __cpuinitdata;
268#endif
269
270 go[MASTER] = 1;
271
272 smp_call_function(sync_master, NULL, 1, 0);
273
274 while (go[MASTER]) /* wait for master to be ready */
275 no_cpu_relax();
276
277 spin_lock_irqsave(&tsc_sync_lock, flags);
278 {
279 for (i = 0; i < NUM_ROUNDS; ++i) {
280 delta = get_delta(&rt, &master_time_stamp);
281 if (delta == 0) {
282 done = 1; /* let's lock on to this... */
283 bound = rt;
284 }
285
286 if (!done) {
287 unsigned long t;
288 if (i > 0) {
289 adjust_latency += -delta;
290 adj = -delta + adjust_latency/4;
291 } else
292 adj = -delta;
293
294 rdtscll(t);
295 wrmsrl(MSR_IA32_TSC, t + adj);
296 }
297#if DEBUG_TSC_SYNC
298 t[i].rt = rt;
299 t[i].master = master_time_stamp;
300 t[i].diff = delta;
301 t[i].lat = adjust_latency/4;
302#endif
303 }
304 }
305 spin_unlock_irqrestore(&tsc_sync_lock, flags);
306
307#if DEBUG_TSC_SYNC
308 for (i = 0; i < NUM_ROUNDS; ++i)
309 printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
310 t[i].rt, t[i].master, t[i].diff, t[i].lat);
311#endif
312
313 printk(KERN_INFO
314 "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
315 "maxerr %lu cycles)\n",
316 smp_processor_id(), boot_cpu_id, delta, rt);
180} 317}
181 318
182/* 319static void __cpuinit tsc_sync_wait(void)
183 * Synchronize TSC from BP to AP.
184 */
185static void __cpuinit __sync_tsc_bp(int cpu)
186{ 320{
187 if (!cpu_has_tsc) 321 if (notscsync || !cpu_has_tsc)
188 return; 322 return;
189 323 printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", smp_processor_id(),
190 /* Wait for AP */ 324 boot_cpu_id);
191 while (atomic_read(&tsc_flag) == 0) 325 sync_tsc();
192 cpu_relax();
193 /* Save BPs TSC */
194 sync_core();
195 rdtscll(bp_tsc);
196 /* Don't do the sync core here to avoid too much latency. */
197 mb();
198 /* Start the AP */
199 _raw_spin_unlock(&tsc_sync_lock);
200 /* Wait for AP again */
201 while (atomic_read(&tsc_flag) < 2)
202 cpu_relax();
203 rdtscl(bp_tsc);
204 barrier();
205} 326}
206 327
207static void __cpuinit sync_tsc_bp(int cpu) 328static __init int notscsync_setup(char *s)
208{ 329{
209 int i; 330 notscsync = 1;
210 for (i = 0; i < NR_LOOPS - 1; i++) { 331 return 0;
211 __sync_tsc_bp(cpu);
212 sync_tsc_bp_init(1);
213 }
214 __sync_tsc_bp(cpu);
215 printk(KERN_INFO "Synced TSC of CPU %d difference %Ld\n",
216 cpu, ap_tsc - bp_tsc);
217} 332}
333__setup("notscsync", notscsync_setup);
218 334
219static atomic_t init_deasserted __cpuinitdata; 335static atomic_t init_deasserted __cpuinitdata;
220 336
@@ -315,11 +431,6 @@ void __cpuinit start_secondary(void)
315 cpu_init(); 431 cpu_init();
316 smp_callin(); 432 smp_callin();
317 433
318 /*
319 * Synchronize the TSC with the BP
320 */
321 sync_tsc_ap();
322
323 /* otherwise gcc will move up the smp_processor_id before the cpu_init */ 434 /* otherwise gcc will move up the smp_processor_id before the cpu_init */
324 barrier(); 435 barrier();
325 436
@@ -334,7 +445,6 @@ void __cpuinit start_secondary(void)
334 enable_8259A_irq(0); 445 enable_8259A_irq(0);
335 } 446 }
336 447
337
338 enable_APIC_timer(); 448 enable_APIC_timer();
339 449
340 /* 450 /*
@@ -343,6 +453,11 @@ void __cpuinit start_secondary(void)
343 cpu_set(smp_processor_id(), cpu_online_map); 453 cpu_set(smp_processor_id(), cpu_online_map);
344 mb(); 454 mb();
345 455
456 /* Wait for TSC sync to not schedule things before.
457 We still process interrupts, which could see an inconsistent
458 time in that window unfortunately. */
459 tsc_sync_wait();
460
346 cpu_idle(); 461 cpu_idle();
347} 462}
348 463
@@ -531,7 +646,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
531 printk("failed fork for CPU %d\n", cpu); 646 printk("failed fork for CPU %d\n", cpu);
532 return PTR_ERR(idle); 647 return PTR_ERR(idle);
533 } 648 }
534 x86_cpu_to_apicid[cpu] = apicid;
535 649
536 cpu_pda[cpu].pcurrent = idle; 650 cpu_pda[cpu].pcurrent = idle;
537 651
@@ -600,8 +714,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
600 714
601 if (cpu_isset(cpu, cpu_callin_map)) { 715 if (cpu_isset(cpu, cpu_callin_map)) {
602 /* number CPUs logically, starting from 1 (BSP is 0) */ 716 /* number CPUs logically, starting from 1 (BSP is 0) */
603 Dprintk("OK.\n");
604 print_cpu_info(&cpu_data[cpu]);
605 Dprintk("CPU has booted.\n"); 717 Dprintk("CPU has booted.\n");
606 } else { 718 } else {
607 boot_error = 1; 719 boot_error = 1;
@@ -842,7 +954,6 @@ void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
842 GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id); 954 GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
843 /* Or can we switch back to PIC here? */ 955 /* Or can we switch back to PIC here? */
844 } 956 }
845 x86_cpu_to_apicid[0] = boot_cpu_id;
846 957
847 /* 958 /*
848 * Now start the IO-APICs 959 * Now start the IO-APICs
@@ -889,18 +1000,14 @@ int __cpuinit __cpu_up(unsigned int cpu)
889 printk("__cpu_up: bad cpu %d\n", cpu); 1000 printk("__cpu_up: bad cpu %d\n", cpu);
890 return -EINVAL; 1001 return -EINVAL;
891 } 1002 }
892 sync_tsc_bp_init(1);
893 1003
894 /* Boot it! */ 1004 /* Boot it! */
895 err = do_boot_cpu(cpu, apicid); 1005 err = do_boot_cpu(cpu, apicid);
896 if (err < 0) { 1006 if (err < 0) {
897 sync_tsc_bp_init(0);
898 Dprintk("do_boot_cpu failed %d\n", err); 1007 Dprintk("do_boot_cpu failed %d\n", err);
899 return err; 1008 return err;
900 } 1009 }
901 1010
902 sync_tsc_bp(cpu);
903
904 /* Unleash the CPU! */ 1011 /* Unleash the CPU! */
905 Dprintk("waiting for cpu %d\n", cpu); 1012 Dprintk("waiting for cpu %d\n", cpu);
906 1013
@@ -923,4 +1030,6 @@ void __cpuinit smp_cpus_done(unsigned int max_cpus)
923 1030
924 detect_siblings(); 1031 detect_siblings();
925 time_init_gtod(); 1032 time_init_gtod();
1033
1034 check_nmi_watchdog();
926} 1035}
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 0e3b60e1ac5b..fb8c809b4cd9 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -26,6 +26,10 @@
26#include <linux/sysdev.h> 26#include <linux/sysdev.h>
27#include <linux/bcd.h> 27#include <linux/bcd.h>
28#include <linux/kallsyms.h> 28#include <linux/kallsyms.h>
29#include <linux/acpi.h>
30#ifdef CONFIG_ACPI
31#include <acpi/achware.h> /* for PM timer frequency */
32#endif
29#include <asm/8253pit.h> 33#include <asm/8253pit.h>
30#include <asm/pgtable.h> 34#include <asm/pgtable.h>
31#include <asm/vsyscall.h> 35#include <asm/vsyscall.h>
@@ -396,6 +400,10 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
396 (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick; 400 (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
397 401
398 vxtime.last = offset; 402 vxtime.last = offset;
403#ifdef CONFIG_X86_PM_TIMER
404 } else if (vxtime.mode == VXTIME_PMTMR) {
405 lost = pmtimer_mark_offset();
406#endif
399 } else { 407 } else {
400 offset = (((tsc - vxtime.last_tsc) * 408 offset = (((tsc - vxtime.last_tsc) *
401 vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ); 409 vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
@@ -898,6 +906,13 @@ void __init time_init(void)
898 hpet_period; 906 hpet_period;
899 cpu_khz = hpet_calibrate_tsc(); 907 cpu_khz = hpet_calibrate_tsc();
900 timename = "HPET"; 908 timename = "HPET";
909#ifdef CONFIG_X86_PM_TIMER
910 } else if (pmtmr_ioport) {
911 vxtime_hz = PM_TIMER_FREQUENCY;
912 timename = "PM";
913 pit_init();
914 cpu_khz = pit_calibrate_tsc();
915#endif
901 } else { 916 } else {
902 pit_init(); 917 pit_init();
903 cpu_khz = pit_calibrate_tsc(); 918 cpu_khz = pit_calibrate_tsc();
@@ -923,35 +938,50 @@ void __init time_init(void)
923} 938}
924 939
925/* 940/*
941 * Make an educated guess if the TSC is trustworthy and synchronized
942 * over all CPUs.
943 */
944static __init int unsynchronized_tsc(void)
945{
946#ifdef CONFIG_SMP
947 if (oem_force_hpet_timer())
948 return 1;
949 /* Intel systems are normally all synchronized. Exceptions
950 are handled in the OEM check above. */
951 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
952 return 0;
953 /* All in a single socket - should be synchronized */
954 if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
955 return 0;
956#endif
957 /* Assume multi socket systems are not synchronized */
958 return num_online_cpus() > 1;
959}
960
961/*
926 * Decide after all CPUs are booted what mode gettimeofday should use. 962 * Decide after all CPUs are booted what mode gettimeofday should use.
927 */ 963 */
928void __init time_init_gtod(void) 964void __init time_init_gtod(void)
929{ 965{
930 char *timetype; 966 char *timetype;
931 967
932 /* 968 if (unsynchronized_tsc())
933 * AMD systems with more than one CPU don't have fully synchronized
934 * TSCs. Always use HPET gettimeofday for these, although it is slower.
935 * Intel SMP systems usually have synchronized TSCs, so use always
936 * the TSC.
937 *
938 * Exceptions:
939 * IBM Summit2 checked by oem_force_hpet_timer().
940 * AMD dual core may also not need HPET. Check me.
941 *
942 * Can be turned off with "notsc".
943 */
944 if (num_online_cpus() > 1 &&
945 boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
946 notsc = 1;
947 /* Some systems will want to disable TSC and use HPET. */
948 if (oem_force_hpet_timer())
949 notsc = 1; 969 notsc = 1;
950 if (vxtime.hpet_address && notsc) { 970 if (vxtime.hpet_address && notsc) {
951 timetype = "HPET"; 971 timetype = "HPET";
952 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; 972 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
953 vxtime.mode = VXTIME_HPET; 973 vxtime.mode = VXTIME_HPET;
954 do_gettimeoffset = do_gettimeoffset_hpet; 974 do_gettimeoffset = do_gettimeoffset_hpet;
975#ifdef CONFIG_X86_PM_TIMER
976 /* Using PM for gettimeofday is quite slow, but we have no other
977 choice because the TSC is too unreliable on some systems. */
978 } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
979 timetype = "PM";
980 do_gettimeoffset = do_gettimeoffset_pm;
981 vxtime.mode = VXTIME_PMTMR;
982 sysctl_vsyscall = 0;
983 printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
984#endif
955 } else { 985 } else {
956 timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC"; 986 timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC";
957 vxtime.mode = VXTIME_TSC; 987 vxtime.mode = VXTIME_TSC;
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 65a37f52c56e..3dfec8fdabcd 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -332,10 +332,12 @@ void handle_BUG(struct pt_regs *regs)
332 printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line); 332 printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
333} 333}
334 334
335#ifdef CONFIG_BUG
335void out_of_line_bug(void) 336void out_of_line_bug(void)
336{ 337{
337 BUG(); 338 BUG();
338} 339}
340#endif
339 341
340static DEFINE_SPINLOCK(die_lock); 342static DEFINE_SPINLOCK(die_lock);
341static int die_owner = -1; 343static int die_owner = -1;
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index b4b8dc59663a..2e5734425949 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -65,7 +65,7 @@ static force_inline void do_vgettimeofday(struct timeval * tv)
65 usec = (__xtime.tv_nsec / 1000) + 65 usec = (__xtime.tv_nsec / 1000) +
66 (__jiffies - __wall_jiffies) * (1000000 / HZ); 66 (__jiffies - __wall_jiffies) * (1000000 / HZ);
67 67
68 if (__vxtime.mode == VXTIME_TSC) { 68 if (__vxtime.mode != VXTIME_HPET) {
69 sync_core(); 69 sync_core();
70 rdtscll(t); 70 rdtscll(t);
71 if (t < __vxtime.last_tsc) 71 if (t < __vxtime.last_tsc)
@@ -217,8 +217,9 @@ static int __init vsyscall_init(void)
217 BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime)); 217 BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
218 BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE))); 218 BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
219 map_vsyscall(); 219 map_vsyscall();
220 sysctl_vsyscall = 1; 220#ifdef CONFIG_SYSCTL
221 register_sysctl_table(kernel_root_table2, 0); 221 register_sysctl_table(kernel_root_table2, 0);
222#endif
222 return 0; 223 return 0;
223} 224}
224 225
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 88626e626886..68ec03070e5a 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -139,35 +139,23 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback);
139#undef memmove 139#undef memmove
140#undef memchr 140#undef memchr
141#undef strlen 141#undef strlen
142#undef strcpy
143#undef strncmp 142#undef strncmp
144#undef strncpy 143#undef strncpy
145#undef strchr 144#undef strchr
146#undef strcmp
147#undef strcpy
148#undef strcat
149#undef memcmp
150 145
151extern void * memset(void *,int,__kernel_size_t); 146extern void * memset(void *,int,__kernel_size_t);
152extern size_t strlen(const char *); 147extern size_t strlen(const char *);
153extern void * memmove(void * dest,const void *src,size_t count); 148extern void * memmove(void * dest,const void *src,size_t count);
154extern char * strcpy(char * dest,const char *src);
155extern int strcmp(const char * cs,const char * ct);
156extern void *memchr(const void *s, int c, size_t n); 149extern void *memchr(const void *s, int c, size_t n);
157extern void * memcpy(void *,const void *,__kernel_size_t); 150extern void * memcpy(void *,const void *,__kernel_size_t);
158extern void * __memcpy(void *,const void *,__kernel_size_t); 151extern void * __memcpy(void *,const void *,__kernel_size_t);
159extern char * strcat(char *, const char *);
160extern int memcmp(const void * cs,const void * ct,size_t count);
161 152
162EXPORT_SYMBOL(memset); 153EXPORT_SYMBOL(memset);
163EXPORT_SYMBOL(strlen); 154EXPORT_SYMBOL(strlen);
164EXPORT_SYMBOL(memmove); 155EXPORT_SYMBOL(memmove);
165EXPORT_SYMBOL(strcpy);
166EXPORT_SYMBOL(strncmp); 156EXPORT_SYMBOL(strncmp);
167EXPORT_SYMBOL(strncpy); 157EXPORT_SYMBOL(strncpy);
168EXPORT_SYMBOL(strchr); 158EXPORT_SYMBOL(strchr);
169EXPORT_SYMBOL(strcmp);
170EXPORT_SYMBOL(strcat);
171EXPORT_SYMBOL(strncat); 159EXPORT_SYMBOL(strncat);
172EXPORT_SYMBOL(memchr); 160EXPORT_SYMBOL(memchr);
173EXPORT_SYMBOL(strrchr); 161EXPORT_SYMBOL(strrchr);
@@ -175,7 +163,6 @@ EXPORT_SYMBOL(strnlen);
175EXPORT_SYMBOL(memscan); 163EXPORT_SYMBOL(memscan);
176EXPORT_SYMBOL(memcpy); 164EXPORT_SYMBOL(memcpy);
177EXPORT_SYMBOL(__memcpy); 165EXPORT_SYMBOL(__memcpy);
178EXPORT_SYMBOL(memcmp);
179 166
180#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM 167#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
181/* prototypes are wrong, these are assembly with custom calling functions */ 168/* prototypes are wrong, these are assembly with custom calling functions */
@@ -206,8 +193,9 @@ EXPORT_SYMBOL(smp_num_siblings);
206extern void do_softirq_thunk(void); 193extern void do_softirq_thunk(void);
207EXPORT_SYMBOL(do_softirq_thunk); 194EXPORT_SYMBOL(do_softirq_thunk);
208 195
209void out_of_line_bug(void); 196#ifdef CONFIG_BUG
210EXPORT_SYMBOL(out_of_line_bug); 197EXPORT_SYMBOL(out_of_line_bug);
198#endif
211 199
212EXPORT_SYMBOL(init_level4_pgt); 200EXPORT_SYMBOL(init_level4_pgt);
213 201
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index e03309216764..5d6b2114cc9a 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -234,6 +234,8 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
234 234
235/* 235/*
236 * Handle a fault on the vmalloc or module mapping area 236 * Handle a fault on the vmalloc or module mapping area
237 *
238 * This assumes no large pages in there.
237 */ 239 */
238static int vmalloc_fault(unsigned long address) 240static int vmalloc_fault(unsigned long address)
239{ 241{
@@ -272,7 +274,10 @@ static int vmalloc_fault(unsigned long address)
272 if (!pte_present(*pte_ref)) 274 if (!pte_present(*pte_ref))
273 return -1; 275 return -1;
274 pte = pte_offset_kernel(pmd, address); 276 pte = pte_offset_kernel(pmd, address);
275 if (!pte_present(*pte) || pte_page(*pte) != pte_page(*pte_ref)) 277 /* Don't use pte_page here, because the mappings can point
278 outside mem_map, and the NUMA hash lookup cannot handle
279 that. */
280 if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
276 BUG(); 281 BUG();
277 __flush_tlb_all(); 282 __flush_tlb_all();
278 return 0; 283 return 0;
@@ -346,7 +351,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
346 * protection error (error_code & 1) == 0. 351 * protection error (error_code & 1) == 0.
347 */ 352 */
348 if (unlikely(address >= TASK_SIZE)) { 353 if (unlikely(address >= TASK_SIZE)) {
349 if (!(error_code & 5)) { 354 if (!(error_code & 5) &&
355 ((address >= VMALLOC_START && address < VMALLOC_END) ||
356 (address >= MODULES_VADDR && address < MODULES_END))) {
350 if (vmalloc_fault(address) < 0) 357 if (vmalloc_fault(address) < 0)
351 goto bad_area_nosemaphore; 358 goto bad_area_nosemaphore;
352 return; 359 return;
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index 74ec8554b195..58aac23760ef 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -133,7 +133,7 @@ ioremap_change_attr(unsigned long phys_addr, unsigned long size,
133 unsigned long flags) 133 unsigned long flags)
134{ 134{
135 int err = 0; 135 int err = 0;
136 if (flags && phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) { 136 if (phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
137 unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; 137 unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
138 unsigned long vaddr = (unsigned long) __va(phys_addr); 138 unsigned long vaddr = (unsigned long) __va(phys_addr);
139 139
@@ -214,7 +214,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
214 remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr)); 214 remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
215 return NULL; 215 return NULL;
216 } 216 }
217 if (ioremap_change_attr(phys_addr, size, flags) < 0) { 217 if (flags && ioremap_change_attr(phys_addr, size, flags) < 0) {
218 area->flags &= 0xffffff; 218 area->flags &= 0xffffff;
219 vunmap(addr); 219 vunmap(addr);
220 return NULL; 220 return NULL;
@@ -251,7 +251,7 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
251 251
252void iounmap(volatile void __iomem *addr) 252void iounmap(volatile void __iomem *addr)
253{ 253{
254 struct vm_struct *p, **pprev; 254 struct vm_struct *p;
255 255
256 if (addr <= high_memory) 256 if (addr <= high_memory)
257 return; 257 return;
@@ -260,24 +260,11 @@ void iounmap(volatile void __iomem *addr)
260 return; 260 return;
261 261
262 write_lock(&vmlist_lock); 262 write_lock(&vmlist_lock);
263 for (p = vmlist, pprev = &vmlist; p != NULL; pprev = &p->next, p = *pprev) 263 p = __remove_vm_area((void *)((unsigned long)addr & PAGE_MASK));
264 if (p->addr == (void *)(PAGE_MASK & (unsigned long)addr)) 264 if (!p)
265 break; 265 printk("iounmap: bad address %p\n", addr);
266 if (!p) { 266 else if (p->flags >> 20)
267 printk("__iounmap: bad address %p\n", addr); 267 ioremap_change_attr(p->phys_addr, p->size, 0);
268 goto out_unlock;
269 }
270 *pprev = p->next;
271 unmap_vm_area(p);
272 if ((p->flags >> 20) &&
273 p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
274 /* p->size includes the guard page, but cpa doesn't like that */
275 change_page_attr(virt_to_page(__va(p->phys_addr)),
276 p->size >> PAGE_SHIFT,
277 PAGE_KERNEL);
278 global_flush_tlb();
279 }
280out_unlock:
281 write_unlock(&vmlist_lock); 268 write_unlock(&vmlist_lock);
282 kfree(p); 269 kfree(p);
283} 270}