From 7d24f0b8a53261709938ffabe3e00f88f6498df9 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Mon, 7 Nov 2005 00:57:52 -0800
Subject: [PATCH] ppc64: Fix bug in SLB miss handler for hugepages

This patch, however, should be applied on top of the 64k-page-size patch to
fix some problems with hugepage (some pre-existing, another introduced by
this patch).

The patch fixes a bug in the SLB miss handler for hugepages on ppc64
introduced by the dynamic hugepage patch (commit id
c594adad5653491813959277fb87a2fef54c4e05) due to a misunderstanding of the
srd instruction's behaviour (mea culpa).  The problem arises when a 64-bit
process maps some hugepages in the low 4GB of the address space (unusual).
In this case, as well as the 256M segment in question being marked for
hugepages, other segments at 32G intervals will be incorrectly marked for
hugepages.

In the process, this patch tweaks the semantics of the hugepage bitmaps to
be more sensible.  Previously, an address below 4G was marked for hugepages
if the appropriate segment bit in the "low areas" bitmask was set *or* if
the low bit in the "high areas" bitmap was set (which would mark all
addresses below 1TB for hugepage).  With this patch, any given address is
governed by a single bitmap.  Addresses below 4GB are marked for hugepage
if and only if their bit is set in the "low areas" bitmap (256M
granularity).  Addresses between 4GB and 1TB are marked for hugepage iff
the low bit in the "high areas" bitmap is set.  Higher addresses are marked
for hugepage iff their bit in the "high areas" bitmap is set (1TB
granularity).

To avoid conflicts, this patch must be applied on top of BenH's pending
patch for 64k base page size [0].  As such, this patch also addresses a
hugepage problem introduced by that patch.  That patch allows hugepages of
1MB in size on hardware which supports it, however, that won't work when
using 4k pages (4 level pagetable), because in that case hugepage PTEs are
stored at the PMD level, and each PMD entry maps 2MB.  This patch simply
disallows hugepages in that case (we can do something cleverer to re-enable
them some other day).

Built, booted, and a handful of hugepage related tests passed on POWER5
LPAR (both ARCH=powerpc and ARCH=ppc64).

[0] http://gate.crashing.org/~benh/ppc64-64k-pages.diff

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/powerpc/mm/hash_utils_64.c |  6 ++++--
 arch/powerpc/mm/hugetlbpage.c   |  6 ++++++
 arch/powerpc/mm/slb_low.S       | 13 +++++++++----
 3 files changed, 19 insertions(+), 6 deletions(-)

(limited to 'arch')

diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index b2f3dbca69..f15dfb92de 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -329,12 +329,14 @@ static void __init htab_init_page_sizes(void)
 	 */
 	if (mmu_psize_defs[MMU_PAGE_16M].shift)
 		mmu_huge_psize = MMU_PAGE_16M;
+	/* With 4k/4level pagetables, we can't (for now) cope with a
+	 * huge page size < PMD_SIZE */
 	else if (mmu_psize_defs[MMU_PAGE_1M].shift)
 		mmu_huge_psize = MMU_PAGE_1M;
 
 	/* Calculate HPAGE_SHIFT and sanity check it */
-	if (mmu_psize_defs[mmu_huge_psize].shift > 16 &&
-	    mmu_psize_defs[mmu_huge_psize].shift < 28)
+	if (mmu_psize_defs[mmu_huge_psize].shift > MIN_HUGEPTE_SHIFT &&
+	    mmu_psize_defs[mmu_huge_psize].shift < SID_SHIFT)
 		HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift;
 	else
 		HPAGE_SHIFT = 0; /* No huge pages dude ! */
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 0073a04047..426c269e55 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -212,6 +212,12 @@ static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
 
 	BUG_ON(area >= NUM_HIGH_AREAS);
 
+	/* Hack, so that each addresses is controlled by exactly one
+	 * of the high or low area bitmaps, the first high area starts
+	 * at 4GB, not 0 */
+	if (start == 0)
+		start = 0x100000000UL;
+
 	/* Check no VMAs are in the region */
 	vma = find_vma(mm, start);
 	if (vma && (vma->vm_start < end))
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index 3e18241b6f..950ffc5848 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -80,12 +80,17 @@ _GLOBAL(slb_miss_kernel_load_virtual)
 BEGIN_FTR_SECTION
 	b	1f
 END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE)
+	cmpldi	r10,16
+
+	lhz	r9,PACALOWHTLBAREAS(r13)
+	mr	r11,r10
+	blt	5f
+
 	lhz	r9,PACAHIGHHTLBAREAS(r13)
 	srdi	r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT)
-	srd	r9,r9,r11
-	lhz	r11,PACALOWHTLBAREAS(r13)
-	srd	r11,r11,r10
-	or.	r9,r9,r11
+
+5:	srd	r9,r9,r11
+	andi.	r9,r9,1
 	beq	1f
 _GLOBAL(slb_miss_user_load_huge)
 	li	r11,0
-- 
cgit v1.2.2


From e1531b4218a7ccfc1b2234b87105201e5ebe1bbf Mon Sep 17 00:00:00 2001
From: "John W. Linville" <linville@tuxdriver.com>
Date: Mon, 7 Nov 2005 00:57:54 -0800
Subject: [PATCH] ia64: re-implement dma_get_cache_alignment to avoid
 EXPORT_SYMBOL

The current ia64 implementation of dma_get_cache_alignment does not work
for modules because it relies on a symbol which is not exported.  Direct
access to a global is a little ugly anyway, so this patch re-implements
dma_get_cache_alignment in a manner similar to what is currently used for
x86_64.

Signed-off-by: John W. Linville <linville@tuxdriver.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ia64/kernel/setup.c | 7 +++++++
 1 file changed, 7 insertions(+)

(limited to 'arch')

diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index fc56ca2da3..3af6de36a4 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -92,6 +92,13 @@ extern void efi_initialize_iomem_resources(struct resource *,
 extern char _text[], _end[], _etext[];
 
 unsigned long ia64_max_cacheline_size;
+
+int dma_get_cache_alignment(void)
+{
+        return ia64_max_cacheline_size;
+}
+EXPORT_SYMBOL(dma_get_cache_alignment);
+
 unsigned long ia64_iobase;	/* virtual address for I/O accesses */
 EXPORT_SYMBOL(ia64_iobase);
 struct io_space io_space[MAX_IO_SPACES];
-- 
cgit v1.2.2


From 732ee21f2894819781766a0cd88e32bdd630d11e Mon Sep 17 00:00:00 2001
From: Olof Johansson <olof@lixom.net>
Date: Mon, 7 Nov 2005 00:57:55 -0800
Subject: [PATCH] POWERPC/PPC64: Fix CONFIG_SMP=n build for ppc64

Two CONFIG_SMP=n build fixes due to missing <asm/smp.h> includes.

Signed-off-by: Olof Johansson <olof@lixom.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/powerpc/kernel/time.c | 1 +
 arch/ppc64/kernel/sysfs.c  | 1 +
 2 files changed, 2 insertions(+)

(limited to 'arch')

diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 6996a593dc..b1c89bc4bf 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -69,6 +69,7 @@
 #include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/hv_call_xm.h>
 #endif
+#include <asm/smp.h>
 
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 6654b35097..e99ec62c2c 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -20,6 +20,7 @@
 #include <asm/paca.h>
 #include <asm/lppaca.h>
 #include <asm/machdep.h>
+#include <asm/smp.h>
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
-- 
cgit v1.2.2


From c8e3c8b21bd7a317d071ab8cf478880e7a4f92d6 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Mon, 7 Nov 2005 00:57:58 -0800
Subject: [PATCH] ppc64: Fix zImage boot

The zImage wrapper has a bug where it doesn't claim() the memory for the
kernel properly, it forgets to take into account the offset between the ELF
header and the kernel itself.  This results on some machines, like G5s,
into a kernel that crashes at boot when clearing the BSS.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc64/boot/main.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index c1dc876bcc..e0dde24a72 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -203,8 +203,15 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
 		if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0)
 			break;
 	}
-	vmlinux.size = (unsigned long)elf64ph->p_filesz;
-	vmlinux.memsize = (unsigned long)elf64ph->p_memsz;
+	vmlinux.size = (unsigned long)elf64ph->p_filesz +
+		(unsigned long)elf64ph->p_offset;
+	/* We need to claim the memsize plus the file offset since gzip
+	 * will expand the header (file offset), then the kernel, then
+	 * possible rubbish we don't care about. But the kernel bss must
+	 * be claimed (it will be zero'd by the kernel itself)
+	 */
+	vmlinux.memsize = (unsigned long)elf64ph->p_memsz +
+		(unsigned long)elf64ph->p_offset;
 	printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
 	vmlinux.addr = try_claim(vmlinux.memsize);
 	if (vmlinux.addr == 0) {
-- 
cgit v1.2.2


From 863c84b97cb660dbb949398e196c0b1bbe4ed39f Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Mon, 7 Nov 2005 00:57:58 -0800
Subject: [PATCH] ppc: Fix ppc32 build after 64K pages

Oops, some last minute changes caused the 64K pages patch to break ppc32
build, this fixes it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/powerpc/Kconfig         | 1 +
 arch/powerpc/mm/ppc_mmu_32.c | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ca7acb0c79..55ce495705 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -605,6 +605,7 @@ config NODES_SPAN_OTHER_NODES
 
 config PPC_64K_PAGES
 	bool "64k page size"
+	depends on PPC64
 	help
 	  This option changes the kernel logical page size to 64k. On machines
           without processor support for 64k pages, the kernel will simulate
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index d137abd241..ed7fcfe5fd 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -188,9 +188,9 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
 
 	if (Hash == 0)
 		return;
-	pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address);
+	pmd = pmd_offset(pgd_offset(mm, ea), ea);
 	if (!pmd_none(*pmd))
-		add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd));
+		add_hash_page(mm->context, ea, pmd_val(*pmd));
 }
 
 /*
-- 
cgit v1.2.2


From 2104da90a9aeef31ff6441d171a7d0492088f1d0 Mon Sep 17 00:00:00 2001
From: Lee Nicks <allinux@gmail.com>
Date: Mon, 7 Nov 2005 00:58:10 -0800
Subject: [PATCH] ppc32: add watchdog & RTC support for Marvell EV64360BP board

This patch adds watchdog, RTC support for Marvell EV64360BP board.

Signed-off-by: Lee Nicks <allinux@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/configs/ev64360_defconfig | 73 +++++++++++++++++++++++++++-----------
 arch/ppc/platforms/ev64360.c       | 12 +++++++
 arch/ppc/syslib/Makefile           |  1 +
 3 files changed, 66 insertions(+), 20 deletions(-)

(limited to 'arch')

diff --git a/arch/ppc/configs/ev64360_defconfig b/arch/ppc/configs/ev64360_defconfig
index de9bbb791d..d471e578dc 100644
--- a/arch/ppc/configs/ev64360_defconfig
+++ b/arch/ppc/configs/ev64360_defconfig
@@ -1,17 +1,17 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc5
-# Fri Aug  5 15:18:23 2005
+# Linux kernel version: 2.6.14
+# Fri Oct 28 19:15:34 2005
 #
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_PPC=y
 CONFIG_PPC32=y
 CONFIG_GENERIC_NVRAM=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
@@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -35,6 +36,7 @@ CONFIG_SYSCTL=y
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -74,7 +76,7 @@ CONFIG_TAU=y
 # CONFIG_TAU_AVERAGE is not set
 # CONFIG_KEXEC is not set
 # CONFIG_CPU_FREQ is not set
-# CONFIG_PM is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_NOT_COHERENT_CACHE=y
 
@@ -86,22 +88,18 @@ CONFIG_NOT_COHERENT_CACHE=y
 # CONFIG_KATANA is not set
 # CONFIG_WILLOW is not set
 # CONFIG_CPCI690 is not set
-# CONFIG_PCORE is not set
 # CONFIG_POWERPMC250 is not set
 # CONFIG_CHESTNUT is not set
 # CONFIG_SPRUCE is not set
 # CONFIG_HDPU is not set
 # CONFIG_EV64260 is not set
 # CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
 # CONFIG_PPLUS is not set
 # CONFIG_PRPMC750 is not set
 # CONFIG_PRPMC800 is not set
 # CONFIG_SANDPOINT is not set
 # CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
 # CONFIG_EST8260 is not set
@@ -138,10 +136,13 @@ CONFIG_FLATMEM_MANUAL=y
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyMM0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2"
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
 CONFIG_SECCOMP=y
 CONFIG_ISA_DMA_API=y
 
@@ -152,7 +153,6 @@ CONFIG_GENERIC_ISA_DMA=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -206,13 +206,18 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
@@ -239,6 +244,7 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -251,6 +257,11 @@ CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -358,7 +369,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -379,6 +389,7 @@ CONFIG_IOSCHED_CFQ=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -419,6 +430,10 @@ CONFIG_NETDEVICES=y
 #
 # CONFIG_ARCNET is not set
 
+#
+# PHY device support
+#
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -434,6 +449,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
@@ -446,6 +462,7 @@ CONFIG_MV643XX_ETH_0=y
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -547,7 +564,20 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # Watchdog Cards
 #
-# CONFIG_WATCHDOG is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_MV64X60_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
 # CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
@@ -571,7 +601,6 @@ CONFIG_GEN_RTC=y
 # I2C support
 #
 # CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
@@ -582,12 +611,17 @@ CONFIG_GEN_RTC=y
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
 #
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -651,10 +685,6 @@ CONFIG_EXT2_FS=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -663,6 +693,7 @@ CONFIG_INOTIFY=y
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -683,11 +714,10 @@ CONFIG_DNOTIFY=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -735,6 +765,7 @@ CONFIG_SUNRPC=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -751,6 +782,7 @@ CONFIG_MSDOS_PARTITION=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
@@ -767,6 +799,7 @@ CONFIG_ZLIB_DEFLATE=y
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SERIAL_TEXT_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c
index b132456445..b9d844f88c 100644
--- a/arch/ppc/platforms/ev64360.c
+++ b/arch/ppc/platforms/ev64360.c
@@ -52,6 +52,8 @@ static u32		ev64360_bus_frequency;
 
 unsigned char	__res[sizeof(bd_t)];
 
+TODC_ALLOC();
+
 static int __init
 ev64360_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 {
@@ -182,6 +184,9 @@ ev64360_setup_peripherals(void)
 		 EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE, 0);
 	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
 
+	TODC_INIT(TODC_TYPE_DS1501, 0, 0,
+		ioremap(EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE), 8);
+
 	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
 		 EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
 	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
@@ -496,6 +501,13 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	ppc_md.power_off = ev64360_power_off;
 	ppc_md.halt = ev64360_halt;
 	ppc_md.find_end_of_memory = ev64360_find_end_of_memory;
+	ppc_md.init = NULL;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
 	ppc_md.calibrate_decr = ev64360_calibrate_decr;
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index b4ef15b45c..2e58c21052 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_BAMBOO)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_CPCI690)		+= todc_time.o pci_auto.o
 obj-$(CONFIG_EBONY)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_EV64260)		+= todc_time.o pci_auto.o
+obj-$(CONFIG_EV64360)		+= todc_time.o
 obj-$(CONFIG_CHESTNUT)		+= mv64360_pic.o pci_auto.o
 obj-$(CONFIG_GEMINI)		+= open_pic.o
 obj-$(CONFIG_GT64260)		+= gt64260_pic.o
-- 
cgit v1.2.2


From fcc188e7fdddd8b23f900e485e6b3db05e7375f4 Mon Sep 17 00:00:00 2001
From: Roland Dreier <rolandd@cisco.com>
Date: Mon, 7 Nov 2005 00:58:11 -0800
Subject: [PATCH] ppc32: Allow ERPN for early serial to depend on CPU type

The PowerPC 440SPe supports up to 16 GB of RAM, and therefore its IO registers
are at 0x4_xxxx_xxxx instead of being at 0x1_xxxx_xxxx like most other PPC 440
chips.  To allow for this, this patch moves the definition of the ERPN used
for mapping UART0 from being hard-coded in the head_44x.S assembly code to
being defined in ibm44x.h.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/kernel/head_44x.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 8b49679fad..677c571aa2 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -190,8 +190,8 @@ skpinv:	addi	r4,r4,1				/* Increment */
 
 	/* xlat fields */
 	lis	r4,UART0_PHYS_IO_BASE@h		/* RPN depends on SoC */
-#ifndef CONFIG_440EP
-	ori	r4,r4,0x0001		/* ERPN is 1 for second 4GB page */
+#ifdef UART0_PHYS_ERPN
+	ori	r4,r4,UART0_PHYS_ERPN		/* Add ERPN if above 4GB */
 #endif
 
 	/* attrib fields */
-- 
cgit v1.2.2


From 41aace4fe81e3da52fa80b8380e5d2d084f77691 Mon Sep 17 00:00:00 2001
From: Roland Dreier <rolandd@cisco.com>
Date: Mon, 7 Nov 2005 00:58:12 -0800
Subject: [PATCH] ppc32: Dump error status for both PLB segments on 440SP

The PowerPC 440SP SoC has two Processor Local Bus (PLB) segments (a
high-throughput segment and a low-latency segment).  Fix our PLB register
definitions to cope with this, and add code to dump the status of both
segments when a machine check occurs.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/syslib/ibm44x_common.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

(limited to 'arch')

diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
index 5152c8e413..ebae2e2fce 100644
--- a/arch/ppc/syslib/ibm44x_common.c
+++ b/arch/ppc/syslib/ibm44x_common.c
@@ -214,9 +214,20 @@ void __init ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned lo
 /* Called from machine_check_exception */
 void platform_machine_check(struct pt_regs *regs)
 {
+#ifdef CONFIG_440SP
+	printk("PLB0: BEAR=0x%08x%08x ACR=  0x%08x BESR= 0x%08x%08x\n",
+	       mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL),
+	       mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESRH),
+	       mfdcr(DCRN_PLB0_BESRL));
+	printk("PLB1: BEAR=0x%08x%08x ACR=  0x%08x BESR= 0x%08x%08x\n",
+	       mfdcr(DCRN_PLB1_BEARH), mfdcr(DCRN_PLB1_BEARL),
+	       mfdcr(DCRN_PLB1_ACR), mfdcr(DCRN_PLB1_BESRH),
+	       mfdcr(DCRN_PLB1_BESRL));
+#else
     	printk("PLB0: BEAR=0x%08x%08x ACR=  0x%08x BESR= 0x%08x\n",
 		mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL),
 		mfdcr(DCRN_PLB0_ACR),  mfdcr(DCRN_PLB0_BESR));
+#endif
 	printk("POB0: BEAR=0x%08x%08x BESR0=0x%08x BESR1=0x%08x\n",
 		mfdcr(DCRN_POB0_BEARH), mfdcr(DCRN_POB0_BEARL),
 		mfdcr(DCRN_POB0_BESR0), mfdcr(DCRN_POB0_BESR1));
-- 
cgit v1.2.2


From b0f7b8bc57ee90138a7c429951457027a90c326f Mon Sep 17 00:00:00 2001
From: Roland Dreier <rolandd@cisco.com>
Date: Mon, 7 Nov 2005 00:58:13 -0800
Subject: [PATCH] ppc32: Add 440SPe support

Add support for the AMCC PowerPC 440SPe SoC, including PCI Express in root
port mode.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/powerpc/kernel/cputable.c     |  10 +
 arch/ppc/platforms/4xx/Kconfig     |   8 +-
 arch/ppc/platforms/4xx/Makefile    |   1 +
 arch/ppc/platforms/4xx/ppc440spe.c | 148 +++++++++++++
 arch/ppc/platforms/4xx/ppc440spe.h |  66 ++++++
 arch/ppc/syslib/Makefile           |   1 +
 arch/ppc/syslib/ibm440sp_common.c  |   4 +-
 arch/ppc/syslib/ibm44x_common.c    |   2 +-
 arch/ppc/syslib/ppc440spe_pcie.c   | 442 +++++++++++++++++++++++++++++++++++++
 arch/ppc/syslib/ppc440spe_pcie.h   | 149 +++++++++++++
 arch/ppc/syslib/ppc4xx_pic.c       |  37 +++-
 11 files changed, 862 insertions(+), 6 deletions(-)
 create mode 100644 arch/ppc/platforms/4xx/ppc440spe.c
 create mode 100644 arch/ppc/platforms/4xx/ppc440spe.h
 create mode 100644 arch/ppc/syslib/ppc440spe_pcie.c
 create mode 100644 arch/ppc/syslib/ppc440spe_pcie.h

(limited to 'arch')

diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 33c63bcf69..cc4e9eb1c1 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -929,6 +929,16 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 	},
+	{ /* 440SPe Rev. A */
+		.pvr_mask		= 0xff000fff,
+		.pvr_value		= 0x53000890,
+		.cpu_name		= "440SPe Rev. A",
+		.cpu_features		= CPU_FTR_SPLIT_ID_CACHE |
+			CPU_FTR_USE_TB,
+		.cpu_user_features	= PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+	},
 #endif /* CONFIG_44x */
 #ifdef CONFIG_FSL_BOOKE
 	{	/* e200z5 */
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 76f4476cab..108d5a730f 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -124,9 +124,13 @@ config 440SP
 	depends on LUAN
 	default y
 
+config 440SPE
+	bool
+	default n
+
 config 440
 	bool
-	depends on 440GP || 440SP || 440EP
+	depends on 440GP || 440SP || 440SPE || 440EP
 	default y
 
 config 440A
@@ -168,7 +172,7 @@ config XILINX_OCP
 
 config IBM_EMAC4
 	bool
-	depends on 440GX || 440SP
+	depends on 440GX || 440SP || 440SPE
 	default y
 
 config BIOS_FIXUP
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile
index 1dd6d7fd6a..694accdb59 100644
--- a/arch/ppc/platforms/4xx/Makefile
+++ b/arch/ppc/platforms/4xx/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_440EP)		+= ibm440ep.o
 obj-$(CONFIG_440GP)		+= ibm440gp.o
 obj-$(CONFIG_440GX)		+= ibm440gx.o
 obj-$(CONFIG_440SP)		+= ibm440sp.o
+obj-$(CONFIG_440SPE)		+= ppc440spe.o
 obj-$(CONFIG_405EP)		+= ibm405ep.o
 obj-$(CONFIG_405GPR)		+= ibm405gpr.o
 obj-$(CONFIG_VIRTEX_II_PRO)	+= virtex-ii_pro.o
diff --git a/arch/ppc/platforms/4xx/ppc440spe.c b/arch/ppc/platforms/4xx/ppc440spe.c
new file mode 100644
index 0000000000..6139a0b339
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ppc440spe.c
@@ -0,0 +1,148 @@
+/*
+ * arch/ppc/platforms/4xx/ppc440spe.c
+ *
+ * PPC440SPe I/O descriptions
+ *
+ * Roland Dreier <rolandd@cisco.com>
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ppc440spe.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ppc440spe_emac0_def = {
+	.rgmii_idx	= -1,		/* No RGMII */
+	.rgmii_mux	= -1,		/* No RGMII */
+	.zmii_idx       = -1,           /* No ZMII */
+	.zmii_mux       = -1,           /* No ZMII */
+	.mal_idx        = 0,            /* MAL device index */
+	.mal_rx_chan    = 0,            /* MAL rx channel number */
+	.mal_tx_chan    = 0,            /* MAL tx channel number */
+	.wol_irq        = 61,  		/* WOL interrupt number */
+	.mdio_idx       = -1,           /* No shared MDIO */
+	.tah_idx	= -1,		/* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ppc440spe_mal0_def = {
+	.num_tx_chans   = 1,    	/* Number of TX channels */
+	.num_rx_chans   = 1,    	/* Number of RX channels */
+	.txeob_irq	= 38,		/* TX End Of Buffer IRQ  */
+	.rxeob_irq	= 39,		/* RX End Of Buffer IRQ  */
+	.txde_irq	= 34,		/* TX Descriptor Error IRQ */
+	.rxde_irq	= 35,		/* RX Descriptor Error IRQ */
+	.serr_irq	= 33,		/* MAL System Error IRQ    */
+	.dcr_base	= DCRN_MAL_BASE /* MAL0_CFG DCR number */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ppc440spe_iic0_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ppc440spe_iic1_def = {
+	.fast_mode	= 0,		/* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 0,
+	  .paddr	= PPC440SPE_UART0_ADDR,
+	  .irq		= UART0_INT,
+	  .pm		= IBM_CPM_UART0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 1,
+	  .paddr	= PPC440SPE_UART1_ADDR,
+	  .irq		= UART1_INT,
+	  .pm		= IBM_CPM_UART1,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_16550,
+	  .index	= 2,
+	  .paddr	= PPC440SPE_UART2_ADDR,
+	  .irq		= UART2_INT,
+	  .pm		= IBM_CPM_UART2,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .index	= 0,
+	  .paddr	= 0x00000004f0000400ULL,
+	  .irq		= 2,
+	  .pm		= IBM_CPM_IIC0,
+	  .additions	= &ppc440spe_iic0_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_IIC,
+	  .index	= 1,
+	  .paddr	= 0x00000004f0000500ULL,
+	  .irq		= 3,
+	  .pm		= IBM_CPM_IIC1,
+	  .additions	= &ppc440spe_iic1_def,
+	  .show		= &ocp_show_iic_data
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_GPIO,
+	  .index	= 0,
+	  .paddr	= 0x00000004f0000700ULL,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= IBM_CPM_GPIO0,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_MAL,
+	  .paddr	= OCP_PADDR_NA,
+	  .irq		= OCP_IRQ_NA,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ppc440spe_mal0_def,
+	  .show		= &ocp_show_mal_data,
+	},
+	{ .vendor	= OCP_VENDOR_IBM,
+	  .function	= OCP_FUNC_EMAC,
+	  .index	= 0,
+	  .paddr	= 0x00000004f0000800ULL,
+	  .irq		= 60,
+	  .pm		= OCP_CPM_NA,
+	  .additions	= &ppc440spe_emac0_def,
+	  .show		= &ocp_show_emac_data,
+	},
+	{ .vendor	= OCP_VENDOR_INVALID
+	}
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+	{ .polarity     = 0xffffffff,
+	  .triggering   = 0x010f0004,
+	  .ext_irq_mask = 0x00000000,
+	},
+	{ .polarity     = 0xffffffff,
+	  .triggering   = 0x001f8040,
+	  .ext_irq_mask = 0x00007c30,   /* IRQ6 - IRQ7, IRQ8 - IRQ12 */
+	},
+	{ .polarity     = 0xffffffff,
+	  .triggering   = 0x00000000,
+	  .ext_irq_mask = 0x000000fc,   /* IRQ0 - IRQ5 */
+	},
+	{ .polarity     = 0xffffffff,
+	  .triggering   = 0x00000000,
+	  .ext_irq_mask = 0x00000000,
+	},
+};
diff --git a/arch/ppc/platforms/4xx/ppc440spe.h b/arch/ppc/platforms/4xx/ppc440spe.h
new file mode 100644
index 0000000000..2216846973
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ppc440spe.h
@@ -0,0 +1,66 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440spe.h
+ *
+ * PPC440SPe definitions
+ *
+ * Roland Dreier <rolandd@cisco.com>
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004-2005 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_PPC440SPE_H
+#define __PPC_PLATFORMS_PPC440SPE_H
+
+#include <linux/config.h>
+
+#include <asm/ibm44x.h>
+
+/* UART */
+#define PPC440SPE_UART0_ADDR	0x00000004f0000200ULL
+#define PPC440SPE_UART1_ADDR	0x00000004f0000300ULL
+#define PPC440SPE_UART2_ADDR	0x00000004f0000600ULL
+#define UART0_INT		0
+#define UART1_INT		1
+#define UART2_INT		37
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0		0x80000000	/* IIC interface */
+#define IBM_CPM_IIC1		0x40000000	/* IIC interface */
+#define IBM_CPM_PCI		0x20000000	/* PCI bridge */
+#define IBM_CPM_CPU		    0x02000000	/* processor core */
+#define IBM_CPM_DMA		    0x01000000	/* DMA controller */
+#define IBM_CPM_BGO		    0x00800000	/* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI		    0x00400000	/* OPB to PLB bridge */
+#define IBM_CPM_EBC		    0x00200000	/* External Bux Controller */
+#define IBM_CPM_EBM		    0x00100000	/* Ext Bus Master Interface */
+#define IBM_CPM_DMC		    0x00080000	/* SDRAM peripheral controller */
+#define IBM_CPM_PLB		    0x00040000	/* PLB bus arbiter */
+#define IBM_CPM_SRAM		0x00020000	/* SRAM memory controller */
+#define IBM_CPM_PPM		    0x00002000	/* PLB Performance Monitor */
+#define IBM_CPM_UIC1		0x00001000	/* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0		0x00000800	/* General Purpose IO (??) */
+#define IBM_CPM_GPT		    0x00000400	/* General Purpose Timers  */
+#define IBM_CPM_UART0		0x00000200	/* serial port 0 */
+#define IBM_CPM_UART1		0x00000100	/* serial port 1 */
+#define IBM_CPM_UART2		0x00000100	/* serial port 1 */
+#define IBM_CPM_UIC0		0x00000080	/* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK		0x00000040	/* CPU timers */
+#define IBM_CPM_EMAC0  		0x00000020	/* EMAC 0     */
+
+#define DFLT_IBM4xx_PM		~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \
+				| IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \
+				| IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \
+				| IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \
+				| IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \
+				| IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \
+			  	| IBM_CPM_EMAC2 | IBM_CPM_EMAC3 )
+#endif /* __PPC_PLATFORMS_PPC440SP_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 2e58c21052..13dff1e51f 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_440EP)		+= ibm440gx_common.o
 obj-$(CONFIG_440GP)		+= ibm440gp_common.o
 obj-$(CONFIG_440GX)		+= ibm440gx_common.o
 obj-$(CONFIG_440SP)		+= ibm440gx_common.o ibm440sp_common.o
+obj-$(CONFIG_440SPE)		+= ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o
 ifeq ($(CONFIG_4xx),y)
 ifeq ($(CONFIG_VIRTEX_II_PRO),y)
 obj-$(CONFIG_40x)		+= xilinx_pic.o
diff --git a/arch/ppc/syslib/ibm440sp_common.c b/arch/ppc/syslib/ibm440sp_common.c
index 417d4cff77..cdafda127d 100644
--- a/arch/ppc/syslib/ibm440sp_common.c
+++ b/arch/ppc/syslib/ibm440sp_common.c
@@ -1,7 +1,7 @@
 /*
  * arch/ppc/syslib/ibm440sp_common.c
  *
- * PPC440SP system library
+ * PPC440SP/PPC440SPe system library
  *
  * Matt Porter <mporter@kernel.crashing.org>
  * Copyright 2002-2005 MontaVista Software Inc.
@@ -35,7 +35,7 @@ unsigned long __init ibm440sp_find_end_of_memory(void)
 	u32 mem_size = 0;
 
 	/* Read two bank sizes and sum */
-	for (i=0; i<2; i++)
+	for (i=0; i< MQ0_NUM_BANKS; i++)
 		switch (mfdcr(DCRN_MQ0_BS0BAS + i) & MQ0_CONFIG_SIZE_MASK) {
 			case MQ0_CONFIG_SIZE_8M:
 				mem_size += PPC44x_MEM_SIZE_8M;
diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
index ebae2e2fce..a5bef9d163 100644
--- a/arch/ppc/syslib/ibm44x_common.c
+++ b/arch/ppc/syslib/ibm44x_common.c
@@ -214,7 +214,7 @@ void __init ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned lo
 /* Called from machine_check_exception */
 void platform_machine_check(struct pt_regs *regs)
 {
-#ifdef CONFIG_440SP
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
 	printk("PLB0: BEAR=0x%08x%08x ACR=  0x%08x BESR= 0x%08x%08x\n",
 	       mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL),
 	       mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESRH),
diff --git a/arch/ppc/syslib/ppc440spe_pcie.c b/arch/ppc/syslib/ppc440spe_pcie.c
new file mode 100644
index 0000000000..1509fc1ddf
--- /dev/null
+++ b/arch/ppc/syslib/ppc440spe_pcie.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/ibm44x.h>
+
+#include "ppc440spe_pcie.h"
+
+static int
+pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		     int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+
+	if (PCI_SLOT(devfn) != 1)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	offset += devfn << 12;
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		*val = in_8(hose->cfg_data + offset);
+		break;
+	case 2:
+		*val = in_le16(hose->cfg_data + offset);
+		break;
+	default:
+		*val = in_le32(hose->cfg_data + offset);
+		break;
+	}
+
+	if (0) printk("%s: read %x(%d) @ %x\n", __func__, *val, len, offset);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+pcie_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		      int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+
+	if (PCI_SLOT(devfn) != 1)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	offset += devfn << 12;
+
+	switch (len) {
+	case 1:
+		out_8(hose->cfg_data + offset, val);
+		break;
+	case 2:
+		out_le16(hose->cfg_data + offset, val);
+		break;
+	default:
+		out_le32(hose->cfg_data + offset, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pcie_pci_ops =
+{
+	.read  = pcie_read_config,
+	.write = pcie_write_config
+};
+
+enum {
+	PTYPE_ENDPOINT		= 0x0,
+	PTYPE_LEGACY_ENDPOINT	= 0x1,
+	PTYPE_ROOT_PORT		= 0x4,
+
+	LNKW_X1			= 0x1,
+	LNKW_X4			= 0x4,
+	LNKW_X8			= 0x8
+};
+
+static void check_error(void)
+{
+	u32 valPE0, valPE1, valPE2;
+
+	/* SDR0_PEGPLLLCT1 reset */
+	if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) {
+		printk(KERN_INFO "PCIE: SDR0_PEGPLLLCT1 reset error 0x%8x\n", valPE0);
+	}
+
+	valPE0 = SDR_READ(PESDR0_RCSSET);
+	valPE1 = SDR_READ(PESDR1_RCSSET);
+	valPE2 = SDR_READ(PESDR2_RCSSET);
+
+	/* SDR0_PExRCSSET rstgu */
+	if ( !(valPE0 & 0x01000000) ||
+	     !(valPE1 & 0x01000000) ||
+	     !(valPE2 & 0x01000000)) {
+		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET rstgu error\n");
+	}
+
+	/* SDR0_PExRCSSET rstdl */
+	if ( !(valPE0 & 0x00010000) ||
+	     !(valPE1 & 0x00010000) ||
+	     !(valPE2 & 0x00010000)) {
+		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET rstdl error\n");
+	}
+
+	/* SDR0_PExRCSSET rstpyn */
+	if ( (valPE0 & 0x00001000) ||
+	     (valPE1 & 0x00001000) ||
+	     (valPE2 & 0x00001000)) {
+		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET rstpyn error\n");
+	}
+
+	/* SDR0_PExRCSSET hldplb */
+	if ( (valPE0 & 0x10000000) ||
+	     (valPE1 & 0x10000000) ||
+	     (valPE2 & 0x10000000)) {
+		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET hldplb error\n");
+	}
+
+	/* SDR0_PExRCSSET rdy */
+	if ( (valPE0 & 0x00100000) ||
+	     (valPE1 & 0x00100000) ||
+	     (valPE2 & 0x00100000)) {
+		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET rdy error\n");
+	}
+
+	/* SDR0_PExRCSSET shutdown */
+	if ( (valPE0 & 0x00000100) ||
+	     (valPE1 & 0x00000100) ||
+	     (valPE2 & 0x00000100)) {
+		printk(KERN_INFO "PCIE:  SDR0_PExRCSSET shutdown error\n");
+	}
+}
+
+/*
+ * Initialize PCI Express core as described in User Manual section 27.12.1
+ */
+int ppc440spe_init_pcie(void)
+{
+	/* Set PLL clock receiver to LVPECL */
+	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28);
+
+	check_error();
+
+	printk(KERN_INFO "PCIE initialization OK\n");
+
+	if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000))
+		printk(KERN_INFO "PESDR_PLLCT2 resistance calibration failed (0x%08x)\n",
+		       SDR_READ(PESDR0_PLLLCT2));
+
+	/* De-assert reset of PCIe PLL, wait for lock */
+	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
+	udelay(3);
+
+	return 0;
+}
+
+int ppc440spe_init_pcie_rootport(int port)
+{
+	static int core_init;
+	void __iomem *utl_base;
+	u32 val = 0;
+	int i;
+
+	if (!core_init) {
+		++core_init;
+		i = ppc440spe_init_pcie();
+		if (i)
+			return i;
+	}
+
+	/*
+	 * Initialize various parts of the PCI Express core for our port:
+	 *
+	 * - Set as a root port and enable max width
+	 *   (PXIE0 -> X8, PCIE1 and PCIE2 -> X4).
+	 * - Set up UTL configuration.
+	 * - Increase SERDES drive strength to levels suggested by AMCC.
+	 * - De-assert RSTPYN, RSTDL and RSTGU.
+	 */
+	switch (port) {
+	case 0:
+		SDR_WRITE(PESDR0_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12);
+
+		SDR_WRITE(PESDR0_UTLSET1, 0x21222222);
+		SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
+
+		SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
+		SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
+
+		SDR_WRITE(PESDR0_RCSSET,
+			  (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+		break;
+
+	case 1:
+		SDR_WRITE(PESDR1_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
+
+		SDR_WRITE(PESDR1_UTLSET1, 0x21222222);
+		SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
+
+		SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000);
+		SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000);
+		SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
+		SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
+
+		SDR_WRITE(PESDR1_RCSSET,
+			  (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+		break;
+
+	case 2:
+		SDR_WRITE(PESDR2_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
+
+		SDR_WRITE(PESDR2_UTLSET1, 0x21222222);
+		SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
+
+		SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000);
+		SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
+		SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
+		SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
+
+		SDR_WRITE(PESDR2_RCSSET,
+			  (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+		break;
+	}
+
+	mdelay(1000);
+
+	switch (port) {
+	case 0: val = SDR_READ(PESDR0_RCSSTS); break;
+	case 1: val = SDR_READ(PESDR1_RCSSTS); break;
+	case 2: val = SDR_READ(PESDR2_RCSSTS); break;
+	}
+
+	if (!(val & (1 << 20)))
+		printk(KERN_INFO "PCIE%d: PGRST inactive\n", port);
+	else
+		printk(KERN_WARNING "PGRST for PCIE%d failed %08x\n", port, val);
+
+	switch (port) {
+	case 0: printk(KERN_INFO "PCIE0: LOOP %08x\n", SDR_READ(PESDR0_LOOP)); break;
+	case 1: printk(KERN_INFO "PCIE1: LOOP %08x\n", SDR_READ(PESDR1_LOOP)); break;
+	case 2: printk(KERN_INFO "PCIE2: LOOP %08x\n", SDR_READ(PESDR2_LOOP)); break;
+	}
+
+	/*
+	 * Map UTL registers at 0xc_1000_0n00
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+		break;
+
+	case 2:
+		mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
+		mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
+		mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
+		mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+	}
+
+	utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100);
+
+	/*
+	 * Set buffer allocations and then assert VRB and TXE.
+	 */
+	out_be32(utl_base + PEUTL_OUTTR,   0x08000000);
+	out_be32(utl_base + PEUTL_INTR,    0x02000000);
+	out_be32(utl_base + PEUTL_OPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_PBBSZ,   0x53000000);
+	out_be32(utl_base + PEUTL_IPHBSZ,  0x08000000);
+	out_be32(utl_base + PEUTL_IPDBSZ,  0x10000000);
+	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+	out_be32(utl_base + PEUTL_PCTL,    0x80800066);
+
+	iounmap(utl_base);
+
+	/*
+	 * We map PCI Express configuration access into the 512MB regions
+	 *     PCIE0: 0xc_4000_0000
+	 *     PCIE1: 0xc_8000_0000
+	 *     PCIE2: 0xc_c000_0000
+	 */
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
+		mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
+		break;
+
+	case 1:
+		mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
+		mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
+		break;
+
+	case 2:
+		mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
+		mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
+		break;
+	}
+
+	/*
+	 * Check for VC0 active and assert RDY.
+	 */
+	switch (port) {
+	case 0:
+		if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16)))
+			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20);
+		break;
+	case 1:
+		if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16)))
+			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20);
+		break;
+	case 2:
+		if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16)))
+			printk(KERN_WARNING "PCIE0: VC0 not active\n");
+		SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20);
+		break;
+	}
+
+#if 0
+	/* Dump all config regs */
+	for (i = 0x300; i <= 0x320; ++i)
+		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+	for (i = 0x340; i <= 0x353; ++i)
+		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+	for (i = 0x370; i <= 0x383; ++i)
+		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+	for (i = 0x3a0; i <= 0x3a2; ++i)
+		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+	for (i = 0x3c0; i <= 0x3c3; ++i)
+		printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+#endif
+
+	mdelay(100);
+
+	return 0;
+}
+
+void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
+{
+	void __iomem *mbase;
+
+	/*
+	 * Map 16MB, which is enough for 4 bits of bus #
+	 */
+	hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000,
+				   1 << 24);
+	hose->ops = &pcie_pci_ops;
+
+	/*
+	 * Set bus numbers on our root port
+	 */
+	mbase = ioremap64(0xc50000000ull + port * 0x40000000, 4096);
+	out_8(mbase + PCI_PRIMARY_BUS, 0);
+	out_8(mbase + PCI_SECONDARY_BUS, 0);
+
+	/*
+	 * Set up outbound translation to hose->mem_space from PLB
+	 * addresses at an offset of 0xd_0000_0000.  We set the low
+	 * bits of the mask to 11 to turn off splitting into 8
+	 * subregions and to enable the outbound translation.
+	 */
+	out_le32(mbase + PECFG_POM0LAH, 0);
+	out_le32(mbase + PECFG_POM0LAL, hose->mem_space.start);
+
+	switch (port) {
+	case 0:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0),  0x0000000d);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0),  hose->mem_space.start);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+		      ~(hose->mem_space.end - hose->mem_space.start) | 3);
+		break;
+	case 1:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1),  0x0000000d);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1),  hose->mem_space.start);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+		      ~(hose->mem_space.end - hose->mem_space.start) | 3);
+
+		break;
+	case 2:
+		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2),  0x0000000d);
+		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2),  hose->mem_space.start);
+		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+		      ~(hose->mem_space.end - hose->mem_space.start) | 3);
+		break;
+	}
+
+	/* Set up 16GB inbound memory window at 0 */
+	out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+	out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
+	out_le32(mbase + PECFG_BAR0LMPA, 0);
+	out_le32(mbase + PECFG_PIM0LAL, 0);
+	out_le32(mbase + PECFG_PIM0LAH, 0);
+	out_le32(mbase + PECFG_PIMEN, 0x1);
+
+	/* Enable I/O, Mem, and Busmaster cycles */
+	out_le16(mbase + PCI_COMMAND,
+		 in_le16(mbase + PCI_COMMAND) |
+		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+	iounmap(mbase);
+}
diff --git a/arch/ppc/syslib/ppc440spe_pcie.h b/arch/ppc/syslib/ppc440spe_pcie.h
new file mode 100644
index 0000000000..55b765ad32
--- /dev/null
+++ b/arch/ppc/syslib/ppc440spe_pcie.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PPC_SYSLIB_PPC440SPE_PCIE_H
+#define __PPC_SYSLIB_PPC440SPE_PCIE_H
+
+#define DCRN_SDR0_CFGADDR	0x00e
+#define DCRN_SDR0_CFGDATA	0x00f
+
+#define DCRN_PCIE0_BASE		0x100
+#define DCRN_PCIE1_BASE		0x120
+#define DCRN_PCIE2_BASE		0x140
+#define PCIE0			DCRN_PCIE0_BASE
+#define PCIE1			DCRN_PCIE1_BASE
+#define PCIE2			DCRN_PCIE2_BASE
+
+#define DCRN_PEGPL_CFGBAH(base)		(base + 0x00)
+#define DCRN_PEGPL_CFGBAL(base)		(base + 0x01)
+#define DCRN_PEGPL_CFGMSK(base)		(base + 0x02)
+#define DCRN_PEGPL_MSGBAH(base)		(base + 0x03)
+#define DCRN_PEGPL_MSGBAL(base)		(base + 0x04)
+#define DCRN_PEGPL_MSGMSK(base)		(base + 0x05)
+#define DCRN_PEGPL_OMR1BAH(base)	(base + 0x06)
+#define DCRN_PEGPL_OMR1BAL(base)	(base + 0x07)
+#define DCRN_PEGPL_OMR1MSKH(base)	(base + 0x08)
+#define DCRN_PEGPL_OMR1MSKL(base)	(base + 0x09)
+#define DCRN_PEGPL_REGBAH(base)		(base + 0x12)
+#define DCRN_PEGPL_REGBAL(base)		(base + 0x13)
+#define DCRN_PEGPL_REGMSK(base)		(base + 0x14)
+#define DCRN_PEGPL_SPECIAL(base)	(base + 0x15)
+
+/*
+ * System DCRs (SDRs)
+ */
+#define PESDR0_PLLLCT1		0x03a0
+#define PESDR0_PLLLCT2		0x03a1
+#define PESDR0_PLLLCT3		0x03a2
+
+#define PESDR0_UTLSET1		0x0300
+#define PESDR0_UTLSET2		0x0301
+#define PESDR0_DLPSET		0x0302
+#define PESDR0_LOOP		0x0303
+#define PESDR0_RCSSET		0x0304
+#define PESDR0_RCSSTS		0x0305
+#define PESDR0_HSSL0SET1	0x0306
+#define PESDR0_HSSL0SET2	0x0307
+#define PESDR0_HSSL0STS		0x0308
+#define PESDR0_HSSL1SET1	0x0309
+#define PESDR0_HSSL1SET2	0x030a
+#define PESDR0_HSSL1STS		0x030b
+#define PESDR0_HSSL2SET1	0x030c
+#define PESDR0_HSSL2SET2	0x030d
+#define PESDR0_HSSL2STS		0x030e
+#define PESDR0_HSSL3SET1	0x030f
+#define PESDR0_HSSL3SET2	0x0310
+#define PESDR0_HSSL3STS		0x0311
+#define PESDR0_HSSL4SET1	0x0312
+#define PESDR0_HSSL4SET2	0x0313
+#define PESDR0_HSSL4STS		0x0314
+#define PESDR0_HSSL5SET1	0x0315
+#define PESDR0_HSSL5SET2	0x0316
+#define PESDR0_HSSL5STS		0x0317
+#define PESDR0_HSSL6SET1	0x0318
+#define PESDR0_HSSL6SET2	0x0319
+#define PESDR0_HSSL6STS		0x031a
+#define PESDR0_HSSL7SET1	0x031b
+#define PESDR0_HSSL7SET2	0x031c
+#define PESDR0_HSSL7STS		0x031d
+#define PESDR0_HSSCTLSET	0x031e
+#define PESDR0_LANE_ABCD	0x031f
+#define PESDR0_LANE_EFGH	0x0320
+
+#define PESDR1_UTLSET1		0x0340
+#define PESDR1_UTLSET2		0x0341
+#define PESDR1_DLPSET		0x0342
+#define PESDR1_LOOP		0x0343
+#define PESDR1_RCSSET		0x0344
+#define PESDR1_RCSSTS		0x0345
+#define PESDR1_HSSL0SET1	0x0346
+#define PESDR1_HSSL0SET2	0x0347
+#define PESDR1_HSSL0STS		0x0348
+#define PESDR1_HSSL1SET1	0x0349
+#define PESDR1_HSSL1SET2	0x034a
+#define PESDR1_HSSL1STS		0x034b
+#define PESDR1_HSSL2SET1	0x034c
+#define PESDR1_HSSL2SET2	0x034d
+#define PESDR1_HSSL2STS		0x034e
+#define PESDR1_HSSL3SET1	0x034f
+#define PESDR1_HSSL3SET2	0x0350
+#define PESDR1_HSSL3STS		0x0351
+#define PESDR1_HSSCTLSET	0x0352
+#define PESDR1_LANE_ABCD	0x0353
+
+#define PESDR2_UTLSET1		0x0370
+#define PESDR2_UTLSET2		0x0371
+#define PESDR2_DLPSET		0x0372
+#define PESDR2_LOOP		0x0373
+#define PESDR2_RCSSET		0x0374
+#define PESDR2_RCSSTS		0x0375
+#define PESDR2_HSSL0SET1	0x0376
+#define PESDR2_HSSL0SET2	0x0377
+#define PESDR2_HSSL0STS		0x0378
+#define PESDR2_HSSL1SET1	0x0379
+#define PESDR2_HSSL1SET2	0x037a
+#define PESDR2_HSSL1STS		0x037b
+#define PESDR2_HSSL2SET1	0x037c
+#define PESDR2_HSSL2SET2	0x037d
+#define PESDR2_HSSL2STS		0x037e
+#define PESDR2_HSSL3SET1	0x037f
+#define PESDR2_HSSL3SET2	0x0380
+#define PESDR2_HSSL3STS		0x0381
+#define PESDR2_HSSCTLSET	0x0382
+#define PESDR2_LANE_ABCD	0x0383
+
+/*
+ * UTL register offsets
+ */
+#define PEUTL_PBBSZ		0x20
+#define PEUTL_OPDBSZ		0x68
+#define PEUTL_IPHBSZ		0x70
+#define PEUTL_IPDBSZ		0x78
+#define PEUTL_OUTTR		0x90
+#define PEUTL_INTR		0x98
+#define PEUTL_PCTL		0xa0
+#define PEUTL_RCIRQEN		0xb8
+
+/*
+ * Config space register offsets
+ */
+#define PECFG_BAR0LMPA		0x210
+#define PECFG_BAR0HMPA		0x214
+#define PECFG_PIMEN		0x33c
+#define PECFG_PIM0LAL		0x340
+#define PECFG_PIM0LAH		0x344
+#define PECFG_POM0LAL		0x380
+#define PECFG_POM0LAH		0x384
+
+int ppc440spe_init_pcie(void);
+int ppc440spe_init_pcie_rootport(int port);
+void ppc440spe_setup_pcie(struct pci_controller *hose, int port);
+
+#endif /* __PPC_SYSLIB_PPC440SPE_PCIE_H */
diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
index 0b435633a0..aa4165144e 100644
--- a/arch/ppc/syslib/ppc4xx_pic.c
+++ b/arch/ppc/syslib/ppc4xx_pic.c
@@ -38,6 +38,7 @@ extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak));
 #define IRQ_MASK_UICx(irq)		(1 << (31 - ((irq) & 0x1f)))
 #define IRQ_MASK_UIC1(irq)		IRQ_MASK_UICx(irq)
 #define IRQ_MASK_UIC2(irq)		IRQ_MASK_UICx(irq)
+#define IRQ_MASK_UIC3(irq)		IRQ_MASK_UICx(irq)
 
 #define UIC_HANDLERS(n)							\
 static void ppc4xx_uic##n##_enable(unsigned int irq)			\
@@ -88,7 +89,38 @@ static void ppc4xx_uic##n##_end(unsigned int irq)			\
 	.end 		= ppc4xx_uic##n##_end,				\
 }									\
 
-#if NR_UICS == 3
+#if NR_UICS == 4
+#define ACK_UIC0_PARENT
+#define ACK_UIC1_PARENT	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
+#define ACK_UIC2_PARENT	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC2NC);
+#define ACK_UIC3_PARENT	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC3NC);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
+UIC_HANDLERS(2);
+UIC_HANDLERS(3);
+
+static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+{
+	u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
+	if (uic0 & UIC0_UIC1NC)
+		return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
+	else if (uic0 & UIC0_UIC2NC)
+		return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2)));
+	else if (uic0 & UIC0_UIC3NC)
+		return 128 - ffs(mfdcr(DCRN_UIC_MSR(UIC3)));
+	else
+		return uic0 ? 32 - ffs(uic0) : -1;
+}
+
+static void __init ppc4xx_pic_impl_init(void)
+{
+	/* Enable cascade interrupts in UIC0 */
+	ppc_cached_irq_mask[0] |= UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC;
+	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC);
+	mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
+}
+
+#elif NR_UICS == 3
 #define ACK_UIC0_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
 #define ACK_UIC1_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
 #define ACK_UIC2_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
@@ -170,6 +202,9 @@ static struct ppc4xx_uic_impl {
 	{ .decl = DECLARE_UIC(1), .base = UIC1 },
 #if NR_UICS > 2
 	{ .decl = DECLARE_UIC(2), .base = UIC2 },
+#if NR_UICS > 3
+	{ .decl = DECLARE_UIC(3), .base = UIC3 },
+#endif
 #endif
 #endif
 };
-- 
cgit v1.2.2


From 90eb2665841d7b444602736e2141a01c948f75b1 Mon Sep 17 00:00:00 2001
From: Roland Dreier <rolandd@cisco.com>
Date: Mon, 7 Nov 2005 00:58:14 -0800
Subject: [PATCH] ppc32: Add Yucca (440SPe eval board) platform

Add support for AMCC PowerPC 440SPe "Yucca" eval board platform.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/boot/simple/Makefile   |   6 +
 arch/ppc/platforms/4xx/Kconfig  |  11 +-
 arch/ppc/platforms/4xx/Makefile |   1 +
 arch/ppc/platforms/4xx/yucca.c  | 395 ++++++++++++++++++++++++++++++++++++++++
 arch/ppc/platforms/4xx/yucca.h  | 111 +++++++++++
 arch/ppc/syslib/Makefile        |   1 +
 6 files changed, 523 insertions(+), 2 deletions(-)
 create mode 100644 arch/ppc/platforms/4xx/yucca.c
 create mode 100644 arch/ppc/platforms/4xx/yucca.h

(limited to 'arch')

diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index b7bd8f61a4..ff0904ee88 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -79,6 +79,12 @@ zimageinitrd-$(CONFIG_LUAN)		:= zImage.initrd-TREE
   entrypoint-$(CONFIG_LUAN)		:= 0x01000000
      extra.o-$(CONFIG_LUAN)		:= pibs.o
 
+      zimage-$(CONFIG_YUCCA)		:= zImage-TREE
+zimageinitrd-$(CONFIG_YUCCA)		:= zImage.initrd-TREE
+         end-$(CONFIG_YUCCA)		:= yucca
+  entrypoint-$(CONFIG_YUCCA)		:= 0x01000000
+     extra.o-$(CONFIG_YUCCA)		:= pibs.o
+
       zimage-$(CONFIG_OCOTEA)		:= zImage-TREE
 zimageinitrd-$(CONFIG_OCOTEA)		:= zImage.initrd-TREE
          end-$(CONFIG_OCOTEA)		:= ocotea
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 108d5a730f..e70e4c6ec7 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -82,6 +82,12 @@ config LUAN
 	help
 	  This option enables support for the IBM PPC440SP evaluation board.
 
+config YUCCA
+	bool "Yucca"
+	select WANT_EARLY_SERIAL
+	help
+	  This option enables support for the AMCC PPC440SPe evaluation board.
+
 config OCOTEA
 	bool "Ocotea"
 	select WANT_EARLY_SERIAL
@@ -126,7 +132,8 @@ config 440SP
 
 config 440SPE
 	bool
-	default n
+	depends on YUCCA
+	default y
 
 config 440
 	bool
@@ -162,7 +169,7 @@ config BOOKE
 
 config IBM_OCP
 	bool
-	depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+	depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
 	default y
 
 config XILINX_OCP
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile
index 694accdb59..c9bb611709 100644
--- a/arch/ppc/platforms/4xx/Makefile
+++ b/arch/ppc/platforms/4xx/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_EBONY)		+= ebony.o
 obj-$(CONFIG_EP405)		+= ep405.o
 obj-$(CONFIG_BUBINGA)		+= bubinga.o
 obj-$(CONFIG_LUAN)		+= luan.o
+obj-$(CONFIG_YUCCA)		+= yucca.o
 obj-$(CONFIG_OCOTEA)		+= ocotea.o
 obj-$(CONFIG_REDWOOD_5)		+= redwood5.o
 obj-$(CONFIG_REDWOOD_6)		+= redwood6.o
diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c
new file mode 100644
index 0000000000..e60f4bd437
--- /dev/null
+++ b/arch/ppc/platforms/4xx/yucca.c
@@ -0,0 +1,395 @@
+/*
+ * arch/ppc/platforms/4xx/yucca.c
+ *
+ * Yucca board specific routines
+ *
+ * Roland Dreier <rolandd@cisco.com> (based on luan.c by Matt Porter)
+ *
+ * Copyright 2004-2005 MontaVista Software Inc.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/ibm44x_common.h>
+#include <syslib/ibm440gx_common.h>
+#include <syslib/ibm440sp_common.h>
+#include <syslib/ppc440spe_pcie.h>
+
+extern bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+static void __init
+yucca_calibrate_decr(void)
+{
+	unsigned int freq;
+
+	if (mfspr(SPRN_CCR1) & CCR1_TCS)
+		freq = YUCCA_TMR_CLK;
+	else
+		freq = clocks.cpu;
+
+	ibm44x_calibrate_decr(freq);
+}
+
+static int
+yucca_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: AMCC\n");
+	seq_printf(m, "machine\t\t: PPC440SPe EVB (Yucca)\n");
+
+	return 0;
+}
+
+static enum {
+	HOSE_UNKNOWN,
+	HOSE_PCIX,
+	HOSE_PCIE0,
+	HOSE_PCIE1,
+	HOSE_PCIE2
+} hose_type[4];
+
+static inline int
+yucca_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+	if (hose_type[hose->index] == HOSE_PCIX) {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 *	  A   B   C   D
+		 */
+		{
+			{ 81, -1, -1, -1 },	/* IDSEL 1 - PCIX0 Slot 0 */
+		};
+		const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else if (hose_type[hose->index] == HOSE_PCIE0) {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 *	  A   B   C   D
+		 */
+		{
+			{ 96, 97, 98, 99 },
+		};
+		const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else if (hose_type[hose->index] == HOSE_PCIE1) {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 *	  A   B   C   D
+		 */
+		{
+			{ 100, 101, 102, 103 },
+		};
+		const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else if (hose_type[hose->index] == HOSE_PCIE2) {
+		static char pci_irq_table[][4] =
+		/*
+		 *	PCI IDSEL/INTPIN->INTLINE
+		 *	  A   B   C   D
+		 */
+		{
+			{ 104, 105, 106, 107 },
+		};
+		const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+	return -1;
+}
+
+static void __init yucca_set_emacdata(void)
+{
+	struct ocp_def *def;
+	struct ocp_func_emac_data *emacdata;
+
+	/* Set phy_map, phy_mode, and mac_addr for the EMAC */
+	def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
+	emacdata = def->additions;
+	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+	emacdata->phy_mode = PHY_MODE_GMII;
+	memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+}
+
+static int __init yucca_pcie_card_present(int port)
+{
+   void __iomem *pcie_fpga_base;
+   u16 reg;
+
+   pcie_fpga_base = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE);
+   reg = in_be16(pcie_fpga_base + FPGA_REG1C);
+   iounmap(pcie_fpga_base);
+
+   switch(port) {
+   case 0: return !(reg & FPGA_REG1C_PE0_PRSNT);
+   case 1: return !(reg & FPGA_REG1C_PE1_PRSNT);
+   case 2: return !(reg & FPGA_REG1C_PE2_PRSNT);
+   default: return 0;
+   }
+}
+
+/*
+ * For the given slot, set rootpoint mode, send power to the slot,
+ * turn on the green LED and turn off the yellow LED, enable the clock
+ * and turn off reset.
+ */
+static void __init yucca_setup_pcie_fpga_rootpoint(int port)
+{
+	void __iomem *pcie_reg_fpga_base;
+	u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint;
+
+	pcie_reg_fpga_base = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE);
+
+	switch(port) {
+	case 0:
+		rootpoint   = FPGA_REG1C_PE0_ROOTPOINT;
+		endpoint    = 0;
+		power 	    = FPGA_REG1A_PE0_PWRON;
+		green_led   = FPGA_REG1A_PE0_GLED;
+		clock 	    = FPGA_REG1A_PE0_REFCLK_ENABLE;
+		yellow_led  = FPGA_REG1A_PE0_YLED;
+		reset_off   = FPGA_REG1C_PE0_PERST;
+		break;
+	case 1:
+		rootpoint   = 0;
+		endpoint    = FPGA_REG1C_PE1_ENDPOINT;
+		power 	    = FPGA_REG1A_PE1_PWRON;
+		green_led   = FPGA_REG1A_PE1_GLED;
+		clock 	    = FPGA_REG1A_PE1_REFCLK_ENABLE;
+		yellow_led  = FPGA_REG1A_PE1_YLED;
+		reset_off   = FPGA_REG1C_PE1_PERST;
+		break;
+	case 2:
+		rootpoint   = 0;
+		endpoint    = FPGA_REG1C_PE2_ENDPOINT;
+		power 	    = FPGA_REG1A_PE2_PWRON;
+		green_led   = FPGA_REG1A_PE2_GLED;
+		clock 	    = FPGA_REG1A_PE2_REFCLK_ENABLE;
+		yellow_led  = FPGA_REG1A_PE2_YLED;
+		reset_off   = FPGA_REG1C_PE2_PERST;
+		break;
+
+	default:
+		return;
+	}
+
+	out_be16(pcie_reg_fpga_base + FPGA_REG1A,
+		 ~(power | clock | green_led) &
+		 (yellow_led | in_be16(pcie_reg_fpga_base + FPGA_REG1A)));
+	out_be16(pcie_reg_fpga_base + FPGA_REG1C,
+		 ~(endpoint | reset_off) &
+		 (rootpoint | in_be16(pcie_reg_fpga_base + FPGA_REG1C)));
+
+	/*
+	 * Leave device in reset for a while after powering on the
+	 * slot to give it a chance to initialize.
+	 */
+	mdelay(250);
+
+	out_be16(pcie_reg_fpga_base + FPGA_REG1C,
+		 reset_off | in_be16(pcie_reg_fpga_base + FPGA_REG1C));
+
+	iounmap(pcie_reg_fpga_base);
+}
+
+static void __init
+yucca_setup_hoses(void)
+{
+	struct pci_controller *hose;
+	char name[20];
+	int i;
+
+	if (0 && ppc440spe_init_pcie()) {
+		printk(KERN_WARNING "PPC440SPe PCI Express initialization failed\n");
+		return;
+	}
+
+	for (i = 0; i <= 2; ++i) {
+		if (!yucca_pcie_card_present(i))
+			continue;
+
+		printk(KERN_INFO "PCIE%d: card present\n", i);
+		yucca_setup_pcie_fpga_rootpoint(i);
+		if (ppc440spe_init_pcie_rootport(i)) {
+			printk(KERN_WARNING "PCIE%d: initialization failed\n", i);
+			continue;
+		}
+
+		hose = pcibios_alloc_controller();
+		if (!hose)
+			return;
+
+		sprintf(name, "PCIE%d host bridge", i);
+		pci_init_resource(&hose->io_resource,
+				  YUCCA_PCIX_LOWER_IO,
+				  YUCCA_PCIX_UPPER_IO,
+				  IORESOURCE_IO,
+				  name);
+
+		hose->mem_space.start = YUCCA_PCIE_LOWER_MEM +
+			i * YUCCA_PCIE_MEM_SIZE;
+		hose->mem_space.end   = hose->mem_space.start +
+			YUCCA_PCIE_MEM_SIZE - 1;
+
+		pci_init_resource(&hose->mem_resources[0],
+				  hose->mem_space.start,
+				  hose->mem_space.end,
+				  IORESOURCE_MEM,
+				  name);
+
+		hose->first_busno = 0;
+		hose->last_busno  = 15;
+		hose_type[hose->index] = HOSE_PCIE0 + i;
+
+		ppc440spe_setup_pcie(hose, i);
+		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+	}
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = yucca_map_irq;
+}
+
+TODC_ALLOC();
+
+static void __init
+yucca_early_serial_map(void)
+{
+	struct uart_port port;
+
+	/* Setup ioremapped serial port access */
+	memset(&port, 0, sizeof(port));
+	port.membase = ioremap64(PPC440SPE_UART0_ADDR, 8);
+	port.irq = UART0_INT;
+	port.uartclk = clocks.uart0;
+	port.regshift = 0;
+	port.iotype = SERIAL_IO_MEM;
+	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	port.line = 0;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 0 failed\n");
+	}
+
+	port.membase = ioremap64(PPC440SPE_UART1_ADDR, 8);
+	port.irq = UART1_INT;
+	port.uartclk = clocks.uart1;
+	port.line = 1;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 1 failed\n");
+	}
+
+	port.membase = ioremap64(PPC440SPE_UART2_ADDR, 8);
+	port.irq = UART2_INT;
+	port.uartclk = BASE_BAUD;
+	port.line = 2;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 2 failed\n");
+	}
+}
+
+static void __init
+yucca_setup_arch(void)
+{
+	yucca_set_emacdata();
+
+#if !defined(CONFIG_BDI_SWITCH)
+	/*
+	 * The Abatron BDI JTAG debugger does not tolerate others
+	 * mucking with the debug registers.
+	 */
+	mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM));
+#endif
+
+	/*
+	 * Determine various clocks.
+	 * To be completely correct we should get SysClk
+	 * from FPGA, because it can be changed by on-board switches
+	 * --ebs
+	 */
+	/* 440GX and 440SPe clocking is the same - rd */
+	ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+	ocp_sys_info.opb_bus_freq = clocks.opb;
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000/HZ;
+
+	/* Setup PCIXn host bridges */
+	yucca_setup_hoses();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	yucca_early_serial_map();
+
+	/* Identify the system */
+	printk("Yucca port (Roland Dreier <rolandd@cisco.com>)\n");
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+		unsigned long r5, unsigned long r6, unsigned long r7)
+{
+	ibm44x_platform_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = yucca_setup_arch;
+	ppc_md.show_cpuinfo = yucca_show_cpuinfo;
+	ppc_md.find_end_of_memory = ibm440sp_find_end_of_memory;
+	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
+
+	ppc_md.calibrate_decr = yucca_calibrate_decr;
+#ifdef CONFIG_KGDB
+	ppc_md.early_serial_map = yucca_early_serial_map;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/yucca.h b/arch/ppc/platforms/4xx/yucca.h
new file mode 100644
index 0000000000..01a4afea15
--- /dev/null
+++ b/arch/ppc/platforms/4xx/yucca.h
@@ -0,0 +1,111 @@
+/*
+ * arch/ppc/platforms/4xx/yucca.h
+ *
+ * Yucca board definitions
+ *
+ * Roland Dreier <rolandd@cisco.com> (based on luan.h by Matt Porter)
+ *
+ * Copyright 2004-2005 MontaVista Software Inc.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_YUCCA_H__
+#define __ASM_YUCCA_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ppc440spe.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0	0xa0000800
+
+/* Location of MAC addresses in PIBS image */
+#define PIBS_FLASH_BASE		0xffe00000
+#define PIBS_MAC_BASE		(PIBS_FLASH_BASE+0x1b0400)
+
+/* External timer clock frequency */
+#define YUCCA_TMR_CLK		25000000
+
+/*
+ * FPGA registers
+ */
+#define YUCCA_FPGA_REG_BASE			0x00000004e2000000ULL
+#define YUCCA_FPGA_REG_SIZE			0x24
+
+#define FPGA_REG1A				0x1a
+
+#define FPGA_REG1A_PE0_GLED			0x8000
+#define FPGA_REG1A_PE1_GLED			0x4000
+#define FPGA_REG1A_PE2_GLED			0x2000
+#define FPGA_REG1A_PE0_YLED			0x1000
+#define FPGA_REG1A_PE1_YLED			0x0800
+#define FPGA_REG1A_PE2_YLED			0x0400
+#define FPGA_REG1A_PE0_PWRON			0x0200
+#define FPGA_REG1A_PE1_PWRON			0x0100
+#define FPGA_REG1A_PE2_PWRON			0x0080
+#define FPGA_REG1A_PE0_REFCLK_ENABLE		0x0040
+#define FPGA_REG1A_PE1_REFCLK_ENABLE		0x0020
+#define FPGA_REG1A_PE2_REFCLK_ENABLE		0x0010
+#define FPGA_REG1A_PE_SPREAD0			0x0008
+#define FPGA_REG1A_PE_SPREAD1			0x0004
+#define FPGA_REG1A_PE_SELSOURCE_0		0x0002
+#define FPGA_REG1A_PE_SELSOURCE_1		0x0001
+
+#define FPGA_REG1C				0x1c
+
+#define FPGA_REG1C_PE0_ROOTPOINT		0x8000
+#define FPGA_REG1C_PE1_ENDPOINT			0x4000
+#define FPGA_REG1C_PE2_ENDPOINT			0x2000
+#define FPGA_REG1C_PE0_PRSNT			0x1000
+#define FPGA_REG1C_PE1_PRSNT			0x0800
+#define FPGA_REG1C_PE2_PRSNT			0x0400
+#define FPGA_REG1C_PE0_WAKE			0x0080
+#define FPGA_REG1C_PE1_WAKE			0x0040
+#define FPGA_REG1C_PE2_WAKE			0x0020
+#define FPGA_REG1C_PE0_PERST			0x0010
+#define FPGA_REG1C_PE1_PERST			0x0008
+#define FPGA_REG1C_PE2_PERST			0x0004
+
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE	3
+
+/* PIBS defined UART mappings, used before early_serial_setup */
+#define UART0_IO_BASE	0xa0000200
+#define UART1_IO_BASE	0xa0000300
+#define UART2_IO_BASE	0xa0000600
+
+#define BASE_BAUD	11059200
+#define STD_UART_OP(num)					\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
+		(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),	\
+		iomem_base: (void*)UART##num##_IO_BASE,		\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)		\
+	STD_UART_OP(2)
+
+/* PCI support */
+#define YUCCA_PCIX_LOWER_IO	0x00000000
+#define YUCCA_PCIX_UPPER_IO	0x0000ffff
+#define YUCCA_PCIX_LOWER_MEM	0x80000000
+#define YUCCA_PCIX_UPPER_MEM	0x8fffffff
+#define YUCCA_PCIE_LOWER_MEM	0x90000000
+#define YUCCA_PCIE_MEM_SIZE	0x10000000
+
+#define YUCCA_PCIX_MEM_SIZE	0x10000000
+#define YUCCA_PCIX_MEM_OFFSET	0x00000000
+#define YUCCA_PCIE_MEM_SIZE	0x10000000
+#define YUCCA_PCIE_MEM_OFFSET	0x00000000
+
+#endif				/* __ASM_YUCCA_H__ */
+#endif				/* __KERNEL__ */
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 13dff1e51f..dcd168f9a7 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_GT64260)		+= gt64260_pic.o
 obj-$(CONFIG_LOPEC)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_HDPU)		+= pci_auto.o
 obj-$(CONFIG_LUAN)		+= pci_auto.o todc_time.o
+obj-$(CONFIG_YUCCA)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_KATANA)		+= pci_auto.o
 obj-$(CONFIG_MV64360)		+= mv64360_pic.o
 obj-$(CONFIG_MV64X60)		+= mv64x60.o mv64x60_win.o
-- 
cgit v1.2.2


From 3e9e7c1d0b7a36fb8affb973a054c5098e27baa8 Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@kernel.crashing.org>
Date: Mon, 7 Nov 2005 00:58:15 -0800
Subject: [PATCH] ppc32: cleanup AMCC PPC40x eval boards to support U-Boot

Cleanup PPC40x eval boards (bubinga, walnut and sycamore) to support U-Boot
as bootloader.  The OpenBIOS bd_info struct is not used in the kernel
anymore (only U-Boot now).

uImage (U-Boot) tested on walnut, sycamore and bubinga
zImage (OpenBIOS) tested on sycamore, bubinga and ebony

Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/boot/simple/Makefile     |  21 +++++++-
 arch/ppc/boot/simple/misc.c       |  16 ++++--
 arch/ppc/boot/simple/openbios.c   | 106 +++++++++++++++++++++++++++++++++++---
 arch/ppc/platforms/4xx/Kconfig    |   2 +-
 arch/ppc/platforms/4xx/bubinga.c  |   2 +-
 arch/ppc/platforms/4xx/bubinga.h  |  64 ++++++++++-------------
 arch/ppc/platforms/4xx/ebony.h    |   4 +-
 arch/ppc/platforms/4xx/sycamore.c |   7 +--
 arch/ppc/platforms/4xx/sycamore.h |  67 ++++++++++--------------
 arch/ppc/platforms/4xx/walnut.c   |   2 +-
 arch/ppc/platforms/4xx/walnut.h   |  67 +++++++++---------------
 11 files changed, 217 insertions(+), 141 deletions(-)

(limited to 'arch')

diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index ff0904ee88..82df88b01b 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -67,6 +67,12 @@ zimageinitrd-$(CONFIG_BAMBOO)		:= zImage.initrd-TREE
   entrypoint-$(CONFIG_BAMBOO)		:= 0x01000000
      extra.o-$(CONFIG_BAMBOO)		:= pibs.o
 
+      zimage-$(CONFIG_BUBINGA)		:= zImage-TREE
+zimageinitrd-$(CONFIG_BUBINGA)		:= zImage.initrd-TREE
+         end-$(CONFIG_BUBINGA)		:= bubinga
+  entrypoint-$(CONFIG_BUBINGA)		:= 0x01000000
+     extra.o-$(CONFIG_BUBINGA)		:= openbios.o
+
       zimage-$(CONFIG_EBONY)		:= zImage-TREE
 zimageinitrd-$(CONFIG_EBONY)		:= zImage.initrd-TREE
          end-$(CONFIG_EBONY)		:= ebony
@@ -91,6 +97,18 @@ zimageinitrd-$(CONFIG_OCOTEA)		:= zImage.initrd-TREE
   entrypoint-$(CONFIG_OCOTEA)		:= 0x01000000
      extra.o-$(CONFIG_OCOTEA)		:= pibs.o
 
+      zimage-$(CONFIG_SYCAMORE)		:= zImage-TREE
+zimageinitrd-$(CONFIG_SYCAMORE)		:= zImage.initrd-TREE
+         end-$(CONFIG_SYCAMORE)		:= sycamore
+  entrypoint-$(CONFIG_SYCAMORE)		:= 0x01000000
+     extra.o-$(CONFIG_SYCAMORE)		:= openbios.o
+
+      zimage-$(CONFIG_WALNUT)		:= zImage-TREE
+zimageinitrd-$(CONFIG_WALNUT)		:= zImage.initrd-TREE
+         end-$(CONFIG_WALNUT)		:= walnut
+  entrypoint-$(CONFIG_WALNUT)		:= 0x01000000
+     extra.o-$(CONFIG_WALNUT)		:= openbios.o
+
      extra.o-$(CONFIG_EV64260)		:= misc-ev64260.o
          end-$(CONFIG_EV64260)		:= ev64260
    cacheflag-$(CONFIG_EV64260)		:= -include $(clear_L2_L3)
@@ -168,7 +186,8 @@ OBJCOPY_ARGS			:= -O elf32-powerpc
 
 # head.o and relocate.o must be at the start.
 boot-y				:= head.o relocate.o $(extra.o-y) $(misc-y)
-boot-$(CONFIG_40x)		+= embed_config.o
+boot-$(CONFIG_REDWOOD_5)	+= embed_config.o
+boot-$(CONFIG_REDWOOD_6)	+= embed_config.o
 boot-$(CONFIG_8xx)		+= embed_config.o
 boot-$(CONFIG_8260)		+= embed_config.o
 boot-$(CONFIG_BSEIP)		+= iic.o
diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
index e02de5b467..f415d6c623 100644
--- a/arch/ppc/boot/simple/misc.c
+++ b/arch/ppc/boot/simple/misc.c
@@ -23,7 +23,7 @@
 #include <asm/page.h>
 #include <asm/mmu.h>
 #include <asm/bootinfo.h>
-#ifdef CONFIG_44x
+#ifdef CONFIG_4xx
 #include <asm/ibm4xx.h>
 #endif
 #include <asm/reg.h>
@@ -88,6 +88,14 @@ get_mem_size(void)
 	return 0;
 }
 
+#if defined(CONFIG_40x)
+#define PPC4xx_EMAC0_MR0	EMAC0_BASE
+#endif
+
+#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0)
+#define PPC4xx_EMAC0_MR0	PPC44x_EMAC0_MR0
+#endif
+
 struct bi_record *
 decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
 {
@@ -103,13 +111,13 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
 	com_port = serial_init(0, NULL);
 #endif
 
-#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0)
+#if defined(PPC4xx_EMAC0_MR0)
 	/* Reset MAL */
 	mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR);
 	/* Wait for reset */
 	while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {};
 	/* Reset EMAC */
-	*(volatile unsigned long *)PPC44x_EMAC0_MR0 = 0x20000000;
+	*(volatile unsigned long *)PPC4xx_EMAC0_MR0 = 0x20000000;
 	__asm__ __volatile__("eieio");
 #endif
 
@@ -164,7 +172,9 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
 		puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
 	}
 
+#ifndef CONFIG_40x /* don't overwrite the 40x image located at 0x00400000! */
 	avail_ram = (char *)0x00400000;
+#endif
 	end_avail = (char *)0x00800000;
 	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
 	puthex((unsigned long)end_avail); puts("\n");
diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c
index c732b6d70c..81f11d8b30 100644
--- a/arch/ppc/boot/simple/openbios.c
+++ b/arch/ppc/boot/simple/openbios.c
@@ -1,19 +1,43 @@
 /*
  * arch/ppc/boot/simple/openbios.c
  *
- * 2005 (c) SYSGO AG - g.jaeger@sysgo.com
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
+ *
+ * Based on original work by
+ *      2005 (c) SYSGO AG - g.jaeger@sysgo.com
+ *
  * This file is licensed under the terms of the GNU General Public
  * License version 2.  This program is licensed "as is" without
  * any warranty of any kind, whether express or implied.
  *
- * Derived from arch/ppc/boot/simple/pibs.c (from MontaVista)
  */
 
 #include <linux/types.h>
 #include <linux/config.h>
 #include <linux/string.h>
 #include <asm/ppcboot.h>
-#include <platforms/4xx/ebony.h>
+#include <asm/ibm4xx.h>
+#include <asm/reg.h>
+#ifdef CONFIG_40x
+#include <asm/io.h>
+#endif
+
+#if defined(CONFIG_BUBINGA)
+#define BOARD_INFO_VECTOR       0xFFF80B50 /* openbios 1.19 moved this vector down  - armin */
+#else
+#define BOARD_INFO_VECTOR	0xFFFE0B50
+#endif
+
+#ifdef CONFIG_40x
+/* Supply a default Ethernet address for those eval boards that don't
+ * ship with one.  This is an address from the MBX board I have, so
+ * it is unlikely you will find it on your network.
+ */
+static	ushort	def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+
+extern unsigned long timebase_period_ns;
+#endif /* CONFIG_40x */
 
 extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
 				       unsigned long cksum);
@@ -23,15 +47,85 @@ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
 bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
 bd_t *hold_residual = &hold_resid_buf;
 
+typedef struct openbios_board_info {
+        unsigned char    bi_s_version[4];       /* Version of this structure */
+        unsigned char    bi_r_version[30];      /* Version of the IBM ROM */
+        unsigned int     bi_memsize;            /* DRAM installed, in bytes */
+#ifdef CONFIG_405EP
+        unsigned char    bi_enetaddr[2][6];     /* Local Ethernet MAC address */
+#else /* CONFIG_405EP */
+        unsigned char    bi_enetaddr[6];        /* Local Ethernet MAC address */
+#endif /* CONFIG_405EP */
+        unsigned char    bi_pci_enetaddr[6];    /* PCI Ethernet MAC address */
+        unsigned int     bi_intfreq;            /* Processor speed, in Hz */
+        unsigned int     bi_busfreq;            /* PLB Bus speed, in Hz */
+        unsigned int     bi_pci_busfreq;        /* PCI Bus speed, in Hz */
+#ifdef CONFIG_405EP
+        unsigned int     bi_opb_busfreq;        /* OPB Bus speed, in Hz */
+        unsigned int     bi_pllouta_freq;       /* PLL OUTA speed, in Hz */
+#endif /* CONFIG_405EP */
+} openbios_bd_t;
+
 void *
 load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
 		void *ign1, void *ign2)
 {
-	decompress_kernel(load_addr, num_words, cksum);
+#ifdef CONFIG_40x
+	openbios_bd_t *openbios_bd = NULL;
+	openbios_bd_t *(*get_board_info)(void) =
+		(openbios_bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);
+
+	/*
+	 * On 40x platforms we not only need the MAC-addresses, but also the
+	 * clocks and memsize. Now try to get all values using the OpenBIOS
+	 * "get_board_info()" callback.
+	 */
+	if ((openbios_bd = get_board_info()) != NULL) {
+		/*
+		 * Copy bd_info from OpenBIOS struct into U-Boot struct
+		 * used by kernel
+		 */
+	        hold_residual->bi_memsize = openbios_bd->bi_memsize;
+	        hold_residual->bi_intfreq = openbios_bd->bi_intfreq;
+	        hold_residual->bi_busfreq = openbios_bd->bi_busfreq;
+	        hold_residual->bi_pci_busfreq = openbios_bd->bi_pci_busfreq;
+		memcpy(hold_residual->bi_pci_enetaddr, openbios_bd->bi_pci_enetaddr, 6);
+#ifdef CONFIG_405EP
+		memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr[0], 6);
+		memcpy(hold_residual->bi_enet1addr, openbios_bd->bi_enetaddr[1], 6);
+	        hold_residual->bi_opbfreq = openbios_bd->bi_opb_busfreq;
+	        hold_residual->bi_procfreq = openbios_bd->bi_pllouta_freq;
+#else /* CONFIG_405EP */
+		memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr, 6);
+#endif /* CONFIG_405EP */
+	} else {
+		/* Hmmm...better try to stuff some defaults.
+		 */
+		hold_residual->bi_memsize = 16 * 1024 * 1024;
+		hold_residual->bi_intfreq = 200000000;
+		hold_residual->bi_busfreq = 100000000;
+		hold_residual->bi_pci_busfreq = 66666666;
+
+		/*
+		 * Only supply one mac-address in this fallback
+		 */
+		memcpy(hold_residual->bi_enetaddr, (void *)def_enet_addr, 6);
+#ifdef CONFIG_405EP
+	        hold_residual->bi_opbfreq = 50000000;
+	        hold_residual->bi_procfreq = 200000000;
+#endif /* CONFIG_405EP */
+	}
 
+	timebase_period_ns = 1000000000 / hold_residual->bi_intfreq;
+#endif /* CONFIG_40x */
+
+#ifdef CONFIG_440GP
 	/* simply copy the MAC addresses */
-	memcpy(hold_residual->bi_enetaddr,  (char *)EBONY_OPENBIOS_MAC_BASE, 6);
-	memcpy(hold_residual->bi_enet1addr, (char *)(EBONY_OPENBIOS_MAC_BASE+EBONY_OPENBIOS_MAC_OFFSET), 6);
+	memcpy(hold_residual->bi_enetaddr,  (char *)OPENBIOS_MAC_BASE, 6);
+	memcpy(hold_residual->bi_enet1addr, (char *)(OPENBIOS_MAC_BASE+OPENBIOS_MAC_OFFSET), 6);
+#endif /* CONFIG_440GP */
+
+	decompress_kernel(load_addr, num_words, cksum);
 
 	return (void *)hold_residual;
 }
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index e70e4c6ec7..d8837911bb 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -225,7 +225,7 @@ config EMBEDDEDBOOT
 
 config IBM_OPENBIOS
 	bool
-	depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+	depends on ASH || REDWOOD_5 || REDWOOD_6
 	default y
 
 config PPC4xx_DMA
diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c
index 3678abf863..8110f55668 100644
--- a/arch/ppc/platforms/4xx/bubinga.c
+++ b/arch/ppc/platforms/4xx/bubinga.c
@@ -89,7 +89,7 @@ bubinga_early_serial_map(void)
           * by 16.
           */
 	uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV);
-	uart_clock = __res.bi_pllouta_freq / uart_div;
+	uart_clock = __res.bi_procfreq / uart_div;
 
 	/* Setup serial port access */
 	memset(&port, 0, sizeof(port));
diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h
index b1df856f8e..b5380cfaf5 100644
--- a/arch/ppc/platforms/4xx/bubinga.h
+++ b/arch/ppc/platforms/4xx/bubinga.h
@@ -1,52 +1,34 @@
 /*
- * Support for IBM PPC 405EP evaluation board (Bubinga).
+ * arch/ppc/platforms/4xx/bubinga.h
  *
- * Author: SAW (IBM), derived from walnut.h.
- *         Maintained by MontaVista Software <source@mvista.com>
+ * Bubinga board definitions
+ *
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
+ *
+ * Based on original work by
+ *	SAW (IBM)
+ *	2003 (c) MontaVista Softare Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
  *
- * 2003 (c) MontaVista Softare Inc.  This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
  */
 
 #ifdef __KERNEL__
 #ifndef __BUBINGA_H__
 #define __BUBINGA_H__
 
-/* 405EP */
+#include <linux/config.h>
 #include <platforms/4xx/ibm405ep.h>
-
-#ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
-        unsigned char    bi_s_version[4];       /* Version of this structure */
-        unsigned char    bi_r_version[30];      /* Version of the IBM ROM */
-        unsigned int     bi_memsize;            /* DRAM installed, in bytes */
-        unsigned char    bi_enetaddr[2][6];     /* Local Ethernet MAC address */        unsigned char    bi_pci_enetaddr[6];    /* PCI Ethernet MAC address */
-        unsigned int     bi_intfreq;            /* Processor speed, in Hz */
-        unsigned int     bi_busfreq;            /* PLB Bus speed, in Hz */
-        unsigned int     bi_pci_busfreq;        /* PCI Bus speed, in Hz */
-        unsigned int     bi_opb_busfreq;        /* OPB Bus speed, in Hz */
-        unsigned int     bi_pllouta_freq;       /* PLL OUTA speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
+#include <asm/ppcboot.h>
 
 /* Memory map for the Bubinga board.
  * Generic 4xx plus RTC.
  */
 
-extern void *bubinga_rtc_base;
 #define BUBINGA_RTC_PADDR	((uint)0xf0000000)
 #define BUBINGA_RTC_VADDR	BUBINGA_RTC_PADDR
 #define BUBINGA_RTC_SIZE	((uint)8*1024)
@@ -58,12 +40,18 @@ extern void *bubinga_rtc_base;
  * for typical configurations at various CPU speeds.
  * The base baud is calculated as (FWDA / EXT UART DIV / 16)
  */
-#define BASE_BAUD       0
+#define BASE_BAUD		0
 
-#define BUBINGA_FPGA_BASE      0xF0300000
+/* Flash */
+#define PPC40x_FPGA_BASE	0xF0300000
+#define PPC40x_FPGA_REG_OFFS	1	/* offset to flash map reg */
+#define PPC40x_FLASH_ONBD_N(x)	(x & 0x02)
+#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01)
+#define PPC40x_FLASH_LOW	0xFFF00000
+#define PPC40x_FLASH_HIGH	0xFFF80000
+#define PPC40x_FLASH_SIZE	0x80000
 
-#define PPC4xx_MACHINE_NAME     "IBM Bubinga"
+#define PPC4xx_MACHINE_NAME	"IBM Bubinga"
 
-#endif /* !__ASSEMBLY__ */
 #endif /* __BUBINGA_H__ */
 #endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h
index d08faa46a0..b91ad4272d 100644
--- a/arch/ppc/platforms/4xx/ebony.h
+++ b/arch/ppc/platforms/4xx/ebony.h
@@ -24,8 +24,8 @@
 #define PPC44x_EMAC0_MR0	0xE0000800
 
 /* Where to find the MAC info */
-#define EBONY_OPENBIOS_MAC_BASE   0xfffffe0c
-#define EBONY_OPENBIOS_MAC_OFFSET 0x0c
+#define OPENBIOS_MAC_BASE	0xfffffe0c
+#define OPENBIOS_MAC_OFFSET	0x0c
 
 /* Default clock rates for Rev. B and Rev. C silicon */
 #define EBONY_440GP_RB_SYSCLK	33000000
diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c
index d8019eec47..281b4a2ffb 100644
--- a/arch/ppc/platforms/4xx/sycamore.c
+++ b/arch/ppc/platforms/4xx/sycamore.c
@@ -88,9 +88,6 @@ ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 void __init
 sycamore_setup_arch(void)
 {
-#define SYCAMORE_PS2_BASE	0xF0100000
-#define SYCAMORE_FPGA_BASE	0xF0300000
-
 	void *fpga_brdc;
 	unsigned char fpga_brdc_data;
 	void *fpga_enable;
@@ -100,7 +97,7 @@ sycamore_setup_arch(void)
 
 	ppc4xx_setup_arch();
 
-	ibm_ocp_set_emac(0, 1);
+	ibm_ocp_set_emac(0, 0);
 
 	kb_data = ioremap(SYCAMORE_PS2_BASE, 8);
 	if (!kb_data) {
@@ -111,7 +108,7 @@ sycamore_setup_arch(void)
 
 	kb_cs = kb_data + 1;
 
-	fpga_status = ioremap(SYCAMORE_FPGA_BASE, 8);
+	fpga_status = ioremap(PPC40x_FPGA_BASE, 8);
 	if (!fpga_status) {
 		printk(KERN_CRIT
 		       "sycamore_setup_arch() fpga_status ioremap failed\n");
diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h
index 3e7b4e2c8c..1cd6c824fd 100644
--- a/arch/ppc/platforms/4xx/sycamore.h
+++ b/arch/ppc/platforms/4xx/sycamore.h
@@ -1,67 +1,52 @@
 /*
  * arch/ppc/platforms/4xx/sycamore.h
  *
- * Macros, definitions, and data structures specific to the IBM PowerPC
- * 405GPr "Sycamore" evaluation board.
+ * Sycamore board definitions
  *
- * Author: Armin Kuster <akuster@mvista.com>
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
+ *
+ * Based on original work by
+ * 	Armin Kuster <akuster@mvista.com>
+ *	2000 (c) MontaVista, Software, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
  *
- * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
  */
 
 #ifdef __KERNEL__
 #ifndef __ASM_SYCAMORE_H__
 #define __ASM_SYCAMORE_H__
 
+#include <linux/config.h>
 #include <platforms/4xx/ibm405gpr.h>
+#include <asm/ppcboot.h>
 
-#ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Sycamore" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
-	unsigned char	 bi_s_version[4];	/* Version of this structure */
-	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
-	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
-	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
-	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
-	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
-	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
-
-/* Memory map for the IBM "Sycamore" 405GP evaluation board.
+/* Memory map for the IBM "Sycamore" 405GPr evaluation board.
  * Generic 4xx plus RTC.
  */
 
-extern void *sycamore_rtc_base;
 #define SYCAMORE_RTC_PADDR	((uint)0xf0000000)
 #define SYCAMORE_RTC_VADDR	SYCAMORE_RTC_PADDR
-#define SYCAMORE_RTC_SIZE		((uint)8*1024)
+#define SYCAMORE_RTC_SIZE	((uint)8*1024)
 
-#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
-#define BASE_BAUD		201600
-#else
 #define BASE_BAUD		691200
-#endif
 
-#define SYCAMORE_PS2_BASE		0xF0100000
-#define SYCAMORE_FPGA_BASE	0xF0300000
+#define SYCAMORE_PS2_BASE	0xF0100000
+
+/* Flash */
+#define PPC40x_FPGA_BASE	0xF0300000
+#define PPC40x_FPGA_REG_OFFS	5	/* offset to flash map reg */
+#define PPC40x_FLASH_ONBD_N(x)	(x & 0x02)
+#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01)
+#define PPC40x_FLASH_LOW	0xFFF00000
+#define PPC40x_FLASH_HIGH	0xFFF80000
+#define PPC40x_FLASH_SIZE	0x80000
 
 #define PPC4xx_MACHINE_NAME	"IBM Sycamore"
 
-#endif /* !__ASSEMBLY__ */
 #endif /* __ASM_SYCAMORE_H__ */
 #endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c
index a33eda4b74..74cb33182d 100644
--- a/arch/ppc/platforms/4xx/walnut.c
+++ b/arch/ppc/platforms/4xx/walnut.c
@@ -90,7 +90,7 @@ walnut_setup_arch(void)
 
 	kb_cs = kb_data + 1;
 
-	fpga_status = ioremap(WALNUT_FPGA_BASE, 8);
+	fpga_status = ioremap(PPC40x_FPGA_BASE, 8);
 	if (!fpga_status) {
 		printk(KERN_CRIT
 		       "walnut_setup_arch() fpga_status ioremap failed\n");
diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h
index 04cfbf3696..dcf2691698 100644
--- a/arch/ppc/platforms/4xx/walnut.h
+++ b/arch/ppc/platforms/4xx/walnut.h
@@ -1,72 +1,55 @@
 /*
  * arch/ppc/platforms/4xx/walnut.h
  *
- * Macros, definitions, and data structures specific to the IBM PowerPC
- * 405GP "Walnut" evaluation board.
+ * Walnut board definitions
  *
- * Authors: Grant Erickson <grant@lcse.umn.edu>, Frank Rowand
- * <frank_rowand@mvista.com>, Debbie Chu <debbie_chu@mvista.com> or
- * source@mvista.com
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
  *
- * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * Based on original work by
+ * 	Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *	Frank Rowand <frank_rowand@mvista.com>
+ *	Debbie Chu <debbie_chu@mvista.com>
+ *	2000 (c) MontaVista, Software, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
  *
- * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
  */
 
 #ifdef __KERNEL__
 #ifndef __ASM_WALNUT_H__
 #define __ASM_WALNUT_H__
 
-/* We have a 405GP core */
+#include <linux/config.h>
 #include <platforms/4xx/ibm405gp.h>
-
-#ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Walnut" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
-	unsigned char	 bi_s_version[4];	/* Version of this structure */
-	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
-	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
-	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
-	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
-	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
-	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
+#include <asm/ppcboot.h>
 
 /* Memory map for the IBM "Walnut" 405GP evaluation board.
  * Generic 4xx plus RTC.
  */
 
-extern void *walnut_rtc_base;
 #define WALNUT_RTC_PADDR	((uint)0xf0000000)
 #define WALNUT_RTC_VADDR	WALNUT_RTC_PADDR
 #define WALNUT_RTC_SIZE		((uint)8*1024)
 
-#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
-#define BASE_BAUD		201600
-#else
 #define BASE_BAUD		691200
-#endif
 
 #define WALNUT_PS2_BASE		0xF0100000
-#define WALNUT_FPGA_BASE	0xF0300000
+
+/* Flash */
+#define PPC40x_FPGA_BASE	0xF0300000
+#define PPC40x_FPGA_REG_OFFS	5	/* offset to flash map reg */
+#define PPC40x_FLASH_ONBD_N(x)	(x & 0x02)
+#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01)
+#define PPC40x_FLASH_LOW	0xFFF00000
+#define PPC40x_FLASH_HIGH	0xFFF80000
+#define PPC40x_FLASH_SIZE	0x80000
+#define WALNUT_FPGA_BASE	PPC40x_FPGA_BASE
 
 #define PPC4xx_MACHINE_NAME	"IBM Walnut"
 
-#endif /* !__ASSEMBLY__ */
 #endif /* __ASM_WALNUT_H__ */
 #endif /* __KERNEL__ */
-- 
cgit v1.2.2


From 7869ec6d735e3802f0d442f585ae6bb7633222f6 Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@kernel.crashing.org>
Date: Mon, 7 Nov 2005 00:58:16 -0800
Subject: [PATCH] ppc32: Remove internal PCI arbiter check on PPC40x

On PPC405GP/GPR it should be possible to enable PCI support, even when the
internal PCI arbiter is disabled (e.g.  when using an external PCI
arbiter).  The removed code didn't allow this, and also generated a warning
on PPC405EP platforms.

Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/syslib/ppc405_pci.c | 7 -------
 1 file changed, 7 deletions(-)

(limited to 'arch')

diff --git a/arch/ppc/syslib/ppc405_pci.c b/arch/ppc/syslib/ppc405_pci.c
index 81c83bf98d..d6d838b16d 100644
--- a/arch/ppc/syslib/ppc405_pci.c
+++ b/arch/ppc/syslib/ppc405_pci.c
@@ -89,13 +89,6 @@ ppc4xx_find_bridges(void)
 	isa_mem_base = 0;
 	pci_dram_offset = 0;
 
-#if  (PSR_PCI_ARBIT_EN > 1)
-	/* Check if running in slave mode */
-	if ((mfdcr(DCRN_CHPSR) & PSR_PCI_ARBIT_EN) == 0) {
-		printk("Running as PCI slave, kernel PCI disabled !\n");
-		return;
-	}
-#endif
 	/* Setup PCI32 hose */
 	hose_a = pcibios_alloc_controller();
 	if (!hose_a)
-- 
cgit v1.2.2


From 634e67ff917c079b102317d53556d758dc207969 Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@kernel.crashing.org>
Date: Mon, 7 Nov 2005 00:58:16 -0800
Subject: [PATCH] ppc32: Add missing initrd header on ppc440

This missing initrd header slipped though last time.

Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/syslib/ibm44x_common.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'arch')

diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
index a5bef9d163..71db11d221 100644
--- a/arch/ppc/syslib/ibm44x_common.c
+++ b/arch/ppc/syslib/ibm44x_common.c
@@ -20,6 +20,7 @@
 #include <linux/types.h>
 #include <linux/serial.h>
 #include <linux/module.h>
+#include <linux/initrd.h>
 
 #include <asm/ibm44x.h>
 #include <asm/mmu.h>
-- 
cgit v1.2.2


From de672e4ade25502c28486da005be3eb79534017d Mon Sep 17 00:00:00 2001
From: Pantelis Antoniou <pantelis.antoniou@gmail.com>
Date: Mon, 7 Nov 2005 00:58:17 -0800
Subject: [PATCH] ppc32: Add CPM1 config option

Kconfig patch needed by fs_enet to work.  Works like CONFIG_CPM2.

Cc: Kumar <kumar.gala@freescale.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/Kconfig | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'arch')

diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 114b90fdea..f8db33d552 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -746,6 +746,16 @@ config MPC834x
 	bool
 	default y if MPC834x_SYS
 
+config CPM1
+	bool
+	depends on 8xx
+	default y
+	help
+	  The CPM1 (Communications Processor Module) is a coprocessor on
+	  embedded CPUs made by Motorola.  Selecting this option means that
+	  you wish to build a kernel for a machine with a CPM1 coprocessor
+	  on it (8xx, 827x, 8560).
+
 config CPM2
 	bool
 	depends on 8260 || MPC8560 || MPC8555
-- 
cgit v1.2.2


From 72777373b3a09c9132a787d5e1e03eaf64f30a64 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Mon, 7 Nov 2005 00:58:20 -0800
Subject: [PATCH] sh: Drop deprecated support for custom ramdisk embedding

sh had its own support for embedding ramdisk images in to the kernel binary,
but people are using initramfs for this now, so we drop the ramdisk embedding.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/sh/Kconfig           | 18 ------------------
 arch/sh/Makefile          |  8 --------
 arch/sh/ramdisk/Makefile  | 20 --------------------
 arch/sh/ramdisk/ld.script |  9 ---------
 4 files changed, 55 deletions(-)
 delete mode 100644 arch/sh/ramdisk/Makefile
 delete mode 100644 arch/sh/ramdisk/ld.script

(limited to 'arch')

diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 3e804c736e..7d31d628cd 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -770,24 +770,6 @@ source "fs/Kconfig.binfmt"
 
 endmenu
 
-menu "SH initrd options"
-	depends on BLK_DEV_INITRD
-
-config EMBEDDED_RAMDISK
-	bool "Embed root filesystem ramdisk into the kernel"
-
-config EMBEDDED_RAMDISK_IMAGE
-	string "Filename of gziped ramdisk image"
-	depends on EMBEDDED_RAMDISK
-	default "ramdisk.gz"
-	help
-	  This is the filename of the ramdisk image to be built into the
-	  kernel.  Relative pathnames are relative to arch/sh/ramdisk/.
-	  The ramdisk image is not part of the kernel distribution; you must
-	  provide one yourself.
-
-endmenu
-
 source "net/Kconfig"
 
 source "drivers/Kconfig"
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 4a3049080b..67192d6b00 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -60,14 +60,6 @@ LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
 
 core-y				+= arch/sh/kernel/ arch/sh/mm/
 
-#
-# ramdisk/initrd support
-# You need a compressed ramdisk image, named
-# CONFIG_EMBEDDED_RAMDISK_IMAGE. Relative pathnames
-# are relative to arch/sh/ramdisk/.
-#
-core-$(CONFIG_EMBEDDED_RAMDISK)	+= arch/sh/ramdisk/
-
 # Boards
 machdir-$(CONFIG_SH_SOLUTION_ENGINE)		:= se/770x
 machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)	:= se/7751
diff --git a/arch/sh/ramdisk/Makefile b/arch/sh/ramdisk/Makefile
deleted file mode 100644
index 99e1c68673..0000000000
--- a/arch/sh/ramdisk/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Makefile for a ramdisk image
-#
-
-obj-y += ramdisk.o
-
-
-O_FORMAT = $(shell $(OBJDUMP) -i | head -n 2 | grep elf32)
-img := $(subst ",,$(CONFIG_EMBEDDED_RAMDISK_IMAGE))
-# add $(src) when $(img) is relative
-img := $(subst $(src)//,/,$(src)/$(img))
-
-quiet_cmd_ramdisk = LD      $@
-define cmd_ramdisk
-	$(LD) -T $(srctree)/$(src)/ld.script -b binary --oformat $(O_FORMAT) \
-		-o $@ $(img)
-endef
-
-$(obj)/ramdisk.o: $(img) $(srctree)/$(src)/ld.script
-	$(call cmd,ramdisk)
diff --git a/arch/sh/ramdisk/ld.script b/arch/sh/ramdisk/ld.script
deleted file mode 100644
index 94beee248c..0000000000
--- a/arch/sh/ramdisk/ld.script
+++ /dev/null
@@ -1,9 +0,0 @@
-OUTPUT_ARCH(sh)
-SECTIONS
-{
-  .initrd :
-  {
-       *(.data)
-  }
-}
-
-- 
cgit v1.2.2


From d5cb9783536a41df9f9cba5b0a1d78047ed787f7 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Mon, 7 Nov 2005 00:58:22 -0800
Subject: [PATCH] sh: SuperHyway support for SH4-202

This adds support for the relatively quirky (ie, not in line with any known
documentation, and amazed it works at all) SuperHyway implementation on
SH4-202.  This depends on the earlier SuperHyway patch for multiple block
support and VCR refactoring.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/sh/drivers/Makefile                 |   5 +-
 arch/sh/drivers/superhyway/Makefile      |   6 ++
 arch/sh/drivers/superhyway/ops-sh4-202.c | 171 +++++++++++++++++++++++++++++++
 3 files changed, 180 insertions(+), 2 deletions(-)
 create mode 100644 arch/sh/drivers/superhyway/Makefile
 create mode 100644 arch/sh/drivers/superhyway/ops-sh4-202.c

(limited to 'arch')

diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile
index bd6726cde3..338c3729d2 100644
--- a/arch/sh/drivers/Makefile
+++ b/arch/sh/drivers/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the Linux SuperH-specific device drivers.
 #
 
-obj-$(CONFIG_PCI)	+= pci/
-obj-$(CONFIG_SH_DMA)	+= dma/
+obj-$(CONFIG_PCI)		+= pci/
+obj-$(CONFIG_SH_DMA)		+= dma/
+obj-$(CONFIG_SUPERHYWAY)	+= superhyway/
 
diff --git a/arch/sh/drivers/superhyway/Makefile b/arch/sh/drivers/superhyway/Makefile
new file mode 100644
index 0000000000..5b8e0c7ca3
--- /dev/null
+++ b/arch/sh/drivers/superhyway/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the SuperHyway specific kernel interface routines under Linux.
+#
+
+obj-$(CONFIG_CPU_SUBTYPE_SH4_202)	+= ops-sh4-202.o
+
diff --git a/arch/sh/drivers/superhyway/ops-sh4-202.c b/arch/sh/drivers/superhyway/ops-sh4-202.c
new file mode 100644
index 0000000000..a55c98a905
--- /dev/null
+++ b/arch/sh/drivers/superhyway/ops-sh4-202.c
@@ -0,0 +1,171 @@
+/*
+ * arch/sh/drivers/superhyway/ops-sh4-202.c
+ *
+ * SuperHyway bus support for SH4-202
+ *
+ * Copyright (C) 2005  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU
+ * General Public License.  See the file "COPYING" in the main
+ * directory of this archive for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/superhyway.h>
+#include <linux/string.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+#define PHYS_EMI_CBLOCK		P4SEGADDR(0x1ec00000)
+#define PHYS_EMI_DBLOCK		P4SEGADDR(0x08000000)
+#define PHYS_FEMI_CBLOCK	P4SEGADDR(0x1f800000)
+#define PHYS_FEMI_DBLOCK	P4SEGADDR(0x00000000)
+
+#define PHYS_EPBR_BLOCK		P4SEGADDR(0x1de00000)
+#define PHYS_DMAC_BLOCK		P4SEGADDR(0x1fa00000)
+#define PHYS_PBR_BLOCK		P4SEGADDR(0x1fc00000)
+
+static struct resource emi_resources[] = {
+	[0] = {
+		.start	= PHYS_EMI_CBLOCK,
+		.end	= PHYS_EMI_CBLOCK + 0x00300000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PHYS_EMI_DBLOCK,
+		.end	= PHYS_EMI_DBLOCK + 0x08000000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct superhyway_device emi_device = {
+	.name		= "emi",
+	.num_resources	= ARRAY_SIZE(emi_resources),
+	.resource	= emi_resources,
+};
+
+static struct resource femi_resources[] = {
+	[0] = {
+		.start	= PHYS_FEMI_CBLOCK,
+		.end	= PHYS_FEMI_CBLOCK + 0x00100000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PHYS_FEMI_DBLOCK,
+		.end	= PHYS_FEMI_DBLOCK + 0x08000000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct superhyway_device femi_device = {
+	.name		= "femi",
+	.num_resources	= ARRAY_SIZE(femi_resources),
+	.resource	= femi_resources,
+};
+
+static struct resource epbr_resources[] = {
+	[0] = {
+		.start	= P4SEGADDR(0x1e7ffff8),
+		.end	= P4SEGADDR(0x1e7ffff8 + (sizeof(u32) * 2) - 1),
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PHYS_EPBR_BLOCK,
+		.end	= PHYS_EPBR_BLOCK + 0x00a00000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct superhyway_device epbr_device = {
+	.name		= "epbr",
+	.num_resources	= ARRAY_SIZE(epbr_resources),
+	.resource	= epbr_resources,
+};
+
+static struct resource dmac_resource = {
+	.start	= PHYS_DMAC_BLOCK,
+	.end	= PHYS_DMAC_BLOCK + 0x00100000 - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct superhyway_device dmac_device = {
+	.name		= "dmac",
+	.num_resources	= 1,
+	.resource	= &dmac_resource,
+};
+
+static struct resource pbr_resources[] = {
+	[0] = {
+		.start	= P4SEGADDR(0x1ffffff8),
+		.end	= P4SEGADDR(0x1ffffff8 + (sizeof(u32) * 2) - 1),
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PHYS_PBR_BLOCK,
+		.end	= PHYS_PBR_BLOCK + 0x00400000 - (sizeof(u32) * 2) - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct superhyway_device pbr_device = {
+	.name		= "pbr",
+	.num_resources	= ARRAY_SIZE(pbr_resources),
+	.resource	= pbr_resources,
+};
+
+static struct superhyway_device *sh4202_devices[] __initdata = {
+	&emi_device, &femi_device, &epbr_device, &dmac_device, &pbr_device,
+};
+
+static int sh4202_read_vcr(unsigned long base, struct superhyway_vcr_info *vcr)
+{
+	u32 vcrh, vcrl;
+	u64 tmp;
+
+	/*
+	 * XXX: Even though the SH4-202 Evaluation Device documentation
+	 * indicates that VCRL is mapped first with VCRH at a + 0x04
+	 * offset, the opposite seems to be true.
+	 *
+	 * Some modules (PBR and ePBR for instance) also appear to have
+	 * VCRL/VCRH flipped in the documentation, but on the SH4-202
+	 * itself it appears that these are all consistently mapped with
+	 * VCRH preceeding VCRL.
+	 *
+	 * Do not trust the documentation, for it is evil.
+	 */
+	vcrh = ctrl_inl(base);
+	vcrl = ctrl_inl(base + sizeof(u32));
+
+	tmp = ((u64)vcrh << 32) | vcrl;
+	memcpy(vcr, &tmp, sizeof(u64));
+
+	return 0;
+}
+
+static int sh4202_write_vcr(unsigned long base, struct superhyway_vcr_info vcr)
+{
+	u64 tmp = *(u64 *)&vcr;
+
+	ctrl_outl((tmp >> 32) & 0xffffffff, base);
+	ctrl_outl(tmp & 0xffffffff, base + sizeof(u32));
+
+	return 0;
+}
+
+static struct superhyway_ops sh4202_superhyway_ops = {
+	.read_vcr	= sh4202_read_vcr,
+	.write_vcr	= sh4202_write_vcr,
+};
+
+struct superhyway_bus superhyway_channels[] = {
+	{ &sh4202_superhyway_ops, },
+	{ 0, },
+};
+
+int __init superhyway_scan_bus(struct superhyway_bus *bus)
+{
+	return superhyway_add_devices(bus, sh4202_devices,
+				      ARRAY_SIZE(sh4202_devices));
+}
+
-- 
cgit v1.2.2


From 65463b73b14ed43368dc5961a6c3dcb0d98cfe1f Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Mon, 7 Nov 2005 00:58:24 -0800
Subject: [PATCH] sh: Drop hp690 discontig support

There was only one board using this (hp690 specifically), and it just so
happens that it's only physically discontiguous at the "normal" P1 offset.  If
we bump up the P1 offset, it's possible to hit a shadowed region of memory
where we suddenly become magically contiguous.

As people have been using this shadowed region workaround for quite some time
(and without any adverse effects), it's time to drop the left over discontig
bits that no longer have any practical use (it was always very much
hp690-centric to begin with).

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/sh/Kconfig        | 10 ----------
 arch/sh/kernel/setup.c | 26 +++++++-------------------
 arch/sh/mm/init.c      | 21 ++-------------------
 3 files changed, 9 insertions(+), 48 deletions(-)

(limited to 'arch')

diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 7d31d628cd..64f5ae0ff9 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -490,16 +490,6 @@ config CPU_SUBTYPE_ST40
        depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1
        default y
 
-config ARCH_DISCONTIGMEM_ENABLE
-	bool
-	depends on SH_HP690
-	default y
-	help
-	  Say Y to upport efficient handling of discontiguous physical memory,
-	  for architectures which are either NUMA (Non-Uniform Memory Access)
-	  or have huge holes in the physical address space for other reasons.
-	  See <file:Documentation/vm/numa> for more.
-
 source "mm/Kconfig"
 
 config ZERO_PAGE_OFFSET
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 25b9d9ebe8..036050b377 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -83,9 +83,9 @@ static struct sh_machine_vector* __init get_mv_byname(const char* name);
 /* ... */
 #define COMMAND_LINE ((char *) (PARAM+0x100))
 
-#define RAMDISK_IMAGE_START_MASK  	0x07FF
+#define RAMDISK_IMAGE_START_MASK	0x07FF
 #define RAMDISK_PROMPT_FLAG		0x8000
-#define RAMDISK_LOAD_FLAG		0x4000	
+#define RAMDISK_LOAD_FLAG		0x4000
 
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
 
@@ -284,18 +284,6 @@ void __init setup_arch(char **cmdline_p)
 #define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
 #define PFN_PHYS(x)	((x) << PAGE_SHIFT)
 
-#ifdef CONFIG_DISCONTIGMEM
-	NODE_DATA(0)->bdata = &discontig_node_bdata[0];
-	NODE_DATA(1)->bdata = &discontig_node_bdata[1];
-
-	bootmap_size = init_bootmem_node(NODE_DATA(1), 
-					 PFN_UP(__MEMORY_START_2ND),
-					 PFN_UP(__MEMORY_START_2ND),
-					 PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND));
-	free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND);
-	reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size);
-#endif
-
 	/*
 	 * Find the highest page frame number we have available
 	 */
@@ -306,10 +294,10 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	max_low_pfn = max_pfn;
 
- 	/*
+	/*
 	 * Partially used pages are not usable - thus
 	 * we are rounding upwards:
- 	 */
+	 */
 	start_pfn = PFN_UP(__pa(_end));
 
 	/*
@@ -360,12 +348,12 @@ void __init setup_arch(char **cmdline_p)
 	reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
- 	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- 	if (&__rd_start != &__rd_end) {
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	if (&__rd_start != &__rd_end) {
 		LOADER_TYPE = 1;
 		INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START;
 		INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start;
- 	}
+	}
 
 	if (LOADER_TYPE && INITRD_START) {
 		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 4e9c854845..e342565f75 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -51,11 +51,6 @@ unsigned long mmu_context_cache = NO_CONTEXT;
 #define MAX_LOW_PFN	(NODE_DATA(0)->bdata->node_low_pfn)
 #endif
 
-#ifdef CONFIG_DISCONTIGMEM
-pg_data_t discontig_page_data[MAX_NUMNODES];
-bootmem_data_t discontig_node_bdata[MAX_NUMNODES];
-#endif
-
 void (*copy_page)(void *from, void *to);
 void (*clear_page)(void *to);
 
@@ -216,15 +211,6 @@ void __init paging_init(void)
 #endif
 	NODE_DATA(0)->node_mem_map = NULL;
 	free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
-
-#ifdef CONFIG_DISCONTIGMEM
-	/*
-	 * And for discontig, do some more fixups on the zone sizes..
-	 */
-	zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT;
-	zones_size[ZONE_NORMAL] = 0;
-	free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
-#endif
 }
 
 void __init mem_init(void)
@@ -248,7 +234,7 @@ void __init mem_init(void)
 	memset(empty_zero_page, 0, PAGE_SIZE);
 	__flush_wback_region(empty_zero_page, PAGE_SIZE);
 
-	/* 
+	/*
 	 * Setup wrappers for copy/clear_page(), these will get overridden
 	 * later in the boot process if a better method is available.
 	 */
@@ -257,9 +243,6 @@ void __init mem_init(void)
 
 	/* this will put all low memory onto the freelists */
 	totalram_pages += free_all_bootmem_node(NODE_DATA(0));
-#ifdef CONFIG_DISCONTIGMEM
-	totalram_pages += free_all_bootmem_node(NODE_DATA(1));
-#endif
 	reservedpages = 0;
 	for (tmp = 0; tmp < num_physpages; tmp++)
 		/*
@@ -286,7 +269,7 @@ void __init mem_init(void)
 void free_initmem(void)
 {
 	unsigned long addr;
-	
+
 	addr = (unsigned long)(&__init_begin);
 	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
-- 
cgit v1.2.2


From 0d6d82b6712c808e461090dd483f111f72b3b38b Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Mon, 7 Nov 2005 00:58:28 -0800
Subject: [PATCH] sh: Use pfn_valid() for lazy dcache write-back on SH7705

SH7705 in extended cache mode has some left-over VALID_PAGE() cruft that it
checks when doing lazy dcache write-back.  This has been gone for some time
(the last bits were in the discontig code, which should now also be gone --
this also fixes up a build error in the non-discontig case).

pfn_valid() gives the desired behaviour, so we switch to that.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/sh/mm/tlb-sh3.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

(limited to 'arch')

diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c
index 7a0d5c10bf..46b09e26e0 100644
--- a/arch/sh/mm/tlb-sh3.c
+++ b/arch/sh/mm/tlb-sh3.c
@@ -40,12 +40,17 @@ void update_mmu_cache(struct vm_area_struct * vma,
 		return;
 
 #if defined(CONFIG_SH7705_CACHE_32KB)
-	struct page *page;
-	page = pte_page(pte);
-	if (VALID_PAGE(page) && !test_bit(PG_mapped, &page->flags)) {
-		unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
-		__flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
-		__set_bit(PG_mapped, &page->flags);
+	{
+		struct page *page = pte_page(pte);
+		unsigned long pfn = pte_pfn(pte);
+
+		if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) {
+			unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+
+			__flush_wback_region((void *)P1SEGADDR(phys),
+					     PAGE_SIZE);
+			__set_bit(PG_mapped, &page->flags);
+		}
 	}
 #endif
 
@@ -80,7 +85,7 @@ void __flush_tlb_page(unsigned long asid, unsigned long page)
 	 */
 	addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000);
 	data = (page & 0xfffe0000) | asid; /* VALID bit is off */
-	
+
 	if ((cpu_data->flags & CPU_HAS_MMU_PAGE_ASSOC)) {
 		addr |= MMU_PAGE_ASSOC_BIT;
 		ways = 1;	/* we already know the way .. */
-- 
cgit v1.2.2


From 38e548ee1a79c8da7b3d9e26f2adce9b61413f84 Mon Sep 17 00:00:00 2001
From: Tobias Klauser <tklauser@nuerscht.ch>
Date: Mon, 7 Nov 2005 00:58:31 -0800
Subject: [PATCH] arch/i386: Use ARRAY_SIZE macro

Use ARRAY_SIZE macro instead of sizeof(x)/sizeof(x[0])

Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/apm.c                            | 5 ++---
 arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 2 +-
 arch/i386/kernel/mca.c                            | 2 +-
 arch/i386/kernel/reboot_fixups.c                  | 2 +-
 arch/i386/kernel/smpboot.c                        | 2 +-
 5 files changed, 6 insertions(+), 7 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index d2ef0c2aa9..86e80c5514 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -447,8 +447,7 @@ static char *	apm_event_name[] = {
 	"system standby resume",
 	"capabilities change"
 };
-#define NR_APM_EVENT_NAME	\
-		(sizeof(apm_event_name) / sizeof(apm_event_name[0]))
+#define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
 
 typedef struct lookup_t {
 	int	key;
@@ -479,7 +478,7 @@ static const lookup_t error_table[] = {
 	{ APM_NO_ERROR,		"BIOS did not set a return code" },
 	{ APM_NOT_PRESENT,	"No APM present" }
 };
-#define ERROR_COUNT	(sizeof(error_table)/sizeof(lookup_t))
+#define ERROR_COUNT	ARRAY_SIZE(error_table)
 
 /**
  *	apm_error	-	display an APM error
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 1465974256..0ea010a7af 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -67,7 +67,7 @@ static const struct cpu_id cpu_ids[] = {
 	[CPU_MP4HT_D0]	= {15,  3, 4 },
 	[CPU_MP4HT_E0]	= {15,  4, 1 },
 };
-#define N_IDS	(sizeof(cpu_ids)/sizeof(cpu_ids[0]))
+#define N_IDS	ARRAY_SIZE(cpu_ids)
 
 struct cpu_model
 {
diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c
index 8600faeea2..558bb20772 100644
--- a/arch/i386/kernel/mca.c
+++ b/arch/i386/kernel/mca.c
@@ -132,7 +132,7 @@ static struct resource mca_standard_resources[] = {
 	{ .start = 0x100, .end = 0x107, .name = "POS (MCA)" }
 };
 
-#define MCA_STANDARD_RESOURCES	(sizeof(mca_standard_resources)/sizeof(struct resource))
+#define MCA_STANDARD_RESOURCES	ARRAY_SIZE(mca_standard_resources)
 
 /**
  *	mca_read_and_store_pos - read the POS registers into a memory buffer
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index c9b87330ae..6f73c9ea4e 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -42,7 +42,7 @@ void mach_reboot_fixups(void)
 	struct pci_dev *dev;
 	int i;
 
-	for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) {
+	for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
 		cur = &(fixups_table[i]);
 		dev = pci_get_device(cur->vendor, cur->device, NULL);
 		if (!dev)
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 01b618e73e..e6488ffc1f 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -612,7 +612,7 @@ static inline void __inquire_remote_apic(int apicid)
 
 	printk("Inquiring remote APIC #%d...\n", apicid);
 
-	for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) {
+	for (i = 0; i < ARRAY_SIZE(regs); i++) {
 		printk("... APIC #%d %s: ", apicid, names[i]);
 
 		/*
-- 
cgit v1.2.2


From 77f72b192fd4624ad639dbf60c48be787c8aea59 Mon Sep 17 00:00:00 2001
From: Zwane Mwaikambo <zwane@arm.linux.org.uk>
Date: Mon, 7 Nov 2005 00:58:33 -0800
Subject: [PATCH] i386: LVT entries remaining unmasked on reboot

Excerpt from bugzilla entry

http://bugzilla.kernel.org/show_bug.cgi?id=5518

"i386 version of Reboot-through-BIOS is unsafe: it forgets to mask APIC LVT
interrupts before jumping to a BIOS entry point.  As a result, BIOS ends up
bombarded with interrupts early on boot.  The BIOS does not expect it since
following a "normal" hardware cpu reset, all APIC LVT registers have the
Mask bit (16) set and can't generate interrupts.

For example, the version of Phoenix BIOS used by VMware enables interrupts
for the first time before masking/clearing APIC LVT.  The APIC Timer LVT
register is still set up for a timer interrupt delivery with a high vector
from the previous Linux incarnation (0xef in our case).  The BIOS has not
fully initialized its IDT at this point and the real mode gate for 0xef
remains all zeros.  Vector 0xef dispatches BIOS to address 0:0, BIOS takes
a #GP and eventually hangs.

machine_shutdown() does attempt to shut down APIC before jumping to BIOS,
but it is ineffective"

Signed-off-by: Zwane Mwaikambo <zwane@arm.linux.org.uk>
Cc: "Seth, Rohit" <rohit.seth@intel.com>
Cc: Zachary Amsden <zach@vmware.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/apic.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 7c724ffa08..496a2c9909 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -559,14 +559,20 @@ void __devinit setup_local_APIC(void)
  * If Linux enabled the LAPIC against the BIOS default
  * disable it down before re-entering the BIOS on shutdown.
  * Otherwise the BIOS may get confused and not power-off.
+ * Additionally clear all LVT entries before disable_local_APIC
+ * for the case where Linux didn't enable the LAPIC.
  */
 void lapic_shutdown(void)
 {
-	if (!cpu_has_apic || !enabled_via_apicbase)
+	if (!cpu_has_apic)
 		return;
 
 	local_irq_disable();
-	disable_local_APIC();
+	clear_local_APIC();
+
+	if (enabled_via_apicbase)
+		disable_local_APIC();
+
 	local_irq_enable();
 }
 
-- 
cgit v1.2.2


From 8d1ed6366b9f3cb54eb5aef5dae79b39b8d5ce43 Mon Sep 17 00:00:00 2001
From: Adrian Bunk <bunk@stusta.de>
Date: Mon, 7 Nov 2005 00:58:35 -0800
Subject: [PATCH] arch/i386/kernel/ldt.c should #include <asm/mmu_context.h>

Every file should #include the header files containing the prototypes of
its global functions

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/ldt.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'arch')

diff --git a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c
index fe1ffa5558..983f95707e 100644
--- a/arch/i386/kernel/ldt.c
+++ b/arch/i386/kernel/ldt.c
@@ -18,6 +18,7 @@
 #include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
+#include <asm/mmu_context.h>
 
 #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
 static void flush_ldt(void *null)
-- 
cgit v1.2.2


From 5cc6135af73ad0c7897d1d00ff361e510ac23ccb Mon Sep 17 00:00:00 2001
From: Adrian Bunk <bunk@stusta.de>
Date: Mon, 7 Nov 2005 00:58:36 -0800
Subject: [PATCH] arch/i386/kernel/reboot_fixups.c should #include
 <linux/reboot_fixups.h>

Every file should #include the header files containing the prototypes of
its global functions

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/reboot_fixups.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'arch')

diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 6f73c9ea4e..10e21a4773 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -10,6 +10,7 @@
 
 #include <asm/delay.h>
 #include <linux/pci.h>
+#include <linux/reboot_fixups.h>
 
 static void cs5530a_warm_reset(struct pci_dev *dev)
 {
-- 
cgit v1.2.2


From cc658cfe3c66a6124b5a8db90cdcdd440201b1dc Mon Sep 17 00:00:00 2001
From: Adrian Bunk <bunk@stusta.de>
Date: Mon, 7 Nov 2005 00:58:37 -0800
Subject: [PATCH] arch/i386/kernel/scx200.c should #include
 <linux/scx200_gpio.h>

Every file should #include the header files containing the prototypes of
its global functions

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/scx200.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'arch')

diff --git a/arch/i386/kernel/scx200.c b/arch/i386/kernel/scx200.c
index 69e203a0d3..9c968ae67c 100644
--- a/arch/i386/kernel/scx200.c
+++ b/arch/i386/kernel/scx200.c
@@ -12,6 +12,7 @@
 #include <linux/pci.h>
 
 #include <linux/scx200.h>
+#include <linux/scx200_gpio.h>
 
 /* Verify that the configuration block really is there */
 #define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base))
-- 
cgit v1.2.2


From 31ab269a0307d8725737dfbbdeb5dcde7b41bc36 Mon Sep 17 00:00:00 2001
From: Shaohua Li <shaohua.li@intel.com>
Date: Mon, 7 Nov 2005 00:58:42 -0800
Subject: [PATCH] x86: add MCE resume

It's widely seen a MCE non-fatal error reported after resume.  It seems MCE
resume is lacked under ia32.  This patch tries to fix the gap.

Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/cpu/common.c         | 5 +----
 arch/i386/kernel/cpu/mcheck/k7.c      | 2 +-
 arch/i386/kernel/cpu/mcheck/mce.c     | 4 ++--
 arch/i386/kernel/cpu/mcheck/p4.c      | 4 ++--
 arch/i386/kernel/cpu/mcheck/p5.c      | 2 +-
 arch/i386/kernel/cpu/mcheck/p6.c      | 2 +-
 arch/i386/kernel/cpu/mcheck/winchip.c | 2 +-
 arch/i386/power/cpu.c                 | 1 +
 8 files changed, 10 insertions(+), 12 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 74145a33cb..c145fb3000 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -30,8 +30,6 @@ static int disable_x86_serial_nr __devinitdata = 1;
 
 struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
 
-extern void mcheck_init(struct cpuinfo_x86 *c);
-
 extern int disable_pse;
 
 static void default_init(struct cpuinfo_x86 * c)
@@ -429,9 +427,8 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
 	}
 
 	/* Init Machine Check Exception if available. */
-#ifdef CONFIG_X86_MCE
 	mcheck_init(c);
-#endif
+
 	if (c == &boot_cpu_data)
 		sysenter_setup();
 	enable_sep_cpu();
diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c
index 7c6b9c7352..fc5d5215e2 100644
--- a/arch/i386/kernel/cpu/mcheck/k7.c
+++ b/arch/i386/kernel/cpu/mcheck/k7.c
@@ -68,7 +68,7 @@ static fastcall void k7_machine_check(struct pt_regs * regs, long error_code)
 
 
 /* AMD K7 machine check is Intel like */
-void __devinit amd_mcheck_init(struct cpuinfo_x86 *c)
+void amd_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	int i;
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c
index 2cf25d2ba0..6170af3c27 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.c
+++ b/arch/i386/kernel/cpu/mcheck/mce.c
@@ -16,7 +16,7 @@
 
 #include "mce.h"
 
-int mce_disabled __devinitdata = 0;
+int mce_disabled = 0;
 int nr_mce_banks;
 
 EXPORT_SYMBOL_GPL(nr_mce_banks);	/* non-fatal.o */
@@ -31,7 +31,7 @@ static fastcall void unexpected_machine_check(struct pt_regs * regs, long error_
 void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
 
 /* This has to be run for each processor */
-void __devinit mcheck_init(struct cpuinfo_x86 *c)
+void mcheck_init(struct cpuinfo_x86 *c)
 {
 	if (mce_disabled==1)
 		return;
diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c
index 1d1e885f50..fd2c459a31 100644
--- a/arch/i386/kernel/cpu/mcheck/p4.c
+++ b/arch/i386/kernel/cpu/mcheck/p4.c
@@ -77,7 +77,7 @@ fastcall void smp_thermal_interrupt(struct pt_regs *regs)
 }
 
 /* P4/Xeon Thermal regulation detect and init */
-static void __devinit intel_init_thermal(struct cpuinfo_x86 *c)
+static void intel_init_thermal(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	unsigned int cpu = smp_processor_id();
@@ -231,7 +231,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
 }
 
 
-void __devinit intel_p4_mcheck_init(struct cpuinfo_x86 *c)
+void intel_p4_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	int i;
diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c
index 3a2e24badd..94bc43d950 100644
--- a/arch/i386/kernel/cpu/mcheck/p5.c
+++ b/arch/i386/kernel/cpu/mcheck/p5.c
@@ -28,7 +28,7 @@ static fastcall void pentium_machine_check(struct pt_regs * regs, long error_cod
 }
 
 /* Set up machine check reporting for processors with Intel style MCE */
-void __devinit intel_p5_mcheck_init(struct cpuinfo_x86 *c)
+void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	
diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c
index 979b18bc95..deeae42ce1 100644
--- a/arch/i386/kernel/cpu/mcheck/p6.c
+++ b/arch/i386/kernel/cpu/mcheck/p6.c
@@ -79,7 +79,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
 }
 
 /* Set up machine check reporting for processors with Intel style MCE */
-void __devinit intel_p6_mcheck_init(struct cpuinfo_x86 *c)
+void intel_p6_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	int i;
diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c
index 5b9d2dd411..9e424b6c29 100644
--- a/arch/i386/kernel/cpu/mcheck/winchip.c
+++ b/arch/i386/kernel/cpu/mcheck/winchip.c
@@ -22,7 +22,7 @@ static fastcall void winchip_machine_check(struct pt_regs * regs, long error_cod
 }
 
 /* Set up machine check reporting on the Winchip C6 series */
-void __devinit winchip_mcheck_init(struct cpuinfo_x86 *c)
+void winchip_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 lo, hi;
 	machine_check_vector = winchip_machine_check;
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index 1f1572692e..50a0bef8c8 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -118,6 +118,7 @@ void __restore_processor_state(struct saved_context *ctxt)
 	fix_processor_context();
 	do_fpu_end();
 	mtrr_ap_init();
+	mcheck_init(&boot_cpu_data);
 }
 
 void restore_processor_state(void)
-- 
cgit v1.2.2


From d9b5444eeb3a663ca4a625878b1421c9e9b18e8b Mon Sep 17 00:00:00 2001
From: Adrian Bunk <bunk@stusta.de>
Date: Mon, 7 Nov 2005 00:58:44 -0800
Subject: [PATCH] cris: "extern inline" -> "static inline"

"extern inline" doesn't make much sense.

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Acked-by: Mikael Starvik <starvik@axis.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/cris/arch-v10/README.mm       | 6 +++---
 arch/cris/arch-v10/kernel/signal.c | 2 +-
 arch/cris/arch-v32/kernel/signal.c | 2 +-
 arch/cris/mm/ioremap.c             | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

(limited to 'arch')

diff --git a/arch/cris/arch-v10/README.mm b/arch/cris/arch-v10/README.mm
index 6f08903f31..517d1f027f 100644
--- a/arch/cris/arch-v10/README.mm
+++ b/arch/cris/arch-v10/README.mm
@@ -177,7 +177,7 @@ The example address is 0xd004000c; in binary this is:
 Given the top-level Page Directory, the offset in that directory is calculated
 using the upper 8 bits:
 
-extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
 {
 	return mm->pgd + (address >> PGDIR_SHIFT);
 }
@@ -190,14 +190,14 @@ The pgd_t from our example will therefore be the 208'th (0xd0) entry in mm->pgd.
 
 Since the Middle Directory does not exist, it is a unity mapping:
 
-extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
 {
 	return (pmd_t *) dir;
 }
 
 The Page Table provides the final lookup by using bits 13 to 23 as index:
 
-extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+static inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
 {
 	return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) &
 					   (PTRS_PER_PTE - 1));
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index 693771961f..19bcad0571 100644
--- a/arch/cris/arch-v10/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -476,7 +476,7 @@ give_sigsegv:
  * OK, we're invoking a handler
  */	
 
-extern inline void
+static inline void
 handle_signal(int canrestart, unsigned long sig,
 	      siginfo_t *info, struct k_sigaction *ka,
               sigset_t *oldset, struct pt_regs * regs)
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index 0a3614dab8..99e59b3eac 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -513,7 +513,7 @@ give_sigsegv:
 }
 
 /* Invoke a singal handler to, well, handle the signal. */
-extern inline void
+static inline void
 handle_signal(int canrestart, unsigned long sig,
 	      siginfo_t *info, struct k_sigaction *ka,
               sigset_t *oldset, struct pt_regs * regs)
diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c
index a92ac98775..1780df3ed9 100644
--- a/arch/cris/mm/ioremap.c
+++ b/arch/cris/mm/ioremap.c
@@ -16,7 +16,7 @@
 #include <asm/tlbflush.h>
 #include <asm/arch/memmap.h>
 
-extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
 	unsigned long phys_addr, pgprot_t prot)
 {
 	unsigned long end;
-- 
cgit v1.2.2


From 953206858070e5921b9d5931c293ec983a6790cb Mon Sep 17 00:00:00 2001
From: Jeff Dike <jdike@addtoit.com>
Date: Mon, 7 Nov 2005 00:58:45 -0800
Subject: [PATCH] uml: improve stub debugging

Add some more debugging information when a stub does something unexpected,
usually segfaulting.  Now, it dumps out the stub's registers as well as the
signal.

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/kernel/skas/process.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

(limited to 'arch')

diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 5cd0e99297..42f2da687d 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -69,6 +69,17 @@ void wait_stub_done(int pid, int sig, char * fname)
 
         if((n < 0) || !WIFSTOPPED(status) ||
            (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
+		unsigned long regs[FRAME_SIZE];
+		if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+			printk("Failed to get registers from stub, "
+			       "errno = %d\n", errno);
+		else {
+			int i;
+
+			printk("Stub registers -\n");
+			for(i = 0; i < FRAME_SIZE; i++)
+				printk("\t%d - %lx\n", i, regs[i]);
+		}
                 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
                       "pid = %d, n = %d, errno = %d, status = 0x%x\n",
                       fname, pid, n, errno, status);
-- 
cgit v1.2.2


From 4f0272415ad1867cea2a7ef5659769243ae50fbe Mon Sep 17 00:00:00 2001
From: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Date: Mon, 7 Nov 2005 00:58:46 -0800
Subject: [PATCH] uml: fix syscall stubs

Jeff Dike noted that the assembly code for syscall stubs is misassembled with
GCC 3.2.3: the values copied in registers weren't preserved between one asm()
and the following one.

So I fixed the thing by rewriting the __asm__ constraints more like unistd.h
ones.

Note: in syscall6 case I had to add one more instruction (i.e.  moving arg6 in
eax and shuffling things around) - it's needed for the function to be valid in
general (we can't load the value from the stack, relative to ebp, because we
change it), but could be avoided since we actually use a constant as param 6.

The only fix would be to turn stub_syscall6 to a macro and use a "i"
constraint for arg6 (i.e., specify it's a constant value).

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/include/sysdep-i386/stub.h   | 64 +++++++++++++++++++++++++-----------
 arch/um/include/sysdep-x86_64/stub.h | 61 ++++++++++++++++++++++++++--------
 2 files changed, 92 insertions(+), 33 deletions(-)

(limited to 'arch')

diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h
index d3699fe1c6..a49ceb199e 100644
--- a/arch/um/include/sysdep-i386/stub.h
+++ b/arch/um/include/sysdep-i386/stub.h
@@ -16,45 +16,69 @@ extern void stub_clone_handler(void);
 #define STUB_MMAP_NR __NR_mmap2
 #define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)
 
+static inline long stub_syscall1(long syscall, long arg1)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1));
+
+	return ret;
+}
+
 static inline long stub_syscall2(long syscall, long arg1, long arg2)
 {
 	long ret;
 
-	__asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
-	__asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
-	__asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
-	__asm__("int $0x80;" : : : "%eax");
-	__asm__ __volatile__("movl %%eax, %0; " : "=g" (ret) :);
-	return(ret);
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2));
+
+	return ret;
 }
 
 static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
 {
-	__asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
-	return(stub_syscall2(syscall, arg1, arg2));
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3));
+
+	return ret;
 }
 
 static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
 				 long arg4)
 {
-	__asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
-	return(stub_syscall3(syscall, arg1, arg2, arg3));
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3), "S" (arg4));
+
+	return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+				 long arg4, long arg5)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5));
+
+	return ret;
 }
 
 static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
 				 long arg4, long arg5, long arg6)
 {
 	long ret;
-	__asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
-	__asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
-	__asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
-	__asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
-	__asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
-	__asm__("movl %0, %%edi; " : : "g" (arg5) : "%edi");
-	__asm__ __volatile__("pushl %%ebp ; movl %1, %%ebp; "
-		"int $0x80; popl %%ebp ; "
-		"movl %%eax, %0; " : "=g" (ret) : "g" (arg6) : "%eax");
-	return(ret);
+
+	__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; "
+			"int $0x80 ; pop %%ebp"
+			: "=a" (ret)
+			: "g" (syscall), "b" (arg1), "c" (arg2), "d" (arg3),
+			  "S" (arg4), "D" (arg5), "0" (arg6));
+
+	return ret;
 }
 
 static inline void trap_myself(void)
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h
index f599058d82..2bd6e7a972 100644
--- a/arch/um/include/sysdep-x86_64/stub.h
+++ b/arch/um/include/sysdep-x86_64/stub.h
@@ -17,37 +17,72 @@ extern void stub_clone_handler(void);
 #define STUB_MMAP_NR __NR_mmap
 #define MMAP_OFFSET(o) (o)
 
+#define __syscall_clobber "r11","rcx","memory"
+#define __syscall "syscall"
+
 static inline long stub_syscall2(long syscall, long arg1, long arg2)
 {
 	long ret;
 
-	__asm__("movq %0, %%rsi; " : : "g" (arg2) : "%rsi");
-	__asm__("movq %0, %%rdi; " : : "g" (arg1) : "%rdi");
-	__asm__("movq %0, %%rax; " : : "g" (syscall) : "%rax");
-	__asm__("syscall;" : : : "%rax", "%r11", "%rcx");
-	__asm__ __volatile__("movq %%rax, %0; " : "=g" (ret) :);
-	return(ret);
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
+
+	return ret;
 }
 
 static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
 {
-	__asm__("movq %0, %%rdx; " : : "g" (arg3) : "%rdx");
-	return(stub_syscall2(syscall, arg1, arg2));
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
+		: __syscall_clobber );
+
+	return ret;
 }
 
 static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
 				 long arg4)
 {
-	__asm__("movq %0, %%r10; " : : "g" (arg4) : "%r10");
-	return(stub_syscall3(syscall, arg1, arg2, arg3));
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; " __syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4)
+		: __syscall_clobber, "r10" );
+
+	return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+				 long arg4, long arg5)
+{
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4), "g" (arg5)
+		: __syscall_clobber, "r10", "r8" );
+
+	return ret;
 }
 
 static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
 				 long arg4, long arg5, long arg6)
 {
-	__asm__("movq %0, %%r9; " : : "g" (arg6) : "%r9");
-	__asm__("movq %0, %%r8; " : : "g" (arg5) : "%r8");
-	return(stub_syscall4(syscall, arg1, arg2, arg3, arg4));
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; "
+		"movq %7, %%r9; " __syscall : "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4), "g" (arg5), "g" (arg6)
+		: __syscall_clobber, "r10", "r8", "r9" );
+
+	return ret;
 }
 
 static inline void trap_myself(void)
-- 
cgit v1.2.2


From 0e76422ca5f34bb43b97c0945646ef072bcc1776 Mon Sep 17 00:00:00 2001
From: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Date: Mon, 7 Nov 2005 00:58:47 -0800
Subject: [PATCH] uml: fix UML network driver endianness bugs

ifa->ifa_address and ifa->ifa_mask are defined as __u32, but used as if they
were char[4].

Network code uses htons() to convert it.  So UML's method to access these
fields is wrong for bigendians (e.g.  s390)

I replaced bytewise copying by memcpy(), maybe even that might be removed, if
ifa->ifa_address/mask may be used immediately.

Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Cc: <viro@parcelfarce.linux.theplanet.co.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/drivers/net_kern.c | 38 +++++++-------------------------------
 arch/um/include/net_user.h |  2 +-
 2 files changed, 8 insertions(+), 32 deletions(-)

(limited to 'arch')

diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 721e2601a7..fe865d9a37 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -96,7 +96,6 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static int uml_net_open(struct net_device *dev)
 {
 	struct uml_net_private *lp = dev->priv;
-	char addr[sizeof("255.255.255.255\0")];
 	int err;
 
 	spin_lock(&lp->lock);
@@ -107,7 +106,7 @@ static int uml_net_open(struct net_device *dev)
 	}
 
 	if(!lp->have_mac){
- 		dev_ip_addr(dev, addr, &lp->mac[2]);
+ 		dev_ip_addr(dev, &lp->mac[2]);
  		set_ether_mac(dev, lp->mac);
 	}
 
@@ -664,8 +663,6 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
 			      void *ptr)
 {
 	struct in_ifaddr *ifa = ptr;
-	u32 addr = ifa->ifa_address;
-	u32 netmask = ifa->ifa_mask;
 	struct net_device *dev = ifa->ifa_dev->dev;
 	struct uml_net_private *lp;
 	void (*proc)(unsigned char *, unsigned char *, void *);
@@ -685,14 +682,8 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
 		break;
 	}
 	if(proc != NULL){
-		addr_buf[0] = addr & 0xff;
-		addr_buf[1] = (addr >> 8) & 0xff;
-		addr_buf[2] = (addr >> 16) & 0xff;
-		addr_buf[3] = addr >> 24;
-		netmask_buf[0] = netmask & 0xff;
-		netmask_buf[1] = (netmask >> 8) & 0xff;
-		netmask_buf[2] = (netmask >> 16) & 0xff;
-		netmask_buf[3] = netmask >> 24;
+		memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf));
+		memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf));
 		(*proc)(addr_buf, netmask_buf, &lp->user);
 	}
 	return(NOTIFY_DONE);
@@ -774,27 +765,18 @@ int setup_etheraddr(char *str, unsigned char *addr)
 	return(1);
 }
 
-void dev_ip_addr(void *d, char *buf, char *bin_buf)
+void dev_ip_addr(void *d, unsigned char *bin_buf)
 {
 	struct net_device *dev = d;
 	struct in_device *ip = dev->ip_ptr;
 	struct in_ifaddr *in;
-	u32 addr;
 
 	if((ip == NULL) || ((in = ip->ifa_list) == NULL)){
 		printk(KERN_WARNING "dev_ip_addr - device not assigned an "
 		       "IP address\n");
 		return;
 	}
-	addr = in->ifa_address;
-	sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff, 
-		(addr >> 16) & 0xff, addr >> 24);
-	if(bin_buf){
-		bin_buf[0] = addr & 0xff;
-		bin_buf[1] = (addr >> 8) & 0xff;
-		bin_buf[2] = (addr >> 16) & 0xff;
-		bin_buf[3] = addr >> 24;
-	}
+	memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
 }
 
 void set_ether_mac(void *d, unsigned char *addr)
@@ -829,14 +811,8 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
 	if(ip == NULL) return;
 	in = ip->ifa_list;
 	while(in != NULL){
-		address[0] = in->ifa_address & 0xff;
-		address[1] = (in->ifa_address >> 8) & 0xff;
-		address[2] = (in->ifa_address >> 16) & 0xff;
-		address[3] = in->ifa_address >> 24;
-		netmask[0] = in->ifa_mask & 0xff;
-		netmask[1] = (in->ifa_mask >> 8) & 0xff;
-		netmask[2] = (in->ifa_mask >> 16) & 0xff;
-		netmask[3] = in->ifa_mask >> 24;
+		memcpy(address, &in->ifa_address, sizeof(address));
+		memcpy(netmask, &in->ifa_mask, sizeof(netmask));
 		(*cb)(address, netmask, arg);
 		in = in->ifa_next;
 	}
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 89885a77a7..800c403920 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -25,7 +25,7 @@ struct net_user_info {
 };
 
 extern void ether_user_init(void *data, void *dev);
-extern void dev_ip_addr(void *d, char *buf, char *bin_buf);
+extern void dev_ip_addr(void *d, unsigned char *bin_buf);
 extern void set_ether_mac(void *d, unsigned char *addr);
 extern void iter_addresses(void *d, void (*cb)(unsigned char *, 
 					       unsigned char *, void *), 
-- 
cgit v1.2.2


From bb578426253ab9950cc20b4e5dd6aefb5500144f Mon Sep 17 00:00:00 2001
From: Gennady Sharapov <Gennady.V.Sharapov@intel.com>
Date: Mon, 7 Nov 2005 00:58:50 -0800
Subject: [PATCH] uml: separate libc-dependent uaccess code

The serial UML OS-abstraction layer patch (um/kernel dir).

This moves all systemcalls from uaccess_user.c file under os-Linux dir

Signed-off-by: Gennady Sharapov <Gennady.V.Sharapov@intel.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/include/os.h             |  6 ++++
 arch/um/include/uml_uaccess.h    |  4 ---
 arch/um/kernel/Makefile          |  2 +-
 arch/um/kernel/tt/uaccess_user.c |  1 +
 arch/um/kernel/uaccess.c         | 30 +++++++++++++++++++
 arch/um/kernel/uaccess_user.c    | 64 ----------------------------------------
 arch/um/os-Linux/Makefile        |  4 +--
 arch/um/os-Linux/uaccess.c       | 32 ++++++++++++++++++++
 8 files changed, 72 insertions(+), 71 deletions(-)
 create mode 100644 arch/um/kernel/uaccess.c
 delete mode 100644 arch/um/kernel/uaccess_user.c
 create mode 100644 arch/um/os-Linux/uaccess.c

(limited to 'arch')

diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 2e58e304b8..b9f53519bb 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -199,6 +199,12 @@ extern void forward_pending_sigio(int target);
 extern int start_fork_tramp(void *arg, unsigned long temp_stack,
 			    int clone_flags, int (*tramp)(void *));
 
+/* uaccess.c */
+extern unsigned long __do_user_copy(void *to, const void *from, int n,
+				    void **fault_addr, void **fault_catcher,
+				    void (*op)(void *to, const void *from,
+					       int n), int *faulted_out);
+
 #endif
 
 /*
diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h
index f77eb64284..c0df11d06f 100644
--- a/arch/um/include/uml_uaccess.h
+++ b/arch/um/include/uml_uaccess.h
@@ -8,10 +8,6 @@
 
 extern int __do_copy_to_user(void *to, const void *from, int n,
 			     void **fault_addr, void **fault_catcher);
-extern unsigned long __do_user_copy(void *to, const void *from, int n,
-				    void **fault_addr, void **fault_catcher,
-				    void (*op)(void *to, const void *from,
-					       int n), int *faulted_out);
 void __do_copy(void *to, const void *from, int n);
 
 #endif
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 1a0001b385..72fd4eada9 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -10,7 +10,7 @@ obj-y = config.o exec_kern.o exitcode.o \
 	helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \
 	process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
 	signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
-	time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
+	time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \
 	umid.o user_util.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
index 8c220f054b..6c92bbccb4 100644
--- a/arch/um/kernel/tt/uaccess_user.c
+++ b/arch/um/kernel/tt/uaccess_user.c
@@ -10,6 +10,7 @@
 #include "uml_uaccess.h"
 #include "task.h"
 #include "kern_util.h"
+#include "os.h"
 
 int __do_copy_from_user(void *to, const void *from, int n,
 			void **fault_addr, void **fault_catcher)
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
new file mode 100644
index 0000000000..054e3de078
--- /dev/null
+++ b/arch/um/kernel/uaccess.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+/* These are here rather than tt/uaccess.c because skas mode needs them in
+ * order to do SIGBUS recovery when a tmpfs mount runs out of room.
+ */
+
+#include <linux/string.h>
+#include "os.h"
+
+void __do_copy(void *to, const void *from, int n)
+{
+	memcpy(to, from, n);
+}
+
+
+int __do_copy_to_user(void *to, const void *from, int n,
+		      void **fault_addr, void **fault_catcher)
+{
+	unsigned long fault;
+	int faulted;
+
+	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
+			       __do_copy, &faulted);
+	if(!faulted) return(0);
+	else return(n - (fault - (unsigned long) to));
+}
diff --git a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c
deleted file mode 100644
index d035257ed0..0000000000
--- a/arch/um/kernel/uaccess_user.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <setjmp.h>
-#include <string.h>
-
-/* These are here rather than tt/uaccess.c because skas mode needs them in
- * order to do SIGBUS recovery when a tmpfs mount runs out of room.
- */
-
-unsigned long __do_user_copy(void *to, const void *from, int n,
-			     void **fault_addr, void **fault_catcher,
-			     void (*op)(void *to, const void *from,
-					int n), int *faulted_out)
-{
-	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
-
-	sigjmp_buf jbuf;
-	*fault_catcher = &jbuf;
-	if(sigsetjmp(jbuf, 1) == 0){
-		(*op)(to, from, n);
-		ret = 0;
-		*faulted_out = 0;
-	} 
-	else {
-		ret = *faddrp;
-		*faulted_out = 1;
-	}
-	*fault_addr = NULL;
-	*fault_catcher = NULL;
-	return ret;
-}
-
-void __do_copy(void *to, const void *from, int n)
-{
-	memcpy(to, from, n);
-}	
-
-
-int __do_copy_to_user(void *to, const void *from, int n,
-		      void **fault_addr, void **fault_catcher)
-{
-	unsigned long fault;
-	int faulted;
-
-	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
-			       __do_copy, &faulted);
-	if(!faulted) return(0);
-	else return(n - (fault - (unsigned long) to));
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index d15ec2af6a..d389c58b18 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,10 +4,10 @@
 #
 
 obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \
-	tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/
+	tt.o tty.o uaccess.o user_syms.o drivers/ sys-$(SUBARCH)/
 
 USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \
-	time.o tt.o tty.o
+	time.o tt.o tty.o uaccess.o
 
 elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
 CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
new file mode 100644
index 0000000000..38d710158c
--- /dev/null
+++ b/arch/um/os-Linux/uaccess.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <setjmp.h>
+#include <string.h>
+
+unsigned long __do_user_copy(void *to, const void *from, int n,
+			     void **fault_addr, void **fault_catcher,
+			     void (*op)(void *to, const void *from,
+					int n), int *faulted_out)
+{
+	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
+
+	sigjmp_buf jbuf;
+	*fault_catcher = &jbuf;
+	if(sigsetjmp(jbuf, 1) == 0){
+		(*op)(to, from, n);
+		ret = 0;
+		*faulted_out = 0;
+	}
+	else {
+		ret = *faddrp;
+		*faulted_out = 1;
+	}
+	*fault_addr = NULL;
+	*fault_catcher = NULL;
+	return ret;
+}
+
-- 
cgit v1.2.2


From 52c653b3bed323df9006c06cdfb4548ec44b3109 Mon Sep 17 00:00:00 2001
From: Jeff Dike <jdike@addtoit.com>
Date: Mon, 7 Nov 2005 00:58:50 -0800
Subject: [PATCH] uml: separate libc-dependent early initialization

The serial UML OS-abstraction layer patch (um/kernel dir).

This moves all systemcalls from main.c file under os-Linux dir and joins mem.c
and um_arch.c files.

Signed-off-by: Gennady Sharapov <Gennady.V.Sharapov@intel.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/kernel/Makefile   |   4 +-
 arch/um/kernel/main.c     | 270 ----------------------------------------------
 arch/um/os-Linux/Makefile |   8 +-
 arch/um/os-Linux/main.c   | 259 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 276 deletions(-)
 delete mode 100644 arch/um/kernel/main.c
 create mode 100644 arch/um/os-Linux/main.c

(limited to 'arch')

diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 72fd4eada9..f985858386 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
 clean-files :=
 
 obj-y = config.o exec_kern.o exitcode.o \
-	helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \
+	helper.o init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
 	process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
 	signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
 	time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \
@@ -24,7 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
 
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
-USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \
+USER_OBJS := $(user-objs-y) config.o helper.o time.o tty_log.o umid.o \
 	user_util.o
 
 include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
deleted file mode 100644
index d31027f0fe..0000000000
--- a/arch/um/kernel/main.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/resource.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-#include <asm/page.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "mem_user.h"
-#include "signal_user.h"
-#include "time_user.h"
-#include "irq_user.h"
-#include "user.h"
-#include "init.h"
-#include "mode.h"
-#include "choose-mode.h"
-#include "uml-config.h"
-#include "os.h"
-
-/* Set in set_stklim, which is called from main and __wrap_malloc.
- * __wrap_malloc only calls it if main hasn't started.
- */
-unsigned long stacksizelim;
-
-/* Set in main */
-char *linux_prog;
-
-#define PGD_BOUND (4 * 1024 * 1024)
-#define STACKSIZE (8 * 1024 * 1024)
-#define THREAD_NAME_LEN (256)
-
-static void set_stklim(void)
-{
-	struct rlimit lim;
-
-	if(getrlimit(RLIMIT_STACK, &lim) < 0){
-		perror("getrlimit");
-		exit(1);
-	}
-	if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){
-		lim.rlim_cur = STACKSIZE;
-		if(setrlimit(RLIMIT_STACK, &lim) < 0){
-			perror("setrlimit");
-			exit(1);
-		}
-	}
-	stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
-}
-
-static __init void do_uml_initcalls(void)
-{
-	initcall_t *call;
-
-	call = &__uml_initcall_start;
-	while (call < &__uml_initcall_end){;
-		(*call)();
-		call++;
-	}
-}
-
-static void last_ditch_exit(int sig)
-{
-	signal(SIGINT, SIG_DFL);
-	signal(SIGTERM, SIG_DFL);
-	signal(SIGHUP, SIG_DFL);
-	uml_cleanup();
-	exit(1);
-}
-
-extern int uml_exitcode;
-
-extern void scan_elf_aux( char **envp);
-
-int main(int argc, char **argv, char **envp)
-{
-	char **new_argv;
-	sigset_t mask;
-	int ret, i, err;
-
-	/* Enable all signals except SIGIO - in some environments, we can
-	 * enter with some signals blocked
-	 */
-
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGIO);
-	if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
-		perror("sigprocmask");
-		exit(1);
-	}
-
-#ifdef UML_CONFIG_CMDLINE_ON_HOST
-	/* Allocate memory for thread command lines */
-	if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
-
-		char padding[THREAD_NAME_LEN] = {
-			[ 0 ...  THREAD_NAME_LEN - 2] = ' ', '\0'
-		};
-
-		new_argv = malloc((argc + 2) * sizeof(char*));
-		if(!new_argv) {
-			perror("Allocating extended argv");
-			exit(1);
-		}
-
-		new_argv[0] = argv[0];
-		new_argv[1] = padding;
-
-		for(i = 2; i <= argc; i++)
-			new_argv[i] = argv[i - 1];
-		new_argv[argc + 1] = NULL;
-
-		execvp(new_argv[0], new_argv);
-		perror("execing with extended args");
-		exit(1);
-	}
-#endif
-
-	linux_prog = argv[0];
-
-	set_stklim();
-
-	new_argv = malloc((argc + 1) * sizeof(char *));
-	if(new_argv == NULL){
-		perror("Mallocing argv");
-		exit(1);
-	}
-	for(i=0;i<argc;i++){
-		new_argv[i] = strdup(argv[i]);
-		if(new_argv[i] == NULL){
-			perror("Mallocing an arg");
-			exit(1);
-		}
-	}
-	new_argv[argc] = NULL;
-
-	set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-	set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-	set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-
-	scan_elf_aux( envp);
-
-	do_uml_initcalls();
-	ret = linux_main(argc, argv);
-
-	/* Disable SIGPROF - I have no idea why libc doesn't do this or turn
-	 * off the profiling time, but UML dies with a SIGPROF just before
-	 * exiting when profiling is active.
-	 */
-	change_sig(SIGPROF, 0);
-
-        /* This signal stuff used to be in the reboot case.  However,
-         * sometimes a SIGVTALRM can come in when we're halting (reproducably
-         * when writing out gcov information, presumably because that takes
-         * some time) and cause a segfault.
-         */
-
-        /* stop timers and set SIG*ALRM to be ignored */
-        disable_timer();
-
-        /* disable SIGIO for the fds and set SIGIO to be ignored */
-        err = deactivate_all_fds();
-        if(err)
-                printf("deactivate_all_fds failed, errno = %d\n", -err);
-
-        /* Let any pending signals fire now.  This ensures
-         * that they won't be delivered after the exec, when
-         * they are definitely not expected.
-         */
-        unblock_signals();
-
-	/* Reboot */
-	if(ret){
-		printf("\n");
-		execvp(new_argv[0], new_argv);
-		perror("Failed to exec kernel");
-		ret = 1;
-	}
-	printf("\n");
-	return(uml_exitcode);
-}
-
-#define CAN_KMALLOC() \
-	(kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1))
-
-extern void *__real_malloc(int);
-
-void *__wrap_malloc(int size)
-{
-	void *ret;
-
-	if(!CAN_KMALLOC())
-		return(__real_malloc(size));
-	else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
-		ret = um_kmalloc(size);
-	else ret = um_vmalloc(size);
-
-	/* glibc people insist that if malloc fails, errno should be
-	 * set by malloc as well. So we do.
-	 */
-	if(ret == NULL)
-		errno = ENOMEM;
-
-	return(ret);
-}
-
-void *__wrap_calloc(int n, int size)
-{
-	void *ptr = __wrap_malloc(n * size);
-
-	if(ptr == NULL) return(NULL);
-	memset(ptr, 0, n * size);
-	return(ptr);
-}
-
-extern void __real_free(void *);
-
-extern unsigned long high_physmem;
-
-void __wrap_free(void *ptr)
-{
-	unsigned long addr = (unsigned long) ptr;
-
-	/* We need to know how the allocation happened, so it can be correctly
-	 * freed.  This is done by seeing what region of memory the pointer is
-	 * in -
-	 * 	physical memory - kmalloc/kfree
-	 *	kernel virtual memory - vmalloc/vfree
-	 * 	anywhere else - malloc/free
-	 * If kmalloc is not yet possible, then either high_physmem and/or
-	 * end_vm are still 0 (as at startup), in which case we call free, or
-	 * we have set them, but anyway addr has not been allocated from those
-	 * areas. So, in both cases __real_free is called.
-	 *
-	 * CAN_KMALLOC is checked because it would be bad to free a buffer
-	 * with kmalloc/vmalloc after they have been turned off during
-	 * shutdown.
-	 * XXX: However, we sometimes shutdown CAN_KMALLOC temporarily, so
-	 * there is a possibility for memory leaks.
-	 */
-
-	if((addr >= uml_physmem) && (addr < high_physmem)){
-		if(CAN_KMALLOC())
-			kfree(ptr);
-	}
-	else if((addr >= start_vm) && (addr < end_vm)){
-		if(CAN_KMALLOC())
-			vfree(ptr);
-	}
-	else __real_free(ptr);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index d389c58b18..0b761a08f0 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,11 +3,11 @@
 # Licensed under the GPL
 #
 
-obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \
-	tt.o tty.o uaccess.o user_syms.o drivers/ sys-$(SUBARCH)/
+obj-y = aio.o elf_aux.o file.o main.o mem.o process.o signal.o start_up.o \
+	time.o tt.o tty.o uaccess.o user_syms.o drivers/ sys-$(SUBARCH)/
 
-USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \
-	time.o tt.o tty.o uaccess.o
+USER_OBJS := aio.o elf_aux.o file.o main.o mem.o process.o signal.o \
+	start_up.o time.o tt.o tty.o uaccess.o
 
 elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
 CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
new file mode 100644
index 0000000000..23da27d225
--- /dev/null
+++ b/arch/um/os-Linux/main.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#include <asm/page.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "mem_user.h"
+#include "signal_user.h"
+#include "time_user.h"
+#include "irq_user.h"
+#include "user.h"
+#include "init.h"
+#include "mode.h"
+#include "choose-mode.h"
+#include "uml-config.h"
+#include "os.h"
+
+/* Set in set_stklim, which is called from main and __wrap_malloc.
+ * __wrap_malloc only calls it if main hasn't started.
+ */
+unsigned long stacksizelim;
+
+/* Set in main */
+char *linux_prog;
+
+#define PGD_BOUND (4 * 1024 * 1024)
+#define STACKSIZE (8 * 1024 * 1024)
+#define THREAD_NAME_LEN (256)
+
+static void set_stklim(void)
+{
+	struct rlimit lim;
+
+	if(getrlimit(RLIMIT_STACK, &lim) < 0){
+		perror("getrlimit");
+		exit(1);
+	}
+	if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){
+		lim.rlim_cur = STACKSIZE;
+		if(setrlimit(RLIMIT_STACK, &lim) < 0){
+			perror("setrlimit");
+			exit(1);
+		}
+	}
+	stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
+}
+
+static __init void do_uml_initcalls(void)
+{
+	initcall_t *call;
+
+	call = &__uml_initcall_start;
+	while (call < &__uml_initcall_end){;
+		(*call)();
+		call++;
+	}
+}
+
+static void last_ditch_exit(int sig)
+{
+	signal(SIGINT, SIG_DFL);
+	signal(SIGTERM, SIG_DFL);
+	signal(SIGHUP, SIG_DFL);
+	uml_cleanup();
+	exit(1);
+}
+
+extern int uml_exitcode;
+
+extern void scan_elf_aux( char **envp);
+
+int main(int argc, char **argv, char **envp)
+{
+	char **new_argv;
+	sigset_t mask;
+	int ret, i, err;
+
+	/* Enable all signals except SIGIO - in some environments, we can
+	 * enter with some signals blocked
+	 */
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGIO);
+	if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
+		perror("sigprocmask");
+		exit(1);
+	}
+
+#ifdef UML_CONFIG_CMDLINE_ON_HOST
+	/* Allocate memory for thread command lines */
+	if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
+
+		char padding[THREAD_NAME_LEN] = {
+			[ 0 ...  THREAD_NAME_LEN - 2] = ' ', '\0'
+		};
+
+		new_argv = malloc((argc + 2) * sizeof(char*));
+		if(!new_argv) {
+			perror("Allocating extended argv");
+			exit(1);
+		}
+
+		new_argv[0] = argv[0];
+		new_argv[1] = padding;
+
+		for(i = 2; i <= argc; i++)
+			new_argv[i] = argv[i - 1];
+		new_argv[argc + 1] = NULL;
+
+		execvp(new_argv[0], new_argv);
+		perror("execing with extended args");
+		exit(1);
+	}
+#endif
+
+	linux_prog = argv[0];
+
+	set_stklim();
+
+	new_argv = malloc((argc + 1) * sizeof(char *));
+	if(new_argv == NULL){
+		perror("Mallocing argv");
+		exit(1);
+	}
+	for(i=0;i<argc;i++){
+		new_argv[i] = strdup(argv[i]);
+		if(new_argv[i] == NULL){
+			perror("Mallocing an arg");
+			exit(1);
+		}
+	}
+	new_argv[argc] = NULL;
+
+	set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+	set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+	set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+
+	scan_elf_aux( envp);
+
+	do_uml_initcalls();
+	ret = linux_main(argc, argv);
+
+	/* Disable SIGPROF - I have no idea why libc doesn't do this or turn
+	 * off the profiling time, but UML dies with a SIGPROF just before
+	 * exiting when profiling is active.
+	 */
+	change_sig(SIGPROF, 0);
+
+	/* This signal stuff used to be in the reboot case.  However,
+	 * sometimes a SIGVTALRM can come in when we're halting (reproducably
+	 * when writing out gcov information, presumably because that takes
+	 * some time) and cause a segfault.
+	 */
+
+	/* stop timers and set SIG*ALRM to be ignored */
+	disable_timer();
+
+	/* disable SIGIO for the fds and set SIGIO to be ignored */
+	err = deactivate_all_fds();
+	if(err)
+		printf("deactivate_all_fds failed, errno = %d\n", -err);
+
+	/* Let any pending signals fire now.  This ensures
+	 * that they won't be delivered after the exec, when
+	 * they are definitely not expected.
+	 */
+	unblock_signals();
+
+	/* Reboot */
+	if(ret){
+		printf("\n");
+		execvp(new_argv[0], new_argv);
+		perror("Failed to exec kernel");
+		ret = 1;
+	}
+	printf("\n");
+	return(uml_exitcode);
+}
+
+#define CAN_KMALLOC() \
+	(kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1))
+
+extern void *__real_malloc(int);
+
+void *__wrap_malloc(int size)
+{
+	void *ret;
+
+	if(!CAN_KMALLOC())
+		return(__real_malloc(size));
+	else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
+		ret = um_kmalloc(size);
+	else ret = um_vmalloc(size);
+
+	/* glibc people insist that if malloc fails, errno should be
+	 * set by malloc as well. So we do.
+	 */
+	if(ret == NULL)
+		errno = ENOMEM;
+
+	return(ret);
+}
+
+void *__wrap_calloc(int n, int size)
+{
+	void *ptr = __wrap_malloc(n * size);
+
+	if(ptr == NULL) return(NULL);
+	memset(ptr, 0, n * size);
+	return(ptr);
+}
+
+extern void __real_free(void *);
+
+extern unsigned long high_physmem;
+
+void __wrap_free(void *ptr)
+{
+	unsigned long addr = (unsigned long) ptr;
+
+	/* We need to know how the allocation happened, so it can be correctly
+	 * freed.  This is done by seeing what region of memory the pointer is
+	 * in -
+	 * 	physical memory - kmalloc/kfree
+	 *	kernel virtual memory - vmalloc/vfree
+	 * 	anywhere else - malloc/free
+	 * If kmalloc is not yet possible, then either high_physmem and/or
+	 * end_vm are still 0 (as at startup), in which case we call free, or
+	 * we have set them, but anyway addr has not been allocated from those
+	 * areas. So, in both cases __real_free is called.
+	 *
+	 * CAN_KMALLOC is checked because it would be bad to free a buffer
+	 * with kmalloc/vmalloc after they have been turned off during
+	 * shutdown.
+	 * XXX: However, we sometimes shutdown CAN_KMALLOC temporarily, so
+	 * there is a possibility for memory leaks.
+	 */
+
+	if((addr >= uml_physmem) && (addr < high_physmem)){
+		if(CAN_KMALLOC())
+			kfree(ptr);
+	}
+	else if((addr >= start_vm) && (addr < end_vm)){
+		if(CAN_KMALLOC())
+			vfree(ptr);
+	}
+	else __real_free(ptr);
+}
-- 
cgit v1.2.2


From ff5c6ff54215fe284e515032878111de5d8a5ce1 Mon Sep 17 00:00:00 2001
From: Jeff Dike <jdike@addtoit.com>
Date: Mon, 7 Nov 2005 00:58:51 -0800
Subject: [PATCH] uml: separate libc-dependent helper code

The serial UML OS-abstraction layer patch (um/kernel dir).

This moves all systemcalls from helper.c file under os-Linux dir

Signed-off-by: Gennady Sharapov <Gennady.V.Sharapov@intel.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/drivers/chan_user.c              |   1 -
 arch/um/drivers/harddog_kern.c           |   1 -
 arch/um/drivers/harddog_user.c           |   1 -
 arch/um/drivers/net_user.c               |   1 -
 arch/um/drivers/port_user.c              |   1 -
 arch/um/drivers/slip_user.c              |   1 -
 arch/um/drivers/slirp_user.c             |   1 -
 arch/um/drivers/xterm.c                  |   1 -
 arch/um/include/helper.h                 |  27 -----
 arch/um/include/os.h                     |   8 ++
 arch/um/kernel/Makefile                  |   5 +-
 arch/um/kernel/helper.c                  | 165 -------------------------------
 arch/um/kernel/ksyms.c                   |   1 -
 arch/um/kernel/sigio_user.c              |   1 -
 arch/um/kernel/user_util.c               |   1 -
 arch/um/os-Linux/Makefile                |   7 +-
 arch/um/os-Linux/aio.c                   |   1 -
 arch/um/os-Linux/drivers/ethertap_user.c |   1 -
 arch/um/os-Linux/drivers/tuntap_user.c   |   1 -
 arch/um/os-Linux/helper.c                | 165 +++++++++++++++++++++++++++++++
 20 files changed, 179 insertions(+), 212 deletions(-)
 delete mode 100644 arch/um/include/helper.h
 delete mode 100644 arch/um/kernel/helper.c
 create mode 100644 arch/um/os-Linux/helper.c

(limited to 'arch')

diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index de3bce71ae..1c55d58024 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -16,7 +16,6 @@
 #include "user_util.h"
 #include "chan_user.h"
 #include "user.h"
-#include "helper.h"
 #include "os.h"
 #include "choose-mode.h"
 #include "mode.h"
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index 147ec19f6b..49acb2badf 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -46,7 +46,6 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
-#include "helper.h"
 #include "mconsole.h"
 
 MODULE_LICENSE("GPL");
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index d934181b8d..def013b5a3 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -8,7 +8,6 @@
 #include <errno.h>
 #include "user_util.h"
 #include "user.h"
-#include "helper.h"
 #include "mconsole.h"
 #include "os.h"
 #include "choose-mode.h"
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 3730d4f127..098fa65981 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -16,7 +16,6 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "net_user.h"
-#include "helper.h"
 #include "os.h"
 
 int tap_open_common(void *dev, char *gate_addr)
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 14dd2002d2..ed4a1a6c5d 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -18,7 +18,6 @@
 #include "user.h"
 #include "chan_user.h"
 #include "port.h"
-#include "helper.h"
 #include "os.h"
 
 struct port_chan {
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 71af444e59..89fbec185c 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -14,7 +14,6 @@
 #include "net_user.h"
 #include "slip.h"
 #include "slip_common.h"
-#include "helper.h"
 #include "os.h"
 
 void slip_user_init(void *data, void *dev)
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 8d91f663d8..b94c66114b 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -13,7 +13,6 @@
 #include "net_user.h"
 #include "slirp.h"
 #include "slip_common.h"
-#include "helper.h"
 #include "os.h"
 
 void slirp_user_init(void *data, void *dev)
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 90e0e5ff45..b530f1a654 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -14,7 +14,6 @@
 #include <sys/socket.h>
 #include "kern_util.h"
 #include "chan_user.h"
-#include "helper.h"
 #include "user_util.h"
 #include "user.h"
 #include "os.h"
diff --git a/arch/um/include/helper.h b/arch/um/include/helper.h
deleted file mode 100644
index 162ac31192..0000000000
--- a/arch/um/include/helper.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __HELPER_H__
-#define __HELPER_H__
-
-extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-		      unsigned long *stack_out);
-extern int run_helper_thread(int (*proc)(void *), void *arg, 
-			     unsigned int flags, unsigned long *stack_out,
-			     int stack_order);
-extern int helper_wait(int pid);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index b9f53519bb..112d7288f0 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -205,6 +205,14 @@ extern unsigned long __do_user_copy(void *to, const void *from, int n,
 				    void (*op)(void *to, const void *from,
 					       int n), int *faulted_out);
 
+/* helper.c */
+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
+		      unsigned long *stack_out);
+extern int run_helper_thread(int (*proc)(void *), void *arg,
+			     unsigned int flags, unsigned long *stack_out,
+			     int stack_order);
+extern int helper_wait(int pid);
+
 #endif
 
 /*
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index f985858386..3de9d21e36 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
 clean-files :=
 
 obj-y = config.o exec_kern.o exitcode.o \
-	helper.o init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
+	init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
 	process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
 	signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
 	time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \
@@ -24,8 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
 
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
-USER_OBJS := $(user-objs-y) config.o helper.o time.o tty_log.o umid.o \
-	user_util.o
+USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o
 
 include arch/um/scripts/Makefile.rules
 
diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c
deleted file mode 100644
index 33fb0bd3b1..0000000000
--- a/arch/um/kernel/helper.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sched.h>
-#include <sys/signal.h>
-#include <sys/wait.h>
-#include "user.h"
-#include "kern_util.h"
-#include "user_util.h"
-#include "helper.h"
-#include "os.h"
-
-struct helper_data {
-	void (*pre_exec)(void*);
-	void *pre_data;
-	char **argv;
-	int fd;
-};
-
-/* Debugging aid, changed only from gdb */
-int helper_pause = 0;
-
-static void helper_hup(int sig)
-{
-}
-
-static int helper_child(void *arg)
-{
-	struct helper_data *data = arg;
-	char **argv = data->argv;
-	int errval;
-
-	if(helper_pause){
-		signal(SIGHUP, helper_hup);
-		pause();
-	}
-	if(data->pre_exec != NULL)
-		(*data->pre_exec)(data->pre_data);
-	execvp(argv[0], argv);
-	errval = errno;
-	printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
-	os_write_file(data->fd, &errval, sizeof(errval));
-	os_kill_process(os_getpid(), 0);
-	return(0);
-}
-
-/* Returns either the pid of the child process we run or -E* on failure.
- * XXX The alloc_stack here breaks if this is called in the tracing thread */
-int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-	       unsigned long *stack_out)
-{
-	struct helper_data data;
-	unsigned long stack, sp;
-	int pid, fds[2], ret, n;
-
-	if((stack_out != NULL) && (*stack_out != 0))
-		stack = *stack_out;
-	else stack = alloc_stack(0, um_in_interrupt());
-	if(stack == 0)
-		return(-ENOMEM);
-
-	ret = os_pipe(fds, 1, 0);
-	if(ret < 0){
-		printk("run_helper : pipe failed, ret = %d\n", -ret);
-		goto out_free;
-	}
-
-	ret = os_set_exec_close(fds[1], 1);
-	if(ret < 0){
-		printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
-		       -ret);
-		goto out_close;
-	}
-
-	sp = stack + page_size() - sizeof(void *);
-	data.pre_exec = pre_exec;
-	data.pre_data = pre_data;
-	data.argv = argv;
-	data.fd = fds[1];
-	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
-	if(pid < 0){
-		ret = -errno;
-		printk("run_helper : clone failed, errno = %d\n", errno);
-		goto out_close;
-	}
-
-	os_close_file(fds[1]);
-	fds[1] = -1;
-
-	/*Read the errno value from the child.*/
-	n = os_read_file(fds[0], &ret, sizeof(ret));
-	if(n < 0){
-		printk("run_helper : read on pipe failed, ret = %d\n", -n);
-		ret = n;
-		os_kill_process(pid, 1);
-	}
-	else if(n != 0){
-		CATCH_EINTR(n = waitpid(pid, NULL, 0));
-		ret = -errno;
-	} else {
-		ret = pid;
-	}
-
-out_close:
-	if (fds[1] != -1)
-		os_close_file(fds[1]);
-	os_close_file(fds[0]);
-out_free:
-	if(stack_out == NULL)
-		free_stack(stack, 0);
-	else *stack_out = stack;
-	return(ret);
-}
-
-int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, 
-		      unsigned long *stack_out, int stack_order)
-{
-	unsigned long stack, sp;
-	int pid, status, err;
-
-	stack = alloc_stack(stack_order, um_in_interrupt());
-	if(stack == 0) return(-ENOMEM);
-
-	sp = stack + (page_size() << stack_order) - sizeof(void *);
-	pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
-	if(pid < 0){
-		err = -errno;
-		printk("run_helper_thread : clone failed, errno = %d\n", 
-		       errno);
-		return err;
-	}
-	if(stack_out == NULL){
-		CATCH_EINTR(pid = waitpid(pid, &status, 0));
-		if(pid < 0){
-			err = -errno;
-			printk("run_helper_thread - wait failed, errno = %d\n",
-			       errno);
-			pid = err;
-		}
-		if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
-			printk("run_helper_thread - thread returned status "
-			       "0x%x\n", status);
-		free_stack(stack, stack_order);
-	}
-	else *stack_out = stack;
-	return(pid);
-}
-
-int helper_wait(int pid)
-{
-	int ret;
-
-	CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
-	if(ret < 0){
-		ret = -errno;
-		printk("helper_wait : waitpid failed, errno = %d\n", errno);
-	}
-	return(ret);
-}
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index a97a72e516..7713e7a6f4 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -20,7 +20,6 @@
 #include "user_util.h"
 #include "mem_user.h"
 #include "os.h"
-#include "helper.h"
 
 EXPORT_SYMBOL(stop);
 EXPORT_SYMBOL(uml_physmem);
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index a52751108a..3fbfd956bf 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -18,7 +18,6 @@
 #include "kern_util.h"
 #include "user_util.h"
 #include "sigio.h"
-#include "helper.h"
 #include "os.h"
 
 /* Changed during early boot */
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
index 41d17c7151..4c231161f2 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/kernel/user_util.c
@@ -27,7 +27,6 @@
 #include "user.h"
 #include "mem_user.h"
 #include "init.h"
-#include "helper.h"
 #include "ptrace_user.h"
 #include "uml-config.h"
 
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 0b761a08f0..b83ac8e21c 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,10 +3,11 @@
 # Licensed under the GPL
 #
 
-obj-y = aio.o elf_aux.o file.o main.o mem.o process.o signal.o start_up.o \
-	time.o tt.o tty.o uaccess.o user_syms.o drivers/ sys-$(SUBARCH)/
+obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
+	start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \
+	sys-$(SUBARCH)/
 
-USER_OBJS := aio.o elf_aux.o file.o main.o mem.o process.o signal.o \
+USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
 	start_up.o time.o tt.o tty.o uaccess.o
 
 elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 41cfb09442..ffa759addd 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -10,7 +10,6 @@
 #include <sched.h>
 #include <sys/syscall.h>
 #include "os.h"
-#include "helper.h"
 #include "aio.h"
 #include "init.h"
 #include "user.h"
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index cd4d6544da..901b85e8a1 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -19,7 +19,6 @@
 #include "user_util.h"
 #include "net_user.h"
 #include "etap.h"
-#include "helper.h"
 #include "os.h"
 
 #define MAX_PACKET ETH_MAX_PACKET
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 4ba9b17adf..52945338b6 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -20,7 +20,6 @@
 #include "kern_util.h"
 #include "user_util.h"
 #include "user.h"
-#include "helper.h"
 #include "os.h"
 
 #define MAX_PACKET ETH_MAX_PACKET
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
new file mode 100644
index 0000000000..36cc8475bc
--- /dev/null
+++ b/arch/um/os-Linux/helper.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+#include <sys/signal.h>
+#include <sys/wait.h>
+#include "user.h"
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+
+struct helper_data {
+	void (*pre_exec)(void*);
+	void *pre_data;
+	char **argv;
+	int fd;
+};
+
+/* Debugging aid, changed only from gdb */
+int helper_pause = 0;
+
+static void helper_hup(int sig)
+{
+}
+
+static int helper_child(void *arg)
+{
+	struct helper_data *data = arg;
+	char **argv = data->argv;
+	int errval;
+
+	if(helper_pause){
+		signal(SIGHUP, helper_hup);
+		pause();
+	}
+	if(data->pre_exec != NULL)
+		(*data->pre_exec)(data->pre_data);
+	execvp(argv[0], argv);
+	errval = errno;
+	printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
+	os_write_file(data->fd, &errval, sizeof(errval));
+	kill(os_getpid(), SIGKILL);
+	return(0);
+}
+
+/* Returns either the pid of the child process we run or -E* on failure.
+ * XXX The alloc_stack here breaks if this is called in the tracing thread */
+int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
+	       unsigned long *stack_out)
+{
+	struct helper_data data;
+	unsigned long stack, sp;
+	int pid, fds[2], ret, n;
+
+	if((stack_out != NULL) && (*stack_out != 0))
+		stack = *stack_out;
+	else stack = alloc_stack(0, um_in_interrupt());
+	if(stack == 0)
+		return(-ENOMEM);
+
+	ret = os_pipe(fds, 1, 0);
+	if(ret < 0){
+		printk("run_helper : pipe failed, ret = %d\n", -ret);
+		goto out_free;
+	}
+
+	ret = os_set_exec_close(fds[1], 1);
+	if(ret < 0){
+		printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
+		       -ret);
+		goto out_close;
+	}
+
+	sp = stack + page_size() - sizeof(void *);
+	data.pre_exec = pre_exec;
+	data.pre_data = pre_data;
+	data.argv = argv;
+	data.fd = fds[1];
+	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
+	if(pid < 0){
+		ret = -errno;
+		printk("run_helper : clone failed, errno = %d\n", errno);
+		goto out_close;
+	}
+
+	close(fds[1]);
+	fds[1] = -1;
+
+	/*Read the errno value from the child.*/
+	n = os_read_file(fds[0], &ret, sizeof(ret));
+	if(n < 0){
+		printk("run_helper : read on pipe failed, ret = %d\n", -n);
+		ret = n;
+		kill(pid, SIGKILL);
+		CATCH_EINTR(waitpid(pid, NULL, 0));
+	}
+	else if(n != 0){
+		CATCH_EINTR(n = waitpid(pid, NULL, 0));
+		ret = -errno;
+	} else {
+		ret = pid;
+	}
+
+out_close:
+	if (fds[1] != -1)
+		close(fds[1]);
+	close(fds[0]);
+out_free:
+	if(stack_out == NULL)
+		free_stack(stack, 0);
+	else *stack_out = stack;
+	return(ret);
+}
+
+int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
+		      unsigned long *stack_out, int stack_order)
+{
+	unsigned long stack, sp;
+	int pid, status, err;
+
+	stack = alloc_stack(stack_order, um_in_interrupt());
+	if(stack == 0) return(-ENOMEM);
+
+	sp = stack + (page_size() << stack_order) - sizeof(void *);
+	pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
+	if(pid < 0){
+		err = -errno;
+		printk("run_helper_thread : clone failed, errno = %d\n",
+		       errno);
+		return err;
+	}
+	if(stack_out == NULL){
+		CATCH_EINTR(pid = waitpid(pid, &status, 0));
+		if(pid < 0){
+			err = -errno;
+			printk("run_helper_thread - wait failed, errno = %d\n",
+			       errno);
+			pid = err;
+		}
+		if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
+			printk("run_helper_thread - thread returned status "
+			       "0x%x\n", status);
+		free_stack(stack, stack_order);
+	}
+	else *stack_out = stack;
+	return(pid);
+}
+
+int helper_wait(int pid)
+{
+	int ret;
+
+	CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
+	if(ret < 0){
+		ret = -errno;
+		printk("helper_wait : waitpid failed, errno = %d\n", errno);
+	}
+	return(ret);
+}
-- 
cgit v1.2.2


From 858259cf7d1c443c836a2022b78cb281f0a9b95e Mon Sep 17 00:00:00 2001
From: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Date: Mon, 7 Nov 2005 00:58:55 -0800
Subject: [PATCH] uml: maintain own LDT entries

Patch imlements full LDT handling in SKAS:
 * UML holds it's own LDT table, used to deliver data on
   modify_ldt(READ)
 * UML disables the default_ldt, inherited from the host (SKAS3)
   or resets LDT entries, set by host's clib and inherited in
   SKAS0
 * A new global variable skas_needs_stub is inserted, that
   can be used to decide, whether stub-pages must be supported
   or not.
 * Uses the syscall-stub to replace missing PTRACE_LDT (therefore,
   write_ldt_entry needs to be modified)

Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/kernel/skas/include/mmu-skas.h |   2 +
 arch/um/kernel/skas/include/skas.h     |   3 +-
 arch/um/kernel/skas/mem.c              |   2 +-
 arch/um/kernel/skas/mmu.c              |  44 +--
 arch/um/kernel/skas/process.c          |   6 +-
 arch/um/kernel/skas/process_kern.c     |   2 +-
 arch/um/os-Linux/start_up.c            |  75 ++++-
 arch/um/scripts/Makefile.rules         |   7 +-
 arch/um/sys-i386/ldt.c                 | 506 ++++++++++++++++++++++++++++++---
 arch/um/sys-x86_64/Makefile            |   5 +-
 arch/um/sys-x86_64/syscalls.c          |  75 -----
 11 files changed, 586 insertions(+), 141 deletions(-)

(limited to 'arch')

diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
index 09536f81ee..44110c521e 100644
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ b/arch/um/kernel/skas/include/mmu-skas.h
@@ -8,6 +8,7 @@
 
 #include "linux/config.h"
 #include "mm_id.h"
+#include "asm/ldt.h"
 
 struct mmu_context_skas {
 	struct mm_id id;
@@ -15,6 +16,7 @@ struct mmu_context_skas {
 #ifdef CONFIG_3_LEVEL_PGTABLES
         unsigned long last_pmd;
 #endif
+	uml_ldt_t ldt;
 };
 
 extern void switch_mm_skas(struct mm_id * mm_idp);
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 060934740f..daa2f85b68 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -10,7 +10,8 @@
 #include "sysdep/ptrace.h"
 
 extern int userspace_pid[];
-extern int proc_mm, ptrace_faultinfo;
+extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
+extern int skas_needs_stub;
 
 extern void switch_threads(void *me, void *next);
 extern void thread_wait(void *sw, void *fb);
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 147466d7ff..88ab96c609 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -20,7 +20,7 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
 	*task_size_out = CONFIG_HOST_TASK_SIZE;
 #else
 	*host_size_out = top;
-	if (proc_mm && ptrace_faultinfo)
+	if (!skas_needs_stub)
 		*task_size_out = top;
 	else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
 #endif
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 9e5e39cea8..677871f1b3 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -15,6 +15,7 @@
 #include "asm/mmu.h"
 #include "asm/pgalloc.h"
 #include "asm/pgtable.h"
+#include "asm/ldt.h"
 #include "os.h"
 #include "skas.h"
 
@@ -74,13 +75,12 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
 
 int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
 {
-	struct mm_struct *cur_mm = current->mm;
-	struct mm_id *cur_mm_id = &cur_mm->context.skas.id;
-	struct mm_id *mm_id = &mm->context.skas.id;
+ 	struct mmu_context_skas *from_mm = NULL;
+	struct mmu_context_skas *to_mm = &mm->context.skas;
 	unsigned long stack = 0;
-	int from, ret = -ENOMEM;
+	int from_fd, ret = -ENOMEM;
 
-	if(!proc_mm || !ptrace_faultinfo){
+	if(skas_needs_stub){
 		stack = get_zeroed_page(GFP_KERNEL);
 		if(stack == 0)
 			goto out;
@@ -102,33 +102,43 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
 
 		mm->nr_ptes--;
 	}
-	mm_id->stack = stack;
+
+	to_mm->id.stack = stack;
+	if(current->mm != NULL && current->mm != &init_mm)
+		from_mm = &current->mm->context.skas;
 
 	if(proc_mm){
-		if((cur_mm != NULL) && (cur_mm != &init_mm))
-			from = cur_mm_id->u.mm_fd;
-		else from = -1;
+		if(from_mm)
+			from_fd = from_mm->id.u.mm_fd;
+		else from_fd = -1;
 
-		ret = new_mm(from, stack);
+		ret = new_mm(from_fd, stack);
 		if(ret < 0){
 			printk("init_new_context_skas - new_mm failed, "
 			       "errno = %d\n", ret);
 			goto out_free;
 		}
-		mm_id->u.mm_fd = ret;
+		to_mm->id.u.mm_fd = ret;
 	}
 	else {
-		if((cur_mm != NULL) && (cur_mm != &init_mm))
-			mm_id->u.pid = copy_context_skas0(stack,
-							  cur_mm_id->u.pid);
-		else mm_id->u.pid = start_userspace(stack);
+		if(from_mm)
+			to_mm->id.u.pid = copy_context_skas0(stack,
+							     from_mm->id.u.pid);
+		else to_mm->id.u.pid = start_userspace(stack);
+	}
+
+	ret = init_new_ldt(to_mm, from_mm);
+	if(ret < 0){
+		printk("init_new_context_skas - init_ldt"
+		       " failed, errno = %d\n", ret);
+		goto out_free;
 	}
 
 	return 0;
 
  out_free:
-	if(mm_id->stack != 0)
-		free_page(mm_id->stack);
+	if(to_mm->id.stack != 0)
+		free_page(to_mm->id.stack);
  out:
 	return ret;
 }
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 42f2da687d..599d679bd4 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -381,9 +381,9 @@ int copy_context_skas0(unsigned long new_stack, int pid)
 }
 
 /*
- * This is used only, if proc_mm is available, while PTRACE_FAULTINFO
- * isn't. Opening /proc/mm creates a new mm_context, which lacks the stub-pages
- * Thus, we map them using /proc/mm-fd
+ * This is used only, if stub pages are needed, while proc_mm is
+ * availabl. Opening /proc/mm creates a new mm_context, which lacks
+ * the stub-pages. Thus, we map them using /proc/mm-fd
  */
 void map_stub_pages(int fd, unsigned long code,
 		    unsigned long data, unsigned long stack)
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index efe92e8aa2..9c99025396 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -145,7 +145,7 @@ int new_mm(int from, unsigned long stack)
 			       "err = %d\n", -n);
 	}
 
-	if(!ptrace_faultinfo)
+	if(skas_needs_stub)
 		map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
 
 	return(fd);
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index b99ab41454..553a09c7d0 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -135,7 +135,9 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode,
 }
 
 int ptrace_faultinfo = 1;
+int ptrace_ldt = 1;
 int proc_mm = 1;
+int skas_needs_stub = 0;
 
 static int __init skas0_cmd_param(char *str, int* add)
 {
@@ -352,14 +354,26 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param,
 "    it. To support PTRACE_FAULTINFO, the host needs to be patched\n"
 "    using the current skas3 patch.\n\n");
 
+static int __init noptraceldt_cmd_param(char *str, int* add)
+{
+	ptrace_ldt = 0;
+	return 0;
+}
+
+__uml_setup("noptraceldt", noptraceldt_cmd_param,
+"noptraceldt\n"
+"    Turns off usage of PTRACE_LDT, even if host supports it.\n"
+"    To support PTRACE_LDT, the host needs to be patched using\n"
+"    the current skas3 patch.\n\n");
+
 #ifdef UML_CONFIG_MODE_SKAS
-static inline void check_skas3_ptrace_support(void)
+static inline void check_skas3_ptrace_faultinfo(void)
 {
 	struct ptrace_faultinfo fi;
 	void *stack;
 	int pid, n;
 
-	printf("Checking for the skas3 patch in the host...");
+	printf("  - PTRACE_FAULTINFO...");
 	pid = start_ptraced_child(&stack);
 
 	n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
@@ -381,9 +395,49 @@ static inline void check_skas3_ptrace_support(void)
 	stop_ptraced_child(pid, stack, 1, 1);
 }
 
-int can_do_skas(void)
+static inline void check_skas3_ptrace_ldt(void)
+{
+#ifdef PTRACE_LDT
+	void *stack;
+	int pid, n;
+	unsigned char ldtbuf[40];
+	struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
+		.func = 2, /* read default ldt */
+		.ptr = ldtbuf,
+		.bytecount = sizeof(ldtbuf)};
+
+	printf("  - PTRACE_LDT...");
+	pid = start_ptraced_child(&stack);
+
+	n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
+	if (n < 0) {
+		if(errno == EIO)
+			printf("not found\n");
+		else {
+			perror("not found");
+		}
+		ptrace_ldt = 0;
+	}
+	else {
+		if(ptrace_ldt)
+			printf("found\n");
+		else
+			printf("found, but use is disabled\n");
+	}
+
+	stop_ptraced_child(pid, stack, 1, 1);
+#else
+	/* PTRACE_LDT might be disabled via cmdline option.
+	 * We want to override this, else we might use the stub
+	 * without real need
+	 */
+	ptrace_ldt = 1;
+#endif
+}
+
+static inline void check_skas3_proc_mm(void)
 {
-	printf("Checking for /proc/mm...");
+	printf("  - /proc/mm...");
 	if (os_access("/proc/mm", OS_ACC_W_OK) < 0) {
  		proc_mm = 0;
 		printf("not found\n");
@@ -394,8 +448,19 @@ int can_do_skas(void)
 		else
 			printf("found\n");
 	}
+}
+
+int can_do_skas(void)
+{
+	printf("Checking for the skas3 patch in the host:\n");
+
+	check_skas3_proc_mm();
+	check_skas3_ptrace_faultinfo();
+	check_skas3_ptrace_ldt();
+
+	if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
+		skas_needs_stub = 1;
 
-	check_skas3_ptrace_support();
 	return 1;
 }
 #else
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 651d9d88b6..b3fbf12570 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -26,8 +26,13 @@ define unprofile
 	$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
 endef
 
+# cmd_make_link checks to see if the $(foo-dir) variable starts with a /.  If
+# so, it's considered to be a path relative to $(srcdir) rather than
+# $(srcdir)/arch/$(SUBARCH).  This is because x86_64 wants to get ldt.c from
+# arch/um/sys-i386 rather than arch/i386 like the other borrowed files.  So,
+# it sets $(ldt.c-dir) to /arch/um/sys-i386.
 quiet_cmd_make_link = SYMLINK $@
-cmd_make_link       = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
+cmd_make_link       = rm -f $@; ln -sf $(srctree)$(if $(filter-out /%,$($(notdir $@)-dir)),/arch/$(SUBARCH))/$($(notdir $@)-dir)/$(notdir $@) $@
 
 # this needs to be before the foreach, because targets does not accept
 # complete paths like $(obj)/$(f). To make sure this works, use a := assignment
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 36b5c2c132..6360f1c958 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -3,53 +3,26 @@
  * Licensed under the GPL
  */
 
+#include "linux/stddef.h"
 #include "linux/config.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/types.h"
+#include "linux/errno.h"
 #include "asm/uaccess.h"
-#include "asm/ptrace.h"
 #include "asm/smp.h"
 #include "asm/ldt.h"
+#include "asm/unistd.h"
 #include "choose-mode.h"
 #include "kern.h"
 #include "mode_kern.h"
 
-#ifdef CONFIG_MODE_TT
-
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 
-static int do_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
-{
-	return modify_ldt(func, ptr, bytecount);
-}
-
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-
-#include "skas.h"
-#include "skas_ptrace.h"
-
-static int do_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
-{
-	struct ptrace_ldt ldt;
-	u32 cpu;
-	int res;
-
-	ldt = ((struct ptrace_ldt) { .func	= func,
-				     .ptr	= ptr,
-				     .bytecount = bytecount });
-
-	cpu = get_cpu();
-	res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, (unsigned long) &ldt);
-	put_cpu();
-
-	return res;
-}
-#endif
+#ifdef CONFIG_MODE_TT
 
-int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+static long do_modify_ldt_tt(int func, void __user *ptr,
+			      unsigned long bytecount)
 {
 	struct user_desc info;
 	int res = 0;
@@ -89,8 +62,7 @@ int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
 		goto out;
 	}
 
-	res = CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
-				p, bytecount);
+	res = modify_ldt(func, p, bytecount);
 	if(res < 0)
 		goto out;
 
@@ -108,3 +80,467 @@ out:
 	kfree(buf);
 	return res;
 }
+
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+
+#include "skas.h"
+#include "skas_ptrace.h"
+#include "asm/mmu_context.h"
+
+long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
+		     void **addr, int done)
+{
+	long res;
+
+	if(proc_mm){
+		/* This is a special handling for the case, that the mm to
+		 * modify isn't current->active_mm.
+		 * If this is called directly by modify_ldt,
+		 *     (current->active_mm->context.skas.u == mm_idp)
+		 * will be true. So no call to switch_mm_skas(mm_idp) is done.
+		 * If this is called in case of init_new_ldt or PTRACE_LDT,
+		 * mm_idp won't belong to current->active_mm, but child->mm.
+		 * So we need to switch child's mm into our userspace, then
+		 * later switch back.
+		 *
+		 * Note: I'm unshure: should interrupts be disabled here?
+		 */
+		if(!current->active_mm || current->active_mm == &init_mm ||
+		   mm_idp != &current->active_mm->context.skas.id)
+			switch_mm_skas(mm_idp);
+	}
+
+	if(ptrace_ldt) {
+		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
+			.func = func,
+			.ptr = desc,
+			.bytecount = sizeof(*desc)};
+		u32 cpu;
+		int pid;
+
+		if(!proc_mm)
+			pid = mm_idp->u.pid;
+		else {
+			cpu = get_cpu();
+			pid = userspace_pid[cpu];
+		}
+
+		res = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
+		if(res)
+			res = errno;
+
+		if(proc_mm)
+			put_cpu();
+	}
+	else {
+		void *stub_addr;
+		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
+					(sizeof(*desc) + sizeof(long) - 1) &
+					    ~(sizeof(long) - 1),
+					addr, &stub_addr);
+		if(!res){
+			unsigned long args[] = { func,
+						 (unsigned long)stub_addr,
+						 sizeof(*desc),
+						 0, 0, 0 };
+			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
+					       0, addr, done);
+		}
+	}
+
+	if(proc_mm){
+		/* This is the second part of special handling, that makes
+		 * PTRACE_LDT possible to implement.
+		 */
+		if(current->active_mm && current->active_mm != &init_mm &&
+		   mm_idp != &current->active_mm->context.skas.id)
+			switch_mm_skas(&current->active_mm->context.skas.id);
+	}
+
+	return res;
+}
+
+static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
+{
+	int res, n;
+	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
+			.func = 0,
+			.bytecount = bytecount,
+			.ptr = (void *)kmalloc(bytecount, GFP_KERNEL)};
+	u32 cpu;
+
+	if(ptrace_ldt.ptr == NULL)
+		return -ENOMEM;
+
+	/* This is called from sys_modify_ldt only, so userspace_pid gives
+	 * us the right number
+	 */
+
+	cpu = get_cpu();
+	res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0,
+		     (unsigned long) &ptrace_ldt);
+	put_cpu();
+	if(res < 0)
+		goto out;
+
+	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
+	if(n != 0)
+		res = -EFAULT;
+
+  out:
+	kfree(ptrace_ldt.ptr);
+
+	return res;
+}
+
+/*
+ * In skas mode, we hold our own ldt data in UML.
+ * Thus, the code implementing sys_modify_ldt_skas
+ * is very similar to (and mostly stolen from) sys_modify_ldt
+ * for arch/i386/kernel/ldt.c
+ * The routines copied and modified in part are:
+ * - read_ldt
+ * - read_default_ldt
+ * - write_ldt
+ * - sys_modify_ldt_skas
+ */
+
+static int read_ldt(void __user * ptr, unsigned long bytecount)
+{
+	int i, err = 0;
+	unsigned long size;
+	uml_ldt_t * ldt = &current->mm->context.skas.ldt;
+
+	if(!ldt->entry_count)
+		goto out;
+	if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+	err = bytecount;
+
+	if(ptrace_ldt){
+		return read_ldt_from_host(ptr, bytecount);
+	}
+
+	down(&ldt->semaphore);
+	if(ldt->entry_count <= LDT_DIRECT_ENTRIES){
+		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
+		if(size > bytecount)
+			size = bytecount;
+		if(copy_to_user(ptr, ldt->entries, size))
+			err = -EFAULT;
+		bytecount -= size;
+		ptr += size;
+	}
+	else {
+		for(i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
+			 i++){
+			size = PAGE_SIZE;
+			if(size > bytecount)
+				size = bytecount;
+			if(copy_to_user(ptr, ldt->pages[i], size)){
+				err = -EFAULT;
+				break;
+			}
+			bytecount -= size;
+			ptr += size;
+		}
+	}
+	up(&ldt->semaphore);
+
+	if(bytecount == 0 || err == -EFAULT)
+		goto out;
+
+	if(clear_user(ptr, bytecount))
+		err = -EFAULT;
+
+out:
+	return err;
+}
+
+static int read_default_ldt(void __user * ptr, unsigned long bytecount)
+{
+	int err;
+
+	if(bytecount > 5*LDT_ENTRY_SIZE)
+		bytecount = 5*LDT_ENTRY_SIZE;
+
+	err = bytecount;
+	/* UML doesn't support lcall7 and lcall27.
+	 * So, we don't really have a default ldt, but emulate
+	 * an empty ldt of common host default ldt size.
+	 */
+	if(clear_user(ptr, bytecount))
+		err = -EFAULT;
+
+	return err;
+}
+
+static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
+{
+	uml_ldt_t * ldt = &current->mm->context.skas.ldt;
+	struct mm_id * mm_idp = &current->mm->context.skas.id;
+	int i, err;
+	struct user_desc ldt_info;
+	struct ldt_entry entry0, *ldt_p;
+	void *addr = NULL;
+
+	err = -EINVAL;
+	if(bytecount != sizeof(ldt_info))
+		goto out;
+	err = -EFAULT;
+	if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+		goto out;
+
+	err = -EINVAL;
+	if(ldt_info.entry_number >= LDT_ENTRIES)
+		goto out;
+	if(ldt_info.contents == 3){
+		if (func == 1)
+			goto out;
+		if (ldt_info.seg_not_present == 0)
+			goto out;
+	}
+
+        if(!ptrace_ldt)
+                down(&ldt->semaphore);
+
+	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
+	if(err)
+		goto out_unlock;
+        else if(ptrace_ldt) {
+	/* With PTRACE_LDT available, this is used as a flag only */
+                ldt->entry_count = 1;
+                goto out;
+        }
+
+	if(ldt_info.entry_number >= ldt->entry_count &&
+	   ldt_info.entry_number >= LDT_DIRECT_ENTRIES){
+		for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
+		    i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
+		    i++){
+			if(i == 0)
+				memcpy(&entry0, ldt->entries, sizeof(entry0));
+			ldt->pages[i] = (struct ldt_entry *)
+					__get_free_page(GFP_KERNEL|__GFP_ZERO);
+			if(!ldt->pages[i]){
+				err = -ENOMEM;
+				/* Undo the change in host */
+				memset(&ldt_info, 0, sizeof(ldt_info));
+				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
+				goto out_unlock;
+			}
+			if(i == 0) {
+				memcpy(ldt->pages[0], &entry0, sizeof(entry0));
+				memcpy(ldt->pages[0]+1, ldt->entries+1,
+				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
+			}
+			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
+		}
+	}
+	if(ldt->entry_count <= ldt_info.entry_number)
+		ldt->entry_count = ldt_info.entry_number + 1;
+
+	if(ldt->entry_count <= LDT_DIRECT_ENTRIES)
+		ldt_p = ldt->entries + ldt_info.entry_number;
+	else
+		ldt_p = ldt->pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
+			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
+
+	if(ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
+	   (func == 1 || LDT_empty(&ldt_info))){
+		ldt_p->a = 0;
+		ldt_p->b = 0;
+	}
+	else{
+		if (func == 1)
+			ldt_info.useable = 0;
+		ldt_p->a = LDT_entry_a(&ldt_info);
+		ldt_p->b = LDT_entry_b(&ldt_info);
+	}
+	err = 0;
+
+out_unlock:
+	up(&ldt->semaphore);
+out:
+	return err;
+}
+
+static long do_modify_ldt_skas(int func, void __user *ptr,
+			       unsigned long bytecount)
+{
+	int ret = -ENOSYS;
+
+	switch (func) {
+		case 0:
+			ret = read_ldt(ptr, bytecount);
+			break;
+		case 1:
+		case 0x11:
+			ret = write_ldt(ptr, bytecount, func);
+			break;
+		case 2:
+			ret = read_default_ldt(ptr, bytecount);
+			break;
+	}
+	return ret;
+}
+
+short dummy_list[9] = {0, -1};
+short * host_ldt_entries = NULL;
+
+void ldt_get_host_info(void)
+{
+	long ret;
+	struct ldt_entry * ldt;
+	int i, size, k, order;
+
+	host_ldt_entries = dummy_list+1;
+
+	for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++);
+
+	ldt = (struct ldt_entry *)
+	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
+	if(ldt == NULL) {
+		printk("ldt_get_host_info: couldn't allocate buffer for host ldt\n");
+		return;
+	}
+
+	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
+	if(ret < 0) {
+		printk("ldt_get_host_info: couldn't read host ldt\n");
+		goto out_free;
+	}
+	if(ret == 0) {
+		/* default_ldt is active, simply write an empty entry 0 */
+		host_ldt_entries = dummy_list;
+		goto out_free;
+	}
+
+	for(i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++){
+		if(ldt[i].a != 0 || ldt[i].b != 0)
+			size++;
+	}
+
+	if(size < sizeof(dummy_list)/sizeof(dummy_list[0])) {
+		host_ldt_entries = dummy_list;
+	}
+	else {
+		size = (size + 1) * sizeof(dummy_list[0]);
+		host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
+		if(host_ldt_entries == NULL) {
+			printk("ldt_get_host_info: couldn't allocate host ldt list\n");
+			goto out_free;
+		}
+	}
+
+	for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){
+		if(ldt[i].a != 0 || ldt[i].b != 0) {
+			host_ldt_entries[k++] = i;
+		}
+	}
+	host_ldt_entries[k] = -1;
+
+out_free:
+	free_pages((unsigned long)ldt, order);
+}
+
+long init_new_ldt(struct mmu_context_skas * new_mm,
+		  struct mmu_context_skas * from_mm)
+{
+	struct user_desc desc;
+	short * num_p;
+	int i;
+	long page, err=0;
+	void *addr = NULL;
+
+	memset(&desc, 0, sizeof(desc));
+
+	if(!ptrace_ldt)
+		init_MUTEX(&new_mm->ldt.semaphore);
+
+	if(!from_mm){
+		/*
+		 * We have to initialize a clean ldt.
+		 */
+		if(proc_mm) {
+			/*
+			 * If the new mm was created using proc_mm, host's
+			 * default-ldt currently is assigned, which normally
+			 * contains the call-gates for lcall7 and lcall27.
+			 * To remove these gates, we simply write an empty
+			 * entry as number 0 to the host.
+			 */
+			err = write_ldt_entry(&new_mm->id, 1, &desc,
+					      &addr, 1);
+		}
+		else{
+			/*
+			 * Now we try to retrieve info about the ldt, we
+			 * inherited from the host. All ldt-entries found
+			 * will be reset in the following loop
+			 */
+			if(host_ldt_entries == NULL)
+				ldt_get_host_info();
+			for(num_p=host_ldt_entries; *num_p != -1; num_p++){
+				desc.entry_number = *num_p;
+				err = write_ldt_entry(&new_mm->id, 1, &desc,
+						      &addr, *(num_p + 1) == -1);
+				if(err)
+					break;
+			}
+		}
+		new_mm->ldt.entry_count = 0;
+	}
+	else if (!ptrace_ldt) {
+		/* Our local LDT is used to supply the data for
+		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
+		 * i.e., we have to use the stub for modify_ldt, which
+		 * can't handle the big read buffer of up to 64kB.
+		 */
+		down(&from_mm->ldt.semaphore);
+		if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){
+			memcpy(new_mm->ldt.entries, from_mm->ldt.entries,
+			       sizeof(new_mm->ldt.entries));
+		}
+		else{
+			i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+			while(i-->0){
+				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
+				if (!page){
+					err = -ENOMEM;
+					break;
+				}
+				new_mm->ldt.pages[i] = (struct ldt_entry*)page;
+				memcpy(new_mm->ldt.pages[i],
+				       from_mm->ldt.pages[i], PAGE_SIZE);
+			}
+		}
+		new_mm->ldt.entry_count = from_mm->ldt.entry_count;
+		up(&from_mm->ldt.semaphore);
+	}
+
+	return err;
+}
+
+
+void free_ldt(struct mmu_context_skas * mm)
+{
+	int i;
+
+	if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){
+		i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+		while(i-- > 0){
+			free_page((long )mm->ldt.pages[i]);
+		}
+	}
+	mm->ldt.entry_count = 0;
+}
+#endif
+
+int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+{
+	return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
+	                        ptr, bytecount));
+}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 06c3633457..ea977df395 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -5,7 +5,7 @@
 #
 
 #XXX: why into lib-y?
-lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
+lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \
 	ptrace.o ptrace_user.o sigcontext.o signal.o stub.o \
 	stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o
 
@@ -14,7 +14,7 @@ obj-$(CONFIG_MODULES) += module.o um_module.o
 
 USER_OBJS := ptrace_user.o sigcontext.o
 
-SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
+SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \
 	thunk.S module.c
 
 include arch/um/scripts/Makefile.rules
@@ -23,6 +23,7 @@ bitops.c-dir = lib
 csum-copy.S-dir = lib
 csum-partial.c-dir = lib
 csum-wrappers.c-dir = lib
+ldt.c-dir = /arch/um/sys-i386
 memcpy.S-dir = lib
 thunk.S-dir = lib
 module.c-dir = kernel
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 3259a4db45..6acee5c4ad 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -28,81 +28,6 @@ asmlinkage long sys_uname64(struct new_utsname __user * name)
 	return err ? -EFAULT : 0;
 }
 
-#ifdef CONFIG_MODE_TT
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-
-long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
-{
-	/* XXX This should check VERIFY_WRITE depending on func, check this
-	 * in i386 as well.
-	 */
-	if (!access_ok(VERIFY_READ, ptr, bytecount))
-		return -EFAULT;
-	return(modify_ldt(func, ptr, bytecount));
-}
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-extern int userspace_pid[];
-
-#include "skas_ptrace.h"
-
-long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
-{
-	struct ptrace_ldt ldt;
-        void *buf;
-        int res, n;
-
-        buf = kmalloc(bytecount, GFP_KERNEL);
-        if(buf == NULL)
-                return(-ENOMEM);
-
-        res = 0;
-
-        switch(func){
-        case 1:
-        case 0x11:
-                res = copy_from_user(buf, ptr, bytecount);
-                break;
-        }
-
-        if(res != 0){
-                res = -EFAULT;
-                goto out;
-        }
-
-	ldt = ((struct ptrace_ldt) { .func	= func,
-				     .ptr	= buf,
-				     .bytecount = bytecount });
-#warning Need to look up userspace_pid by cpu
-	res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt);
-        if(res < 0)
-                goto out;
-
-        switch(func){
-        case 0:
-        case 2:
-                n = res;
-                res = copy_to_user(ptr, buf, n);
-                if(res != 0)
-                        res = -EFAULT;
-                else
-                        res = n;
-                break;
-        }
-
- out:
-        kfree(buf);
-        return(res);
-}
-#endif
-
-long sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
-{
-        return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func,
-                                ptr, bytecount));
-}
-
 #ifdef CONFIG_MODE_TT
 extern long arch_prctl(int code, unsigned long addr);
 
-- 
cgit v1.2.2


From ae17381608a11781a6a67e0ce51607f36780aac7 Mon Sep 17 00:00:00 2001
From: Jeff Dike <jdike@addtoit.com>
Date: Mon, 7 Nov 2005 00:58:57 -0800
Subject: [PATCH] uml: big memory fixes

A number of fixes to improve behavior when large physical memory sizes
are specified:

- libc files need -D_FILE_OFFSET_BITS=64 because there are unavoidable uses
  of non-64 interfaces in libc

- some %d need to be %u

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/Makefile            |  2 +-
 arch/um/include/mem_user.h  |  2 +-
 arch/um/include/os.h        |  2 +-
 arch/um/kernel/physmem.c    |  4 ++--
 arch/um/kernel/um_arch.c    | 10 +++++-----
 arch/um/os-Linux/mem.c      |  6 +++---
 arch/um/os-Linux/start_up.c |  2 +-
 7 files changed, 14 insertions(+), 14 deletions(-)

(limited to 'arch')

diff --git a/arch/um/Makefile b/arch/um/Makefile
index e1ffad2246..e55d32e903 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -60,7 +60,7 @@ AFLAGS += $(ARCH_INCLUDE)
 
 USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
 USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
-	$(MODE_INCLUDE)
+	$(MODE_INCLUDE) -D_FILE_OFFSET_BITS=64
 
 # -Derrno=kernel_errno - This turns all kernel references to errno into
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index 9fef4123a6..a1064c5823 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -57,7 +57,7 @@ extern int init_maps(unsigned long physmem, unsigned long iomem,
 		     unsigned long highmem);
 extern unsigned long get_vm(unsigned long len);
 extern void setup_physmem(unsigned long start, unsigned long usable,
-			  unsigned long len, unsigned long highmem);
+			  unsigned long len, unsigned long long highmem);
 extern void add_iomem(char *name, int fd, unsigned long size);
 extern unsigned long phys_offset(unsigned long phys);
 extern void unmap_physmem(void);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 112d7288f0..2cccfa5b8a 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -167,7 +167,7 @@ extern int can_do_skas(void);
 #endif
 
 /* mem.c */
-extern int create_mem_file(unsigned long len);
+extern int create_mem_file(unsigned long long len);
 
 /* process.c */
 extern unsigned long os_process_pc(int pid);
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index ea670fcc8a..f3b583a878 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -246,7 +246,7 @@ int is_remapped(void *virt)
 /* Changed during early boot */
 unsigned long high_physmem;
 
-extern unsigned long physmem_size;
+extern unsigned long long physmem_size;
 
 int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
 {
@@ -321,7 +321,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
 extern int __syscall_stub_start, __binary_start;
 
 void setup_physmem(unsigned long start, unsigned long reserve_end,
-		   unsigned long len, unsigned long highmem)
+		   unsigned long len, unsigned long long highmem)
 {
 	unsigned long reserve = reserve_end - start;
 	int pfn = PFN_UP(__pa(reserve_end));
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 93dc782dc1..142a949391 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -137,7 +137,7 @@ static char *argv1_end = NULL;
 
 /* Set in early boot */
 static int have_root __initdata = 0;
-long physmem_size = 32 * 1024 * 1024;
+long long physmem_size = 32 * 1024 * 1024;
 
 void set_cmdline(char *cmd)
 {
@@ -402,7 +402,7 @@ int linux_main(int argc, char **argv)
 #ifndef CONFIG_HIGHMEM
 		highmem = 0;
 		printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
-		       "to %ld bytes\n", physmem_size);
+		       "to %lu bytes\n", physmem_size);
 #endif
 	}
 
@@ -414,8 +414,8 @@ int linux_main(int argc, char **argv)
 
 	setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
 	if(init_maps(physmem_size, iomem_size, highmem)){
-		printf("Failed to allocate mem_map for %ld bytes of physical "
-		       "memory and %ld bytes of highmem\n", physmem_size,
+		printf("Failed to allocate mem_map for %lu bytes of physical "
+		       "memory and %lu bytes of highmem\n", physmem_size,
 		       highmem);
 		exit(1);
 	}
@@ -426,7 +426,7 @@ int linux_main(int argc, char **argv)
 	end_vm = start_vm + virtmem_size;
 
 	if(virtmem_size < physmem_size)
-		printf("Kernel virtual memory size shrunk to %ld bytes\n",
+		printf("Kernel virtual memory size shrunk to %lu bytes\n",
 		       virtmem_size);
 
   	uml_postsetup();
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 8e71edaaf8..9d7d69a523 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -88,7 +88,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink)
  * This proc is used in start_up.c
  * So it isn't 'static'.
  */
-int create_tmp_file(unsigned long len)
+int create_tmp_file(unsigned long long len)
 {
 	int fd, err;
 	char zero;
@@ -121,7 +121,7 @@ int create_tmp_file(unsigned long len)
 	return(fd);
 }
 
-static int create_anon_file(unsigned long len)
+static int create_anon_file(unsigned long long len)
 {
 	void *addr;
 	int fd;
@@ -144,7 +144,7 @@ static int create_anon_file(unsigned long len)
 
 extern int have_devanon;
 
-int create_mem_file(unsigned long len)
+int create_mem_file(unsigned long long len)
 {
 	int err, fd;
 
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 553a09c7d0..37517d49c4 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -296,7 +296,7 @@ static void __init check_ptrace(void)
 	check_sysemu();
 }
 
-extern int create_tmp_file(unsigned long len);
+extern int create_tmp_file(unsigned long long len);
 
 static void check_tmpexec(void)
 {
-- 
cgit v1.2.2


From 77cc0db46e5d04b476e1984134892edb86cda8e6 Mon Sep 17 00:00:00 2001
From: Jeff Dike <jdike@addtoit.com>
Date: Mon, 7 Nov 2005 00:58:57 -0800
Subject: [PATCH] uml: make tt mode-dependent options depend on MODE_TT

This makes some of the tt-specific options actually depend on CONFIG_MODE_TT.

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/Kconfig | 46 ++++++++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 22 deletions(-)

(limited to 'arch')

diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index cd06ed7d84..3b5f47c469 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -65,6 +65,30 @@ config STATIC_LINK
 	chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
 	here.
 
+config HOST_2G_2G
+	bool "2G/2G host address space split"
+	default n
+	depends on MODE_TT
+	help
+	This is needed when the host on which you run has a 2G/2G memory
+	split, instead of the customary 3G/1G.
+
+	Note that to enable such a host
+	configuration, which makes sense only in some cases, you need special
+	host patches.
+
+	So, if you do not know what to do here, say 'N'.
+
+config KERNEL_HALF_GIGS
+	int "Kernel address space size (in .5G units)"
+	default "1"
+	depends on MODE_TT
+	help
+        This determines the amount of address space that UML will allocate for
+        its own, measured in half Gigabyte units.  The default is 1.
+        Change this only if you need to boot UML with an unusually large amount
+        of physical memory.
+
 config MODE_SKAS
 	bool "Separate Kernel Address Space support"
 	default y
@@ -182,19 +206,6 @@ config MAGIC_SYSRQ
 	The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
 	unless you really know what this hack does.
 
-config HOST_2G_2G
-	bool "2G/2G host address space split"
-	default n
-	help
-	This is needed when the host on which you run has a 2G/2G memory
-	split, instead of the customary 3G/1G.
-
-	Note that to enable such a host
-	configuration, which makes sense only in some cases, you need special
-	host patches.
-
-	So, if you do not know what to do here, say 'N'.
-
 config SMP
 	bool "Symmetric multi-processing support (EXPERIMENTAL)"
 	default n
@@ -241,15 +252,6 @@ config NEST_LEVEL
         set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS.
         Only change this if you are running nested UMLs.
 
-config KERNEL_HALF_GIGS
-	int "Kernel address space size (in .5G units)"
-	default "1"
-	help
-        This determines the amount of address space that UML will allocate for
-        its own, measured in half Gigabyte units.  The default is 1.
-        Change this only if you need to boot UML with an unusually large amount
-        of physical memory.
-
 config HIGHMEM
 	bool "Highmem support"
 	depends on !64BIT
-- 
cgit v1.2.2


From 353f8d1cd5b8540c1591f00a5cbd3aeca699cfcf Mon Sep 17 00:00:00 2001
From: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Date: Mon, 7 Nov 2005 00:58:58 -0800
Subject: [PATCH] uml: fix hardcoded ZONE_* constants in zone setup

Remove usage of hardcoded constants in paging_init().

By chance I spotted a bug in zones_setup involving a change to ZONE_*
constants, due to the ZONE_DMA32 patch from Andi Kleen (which is in -mm).
So, possibly, instead of zones_size[2] you will find zones_size[3] in the
code, but that change is wrong and this patch is still correct.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/kernel/mem.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 462cc9d653..fa4f915be5 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -234,8 +234,8 @@ void paging_init(void)
 	empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
 	for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) 
 		zones_size[i] = 0;
-	zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
-	zones_size[2] = highmem >> PAGE_SHIFT;
+	zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
+	zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
 	free_area_init(zones_size);
 
 	/*
-- 
cgit v1.2.2


From 26d89d1eef38473d0da64b7137952c56d0b6d13f Mon Sep 17 00:00:00 2001
From: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Date: Mon, 7 Nov 2005 00:58:59 -0800
Subject: [PATCH] uml: build host-binaries with the native host arch again

This patch reverts back the changes to HOSTCFLAGS and HOSTLDFLAGS

When we were building complete binaries to get constants (such as ptrace
register layout on stack) from host userspace headers, we needed to make the
arch for building HOST binaries match our one: i.e.  on a 64bit system
compiling 32bit binaries, we compile 32-bit hostprogs and need, say, 32-bit
ncurses.  Now we can revert that - that avoids problem with, say, menuconfig
and ncurses, on a system which can't compile well 32-bit programs.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/Makefile-i386 | 2 --
 1 file changed, 2 deletions(-)

(limited to 'arch')

diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index aef7c50f8e..1f7dcb064a 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -17,8 +17,6 @@ ifeq ("$(origin SUBARCH)", "command line")
 ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
 CFLAGS			+= $(call cc-option,-m32)
 USER_CFLAGS		+= $(call cc-option,-m32)
-HOSTCFLAGS		+= $(call cc-option,-m32)
-HOSTLDFLAGS		+= $(call cc-option,-m32)
 AFLAGS			+= $(call cc-option,-m32)
 LINK-y			+= $(call cc-option,-m32)
 UML_OBJCOPYFLAGS	+= -F $(ELF_FORMAT)
-- 
cgit v1.2.2


From e1c3ad96f662bf1071a71feffadfe0f7604f14e2 Mon Sep 17 00:00:00 2001
From: Heiko Carstens <heiko.carstens@de.ibm.com>
Date: Mon, 7 Nov 2005 00:59:02 -0800
Subject: [PATCH] s390: signal delivery

Always create all signal frames for pending signals before returning to
userspace, not just a single one.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/s390/kernel/entry.S   | 4 ++--
 arch/s390/kernel/entry64.S | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'arch')

diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 9b30f4cf32..27b07730b7 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -288,7 +288,7 @@ sysc_sigpending:
 	bo	BASED(sysc_restart)
 	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
 	bo	BASED(sysc_singlestep)
-	b	BASED(sysc_leave)      # out of here, do NOT recheck
+	b	BASED(sysc_work_loop)
 
 #
 # _TIF_RESTART_SVC is set, set up registers and restart svc
@@ -645,7 +645,7 @@ io_sigpending:
         l       %r1,BASED(.Ldo_signal)
 	basr    %r14,%r1	       # call do_signal
         stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
-	b	BASED(io_leave)        # out of here, do NOT recheck
+	b	BASED(io_work_loop)
 
 /*
  * External interrupt handler routine
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 7b9b4a2ba1..4eb71ffcf4 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -283,7 +283,7 @@ sysc_sigpending:
 	jo	sysc_restart
 	tm	__TI_flags+7(%r9),_TIF_SINGLE_STEP
 	jo	sysc_singlestep
-	j	sysc_leave        # out of here, do NOT recheck
+	j	sysc_work_loop
 
 #
 # _TIF_RESTART_SVC is set, set up registers and restart svc
@@ -684,7 +684,7 @@ io_sigpending:
 	slgr    %r3,%r3			# clear *oldset
 	brasl	%r14,do_signal		# call do_signal
 	stnsm   __SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
-	j	sysc_leave		# out of here, do NOT recheck
+	j	io_work_loop
 
 /*
  * External interrupt handler routine
-- 
cgit v1.2.2


From 1b44e98d7d0754bbcf0222baf179f5e2e3dbea7b Mon Sep 17 00:00:00 2001
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
Date: Mon, 7 Nov 2005 00:59:02 -0800
Subject: [PATCH] s390: stop_hz_timer vs. xtime updates

The calculation of the value return by next_timer_interrupt from jiffies to
jiffies_64 is racy against xtime updates.  We need to protect the calculation
with read_seqbegin/read_seqretry.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/s390/kernel/time.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

(limited to 'arch')

diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9a1d95894f..c36353e8c1 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -237,6 +237,8 @@ int sysctl_hz_timer = 1;
  */
 static inline void stop_hz_timer(void)
 {
+	unsigned long flags;
+	unsigned long seq, next;
 	__u64 timer, todval;
 
 	if (sysctl_hz_timer != 0)
@@ -257,7 +259,11 @@ static inline void stop_hz_timer(void)
 	 * This cpu is going really idle. Set up the clock comparator
 	 * for the next event.
 	 */
-	timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
+	next = next_timer_interrupt();
+	do {
+		seq = read_seqbegin_irqsave(&xtime_lock, flags);
+		timer = (__u64)(next - jiffies) + jiffies_64;
+	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 	todval = -1ULL;
 	/* Be careful about overflows. */
 	if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
-- 
cgit v1.2.2


From 9b4554aa21270f5b6fa19a9dd2285f16e11f15f1 Mon Sep 17 00:00:00 2001
From: Heiko Carstens <heiko.carstens@de.ibm.com>
Date: Mon, 7 Nov 2005 00:59:04 -0800
Subject: [PATCH] s390: memory query wait psw

Don't switch back to 24 bit addressing mode when waiting for an external
interrupt and set the correct bit in wait PSW (external mask instead of I/O
mask).

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/s390/kernel/head.S   | 3 +--
 arch/s390/kernel/head64.S | 5 ++---
 2 files changed, 3 insertions(+), 5 deletions(-)

(limited to 'arch')

diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 039354d723..4ca0293321 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -572,8 +572,7 @@ startup:basr  %r13,0                     # get base
 .Lcr:
 	.long 0x00			# place holder for cr0
 .Lwaitsclp:
-	.long 0x020A0000
-	.long .Lsclph
+	.long 0x010a0000,0x80000000 + .Lsclph
 .Lrcp:
 	.int 0x00120001			# Read SCP forced code
 .Lrcp2:
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 193aafa72f..d9be8f96f2 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -530,7 +530,7 @@ startup:basr  %r13,0                     # get base
 	be    .Lfchunk-.LPG1(%r13)	# leave
 	chi   %r1,2
 	be    .Lservicecall-.LPG1(%r13)
-	lpsw  .Lwaitsclp-.LPG1(%r13)
+	lpswe .Lwaitsclp-.LPG1(%r13)
 .Lsclph:
 	lh    %r1,.Lsccbr-PARMAREA(%r4)
 	chi   %r1,0x10			# 0x0010 is the sucess code
@@ -567,8 +567,7 @@ startup:basr  %r13,0                     # get base
 .Lcr:
 	.quad 0x00  # place holder for cr0
 .Lwaitsclp:
-	.long 0x020A0000
-	.quad .Lsclph
+	.quad  0x0102000180000000,.Lsclph
 .Lrcp:
 	.int 0x00120001 # Read SCP forced code
 .Lrcp2:
-- 
cgit v1.2.2


From d4b68996785326a67e9842219ab69984243ec658 Mon Sep 17 00:00:00 2001
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
Date: Mon, 7 Nov 2005 00:59:06 -0800
Subject: [PATCH] s390: remove pagex support

Remove pagex pseudo page fault code.  It does not work together with the
system call speedup that makes the complete system call path enabled for
interrupts.  To make pagex and the syscall speedup code work together we would
have to add code to the program check handler to do a critical section cleanup
like the asynchronous interrupt code.  This would make program checks slower.
Not what we want.

Newer versions of z/VM have the improved pfault pseudo page fault interface.
This replaces the old pagex interface and does not have the problem.  So its
better to just rip out the pagex code.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/s390/kernel/traps.c |  29 ++----------
 arch/s390/mm/fault.c     | 113 +----------------------------------------------
 2 files changed, 5 insertions(+), 137 deletions(-)

(limited to 'arch')

diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 6b8703ec2a..c5bd36fae5 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -57,7 +57,6 @@ int sysctl_userprocess_debug = 0;
 
 extern pgm_check_handler_t do_protection_exception;
 extern pgm_check_handler_t do_dat_exception;
-extern pgm_check_handler_t do_pseudo_page_fault;
 #ifdef CONFIG_PFAULT
 extern int pfault_init(void);
 extern void pfault_fini(void);
@@ -676,20 +675,6 @@ asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
 	panic("Corrupt kernel stack, can't continue.");
 }
 
-#ifndef CONFIG_ARCH_S390X
-static int
-pagex_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
-	if (MACHINE_IS_VM)
-		cpcmd("SET PAGEX OFF", NULL, 0, NULL);
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block pagex_reboot_notifier = {
-	.notifier_call = &pagex_reboot_event,
-};
-#endif
-
 /* init is done in lowcore.S and head.S */
 
 void __init trap_init(void)
@@ -717,9 +702,7 @@ void __init trap_init(void)
         pgm_check_table[0x11] = &do_dat_exception;
         pgm_check_table[0x12] = &translation_exception;
         pgm_check_table[0x13] = &special_op_exception;
-#ifndef CONFIG_ARCH_S390X
- 	pgm_check_table[0x14] = &do_pseudo_page_fault;
-#else /* CONFIG_ARCH_S390X */
+#ifdef CONFIG_ARCH_S390X
         pgm_check_table[0x38] = &do_dat_exception;
 	pgm_check_table[0x39] = &do_dat_exception;
 	pgm_check_table[0x3A] = &do_dat_exception;
@@ -731,12 +714,10 @@ void __init trap_init(void)
 	pgm_check_table[0x40] = &do_monitor_call;
 
 	if (MACHINE_IS_VM) {
+#ifdef CONFIG_PFAULT
 		/*
-		 * First try to get pfault pseudo page faults going.
-		 * If this isn't available turn on pagex page faults.
+		 * Try to get pfault pseudo page faults going.
 		 */
-#ifdef CONFIG_PFAULT
-		/* request the 0x2603 external interrupt */
 		if (register_early_external_interrupt(0x2603, pfault_interrupt,
 						      &ext_int_pfault) != 0)
 			panic("Couldn't request external interrupt 0x2603");
@@ -747,10 +728,6 @@ void __init trap_init(void)
 		/* Tough luck, no pfault. */
 		unregister_early_external_interrupt(0x2603, pfault_interrupt,
 						    &ext_int_pfault);
-#endif
-#ifndef CONFIG_ARCH_S390X
-		register_reboot_notifier(&pagex_reboot_notifier);
-		cpcmd("SET PAGEX ON", NULL, 0, NULL);
 #endif
 	}
 }
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 856a971759..64e32da777 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -352,115 +352,6 @@ void do_dat_exception(struct pt_regs *regs, unsigned long error_code)
 	do_exception(regs, error_code & 0xff, 0);
 }
 
-#ifndef CONFIG_ARCH_S390X
-
-typedef struct _pseudo_wait_t {
-       struct _pseudo_wait_t *next;
-       wait_queue_head_t queue;
-       unsigned long address;
-       int resolved;
-} pseudo_wait_t;
-
-static pseudo_wait_t *pseudo_lock_queue = NULL;
-static spinlock_t pseudo_wait_spinlock; /* spinlock to protect lock queue */
-
-/*
- * This routine handles 'pagex' pseudo page faults.
- */
-asmlinkage void
-do_pseudo_page_fault(struct pt_regs *regs, unsigned long error_code)
-{
-        pseudo_wait_t wait_struct;
-        pseudo_wait_t *ptr, *last, *next;
-        unsigned long address;
-
-        /*
-         * get the failing address
-         * more specific the segment and page table portion of
-         * the address
-         */
-        address = S390_lowcore.trans_exc_code & 0xfffff000;
-
-        if (address & 0x80000000) {
-                /* high bit set -> a page has been swapped in by VM */
-                address &= 0x7fffffff;
-                spin_lock(&pseudo_wait_spinlock);
-                last = NULL;
-                ptr = pseudo_lock_queue;
-                while (ptr != NULL) {
-                        next = ptr->next;
-                        if (address == ptr->address) {
-				 /*
-                                 * This is one of the processes waiting
-                                 * for the page. Unchain from the queue.
-                                 * There can be more than one process
-                                 * waiting for the same page. VM presents
-                                 * an initial and a completion interrupt for
-                                 * every process that tries to access a 
-                                 * page swapped out by VM. 
-                                 */
-                                if (last == NULL)
-                                        pseudo_lock_queue = next;
-                                else
-                                        last->next = next;
-                                /* now wake up the process */
-                                ptr->resolved = 1;
-                                wake_up(&ptr->queue);
-                        } else
-                                last = ptr;
-                        ptr = next;
-                }
-                spin_unlock(&pseudo_wait_spinlock);
-        } else {
-                /* Pseudo page faults in kernel mode is a bad idea */
-                if (!(regs->psw.mask & PSW_MASK_PSTATE)) {
-                        /*
-			 * VM presents pseudo page faults if the interrupted
-			 * state was not disabled for interrupts. So we can
-			 * get pseudo page fault interrupts while running
-			 * in kernel mode. We simply access the page here
-			 * while we are running disabled. VM will then swap
-			 * in the page synchronously.
-                         */
-                         if (check_user_space(regs, error_code) == 0)
-                                 /* dereference a virtual kernel address */
-                                 __asm__ __volatile__ (
-                                         "  ic 0,0(%0)"
-                                         : : "a" (address) : "0");
-                         else
-                                 /* dereference a virtual user address */
-                                 __asm__ __volatile__ (
-                                         "  la   2,0(%0)\n"
-                                         "  sacf 512\n"
-                                         "  ic   2,0(2)\n"
-					 "0:sacf 0\n"
-					 ".section __ex_table,\"a\"\n"
-					 "  .align 4\n"
-					 "  .long  0b,0b\n"
-					 ".previous"
-                                         : : "a" (address) : "2" );
-
-                        return;
-                }
-		/* initialize and add element to pseudo_lock_queue */
-                init_waitqueue_head (&wait_struct.queue);
-                wait_struct.address = address;
-                wait_struct.resolved = 0;
-                spin_lock(&pseudo_wait_spinlock);
-                wait_struct.next = pseudo_lock_queue;
-                pseudo_lock_queue = &wait_struct;
-                spin_unlock(&pseudo_wait_spinlock);
-		/*
-		 * The instruction that caused the program check will
-		 * be repeated. Don't signal single step via SIGTRAP.
-		 */
-		clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
-                /* go to sleep */
-                wait_event(wait_struct.queue, wait_struct.resolved);
-        }
-}
-#endif /* CONFIG_ARCH_S390X */
-
 #ifdef CONFIG_PFAULT 
 /*
  * 'pfault' pseudo page faults routines.
@@ -508,7 +399,7 @@ int pfault_init(void)
 		"   .quad  0b,1b\n"
 #endif /* CONFIG_ARCH_S390X */
 		".previous"
-                : "=d" (rc) : "a" (&refbk) : "cc" );
+                : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" );
         __ctl_set_bit(0, 9);
         return rc;
 }
@@ -532,7 +423,7 @@ void pfault_fini(void)
 		"   .quad  0b,0b\n"
 #endif /* CONFIG_ARCH_S390X */
 		".previous"
-		: : "a" (&refbk) : "cc" );
+		: : "a" (&refbk), "m" (refbk) : "cc" );
 }
 
 asmlinkage void
-- 
cgit v1.2.2


From 0ad775dbba12de3b7d25f586efe81ad995ca75a7 Mon Sep 17 00:00:00 2001
From: Heiko Carstens <heiko.carstens@de.ibm.com>
Date: Mon, 7 Nov 2005 00:59:12 -0800
Subject: [PATCH] s390: merge common parts of head.S and head64.S

Merge common parts of head.S and head64.S into head.S and move architecture
specific parts to head31.S and head64.S respectively.  Saves us ~500 lines
of duplicated assembly code.

Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/s390/Makefile        |   4 +-
 arch/s390/kernel/Makefile |   4 +-
 arch/s390/kernel/head.S   | 382 +++-----------------------------
 arch/s390/kernel/head31.S | 336 +++++++++++++++++++++++++++++
 arch/s390/kernel/head64.S | 538 +---------------------------------------------
 5 files changed, 381 insertions(+), 883 deletions(-)
 create mode 100644 arch/s390/kernel/head31.S

(limited to 'arch')

diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 98db30481d..73a09a6ee6 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -76,9 +76,7 @@ AFLAGS		+= $(aflags-y)
 OBJCOPYFLAGS	:= -O binary
 LDFLAGS_vmlinux := -e start
 
-head-$(CONFIG_ARCH_S390_31)	+= arch/$(ARCH)/kernel/head.o
-head-$(CONFIG_ARCH_S390X)	+= arch/$(ARCH)/kernel/head64.o
-head-y				+= arch/$(ARCH)/kernel/init_task.o
+head-y		:= arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
 
 core-y		+= arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \
 		   arch/$(ARCH)/appldata/
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 8584dd8232..7434c32bc6 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -8,9 +8,7 @@ obj-y	:=  bitmap.o traps.o time.o process.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
             semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o
 
-extra-$(CONFIG_ARCH_S390_31)	+= head.o 
-extra-$(CONFIG_ARCH_S390X)	+= head64.o 
-extra-y				+= init_task.o vmlinux.lds
+extra-y				+= head.o init_task.o vmlinux.lds
 
 obj-$(CONFIG_MODULES)		+= s390_ksyms.o module.o
 obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 4ca0293321..d31a97c89f 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -1,11 +1,12 @@
 /*
  *  arch/s390/kernel/head.S
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Hartmut Penner (hp@de.ibm.com),
- *               Martin Schwidefsky (schwidefsky@de.ibm.com),
- *               Rob van der Heij (rvdhei@iae.nl)
+ * (C) Copyright IBM Corp. 1999, 2005
+ *
+ *    Author(s): Hartmut Penner <hp@de.ibm.com>
+ *		 Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *		 Rob van der Heij <rvdhei@iae.nl>
+ *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  *
  * There are 5 different IPL methods
  *  1) load the image directly into ram at address 0 and do an PSW restart
@@ -19,12 +20,7 @@
  *  5) direct call of start by the SALIPL loader
  *  We use the cpuid to distinguish between VM and native ipl
  *  params for kernel are pushed to 0x10400 (see setup.h)
-
-    Changes: 
-    Okt 25 2000 <rvdheij@iae.nl>
-	added code to skip HDR and EOF to allow SL tape IPL (5 retries)
-	changed first CCW from rewind to backspace block
-
+ *
  */
 
 #include <linux/config.h>
@@ -34,6 +30,12 @@
 #include <asm/thread_info.h>
 #include <asm/page.h>
 
+#ifdef CONFIG_ARCH_S390X
+#define ARCH_OFFSET	4
+#else
+#define ARCH_OFFSET	0
+#endif
+
 #ifndef CONFIG_IPL
         .org   0
         .long  0x00080000,0x80000000+startup   # Just a restart PSW
@@ -201,7 +203,7 @@
         ssch  0(%r3)                           # load chunk of 1600 bytes
         bnz   .Llderr
 .Lwait4irq:
-        mvc   __LC_IO_NEW_PSW(8),.Lnewpsw      # set up IO interrupt psw
+        mvc   0x78(8),.Lnewpsw                 # set up IO interrupt psw
         lpsw  .Lwaitpsw              
 .Lioint:
         c     %r1,0xb8                         # compare subchannel number
@@ -265,13 +267,13 @@ iplstart:
         la    %r2,IPL_BS                       # load start address
         bas   %r14,.Lloader                    # load rest of ipl image
         l     %r12,.Lparm                      # pointer to parameter area
-        st    %r1,IPL_DEVICE-PARMAREA(%r12)    # store ipl device number
+        st    %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
 
 #
 # load parameter file from ipl device
 #
 .Lagain1:
- 	l     %r2,INITRD_START-PARMAREA(%r12)  # use ramdisk location as temp
+ 	l     %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # ramdisk loc. is temp
         bas   %r14,.Lloader                    # load parameter file
         ltr   %r2,%r2                          # got anything ?
         bz    .Lnopf
@@ -279,7 +281,7 @@ iplstart:
 	bnh   .Lnotrunc
 	la    %r2,895
 .Lnotrunc:
-	l     %r4,INITRD_START-PARMAREA(%r12)
+	l     %r4,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
 	clc   0(3,%r4),.L_hdr		       # if it is HDRx
 	bz    .Lagain1			       # skip dataset header
 	clc   0(3,%r4),.L_eof		       # if it is EOFx
@@ -322,14 +324,14 @@ iplstart:
 # load ramdisk from ipl device
 #	
 .Lagain2:
- 	l     %r2,INITRD_START-PARMAREA(%r12)  # load adr. of ramdisk
+ 	l     %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # addr of ramdisk
         bas   %r14,.Lloader                    # load ramdisk
- 	st    %r2,INITRD_SIZE-PARMAREA(%r12)   # store size of ramdisk
+ 	st    %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk
         ltr   %r2,%r2
         bnz   .Lrdcont
-        st    %r2,INITRD_START-PARMAREA(%r12)  # no ramdisk found, null it
+        st    %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
 .Lrdcont:
-	l     %r2,INITRD_START-PARMAREA(%r12)
+	l     %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
 
 	clc   0(3,%r2),.L_hdr		       # skip HDRx and EOFx 
 	bz    .Lagain2
@@ -432,10 +434,10 @@ start:
 	la    %r3,1(%r3)
 .done:
         l     %r1,.memsize
-	st    %r3,0(%r1)
+	st    %r3,ARCH_OFFSET(%r1)
 	slr   %r0,%r0
-	st    %r0,INITRD_SIZE-PARMAREA(%r11)
-	st    %r0,INITRD_START-PARMAREA(%r11)
+	st    %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
+	st    %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
 	j     startup                   # continue with startup
 .tbl:	.long _ebcasc			# translate table
 .cmd:	.long COMMAND_LINE		# address of command line buffer
@@ -478,303 +480,23 @@ start:
 	.byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 
 	.byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
 
-#
-# startup-code at 0x10000, running in real mode
-# this is called either by the ipl loader or directly by PSW restart
-# or linload or SALIPL
-#
-        .org  0x10000
-startup:basr  %r13,0                     # get base
-.LPG1:	l     %r1, .Lget_ipl_device_addr-.LPG1(%r13)
-	basr  %r14, %r1
-	lctl  %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
-	la    %r12,_pstart-.LPG1(%r13)   # pointer to parameter area
-					 # move IPL device to lowcore
-        mvc   __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
-	
-#
-# clear bss memory
-#
-        l     %r2,.Lbss_bgn-.LPG1(%r13) # start of bss
-        l     %r3,.Lbss_end-.LPG1(%r13) # end of bss
-        sr    %r3,%r2                   # length of bss
-        sr    %r4,%r4                   #
-        sr    %r5,%r5                   # set src,length and pad to zero
-        sr    %r0,%r0                   #
-        mvcle %r2,%r4,0                 # clear mem
-        jo    .-4                       # branch back, if not finish
-
-	l     %r2,.Lrcp-.LPG1(%r13)	# Read SCP forced command word
-.Lservicecall:
-	stosm .Lpmask-.LPG1(%r13),0x01	# authorize ext interrupts
-
-	stctl %r0, %r0,.Lcr-.LPG1(%r13)	# get cr0
-	la    %r1,0x200			# set bit 22
-	o     %r1,.Lcr-.LPG1(%r13)	# or old cr0 with r1
-	st    %r1,.Lcr-.LPG1(%r13)
-	lctl  %r0, %r0,.Lcr-.LPG1(%r13)	# load modified cr0
-
-	mvc   __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
-	la    %r1, .Lsclph-.LPG1(%r13)
-	a     %r1,__LC_EXT_NEW_PSW+4	# set handler
-	st    %r1,__LC_EXT_NEW_PSW+4
-
-	la    %r4,_pstart-.LPG1(%r13)	# %r4 is our index for sccb stuff
-	la    %r1, .Lsccb-PARMAREA(%r4)	# our sccb
-	.insn rre,0xb2200000,%r2,%r1	# service call
-	ipm   %r1
-	srl   %r1,28			# get cc code
-	xr    %r3, %r3
-	chi   %r1,3
-	be    .Lfchunk-.LPG1(%r13)	# leave
-	chi   %r1,2
-	be    .Lservicecall-.LPG1(%r13)
-	lpsw  .Lwaitsclp-.LPG1(%r13)
-.Lsclph:
-	lh    %r1,.Lsccbr-PARMAREA(%r4)
-	chi   %r1,0x10			# 0x0010 is the sucess code
-	je    .Lprocsccb		# let's process the sccb
-	chi   %r1,0x1f0
-	bne   .Lfchunk-.LPG1(%r13)	# unhandled error code
-	c     %r2, .Lrcp-.LPG1(%r13)	# Did we try Read SCP forced
-	bne   .Lfchunk-.LPG1(%r13)	# if no, give up
-	l     %r2, .Lrcp2-.LPG1(%r13)	# try with Read SCP
-	b     .Lservicecall-.LPG1(%r13)
-.Lprocsccb:
-	lhi   %r1,0
-	icm   %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
-	jnz   .Lscnd
-	lhi   %r1,0x800			# otherwise report 2GB
-.Lscnd:
-	lhi   %r3,0x800			# limit reported memory size to 2GB
-	cr    %r1,%r3
-	jl    .Lno2gb
-	lr    %r1,%r3
-.Lno2gb:
-	xr    %r3,%r3			# same logic
-	ic    %r3,.Lscpa1-PARMAREA(%r4)
-	chi   %r3,0x00
-	jne   .Lcompmem
-	l     %r3,.Lscpa2-PARMAREA(%r13)
-.Lcompmem:
-	mr    %r2,%r1			# mem in MB on 128-bit
-	l     %r1,.Lonemb-.LPG1(%r13)
-	mr    %r2,%r1			# mem size in bytes in %r3
-	b     .Lfchunk-.LPG1(%r13)
-
-	.align 4
-.Lget_ipl_device_addr:
-	.long .Lget_ipl_device
-.Lpmask:
-	.byte 0
-.align 8
-.Lpcext:.long  0x00080000,0x80000000
-.Lcr:
-	.long 0x00			# place holder for cr0
-.Lwaitsclp:
-	.long 0x010a0000,0x80000000 + .Lsclph
-.Lrcp:
-	.int 0x00120001			# Read SCP forced code
-.Lrcp2:
-	.int 0x00020001			# Read SCP code
-.Lonemb:
-	.int 0x100000
-.Lfchunk:
-
-#
-# find memory chunks.
-#
-	lr    %r9,%r3			 # end of mem
-	mvc   __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
-	la    %r1,1                      # test in increments of 128KB
-	sll   %r1,17
-	l     %r3,.Lmchunk-.LPG1(%r13)   # get pointer to memory_chunk array
-	slr   %r4,%r4                    # set start of chunk to zero
-	slr   %r5,%r5                    # set end of chunk to zero
-	slr   %r6,%r6			 # set access code to zero
-	la    %r10, MEMORY_CHUNKS	 # number of chunks
-.Lloop:
-	tprot 0(%r5),0			 # test protection of first byte
-	ipm   %r7
-	srl   %r7,28
-	clr   %r6,%r7			 # compare cc with last access code
-	be    .Lsame-.LPG1(%r13)
-	b     .Lchkmem-.LPG1(%r13)
-.Lsame:
-	ar    %r5,%r1			 # add 128KB to end of chunk
-	bno   .Lloop-.LPG1(%r13)	 # r1 < 0x80000000 -> loop
-.Lchkmem:				 # > 2GB or tprot got a program check
-	clr   %r4,%r5			 # chunk size > 0?
-	be    .Lchkloop-.LPG1(%r13)
-	st    %r4,0(%r3)		 # store start address of chunk
-	lr    %r0,%r5
-	slr   %r0,%r4
-	st    %r0,4(%r3)		 # store size of chunk
-	st    %r6,8(%r3)		 # store type of chunk
-	la    %r3,12(%r3)
-	l     %r4,.Lmemsize-.LPG1(%r13)	 # address of variable memory_size
-	st    %r5,0(%r4)		 # store last end to memory size
-	ahi   %r10,-1			 # update chunk number
-.Lchkloop:
-	lr    %r6,%r7			 # set access code to last cc
-	# we got an exception or we're starting a new
-	# chunk , we must check if we should
-	# still try to find valid memory (if we detected
-	# the amount of available storage), and if we
-	# have chunks left
-	xr    %r0,%r0
-	clr   %r0,%r9			 # did we detect memory?
-	je    .Ldonemem			 # if not, leave
-	chi   %r10,0			 # do we have chunks left?
-	je    .Ldonemem
-	alr   %r5,%r1			 # add 128KB to end of chunk
-	lr    %r4,%r5			 # potential new chunk
-	clr    %r5,%r9			 # should we go on?
-	jl     .Lloop
-.Ldonemem:		
-        l      %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
-#
-# find out if we are running under VM
-#
-        stidp  __LC_CPUID               # store cpuid
-	tm     __LC_CPUID,0xff          # running under VM ?
-	bno    .Lnovm-.LPG1(%r13)
-        oi     3(%r12),1                # set VM flag
-.Lnovm:
-        lh     %r0,__LC_CPUID+4         # get cpu version
-        chi    %r0,0x7490               # running on a P/390 ?
-        bne    .Lnop390-.LPG1(%r13)
-        oi     3(%r12),4                # set P/390 flag
-.Lnop390:
-
-#
-# find out if we have an IEEE fpu
-#
-        mvc    __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
-	efpc   %r0,0                    # test IEEE extract fpc instruction
-        oi     3(%r12),2                # set IEEE fpu flag
-.Lchkfpu:
-
-#
-# find out if we have the CSP instruction
-#
-       mvc    __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13)
-       la     %r0,0
-       lr     %r1,%r0
-       la     %r2,4
-       csp    %r0,%r2                   # Test CSP instruction
-       oi     3(%r12),8                 # set CSP flag
-.Lchkcsp:
-
-#
-# find out if we have the MVPG instruction
-#
-       mvc    __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13)
-       sr     %r0,%r0
-       la     %r1,0
-       la     %r2,0
-       mvpg   %r1,%r2                   # Test CSP instruction
-       oi     3(%r12),16                # set MVPG flag
-.Lchkmvpg:
-
-#
-# find out if we have the IDTE instruction
-#
-	mvc	__LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13)
-	.long	0xb2b10000		# store facility list
-	tm	0xc8,0x08		# check bit for clearing-by-ASCE
-	bno	.Lchkidte-.LPG1(%r13)
-	lhi	%r1,2094
-	lhi	%r2,0
-	.long	0xb98e2001
-	oi	3(%r12),0x80		# set IDTE flag
-.Lchkidte:
-
-        lpsw  .Lentry-.LPG1(13)         # jump to _stext in primary-space,
-                                        # virtual and never return ...
-        .align 8
-.Lentry:.long  0x00080000,0x80000000 + _stext
-.Lctl:  .long  0x04b50002               # cr0: various things
-        .long  0                        # cr1: primary space segment table
-        .long  .Lduct                   # cr2: dispatchable unit control table
-        .long  0                        # cr3: instruction authorization
-        .long  0                        # cr4: instruction authorization
-        .long  0xffffffff               # cr5: primary-aste origin
-        .long  0                        # cr6:  I/O interrupts
-        .long  0                        # cr7:  secondary space segment table
-        .long  0                        # cr8:  access registers translation
-        .long  0                        # cr9:  tracing off
-        .long  0                        # cr10: tracing off
-        .long  0                        # cr11: tracing off
-        .long  0                        # cr12: tracing off
-        .long  0                        # cr13: home space segment table
-        .long  0xc0000000               # cr14: machine check handling off
-        .long  0                        # cr15: linkage stack operations
-.Lpcmem:.long  0x00080000,0x80000000 + .Lchkmem
-.Lpcfpu:.long  0x00080000,0x80000000 + .Lchkfpu
-.Lpccsp:.long  0x00080000,0x80000000 + .Lchkcsp
-.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
-.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
-.Lmemsize:.long memory_size
-.Lmchunk:.long memory_chunk
-.Lmflags:.long machine_flags
-.Lbss_bgn:  .long  __bss_start
-.Lbss_end:  .long  _end
-
-	.org PARMAREA-64
-.Lduct:	.long 0,0,0,0,0,0,0,0
-	.long 0,0,0,0,0,0,0,0
-
-#
-# params at 10400 (setup.h)
-#
-	.org   PARMAREA
-	.global _pstart
-_pstart:	
-        .long  0,0                      # IPL_DEVICE
-        .long  0,RAMDISK_ORIGIN         # INITRD_START
-        .long  0,RAMDISK_SIZE           # INITRD_SIZE
-
-        .org   COMMAND_LINE
-    	.byte  "root=/dev/ram0 ro"
-        .byte  0
-	.org   0x11000
-.Lsccb:
-	.hword 0x1000			# length, one page
-	.byte 0x00,0x00,0x00
-	.byte 0x80			# variable response bit set
-.Lsccbr:
-	.hword 0x00			# response code
-.Lscpincr1:
-	.hword 0x00
-.Lscpa1:
-	.byte 0x00
-	.fill 89,1,0
-.Lscpa2:
-	.int 0x00
-.Lscpincr2:
-	.quad 0x00
-	.fill 3984,1,0
-	.org 0x12000
-	.global _pend
-_pend:	
-
+.macro GET_IPL_DEVICE
 .Lget_ipl_device:
 	basr  %r12,0
-.LPG2:	l     %r1,0xb8			# get sid
+.LGID:	l     %r1,0xb8			# get sid
 	sll   %r1,15			# test if subchannel is enabled
 	srl   %r1,31
 	ltr   %r1,%r1
 	bz    0(%r14)			# subchannel disabled
 	l     %r1,0xb8
-	la    %r5,.Lipl_schib-.LPG2(%r12)
+	la    %r5,.Lipl_schib-.LGID(%r12)
 	stsch 0(%r5)		        # get schib of subchannel
 	bnz   0(%r14)			# schib not available
 	tm    5(%r5),0x01		# devno valid?
 	bno   0(%r14)
-	la    %r6,ipl_parameter_flags-.LPG2(%r12)
+	la    %r6,ipl_parameter_flags-.LGID(%r12)
 	oi    3(%r6),0x01		# set flag
-	la    %r2,ipl_devno-.LPG2(%r12)
+	la    %r2,ipl_devno-.LGID(%r12)
 	mvc   0(2,%r2),6(%r5)		# store devno
 	tm    4(%r5),0x80		# qdio capable device?
 	bno   0(%r14)
@@ -815,46 +537,10 @@ ipl_parameter_flags:
 	.globl ipl_devno
 ipl_devno:
 	.word 0
+.endm
 
-#ifdef CONFIG_SHARED_KERNEL
-	.org   0x100000
+#ifdef CONFIG_ARCH_S390X
+#include "head64.S"
+#else
+#include "head31.S"
 #endif
-
-#
-# startup-code, running in virtual mode
-#
-        .globl _stext
-_stext:	basr  %r13,0                    # get base
-.LPG3:
-#
-# Setup stack
-#
-        l     %r15,.Linittu-.LPG3(%r13)
-	mvc   __LC_CURRENT(4),__TI_task(%r15)
-        ahi   %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
-        st    %r15,__LC_KERNEL_STACK    # set end of kernel stack
-        ahi   %r15,-96
-        xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
-
-# check control registers
-        stctl  %c0,%c15,0(%r15)
-	oi     2(%r15),0x40             # enable sigp emergency signal
-	oi     0(%r15),0x10             # switch on low address protection
-        lctl   %c0,%c15,0(%r15)
-
-#
-        lam    0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
-        l      %r14,.Lstart-.LPG3(%r13)
-        basr   %r14,%r14                # call start_kernel
-#
-# We returned from start_kernel ?!? PANIK
-#
-        basr  %r13,0
-	lpsw  .Ldw-.(%r13)           # load disabled wait psw
-#
-            .align 8
-.Ldw:	    .long  0x000a0000,0x00000000
-.Linittu:   .long  init_thread_union
-.Lstart:    .long  start_kernel
-.Laregs:    .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
new file mode 100644
index 0000000000..2d3b089bfb
--- /dev/null
+++ b/arch/s390/kernel/head31.S
@@ -0,0 +1,336 @@
+/*
+ * arch/s390/kernel/head31.S
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ *   Author(s):	Hartmut Penner <hp@de.ibm.com>
+ *		Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *		Rob van der Heij <rvdhei@iae.nl>
+ *		Heiko Carstens <heiko.carstens@de.ibm.com>
+ *
+ */
+
+#
+# startup-code at 0x10000, running in absolute addressing mode
+# this is called either by the ipl loader or directly by PSW restart
+# or linload or SALIPL
+#
+	.org	0x10000
+startup:basr	%r13,0			 # get base
+.LPG1:	l	%r1, .Lget_ipl_device_addr-.LPG1(%r13)
+	basr	%r14, %r1
+	lctl	%c0,%c15,.Lctl-.LPG1(%r13) # load control registers
+	la	%r12,_pstart-.LPG1(%r13) # pointer to parameter area
+					 # move IPL device to lowcore
+	mvc	__LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
+
+#
+# clear bss memory
+#
+	l	%r2,.Lbss_bgn-.LPG1(%r13) # start of bss
+	l	%r3,.Lbss_end-.LPG1(%r13) # end of bss
+	sr	%r3,%r2			# length of bss
+	sr	%r4,%r4
+	sr	%r5,%r5			# set src,length and pad to zero
+	sr	%r0,%r0
+	mvcle	%r2,%r4,0		# clear mem
+	jo	.-4			# branch back, if not finish
+
+	l	%r2,.Lrcp-.LPG1(%r13)	# Read SCP forced command word
+.Lservicecall:
+	stosm	.Lpmask-.LPG1(%r13),0x01	# authorize ext interrupts
+
+	stctl	%r0, %r0,.Lcr-.LPG1(%r13)	# get cr0
+	la	%r1,0x200		# set bit 22
+	o	%r1,.Lcr-.LPG1(%r13)	# or old cr0 with r1
+	st	%r1,.Lcr-.LPG1(%r13)
+	lctl	%r0, %r0,.Lcr-.LPG1(%r13)	# load modified cr0
+
+	mvc	__LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
+	la	%r1, .Lsclph-.LPG1(%r13)
+	a	%r1,__LC_EXT_NEW_PSW+4	# set handler
+	st	%r1,__LC_EXT_NEW_PSW+4
+
+	la	%r4,_pstart-.LPG1(%r13)	# %r4 is our index for sccb stuff
+	la	%r1, .Lsccb-PARMAREA(%r4)	# our sccb
+	.insn	rre,0xb2200000,%r2,%r1	# service call
+	ipm	%r1
+	srl	%r1,28			# get cc code
+	xr	%r3, %r3
+	chi	%r1,3
+	be	.Lfchunk-.LPG1(%r13)	# leave
+	chi	%r1,2
+	be	.Lservicecall-.LPG1(%r13)
+	lpsw	.Lwaitsclp-.LPG1(%r13)
+.Lsclph:
+	lh	%r1,.Lsccbr-PARMAREA(%r4)
+	chi	%r1,0x10		# 0x0010 is the sucess code
+	je	.Lprocsccb		# let's process the sccb
+	chi	%r1,0x1f0
+	bne	.Lfchunk-.LPG1(%r13)	# unhandled error code
+	c	%r2, .Lrcp-.LPG1(%r13)	# Did we try Read SCP forced
+	bne	.Lfchunk-.LPG1(%r13)	# if no, give up
+	l	%r2, .Lrcp2-.LPG1(%r13)	# try with Read SCP
+	b	.Lservicecall-.LPG1(%r13)
+.Lprocsccb:
+	lhi	%r1,0
+	icm	%r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+	jnz	.Lscnd
+	lhi	%r1,0x800		# otherwise report 2GB
+.Lscnd:
+	lhi	%r3,0x800		# limit reported memory size to 2GB
+	cr	%r1,%r3
+	jl	.Lno2gb
+	lr	%r1,%r3
+.Lno2gb:
+	xr	%r3,%r3			# same logic
+	ic	%r3,.Lscpa1-PARMAREA(%r4)
+	chi	%r3,0x00
+	jne	.Lcompmem
+	l	%r3,.Lscpa2-PARMAREA(%r13)
+.Lcompmem:
+	mr	%r2,%r1			# mem in MB on 128-bit
+	l	%r1,.Lonemb-.LPG1(%r13)
+	mr	%r2,%r1			# mem size in bytes in %r3
+	b	.Lfchunk-.LPG1(%r13)
+
+	.align 4
+.Lget_ipl_device_addr:
+	.long	.Lget_ipl_device
+.Lpmask:
+	.byte	0
+.align 8
+.Lpcext:.long	0x00080000,0x80000000
+.Lcr:
+	.long	0x00			# place holder for cr0
+.Lwaitsclp:
+	.long 0x010a0000,0x80000000 + .Lsclph
+.Lrcp:
+	.int	0x00120001		# Read SCP forced code
+.Lrcp2:
+	.int	0x00020001		# Read SCP code
+.Lonemb:
+	.int	0x100000
+.Lfchunk:
+
+#
+# find memory chunks.
+#
+	lr	%r9,%r3			# end of mem
+	mvc	__LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
+	la	%r1,1			# test in increments of 128KB
+	sll	%r1,17
+	l	%r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array
+	slr	%r4,%r4			# set start of chunk to zero
+	slr	%r5,%r5			# set end of chunk to zero
+	slr	%r6,%r6			# set access code to zero
+	la	%r10, MEMORY_CHUNKS	# number of chunks
+.Lloop:
+	tprot	0(%r5),0		# test protection of first byte
+	ipm	%r7
+	srl	%r7,28
+	clr	%r6,%r7			# compare cc with last access code
+	be	.Lsame-.LPG1(%r13)
+	b	.Lchkmem-.LPG1(%r13)
+.Lsame:
+	ar	%r5,%r1			# add 128KB to end of chunk
+	bno	.Lloop-.LPG1(%r13)	# r1 < 0x80000000 -> loop
+.Lchkmem:				# > 2GB or tprot got a program check
+	clr	%r4,%r5			# chunk size > 0?
+	be	.Lchkloop-.LPG1(%r13)
+	st	%r4,0(%r3)		# store start address of chunk
+	lr	%r0,%r5
+	slr	%r0,%r4
+	st	%r0,4(%r3)		# store size of chunk
+	st	%r6,8(%r3)		# store type of chunk
+	la	%r3,12(%r3)
+	l	%r4,.Lmemsize-.LPG1(%r13)	 # address of variable memory_size
+	st	%r5,0(%r4)		# store last end to memory size
+	ahi	%r10,-1			# update chunk number
+.Lchkloop:
+	lr	%r6,%r7			# set access code to last cc
+	# we got an exception or we're starting a new
+	# chunk , we must check if we should
+	# still try to find valid memory (if we detected
+	# the amount of available storage), and if we
+	# have chunks left
+	xr	%r0,%r0
+	clr	%r0,%r9			# did we detect memory?
+	je	.Ldonemem		# if not, leave
+	chi	%r10,0			# do we have chunks left?
+	je	.Ldonemem
+	alr	%r5,%r1			# add 128KB to end of chunk
+	lr	%r4,%r5			# potential new chunk
+	clr	%r5,%r9			# should we go on?
+	jl	.Lloop
+.Ldonemem:
+	l	%r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
+#
+# find out if we are running under VM
+#
+	stidp	__LC_CPUID		# store cpuid
+	tm	__LC_CPUID,0xff		# running under VM ?
+	bno	.Lnovm-.LPG1(%r13)
+	oi	3(%r12),1		# set VM flag
+.Lnovm:
+	lh	%r0,__LC_CPUID+4	# get cpu version
+	chi	%r0,0x7490		# running on a P/390 ?
+	bne	.Lnop390-.LPG1(%r13)
+	oi	3(%r12),4		# set P/390 flag
+.Lnop390:
+
+#
+# find out if we have an IEEE fpu
+#
+	mvc	__LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
+	efpc	%r0,0			# test IEEE extract fpc instruction
+	oi	3(%r12),2		# set IEEE fpu flag
+.Lchkfpu:
+
+#
+# find out if we have the CSP instruction
+#
+       mvc	 __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13)
+       la	 %r0,0
+       lr	%r1,%r0
+       la	%r2,4
+       csp	%r0,%r2			# Test CSP instruction
+       oi	3(%r12),8		# set CSP flag
+.Lchkcsp:
+
+#
+# find out if we have the MVPG instruction
+#
+       mvc	__LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13)
+       sr	%r0,%r0
+       la	%r1,0
+       la	%r2,0
+       mvpg	%r1,%r2			# Test CSP instruction
+       oi	3(%r12),16		# set MVPG flag
+.Lchkmvpg:
+
+#
+# find out if we have the IDTE instruction
+#
+	mvc	__LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13)
+	.long	0xb2b10000		# store facility list
+	tm	0xc8,0x08		# check bit for clearing-by-ASCE
+	bno	.Lchkidte-.LPG1(%r13)
+	lhi	%r1,2094
+	lhi	%r2,0
+	.long	0xb98e2001
+	oi	3(%r12),0x80		# set IDTE flag
+.Lchkidte:
+
+	lpsw  .Lentry-.LPG1(13)		# jump to _stext in primary-space,
+					# virtual and never return ...
+	.align	8
+.Lentry:.long	0x00080000,0x80000000 + _stext
+.Lctl:	.long	0x04b50002		# cr0: various things
+	.long	0			# cr1: primary space segment table
+	.long	.Lduct			# cr2: dispatchable unit control table
+	.long	0			# cr3: instruction authorization
+	.long	0			# cr4: instruction authorization
+	.long	0xffffffff		# cr5: primary-aste origin
+	.long	0			# cr6:	I/O interrupts
+	.long	0			# cr7:	secondary space segment table
+	.long	0			# cr8:	access registers translation
+	.long	0			# cr9:	tracing off
+	.long	0			# cr10: tracing off
+	.long	0			# cr11: tracing off
+	.long	0			# cr12: tracing off
+	.long	0			# cr13: home space segment table
+	.long	0xc0000000		# cr14: machine check handling off
+	.long	0			# cr15: linkage stack operations
+.Lpcmem:.long	0x00080000,0x80000000 + .Lchkmem
+.Lpcfpu:.long	0x00080000,0x80000000 + .Lchkfpu
+.Lpccsp:.long	0x00080000,0x80000000 + .Lchkcsp
+.Lpcmvpg:.long	0x00080000,0x80000000 + .Lchkmvpg
+.Lpcidte:.long	0x00080000,0x80000000 + .Lchkidte
+.Lmemsize:.long memory_size
+.Lmchunk:.long	memory_chunk
+.Lmflags:.long	machine_flags
+.Lbss_bgn:  .long __bss_start
+.Lbss_end:  .long _end
+
+	.org	PARMAREA-64
+.Lduct:	.long	0,0,0,0,0,0,0,0
+	.long	0,0,0,0,0,0,0,0
+
+#
+# params at 10400 (setup.h)
+#
+	.org	PARMAREA
+	.global _pstart
+_pstart:
+	.long	0,0			# IPL_DEVICE
+	.long	0,RAMDISK_ORIGIN	# INITRD_START
+	.long	0,RAMDISK_SIZE		# INITRD_SIZE
+
+	.org	COMMAND_LINE
+	.byte	"root=/dev/ram0 ro"
+	.byte	0
+	.org	0x11000
+.Lsccb:
+	.hword	0x1000			# length, one page
+	.byte	0x00,0x00,0x00
+	.byte	0x80			# variable response bit set
+.Lsccbr:
+	.hword	0x00			# response code
+.Lscpincr1:
+	.hword	0x00
+.Lscpa1:
+	.byte	0x00
+	.fill	89,1,0
+.Lscpa2:
+	.int	0x00
+.Lscpincr2:
+	.quad	0x00
+	.fill	3984,1,0
+	.org	0x12000
+	.global	_pend
+_pend:
+
+	GET_IPL_DEVICE
+
+#ifdef CONFIG_SHARED_KERNEL
+	.org	0x100000
+#endif
+
+#
+# startup-code, running in virtual mode
+#
+	.globl	_stext
+_stext:	basr	%r13,0			# get base
+.LPG3:
+#
+# Setup stack
+#
+	l	%r15,.Linittu-.LPG3(%r13)
+	mvc	__LC_CURRENT(4),__TI_task(%r15)
+	ahi	%r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
+	st	%r15,__LC_KERNEL_STACK	# set end of kernel stack
+	ahi	%r15,-96
+	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
+
+# check control registers
+	stctl	%c0,%c15,0(%r15)
+	oi	2(%r15),0x40		# enable sigp emergency signal
+	oi	0(%r15),0x10		# switch on low address protection
+	lctl	%c0,%c15,0(%r15)
+
+#
+	lam	0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
+	l	%r14,.Lstart-.LPG3(%r13)
+	basr	%r14,%r14		# call start_kernel
+#
+# We returned from start_kernel ?!? PANIK
+#
+	basr	%r13,0
+	lpsw	.Ldw-.(%r13)		# load disabled wait psw
+#
+	.align	8
+.Ldw:	.long	0x000a0000,0x00000000
+.Linittu:.long	init_thread_union
+.Lstart:.long	start_kernel
+.Laregs:.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index d9be8f96f2..f08c06f45d 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -1,482 +1,17 @@
 /*
- *  arch/s390/kernel/head.S
+ * arch/s390/kernel/head64.S
  *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Hartmut Penner (hp@de.ibm.com),
- *               Martin Schwidefsky (schwidefsky@de.ibm.com),
- *               Rob van der Heij (rvdhei@iae.nl)
+ * (C) Copyright IBM Corp. 1999,2005
+ *
+ *   Author(s):	Hartmut Penner <hp@de.ibm.com>
+ *		Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *		Rob van der Heij <rvdhei@iae.nl>
+ *		Heiko Carstens <heiko.carstens@de.ibm.com>
  *
- * There are 5 different IPL methods
- *  1) load the image directly into ram at address 0 and do an PSW restart
- *  2) linload will load the image from address 0x10000 to memory 0x10000
- *     and start the code thru LPSW 0x0008000080010000 (VM only, deprecated)
- *  3) generate the tape ipl header, store the generated image on a tape
- *     and ipl from it
- *     In case of SL tape you need to IPL 5 times to get past VOL1 etc
- *  4) generate the vm reader ipl header, move the generated image to the
- *     VM reader (use option NOH!) and do a ipl from reader (VM only)
- *  5) direct call of start by the SALIPL loader
- *  We use the cpuid to distinguish between VM and native ipl
- *  params for kernel are pushed to 0x10400 (see setup.h)
-
-    Changes: 
-    Okt 25 2000 <rvdheij@iae.nl>
-	added code to skip HDR and EOF to allow SL tape IPL (5 retries)
-	changed first CCW from rewind to backspace block
-
  */
 
-#include <linux/config.h>
-#include <asm/setup.h>
-#include <asm/lowcore.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/page.h>
-
-#ifndef CONFIG_IPL
-        .org   0
-        .long  0x00080000,0x80000000+startup   # Just a restart PSW
-#else
-#ifdef CONFIG_IPL_TAPE
-#define IPL_BS 1024
-        .org   0
-        .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
-        .long  0x27000000,0x60000001           # by ipl to addresses 0-23.
-        .long  0x02000000,0x20000000+IPL_BS    # (a PSW and two CCWs).
-        .long  0x00000000,0x00000000           # external old psw
-        .long  0x00000000,0x00000000           # svc old psw
-        .long  0x00000000,0x00000000           # program check old psw
-        .long  0x00000000,0x00000000           # machine check old psw
-        .long  0x00000000,0x00000000           # io old psw
-        .long  0x00000000,0x00000000
-        .long  0x00000000,0x00000000
-        .long  0x00000000,0x00000000
-        .long  0x000a0000,0x00000058           # external new psw
-        .long  0x000a0000,0x00000060           # svc new psw
-        .long  0x000a0000,0x00000068           # program check new psw
-        .long  0x000a0000,0x00000070           # machine check new psw
-        .long  0x00080000,0x80000000+.Lioint   # io new psw
-
-        .org   0x100
-#
-# subroutine for loading from tape
-# Paramters:	
-#  R1 = device number
-#  R2 = load address
-.Lloader:	
-        st    %r14,.Lldret
-        la    %r3,.Lorbread                    # r3 = address of orb 
-	la    %r5,.Lirb                        # r5 = address of irb
-        st    %r2,.Lccwread+4                  # initialize CCW data addresses
-        lctl  %c6,%c6,.Lcr6               
-        slr   %r2,%r2
-.Lldlp:
-        la    %r6,3                            # 3 retries
-.Lssch:
-        ssch  0(%r3)                           # load chunk of IPL_BS bytes
-        bnz   .Llderr
-.Lw4end:
-        bas   %r14,.Lwait4io
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Lrecov
-        slr   %r7,%r7
-        icm   %r7,3,10(%r5)                    # get residual count
-        lcr   %r7,%r7
-        la    %r7,IPL_BS(%r7)                  # IPL_BS-residual=#bytes read
-        ar    %r2,%r7                          # add to total size
-        tm    8(%r5),0x01                      # found a tape mark ?
-        bnz   .Ldone
-        l     %r0,.Lccwread+4                  # update CCW data addresses
-        ar    %r0,%r7
-        st    %r0,.Lccwread+4                
-        b     .Lldlp
-.Ldone:
-        l     %r14,.Lldret
-        br    %r14                             # r2 contains the total size
-.Lrecov:
-        bas   %r14,.Lsense                     # do the sensing
-        bct   %r6,.Lssch                       # dec. retry count & branch
-        b     .Llderr
-#
-# Sense subroutine
-#
-.Lsense:
-        st    %r14,.Lsnsret
-        la    %r7,.Lorbsense              
-        ssch  0(%r7)                           # start sense command
-        bnz   .Llderr
-        bas   %r14,.Lwait4io
-        l     %r14,.Lsnsret
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Llderr
-        br    %r14
-#
-# Wait for interrupt subroutine
-#
-.Lwait4io:
-        lpsw  .Lwaitpsw                 
-.Lioint:
-        c     %r1,0xb8                         # compare subchannel number
-        bne   .Lwait4io
-        tsch  0(%r5)
-        slr   %r0,%r0
-        tm    8(%r5),0x82                      # do we have a problem ?
-        bnz   .Lwtexit
-        tm    8(%r5),0x04                      # got device end ?
-        bz    .Lwait4io
-.Lwtexit:
-        br    %r14
-.Llderr:
-        lpsw  .Lcrash              
-
-        .align 8
-.Lorbread:
-	.long  0x00000000,0x0080ff00,.Lccwread
-        .align 8
-.Lorbsense:
-        .long  0x00000000,0x0080ff00,.Lccwsense
-        .align 8
-.Lccwread:
-        .long  0x02200000+IPL_BS,0x00000000
-.Lccwsense:
-        .long  0x04200001,0x00000000
-.Lwaitpsw:
-	.long  0x020a0000,0x80000000+.Lioint
-
-.Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6:  .long  0xff000000
-        .align 8
-.Lcrash:.long  0x000a0000,0x00000000
-.Lldret:.long  0
-.Lsnsret: .long 0
-#endif  /* CONFIG_IPL_TAPE */
-
-#ifdef CONFIG_IPL_VM
-#define IPL_BS 0x730
-        .org   0
-        .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
-        .long  0x02000018,0x60000050           # by ipl to addresses 0-23.
-        .long  0x02000068,0x60000050           # (a PSW and two CCWs).
-        .fill  80-24,1,0x40                    # bytes 24-79 are discarded !!
-        .long  0x020000f0,0x60000050           # The next 160 byte are loaded
-        .long  0x02000140,0x60000050           # to addresses 0x18-0xb7
-        .long  0x02000190,0x60000050           # They form the continuation
-        .long  0x020001e0,0x60000050           # of the CCW program started
-        .long  0x02000230,0x60000050           # by ipl and load the range
-        .long  0x02000280,0x60000050           # 0x0f0-0x730 from the image
-        .long  0x020002d0,0x60000050           # to the range 0x0f0-0x730
-        .long  0x02000320,0x60000050           # in memory. At the end of
-        .long  0x02000370,0x60000050           # the channel program the PSW
-        .long  0x020003c0,0x60000050           # at location 0 is loaded.
-        .long  0x02000410,0x60000050           # Initial processing starts
-        .long  0x02000460,0x60000050           # at 0xf0 = iplstart.
-        .long  0x020004b0,0x60000050
-        .long  0x02000500,0x60000050
-        .long  0x02000550,0x60000050
-        .long  0x020005a0,0x60000050
-        .long  0x020005f0,0x60000050
-        .long  0x02000640,0x60000050
-        .long  0x02000690,0x60000050
-        .long  0x020006e0,0x20000050
-
-        .org   0xf0
-#
-# subroutine for loading cards from the reader
-#
-.Lloader:	
-	la    %r3,.Lorb                        # r2 = address of orb into r2
-	la    %r5,.Lirb                        # r4 = address of irb
-        la    %r6,.Lccws              
-        la    %r7,20
-.Linit:
-        st    %r2,4(%r6)                       # initialize CCW data addresses
-        la    %r2,0x50(%r2)
-        la    %r6,8(%r6)
-        bct   7,.Linit
-
-        lctl  %c6,%c6,.Lcr6                    # set IO subclass mask
-	slr   %r2,%r2
-.Lldlp:
-        ssch  0(%r3)                           # load chunk of 1600 bytes
-        bnz   .Llderr
-.Lwait4irq:
-        mvc   0x78(8),.Lnewpsw                 # set up IO interrupt psw
-        lpsw  .Lwaitpsw              
-.Lioint:
-        c     %r1,0xb8                         # compare subchannel number
-	bne   .Lwait4irq
-	tsch  0(%r5)
-
-	slr   %r0,%r0
-	ic    %r0,8(%r5)                       # get device status
-	chi   %r0,8                            # channel end ?
-	be    .Lcont
-	chi   %r0,12                           # channel end + device end ?
-	be    .Lcont
-
-        l     %r0,4(%r5)
-        s     %r0,8(%r3)                       # r0/8 = number of ccws executed
-        mhi   %r0,10                           # *10 = number of bytes in ccws
-        lh    %r3,10(%r5)                      # get residual count
-        sr    %r0,%r3                          # #ccws*80-residual=#bytes read
-	ar    %r2,%r0
-	
-        br    %r14                             # r2 contains the total size
-
-.Lcont:
-	ahi   %r2,0x640                        # add 0x640 to total size
-        la    %r6,.Lccws             
-        la    %r7,20
-.Lincr:
-        l     %r0,4(%r6)                       # update CCW data addresses
-        ahi   %r0,0x640
-        st    %r0,4(%r6)
-        ahi   %r6,8
-        bct   7,.Lincr
-
-        b     .Lldlp
-.Llderr:
-        lpsw  .Lcrash              
-
-        .align 8
-.Lorb:	.long  0x00000000,0x0080ff00,.Lccws
-.Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6:  .long  0xff000000
-.Lloadp:.long  0,0
-        .align 8
-.Lcrash:.long  0x000a0000,0x00000000
-.Lnewpsw:
-        .long  0x00080000,0x80000000+.Lioint
-.Lwaitpsw:
-        .long  0x020a0000,0x80000000+.Lioint
-
-        .align 8
-.Lccws: .rept  19
-        .long  0x02600050,0x00000000
-        .endr
-        .long  0x02200050,0x00000000
-#endif  /* CONFIG_IPL_VM */
-
-iplstart:
-        lh    %r1,0xb8                         # test if subchannel number
-        bct   %r1,.Lnoload                     #  is valid
-	l     %r1,0xb8                         # load ipl subchannel number
-        la    %r2,IPL_BS                       # load start address
-        bas   %r14,.Lloader                    # load rest of ipl image
-        larl  %r12,_pstart                     # pointer to parameter area
-        st    %r1,IPL_DEVICE+4-PARMAREA(%r12)  # store ipl device number
-
-#
-# load parameter file from ipl device
 #
-.Lagain1:
- 	l     %r2,INITRD_START+4-PARMAREA(%r12)# use ramdisk location as temp
-        bas   %r14,.Lloader                    # load parameter file
-        ltr   %r2,%r2                          # got anything ?
-        bz    .Lnopf
-	chi   %r2,895
-	bnh   .Lnotrunc
-	la    %r2,895
-.Lnotrunc:
-	l     %r4,INITRD_START+4-PARMAREA(%r12)
- 	clc   0(3,%r4),.L_hdr		       # if it is HDRx
- 	bz    .Lagain1			       # skip dataset header
- 	clc   0(3,%r4),.L_eof		       # if it is EOFx
- 	bz    .Lagain1			       # skip dateset trailer
-        la    %r5,0(%r4,%r2)
-        lr    %r3,%r2
-.Lidebc:
-        tm    0(%r5),0x80                      # high order bit set ?
-        bo    .Ldocv                           #  yes -> convert from EBCDIC
-        ahi   %r5,-1
-        bct   %r3,.Lidebc
-        b     .Lnocv
-.Ldocv:
-        l     %r3,.Lcvtab
-        tr    0(256,%r4),0(%r3)                # convert parameters to ascii
-        tr    256(256,%r4),0(%r3)
-        tr    512(256,%r4),0(%r3)
-        tr    768(122,%r4),0(%r3)
-.Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
-	mvc   0(256,%r3),0(%r4)
-	mvc   256(256,%r3),256(%r4)
-	mvc   512(256,%r3),512(%r4)
-	mvc   768(122,%r3),768(%r4)
-        slr   %r0,%r0
-        b     .Lcntlp
-.Ldelspc:
-        ic    %r0,0(%r2,%r3)
-        chi   %r0,0x20                         # is it a space ?
-        be    .Lcntlp
-        ahi   %r2,1
-        b     .Leolp
-.Lcntlp:
-        brct  %r2,.Ldelspc
-.Leolp:
-        slr   %r0,%r0
-        stc   %r0,0(%r2,%r3)                   # terminate buffer
-.Lnopf:
-
-#
-# load ramdisk from ipl device
-#
-.Lagain2:
- 	l     %r2,INITRD_START+4-PARMAREA(%r12)# load adr. of ramdisk
-        bas   %r14,.Lloader                    # load ramdisk
- 	st    %r2,INITRD_SIZE+4-PARMAREA(%r12) # store size of ramdisk
-        ltr   %r2,%r2
-        bnz   .Lrdcont
-        st    %r2,INITRD_START+4-PARMAREA(%r12)# no ramdisk found, null it
-.Lrdcont:
-	l     %r2,INITRD_START+4-PARMAREA(%r12)
-	clc   0(3,%r2),.L_hdr		       # skip HDRx and EOFx 
-	bz    .Lagain2
-	clc   0(3,%r2),.L_eof
-	bz    .Lagain2
-
-#ifdef CONFIG_IPL_VM
-#
-# reset files in VM reader
-#
-        stidp __LC_CPUID                       # store cpuid
-	tm    __LC_CPUID,0xff                  # running VM ?
-	bno   .Lnoreset
-        la    %r2,.Lreset              
-        lhi   %r3,26
-	diag  %r2,%r3,8
-	la    %r5,.Lirb
-	stsch 0(%r5)			       # check if irq is pending
-	tm    30(%r5),0x0f		       # by verifying if any of the
-	bnz   .Lwaitforirq		       # activity or status control
-	tm    31(%r5),0xff		       # bits is set in the schib
-	bz    .Lnoreset
-.Lwaitforirq:
-	mvc   0x78(8),.Lrdrnewpsw	       # set up IO interrupt psw
-.Lwaitrdrirq:
-	lpsw  .Lrdrwaitpsw
-.Lrdrint:
-	c     %r1,0xb8			       # compare subchannel number
-	bne   .Lwaitrdrirq
-	la    %r5,.Lirb
-	tsch  0(%r5)
-.Lnoreset:
-	b     .Lnoload
-
-	.align 8
-.Lrdrnewpsw:
-	.long  0x00080000,0x80000000+.Lrdrint
-.Lrdrwaitpsw:
-	.long  0x020a0000,0x80000000+.Lrdrint
-#endif
-
-#
-# everything loaded, go for it
-#
-.Lnoload:
-        l     %r1,.Lstartup
-        br    %r1
-
-.Lstartup: .long startup
-.Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
-.Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
-        .byte  0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
-        .byte  0xc8,0xd6,0xd3,0xc4             # "change rdr all keep nohold"
-.L_eof: .long  0xc5d6c600       /* C'EOF' */
-.L_hdr: .long  0xc8c4d900       /* C'HDR' */
-#endif  /* CONFIG_IPL */
-
-#
-# SALIPL loader support. Based on a patch by Rob van der Heij.
-# This entry point is called directly from the SALIPL loader and
-# doesn't need a builtin ipl record.
-#
-        .org  0x800
-	.globl start
-start:
-	stm   %r0,%r15,0x07b0		# store registers
-	basr  %r12,%r0
-.base:
-	l     %r11,.parm
-	l     %r8,.cmd			# pointer to command buffer
-
-	ltr   %r9,%r9			# do we have SALIPL parameters?
-	bp    .sk8x8
-
-	mvc   0(64,%r8),0x00b0		# copy saved registers
-	xc    64(240-64,%r8),0(%r8)	# remainder of buffer
-	tr    0(64,%r8),.lowcase	
-	b     .gotr
-.sk8x8:
-	mvc   0(240,%r8),0(%r9)		# copy iplparms into buffer
-.gotr:
-	l     %r10,.tbl			# EBCDIC to ASCII table
-	tr    0(240,%r8),0(%r10)
-	stidp __LC_CPUID		# Are we running on VM maybe
-	cli   __LC_CPUID,0xff
-	bnz   .test
-	.long 0x83300060		# diag 3,0,x'0060' - storage size
-	b     .done
-.test:
-	mvc   0x68(8),.pgmnw		# set up pgm check handler
-	l     %r2,.fourmeg
-	lr    %r3,%r2
-	bctr  %r3,%r0			# 4M-1
-.loop:  iske  %r0,%r3
-	ar    %r3,%r2
-.pgmx:
-	sr    %r3,%r2
-	la    %r3,1(%r3)
-.done:
-	l     %r1,.memsize
-	st    %r3,4(%r1)
-	slr   %r0,%r0
-	st    %r0,INITRD_SIZE+4-PARMAREA(%r11)
-	st    %r0,INITRD_START+4-PARMAREA(%r11)
-	j     startup                   # continue with startup
-.tbl:	.long _ebcasc			# translate table
-.cmd:	.long COMMAND_LINE		# address of command line buffer
-.parm:	.long PARMAREA
-.fourmeg: .long 0x00400000      	# 4M
-.pgmnw:	.long 0x00080000,.pgmx
-.memsize: .long memory_size
-.lowcase:
-	.byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 
-	.byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
-	.byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 
-	.byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
-	.byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 
-	.byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
-	.byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 
-	.byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
-	.byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 
-	.byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
-	.byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 
-	.byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
-	.byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 
-	.byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
-	.byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 
-	.byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
-
-	.byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 
-	.byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
-	.byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 
-	.byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
-	.byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 
-	.byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
-	.byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 
-	.byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
-	.byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87	# .abcdefg 
-	.byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf	# hi
-	.byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 	# .jklmnop
-	.byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf	# qr
-	.byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7	# ..stuvwx
-	.byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef	# yz
-	.byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 
-	.byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
-
-#
-# startup-code at 0x10000, running in real mode
+# startup-code at 0x10000, running in absolute addressing mode
 # this is called either by the ipl loader or directly by PSW restart
 # or linload or SALIPL
 #
@@ -750,62 +285,7 @@ _pstart:
 	.global _pend
 _pend:	
 
-.Lget_ipl_device:
-	basr  %r12,0
-.LPG2:	l     %r1,0xb8			# get sid
-	sll   %r1,15			# test if subchannel is enabled
-	srl   %r1,31
-	ltr   %r1,%r1
-	bz    0(%r14)			# subchannel disabled
-	l     %r1,0xb8
-	la    %r5,.Lipl_schib-.LPG2(%r12)
-	stsch 0(%r5)		        # get schib of subchannel
-	bnz   0(%r14)			# schib not available
-	tm    5(%r5),0x01		# devno valid?
-	bno   0(%r14)
-	la    %r6,ipl_parameter_flags-.LPG2(%r12)
-	oi    3(%r6),0x01		# set flag
-	la    %r2,ipl_devno-.LPG2(%r12)
-	mvc   0(2,%r2),6(%r5)		# store devno
-	tm    4(%r5),0x80		# qdio capable device?
-	bno   0(%r14)
-	oi    3(%r6),0x02		# set flag
-
-	# copy ipl parameters
-
-	lhi   %r0,4096
-	l     %r2,20(%r0)		# get address of parameter list
-	lhi   %r3,IPL_PARMBLOCK_ORIGIN
-	st    %r3,20(%r0)
-	lhi   %r4,1
-	cr    %r2,%r3			# start parameters < destination ?
-	jl    0f
-	lhi   %r1,1			# copy direction is upwards
-	j     1f
-0:	lhi   %r1,-1			# copy direction is downwards
-	ar    %r2,%r0
-	ar    %r3,%r0
-	ar    %r2,%r1
-	ar    %r3,%r1
-1:	mvc   0(1,%r3),0(%r2)		# finally copy ipl parameters
-	ar    %r3,%r1
-	ar    %r2,%r1
-	sr    %r0,%r4
-	jne   1b
-	b     0(%r14)
-
-	.align 4
-.Lipl_schib:
-	.rept 13
-	.long 0
-	.endr
-
-	.globl ipl_parameter_flags
-ipl_parameter_flags:
-	.long 0
-	.globl ipl_devno
-ipl_devno:
-	.word 0
+	GET_IPL_DEVICE
 
 #ifdef CONFIG_SHARED_KERNEL
 	.org   0x100000
-- 
cgit v1.2.2


From cd6b0762a04978baf48412456a687842de97e381 Mon Sep 17 00:00:00 2001
From: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Date: Mon, 7 Nov 2005 00:59:14 -0800
Subject: [PATCH] Move Kprobes and Oprofile to "Instrumentation Support" menu

Andrew Morton suggested to move kprobes from kernel hacking menu, since
kernel hacking menu is in-appropriate for the Kprobes.  This patch moves
Kprobes and Oprofile under instrumentation menu.

(akpm: it's not a natural fit, but things like djprobes and the s390 guys'
statistics library need a home)

Signed-of-by: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Cc: Philippe Elie <phil.el@wanadoo.fr>
Cc: John Levon <levon@movementarian.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/Kconfig             | 13 +++++++++++++
 arch/i386/Kconfig.debug       | 10 ----------
 arch/i386/oprofile/Kconfig    |  6 ------
 arch/ia64/Kconfig             | 13 +++++++++++++
 arch/ia64/Kconfig.debug       | 11 -----------
 arch/ia64/oprofile/Kconfig    |  6 ------
 arch/powerpc/Kconfig          | 13 +++++++++++++
 arch/powerpc/Kconfig.debug    | 10 ----------
 arch/powerpc/oprofile/Kconfig |  6 ------
 arch/sparc64/Kconfig          | 13 +++++++++++++
 arch/sparc64/Kconfig.debug    | 10 ----------
 arch/sparc64/oprofile/Kconfig |  6 ------
 arch/x86_64/Kconfig           | 13 +++++++++++++
 arch/x86_64/Kconfig.debug     | 10 ----------
 arch/x86_64/oprofile/Kconfig  |  6 ------
 15 files changed, 65 insertions(+), 81 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index bac0da731e..dbf90ad6ea 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -997,8 +997,21 @@ source "drivers/Kconfig"
 
 source "fs/Kconfig"
 
+menu "Instrumentation Support"
+	depends on EXPERIMENTAL
+
 source "arch/i386/oprofile/Kconfig"
 
+config KPROBES
+	bool "Kprobes (EXPERIMENTAL)"
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+endmenu
+
 source "arch/i386/Kconfig.debug"
 
 source "security/Kconfig"
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index 5228c40a6f..c48b424dd6 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -22,16 +22,6 @@ config DEBUG_STACKOVERFLOW
 	  This option will cause messages to be printed if free stack space
 	  drops below a certain limit.
 
-config KPROBES
-	bool "Kprobes"
-	depends on DEBUG_KERNEL
-	help
-	  Kprobes allows you to trap at almost any kernel address and
-	  execute a callback function.  register_kprobe() establishes
-	  a probepoint and specifies the callback.  Kprobes is useful
-	  for kernel debugging, non-intrusive instrumentation and testing.
-	  If in doubt, say "N".
-
 config DEBUG_STACK_USAGE
 	bool "Stack utilization instrumentation"
 	depends on DEBUG_KERNEL
diff --git a/arch/i386/oprofile/Kconfig b/arch/i386/oprofile/Kconfig
index 5ade19801b..d8a8408847 100644
--- a/arch/i386/oprofile/Kconfig
+++ b/arch/i386/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
-	depends on EXPERIMENTAL
-
 config PROFILING
 	bool "Profiling support (EXPERIMENTAL)"
 	help
@@ -19,5 +15,3 @@ config OPROFILE
 
 	  If unsure, say N.
 
-endmenu
-
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 3b4248cff9..9f2093c1f4 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -426,8 +426,21 @@ config GENERIC_PENDING_IRQ
 
 source "arch/ia64/hp/sim/Kconfig"
 
+menu "Instrumentation Support"
+        depends on EXPERIMENTAL
+
 source "arch/ia64/oprofile/Kconfig"
 
+config KPROBES
+	bool "Kprobes (EXPERIMENTAL)"
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+endmenu
+
 source "arch/ia64/Kconfig.debug"
 
 source "security/Kconfig"
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
index fda67ac993..de9d507ba0 100644
--- a/arch/ia64/Kconfig.debug
+++ b/arch/ia64/Kconfig.debug
@@ -2,17 +2,6 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
-config KPROBES
-        bool "Kprobes"
-        depends on DEBUG_KERNEL
-        help
-          Kprobes allows you to trap at almost any kernel address and
-          execute a callback function.  register_kprobe() establishes
-          a probepoint and specifies the callback.  Kprobes is useful
-          for kernel debugging, non-intrusive instrumentation and testing.
-          If in doubt, say "N".
-
-
 choice
 	prompt "Physical memory granularity"
 	default IA64_GRANULE_64MB
diff --git a/arch/ia64/oprofile/Kconfig b/arch/ia64/oprofile/Kconfig
index 56e6f614b0..97271ab484 100644
--- a/arch/ia64/oprofile/Kconfig
+++ b/arch/ia64/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
-	depends on EXPERIMENTAL
-
 config PROFILING
 	bool "Profiling support (EXPERIMENTAL)"
 	help
@@ -22,5 +18,3 @@ config OPROFILE
 
 	  If unsure, say N.
 
-endmenu
-
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 55ce495705..6ffae2d2b3 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -917,8 +917,21 @@ source "arch/powerpc/platforms/iseries/Kconfig"
 
 source "lib/Kconfig"
 
+menu "Instrumentation Support"
+        depends on EXPERIMENTAL
+
 source "arch/powerpc/oprofile/Kconfig"
 
+config KPROBES
+	bool "Kprobes (EXPERIMENTAL)"
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+endmenu
+
 source "arch/powerpc/Kconfig.debug"
 
 source "security/Kconfig"
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 0baf64ec80..30a30bf559 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -9,16 +9,6 @@ config DEBUG_STACKOVERFLOW
 	  This option will cause messages to be printed if free stack space
 	  drops below a certain limit.
 
-config KPROBES
-	bool "Kprobes"
-	depends on DEBUG_KERNEL && PPC64
-	help
-	  Kprobes allows you to trap at almost any kernel address and
-	  execute a callback function.  register_kprobe() establishes
-	  a probepoint and specifies the callback.  Kprobes is useful
-	  for kernel debugging, non-intrusive instrumentation and testing.
-	  If in doubt, say "N".
-
 config DEBUG_STACK_USAGE
 	bool "Stack utilization instrumentation"
 	depends on DEBUG_KERNEL && PPC64
diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig
index 19d37730b6..eb2dece76a 100644
--- a/arch/powerpc/oprofile/Kconfig
+++ b/arch/powerpc/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
-	depends on EXPERIMENTAL
-
 config PROFILING
 	bool "Profiling support (EXPERIMENTAL)"
 	help
@@ -19,5 +15,3 @@ config OPROFILE
 
 	  If unsure, say N.
 
-endmenu
-
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 1e9d8638a2..3fded69b19 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -377,8 +377,21 @@ source "drivers/fc4/Kconfig"
 
 source "fs/Kconfig"
 
+menu "Instrumentation Support"
+        depends on EXPERIMENTAL
+
 source "arch/sparc64/oprofile/Kconfig"
 
+config KPROBES
+	bool "Kprobes (EXPERIMENTAL)"
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+endmenu
+
 source "arch/sparc64/Kconfig.debug"
 
 source "security/Kconfig"
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
index fa06ea0483..3e31be494e 100644
--- a/arch/sparc64/Kconfig.debug
+++ b/arch/sparc64/Kconfig.debug
@@ -11,16 +11,6 @@ config DEBUG_STACK_USAGE
 
 	  This option will slow down process creation somewhat.
 
-config KPROBES
-	bool "Kprobes"
-	depends on DEBUG_KERNEL
-	help
-	  Kprobes allows you to trap at almost any kernel address and
-	  execute a callback function.  register_kprobe() establishes
-	  a probepoint and specifies the callback.  Kprobes is useful
-	  for kernel debugging, non-intrusive instrumentation and testing.
-	  If in doubt, say "N".
-
 config DEBUG_DCFLUSH
 	bool "D-cache flush debugging"
 	depends on DEBUG_KERNEL
diff --git a/arch/sparc64/oprofile/Kconfig b/arch/sparc64/oprofile/Kconfig
index 5ade19801b..d8a8408847 100644
--- a/arch/sparc64/oprofile/Kconfig
+++ b/arch/sparc64/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
-	depends on EXPERIMENTAL
-
 config PROFILING
 	bool "Profiling support (EXPERIMENTAL)"
 	help
@@ -19,5 +15,3 @@ config OPROFILE
 
 	  If unsure, say N.
 
-endmenu
-
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 21afa69a08..4cce2f6f17 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -532,8 +532,21 @@ source "drivers/firmware/Kconfig"
 
 source fs/Kconfig
 
+menu "Instrumentation Support"
+        depends on EXPERIMENTAL
+
 source "arch/x86_64/oprofile/Kconfig"
 
+config KPROBES
+	bool "Kprobes (EXPERIMENTAL)"
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+endmenu
+
 source "arch/x86_64/Kconfig.debug"
 
 source "security/Kconfig"
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
index 9cf1410d2f..d584ecc27e 100644
--- a/arch/x86_64/Kconfig.debug
+++ b/arch/x86_64/Kconfig.debug
@@ -33,16 +33,6 @@ config IOMMU_DEBUG
 	 options. See Documentation/x86_64/boot-options.txt for more
 	 details.
 
-config KPROBES
-	bool "Kprobes"
-	depends on DEBUG_KERNEL
-	help
-	  Kprobes allows you to trap at almost any kernel address and
-	  execute a callback function.  register_kprobe() establishes
-	  a probepoint and specifies the callback.  Kprobes is useful
-	  for kernel debugging, non-intrusive instrumentation and testing.
-	  If in doubt, say "N".
-
 config IOMMU_LEAK
        bool "IOMMU leak tracing"
        depends on DEBUG_KERNEL
diff --git a/arch/x86_64/oprofile/Kconfig b/arch/x86_64/oprofile/Kconfig
index 5ade19801b..d8a8408847 100644
--- a/arch/x86_64/oprofile/Kconfig
+++ b/arch/x86_64/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
-	depends on EXPERIMENTAL
-
 config PROFILING
 	bool "Profiling support (EXPERIMENTAL)"
 	help
@@ -19,5 +15,3 @@ config OPROFILE
 
 	  If unsure, say N.
 
-endmenu
-
-- 
cgit v1.2.2


From 8c65b4a60450590e79a28e9717ceffa9e4debb3f Mon Sep 17 00:00:00 2001
From: Tim Schmielau <tim@physik3.uni-rostock.de>
Date: Mon, 7 Nov 2005 00:59:43 -0800
Subject: [PATCH] fix remaining missing includes

Fix more include file problems that surfaced since I submitted the previous
fix-missing-includes.patch.  This should now allow not to include sched.h
from module.h, which is done by a followup patch.

Signed-off-by: Tim Schmielau <tim@physik3.uni-rostock.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/arm/mach-aaec2000/clock.c | 1 +
 arch/arm/mach-epxa10db/mm.c    | 1 +
 arch/arm/mach-pxa/corgi_lcd.c  | 1 +
 arch/ppc/syslib/ppc_sys.c      | 1 +
 4 files changed, 4 insertions(+)

(limited to 'arch')

diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c
index 99e019169d..0340ddc482 100644
--- a/arch/arm/mach-aaec2000/clock.c
+++ b/arch/arm/mach-aaec2000/clock.c
@@ -14,6 +14,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/string.h>
 
 #include <asm/semaphore.h>
 #include <asm/hardware/clock.h>
diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c
index e8832d0910..cfd0d2182d 100644
--- a/arch/arm/mach-epxa10db/mm.c
+++ b/arch/arm/mach-epxa10db/mm.c
@@ -25,6 +25,7 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/sizes.h>
+#include <asm/page.h>
  
 #include <asm/mach/map.h>
 
diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
index 54162ba954..698eb06545 100644
--- a/arch/arm/mach-pxa/corgi_lcd.c
+++ b/arch/arm/mach-pxa/corgi_lcd.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
+#include <linux/string.h>
 #include <asm/arch/akita.h>
 #include <asm/arch/corgi.h>
 #include <asm/arch/hardware.h>
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 62ee86e807..603f011908 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -14,6 +14,7 @@
  * option) any later version.
  */
 
+#include <linux/string.h>
 #include <asm/ppc_sys.h>
 
 int (*ppc_sys_device_fixup) (struct platform_device * pdev);
-- 
cgit v1.2.2


From 481bed454247538e9f57d4ea37b153ccba24ba7b Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Mon, 7 Nov 2005 00:59:47 -0800
Subject: [PATCH] consolidate sys_ptrace()

The sys_ptrace boilerplate code (everything outside the big switch
statement for the arch-specific requests) is shared by most architectures.
This patch moves it to kernel/ptrace.c and leaves the arch-specific code as
arch_ptrace.

Some architectures have a too different ptrace so we have to exclude them.
They continue to keep their implementations.  For sh64 I had to add a
sh64_ptrace wrapper because it does some initialization on the first call.
For um I removed an ifdefed SUBARCH_PTRACE_SPECIAL block, but
SUBARCH_PTRACE_SPECIAL isn't defined anywhere in the tree.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Paul Mackerras <paulus@samba.org>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Acked-By: David Howells <dhowells@redhat.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/arm/kernel/ptrace.c           | 49 +---------------------
 arch/arm26/kernel/ptrace.c         | 49 +---------------------
 arch/cris/arch-v10/kernel/ptrace.c | 51 +----------------------
 arch/cris/arch-v32/kernel/ptrace.c | 51 +----------------------
 arch/frv/kernel/ptrace.c           | 43 +-------------------
 arch/h8300/kernel/ptrace.c         | 39 +-----------------
 arch/i386/kernel/ptrace.c          | 44 +-------------------
 arch/m68k/kernel/ptrace.c          | 47 ++-------------------
 arch/m68knommu/kernel/ptrace.c     | 39 +-----------------
 arch/mips/kernel/ptrace.c          | 55 +++----------------------
 arch/parisc/kernel/ptrace.c        | 50 ++---------------------
 arch/powerpc/kernel/ptrace.c       | 43 +-------------------
 arch/sh/kernel/ptrace.c            | 44 +-------------------
 arch/sh64/kernel/ptrace.c          | 83 +++++++++++++-------------------------
 arch/sh64/kernel/syscalls.S        |  2 +-
 arch/um/kernel/ptrace.c            | 50 +----------------------
 arch/v850/kernel/ptrace.c          | 43 +-------------------
 arch/x86_64/kernel/ptrace.c        | 43 +-------------------
 arch/xtensa/kernel/ptrace.c        | 55 +------------------------
 19 files changed, 62 insertions(+), 818 deletions(-)

(limited to 'arch')

diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9bd8609a29..9a340e790d 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
 
 #endif
 
-static int do_ptrace(int request, struct task_struct *child, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
 	unsigned long tmp;
 	int ret;
@@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
 	return ret;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
-{
-	struct task_struct *child;
-	int ret;
-
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret == 0)
-		ret = do_ptrace(request, child, addr, data);
-
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
-	return ret;
-}
-
 asmlinkage void syscall_trace(int why, struct pt_regs *regs)
 {
 	unsigned long ip;
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index cf7e977d18..4e6b7356a7 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
 			      sizeof(struct user_fp)) ? -EFAULT : 0;
 }
 
-static int do_ptrace(int request, struct task_struct *child, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
 	unsigned long tmp;
 	int ret;
@@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
 	return ret;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
-{
-	struct task_struct *child;
-	int ret;
-
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret == 0)
-		ret = do_ptrace(request, child, addr, data);
-
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
-	return ret;
-}
-
 asmlinkage void syscall_trace(int why, struct pt_regs *regs)
 {
 	unsigned long ip;
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index 130dd214e4..6cbd34a27b 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child)
  * (in user space) where the result of the ptrace call is written (instead of
  * being returned).
  */
-asmlinkage int 
-sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int ret;
 	unsigned long __user *datap = (unsigned long __user *)data;
 
-	lock_kernel();
-	ret = -EPERM;
-	
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	
-	if (child)
-		get_task_struct(child);
-	
-	read_unlock(&tasklist_lock);
-	
-	if (!child)
-		goto out;
-	
-	ret = -EPERM;
-	
-	if (pid == 1)		/* Leave the init process alone! */
-		goto out_tsk;
-	
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-	
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 		/* Read word at location address. */ 
 		case PTRACE_PEEKTEXT:
@@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data)
 			ret = ptrace_request(child, request, addr, data);
 			break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+
 	return ret;
 }
 
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index 208489da2a..5528b83a62 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child)
 }
 
 
-asmlinkage int
-sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int ret;
 	unsigned long __user *datap = (unsigned long __user *)data;
 
-	lock_kernel();
-	ret = -EPERM;
-
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-
-	if (child)
-		get_task_struct(child);
-
-	read_unlock(&tasklist_lock);
-
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-
-	if (pid == 1)		/* Leave the init process alone! */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 		/* Read word at location address. */
 		case PTRACE_PEEKTEXT:
@@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data)
 			ret = ptrace_request(child, request, addr, data);
 			break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+
 	return ret;
 }
 
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index cb335a14a3..f953484e7d 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child)
 	child->thread.frame0->__status |= REG__STATUS_STEP;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	unsigned long tmp;
 	int ret;
 
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 		/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 		ret = -EIO;
 		break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
 	return ret;
 }
 
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index a569fe4aa2..0ff6f79b0f 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -57,43 +57,10 @@ void ptrace_disable(struct task_struct *child)
 	h8300_disable_trace(child);
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int ret;
 
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 		case PTRACE_PEEKDATA: {
@@ -251,10 +218,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 			ret = -EIO;
 			break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
 	return ret;
 }
 
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index efd11f09c9..5ffbb4b7ad 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -354,49 +354,12 @@ ptrace_set_thread_area(struct task_struct *child,
 	return 0;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	struct user * dummy = NULL;
 	int i, ret;
 	unsigned long __user *datap = (unsigned long __user *)data;
 
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -663,10 +626,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+ out_tsk:
 	return ret;
 }
 
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index f7f1d2e5b9..7e54422685 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -121,48 +121,11 @@ void ptrace_disable(struct task_struct *child)
 	child->thread.work.syscall_trace = 0;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	unsigned long tmp;
 	int i, ret = 0;
 
-	lock_kernel();
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED) {
-			ret = -EPERM;
-			goto out;
-		}
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		goto out;
-	}
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (unlikely(!child)) {
-		ret = -ESRCH;
-		goto out;
-	}
-
-	/* you may not mess with init */
-	if (unlikely(pid == 1)) {
-		ret = -EPERM;
-		goto out_tsk;
-	}
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret)
-		goto out_tsk;
-
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT:	/* read word at location addr. */
@@ -317,14 +280,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+
 	return ret;
 out_eio:
-	ret = -EIO;
-	goto out_tsk;
+	return -EIO;
 }
 
 asmlinkage void syscall_trace(void)
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index 621d7b91cc..262ab8c72e 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -101,43 +101,10 @@ void ptrace_disable(struct task_struct *child)
 	put_reg(child, PT_SR, tmp);
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(truct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int ret;
 
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 		/* when I and D space are separate, these will need to be fixed. */
 		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -357,10 +324,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 			ret = -EIO;
 			break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
 	return ret;
 }
 
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f1b0f3e1f9..510da5fda5 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -174,51 +174,10 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data)
 	return 0;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int ret;
 
-#if 0
-	printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
-	       (int) request, (int) pid, (unsigned long) addr,
-	       (unsigned long) data);
-#endif
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		if ((ret = security_ptrace(current->parent, current)))
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -319,7 +278,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 			if (!cpu_has_dsp) {
 				tmp = 0;
 				ret = -EIO;
-				goto out_tsk;
+				goto out;
 			}
 			if (child->thread.dsp.used_dsp) {
 				dregs = __get_dsp_regs(child);
@@ -333,14 +292,14 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 			if (!cpu_has_dsp) {
 				tmp = 0;
 				ret = -EIO;
-				goto out_tsk;
+				goto out;
 			}
 			tmp = child->thread.dsp.dspcontrol;
 			break;
 		default:
 			tmp = 0;
 			ret = -EIO;
-			goto out_tsk;
+			goto out;
 		}
 		ret = put_user(tmp, (unsigned long __user *) data);
 		break;
@@ -495,11 +454,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+ out:
 	return ret;
 }
 
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 18130c3748..b6fe202a62 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -78,52 +78,13 @@ void ptrace_disable(struct task_struct *child)
 	pa_psw(child)->l = 0;
 }
 
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	long ret;
 #ifdef DEBUG_PTRACE
 	long oaddr=addr, odata=data;
 #endif
 
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-
-		ret = security_ptrace(current->parent, current);
-		if (ret) 
-			goto out;
-
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-	ret = -EPERM;
-	if (pid == 1)		/* no messing around with init! */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
@@ -383,11 +344,11 @@ long sys_ptrace(long request, long pid, long addr, long data)
 
 	case PTRACE_GETEVENTMSG:
                 ret = put_user(child->ptrace_message, (unsigned int __user *) data);
-		goto out_tsk;
+		goto out;
 
 	default:
 		ret = ptrace_request(child, request, addr, data);
-		goto out_tsk;
+		goto out;
 	}
 
 out_wake_notrap:
@@ -396,10 +357,7 @@ out_wake:
 	wake_up_process(child);
 	ret = 0;
 out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
-	DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
+	DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
 		request, pid, oaddr, odata, ret);
 	return ret;
 }
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 568ea335d6..3d2abd95c7 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -248,46 +248,10 @@ void ptrace_disable(struct task_struct *child)
 	clear_single_step(child);
 }
 
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int ret = -EPERM;
 
-	lock_kernel();
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -540,10 +504,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+
 	return ret;
 }
 
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 1fbe5a428e..1a8be06519 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -80,48 +80,11 @@ void ptrace_disable(struct task_struct *child)
 	/* nothing to do.. */
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	struct user * dummy = NULL;
 	int ret;
 
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -289,10 +252,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+
 	return ret;
 }
 
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index 71f2eec00b..cd22e94713 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -28,6 +28,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/signal.h>
+#include <linux/syscalls.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -121,61 +122,11 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data)
 	return 0;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
-	extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
-#define WPC_DBRMODE 0x0d104008
-	static int first_call = 1;
 	int ret;
 
-	lock_kernel();
-
-	if (first_call) {
-		/* Set WPC.DBRMODE to 0.  This makes all debug events get
-		 * delivered through RESVEC, i.e. into the handlers in entry.S.
-		 * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
-		 * would normally be left set to 1, which makes debug events get
-		 * delivered through DBRVEC, i.e. into the remote gdb's
-		 * handlers.  This prevents ptrace getting them, and confuses
-		 * the remote gdb.) */
-		printk("DBRMODE set to 0 to permit native debugging\n");
-		poke_real_address_q(WPC_DBRMODE, 0);
-		first_call = 0;
-	}
-
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-			goto out_tsk;
-		}
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -313,13 +264,33 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
 	return ret;
 }
 
+asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
+{
+	extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
+#define WPC_DBRMODE 0x0d104008
+	static int first_call = 1;
+
+	lock_kernel();
+	if (first_call) {
+		/* Set WPC.DBRMODE to 0.  This makes all debug events get
+		 * delivered through RESVEC, i.e. into the handlers in entry.S.
+		 * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
+		 * would normally be left set to 1, which makes debug events get
+		 * delivered through DBRVEC, i.e. into the remote gdb's
+		 * handlers.  This prevents ptrace getting them, and confuses
+		 * the remote gdb.) */
+		printk("DBRMODE set to 0 to permit native debugging\n");
+		poke_real_address_q(WPC_DBRMODE, 0);
+		first_call = 0;
+	}
+	unlock_kernel();
+
+	return sys_ptrace(request, pid, addr, data);
+}
+
 asmlinkage void syscall_trace(void)
 {
 	struct task_struct *tsk = current;
diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S
index a3d037805f..c0079d54c8 100644
--- a/arch/sh64/kernel/syscalls.S
+++ b/arch/sh64/kernel/syscalls.S
@@ -46,7 +46,7 @@ sys_call_table:
 	.long sys_setuid16
 	.long sys_getuid16
 	.long sys_stime			/* 25 */
-	.long sys_ptrace
+	.long sh64_ptrace
 	.long sys_alarm
 	.long sys_fstat
 	.long sys_pause
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 71af4d5038..98e09395c0 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child)
 extern int peek_user(struct task_struct * child, long addr, long data);
 extern int poke_user(struct task_struct * child, long addr, long data);
 
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int i, ret;
 
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-
-		ret = security_ptrace(current->parent, current);
-		if (ret)
- 			goto out;
-
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-#ifdef SUBACH_PTRACE_SPECIAL
-        SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
-#endif
-
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (ret < 0)
-		goto out_tsk;
-
 	switch (request) {
 		/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -282,10 +239,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
- out_tsk:
-	put_task_struct(child);
- out:
-	unlock_kernel();
+
 	return ret;
 }
 
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index d6077ff47d..18492d02aa 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -113,45 +113,10 @@ static int set_single_step (struct task_struct *t, int val)
 	return 1;
 }
 
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int rval;
 
-	lock_kernel();
-
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED) {
-			rval = -EPERM;
-			goto out;
-		}
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		rval = 0;
-		goto out;
-	}
-	rval = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	rval = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		rval = ptrace_attach(child);
-		goto out_tsk;
-	}
-	rval = ptrace_check_attach(child, request == PTRACE_KILL);
-	if (rval < 0)
-		goto out_tsk;
-
 	switch (request) {
 		unsigned long val, copied;
 
@@ -248,11 +213,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
 		rval = -EIO;
 		goto out;
 	}
-
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+ out:
 	return rval;
 }
 
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index bbf64b59a2..a87b6cebe8 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -313,48 +313,11 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
 
 }
 
-asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	long i, ret;
 	unsigned ui;
 
-	/* This lock_kernel fixes a subtle race with suid exec */
-	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-	ret = ptrace_check_attach(child, request == PTRACE_KILL); 
-	if (ret < 0) 
-		goto out_tsk;
-
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -608,10 +571,6 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
 		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
 	return ret;
 }
 
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 14460743de..ab5c4c65b5 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -45,58 +45,10 @@ void ptrace_disable(struct task_struct *child)
 	/* Nothing to do.. */
 }
 
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct task_struct *child;
 	int ret = -EPERM;
 
-	lock_kernel();
-
-#if 0
-	if ((int)request != 1)
-	printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
-	       (int) request, (int) pid, (unsigned long) addr,
-	       (unsigned long) data);
-#endif
-
-	if (request == PTRACE_TRACEME) {
-
-		/* Are we already being traced? */
-
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-
-		if ((ret = security_ptrace(current->parent, current)))
-			goto out;
-
-		/* Set the ptrace bit in the process flags. */
-
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out;
-
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
-		goto out_tsk;
-	}
-
-	if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0)
-		goto out_tsk;
-
 	switch (request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
 	case PTRACE_PEEKDATA:
@@ -375,10 +327,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_request(child, request, addr, data);
 		goto out;
 	}
-out_tsk:
-	put_task_struct(child);
-out:
-	unlock_kernel();
+ out:
 	return ret;
 }
 
-- 
cgit v1.2.2


From 66ff2d0691e00e1e7bfdf398a970310c9a0fe671 Mon Sep 17 00:00:00 2001
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Date: Mon, 7 Nov 2005 01:00:07 -0800
Subject: [PATCH] Kprobes: rearrange preempt_disable/enable() calls

The following set of patches are aimed at improving kprobes scalability.  We
currently serialize kprobe registration, unregistration and handler execution
using a single spinlock - kprobe_lock.

With these changes, kprobe handlers can run without any locks held.  It also
allows for simultaneous kprobe handler executions on different processors as
we now track kprobe execution on a per processor basis.  It is now necessary
that the handlers be re-entrant since handlers can run concurrently on
multiple processors.

All changes have been tested on i386, ia64, ppc64 and x86_64, while sparc64
has been compile tested only.

The patches can be viewed as 3 logical chunks:

patch 1: 	Reorder preempt_(dis/en)able calls
patches 2-7: 	Introduce per_cpu data areas to track kprobe execution
patches 8-9: 	Use RCU to synchronize kprobe (un)registration and handler
		execution.

Thanks to Maneesh Soni, James Keniston and Anil Keshavamurthy for their
review and suggestions. Thanks again to Anil, Hien Nguyen and Kevin Stafford
for testing the patches.

This patch:

Reorder preempt_disable/enable() calls in arch kprobes files in preparation to
introduce locking changes.  No functional changes introduced by this patch.

Signed-off-by: Ananth N Mavinakayahanalli <ananth@in.ibm.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/kprobes.c    | 35 ++++++++++++++++++-----------------
 arch/ia64/kernel/kprobes.c    | 22 ++++++++++++++--------
 arch/ppc64/kernel/kprobes.c   | 11 ++++++-----
 arch/sparc64/kernel/kprobes.c | 25 +++++++++++++------------
 arch/x86_64/kernel/kprobes.c  | 28 ++++++++++++++--------------
 5 files changed, 65 insertions(+), 56 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 6345b430b1..fd35039859 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -158,8 +158,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	kprobe_opcode_t *addr = NULL;
 	unsigned long *lp;
 
-	/* We're in an interrupt, but this is clear and BUG()-safe. */
-	preempt_disable();
 	/* Check if the application is using LDT entry for its code segment and
 	 * calculate the address by reading the base address from the LDT entry.
 	 */
@@ -232,6 +230,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 		goto no_kprobe;
 	}
 
+	/*
+	 * This preempt_disable() matches the preempt_enable_no_resched()
+	 * in post_kprobe_handler()
+	 */
+	preempt_disable();
 	kprobe_status = KPROBE_HIT_ACTIVE;
 	set_current_kprobe(p, regs);
 
@@ -245,7 +248,6 @@ ss_probe:
 	return 1;
 
 no_kprobe:
-	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -313,11 +315,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	unlock_kprobes();
 	preempt_enable_no_resched();
 
-        /*
-         * By returning a non-zero value, we are telling
-         * kprobe_handler() that we have handled unlocking
-         * and re-enabling preemption.
-         */
+	/*
+	 * By returning a non-zero value, we are telling
+	 * kprobe_handler() that we have handled unlocking
+	 * and re-enabling preemption
+	 */
         return 1;
 }
 
@@ -453,29 +455,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 				       unsigned long val, void *data)
 {
 	struct die_args *args = (struct die_args *)data;
+	int ret = NOTIFY_DONE;
+
+	preempt_disable();
 	switch (val) {
 	case DIE_INT3:
 		if (kprobe_handler(args->regs))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	case DIE_DEBUG:
 		if (post_kprobe_handler(args->regs))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	case DIE_GPF:
-		if (kprobe_running() &&
-		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_STOP;
-		break;
 	case DIE_PAGE_FAULT:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	default:
 		break;
 	}
-	return NOTIFY_DONE;
+	preempt_enable();
+	return ret;
 }
 
 int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
@@ -502,7 +504,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 
 void __kprobes jprobe_return(void)
 {
-	preempt_enable_no_resched();
 	asm volatile ("       xchgl   %%ebx,%%esp     \n"
 		      "       int3			\n"
 		      "       .globl jprobe_return_end	\n"
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 471086b808..1e80ec80dd 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -395,7 +395,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
         /*
          * By returning a non-zero value, we are telling
          * kprobe_handler() that we have handled unlocking
-         * and re-enabling preemption.
+	 * and re-enabling preemption
          */
         return 1;
 }
@@ -607,8 +607,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 	struct pt_regs *regs = args->regs;
 	kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
 
-	preempt_disable();
-
 	/* Handle recursion cases */
 	if (kprobe_running()) {
 		p = get_kprobe(addr);
@@ -665,6 +663,11 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 		goto no_kprobe;
 	}
 
+	/*
+	 * This preempt_disable() matches the preempt_enable_no_resched()
+	 * in post_kprobes_handler()
+	 */
+	preempt_disable();
 	kprobe_status = KPROBE_HIT_ACTIVE;
 	set_current_kprobe(p);
 
@@ -682,7 +685,6 @@ ss_probe:
 	return 1;
 
 no_kprobe:
-	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -733,22 +735,26 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 				       unsigned long val, void *data)
 {
 	struct die_args *args = (struct die_args *)data;
+	int ret = NOTIFY_DONE;
+
+	preempt_disable();
 	switch(val) {
 	case DIE_BREAK:
 		if (pre_kprobes_handler(args))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	case DIE_SS:
 		if (post_kprobes_handler(args->regs))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	case DIE_PAGE_FAULT:
 		if (kprobes_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 	default:
 		break;
 	}
-	return NOTIFY_DONE;
+	preempt_enable();
+	return ret;
 }
 
 int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index ed876a5178..6071ee99f5 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -209,6 +209,11 @@ static inline int kprobe_handler(struct pt_regs *regs)
 		goto no_kprobe;
 	}
 
+	/*
+	 * This preempt_disable() matches the preempt_enable_no_resched()
+	 * in post_kprobe_handler().
+	 */
+	preempt_disable();
 	kprobe_status = KPROBE_HIT_ACTIVE;
 	current_kprobe = p;
 	kprobe_saved_msr = regs->msr;
@@ -219,11 +224,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
 ss_probe:
 	prepare_singlestep(p, regs);
 	kprobe_status = KPROBE_HIT_SS;
-	/*
-	 * This preempt_disable() matches the preempt_enable_no_resched()
-	 * in post_kprobe_handler().
-	 */
-	preempt_disable();
 	return 1;
 
 no_kprobe:
@@ -293,6 +293,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	regs->nip = orig_ret_address;
 
 	unlock_kprobes();
+	preempt_enable_no_resched();
 
         /*
          * By returning a non-zero value, we are telling
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 0d66d07c8c..755a0d7d88 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -118,8 +118,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	void *addr = (void *) regs->tpc;
 	int ret = 0;
 
-	preempt_disable();
-
 	if (kprobe_running()) {
 		/* We *are* holding lock here, so this is safe.
 		 * Disarm the probe we just hit, and ignore it.
@@ -171,6 +169,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 		goto no_kprobe;
 	}
 
+	/*
+	 * This preempt_disable() matches the preempt_enable_no_resched()
+	 * in post_kprobes_handler()
+	 */
+	preempt_disable();
 	set_current_kprobe(p, regs);
 	kprobe_status = KPROBE_HIT_ACTIVE;
 	if (p->pre_handler && p->pre_handler(p, regs))
@@ -182,7 +185,6 @@ ss_probe:
 	return 1;
 
 no_kprobe:
-	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -322,29 +324,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 				       unsigned long val, void *data)
 {
 	struct die_args *args = (struct die_args *)data;
+	int ret = NOTIFY_DONE;
+
+	preempt_disable();
 	switch (val) {
 	case DIE_DEBUG:
 		if (kprobe_handler(args->regs))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	case DIE_DEBUG_2:
 		if (post_kprobe_handler(args->regs))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	case DIE_GPF:
-		if (kprobe_running() &&
-		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_STOP;
-		break;
 	case DIE_PAGE_FAULT:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	default:
 		break;
 	}
-	return NOTIFY_DONE;
+	preempt_enable();
+	return ret;
 }
 
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
@@ -396,7 +398,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 
 void __kprobes jprobe_return(void)
 {
-	preempt_enable_no_resched();
 	__asm__ __volatile__(
 		".globl	jprobe_return_trap_instruction\n"
 "jprobe_return_trap_instruction:\n\t"
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 76a28b007b..ebfa2c9241 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -302,9 +302,6 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 	int ret = 0;
 	kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t));
 
-	/* We're in an interrupt, but this is clear and BUG()-safe. */
-	preempt_disable();
-
 	/* Check we're not actually recursing */
 	if (kprobe_running()) {
 		/* We *are* holding lock here, so this is safe.
@@ -372,6 +369,11 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 		goto no_kprobe;
 	}
 
+	/*
+	 * This preempt_disable() matches the preempt_enable_no_resched()
+	 * in post_kprobe_handler()
+	 */
+	preempt_disable();
 	kprobe_status = KPROBE_HIT_ACTIVE;
 	set_current_kprobe(p, regs);
 
@@ -385,7 +387,6 @@ ss_probe:
 	return 1;
 
 no_kprobe:
-	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -456,7 +457,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
         /*
          * By returning a non-zero value, we are telling
          * kprobe_handler() that we have handled unlocking
-         * and re-enabling preemption.
+	 * and re-enabling preemption
          */
         return 1;
 }
@@ -599,29 +600,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 				       unsigned long val, void *data)
 {
 	struct die_args *args = (struct die_args *)data;
+	int ret = NOTIFY_DONE;
+
+	preempt_disable();
 	switch (val) {
 	case DIE_INT3:
 		if (kprobe_handler(args->regs))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	case DIE_DEBUG:
 		if (post_kprobe_handler(args->regs))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	case DIE_GPF:
-		if (kprobe_running() &&
-		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_STOP;
-		break;
 	case DIE_PAGE_FAULT:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_STOP;
+			ret = NOTIFY_STOP;
 		break;
 	default:
 		break;
 	}
-	return NOTIFY_DONE;
+	preempt_enable();
+	return ret;
 }
 
 int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
@@ -647,7 +648,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 
 void __kprobes jprobe_return(void)
 {
-	preempt_enable_no_resched();
 	asm volatile ("       xchg   %%rbx,%%rsp     \n"
 		      "       int3			\n"
 		      "       .globl jprobe_return_end	\n"
-- 
cgit v1.2.2


From 9a0e3a86837ac7542e601c18346102c9d9e65fa5 Mon Sep 17 00:00:00 2001
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Date: Mon, 7 Nov 2005 01:00:08 -0800
Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - i386 changes

I386 changes to track kprobe execution on a per-cpu basis.  We now track the
kprobe state machine independently on each cpu, using an arch specific kprobe
control block.

Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/kprobes.c | 126 +++++++++++++++++++++++++--------------------
 1 file changed, 69 insertions(+), 57 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index fd35039859..99565a6691 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -37,16 +37,11 @@
 #include <asm/kdebug.h>
 #include <asm/desc.h>
 
-static struct kprobe *current_kprobe;
-static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags;
-static struct kprobe *kprobe_prev;
-static unsigned long kprobe_status_prev, kprobe_old_eflags_prev, kprobe_saved_eflags_prev;
-static struct pt_regs jprobe_saved_regs;
-static long *jprobe_saved_esp;
-/* copy of the kernel stack at the probe fire time */
-static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
 void jprobe_return_end(void);
 
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
@@ -91,29 +86,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
 }
 
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	kprobe_prev = current_kprobe;
-	kprobe_status_prev = kprobe_status;
-	kprobe_old_eflags_prev = kprobe_old_eflags;
-	kprobe_saved_eflags_prev = kprobe_saved_eflags;
+	kcb->prev_kprobe.kp = kprobe_running();
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+	kcb->prev_kprobe.old_eflags = kcb->kprobe_old_eflags;
+	kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
 }
 
-static inline void restore_previous_kprobe(void)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	current_kprobe = kprobe_prev;
-	kprobe_status = kprobe_status_prev;
-	kprobe_old_eflags = kprobe_old_eflags_prev;
-	kprobe_saved_eflags = kprobe_saved_eflags_prev;
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
+	kcb->kprobe_old_eflags = kcb->prev_kprobe.old_eflags;
+	kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+				struct kprobe_ctlblk *kcb)
 {
-	current_kprobe = p;
-	kprobe_saved_eflags = kprobe_old_eflags
+	__get_cpu_var(current_kprobe) = p;
+	kcb->kprobe_saved_eflags = kcb->kprobe_old_eflags
 		= (regs->eflags & (TF_MASK | IF_MASK));
 	if (is_IF_modifier(p->opcode))
-		kprobe_saved_eflags &= ~IF_MASK;
+		kcb->kprobe_saved_eflags &= ~IF_MASK;
 }
 
 static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -157,6 +153,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	int ret = 0;
 	kprobe_opcode_t *addr = NULL;
 	unsigned long *lp;
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	/* Check if the application is using LDT entry for its code segment and
 	 * calculate the address by reading the base address from the LDT entry.
@@ -175,10 +172,10 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 		   Disarm the probe we just hit, and ignore it. */
 		p = get_kprobe(addr);
 		if (p) {
-			if (kprobe_status == KPROBE_HIT_SS &&
+			if (kcb->kprobe_status == KPROBE_HIT_SS &&
 				*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
 				regs->eflags &= ~TF_MASK;
-				regs->eflags |= kprobe_saved_eflags;
+				regs->eflags |= kcb->kprobe_saved_eflags;
 				unlock_kprobes();
 				goto no_kprobe;
 			}
@@ -188,14 +185,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 			 * just single step on the instruction of the new probe
 			 * without calling any user handlers.
 			 */
-			save_previous_kprobe();
-			set_current_kprobe(p, regs);
+			save_previous_kprobe(kcb);
+			set_current_kprobe(p, regs, kcb);
 			p->nmissed++;
 			prepare_singlestep(p, regs);
-			kprobe_status = KPROBE_REENTER;
+			kcb->kprobe_status = KPROBE_REENTER;
 			return 1;
 		} else {
-			p = current_kprobe;
+			p = __get_cpu_var(current_kprobe);
 			if (p->break_handler && p->break_handler(p, regs)) {
 				goto ss_probe;
 			}
@@ -235,8 +232,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	 * in post_kprobe_handler()
 	 */
 	preempt_disable();
-	kprobe_status = KPROBE_HIT_ACTIVE;
-	set_current_kprobe(p, regs);
+	set_current_kprobe(p, regs, kcb);
+	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
 	if (p->pre_handler && p->pre_handler(p, regs))
 		/* handler has already set things up, so skip ss setup */
@@ -244,7 +241,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 
 ss_probe:
 	prepare_singlestep(p, regs);
-	kprobe_status = KPROBE_HIT_SS;
+	kcb->kprobe_status = KPROBE_HIT_SS;
 	return 1;
 
 no_kprobe:
@@ -312,6 +309,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
 	regs->eip = orig_ret_address;
 
+	reset_current_kprobe();
 	unlock_kprobes();
 	preempt_enable_no_resched();
 
@@ -345,7 +343,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
  * that is atop the stack is the address following the copied instruction.
  * We need to make it the address following the original instruction.
  */
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p,
+		struct pt_regs *regs, struct kprobe_ctlblk *kcb)
 {
 	unsigned long *tos = (unsigned long *)&regs->esp;
 	unsigned long next_eip = 0;
@@ -355,7 +354,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 	switch (p->ainsn.insn[0]) {
 	case 0x9c:		/* pushfl */
 		*tos &= ~(TF_MASK | IF_MASK);
-		*tos |= kprobe_old_eflags;
+		*tos |= kcb->kprobe_old_eflags;
 		break;
 	case 0xc3:		/* ret/lret */
 	case 0xcb:
@@ -400,22 +399,26 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
  */
 static inline int post_kprobe_handler(struct pt_regs *regs)
 {
-	if (!kprobe_running())
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
 		return 0;
 
-	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
-		kprobe_status = KPROBE_HIT_SSDONE;
-		current_kprobe->post_handler(current_kprobe, regs, 0);
+	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		cur->post_handler(cur, regs, 0);
 	}
 
-	resume_execution(current_kprobe, regs);
-	regs->eflags |= kprobe_saved_eflags;
+	resume_execution(cur, regs, kcb);
+	regs->eflags |= kcb->kprobe_saved_eflags;
 
 	/*Restore back the original saved kprobes variables and continue. */
-	if (kprobe_status == KPROBE_REENTER) {
-		restore_previous_kprobe();
+	if (kcb->kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe(kcb);
 		goto out;
 	}
+	reset_current_kprobe();
 	unlock_kprobes();
 out:
 	preempt_enable_no_resched();
@@ -434,14 +437,17 @@ out:
 /* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
-	if (current_kprobe->fault_handler
-	    && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
 		return 1;
 
-	if (kprobe_status & KPROBE_HIT_SS) {
-		resume_execution(current_kprobe, regs);
-		regs->eflags |= kprobe_old_eflags;
+	if (kcb->kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(cur, regs, kcb);
+		regs->eflags |= kcb->kprobe_old_eflags;
 
+		reset_current_kprobe();
 		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
@@ -484,10 +490,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 	unsigned long addr;
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	jprobe_saved_regs = *regs;
-	jprobe_saved_esp = &regs->esp;
-	addr = (unsigned long)jprobe_saved_esp;
+	kcb->jprobe_saved_regs = *regs;
+	kcb->jprobe_saved_esp = &regs->esp;
+	addr = (unsigned long)(kcb->jprobe_saved_esp);
 
 	/*
 	 * TBD: As Linus pointed out, gcc assumes that the callee
@@ -496,7 +503,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 	 * we also save and restore enough stack bytes to cover
 	 * the argument area.
 	 */
-	memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr));
+	memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
+			MIN_STACK_SIZE(addr));
 	regs->eflags &= ~IF_MASK;
 	regs->eip = (unsigned long)(jp->entry);
 	return 1;
@@ -504,34 +512,38 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 
 void __kprobes jprobe_return(void)
 {
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
 	asm volatile ("       xchgl   %%ebx,%%esp     \n"
 		      "       int3			\n"
 		      "       .globl jprobe_return_end	\n"
 		      "       jprobe_return_end:	\n"
 		      "       nop			\n"::"b"
-		      (jprobe_saved_esp):"memory");
+		      (kcb->jprobe_saved_esp):"memory");
 }
 
 int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 	u8 *addr = (u8 *) (regs->eip - 1);
-	unsigned long stack_addr = (unsigned long)jprobe_saved_esp;
+	unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_esp);
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 
 	if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
-		if (&regs->esp != jprobe_saved_esp) {
+		if (&regs->esp != kcb->jprobe_saved_esp) {
 			struct pt_regs *saved_regs =
-			    container_of(jprobe_saved_esp, struct pt_regs, esp);
+			    container_of(kcb->jprobe_saved_esp,
+					    struct pt_regs, esp);
 			printk("current esp %p does not match saved esp %p\n",
-			       &regs->esp, jprobe_saved_esp);
+			       &regs->esp, kcb->jprobe_saved_esp);
 			printk("Saved registers for jprobe %p\n", jp);
 			show_registers(saved_regs);
 			printk("Current registers\n");
 			show_registers(regs);
 			BUG();
 		}
-		*regs = jprobe_saved_regs;
-		memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack,
+		*regs = kcb->jprobe_saved_regs;
+		memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
 		       MIN_STACK_SIZE(stack_addr));
 		return 1;
 	}
-- 
cgit v1.2.2


From 8a5c4dc5e5d72b7802f5647082ccf3861a94f013 Mon Sep 17 00:00:00 2001
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Date: Mon, 7 Nov 2005 01:00:09 -0800
Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - ia64 changes

IA64 changes to track kprobe execution on a per-cpu basis.  We now track the
kprobe state machine independently on each cpu using an arch specific kprobe
control block.

Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ia64/kernel/kprobes.c | 83 +++++++++++++++++++++++++---------------------
 1 file changed, 45 insertions(+), 38 deletions(-)

(limited to 'arch')

diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 1e80ec80dd..17e70b1b8d 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -38,13 +38,8 @@
 
 extern void jprobe_inst_return(void);
 
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE	0x00000001
-#define KPROBE_HIT_SS		0x00000002
-
-static struct kprobe *current_kprobe, *kprobe_prev;
-static unsigned long kprobe_status, kprobe_status_prev;
-static struct pt_regs jprobe_saved_regs;
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 enum instruction_type {A, I, M, F, B, L, X, u};
 static enum instruction_type bundle_encoding[32][3] = {
@@ -313,21 +308,22 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
 	return 0;
 }
 
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	kprobe_prev = current_kprobe;
-	kprobe_status_prev = kprobe_status;
+	kcb->prev_kprobe.kp = kprobe_running();
+	kcb->prev_kprobe.status = kcb->kprobe_status;
 }
 
-static inline void restore_previous_kprobe(void)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	current_kprobe = kprobe_prev;
-	kprobe_status = kprobe_status_prev;
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
 }
 
-static inline void set_current_kprobe(struct kprobe *p)
+static inline void set_current_kprobe(struct kprobe *p,
+			struct kprobe_ctlblk *kcb)
 {
-	current_kprobe = p;
+	__get_cpu_var(current_kprobe) = p;
 }
 
 static void kretprobe_trampoline(void)
@@ -389,6 +385,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
 	regs->cr_iip = orig_ret_address;
 
+	reset_current_kprobe();
 	unlock_kprobes();
 	preempt_enable_no_resched();
 
@@ -606,12 +603,13 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 	int ret = 0;
 	struct pt_regs *regs = args->regs;
 	kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	/* Handle recursion cases */
 	if (kprobe_running()) {
 		p = get_kprobe(addr);
 		if (p) {
-			if ( (kprobe_status == KPROBE_HIT_SS) &&
+			if ((kcb->kprobe_status == KPROBE_HIT_SS) &&
 	 		     (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
   				ia64_psr(regs)->ss = 0;
 				unlock_kprobes();
@@ -623,17 +621,17 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 			 * just single step on the instruction of the new probe
 			 * without calling any user handlers.
 			 */
-			save_previous_kprobe();
-			set_current_kprobe(p);
+			save_previous_kprobe(kcb);
+			set_current_kprobe(p, kcb);
 			p->nmissed++;
 			prepare_ss(p, regs);
-			kprobe_status = KPROBE_REENTER;
+			kcb->kprobe_status = KPROBE_REENTER;
 			return 1;
 		} else if (args->err == __IA64_BREAK_JPROBE) {
 			/*
 			 * jprobe instrumented function just completed
 			 */
-			p = current_kprobe;
+			p = __get_cpu_var(current_kprobe);
 			if (p->break_handler && p->break_handler(p, regs)) {
 				goto ss_probe;
 			}
@@ -668,8 +666,8 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 	 * in post_kprobes_handler()
 	 */
 	preempt_disable();
-	kprobe_status = KPROBE_HIT_ACTIVE;
-	set_current_kprobe(p);
+	set_current_kprobe(p, kcb);
+	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
 	if (p->pre_handler && p->pre_handler(p, regs))
 		/*
@@ -681,7 +679,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 
 ss_probe:
 	prepare_ss(p, regs);
-	kprobe_status = KPROBE_HIT_SS;
+	kcb->kprobe_status = KPROBE_HIT_SS;
 	return 1;
 
 no_kprobe:
@@ -690,22 +688,25 @@ no_kprobe:
 
 static int __kprobes post_kprobes_handler(struct pt_regs *regs)
 {
-	if (!kprobe_running())
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
 		return 0;
 
-	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
-		kprobe_status = KPROBE_HIT_SSDONE;
-		current_kprobe->post_handler(current_kprobe, regs, 0);
+	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		cur->post_handler(cur, regs, 0);
 	}
 
-	resume_execution(current_kprobe, regs);
+	resume_execution(cur, regs);
 
 	/*Restore back the original saved kprobes variables and continue. */
-	if (kprobe_status == KPROBE_REENTER) {
-		restore_previous_kprobe();
+	if (kcb->kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe(kcb);
 		goto out;
 	}
-
+	reset_current_kprobe();
 	unlock_kprobes();
 
 out:
@@ -715,15 +716,18 @@ out:
 
 static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
 {
-	if (!kprobe_running())
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
 		return 0;
 
-	if (current_kprobe->fault_handler &&
-	    current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
 		return 1;
 
-	if (kprobe_status & KPROBE_HIT_SS) {
-		resume_execution(current_kprobe, regs);
+	if (kcb->kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(cur, regs);
+		reset_current_kprobe();
 		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
@@ -761,9 +765,10 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 	unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	/* save architectural state */
-	jprobe_saved_regs = *regs;
+	kcb->jprobe_saved_regs = *regs;
 
 	/* after rfi, execute the jprobe instrumented function */
 	regs->cr_iip = addr & ~0xFULL;
@@ -781,7 +786,9 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 
 int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
-	*regs = jprobe_saved_regs;
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	*regs = kcb->jprobe_saved_regs;
 	return 1;
 }
 
-- 
cgit v1.2.2


From 0dc036c91ac11b2b76bb91b59d8c7af919aa4a8d Mon Sep 17 00:00:00 2001
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Date: Mon, 7 Nov 2005 01:00:10 -0800
Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - ppc64 changes

PPC64 changes to track kprobe execution on a per-cpu basis.  We now track the
kprobe state machine independently on each cpu using an arch specific kprobe
control block.

Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc64/kernel/kprobes.c | 94 ++++++++++++++++++++++++++-------------------
 1 file changed, 54 insertions(+), 40 deletions(-)

(limited to 'arch')

diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 6071ee99f5..3f89f3e558 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -37,12 +37,8 @@
 #include <asm/sstep.h>
 
 static DECLARE_MUTEX(kprobe_mutex);
-
-static struct kprobe *current_kprobe;
-static unsigned long kprobe_status, kprobe_saved_msr;
-static struct kprobe *kprobe_prev;
-static unsigned long kprobe_status_prev, kprobe_saved_msr_prev;
-static struct pt_regs jprobe_saved_regs;
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
@@ -108,18 +104,25 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 		regs->nip = (unsigned long)p->ainsn.insn;
 }
 
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+	kcb->prev_kprobe.kp = kprobe_running();
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+	kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
+}
+
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	kprobe_prev = current_kprobe;
-	kprobe_status_prev = kprobe_status;
-	kprobe_saved_msr_prev = kprobe_saved_msr;
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
+	kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
 }
 
-static inline void restore_previous_kprobe(void)
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+				struct kprobe_ctlblk *kcb)
 {
-	current_kprobe = kprobe_prev;
-	kprobe_status = kprobe_status_prev;
-	kprobe_saved_msr = kprobe_saved_msr_prev;
+	__get_cpu_var(current_kprobe) = p;
+	kcb->kprobe_saved_msr = regs->msr;
 }
 
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
@@ -145,6 +148,7 @@ static inline int kprobe_handler(struct pt_regs *regs)
 	struct kprobe *p;
 	int ret = 0;
 	unsigned int *addr = (unsigned int *)regs->nip;
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	/* Check we're not actually recursing */
 	if (kprobe_running()) {
@@ -153,10 +157,10 @@ static inline int kprobe_handler(struct pt_regs *regs)
 		p = get_kprobe(addr);
 		if (p) {
 			kprobe_opcode_t insn = *p->ainsn.insn;
-			if (kprobe_status == KPROBE_HIT_SS &&
+			if (kcb->kprobe_status == KPROBE_HIT_SS &&
 					is_trap(insn)) {
 				regs->msr &= ~MSR_SE;
-				regs->msr |= kprobe_saved_msr;
+				regs->msr |= kcb->kprobe_saved_msr;
 				unlock_kprobes();
 				goto no_kprobe;
 			}
@@ -166,15 +170,15 @@ static inline int kprobe_handler(struct pt_regs *regs)
 			 * just single step on the instruction of the new probe
 			 * without calling any user handlers.
 			 */
-			save_previous_kprobe();
-			current_kprobe = p;
-			kprobe_saved_msr = regs->msr;
+			save_previous_kprobe(kcb);
+			set_current_kprobe(p, regs, kcb);
+			kcb->kprobe_saved_msr = regs->msr;
 			p->nmissed++;
 			prepare_singlestep(p, regs);
-			kprobe_status = KPROBE_REENTER;
+			kcb->kprobe_status = KPROBE_REENTER;
 			return 1;
 		} else {
-			p = current_kprobe;
+			p = __get_cpu_var(current_kprobe);
 			if (p->break_handler && p->break_handler(p, regs)) {
 				goto ss_probe;
 			}
@@ -214,16 +218,15 @@ static inline int kprobe_handler(struct pt_regs *regs)
 	 * in post_kprobe_handler().
 	 */
 	preempt_disable();
-	kprobe_status = KPROBE_HIT_ACTIVE;
-	current_kprobe = p;
-	kprobe_saved_msr = regs->msr;
+	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+	set_current_kprobe(p, regs, kcb);
 	if (p->pre_handler && p->pre_handler(p, regs))
 		/* handler has already set things up, so skip ss setup */
 		return 1;
 
 ss_probe:
 	prepare_singlestep(p, regs);
-	kprobe_status = KPROBE_HIT_SS;
+	kcb->kprobe_status = KPROBE_HIT_SS;
 	return 1;
 
 no_kprobe:
@@ -292,6 +295,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
 	regs->nip = orig_ret_address;
 
+	reset_current_kprobe();
 	unlock_kprobes();
 	preempt_enable_no_resched();
 
@@ -324,22 +328,26 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 
 static inline int post_kprobe_handler(struct pt_regs *regs)
 {
-	if (!kprobe_running())
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
 		return 0;
 
-	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
-		kprobe_status = KPROBE_HIT_SSDONE;
-		current_kprobe->post_handler(current_kprobe, regs, 0);
+	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		cur->post_handler(cur, regs, 0);
 	}
 
-	resume_execution(current_kprobe, regs);
-	regs->msr |= kprobe_saved_msr;
+	resume_execution(cur, regs);
+	regs->msr |= kcb->kprobe_saved_msr;
 
 	/*Restore back the original saved kprobes variables and continue. */
-	if (kprobe_status == KPROBE_REENTER) {
-		restore_previous_kprobe();
+	if (kcb->kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe(kcb);
 		goto out;
 	}
+	reset_current_kprobe();
 	unlock_kprobes();
 out:
 	preempt_enable_no_resched();
@@ -358,15 +366,18 @@ out:
 /* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
-	if (current_kprobe->fault_handler
-	    && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
 		return 1;
 
-	if (kprobe_status & KPROBE_HIT_SS) {
-		resume_execution(current_kprobe, regs);
+	if (kcb->kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(cur, regs);
 		regs->msr &= ~MSR_SE;
-		regs->msr |= kprobe_saved_msr;
+		regs->msr |= kcb->kprobe_saved_msr;
 
+		reset_current_kprobe();
 		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
@@ -411,8 +422,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
+	memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs));
 
 	/* setup return addr to the jprobe handler routine */
 	regs->nip = (unsigned long)(((func_descr_t *)jp->entry)->entry);
@@ -432,12 +444,14 @@ void __kprobes jprobe_return_end(void)
 
 int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
 	/*
 	 * FIXME - we should ideally be validating that we got here 'cos
 	 * of the "trap" in jprobe_return() above, before restoring the
 	 * saved regs...
 	 */
-	memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
+	memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
 	return 1;
 }
 
-- 
cgit v1.2.2


From f215d985e936cf493959b365a10593b6d5f80447 Mon Sep 17 00:00:00 2001
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Date: Mon, 7 Nov 2005 01:00:11 -0800
Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - sparc64 changes

Sparc64 changes to track kprobe execution on a per-cpu basis.  We now track
the kprobe state machine independently on each cpu using an arch specific
kprobe control block.

Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/sparc64/kernel/kprobes.c | 131 +++++++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 64 deletions(-)

(limited to 'arch')

diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 755a0d7d88..b95984154d 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -38,6 +38,9 @@
  * - Mark that we are no longer actively in a kprobe.
  */
 
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
 	return 0;
@@ -66,46 +69,39 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
 }
 
-static struct kprobe *current_kprobe;
-static unsigned long current_kprobe_orig_tnpc;
-static unsigned long current_kprobe_orig_tstate_pil;
-static unsigned int kprobe_status;
-static struct kprobe *kprobe_prev;
-static unsigned long kprobe_orig_tnpc_prev;
-static unsigned long kprobe_orig_tstate_pil_prev;
-static unsigned int kprobe_status_prev;
-
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	kprobe_status_prev = kprobe_status;
-	kprobe_orig_tnpc_prev = current_kprobe_orig_tnpc;
-	kprobe_orig_tstate_pil_prev = current_kprobe_orig_tstate_pil;
-	kprobe_prev = current_kprobe;
+	kcb->prev_kprobe.kp = kprobe_running();
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+	kcb->prev_kprobe.orig_tnpc = kcb->kprobe_orig_tnpc;
+	kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil;
 }
 
-static inline void restore_previous_kprobe(void)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	kprobe_status = kprobe_status_prev;
-	current_kprobe_orig_tnpc = kprobe_orig_tnpc_prev;
-	current_kprobe_orig_tstate_pil = kprobe_orig_tstate_pil_prev;
-	current_kprobe = kprobe_prev;
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
+	kcb->kprobe_orig_tnpc = kcb->prev_kprobe.orig_tnpc;
+	kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+				struct kprobe_ctlblk *kcb)
 {
-	current_kprobe_orig_tnpc = regs->tnpc;
-	current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
-	current_kprobe = p;
+	__get_cpu_var(current_kprobe) = p;
+	kcb->kprobe_orig_tnpc = regs->tnpc;
+	kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
+			struct kprobe_ctlblk *kcb)
 {
 	regs->tstate |= TSTATE_PIL;
 
 	/*single step inline, if it a breakpoint instruction*/
 	if (p->opcode == BREAKPOINT_INSTRUCTION) {
 		regs->tpc = (unsigned long) p->addr;
-		regs->tnpc = current_kprobe_orig_tnpc;
+		regs->tnpc = kcb->kprobe_orig_tnpc;
 	} else {
 		regs->tpc = (unsigned long) &p->ainsn.insn[0];
 		regs->tnpc = (unsigned long) &p->ainsn.insn[1];
@@ -117,6 +113,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	struct kprobe *p;
 	void *addr = (void *) regs->tpc;
 	int ret = 0;
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	if (kprobe_running()) {
 		/* We *are* holding lock here, so this is safe.
@@ -124,9 +121,9 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 		 */
 		p = get_kprobe(addr);
 		if (p) {
-			if (kprobe_status == KPROBE_HIT_SS) {
+			if (kcb->kprobe_status == KPROBE_HIT_SS) {
 				regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
-					current_kprobe_orig_tstate_pil);
+					kcb->kprobe_orig_tstate_pil);
 				unlock_kprobes();
 				goto no_kprobe;
 			}
@@ -136,14 +133,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 			 * just single step on the instruction of the new probe
 			 * without calling any user handlers.
 			 */
-			save_previous_kprobe();
-			set_current_kprobe(p, regs);
+			save_previous_kprobe(kcb);
+			set_current_kprobe(p, regs, kcb);
 			p->nmissed++;
-			kprobe_status = KPROBE_REENTER;
-			prepare_singlestep(p, regs);
+			kcb->kprobe_status = KPROBE_REENTER;
+			prepare_singlestep(p, regs, kcb);
 			return 1;
 		} else {
-			p = current_kprobe;
+			p = __get_cpu_var(current_kprobe);
 			if (p->break_handler && p->break_handler(p, regs))
 				goto ss_probe;
 		}
@@ -174,14 +171,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	 * in post_kprobes_handler()
 	 */
 	preempt_disable();
-	set_current_kprobe(p, regs);
-	kprobe_status = KPROBE_HIT_ACTIVE;
+	set_current_kprobe(p, regs, kcb);
+	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 	if (p->pre_handler && p->pre_handler(p, regs))
 		return 1;
 
 ss_probe:
-	prepare_singlestep(p, regs);
-	kprobe_status = KPROBE_HIT_SS;
+	prepare_singlestep(p, regs, kcb);
+	kcb->kprobe_status = KPROBE_HIT_SS;
 	return 1;
 
 no_kprobe:
@@ -262,11 +259,12 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
  * This function prepares to return from the post-single-step
  * breakpoint trap.
  */
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p,
+		struct pt_regs *regs, struct kprobe_ctlblk *kcb)
 {
 	u32 insn = p->ainsn.insn[0];
 
-	regs->tpc = current_kprobe_orig_tnpc;
+	regs->tpc = kcb->kprobe_orig_tnpc;
 	regs->tnpc = relbranch_fixup(insn,
 				     (unsigned long) p->addr,
 				     (unsigned long) &p->ainsn.insn[0],
@@ -274,26 +272,30 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 	retpc_fixup(regs, insn, (unsigned long) p->addr);
 
 	regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
-			current_kprobe_orig_tstate_pil);
+			kcb->kprobe_orig_tstate_pil);
 }
 
 static inline int post_kprobe_handler(struct pt_regs *regs)
 {
-	if (!kprobe_running())
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
 		return 0;
 
-	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
-		kprobe_status = KPROBE_HIT_SSDONE;
-		current_kprobe->post_handler(current_kprobe, regs, 0);
+	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		cur->post_handler(cur, regs, 0);
 	}
 
-	resume_execution(current_kprobe, regs);
+	resume_execution(cur, regs, kcb);
 
 	/*Restore back the original saved kprobes variables and continue. */
-	if (kprobe_status == KPROBE_REENTER) {
-		restore_previous_kprobe();
+	if (kcb->kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe(kcb);
 		goto out;
 	}
+	reset_current_kprobe();
 	unlock_kprobes();
 out:
 	preempt_enable_no_resched();
@@ -304,13 +306,16 @@ out:
 /* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
-	if (current_kprobe->fault_handler
-	    && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
 		return 1;
 
-	if (kprobe_status & KPROBE_HIT_SS) {
-		resume_execution(current_kprobe, regs);
+	if (kcb->kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(cur, regs, kcb);
 
+		reset_current_kprobe();
 		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
@@ -370,24 +375,21 @@ asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 }
 
 /* Jprobes support.  */
-static struct pt_regs jprobe_saved_regs;
-static struct pt_regs *jprobe_saved_regs_location;
-static struct sparc_stackf jprobe_saved_stack;
-
 int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	jprobe_saved_regs_location = regs;
-	memcpy(&jprobe_saved_regs, regs, sizeof(*regs));
+	kcb->jprobe_saved_regs_location = regs;
+	memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs));
 
 	/* Save a whole stack frame, this gets arguments
 	 * pushed onto the stack after using up all the
 	 * arg registers.
 	 */
-	memcpy(&jprobe_saved_stack,
+	memcpy(&(kcb->jprobe_saved_stack),
 	       (char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
-	       sizeof(jprobe_saved_stack));
+	       sizeof(kcb->jprobe_saved_stack));
 
 	regs->tpc  = (unsigned long) jp->entry;
 	regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
@@ -411,14 +413,15 @@ extern void __show_regs(struct pt_regs * regs);
 int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	u32 *addr = (u32 *) regs->tpc;
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	if (addr == (u32 *) jprobe_return_trap_instruction) {
-		if (jprobe_saved_regs_location != regs) {
+		if (kcb->jprobe_saved_regs_location != regs) {
 			printk("JPROBE: Current regs (%p) does not match "
 			       "saved regs (%p).\n",
-			       regs, jprobe_saved_regs_location);
+			       regs, kcb->jprobe_saved_regs_location);
 			printk("JPROBE: Saved registers\n");
-			__show_regs(jprobe_saved_regs_location);
+			__show_regs(kcb->jprobe_saved_regs_location);
 			printk("JPROBE: Current registers\n");
 			__show_regs(regs);
 			BUG();
@@ -427,11 +430,11 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 		 * first so that UREG_FP is the original one for
 		 * the stack frame restore.
 		 */
-		memcpy(regs, &jprobe_saved_regs, sizeof(*regs));
+		memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs));
 
 		memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
-		       &jprobe_saved_stack,
-		       sizeof(jprobe_saved_stack));
+		       &(kcb->jprobe_saved_stack),
+		       sizeof(kcb->jprobe_saved_stack));
 
 		return 1;
 	}
-- 
cgit v1.2.2


From e7a510f92c1e482a7db05afd3cb84af1f4cfe0bc Mon Sep 17 00:00:00 2001
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Date: Mon, 7 Nov 2005 01:00:12 -0800
Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - x86_64 changes

x86_64 changes to track kprobe execution on a per-cpu basis.  We now track the
kprobe state machine independently on each cpu using a arch specific kprobe
control block.

Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/x86_64/kernel/kprobes.c | 129 +++++++++++++++++++++++--------------------
 1 file changed, 70 insertions(+), 59 deletions(-)

(limited to 'arch')

diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index ebfa2c9241..6cb40d133b 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -44,17 +44,10 @@
 #include <asm/kdebug.h>
 
 static DECLARE_MUTEX(kprobe_mutex);
-
-static struct kprobe *current_kprobe;
-static unsigned long kprobe_status, kprobe_old_rflags, kprobe_saved_rflags;
-static struct kprobe *kprobe_prev;
-static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev;
-static struct pt_regs jprobe_saved_regs;
-static long *jprobe_saved_rsp;
 void jprobe_return_end(void);
 
-/* copy of the kernel stack at the probe fire time */
-static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 /*
  * returns non-zero if opcode modifies the interrupt flag.
@@ -236,29 +229,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
 	up(&kprobe_mutex);
 }
 
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	kprobe_prev = current_kprobe;
-	kprobe_status_prev = kprobe_status;
-	kprobe_old_rflags_prev = kprobe_old_rflags;
-	kprobe_saved_rflags_prev = kprobe_saved_rflags;
+	kcb->prev_kprobe.kp = kprobe_running();
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+	kcb->prev_kprobe.old_rflags = kcb->kprobe_old_rflags;
+	kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags;
 }
 
-static inline void restore_previous_kprobe(void)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	current_kprobe = kprobe_prev;
-	kprobe_status = kprobe_status_prev;
-	kprobe_old_rflags = kprobe_old_rflags_prev;
-	kprobe_saved_rflags = kprobe_saved_rflags_prev;
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
+	kcb->kprobe_old_rflags = kcb->prev_kprobe.old_rflags;
+	kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+				struct kprobe_ctlblk *kcb)
 {
-	current_kprobe = p;
-	kprobe_saved_rflags = kprobe_old_rflags
+	__get_cpu_var(current_kprobe) = p;
+	kcb->kprobe_saved_rflags = kcb->kprobe_old_rflags
 		= (regs->eflags & (TF_MASK | IF_MASK));
 	if (is_IF_modifier(p->ainsn.insn))
-		kprobe_saved_rflags &= ~IF_MASK;
+		kcb->kprobe_saved_rflags &= ~IF_MASK;
 }
 
 static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -301,6 +295,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 	struct kprobe *p;
 	int ret = 0;
 	kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t));
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	/* Check we're not actually recursing */
 	if (kprobe_running()) {
@@ -308,13 +303,13 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 		   Disarm the probe we just hit, and ignore it. */
 		p = get_kprobe(addr);
 		if (p) {
-			if (kprobe_status == KPROBE_HIT_SS &&
+			if (kcb->kprobe_status == KPROBE_HIT_SS &&
 				*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
 				regs->eflags &= ~TF_MASK;
-				regs->eflags |= kprobe_saved_rflags;
+				regs->eflags |= kcb->kprobe_saved_rflags;
 				unlock_kprobes();
 				goto no_kprobe;
-			} else if (kprobe_status == KPROBE_HIT_SSDONE) {
+			} else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) {
 				/* TODO: Provide re-entrancy from
 				 * post_kprobes_handler() and avoid exception
 				 * stack corruption while single-stepping on
@@ -322,6 +317,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 				 */
 				arch_disarm_kprobe(p);
 				regs->rip = (unsigned long)p->addr;
+				reset_current_kprobe();
 				ret = 1;
 			} else {
 				/* We have reentered the kprobe_handler(), since
@@ -331,15 +327,15 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 				 * of the new probe without calling any user
 				 * handlers.
 				 */
-				save_previous_kprobe();
-				set_current_kprobe(p, regs);
+				save_previous_kprobe(kcb);
+				set_current_kprobe(p, regs, kcb);
 				p->nmissed++;
 				prepare_singlestep(p, regs);
-				kprobe_status = KPROBE_REENTER;
+				kcb->kprobe_status = KPROBE_REENTER;
 				return 1;
 			}
 		} else {
-			p = current_kprobe;
+			p = __get_cpu_var(current_kprobe);
 			if (p->break_handler && p->break_handler(p, regs)) {
 				goto ss_probe;
 			}
@@ -374,8 +370,8 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 	 * in post_kprobe_handler()
 	 */
 	preempt_disable();
-	kprobe_status = KPROBE_HIT_ACTIVE;
-	set_current_kprobe(p, regs);
+	set_current_kprobe(p, regs, kcb);
+	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
 	if (p->pre_handler && p->pre_handler(p, regs))
 		/* handler has already set things up, so skip ss setup */
@@ -383,7 +379,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 
 ss_probe:
 	prepare_singlestep(p, regs);
-	kprobe_status = KPROBE_HIT_SS;
+	kcb->kprobe_status = KPROBE_HIT_SS;
 	return 1;
 
 no_kprobe:
@@ -451,6 +447,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
 	regs->rip = orig_ret_address;
 
+	reset_current_kprobe();
 	unlock_kprobes();
 	preempt_enable_no_resched();
 
@@ -484,7 +481,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
  * that is atop the stack is the address following the copied instruction.
  * We need to make it the address following the original instruction.
  */
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p,
+		struct pt_regs *regs, struct kprobe_ctlblk *kcb)
 {
 	unsigned long *tos = (unsigned long *)regs->rsp;
 	unsigned long next_rip = 0;
@@ -499,7 +497,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 	switch (*insn) {
 	case 0x9c:		/* pushfl */
 		*tos &= ~(TF_MASK | IF_MASK);
-		*tos |= kprobe_old_rflags;
+		*tos |= kcb->kprobe_old_rflags;
 		break;
 	case 0xc3:		/* ret/lret */
 	case 0xcb:
@@ -544,24 +542,28 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
  */
 int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
-	if (!kprobe_running())
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
 		return 0;
 
-	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
-		kprobe_status = KPROBE_HIT_SSDONE;
-		current_kprobe->post_handler(current_kprobe, regs, 0);
+	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		cur->post_handler(cur, regs, 0);
 	}
 
-	resume_execution(current_kprobe, regs);
-	regs->eflags |= kprobe_saved_rflags;
+	resume_execution(cur, regs, kcb);
+	regs->eflags |= kcb->kprobe_saved_rflags;
 
 	/* Restore the original saved kprobes variables and continue. */
-	if (kprobe_status == KPROBE_REENTER) {
-		restore_previous_kprobe();
+	if (kcb->kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe(kcb);
 		goto out;
 	} else {
 		unlock_kprobes();
 	}
+	reset_current_kprobe();
 out:
 	preempt_enable_no_resched();
 
@@ -579,14 +581,17 @@ out:
 /* Interrupts disabled, kprobe_lock held. */
 int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
-	if (current_kprobe->fault_handler
-	    && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
 		return 1;
 
-	if (kprobe_status & KPROBE_HIT_SS) {
-		resume_execution(current_kprobe, regs);
-		regs->eflags |= kprobe_old_rflags;
+	if (kcb->kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(cur, regs, kcb);
+		regs->eflags |= kcb->kprobe_old_rflags;
 
+		reset_current_kprobe();
 		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
@@ -629,10 +634,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 	unsigned long addr;
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	jprobe_saved_regs = *regs;
-	jprobe_saved_rsp = (long *) regs->rsp;
-	addr = (unsigned long)jprobe_saved_rsp;
+	kcb->jprobe_saved_regs = *regs;
+	kcb->jprobe_saved_rsp = (long *) regs->rsp;
+	addr = (unsigned long)(kcb->jprobe_saved_rsp);
 	/*
 	 * As Linus pointed out, gcc assumes that the callee
 	 * owns the argument space and could overwrite it, e.g.
@@ -640,7 +646,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 	 * we also save and restore enough stack bytes to cover
 	 * the argument area.
 	 */
-	memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr));
+	memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
+			MIN_STACK_SIZE(addr));
 	regs->eflags &= ~IF_MASK;
 	regs->rip = (unsigned long)(jp->entry);
 	return 1;
@@ -648,34 +655,38 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 
 void __kprobes jprobe_return(void)
 {
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
 	asm volatile ("       xchg   %%rbx,%%rsp     \n"
 		      "       int3			\n"
 		      "       .globl jprobe_return_end	\n"
 		      "       jprobe_return_end:	\n"
 		      "       nop			\n"::"b"
-		      (jprobe_saved_rsp):"memory");
+		      (kcb->jprobe_saved_rsp):"memory");
 }
 
 int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 	u8 *addr = (u8 *) (regs->rip - 1);
-	unsigned long stack_addr = (unsigned long)jprobe_saved_rsp;
+	unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_rsp);
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 
 	if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
-		if ((long *)regs->rsp != jprobe_saved_rsp) {
+		if ((long *)regs->rsp != kcb->jprobe_saved_rsp) {
 			struct pt_regs *saved_regs =
-			    container_of(jprobe_saved_rsp, struct pt_regs, rsp);
+			    container_of(kcb->jprobe_saved_rsp,
+					    struct pt_regs, rsp);
 			printk("current rsp %p does not match saved rsp %p\n",
-			       (long *)regs->rsp, jprobe_saved_rsp);
+			       (long *)regs->rsp, kcb->jprobe_saved_rsp);
 			printk("Saved registers for jprobe %p\n", jp);
 			show_registers(saved_regs);
 			printk("Current registers\n");
 			show_registers(regs);
 			BUG();
 		}
-		*regs = jprobe_saved_regs;
-		memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack,
+		*regs = kcb->jprobe_saved_regs;
+		memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
 		       MIN_STACK_SIZE(stack_addr));
 		return 1;
 	}
-- 
cgit v1.2.2


From 991a51d83a3d9bebfafdd1e692cf310899d60791 Mon Sep 17 00:00:00 2001
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Date: Mon, 7 Nov 2005 01:00:14 -0800
Subject: [PATCH] Kprobes: Use RCU for (un)register synchronization - arch
 changes

Changes to the arch kprobes infrastructure to take advantage of the locking
changes introduced by usage of RCU for synchronization.  All handlers are now
run without any locks held, so they have to be re-entrant or provide their own
synchronization.

Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/kprobes.c    | 22 +++++++---------------
 arch/ia64/kernel/kprobes.c    | 16 ++++++----------
 arch/ppc64/kernel/kprobes.c   | 24 ++++++------------------
 arch/sparc64/kernel/kprobes.c | 14 ++------------
 arch/x86_64/kernel/kprobes.c  | 25 ++++++-------------------
 5 files changed, 27 insertions(+), 74 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 99565a6691..ad46929926 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -31,7 +31,6 @@
 #include <linux/config.h>
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
-#include <linux/spinlock.h>
 #include <linux/preempt.h>
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
@@ -123,6 +122,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 		regs->eip = (unsigned long)&p->ainsn.insn;
 }
 
+/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
 				      struct pt_regs *regs)
 {
@@ -168,15 +168,12 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	}
 	/* Check we're not actually recursing */
 	if (kprobe_running()) {
-		/* We *are* holding lock here, so this is safe.
-		   Disarm the probe we just hit, and ignore it. */
 		p = get_kprobe(addr);
 		if (p) {
 			if (kcb->kprobe_status == KPROBE_HIT_SS &&
 				*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
 				regs->eflags &= ~TF_MASK;
 				regs->eflags |= kcb->kprobe_saved_eflags;
-				unlock_kprobes();
 				goto no_kprobe;
 			}
 			/* We have reentered the kprobe_handler(), since
@@ -197,14 +194,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 				goto ss_probe;
 			}
 		}
-		/* If it's not ours, can't be delete race, (we hold lock). */
 		goto no_kprobe;
 	}
 
-	lock_kprobes();
 	p = get_kprobe(addr);
 	if (!p) {
-		unlock_kprobes();
 		if (regs->eflags & VM_MASK) {
 			/* We are in virtual-8086 mode. Return 0 */
 			goto no_kprobe;
@@ -268,9 +262,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
         struct hlist_node *node, *tmp;
-	unsigned long orig_ret_address = 0;
+	unsigned long flags, orig_ret_address = 0;
 	unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
 
+	spin_lock_irqsave(&kretprobe_lock, flags);
         head = kretprobe_inst_table_head(current);
 
 	/*
@@ -310,7 +305,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	regs->eip = orig_ret_address;
 
 	reset_current_kprobe();
-	unlock_kprobes();
+	spin_unlock_irqrestore(&kretprobe_lock, flags);
 	preempt_enable_no_resched();
 
 	/*
@@ -395,7 +390,7 @@ static void __kprobes resume_execution(struct kprobe *p,
 
 /*
  * Interrupts are disabled on entry as trap1 is an interrupt gate and they
- * remain disabled thoroughout this function.  And we hold kprobe lock.
+ * remain disabled thoroughout this function.
  */
 static inline int post_kprobe_handler(struct pt_regs *regs)
 {
@@ -419,7 +414,6 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
 		goto out;
 	}
 	reset_current_kprobe();
-	unlock_kprobes();
 out:
 	preempt_enable_no_resched();
 
@@ -434,7 +428,6 @@ out:
 	return 1;
 }
 
-/* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
@@ -448,7 +441,6 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 		regs->eflags |= kcb->kprobe_old_eflags;
 
 		reset_current_kprobe();
-		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
 	return 0;
@@ -463,7 +455,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	preempt_disable();
+	rcu_read_lock();
 	switch (val) {
 	case DIE_INT3:
 		if (kprobe_handler(args->regs))
@@ -482,7 +474,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	default:
 		break;
 	}
-	preempt_enable();
+	rcu_read_unlock();
 	return ret;
 }
 
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 17e70b1b8d..fddbac32d4 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -26,7 +26,6 @@
 #include <linux/config.h>
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
-#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/preempt.h>
@@ -343,10 +342,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	struct kretprobe_instance *ri = NULL;
 	struct hlist_head *head;
 	struct hlist_node *node, *tmp;
-	unsigned long orig_ret_address = 0;
+	unsigned long flags, orig_ret_address = 0;
 	unsigned long trampoline_address =
 		((struct fnptr *)kretprobe_trampoline)->ip;
 
+	spin_lock_irqsave(&kretprobe_lock, flags);
         head = kretprobe_inst_table_head(current);
 
 	/*
@@ -386,7 +386,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	regs->cr_iip = orig_ret_address;
 
 	reset_current_kprobe();
-	unlock_kprobes();
+	spin_unlock_irqrestore(&kretprobe_lock, flags);
 	preempt_enable_no_resched();
 
         /*
@@ -397,6 +397,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
         return 1;
 }
 
+/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
 				      struct pt_regs *regs)
 {
@@ -612,7 +613,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 			if ((kcb->kprobe_status == KPROBE_HIT_SS) &&
 	 		     (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
   				ia64_psr(regs)->ss = 0;
-				unlock_kprobes();
 				goto no_kprobe;
 			}
 			/* We have reentered the pre_kprobe_handler(), since
@@ -641,10 +641,8 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 		}
 	}
 
-	lock_kprobes();
 	p = get_kprobe(addr);
 	if (!p) {
-		unlock_kprobes();
 		if (!is_ia64_break_inst(regs)) {
 			/*
 			 * The breakpoint instruction was removed right
@@ -707,7 +705,6 @@ static int __kprobes post_kprobes_handler(struct pt_regs *regs)
 		goto out;
 	}
 	reset_current_kprobe();
-	unlock_kprobes();
 
 out:
 	preempt_enable_no_resched();
@@ -728,7 +725,6 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
 	if (kcb->kprobe_status & KPROBE_HIT_SS) {
 		resume_execution(cur, regs);
 		reset_current_kprobe();
-		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
 
@@ -741,7 +737,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	preempt_disable();
+	rcu_read_lock();
 	switch(val) {
 	case DIE_BREAK:
 		if (pre_kprobes_handler(args))
@@ -757,7 +753,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	default:
 		break;
 	}
-	preempt_enable();
+	rcu_read_unlock();
 	return ret;
 }
 
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 3f89f3e558..e0a25b3543 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -30,7 +30,6 @@
 #include <linux/config.h>
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
-#include <linux/spinlock.h>
 #include <linux/preempt.h>
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
@@ -125,6 +124,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 	kcb->kprobe_saved_msr = regs->msr;
 }
 
+/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
 				      struct pt_regs *regs)
 {
@@ -152,8 +152,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
 
 	/* Check we're not actually recursing */
 	if (kprobe_running()) {
-		/* We *are* holding lock here, so this is safe.
-		   Disarm the probe we just hit, and ignore it. */
 		p = get_kprobe(addr);
 		if (p) {
 			kprobe_opcode_t insn = *p->ainsn.insn;
@@ -161,7 +159,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
 					is_trap(insn)) {
 				regs->msr &= ~MSR_SE;
 				regs->msr |= kcb->kprobe_saved_msr;
-				unlock_kprobes();
 				goto no_kprobe;
 			}
 			/* We have reentered the kprobe_handler(), since
@@ -183,14 +180,11 @@ static inline int kprobe_handler(struct pt_regs *regs)
 				goto ss_probe;
 			}
 		}
-		/* If it's not ours, can't be delete race, (we hold lock). */
 		goto no_kprobe;
 	}
 
-	lock_kprobes();
 	p = get_kprobe(addr);
 	if (!p) {
-		unlock_kprobes();
 		if (*addr != BREAKPOINT_INSTRUCTION) {
 			/*
 			 * PowerPC has multiple variants of the "trap"
@@ -254,9 +248,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
         struct hlist_node *node, *tmp;
-	unsigned long orig_ret_address = 0;
+	unsigned long flags, orig_ret_address = 0;
 	unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
 
+	spin_lock_irqsave(&kretprobe_lock, flags);
         head = kretprobe_inst_table_head(current);
 
 	/*
@@ -296,7 +291,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	regs->nip = orig_ret_address;
 
 	reset_current_kprobe();
-	unlock_kprobes();
+	spin_unlock_irqrestore(&kretprobe_lock, flags);
 	preempt_enable_no_resched();
 
         /*
@@ -348,7 +343,6 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
 		goto out;
 	}
 	reset_current_kprobe();
-	unlock_kprobes();
 out:
 	preempt_enable_no_resched();
 
@@ -363,7 +357,6 @@ out:
 	return 1;
 }
 
-/* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
@@ -378,7 +371,6 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 		regs->msr |= kcb->kprobe_saved_msr;
 
 		reset_current_kprobe();
-		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
 	return 0;
@@ -393,11 +385,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	/*
-	 * Interrupts are not disabled here.  We need to disable
-	 * preemption, because kprobe_running() uses smp_processor_id().
-	 */
-	preempt_disable();
+	rcu_read_lock();
 	switch (val) {
 	case DIE_BPT:
 		if (kprobe_handler(args->regs))
@@ -415,7 +403,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	default:
 		break;
 	}
-	preempt_enable_no_resched();
+	rcu_read_unlock();
 	return ret;
 }
 
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index b95984154d..58a815e903 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -116,15 +116,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	if (kprobe_running()) {
-		/* We *are* holding lock here, so this is safe.
-		 * Disarm the probe we just hit, and ignore it.
-		 */
 		p = get_kprobe(addr);
 		if (p) {
 			if (kcb->kprobe_status == KPROBE_HIT_SS) {
 				regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
 					kcb->kprobe_orig_tstate_pil);
-				unlock_kprobes();
 				goto no_kprobe;
 			}
 			/* We have reentered the kprobe_handler(), since
@@ -144,14 +140,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 			if (p->break_handler && p->break_handler(p, regs))
 				goto ss_probe;
 		}
-		/* If it's not ours, can't be delete race, (we hold lock). */
 		goto no_kprobe;
 	}
 
-	lock_kprobes();
 	p = get_kprobe(addr);
 	if (!p) {
-		unlock_kprobes();
 		if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
 			/*
 			 * The breakpoint instruction was removed right
@@ -296,14 +289,12 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
 		goto out;
 	}
 	reset_current_kprobe();
-	unlock_kprobes();
 out:
 	preempt_enable_no_resched();
 
 	return 1;
 }
 
-/* Interrupts disabled, kprobe_lock held. */
 static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
@@ -316,7 +307,6 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 		resume_execution(cur, regs, kcb);
 
 		reset_current_kprobe();
-		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
 	return 0;
@@ -331,7 +321,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	preempt_disable();
+	rcu_read_lock();
 	switch (val) {
 	case DIE_DEBUG:
 		if (kprobe_handler(args->regs))
@@ -350,7 +340,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	default:
 		break;
 	}
-	preempt_enable();
+	rcu_read_unlock();
 	return ret;
 }
 
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 6cb40d133b..9bef2c8dc1 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -34,7 +34,6 @@
 #include <linux/config.h>
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
-#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/preempt.h>
@@ -266,6 +265,7 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 		regs->rip = (unsigned long)p->ainsn.insn;
 }
 
+/* Called with kretprobe_lock held */
 void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
 				      struct pt_regs *regs)
 {
@@ -299,15 +299,12 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 
 	/* Check we're not actually recursing */
 	if (kprobe_running()) {
-		/* We *are* holding lock here, so this is safe.
-		   Disarm the probe we just hit, and ignore it. */
 		p = get_kprobe(addr);
 		if (p) {
 			if (kcb->kprobe_status == KPROBE_HIT_SS &&
 				*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
 				regs->eflags &= ~TF_MASK;
 				regs->eflags |= kcb->kprobe_saved_rflags;
-				unlock_kprobes();
 				goto no_kprobe;
 			} else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) {
 				/* TODO: Provide re-entrancy from
@@ -340,14 +337,11 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 				goto ss_probe;
 			}
 		}
-		/* If it's not ours, can't be delete race, (we hold lock). */
 		goto no_kprobe;
 	}
 
-	lock_kprobes();
 	p = get_kprobe(addr);
 	if (!p) {
-		unlock_kprobes();
 		if (*addr != BREAKPOINT_INSTRUCTION) {
 			/*
 			 * The breakpoint instruction was removed right
@@ -406,9 +400,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
         struct kretprobe_instance *ri = NULL;
         struct hlist_head *head;
         struct hlist_node *node, *tmp;
-	unsigned long orig_ret_address = 0;
+	unsigned long flags, orig_ret_address = 0;
 	unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
 
+	spin_lock_irqsave(&kretprobe_lock, flags);
         head = kretprobe_inst_table_head(current);
 
 	/*
@@ -448,7 +443,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	regs->rip = orig_ret_address;
 
 	reset_current_kprobe();
-	unlock_kprobes();
+	spin_unlock_irqrestore(&kretprobe_lock, flags);
 	preempt_enable_no_resched();
 
         /*
@@ -536,10 +531,6 @@ static void __kprobes resume_execution(struct kprobe *p,
 	}
 }
 
-/*
- * Interrupts are disabled on entry as trap1 is an interrupt gate and they
- * remain disabled thoroughout this function.  And we hold kprobe lock.
- */
 int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *cur = kprobe_running();
@@ -560,8 +551,6 @@ int __kprobes post_kprobe_handler(struct pt_regs *regs)
 	if (kcb->kprobe_status == KPROBE_REENTER) {
 		restore_previous_kprobe(kcb);
 		goto out;
-	} else {
-		unlock_kprobes();
 	}
 	reset_current_kprobe();
 out:
@@ -578,7 +567,6 @@ out:
 	return 1;
 }
 
-/* Interrupts disabled, kprobe_lock held. */
 int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
@@ -592,7 +580,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 		regs->eflags |= kcb->kprobe_old_rflags;
 
 		reset_current_kprobe();
-		unlock_kprobes();
 		preempt_enable_no_resched();
 	}
 	return 0;
@@ -607,7 +594,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	preempt_disable();
+	rcu_read_lock();
 	switch (val) {
 	case DIE_INT3:
 		if (kprobe_handler(args->regs))
@@ -626,7 +613,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	default:
 		break;
 	}
-	preempt_enable();
+	rcu_read_unlock();
 	return ret;
 }
 
-- 
cgit v1.2.2


From d217d5450f11d8c907c0458d175b0dc999b4d06d Mon Sep 17 00:00:00 2001
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Date: Mon, 7 Nov 2005 01:00:14 -0800
Subject: [PATCH] Kprobes: preempt_disable/enable() simplification

Reorganize the preempt_disable/enable calls to eliminate the extra preempt
depth.  Changes based on Paul McKenney's review suggestions for the kprobes
RCU changeset.

Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/kprobes.c    | 25 +++++++++++++++----------
 arch/ia64/kernel/kprobes.c    | 37 ++++++++++++++++++++-----------------
 arch/ppc64/kernel/kprobes.c   | 25 +++++++++++++++----------
 arch/sparc64/kernel/kprobes.c | 21 +++++++++++++--------
 arch/x86_64/kernel/kprobes.c  | 29 +++++++++++++++--------------
 5 files changed, 78 insertions(+), 59 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index ad46929926..32b0c24ab9 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -153,7 +153,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	int ret = 0;
 	kprobe_opcode_t *addr = NULL;
 	unsigned long *lp;
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	struct kprobe_ctlblk *kcb;
+
+	/*
+	 * We don't want to be preempted for the entire
+	 * duration of kprobe processing
+	 */
+	preempt_disable();
+	kcb = get_kprobe_ctlblk();
 
 	/* Check if the application is using LDT entry for its code segment and
 	 * calculate the address by reading the base address from the LDT entry.
@@ -221,11 +228,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 		goto no_kprobe;
 	}
 
-	/*
-	 * This preempt_disable() matches the preempt_enable_no_resched()
-	 * in post_kprobe_handler()
-	 */
-	preempt_disable();
 	set_current_kprobe(p, regs, kcb);
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
@@ -239,6 +241,7 @@ ss_probe:
 	return 1;
 
 no_kprobe:
+	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -310,8 +313,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 
 	/*
 	 * By returning a non-zero value, we are telling
-	 * kprobe_handler() that we have handled unlocking
-	 * and re-enabling preemption
+	 * kprobe_handler() that we don't want the post_handler
+	 * to run (and have re-enabled preemption)
 	 */
         return 1;
 }
@@ -455,7 +458,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	rcu_read_lock();
 	switch (val) {
 	case DIE_INT3:
 		if (kprobe_handler(args->regs))
@@ -467,14 +469,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 		break;
 	case DIE_GPF:
 	case DIE_PAGE_FAULT:
+		/* kprobe_running() needs smp_processor_id() */
+		preempt_disable();
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
 			ret = NOTIFY_STOP;
+		preempt_enable();
 		break;
 	default:
 		break;
 	}
-	rcu_read_unlock();
 	return ret;
 }
 
@@ -537,6 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 		*regs = kcb->jprobe_saved_regs;
 		memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
 		       MIN_STACK_SIZE(stack_addr));
+		preempt_enable_no_resched();
 		return 1;
 	}
 	return 0;
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index fddbac32d4..96736a119c 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -389,11 +389,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	spin_unlock_irqrestore(&kretprobe_lock, flags);
 	preempt_enable_no_resched();
 
-        /*
-         * By returning a non-zero value, we are telling
-         * kprobe_handler() that we have handled unlocking
-	 * and re-enabling preemption
-         */
+	/*
+	 * By returning a non-zero value, we are telling
+	 * kprobe_handler() that we don't want the post_handler
+	 * to run (and have re-enabled preemption)
+	 */
         return 1;
 }
 
@@ -604,7 +604,14 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 	int ret = 0;
 	struct pt_regs *regs = args->regs;
 	kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	struct kprobe_ctlblk *kcb;
+
+	/*
+	 * We don't want to be preempted for the entire
+	 * duration of kprobe processing
+	 */
+	preempt_disable();
+	kcb = get_kprobe_ctlblk();
 
 	/* Handle recursion cases */
 	if (kprobe_running()) {
@@ -659,11 +666,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 		goto no_kprobe;
 	}
 
-	/*
-	 * This preempt_disable() matches the preempt_enable_no_resched()
-	 * in post_kprobes_handler()
-	 */
-	preempt_disable();
 	set_current_kprobe(p, kcb);
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
@@ -681,6 +683,7 @@ ss_probe:
 	return 1;
 
 no_kprobe:
+	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -716,9 +719,6 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	if (!cur)
-		return 0;
-
 	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
 		return 1;
 
@@ -737,7 +737,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	rcu_read_lock();
 	switch(val) {
 	case DIE_BREAK:
 		if (pre_kprobes_handler(args))
@@ -748,12 +747,15 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 			ret = NOTIFY_STOP;
 		break;
 	case DIE_PAGE_FAULT:
-		if (kprobes_fault_handler(args->regs, args->trapnr))
+		/* kprobe_running() needs smp_processor_id() */
+		preempt_disable();
+		if (kprobe_running() &&
+			kprobes_fault_handler(args->regs, args->trapnr))
 			ret = NOTIFY_STOP;
+		preempt_enable();
 	default:
 		break;
 	}
-	rcu_read_unlock();
 	return ret;
 }
 
@@ -785,6 +787,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	*regs = kcb->jprobe_saved_regs;
+	preempt_enable_no_resched();
 	return 1;
 }
 
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index e0a25b3543..511af54e62 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -148,7 +148,14 @@ static inline int kprobe_handler(struct pt_regs *regs)
 	struct kprobe *p;
 	int ret = 0;
 	unsigned int *addr = (unsigned int *)regs->nip;
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	struct kprobe_ctlblk *kcb;
+
+	/*
+	 * We don't want to be preempted for the entire
+	 * duration of kprobe processing
+	 */
+	preempt_disable();
+	kcb = get_kprobe_ctlblk();
 
 	/* Check we're not actually recursing */
 	if (kprobe_running()) {
@@ -207,11 +214,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
 		goto no_kprobe;
 	}
 
-	/*
-	 * This preempt_disable() matches the preempt_enable_no_resched()
-	 * in post_kprobe_handler().
-	 */
-	preempt_disable();
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 	set_current_kprobe(p, regs, kcb);
 	if (p->pre_handler && p->pre_handler(p, regs))
@@ -224,6 +226,7 @@ ss_probe:
 	return 1;
 
 no_kprobe:
+	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -296,8 +299,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 
         /*
          * By returning a non-zero value, we are telling
-         * kprobe_handler() that we have handled unlocking
-         * and re-enabling preemption.
+         * kprobe_handler() that we don't want the post_handler
+         * to run (and have re-enabled preemption)
          */
         return 1;
 }
@@ -385,7 +388,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	rcu_read_lock();
 	switch (val) {
 	case DIE_BPT:
 		if (kprobe_handler(args->regs))
@@ -396,14 +398,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 			ret = NOTIFY_STOP;
 		break;
 	case DIE_PAGE_FAULT:
+		/* kprobe_running() needs smp_processor_id() */
+		preempt_disable();
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
 			ret = NOTIFY_STOP;
+		preempt_enable();
 		break;
 	default:
 		break;
 	}
-	rcu_read_unlock();
 	return ret;
 }
 
@@ -440,6 +444,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 	 * saved regs...
 	 */
 	memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
+	preempt_enable_no_resched();
 	return 1;
 }
 
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 58a815e903..96bd09b098 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -113,7 +113,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	struct kprobe *p;
 	void *addr = (void *) regs->tpc;
 	int ret = 0;
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	struct kprobe_ctlblk *kcb;
+
+	/*
+	 * We don't want to be preempted for the entire
+	 * duration of kprobe processing
+	 */
+	preempt_disable();
+	kcb = get_kprobe_ctlblk();
 
 	if (kprobe_running()) {
 		p = get_kprobe(addr);
@@ -159,11 +166,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 		goto no_kprobe;
 	}
 
-	/*
-	 * This preempt_disable() matches the preempt_enable_no_resched()
-	 * in post_kprobes_handler()
-	 */
-	preempt_disable();
 	set_current_kprobe(p, regs, kcb);
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 	if (p->pre_handler && p->pre_handler(p, regs))
@@ -175,6 +177,7 @@ ss_probe:
 	return 1;
 
 no_kprobe:
+	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -321,7 +324,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	rcu_read_lock();
 	switch (val) {
 	case DIE_DEBUG:
 		if (kprobe_handler(args->regs))
@@ -333,14 +335,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 		break;
 	case DIE_GPF:
 	case DIE_PAGE_FAULT:
+		/* kprobe_running() needs smp_processor_id() */
+		preempt_disable();
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
 			ret = NOTIFY_STOP;
+		preempt_enable();
 		break;
 	default:
 		break;
 	}
-	rcu_read_unlock();
 	return ret;
 }
 
@@ -426,6 +430,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 		       &(kcb->jprobe_saved_stack),
 		       sizeof(kcb->jprobe_saved_stack));
 
+		preempt_enable_no_resched();
 		return 1;
 	}
 	return 0;
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 9bef2c8dc1..dddeb678b4 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -286,16 +286,19 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
         }
 }
 
-/*
- * Interrupts are disabled on entry as trap3 is an interrupt gate and they
- * remain disabled thorough out this function.
- */
 int __kprobes kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p;
 	int ret = 0;
 	kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t));
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	struct kprobe_ctlblk *kcb;
+
+	/*
+	 * We don't want to be preempted for the entire
+	 * duration of kprobe processing
+	 */
+	preempt_disable();
+	kcb = get_kprobe_ctlblk();
 
 	/* Check we're not actually recursing */
 	if (kprobe_running()) {
@@ -359,11 +362,6 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
 		goto no_kprobe;
 	}
 
-	/*
-	 * This preempt_disable() matches the preempt_enable_no_resched()
-	 * in post_kprobe_handler()
-	 */
-	preempt_disable();
 	set_current_kprobe(p, regs, kcb);
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
@@ -377,6 +375,7 @@ ss_probe:
 	return 1;
 
 no_kprobe:
+	preempt_enable_no_resched();
 	return ret;
 }
 
@@ -448,8 +447,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 
         /*
          * By returning a non-zero value, we are telling
-         * kprobe_handler() that we have handled unlocking
-	 * and re-enabling preemption
+         * kprobe_handler() that we don't want the post_handler
+	 * to run (and have re-enabled preemption)
          */
         return 1;
 }
@@ -594,7 +593,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	rcu_read_lock();
 	switch (val) {
 	case DIE_INT3:
 		if (kprobe_handler(args->regs))
@@ -606,14 +604,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 		break;
 	case DIE_GPF:
 	case DIE_PAGE_FAULT:
+		/* kprobe_running() needs smp_processor_id() */
+		preempt_disable();
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
 			ret = NOTIFY_STOP;
+		preempt_enable();
 		break;
 	default:
 		break;
 	}
-	rcu_read_unlock();
 	return ret;
 }
 
@@ -675,6 +675,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 		*regs = kcb->jprobe_saved_regs;
 		memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
 		       MIN_STACK_SIZE(stack_addr));
+		preempt_enable_no_resched();
 		return 1;
 	}
 	return 0;
-- 
cgit v1.2.2


From 2b0c28d7f8846f80a436093e906f5175d1fa8f55 Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@kernel.crashing.org>
Date: Mon, 7 Nov 2005 01:00:19 -0800
Subject: [PATCH] RapidIO support: ppc32

Adds PPC32 RIO support.  Init code for the MPC85xx RIO ports and glue for the
STx GP3 board to use it.

Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/Kconfig                             |   8 +
 arch/ppc/configs/stx_gp3_defconfig           |  86 ++-
 arch/ppc/kernel/Makefile                     |   1 +
 arch/ppc/kernel/rio.c                        |  52 ++
 arch/ppc/platforms/85xx/mpc85xx_ads_common.c |  10 +
 arch/ppc/platforms/85xx/stx_gp3.c            |  14 +
 arch/ppc/syslib/Makefile                     |   1 +
 arch/ppc/syslib/ppc85xx_rio.c                | 932 +++++++++++++++++++++++++++
 arch/ppc/syslib/ppc85xx_rio.h                |  21 +
 9 files changed, 1091 insertions(+), 34 deletions(-)
 create mode 100644 arch/ppc/kernel/rio.c
 create mode 100644 arch/ppc/syslib/ppc85xx_rio.c
 create mode 100644 arch/ppc/syslib/ppc85xx_rio.h

(limited to 'arch')

diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index f8db33d552..8fa51b0a32 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -1257,6 +1257,14 @@ source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
+config RAPIDIO
+	bool "RapidIO support" if MPC8540 || MPC8560
+	help
+	  If you say Y here, the kernel will include drivers and
+	  infrastructure code to support RapidIO interconnect devices.
+
+source "drivers/rapidio/Kconfig"
+
 endmenu
 
 menu "Advanced setup"
diff --git a/arch/ppc/configs/stx_gp3_defconfig b/arch/ppc/configs/stx_gp3_defconfig
index 66dae83676..3fedc43e44 100644
--- a/arch/ppc/configs/stx_gp3_defconfig
+++ b/arch/ppc/configs/stx_gp3_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 14:32:58 2005
+# Linux kernel version: 2.6.12-rc4
+# Tue May 24 18:11:04 2005
 #
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y
 CONFIG_PPC=y
 CONFIG_PPC32=y
 CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 
 #
 # Code maturity level options
@@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -29,7 +31,6 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
@@ -37,6 +38,9 @@ CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -46,6 +50,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -69,9 +74,11 @@ CONFIG_KMOD=y
 CONFIG_E500=y
 CONFIG_BOOKE=y
 CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
 # CONFIG_SPE is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
 CONFIG_85xx=y
 CONFIG_PPC_INDIRECT_PCI_BE=y
 
@@ -96,6 +103,7 @@ CONFIG_HIGHMEM=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
@@ -104,15 +112,15 @@ CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PC-card bridges
-#
+CONFIG_RAPIDIO=y
+CONFIG_RAPIDIO_8_BIT_TRANSPORT=y
+CONFIG_RAPIDIO_DISC_TIMEOUT=30
 
 #
 # Advanced setup
@@ -152,7 +160,7 @@ CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
 # CONFIG_PARPORT_1284 is not set
 
 #
@@ -264,7 +272,6 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -274,7 +281,6 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_IMM is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=m
@@ -283,6 +289,7 @@ CONFIG_SCSI_QLA2XXX=m
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
@@ -322,7 +329,6 @@ CONFIG_NET=y
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -431,7 +437,7 @@ CONFIG_IP_NF_NAT_FTP=m
 #
 # Network testing
 #
-# CONFIG_NET_PKTGEN is not set
+CONFIG_NET_PKTGEN=y
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
@@ -499,6 +505,7 @@ CONFIG_GFAR_NAPI=y
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+CONFIG_RIONET=y
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
@@ -535,20 +542,6 @@ CONFIG_INPUT_JOYDEV=m
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_EVBUG is not set
 
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
 #
 # Input Device Drivers
 #
@@ -566,6 +559,19 @@ CONFIG_MOUSE_PS2=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -590,6 +596,7 @@ CONFIG_SERIAL_CPM_SCC2=y
 # CONFIG_SERIAL_CPM_SCC4 is not set
 # CONFIG_SERIAL_CPM_SMC1 is not set
 # CONFIG_SERIAL_CPM_SMC2 is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -625,6 +632,11 @@ CONFIG_DRM=m
 # CONFIG_DRM_SIS is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
 #
 # I2C support
 #
@@ -648,12 +660,12 @@ CONFIG_I2C_ALGOBIT=m
 # CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
 # CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_SCx200_ACB is not set
@@ -677,7 +689,9 @@ CONFIG_I2C_ALGOBIT=m
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM63 is not set
 # CONFIG_SENSORS_LM75 is not set
@@ -688,9 +702,11 @@ CONFIG_I2C_ALGOBIT=m
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -700,10 +716,12 @@ CONFIG_I2C_ALGOBIT=m
 #
 # Other I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -732,7 +750,6 @@ CONFIG_I2C_ALGOBIT=m
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -752,13 +769,9 @@ CONFIG_SOUND=m
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -789,6 +802,10 @@ CONFIG_JBD_DEBUG=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -859,7 +876,6 @@ CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -942,8 +958,10 @@ CONFIG_ZLIB_INFLATE=m
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index c610ca933a..76a55a438f 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_POWER4)		+= cpu_setup_power4.o
 obj-$(CONFIG_MODULES)		+= module.o ppc_ksyms.o
 obj-$(CONFIG_NOT_COHERENT_CACHE)	+= dma-mapping.o
 obj-$(CONFIG_PCI)		+= pci.o
+obj-$(CONFIG_RAPIDIO)		+= rio.o
 obj-$(CONFIG_KGDB)		+= ppc-stub.o
 obj-$(CONFIG_SMP)		+= smp.o smp-tbsync.o
 obj-$(CONFIG_TAU)		+= temp.o
diff --git a/arch/ppc/kernel/rio.c b/arch/ppc/kernel/rio.c
new file mode 100644
index 0000000000..29487fedfc
--- /dev/null
+++ b/arch/ppc/kernel/rio.c
@@ -0,0 +1,52 @@
+/*
+ * RapidIO PPC32 support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/rio.h>
+
+#include <asm/rio.h>
+
+/**
+ * platform_rio_init - Do platform specific RIO init
+ *
+ * Any platform specific initialization of RapdIO
+ * hardware is done here as well as registration
+ * of any active master ports in the system.
+ */
+void __attribute__ ((weak))
+    platform_rio_init(void)
+{
+	printk(KERN_WARNING "RIO: No platform_rio_init() present\n");
+}
+
+/**
+ * ppc_rio_init - Do PPC32 RIO init
+ *
+ * Calls platform-specific RIO init code and then calls
+ * rio_init_mports() to initialize any master ports that
+ * have been registered with the RIO subsystem.
+ */
+static int __init ppc_rio_init(void)
+{
+	printk(KERN_INFO "RIO: RapidIO init\n");
+
+	/* Platform specific initialization */
+	platform_rio_init();
+
+	/* Enumerate all registered ports */
+	rio_init_mports();
+
+	return 0;
+}
+
+subsys_initcall(ppc_rio_init);
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
index bd3ac01367..16ad092d8a 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
@@ -45,6 +45,8 @@
 
 #include <mm/mmu_decl.h>
 
+#include <syslib/ppc85xx_rio.h>
+
 #include <platforms/85xx/mpc85xx_ads_common.h>
 
 #ifndef CONFIG_PCI
@@ -189,3 +191,11 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
 }
 
 #endif /* CONFIG_PCI */
+
+#ifdef CONFIG_RAPIDIO
+void platform_rio_init(void)
+{
+	/* 512MB RIO LAW at 0xc0000000 */
+	mpc85xx_rio_setup(0xc0000000, 0x20000000);
+}
+#endif /* CONFIG_RAPIDIO */
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 1e1b85f819..15ce9d0706 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -37,6 +37,7 @@
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
 #include <linux/interrupt.h>
+#include <linux/rio.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -57,6 +58,7 @@
 
 #include <syslib/cpm2_pic.h>
 #include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_rio.h>
 
 
 unsigned char __res[sizeof(bd_t)];
@@ -273,6 +275,18 @@ int mpc85xx_exclude_device(u_char bus, u_char devfn)
 }
 #endif /* CONFIG_PCI */
 
+#ifdef CONFIG_RAPIDIO
+void
+platform_rio_init(void)
+{
+	/*
+	 * The STx firmware configures the RapidIO Local Access Window
+	 * at 0xc0000000 with a size of 512MB.
+	 */
+	mpc85xx_rio_setup(0xc0000000, 0x20000000);
+}
+#endif /* CONFIG_RAPIDIO */
+
 void __init
 platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	      unsigned long r6, unsigned long r7)
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index dcd168f9a7..5bd33baac2 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_PPC4xx_DMA)	+= ppc4xx_dma.o
 obj-$(CONFIG_PPC4xx_EDMA)	+= ppc4xx_sgdma.o
 ifeq ($(CONFIG_40x),y)
 obj-$(CONFIG_PCI)		+= pci_auto.o ppc405_pci.o
+obj-$(CONFIG_RAPIDIO)		+= ppc85xx_rio.o
 endif
 endif
 obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c
new file mode 100644
index 0000000000..9d09c2715e
--- /dev/null
+++ b/arch/ppc/syslib/ppc85xx_rio.c
@@ -0,0 +1,932 @@
+/*
+ * MPC85xx RapidIO support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+
+#include <asm/io.h>
+
+#define RIO_REGS_BASE		(CCSRBAR + 0xc0000)
+#define RIO_ATMU_REGS_OFFSET	0x10c00
+#define RIO_MSG_REGS_OFFSET	0x11000
+#define RIO_MAINT_WIN_SIZE	0x400000
+#define RIO_DBELL_WIN_SIZE	0x1000
+
+#define RIO_MSG_OMR_MUI		0x00000002
+#define RIO_MSG_OSR_TE		0x00000080
+#define RIO_MSG_OSR_QOI		0x00000020
+#define RIO_MSG_OSR_QFI		0x00000010
+#define RIO_MSG_OSR_MUB		0x00000004
+#define RIO_MSG_OSR_EOMI	0x00000002
+#define RIO_MSG_OSR_QEI		0x00000001
+
+#define RIO_MSG_IMR_MI		0x00000002
+#define RIO_MSG_ISR_TE		0x00000080
+#define RIO_MSG_ISR_QFI		0x00000010
+#define RIO_MSG_ISR_DIQI	0x00000001
+
+#define RIO_MSG_DESC_SIZE	32
+#define RIO_MSG_BUFFER_SIZE	4096
+#define RIO_MIN_TX_RING_SIZE	2
+#define RIO_MAX_TX_RING_SIZE	2048
+#define RIO_MIN_RX_RING_SIZE	2
+#define RIO_MAX_RX_RING_SIZE	2048
+
+#define DOORBELL_DMR_DI		0x00000002
+#define DOORBELL_DSR_TE		0x00000080
+#define DOORBELL_DSR_QFI	0x00000010
+#define DOORBELL_DSR_DIQI	0x00000001
+#define DOORBELL_TID_OFFSET	0x03
+#define DOORBELL_SID_OFFSET	0x05
+#define DOORBELL_INFO_OFFSET	0x06
+
+#define DOORBELL_MESSAGE_SIZE	0x08
+#define DBELL_SID(x)		(*(u8 *)(x + DOORBELL_SID_OFFSET))
+#define DBELL_TID(x)		(*(u8 *)(x + DOORBELL_TID_OFFSET))
+#define DBELL_INF(x)		(*(u16 *)(x + DOORBELL_INFO_OFFSET))
+
+#define is_power_of_2(x)	(((x) & ((x) - 1)) == 0)
+
+struct rio_atmu_regs {
+	u32 rowtar;
+	u32 pad1;
+	u32 rowbar;
+	u32 pad2;
+	u32 rowar;
+	u32 pad3[3];
+};
+
+struct rio_msg_regs {
+	u32 omr;
+	u32 osr;
+	u32 pad1;
+	u32 odqdpar;
+	u32 pad2;
+	u32 osar;
+	u32 odpr;
+	u32 odatr;
+	u32 odcr;
+	u32 pad3;
+	u32 odqepar;
+	u32 pad4[13];
+	u32 imr;
+	u32 isr;
+	u32 pad5;
+	u32 ifqdpar;
+	u32 pad6;
+	u32 ifqepar;
+	u32 pad7[250];
+	u32 dmr;
+	u32 dsr;
+	u32 pad8;
+	u32 dqdpar;
+	u32 pad9;
+	u32 dqepar;
+	u32 pad10[26];
+	u32 pwmr;
+	u32 pwsr;
+	u32 pad11;
+	u32 pwqbar;
+};
+
+struct rio_tx_desc {
+	u32 res1;
+	u32 saddr;
+	u32 dport;
+	u32 dattr;
+	u32 res2;
+	u32 res3;
+	u32 dwcnt;
+	u32 res4;
+};
+
+static u32 regs_win;
+static struct rio_atmu_regs *atmu_regs;
+static struct rio_atmu_regs *maint_atmu_regs;
+static struct rio_atmu_regs *dbell_atmu_regs;
+static u32 dbell_win;
+static u32 maint_win;
+static struct rio_msg_regs *msg_regs;
+
+static struct rio_dbell_ring {
+	void *virt;
+	dma_addr_t phys;
+} dbell_ring;
+
+static struct rio_msg_tx_ring {
+	void *virt;
+	dma_addr_t phys;
+	void *virt_buffer[RIO_MAX_TX_RING_SIZE];
+	dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE];
+	int tx_slot;
+	int size;
+} msg_tx_ring;
+
+static struct rio_msg_rx_ring {
+	void *virt;
+	dma_addr_t phys;
+	void *virt_buffer[RIO_MAX_RX_RING_SIZE];
+	int rx_slot;
+	int size;
+} msg_rx_ring;
+
+/**
+ * mpc85xx_rio_doorbell_send - Send a MPC85xx doorbell message
+ * @index: ID of RapidIO interface
+ * @destid: Destination ID of target device
+ * @data: 16-bit info field of RapidIO doorbell message
+ *
+ * Sends a MPC85xx doorbell message. Returns %0 on success or
+ * %-EINVAL on failure.
+ */
+static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data)
+{
+	pr_debug("mpc85xx_doorbell_send: index %d destid %4.4x data %4.4x\n",
+		 index, destid, data);
+	out_be32((void *)&dbell_atmu_regs->rowtar, destid << 22);
+	out_be16((void *)(dbell_win), data);
+
+	return 0;
+}
+
+/**
+ * mpc85xx_local_config_read - Generate a MPC85xx local config space read
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be read into
+ *
+ * Generates a MPC85xx local configuration space read. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data)
+{
+	pr_debug("mpc85xx_local_config_read: index %d offset %8.8x\n", index,
+		 offset);
+	*data = in_be32((void *)(regs_win + offset));
+
+	return 0;
+}
+
+/**
+ * mpc85xx_local_config_write - Generate a MPC85xx local config space write
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be written
+ *
+ * Generates a MPC85xx local configuration space write. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data)
+{
+	pr_debug
+	    ("mpc85xx_local_config_write: index %d offset %8.8x data %8.8x\n",
+	     index, offset, data);
+	out_be32((void *)(regs_win + offset), data);
+
+	return 0;
+}
+
+/**
+ * mpc85xx_rio_config_read - Generate a MPC85xx read maintenance transaction
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Location to be read into
+ *
+ * Generates a MPC85xx read maintenance transaction. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int
+mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len,
+			u32 * val)
+{
+	u8 *data;
+
+	pr_debug
+	    ("mpc85xx_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
+	     index, destid, hopcount, offset, len);
+	out_be32((void *)&maint_atmu_regs->rowtar,
+		 (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
+
+	data = (u8 *) maint_win + offset;
+	switch (len) {
+	case 1:
+		*val = in_8((u8 *) data);
+		break;
+	case 2:
+		*val = in_be16((u16 *) data);
+		break;
+	default:
+		*val = in_be32((u32 *) data);
+		break;
+	}
+
+	return 0;
+}
+
+/**
+ * mpc85xx_rio_config_write - Generate a MPC85xx write maintenance transaction
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Value to be written
+ *
+ * Generates an MPC85xx write maintenance transaction. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int
+mpc85xx_rio_config_write(int index, u16 destid, u8 hopcount, u32 offset,
+			 int len, u32 val)
+{
+	u8 *data;
+	pr_debug
+	    ("mpc85xx_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
+	     index, destid, hopcount, offset, len, val);
+	out_be32((void *)&maint_atmu_regs->rowtar,
+		 (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
+
+	data = (u8 *) maint_win + offset;
+	switch (len) {
+	case 1:
+		out_8((u8 *) data, val);
+		break;
+	case 2:
+		out_be16((u16 *) data, val);
+		break;
+	default:
+		out_be32((u32 *) data, val);
+		break;
+	}
+
+	return 0;
+}
+
+/**
+ * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue
+ * @mport: Master port with outbound message queue
+ * @rdev: Target of outbound message
+ * @mbox: Outbound mailbox
+ * @buffer: Message to add to outbound queue
+ * @len: Length of message
+ *
+ * Adds the @buffer message to the MPC85xx outbound message queue. Returns
+ * %0 on success or %-EINVAL on failure.
+ */
+int
+rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
+			void *buffer, size_t len)
+{
+	u32 omr;
+	struct rio_tx_desc *desc =
+	    (struct rio_tx_desc *)msg_tx_ring.virt + msg_tx_ring.tx_slot;
+	int ret = 0;
+
+	pr_debug
+	    ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n",
+	     rdev->destid, mbox, (int)buffer, len);
+
+	if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Copy and clear rest of buffer */
+	memcpy(msg_tx_ring.virt_buffer[msg_tx_ring.tx_slot], buffer, len);
+	if (len < (RIO_MAX_MSG_SIZE - 4))
+		memset((void *)((u32) msg_tx_ring.
+				virt_buffer[msg_tx_ring.tx_slot] + len), 0,
+		       RIO_MAX_MSG_SIZE - len);
+
+	/* Set mbox field for message */
+	desc->dport = mbox & 0x3;
+
+	/* Enable EOMI interrupt, set priority, and set destid */
+	desc->dattr = 0x28000000 | (rdev->destid << 2);
+
+	/* Set transfer size aligned to next power of 2 (in double words) */
+	desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len);
+
+	/* Set snooping and source buffer address */
+	desc->saddr = 0x00000004 | msg_tx_ring.phys_buffer[msg_tx_ring.tx_slot];
+
+	/* Increment enqueue pointer */
+	omr = in_be32((void *)&msg_regs->omr);
+	out_be32((void *)&msg_regs->omr, omr | RIO_MSG_OMR_MUI);
+
+	/* Go to next descriptor */
+	if (++msg_tx_ring.tx_slot == msg_tx_ring.size)
+		msg_tx_ring.tx_slot = 0;
+
+      out:
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(rio_hw_add_outb_message);
+
+/**
+ * mpc85xx_rio_tx_handler - MPC85xx outbound message interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ * @regs: Register context
+ *
+ * Handles outbound message interrupts. Executes a register outbound
+ * mailbox event handler and acks the interrupt occurence.
+ */
+static irqreturn_t
+mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	int osr;
+	struct rio_mport *port = (struct rio_mport *)dev_instance;
+
+	osr = in_be32((void *)&msg_regs->osr);
+
+	if (osr & RIO_MSG_OSR_TE) {
+		pr_info("RIO: outbound message transmission error\n");
+		out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_TE);
+		goto out;
+	}
+
+	if (osr & RIO_MSG_OSR_QOI) {
+		pr_info("RIO: outbound message queue overflow\n");
+		out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_QOI);
+		goto out;
+	}
+
+	if (osr & RIO_MSG_OSR_EOMI) {
+		u32 dqp = in_be32((void *)&msg_regs->odqdpar);
+		int slot = (dqp - msg_tx_ring.phys) >> 5;
+		port->outb_msg[0].mcback(port, -1, slot);
+
+		/* Ack the end-of-message interrupt */
+		out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI);
+	}
+
+      out:
+	return IRQ_HANDLED;
+}
+
+/**
+ * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox
+ * @mport: Master port implementing the outbound message unit
+ * @mbox: Mailbox to open
+ * @entries: Number of entries in the outbound mailbox ring
+ *
+ * Initializes buffer ring, request the outbound message interrupt,
+ * and enables the outbound message unit. Returns %0 on success and
+ * %-EINVAL or %-ENOMEM on failure.
+ */
+int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries)
+{
+	int i, j, rc = 0;
+
+	if ((entries < RIO_MIN_TX_RING_SIZE) ||
+	    (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* Initialize shadow copy ring */
+	msg_tx_ring.size = entries;
+
+	for (i = 0; i < msg_tx_ring.size; i++) {
+		if (!
+		    (msg_tx_ring.virt_buffer[i] =
+		     dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+					&msg_tx_ring.phys_buffer[i],
+					GFP_KERNEL))) {
+			rc = -ENOMEM;
+			for (j = 0; j < msg_tx_ring.size; j++)
+				if (msg_tx_ring.virt_buffer[j])
+					dma_free_coherent(NULL,
+							  RIO_MSG_BUFFER_SIZE,
+							  msg_tx_ring.
+							  virt_buffer[j],
+							  msg_tx_ring.
+							  phys_buffer[j]);
+			goto out;
+		}
+	}
+
+	/* Initialize outbound message descriptor ring */
+	if (!(msg_tx_ring.virt = dma_alloc_coherent(NULL,
+						    msg_tx_ring.size *
+						    RIO_MSG_DESC_SIZE,
+						    &msg_tx_ring.phys,
+						    GFP_KERNEL))) {
+		rc = -ENOMEM;
+		goto out_dma;
+	}
+	memset(msg_tx_ring.virt, 0, msg_tx_ring.size * RIO_MSG_DESC_SIZE);
+	msg_tx_ring.tx_slot = 0;
+
+	/* Point dequeue/enqueue pointers at first entry in ring */
+	out_be32((void *)&msg_regs->odqdpar, msg_tx_ring.phys);
+	out_be32((void *)&msg_regs->odqepar, msg_tx_ring.phys);
+
+	/* Configure for snooping */
+	out_be32((void *)&msg_regs->osar, 0x00000004);
+
+	/* Clear interrupt status */
+	out_be32((void *)&msg_regs->osr, 0x000000b3);
+
+	/* Hook up outbound message handler */
+	if ((rc =
+	     request_irq(MPC85xx_IRQ_RIO_TX, mpc85xx_rio_tx_handler, 0,
+			 "msg_tx", (void *)mport)) < 0)
+		goto out_irq;
+
+	/*
+	 * Configure outbound message unit
+	 *      Snooping
+	 *      Interrupts (all enabled, except QEIE)
+	 *      Chaining mode
+	 *      Disable
+	 */
+	out_be32((void *)&msg_regs->omr, 0x00100220);
+
+	/* Set number of entries */
+	out_be32((void *)&msg_regs->omr,
+		 in_be32((void *)&msg_regs->omr) |
+		 ((get_bitmask_order(entries) - 2) << 12));
+
+	/* Now enable the unit */
+	out_be32((void *)&msg_regs->omr, in_be32((void *)&msg_regs->omr) | 0x1);
+
+      out:
+	return rc;
+
+      out_irq:
+	dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+			  msg_tx_ring.virt, msg_tx_ring.phys);
+
+      out_dma:
+	for (i = 0; i < msg_tx_ring.size; i++)
+		dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+				  msg_tx_ring.virt_buffer[i],
+				  msg_tx_ring.phys_buffer[i]);
+
+	return rc;
+}
+
+/**
+ * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox
+ * @mport: Master port implementing the outbound message unit
+ * @mbox: Mailbox to close
+ *
+ * Disables the outbound message unit, free all buffers, and
+ * frees the outbound message interrupt.
+ */
+void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
+{
+	/* Disable inbound message unit */
+	out_be32((void *)&msg_regs->omr, 0);
+
+	/* Free ring */
+	dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+			  msg_tx_ring.virt, msg_tx_ring.phys);
+
+	/* Free interrupt */
+	free_irq(MPC85xx_IRQ_RIO_TX, (void *)mport);
+}
+
+/**
+ * mpc85xx_rio_rx_handler - MPC85xx inbound message interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ * @regs: Register context
+ *
+ * Handles inbound message interrupts. Executes a registered inbound
+ * mailbox event handler and acks the interrupt occurence.
+ */
+static irqreturn_t
+mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	int isr;
+	struct rio_mport *port = (struct rio_mport *)dev_instance;
+
+	isr = in_be32((void *)&msg_regs->isr);
+
+	if (isr & RIO_MSG_ISR_TE) {
+		pr_info("RIO: inbound message reception error\n");
+		out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_TE);
+		goto out;
+	}
+
+	/* XXX Need to check/dispatch until queue empty */
+	if (isr & RIO_MSG_ISR_DIQI) {
+		/*
+		 * We implement *only* mailbox 0, but can receive messages
+		 * for any mailbox/letter to that mailbox destination. So,
+		 * make the callback with an unknown/invalid mailbox number
+		 * argument.
+		 */
+		port->inb_msg[0].mcback(port, -1, -1);
+
+		/* Ack the queueing interrupt */
+		out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI);
+	}
+
+      out:
+	return IRQ_HANDLED;
+}
+
+/**
+ * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox
+ * @mport: Master port implementing the inbound message unit
+ * @mbox: Mailbox to open
+ * @entries: Number of entries in the inbound mailbox ring
+ *
+ * Initializes buffer ring, request the inbound message interrupt,
+ * and enables the inbound message unit. Returns %0 on success
+ * and %-EINVAL or %-ENOMEM on failure.
+ */
+int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries)
+{
+	int i, rc = 0;
+
+	if ((entries < RIO_MIN_RX_RING_SIZE) ||
+	    (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* Initialize client buffer ring */
+	msg_rx_ring.size = entries;
+	msg_rx_ring.rx_slot = 0;
+	for (i = 0; i < msg_rx_ring.size; i++)
+		msg_rx_ring.virt_buffer[i] = NULL;
+
+	/* Initialize inbound message ring */
+	if (!(msg_rx_ring.virt = dma_alloc_coherent(NULL,
+						    msg_rx_ring.size *
+						    RIO_MAX_MSG_SIZE,
+						    &msg_rx_ring.phys,
+						    GFP_KERNEL))) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* Point dequeue/enqueue pointers at first entry in ring */
+	out_be32((void *)&msg_regs->ifqdpar, (u32) msg_rx_ring.phys);
+	out_be32((void *)&msg_regs->ifqepar, (u32) msg_rx_ring.phys);
+
+	/* Clear interrupt status */
+	out_be32((void *)&msg_regs->isr, 0x00000091);
+
+	/* Hook up inbound message handler */
+	if ((rc =
+	     request_irq(MPC85xx_IRQ_RIO_RX, mpc85xx_rio_rx_handler, 0,
+			 "msg_rx", (void *)mport)) < 0) {
+		dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+				  msg_tx_ring.virt_buffer[i],
+				  msg_tx_ring.phys_buffer[i]);
+		goto out;
+	}
+
+	/*
+	 * Configure inbound message unit:
+	 *      Snooping
+	 *      4KB max message size
+	 *      Unmask all interrupt sources
+	 *      Disable
+	 */
+	out_be32((void *)&msg_regs->imr, 0x001b0060);
+
+	/* Set number of queue entries */
+	out_be32((void *)&msg_regs->imr,
+		 in_be32((void *)&msg_regs->imr) |
+		 ((get_bitmask_order(entries) - 2) << 12));
+
+	/* Now enable the unit */
+	out_be32((void *)&msg_regs->imr, in_be32((void *)&msg_regs->imr) | 0x1);
+
+      out:
+	return rc;
+}
+
+/**
+ * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox
+ * @mport: Master port implementing the inbound message unit
+ * @mbox: Mailbox to close
+ *
+ * Disables the inbound message unit, free all buffers, and
+ * frees the inbound message interrupt.
+ */
+void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
+{
+	/* Disable inbound message unit */
+	out_be32((void *)&msg_regs->imr, 0);
+
+	/* Free ring */
+	dma_free_coherent(NULL, msg_rx_ring.size * RIO_MAX_MSG_SIZE,
+			  msg_rx_ring.virt, msg_rx_ring.phys);
+
+	/* Free interrupt */
+	free_irq(MPC85xx_IRQ_RIO_RX, (void *)mport);
+}
+
+/**
+ * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
+ * @mport: Master port implementing the inbound message unit
+ * @mbox: Inbound mailbox number
+ * @buf: Buffer to add to inbound queue
+ *
+ * Adds the @buf buffer to the MPC85xx inbound message queue. Returns
+ * %0 on success or %-EINVAL on failure.
+ */
+int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
+{
+	int rc = 0;
+
+	pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
+		 msg_rx_ring.rx_slot);
+
+	if (msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot]) {
+		printk(KERN_ERR
+		       "RIO: error adding inbound buffer %d, buffer exists\n",
+		       msg_rx_ring.rx_slot);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot] = buf;
+	if (++msg_rx_ring.rx_slot == msg_rx_ring.size)
+		msg_rx_ring.rx_slot = 0;
+
+      out:
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer);
+
+/**
+ * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit
+ * @mport: Master port implementing the inbound message unit
+ * @mbox: Inbound mailbox number
+ *
+ * Gets the next available inbound message from the inbound message queue.
+ * A pointer to the message is returned on success or NULL on failure.
+ */
+void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
+{
+	u32 imr;
+	u32 phys_buf, virt_buf;
+	void *buf = NULL;
+	int buf_idx;
+
+	phys_buf = in_be32((void *)&msg_regs->ifqdpar);
+
+	/* If no more messages, then bail out */
+	if (phys_buf == in_be32((void *)&msg_regs->ifqepar))
+		goto out2;
+
+	virt_buf = (u32) msg_rx_ring.virt + (phys_buf - msg_rx_ring.phys);
+	buf_idx = (phys_buf - msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
+	buf = msg_rx_ring.virt_buffer[buf_idx];
+
+	if (!buf) {
+		printk(KERN_ERR
+		       "RIO: inbound message copy failed, no buffers\n");
+		goto out1;
+	}
+
+	/* Copy max message size, caller is expected to allocate that big */
+	memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE);
+
+	/* Clear the available buffer */
+	msg_rx_ring.virt_buffer[buf_idx] = NULL;
+
+      out1:
+	imr = in_be32((void *)&msg_regs->imr);
+	out_be32((void *)&msg_regs->imr, imr | RIO_MSG_IMR_MI);
+
+      out2:
+	return buf;
+}
+
+EXPORT_SYMBOL_GPL(rio_hw_get_inb_message);
+
+/**
+ * mpc85xx_rio_dbell_handler - MPC85xx doorbell interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ * @regs: Register context
+ *
+ * Handles doorbell interrupts. Parses a list of registered
+ * doorbell event handlers and executes a matching event handler.
+ */
+static irqreturn_t
+mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	int dsr;
+	struct rio_mport *port = (struct rio_mport *)dev_instance;
+
+	dsr = in_be32((void *)&msg_regs->dsr);
+
+	if (dsr & DOORBELL_DSR_TE) {
+		pr_info("RIO: doorbell reception error\n");
+		out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_TE);
+		goto out;
+	}
+
+	if (dsr & DOORBELL_DSR_QFI) {
+		pr_info("RIO: doorbell queue full\n");
+		out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_QFI);
+		goto out;
+	}
+
+	/* XXX Need to check/dispatch until queue empty */
+	if (dsr & DOORBELL_DSR_DIQI) {
+		u32 dmsg =
+		    (u32) dbell_ring.virt +
+		    (in_be32((void *)&msg_regs->dqdpar) & 0xfff);
+		u32 dmr;
+		struct rio_dbell *dbell;
+		int found = 0;
+
+		pr_debug
+		    ("RIO: processing doorbell, sid %2.2x tid %2.2x info %4.4x\n",
+		     DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
+
+		list_for_each_entry(dbell, &port->dbells, node) {
+			if ((dbell->res->start <= DBELL_INF(dmsg)) &&
+			    (dbell->res->end >= DBELL_INF(dmsg))) {
+				found = 1;
+				break;
+			}
+		}
+		if (found) {
+			dbell->dinb(port, DBELL_SID(dmsg), DBELL_TID(dmsg),
+				    DBELL_INF(dmsg));
+		} else {
+			pr_debug
+			    ("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n",
+			     DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
+		}
+		dmr = in_be32((void *)&msg_regs->dmr);
+		out_be32((void *)&msg_regs->dmr, dmr | DOORBELL_DMR_DI);
+		out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_DIQI);
+	}
+
+      out:
+	return IRQ_HANDLED;
+}
+
+/**
+ * mpc85xx_rio_doorbell_init - MPC85xx doorbell interface init
+ * @mport: Master port implementing the inbound doorbell unit
+ *
+ * Initializes doorbell unit hardware and inbound DMA buffer
+ * ring. Called from mpc85xx_rio_setup(). Returns %0 on success
+ * or %-ENOMEM on failure.
+ */
+static int mpc85xx_rio_doorbell_init(struct rio_mport *mport)
+{
+	int rc = 0;
+
+	/* Map outbound doorbell window immediately after maintenance window */
+	if (!(dbell_win =
+	      (u32) ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
+			    RIO_DBELL_WIN_SIZE))) {
+		printk(KERN_ERR
+		       "RIO: unable to map outbound doorbell window\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* Initialize inbound doorbells */
+	if (!(dbell_ring.virt = dma_alloc_coherent(NULL,
+						   512 * DOORBELL_MESSAGE_SIZE,
+						   &dbell_ring.phys,
+						   GFP_KERNEL))) {
+		printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
+		rc = -ENOMEM;
+		iounmap((void *)dbell_win);
+		goto out;
+	}
+
+	/* Point dequeue/enqueue pointers at first entry in ring */
+	out_be32((void *)&msg_regs->dqdpar, (u32) dbell_ring.phys);
+	out_be32((void *)&msg_regs->dqepar, (u32) dbell_ring.phys);
+
+	/* Clear interrupt status */
+	out_be32((void *)&msg_regs->dsr, 0x00000091);
+
+	/* Hook up doorbell handler */
+	if ((rc =
+	     request_irq(MPC85xx_IRQ_RIO_BELL, mpc85xx_rio_dbell_handler, 0,
+			 "dbell_rx", (void *)mport) < 0)) {
+		iounmap((void *)dbell_win);
+		dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE,
+				  dbell_ring.virt, dbell_ring.phys);
+		printk(KERN_ERR
+		       "MPC85xx RIO: unable to request inbound doorbell irq");
+		goto out;
+	}
+
+	/* Configure doorbells for snooping, 512 entries, and enable */
+	out_be32((void *)&msg_regs->dmr, 0x00108161);
+
+      out:
+	return rc;
+}
+
+static char *cmdline = NULL;
+
+static int mpc85xx_rio_get_hdid(int index)
+{
+	/* XXX Need to parse multiple entries in some format */
+	if (!cmdline)
+		return -1;
+
+	return simple_strtol(cmdline, NULL, 0);
+}
+
+static int mpc85xx_rio_get_cmdline(char *s)
+{
+	if (!s)
+		return 0;
+
+	cmdline = s;
+	return 1;
+}
+
+__setup("riohdid=", mpc85xx_rio_get_cmdline);
+
+/**
+ * mpc85xx_rio_setup - Setup MPC85xx RapidIO interface
+ * @law_start: Starting physical address of RapidIO LAW
+ * @law_size: Size of RapidIO LAW
+ *
+ * Initializes MPC85xx RapidIO hardware interface, configures
+ * master port with system-specific info, and registers the
+ * master port with the RapidIO subsystem.
+ */
+void mpc85xx_rio_setup(int law_start, int law_size)
+{
+	struct rio_ops *ops;
+	struct rio_mport *port;
+
+	ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL);
+	ops->lcread = mpc85xx_local_config_read;
+	ops->lcwrite = mpc85xx_local_config_write;
+	ops->cread = mpc85xx_rio_config_read;
+	ops->cwrite = mpc85xx_rio_config_write;
+	ops->dsend = mpc85xx_rio_doorbell_send;
+
+	port = kmalloc(sizeof(struct rio_mport), GFP_KERNEL);
+	port->id = 0;
+	port->index = 0;
+	INIT_LIST_HEAD(&port->dbells);
+	port->iores.start = law_start;
+	port->iores.end = law_start + law_size;
+	port->iores.flags = IORESOURCE_MEM;
+
+	rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
+	rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
+	rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
+	strcpy(port->name, "RIO0 mport");
+
+	port->ops = ops;
+	port->host_deviceid = mpc85xx_rio_get_hdid(port->id);
+
+	rio_register_mport(port);
+
+	regs_win = (u32) ioremap(RIO_REGS_BASE, 0x20000);
+	atmu_regs = (struct rio_atmu_regs *)(regs_win + RIO_ATMU_REGS_OFFSET);
+	maint_atmu_regs = atmu_regs + 1;
+	dbell_atmu_regs = atmu_regs + 2;
+	msg_regs = (struct rio_msg_regs *)(regs_win + RIO_MSG_REGS_OFFSET);
+
+	/* Configure maintenance transaction window */
+	out_be32((void *)&maint_atmu_regs->rowbar, 0x000c0000);
+	out_be32((void *)&maint_atmu_regs->rowar, 0x80077015);
+
+	maint_win = (u32) ioremap(law_start, RIO_MAINT_WIN_SIZE);
+
+	/* Configure outbound doorbell window */
+	out_be32((void *)&dbell_atmu_regs->rowbar, 0x000c0400);
+	out_be32((void *)&dbell_atmu_regs->rowar, 0x8004200b);
+	mpc85xx_rio_doorbell_init(port);
+}
diff --git a/arch/ppc/syslib/ppc85xx_rio.h b/arch/ppc/syslib/ppc85xx_rio.h
new file mode 100644
index 0000000000..c0827a2c3e
--- /dev/null
+++ b/arch/ppc/syslib/ppc85xx_rio.h
@@ -0,0 +1,21 @@
+/*
+ * MPC85xx RapidIO definitions
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PPC_SYSLIB_PPC85XX_RIO_H
+#define __PPC_SYSLIB_PPC85XX_RIO_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+extern void mpc85xx_rio_setup(int law_start, int law_size);
+
+#endif				/* __PPC_SYSLIB_PPC85XX_RIO_H */
-- 
cgit v1.2.2


From 6978bbc097c2f665c336927a9d56ae39ef75fa56 Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@kernel.crashing.org>
Date: Mon, 7 Nov 2005 01:00:20 -0800
Subject: [PATCH] rapidio: message interface updates

Updates the RIO messaging interface to pass a device instance into the
event registeration and callbacks.

Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/syslib/ppc85xx_rio.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

(limited to 'arch')

diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c
index 9d09c2715e..297f3b5491 100644
--- a/arch/ppc/syslib/ppc85xx_rio.c
+++ b/arch/ppc/syslib/ppc85xx_rio.c
@@ -135,6 +135,7 @@ static struct rio_msg_tx_ring {
 	dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE];
 	int tx_slot;
 	int size;
+	void *dev_id;
 } msg_tx_ring;
 
 static struct rio_msg_rx_ring {
@@ -143,6 +144,7 @@ static struct rio_msg_rx_ring {
 	void *virt_buffer[RIO_MAX_RX_RING_SIZE];
 	int rx_slot;
 	int size;
+	void *dev_id;
 } msg_rx_ring;
 
 /**
@@ -376,7 +378,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs)
 	if (osr & RIO_MSG_OSR_EOMI) {
 		u32 dqp = in_be32((void *)&msg_regs->odqdpar);
 		int slot = (dqp - msg_tx_ring.phys) >> 5;
-		port->outb_msg[0].mcback(port, -1, slot);
+		port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot);
 
 		/* Ack the end-of-message interrupt */
 		out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI);
@@ -389,6 +391,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs)
 /**
  * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox
  * @mport: Master port implementing the outbound message unit
+ * @dev_id: Device specific pointer to pass on event
  * @mbox: Mailbox to open
  * @entries: Number of entries in the outbound mailbox ring
  *
@@ -396,7 +399,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs)
  * and enables the outbound message unit. Returns %0 on success and
  * %-EINVAL or %-ENOMEM on failure.
  */
-int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries)
+int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
 {
 	int i, j, rc = 0;
 
@@ -407,6 +410,7 @@ int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries)
 	}
 
 	/* Initialize shadow copy ring */
+	msg_tx_ring.dev_id = dev_id;
 	msg_tx_ring.size = entries;
 
 	for (i = 0; i < msg_tx_ring.size; i++) {
@@ -541,7 +545,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs)
 		 * make the callback with an unknown/invalid mailbox number
 		 * argument.
 		 */
-		port->inb_msg[0].mcback(port, -1, -1);
+		port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1);
 
 		/* Ack the queueing interrupt */
 		out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI);
@@ -554,6 +558,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs)
 /**
  * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox
  * @mport: Master port implementing the inbound message unit
+ * @dev_id: Device specific pointer to pass on event
  * @mbox: Mailbox to open
  * @entries: Number of entries in the inbound mailbox ring
  *
@@ -561,7 +566,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs)
  * and enables the inbound message unit. Returns %0 on success
  * and %-EINVAL or %-ENOMEM on failure.
  */
-int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries)
+int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
 {
 	int i, rc = 0;
 
@@ -572,6 +577,7 @@ int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries)
 	}
 
 	/* Initialize client buffer ring */
+	msg_rx_ring.dev_id = dev_id;
 	msg_rx_ring.size = entries;
 	msg_rx_ring.rx_slot = 0;
 	for (i = 0; i < msg_rx_ring.size; i++)
@@ -777,7 +783,7 @@ mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs)
 			}
 		}
 		if (found) {
-			dbell->dinb(port, DBELL_SID(dmsg), DBELL_TID(dmsg),
+			dbell->dinb(port, dbell->dev_id, DBELL_SID(dmsg), DBELL_TID(dmsg),
 				    DBELL_INF(dmsg));
 		} else {
 			pr_debug
-- 
cgit v1.2.2


From 9e173c031a7542b1f66b6da853772e5de1804399 Mon Sep 17 00:00:00 2001
From: Nishanth Aravamudan <nacc@us.ibm.com>
Date: Mon, 7 Nov 2005 01:01:11 -0800
Subject: [PATCH] ia64: fix-up schedule_timeout() usage

Use schedule_timeout_interruptible() instead of
set_current_state()/schedule_timeout() to reduce kernel size.

Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ia64/hp/sim/simserial.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'arch')

diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index b42ec37be5..19ee635eeb 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -642,10 +642,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 	info->event = 0;
 	info->tty = 0;
 	if (info->blocked_open) {
-		if (info->close_delay) {
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(info->close_delay);
-		}
+		if (info->close_delay)
+			schedule_timeout_interruptible(info->close_delay);
 		wake_up_interruptible(&info->open_wait);
 	}
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-- 
cgit v1.2.2


From 28faa4298ec069d1de4f54597f963be8ef35e706 Mon Sep 17 00:00:00 2001
From: Nishanth Aravamudan <nacc@us.ibm.com>
Date: Mon, 7 Nov 2005 01:01:12 -0800
Subject: [PATCH] m68k: fix-up schedule_timeout() usage

Use schedule_timeout_interruptible() instead of
set_current_state()/schedule_timeout() to reduce kernel size.

Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: <geert@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68k/atari/time.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'arch')

diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 6df7fb60df..e79bbc9421 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -212,10 +212,8 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
      * additionally the RTC_SET bit is set to prevent an update cycle.
      */
 
-    while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
-        current->state = TASK_INTERRUPTIBLE;
-        schedule_timeout(HWCLK_POLL_INTERVAL);
-    }
+    while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP )
+        schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
 
     local_irq_save(flags);
     RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
-- 
cgit v1.2.2


From 8f09f4a25a927080e1fa1331735c3d1b5664866b Mon Sep 17 00:00:00 2001
From: Nishanth Aravamudan <nacc@us.ibm.com>
Date: Mon, 7 Nov 2005 01:01:13 -0800
Subject: [PATCH] ppc: fix-up schedule_timeout() usage

Use schedule_timeout_interruptible() instead of
set_current_state()/schedule_timeout() to reduce kernel size.  Also use
human-time conversion functions instead of hard-coded HZ division to avoid
rounding errors.

Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/ppc/4xx_io/serial_sicc.c | 17 +++++++----------
 arch/ppc/8260_io/fcc_enet.c   |  3 +--
 2 files changed, 8 insertions(+), 12 deletions(-)

(limited to 'arch')

diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c
index e95c48d575..84d96b857e 100644
--- a/arch/ppc/4xx_io/serial_sicc.c
+++ b/arch/ppc/4xx_io/serial_sicc.c
@@ -1145,8 +1145,8 @@ static int set_serial_info(struct SICC_info *info,
     info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
                (info->flags & ASYNC_INTERNAL_FLAGS));
     state->custom_divisor = new_serial.custom_divisor;
-    state->close_delay = new_serial.close_delay * HZ / 100;
-    state->closing_wait = new_serial.closing_wait * HZ / 100;
+    state->close_delay = msecs_to_jiffies(10 * new_serial.close_delay);
+    state->closing_wait = msecs_to_jiffies(10 * new_serial.closing_wait);
     info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
     port->fifosize = new_serial.xmit_fifo_size;
 
@@ -1465,10 +1465,8 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp)
     info->event = 0;
     info->tty = NULL;
     if (info->blocked_open) {
-        if (info->state->close_delay) {
-            set_current_state(TASK_INTERRUPTIBLE);
-            schedule_timeout(info->state->close_delay);
-        }
+        if (info->state->close_delay)
+            schedule_timeout_interruptible(info->state->close_delay);
         wake_up_interruptible(&info->open_wait);
     }
     info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -1496,7 +1494,7 @@ static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout)
      * Note: we have to use pretty tight timings here to satisfy
      * the NIST-PCTS.
      */
-    char_time = (info->timeout - HZ/50) / info->port->fifosize;
+    char_time = (info->timeout - msecs_to_jiffies(20)) / info->port->fifosize;
     char_time = char_time / 5;
     if (char_time == 0)
         char_time = 1;
@@ -1521,8 +1519,7 @@ static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout)
            tty->index, jiffies,
            expire, char_time);
     while ((readb(info->port->uart_base + BL_SICC_LSR) & _LSR_TX_ALL) != _LSR_TX_ALL) {
-        set_current_state(TASK_INTERRUPTIBLE);
-        schedule_timeout(char_time);
+        schedule_timeout_interruptible(char_time);
         if (signal_pending(current))
             break;
         if (timeout && time_after(jiffies, expire))
@@ -1773,7 +1770,7 @@ int __init siccuart_init(void)
     for (i = 0; i < SERIAL_SICC_NR; i++) {
         struct SICC_state *state = sicc_state + i;
         state->line     = i;
-        state->close_delay  = 5 * HZ / 10;
+        state->close_delay  = msecs_to_jiffies(500);
         state->closing_wait = 30 * HZ;
 	spin_lock_init(&state->sicc_lock);
     }
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index 2086c6ad11..4edeede9cc 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -1309,8 +1309,7 @@ static void mii_dm9161_wait(uint mii_reg, struct net_device *dev)
 
 	/* Davicom takes a bit to come up after a reset,
 	 * so wait here for a bit */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(timeout);
+	schedule_timeout_uninterruptible(timeout);
 }
 
 static phy_info_t phy_info_dm9161 = {
-- 
cgit v1.2.2


From bc874d174b224c016adac85fc9dd6da1161ffc57 Mon Sep 17 00:00:00 2001
From: Nishanth Aravamudan <nacc@us.ibm.com>
Date: Mon, 7 Nov 2005 01:01:14 -0800
Subject: [PATCH] um: fix-up schedule_timeout() usage

Use schedule_timeout_interruptible() instead of
set_current_state()/schedule_timeout() to reduce kernel size.

Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Acked-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/um/drivers/random.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'arch')

diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index f9e22198e0..ba471f5864 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -58,10 +58,8 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
                         if (filp->f_flags & O_NONBLOCK)
                                 return ret ? : -EAGAIN;
 
-                        if(need_resched()){
-                                current->state = TASK_INTERRUPTIBLE;
-                                schedule_timeout(1);
-                        }
+                        if(need_resched())
+                                schedule_timeout_interruptible(1);
                 }
                 else return n;
 		if (signal_pending (current))
-- 
cgit v1.2.2


From b2325fe1b7e5654fac9e9419423aa2c58a3dbd83 Mon Sep 17 00:00:00 2001
From: Jesper Juhl <jesper.juhl@gmail.com>
Date: Mon, 7 Nov 2005 01:01:35 -0800
Subject: [PATCH] kfree cleanup: arch

This is the arch/ part of the big kfree cleanup patch.

Remove pointless checks for NULL prior to calling kfree() in arch/.

Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
Acked-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/arm/mach-integrator/impd1.c          |  3 +--
 arch/cris/arch-v32/drivers/cryptocop.c    | 14 +++++++-------
 arch/ia64/kernel/perfmon.c                |  2 +-
 arch/powerpc/platforms/pseries/reconfig.c |  6 ++----
 arch/ppc/8xx_io/cs4218_tdm.c              |  3 +--
 arch/ppc/syslib/prom.c                    |  6 ++----
 arch/ppc64/kernel/lparcfg.c               |  4 +---
 arch/ppc64/kernel/scanlog.c               |  3 +--
 arch/s390/mm/extmem.c                     |  8 ++++----
 arch/sparc64/kernel/us2e_cpufreq.c        |  7 ++-----
 arch/sparc64/kernel/us3_cpufreq.c         |  7 ++-----
 arch/um/kernel/sigio_user.c               |  2 +-
 12 files changed, 25 insertions(+), 40 deletions(-)

(limited to 'arch')

diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index a1b153d162..a4bafee77a 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -420,8 +420,7 @@ static int impd1_probe(struct lm_device *dev)
  free_impd1:
 	if (impd1 && impd1->base)
 		iounmap(impd1->base);
-	if (impd1)
-		kfree(impd1);
+	kfree(impd1);
  release_lm:
 	release_mem_region(dev->resource.start, SZ_4K);
 	return ret;
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index ca72076c63..501fa52d8d 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -277,7 +277,7 @@ struct file_operations cryptocop_fops = {
 static void free_cdesc(struct cryptocop_dma_desc *cdesc)
 {
 	DEBUG(printk("free_cdesc: cdesc 0x%p, from_pool=%d\n", cdesc, cdesc->from_pool));
-	if (cdesc->free_buf) kfree(cdesc->free_buf);
+	kfree(cdesc->free_buf);
 
 	if (cdesc->from_pool) {
 		unsigned long int flags;
@@ -2950,15 +2950,15 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
 		put_page(outpages[i]);
 	}
 
-	if (digest_result) kfree(digest_result);
-	if (inpages) kfree(inpages);
-	if (outpages) kfree(outpages);
+	kfree(digest_result);
+	kfree(inpages);
+	kfree(outpages);
 	if (cop){
-		if (cop->tfrm_op.indata) kfree(cop->tfrm_op.indata);
-		if (cop->tfrm_op.outdata) kfree(cop->tfrm_op.outdata);
+		kfree(cop->tfrm_op.indata);
+		kfree(cop->tfrm_op.outdata);
 		kfree(cop);
 	}
-	if (jc) kfree(jc);
+	kfree(jc);
 
 	DEBUG(print_lock_status());
 
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index f7dfc107cb..410d4804fa 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -4940,7 +4940,7 @@ abort_locked:
 	if (call_made && PFM_CMD_RW_ARG(cmd) && copy_to_user(arg, args_k, base_sz*count)) ret = -EFAULT;
 
 error_args:
-	if (args_k) kfree(args_k);
+	kfree(args_k);
 
 	DPRINT(("cmd=%s ret=%ld\n", PFM_CMD_NAME(cmd), ret));
 
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 58c61219d0..d7d4003394 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -286,10 +286,8 @@ static struct property *new_property(const char *name, const int length,
 	return new;
 
 cleanup:
-	if (new->name)
-		kfree(new->name);
-	if (new->value)
-		kfree(new->value);
+	kfree(new->name);
+	kfree(new->value);
 	kfree(new);
 	return NULL;
 }
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index 532caa388d..49eb2a7e65 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -1013,8 +1013,7 @@ static void CS_IrqCleanup(void)
 	*/
 	cpm_free_handler(CPMVEC_SMC2);
 
-	if (beep_buf)
-		kfree(beep_buf);
+	kfree(beep_buf);
 	kd_mksound = orig_mksound;
 }
 #endif /* MODULE */
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
index 278da6ee62..1b9aa0d6a9 100644
--- a/arch/ppc/syslib/prom.c
+++ b/arch/ppc/syslib/prom.c
@@ -1335,10 +1335,8 @@ release_OF_resource(struct device_node* node, int index)
 	if (!res)
 		return -ENODEV;
 
-	if (res->name) {
-		kfree(res->name);
-		res->name = NULL;
-	}
+	kfree(res->name);
+	res->name = NULL;
 	release_resource(res);
 	kfree(res);
 
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index e86155770b..3e7b2f28ec 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -599,9 +599,7 @@ int __init lparcfg_init(void)
 void __exit lparcfg_cleanup(void)
 {
 	if (proc_ppc64_lparcfg) {
-		if (proc_ppc64_lparcfg->data) {
-			kfree(proc_ppc64_lparcfg->data);
-		}
+		kfree(proc_ppc64_lparcfg->data);
 		remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);
 	}
 }
diff --git a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c
index 215bf89003..2edc947f7c 100644
--- a/arch/ppc64/kernel/scanlog.c
+++ b/arch/ppc64/kernel/scanlog.c
@@ -225,8 +225,7 @@ int __init scanlog_init(void)
 void __exit scanlog_cleanup(void)
 {
 	if (proc_ppc64_scan_log_dump) {
-		if (proc_ppc64_scan_log_dump->data)
-			kfree(proc_ppc64_scan_log_dump->data);
+		kfree(proc_ppc64_scan_log_dump->data);
 		remove_proc_entry("scan-log-dump", proc_ppc64_scan_log_dump->parent);
 	}
 }
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index c5348108ca..506a33b51e 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -234,8 +234,8 @@ query_segment_type (struct dcss_segment *seg)
 	rc = 0;
 
  out_free:
-	if (qin) kfree(qin);
-	if (qout) kfree(qout);
+	kfree(qin);
+	kfree(qout);
 	return rc;
 }
 
@@ -394,7 +394,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
 				segtype_string[seg->vm_segtype]);
 	goto out;
  out_free:
-	kfree (seg);
+	kfree(seg);
  out:
 	return rc;
 }
@@ -505,7 +505,7 @@ segment_modify_shared (char *name, int do_nonshared)
 	list_del(&seg->list);
 	dcss_diag(DCSS_PURGESEG, seg->dcss_name,
 		  &dummy, &dummy);
-	kfree (seg);
+	kfree(seg);
  out_unlock:
 	spin_unlock(&dcss_lock);
 	return rc;
diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c
index 686e526bec..b35dc8dc99 100644
--- a/arch/sparc64/kernel/us2e_cpufreq.c
+++ b/arch/sparc64/kernel/us2e_cpufreq.c
@@ -388,10 +388,8 @@ err_out:
 			kfree(driver);
 			cpufreq_us2e_driver = NULL;
 		}
-		if (us2e_freq_table) {
-			kfree(us2e_freq_table);
-			us2e_freq_table = NULL;
-		}
+		kfree(us2e_freq_table);
+		us2e_freq_table = NULL;
 		return ret;
 	}
 
@@ -402,7 +400,6 @@ static void __exit us2e_freq_exit(void)
 {
 	if (cpufreq_us2e_driver) {
 		cpufreq_unregister_driver(cpufreq_us2e_driver);
-
 		kfree(cpufreq_us2e_driver);
 		cpufreq_us2e_driver = NULL;
 		kfree(us2e_freq_table);
diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c
index 0340041f61..6d1f9a3c46 100644
--- a/arch/sparc64/kernel/us3_cpufreq.c
+++ b/arch/sparc64/kernel/us3_cpufreq.c
@@ -249,10 +249,8 @@ err_out:
 			kfree(driver);
 			cpufreq_us3_driver = NULL;
 		}
-		if (us3_freq_table) {
-			kfree(us3_freq_table);
-			us3_freq_table = NULL;
-		}
+		kfree(us3_freq_table);
+		us3_freq_table = NULL;
 		return ret;
 	}
 
@@ -263,7 +261,6 @@ static void __exit us3_freq_exit(void)
 {
 	if (cpufreq_us3_driver) {
 		cpufreq_unregister_driver(cpufreq_us3_driver);
-
 		kfree(cpufreq_us3_driver);
 		cpufreq_us3_driver = NULL;
 		kfree(us3_freq_table);
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 3fbfd956bf..48b1f644b9 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -224,7 +224,7 @@ static int need_poll(int n)
 		next_poll.used = n;
 		return(0);
 	}
-	if(next_poll.poll != NULL) kfree(next_poll.poll);
+	kfree(next_poll.poll);
 	next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
 	if(next_poll.poll == NULL){
 		printk("need_poll : failed to allocate new pollfds\n");
-- 
cgit v1.2.2


From 5fed0578be842dd7d24e5240a75b02bbc748501f Mon Sep 17 00:00:00 2001
From: Adrian Bunk <bunk@stusta.de>
Date: Mon, 7 Nov 2005 01:01:46 -0800
Subject: [PATCH] unexport phys_proc_id and cpu_core_id

EXPORT_SYMBOL's for phys_proc_id and cpu_core_id were added this year but
never used.

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/i386/kernel/smpboot.c   | 2 --
 arch/x86_64/kernel/smpboot.c | 2 --
 2 files changed, 4 deletions(-)

(limited to 'arch')

diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index e6488ffc1f..47ec76794d 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -68,11 +68,9 @@ EXPORT_SYMBOL(smp_num_siblings);
 
 /* Package ID of each logical CPU */
 int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
-EXPORT_SYMBOL(phys_proc_id);
 
 /* Core ID of each logical CPU */
 int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
-EXPORT_SYMBOL(cpu_core_id);
 
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_sibling_map);
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 658a81b33f..4b5b088ec1 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -65,8 +65,6 @@ int smp_num_siblings = 1;
 /* Package ID of each logical CPU */
 u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
 u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
-EXPORT_SYMBOL(phys_proc_id);
-EXPORT_SYMBOL(cpu_core_id);
 
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map __read_mostly;
-- 
cgit v1.2.2


From 54b03d133b63223e3c358f882a935d9a244ed852 Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: add ColdFire 5208 setup support

Add setup support for the new Freescale 5208 ColdFire processor.
(Also fixed a little typo in there, "UNKOWN" -> "UNKNOWN").
Patch originally from Matt Waddel (from code originally written by
Mike Lavender).

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/kernel/setup.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'arch')

diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index a220345e97..abb80fa2b9 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -107,6 +107,9 @@ void (*mach_power_off)( void ) = NULL;
 #if defined(CONFIG_M5206e)
 	#define	CPU "COLDFIRE(m5206e)"
 #endif
+#if defined(CONFIG_M520x)
+	#define CPU "COLDFIRE(m520x)"
+#endif
 #if defined(CONFIG_M523x)
 	#define CPU "COLDFIRE(m523x)"
 #endif
@@ -132,7 +135,7 @@ void (*mach_power_off)( void ) = NULL;
 	#define	CPU "COLDFIRE(m5407)"
 #endif
 #ifndef CPU
-	#define	CPU "UNKOWN"
+	#define	CPU "UNKNOWN"
 #endif
 
 /* (es) */
-- 
cgit v1.2.2


From 9c899990ba94d5d6df25ef868aa7d5249653868c Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: add 5208 ColdFire platform Makefile

Add Freescale 5208 ColdFire platform Makefile.
Patch originally from Matt Waddel (from code originally written by
Mike Lavender).

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/platform/520x/Makefile | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 arch/m68knommu/platform/520x/Makefile

(limited to 'arch')

diff --git a/arch/m68knommu/platform/520x/Makefile b/arch/m68knommu/platform/520x/Makefile
new file mode 100644
index 0000000000..e861b05106
--- /dev/null
+++ b/arch/m68knommu/platform/520x/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the M5208 specific file.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+ifdef CONFIG_FULLDEBUG
+AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+endif
+
+obj-y := config.o
-- 
cgit v1.2.2


From 3aec6fe2a24067ffeb2e7641bd9dd18e41654842 Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: use the ColdFire PIT timer for new 5208

The Freescale 5208 ColdFire uses the common PIT timer code for
its internal timer. Build it when configured for the 5208 processor.
Add support for the internal register map of the 5208 ColdFire fmaily.
Patch originally from Matt Waddel (from code originally written by
Mike Lavender).

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/platform/5307/Makefile | 1 +
 1 file changed, 1 insertion(+)

(limited to 'arch')

diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 6fe5a2b8fb..8d1619dc1e 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -19,6 +19,7 @@ endif
 obj-$(CONFIG_COLDFIRE)	+= entry.o vectors.o ints.o
 obj-$(CONFIG_M5206)	+= timers.o
 obj-$(CONFIG_M5206e)	+= timers.o
+obj-$(CONFIG_M520x)	+= pit.o
 obj-$(CONFIG_M523x)	+= pit.o
 obj-$(CONFIG_M5249)	+= timers.o
 obj-$(CONFIG_M527x)     += pit.o
-- 
cgit v1.2.2


From 9ed8a0d6c80bce78c703c85fa2f15db277fde933 Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: add ColdFire 5208 and M5208EVB build support

Add build support for the new Freescale 5208 ColdFire processor,
and its M5208EVB eval board. Patch originally from Matt Waddel.

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/Makefile | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index b8fdf191b8..b6b5c14e55 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -14,6 +14,7 @@ platform-$(CONFIG_M68VZ328)	:= 68VZ328
 platform-$(CONFIG_M68360)	:= 68360
 platform-$(CONFIG_M5206)	:= 5206
 platform-$(CONFIG_M5206e)	:= 5206e
+platform-$(CONFIG_M520x)	:= 520x
 platform-$(CONFIG_M523x)	:= 523x
 platform-$(CONFIG_M5249)	:= 5249
 platform-$(CONFIG_M527x)	:= 527x
@@ -29,7 +30,7 @@ board-$(CONFIG_UCDIMM)		:= ucdimm
 board-$(CONFIG_UCQUICC)		:= uCquicc
 board-$(CONFIG_DRAGEN2)		:= de2
 board-$(CONFIG_ARNEWSH)		:= ARNEWSH
-board-$(CONFIG_MOTOROLA)	:= MOTOROLA
+board-$(CONFIG_FREESCALE)	:= FREESCALE
 board-$(CONFIG_M5235EVB)	:= M5235EVB
 board-$(CONFIG_M5271EVB)	:= M5271EVB
 board-$(CONFIG_M5275EVB)	:= M5275EVB
@@ -41,6 +42,7 @@ board-$(CONFIG_SECUREEDGEMP3)	:= MP3
 board-$(CONFIG_CLEOPATRA)	:= CLEOPATRA
 board-$(CONFIG_senTec)		:= senTec
 board-$(CONFIG_SNEHA) 	        := SNEHA
+board-$(CONFIG_M5208EVB)	:= M5208EVB
 board-$(CONFIG_MOD5272)		:= MOD5272
 BOARD := $(board-y)
 
@@ -56,6 +58,7 @@ MODEL := $(model-y)
 #
 cpuclass-$(CONFIG_M5206)	:= 5307
 cpuclass-$(CONFIG_M5206e)	:= 5307
+cpuclass-$(CONFIG_M520x)	:= 5307
 cpuclass-$(CONFIG_M523x)	:= 5307
 cpuclass-$(CONFIG_M5249)	:= 5307
 cpuclass-$(CONFIG_M527x)	:= 5307
@@ -80,6 +83,7 @@ export PLATFORM BOARD MODEL CPUCLASS
 #
 cflags-$(CONFIG_M5206)		:= -m5200 -Wa,-S -Wa,-m5200
 cflags-$(CONFIG_M5206e)		:= -m5200 -Wa,-S -Wa,-m5200
+cflags-$(CONFIG_M520x)		:= -m5307 -Wa,-S -Wa,-m5307
 cflags-$(CONFIG_M523x)		:= -m5307 -Wa,-S -Wa,-m5307
 cflags-$(CONFIG_M5249)		:= -m5200 -Wa,-S -Wa,-m5200
 cflags-$(CONFIG_M527x)		:= -m5307 -Wa,-S -Wa,-m5307
@@ -95,7 +99,6 @@ cflags-$(CONFIG_M68360)		:= -m68332
 AFLAGS += $(cflags-y)
 
 CFLAGS += $(cflags-y)
-CFLAGS += -fno-builtin
 CFLAGS += -O1 -g
 CFLAGS += -D__linux__
 CFLAGS += -DUTS_SYSNAME=\"uClinux\"
-- 
cgit v1.2.2


From 88a605b02449852213a46f8a8ab760cfc5b9b7c8 Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: platform config code for 5208 ColdFire

Platform configuration code for the Freescale 5208 ColdFire processor.
Patch originally from Matt Waddel (from code originally written by
Mike Lavender).

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/platform/520x/config.c | 65 +++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 arch/m68knommu/platform/520x/config.c

(limited to 'arch')

diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c
new file mode 100644
index 0000000000..71dea2e0f4
--- /dev/null
+++ b/arch/m68knommu/platform/520x/config.c
@@ -0,0 +1,65 @@
+/***************************************************************************/
+
+/*
+ *  linux/arch/m68knommu/platform/520x/config.c
+ *
+ *  Copyright (C) 2005,      Freescale (www.freescale.com)
+ *  Copyright (C) 2005,      Intec Automation (mike@steroidmicros.com)
+ *  Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <asm/machdep.h>
+#include <asm/dma.h>
+
+/***************************************************************************/
+
+/*
+ *	DMA channel base address table.
+ */
+unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS];
+unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+/***************************************************************************/
+
+void coldfire_pit_tick(void);
+void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_pit_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+/***************************************************************************/
+
+/*
+ *  Program the vector to be an auto-vectored.
+ */
+
+void mcf_autovector(unsigned int vec)
+{
+    /* Everything is auto-vectored on the 520x devices */
+}
+
+/***************************************************************************/
+
+void config_BSP(char *commandp, int size)
+{
+#ifdef CONFIG_BOOTPARAM
+    strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
+    commandp[size-1] = 0;
+#else
+    memset(commandp, 0, size);
+#endif
+
+    mach_sched_init = coldfire_pit_init;
+    mach_tick = coldfire_pit_tick;
+    mach_gettimeoffset = coldfire_pit_offset;
+    mach_trap_init = coldfire_trap_init;
+    mach_reset = coldfire_reset;
+}
+
+/***************************************************************************/
-- 
cgit v1.2.2


From f15bf19b49854c984c27209bd4ade31a9c84f4de Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: modify the ColdFire PIT timer for new 5208

Modified common ColdFire PIT timer code to support the 5208 as well.
It uses a different set of mask and interrupt bits than other ColdFire
processors. The defines for these bits have been moved in header
files and set appropriately for the different processor varients.
Patch originally from Matt Waddel.

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/platform/5307/pit.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'arch')

diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c
index a9b2c2e7e2..323f2677e4 100644
--- a/arch/m68knommu/platform/5307/pit.c
+++ b/arch/m68knommu/platform/5307/pit.c
@@ -3,7 +3,7 @@
 /*
  *	pit.c -- Motorola ColdFire PIT timer. Currently this type of
  *	         hardware timer only exists in the Motorola ColdFire
- *		 5270/5271 and 5282 CPUs.
+ *		 5270/5271, 5282 and other CPUs.
  *
  *	Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
  *	Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
@@ -47,10 +47,10 @@ void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
 
 	icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
 		MCFINTC_ICR0 + MCFINT_PIT1);
-	*icrp = 0x2b; /* PIT1 with level 5, priority 3 */
+	*icrp = ICR_INTRCONF;
 
-	imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
-	*imrp &= ~(1 << (MCFINT_PIT1 - 32));
+	imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
+	*imrp &= ~MCFPIT_IMR_IBIT;
 
 	/* Set up PIT timer 1 as poll clock */
 	tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
@@ -70,7 +70,7 @@ unsigned long coldfire_pit_offset(void)
 	unsigned long pmr, pcntr, offset;
 
 	tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
-	ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IPRH);
+	ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
 
 	pmr = *(&tp->pmr);
 	pcntr = *(&tp->pcntr);
@@ -80,7 +80,7 @@ unsigned long coldfire_pit_offset(void)
 	 * timer interupt is pending, then add on a ticks worth of time.
 	 */
 	offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr;
-	if ((offset < (1000000 / HZ / 2)) && (*ipr & (1 << (MCFINT_PIT1 - 32))))
+	if ((offset < (1000000 / HZ / 2)) && (*ipr & MCFPIT_IMR_IBIT))
 		offset += 1000000 / HZ;
 	return offset;	
 }
-- 
cgit v1.2.2


From 5b3d98bb7f2842551bf3dc76ade09826d70a1cbe Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: handle non base address 0 memory of M5208EVB board

The Freescale M5208EVB ColdFire eval board is one of the few that
doesn't have its DRAM based at address 0. Handle this special case
in the common ColdFire startup code.

Patch originally from Matt Waddel.

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/platform/5307/head.S | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'arch')

diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S
index 7f4ba83790..c30c462b99 100644
--- a/arch/m68knommu/platform/5307/head.S
+++ b/arch/m68knommu/platform/5307/head.S
@@ -113,6 +113,9 @@
 #define MEM_BASE	0x02000000
 #define VBR_BASE	0x20000000	/* vectors in SRAM */
 #endif
+#if defined(CONFIG_M5208EVB)
+#define MEM_BASE	0x40000000
+#endif
 
 #ifndef MEM_BASE
 #define	MEM_BASE	0x00000000	/* memory base at address 0 */
-- 
cgit v1.2.2


From 124df2df0c905b8762cd860a0e3fc9201fba8777 Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: align param section and add 5208EVB linker support

Align the param section. It can end up starting on an unalingned
boundary depending on the size of ksymtab_strings. If it is
unaligned things like modules will fail to load with unaligned
access traps.

Add linker scipt support for the M5208EVB board.
Patch originally from Matt Waddel.

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/kernel/vmlinux.lds.S | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'arch')

diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 47f0678719..0eab92ca4b 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -124,6 +124,14 @@
 #define	RAM_LENGTH	0x3e0000
 #endif
 
+/*
+ *	The Freescale 5208EVB board has 32MB of RAM.
+ */
+#if defined(CONFIG_M5208EVB)
+#define	RAM_START	0x40020000
+#define	RAM_LENGTH	0x01e00000
+#endif
+
 /*
  *	The senTec COBRA5272 board has nearly the same memory layout as 
  *	the M5272C3. We assume 16MiB ram.
@@ -275,6 +283,7 @@ SECTIONS {
 		*(__ksymtab_strings)
 
 		/* Built-in module parameters */
+		. = ALIGN(4) ;
 		__start___param = .;
 		*(__param)
 		__stop___param = .;
-- 
cgit v1.2.2


From 4e51f674588009163d70a650bf7bc2a2e914ef89 Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: add ColdFire 5208 configure support

Added support for the new Freescale 5208 ColdFire processor.
Also changed name "Motorola" to new company name "Freescale".

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/Kconfig | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

(limited to 'arch')

diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 8520df9cee..b96498120f 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -71,6 +71,11 @@ config M5206e
 	help
 	  Motorola ColdFire 5206e processor support.
 
+config M520x
+	bool "MCF520x"
+	help
+	   Freescale Coldfire 5207/5208 processor support.
+
 config M523x
 	bool "MCF523x"
 	help
@@ -120,7 +125,7 @@ config M527x
 
 config COLDFIRE
 	bool
-	depends on (M5206 || M5206e || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407)
+	depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407)
 	default y
 
 choice
@@ -322,6 +327,12 @@ config ELITE
 	help
 	  Support for the Motorola M5206eLITE board.
 
+config M5208EVB
+	bool "Freescale M5208EVB board support"
+	depends on M520x
+	help
+	  Support for the Freescale Coldfire M5208EVB.
+
 config M5235EVB
 	bool "Freescale M5235EVB support"
 	depends on M523x
@@ -465,10 +476,10 @@ config ARNEWSH
 	default y
 	depends on (ARN5206 || ARN5307)
 
-config MOTOROLA
+config FREESCALE
 	bool
 	default y
-	depends on (M5206eC3 || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3)
+	depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3)
 
 config HW_FEITH
 	bool
-- 
cgit v1.2.2


From 2ed5e6d09e266bd2288d49aaaf240ed8c468c13c Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@snapgear.com>
Date: Mon, 7 Nov 2005 14:09:50 +1000
Subject: [PATCH] m68knommu: move some platform irq support out of irq.h

Move some of the m68knommu platform specific irq core support
to its own header, irqnode.h. Having it in asm-m68knommu/irq.h
causes some build pain, since it is included in a number of
common code places (and not all the required definitions will
be included at these places).

Signed-off-by: Greg Ungerer <gerg@uclinux.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 arch/m68knommu/kernel/asm-offsets.c | 1 +
 arch/m68knommu/platform/5307/ints.c | 1 +
 2 files changed, 2 insertions(+)

(limited to 'arch')

diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index cd3ffe1265..b988c7bdc6 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -15,6 +15,7 @@
 #include <linux/hardirq.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
+#include <asm/irqnode.h>
 #include <asm/thread_info.h>
 
 #define DEFINE(sym, val) \
diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c
index 0117754d44..a134fb2f05 100644
--- a/arch/m68knommu/platform/5307/ints.c
+++ b/arch/m68knommu/platform/5307/ints.c
@@ -26,6 +26,7 @@
 
 #include <asm/system.h>
 #include <asm/irq.h>
+#include <asm/irqnode.h>
 #include <asm/traps.h>
 #include <asm/page.h>
 #include <asm/machdep.h>
-- 
cgit v1.2.2


From afc4841d8a0118fcce9fd520b21ec1da401603a3 Mon Sep 17 00:00:00 2001
From: Ralf Baechle <ralf@linux-mips.org>
Date: Mon, 31 Oct 2005 00:30:39 +0000
Subject: Turn rtlx upside down.

 o Coding style
 o Race condition on open
 o Switch to dynamic major
 o Header file cleanup

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/kernel/rtlx.c | 197 +++++++++++++++++++++++-------------------------
 1 file changed, 93 insertions(+), 104 deletions(-)

(limited to 'arch')

diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 8c81f3cb4e..1d855112ba 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -20,42 +20,42 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/elf.h>
-#include <linux/seq_file.h>
-#include <linux/syscalls.h>
-#include <linux/moduleloader.h>
-#include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <asm/mipsmtregs.h>
-#include <asm/cacheflush.h>
-#include <asm/atomic.h>
+#include <asm/bitops.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/rtlx.h>
+#include <asm/uaccess.h>
 
-#define RTLX_MAJOR 64
 #define RTLX_TARG_VPE 1
 
-struct rtlx_info *rtlx;
+static struct rtlx_info *rtlx;
 static int major;
 static char module_name[] = "rtlx";
-static inline int spacefree(int read, int write, int size);
+static struct irqaction irq;
+static int irq_num;
+
+static inline int spacefree(int read, int write, int size)
+{
+	if (read == write) {
+		/*
+		 * never fill the buffer completely, so indexes are always
+		 * equal if empty and only empty, or !equal if data available
+		 */
+		return size - 1;
+	}
+
+	return ((read + size - write) % size) - 1;
+}
 
 static struct chan_waitqueues {
 	wait_queue_head_t rt_queue;
 	wait_queue_head_t lx_queue;
 } channel_wqs[RTLX_CHANNELS];
 
-static struct irqaction irq;
-static int irq_num;
-
 extern void *vpe_get_shared(int index);
 
 static void rtlx_dispatch(struct pt_regs *regs)
@@ -63,9 +63,8 @@ static void rtlx_dispatch(struct pt_regs *regs)
 	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs);
 }
 
-irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	irqreturn_t r = IRQ_HANDLED;
 	int i;
 
 	for (i = 0; i < RTLX_CHANNELS; i++) {
@@ -75,30 +74,7 @@ irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 			wake_up_interruptible(&channel_wqs[i].lx_queue);
 	}
 
-	return r;
-}
-
-void dump_rtlx(void)
-{
-	int i;
-
-	printk("id 0x%lx state %d\n", rtlx->id, rtlx->state);
-
-	for (i = 0; i < RTLX_CHANNELS; i++) {
-		struct rtlx_channel *chan = &rtlx->channel[i];
-
-		printk(" rt_state %d lx_state %d buffer_size %d\n",
-		       chan->rt_state, chan->lx_state, chan->buffer_size);
-
-		printk(" rt_read %d rt_write %d\n",
-		       chan->rt_read, chan->rt_write);
-
-		printk(" lx_read %d lx_write %d\n",
-		       chan->lx_read, chan->lx_write);
-
-		printk(" rt_buffer <%s>\n", chan->rt_buffer);
-		printk(" lx_buffer <%s>\n", chan->lx_buffer);
-	}
+	return IRQ_HANDLED;
 }
 
 /* call when we have the address of the shared structure from the SP side. */
@@ -108,7 +84,7 @@ static int rtlx_init(struct rtlx_info *rtlxi)
 
 	if (rtlxi->id != RTLX_ID) {
 		printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi);
-		return (-ENOEXEC);
+		return -ENOEXEC;
 	}
 
 	/* initialise the wait queues */
@@ -120,9 +96,8 @@ static int rtlx_init(struct rtlx_info *rtlxi)
 	/* set up for interrupt handling */
 	memset(&irq, 0, sizeof(struct irqaction));
 
-	if (cpu_has_vint) {
+	if (cpu_has_vint)
 		set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
-	}
 
 	irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
 	irq.handler = rtlx_interrupt;
@@ -132,7 +107,8 @@ static int rtlx_init(struct rtlx_info *rtlxi)
 	setup_irq(irq_num, &irq);
 
 	rtlx = rtlxi;
-	return (0);
+
+	return 0;
 }
 
 /* only allow one open process at a time to open each channel */
@@ -147,36 +123,36 @@ static int rtlx_open(struct inode *inode, struct file *filp)
 	if (rtlx == NULL) {
 		struct rtlx_info **p;
 		if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
-			printk(" vpe_get_shared is NULL. Has an SP program been loaded?\n");
-			return (-EFAULT);
+			printk(KERN_ERR "vpe_get_shared is NULL. "
+			       "Has an SP program been loaded?\n");
+			return -EFAULT;
 		}
 
 		if (*p == NULL) {
-			printk(" vpe_shared %p %p\n", p, *p);
-			return (-EFAULT);
+			printk(KERN_ERR "vpe_shared %p %p\n", p, *p);
+			return -EFAULT;
 		}
 
 		if ((ret = rtlx_init(*p)) < 0)
-			return (ret);
+			return ret;
 	}
 
 	chan = &rtlx->channel[minor];
 
-	/* already open? */
-	if (chan->lx_state == RTLX_STATE_OPENED)
-		return (-EBUSY);
+	if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state))
+		return -EBUSY;
 
-	chan->lx_state = RTLX_STATE_OPENED;
-	return (0);
+	return 0;
 }
 
 static int rtlx_release(struct inode *inode, struct file *filp)
 {
-	int minor;
+	int minor = MINOR(inode->i_rdev);
 
-	minor = MINOR(inode->i_rdev);
-	rtlx->channel[minor].lx_state = RTLX_STATE_UNUSED;
-	return (0);
+	clear_bit(RTLX_STATE_OPENED, &rtlx->channel[minor].lx_state);
+	smp_mb__after_clear_bit();
+
+	return 0;
 }
 
 static unsigned int rtlx_poll(struct file *file, poll_table * wait)
@@ -199,12 +175,13 @@ static unsigned int rtlx_poll(struct file *file, poll_table * wait)
 	if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size))
 		mask |= POLLOUT | POLLWRNORM;
 
-	return (mask);
+	return mask;
 }
 
 static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count,
 			 loff_t * ppos)
 {
+	unsigned long failed;
 	size_t fl = 0L;
 	int minor;
 	struct rtlx_channel *lx;
@@ -216,7 +193,7 @@ static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count,
 	/* data available? */
 	if (lx->lx_write == lx->lx_read) {
 		if (file->f_flags & O_NONBLOCK)
-			return (0);	// -EAGAIN makes cat whinge
+			return 0;	/* -EAGAIN makes cat whinge */
 
 		/* go to sleep */
 		add_wait_queue(&channel_wqs[minor].lx_queue, &wait);
@@ -232,39 +209,39 @@ static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count,
 	}
 
 	/* find out how much in total */
-	count = min( count,
-		     (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size);
+	count = min(count,
+		    (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size);
 
 	/* then how much from the read pointer onwards */
-	fl = min( count, (size_t)lx->buffer_size - lx->lx_read);
+	fl = min(count, (size_t)lx->buffer_size - lx->lx_read);
 
-	copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl);
+	failed = copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl);
+	if (failed) {
+		count = fl - failed;
+		goto out;
+	}
 
 	/* and if there is anything left at the beginning of the buffer */
-	if ( count - fl )
-		copy_to_user (buffer + fl, lx->lx_buffer, count - fl);
+	if (count - fl) {
+		failed = copy_to_user (buffer + fl, lx->lx_buffer, count - fl);
+		if (failed) {
+			count -= failed;
+			goto out;
+		}
+	}
 
+out:
 	/* update the index */
 	lx->lx_read += count;
 	lx->lx_read %= lx->buffer_size;
 
-	return (count);
-}
-
-static inline int spacefree(int read, int write, int size)
-{
-	if (read == write) {
-		/* never fill the buffer completely, so indexes are always equal if empty
-		   and only empty, or !equal if data available */
-		return (size - 1);
-	}
-
-	return ((read + size - write) % size) - 1;
+	return count;
 }
 
 static ssize_t rtlx_write(struct file *file, const char __user * buffer,
 			  size_t count, loff_t * ppos)
 {
+	unsigned long failed;
 	int minor;
 	struct rtlx_channel *rt;
 	size_t fl;
@@ -277,7 +254,7 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer,
 	if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) {
 
 		if (file->f_flags & O_NONBLOCK)
-			return (-EAGAIN);
+			return -EAGAIN;
 
 		add_wait_queue(&channel_wqs[minor].rt_queue, &wait);
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -290,52 +267,64 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer,
 	}
 
 	/* total number of bytes to copy */
-	count = min( count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) );
+	count = min(count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) );
 
 	/* first bit from write pointer to the end of the buffer, or count */
 	fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
 
-	copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl);
+	failed = copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl);
+	if (failed) {
+		count = fl - failed;
+		goto out;
+	}
 
 	/* if there's any left copy to the beginning of the buffer */
-	if( count - fl )
-		copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
+	if (count - fl) {
+		failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
+		if (failed) {
+			count -= failed;
+			goto out;
+		}
+	}
 
+out:
 	rt->rt_write += count;
 	rt->rt_write %= rt->buffer_size;
 
-	return(count);
+	return count;
 }
 
 static struct file_operations rtlx_fops = {
-	.owner = THIS_MODULE,
-	.open = rtlx_open,
-	.release = rtlx_release,
-	.write = rtlx_write,
-	.read = rtlx_read,
-	.poll = rtlx_poll
+	.owner		= THIS_MODULE,
+	.open		= rtlx_open,
+	.release	= rtlx_release,
+	.write		= rtlx_write,
+	.read		= rtlx_read,
+	.poll		= rtlx_poll
 };
 
-static int rtlx_module_init(void)
+static char register_chrdev_failed[] __initdata =
+	KERN_ERR "rtlx_module_init: unable to register device\n";
+
+static int __init rtlx_module_init(void)
 {
-	if ((major = register_chrdev(RTLX_MAJOR, module_name, &rtlx_fops)) < 0) {
-		printk("rtlx_module_init: unable to register device\n");
-		return (-EBUSY);
+	major = register_chrdev(0, module_name, &rtlx_fops);
+	if (major < 0) {
+		printk(register_chrdev_failed);
+		return major;
 	}
 
-	if (major == 0)
-		major = RTLX_MAJOR;
-
-	return (0);
+	return 0;
 }
 
-static void rtlx_module_exit(void)
+static void __exit rtlx_module_exit(void)
 {
 	unregister_chrdev(major, module_name);
 }
 
 module_init(rtlx_module_init);
 module_exit(rtlx_module_exit);
+
 MODULE_DESCRIPTION("MIPS RTLX");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc");
+MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc.");
 MODULE_LICENSE("GPL");
-- 
cgit v1.2.2


From b8c2a77ce38defcf539a4ba5c666f8e9f093f887 Mon Sep 17 00:00:00 2001
From: Ralf Baechle <ralf@linux-mips.org>
Date: Mon, 31 Oct 2005 13:08:37 +0000
Subject: PNX8550 uses a MIPS32-like processor core, not R4xx0.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/Kconfig                         |  2 +-
 arch/mips/configs/pnx8550-jbs_defconfig   | 11 ++++++-----
 arch/mips/configs/pnx8550-v2pci_defconfig | 10 ++++++----
 3 files changed, 13 insertions(+), 10 deletions(-)

(limited to 'arch')

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0097a0d53b..e380a8322a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -958,7 +958,7 @@ config SOC_PNX8550
 	bool
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
-	select SYS_HAS_CPU_R4X00
+	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 
 config SWAP_IO_SPACE
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index 95f84d7119..555837e4c0 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -129,7 +129,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R1=y
 # CONFIG_CPU_MIPS32_R2 is not set
 # CONFIG_CPU_MIPS64_R1 is not set
 # CONFIG_CPU_MIPS64_R2 is not set
@@ -137,7 +137,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
 # CONFIG_CPU_R4300 is not set
-CONFIG_CPU_R4X00=y
+# CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
 # CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R5432 is not set
@@ -148,10 +148,11 @@ CONFIG_CPU_R4X00=y
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
@@ -162,11 +163,11 @@ CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index deb24c29ac..05e65206a7 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -128,7 +128,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R1=y
 # CONFIG_CPU_MIPS32_R2 is not set
 # CONFIG_CPU_MIPS64_R1 is not set
 # CONFIG_CPU_MIPS64_R2 is not set
@@ -136,7 +136,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
 # CONFIG_CPU_R4300 is not set
-CONFIG_CPU_R4X00=y
+# CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
 # CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R5432 is not set
@@ -147,10 +147,11 @@ CONFIG_CPU_R4X00=y
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
@@ -161,6 +162,7 @@ CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_ADVANCED=y
-- 
cgit v1.2.2


From 307bd284c205616e02fb85557b97f0e3e969662e Mon Sep 17 00:00:00 2001
From: Ralf Baechle <ralf@linux-mips.org>
Date: Mon, 31 Oct 2005 23:34:52 +0000
Subject: VPE loader janitoring

 o Switch to dynamic major
 o Remove duplicate SHN_MIPS_SCOMMON definition
 o Coding style: remove typedefs.
 o Coding style: reorder to avoid the need for forward declarations
 o Use kzalloc.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/kernel/vpe.c | 100 ++++++++++++++++++++++---------------------------
 1 file changed, 44 insertions(+), 56 deletions(-)

(limited to 'arch')

diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 97fefcc9db..06be405be3 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -58,10 +58,6 @@
 
 typedef void *vpe_handle;
 
-// defined here because the kernel module loader doesn't have
-// anything to do with it.
-#define SHN_MIPS_SCOMMON 0xff03
-
 #ifndef ARCH_SHF_SMALL
 #define ARCH_SHF_SMALL 0
 #endif
@@ -69,11 +65,8 @@ typedef void *vpe_handle;
 /* If this is set, the section belongs in the init part of the module */
 #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
 
-// temp number,
-#define VPE_MAJOR 63
-
 static char module_name[] = "vpe";
-static int major = 0;
+static int major;
 
 /* grab the likely amount of memory we will need. */
 #ifdef CONFIG_MIPS_VPE_LOADER_TOM
@@ -98,22 +91,7 @@ enum tc_state {
 	TC_STATE_DYNAMIC
 };
 
-struct vpe;
-typedef struct tc {
-	enum tc_state state;
-	int index;
-
-	/* parent VPE */
-	struct vpe *pvpe;
-
-	/* The list of TC's with this VPE */
-	struct list_head tc;
-
-	/* The global list of tc's */
-	struct list_head list;
-} tc_t;
-
-typedef struct vpe {
+struct vpe {
 	enum vpe_state state;
 
 	/* (device) minor associated with this vpe */
@@ -135,7 +113,21 @@ typedef struct vpe {
 
 	/* shared symbol address */
 	void *shared_ptr;
-} vpe_t;
+};
+
+struct tc {
+	enum tc_state state;
+	int index;
+
+	/* parent VPE */
+	struct vpe *pvpe;
+
+	/* The list of TC's with this VPE */
+	struct list_head tc;
+
+	/* The global list of tc's */
+	struct list_head list;
+};
 
 struct vpecontrol_ {
 	/* Virtual processing elements */
@@ -146,7 +138,7 @@ struct vpecontrol_ {
 } vpecontrol;
 
 static void release_progmem(void *ptr);
-static void dump_vpe(vpe_t * v);
+static void dump_vpe(struct vpe * v);
 extern void save_gp_address(unsigned int secbase, unsigned int rel);
 
 /* get the vpe associated with this minor */
@@ -197,13 +189,11 @@ struct vpe *alloc_vpe(int minor)
 {
 	struct vpe *v;
 
-	if ((v = kmalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) {
+	if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) {
 		printk(KERN_WARNING "VPE: alloc_vpe no mem\n");
 		return NULL;
 	}
 
-	memset(v, 0, sizeof(struct vpe));
-
 	INIT_LIST_HEAD(&v->tc);
 	list_add_tail(&v->list, &vpecontrol.vpe_list);
 
@@ -216,13 +206,11 @@ struct tc *alloc_tc(int index)
 {
 	struct tc *t;
 
-	if ((t = kmalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) {
+	if ((t = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) {
 		printk(KERN_WARNING "VPE: alloc_tc no mem\n");
 		return NULL;
 	}
 
-	memset(t, 0, sizeof(struct tc));
-
 	INIT_LIST_HEAD(&t->tc);
 	list_add_tail(&t->list, &vpecontrol.tc_list);
 
@@ -412,16 +400,17 @@ static int apply_r_mips_26(struct module *me, uint32_t *location,
 		return -ENOEXEC;
 	}
 
-/* Not desperately convinced this is a good check of an overflow condition
-   anyway. But it gets in the way of handling undefined weak symbols which
-   we want to set to zero.
-   if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-   printk(KERN_ERR
-   "module %s: relocation overflow\n",
-   me->name);
-   return -ENOEXEC;
-   }
-*/
+/*
+ * Not desperately convinced this is a good check of an overflow condition
+ * anyway. But it gets in the way of handling undefined weak symbols which
+ * we want to set to zero.
+ * if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+ * printk(KERN_ERR
+ * "module %s: relocation overflow\n",
+ * me->name);
+ * return -ENOEXEC;
+ * }
+ */
 
 	*location = (*location & ~0x03ffffff) |
 		((*location + (v >> 2)) & 0x03ffffff);
@@ -681,7 +670,7 @@ static void dump_tclist(void)
 }
 
 /* We are prepared so configure and start the VPE... */
-int vpe_run(vpe_t * v)
+int vpe_run(struct vpe * v)
 {
 	unsigned long val;
 	struct tc *t;
@@ -772,7 +761,7 @@ int vpe_run(vpe_t * v)
 	return 0;
 }
 
-static unsigned long find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs,
+static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
 				      unsigned int symindex, const char *strtab,
 				      struct module *mod)
 {
@@ -792,10 +781,12 @@ static unsigned long find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs,
 	return 0;
 }
 
-/* Allocates a VPE with some program code space(the load address), copies the contents
-   of the program (p)buffer performing relocatations/etc, free's it when finished.
+/*
+ * Allocates a VPE with some program code space(the load address), copies
+ * the contents of the program (p)buffer performing relocatations/etc,
+ * free's it when finished.
 */
-int vpe_elfload(vpe_t * v)
+int vpe_elfload(struct vpe * v)
 {
 	Elf_Ehdr *hdr;
 	Elf_Shdr *sechdrs;
@@ -931,7 +922,7 @@ cleanup:
 	return err;
 }
 
-static void dump_vpe(vpe_t * v)
+static void dump_vpe(struct vpe * v)
 {
 	struct tc *t;
 
@@ -947,7 +938,7 @@ static void dump_vpe(vpe_t * v)
 static int vpe_open(struct inode *inode, struct file *filp)
 {
 	int minor;
-	vpe_t *v;
+	struct vpe *v;
 
 	/* assume only 1 device at the mo. */
 	if ((minor = MINOR(inode->i_rdev)) != 1) {
@@ -1001,7 +992,7 @@ static int vpe_open(struct inode *inode, struct file *filp)
 static int vpe_release(struct inode *inode, struct file *filp)
 {
 	int minor, ret = 0;
-	vpe_t *v;
+	struct vpe *v;
 	Elf_Ehdr *hdr;
 
 	minor = MINOR(inode->i_rdev);
@@ -1035,7 +1026,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
 {
 	int minor;
 	size_t ret = count;
-	vpe_t *v;
+	struct vpe *v;
 
 	minor = MINOR(file->f_dentry->d_inode->i_rdev);
 	if ((v = get_vpe(minor)) == NULL)
@@ -1180,14 +1171,11 @@ static int __init vpe_module_init(void)
 		return -ENODEV;
 	}
 
-	if ((major = register_chrdev(VPE_MAJOR, module_name, &vpe_fops) < 0)) {
+	if ((major = register_chrdev(0, module_name, &vpe_fops) < 0)) {
 		printk("VPE loader: unable to register character device\n");
-		return -EBUSY;
+		return major;
 	}
 
-	if (major == 0)
-		major = VPE_MAJOR;
-
 	dmt();
 	dvpe();
 
-- 
cgit v1.2.2


From 15b96a475706bfac71697a5d2f256750bdf749d3 Mon Sep 17 00:00:00 2001
From: Ralf Baechle <ralf@linux-mips.org>
Date: Mon, 7 Nov 2005 18:05:37 +0000
Subject: Add .gitignore files for MIPS.

---
 arch/mips/boot/.gitignore | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 arch/mips/boot/.gitignore

(limited to 'arch')

diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore
new file mode 100644
index 0000000000..ba63401c6e
--- /dev/null
+++ b/arch/mips/boot/.gitignore
@@ -0,0 +1,4 @@
+mkboot
+elf2ecoff
+zImage
+zImage.tmp
-- 
cgit v1.2.2


From 53c2df2f4ebbc1d8231ca7cc13ac5381230888b1 Mon Sep 17 00:00:00 2001
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Thu, 3 Nov 2005 01:01:15 +0900
Subject: Use rtc_lock to protect RTC operations

Many RTC routines were not protected against each other, so there are
potential races, for example, ntp-update against /dev/rtc.  This patch
fixes them using rtc_lock.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/ddb5xxx/common/rtc_ds1386.c  |  6 ++++++
 arch/mips/dec/time.c                   | 24 ++++++++++++++++++++++--
 arch/mips/jmr3927/common/rtc_ds1742.c  |  6 ++++++
 arch/mips/lasat/ds1603.c               |  9 +++++++++
 arch/mips/momentum/jaguar_atx/setup.c  |  6 ++++++
 arch/mips/momentum/ocelot_3/setup.c    |  6 ++++++
 arch/mips/momentum/ocelot_c/setup.c    |  6 ++++++
 arch/mips/pmc-sierra/yosemite/setup.c  |  6 ++++++
 arch/mips/sgi-ip22/ip22-time.c         |  6 ++++++
 arch/mips/sibyte/swarm/rtc_m41t81.c    |  7 +++++++
 arch/mips/sibyte/swarm/rtc_xicor1241.c |  6 ++++++
 11 files changed, 86 insertions(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c
index f5b11508ff..995896ac0e 100644
--- a/arch/mips/ddb5xxx/common/rtc_ds1386.c
+++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c
@@ -41,7 +41,9 @@ rtc_ds1386_get_time(void)
 	u8 byte;
 	u8 temp;
 	unsigned int year, month, day, hour, minute, second;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* let us freeze external registers */
 	byte = READ_RTC(0xB);
 	byte &= 0x3f;
@@ -60,6 +62,7 @@ rtc_ds1386_get_time(void)
 	/* enable time transfer */
 	byte |= 0x80;
 	WRITE_RTC(0xB, byte);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	/* calc hour */
 	if (temp & 0x40) {
@@ -81,7 +84,9 @@ rtc_ds1386_set_time(unsigned long t)
 	u8 byte;
 	u8 temp;
 	u8 year, month, day, hour, minute, second;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* let us freeze external registers */
 	byte = READ_RTC(0xB);
 	byte &= 0x3f;
@@ -133,6 +138,7 @@ rtc_ds1386_set_time(unsigned long t)
 	if (second != READ_RTC(0x1)) {
 		WRITE_RTC(0x1, second);
 	}
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index dc7091caa7..1748223441 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -37,10 +37,25 @@
 #include <asm/dec/machtype.h>
 
 
+/*
+ * Returns true if a clock update is in progress
+ */
+static inline unsigned char dec_rtc_is_updating(void)
+{
+	unsigned char uip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return uip;
+}
+
 static unsigned long dec_rtc_get_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec, real_year;
 	int i;
+	unsigned long flags;
 
 	/* The Linux interpretation of the DS1287 clock register contents:
 	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
@@ -49,11 +64,12 @@ static unsigned long dec_rtc_get_time(void)
 	 */
 	/* read RTC exactly on falling edge of update flag */
 	for (i = 0; i < 1000000; i++)	/* may take up to 1 second... */
-		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+		if (dec_rtc_is_updating())
 			break;
 	for (i = 0; i < 1000000; i++)	/* must try at least 2.228 ms */
-		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+		if (!dec_rtc_is_updating())
 			break;
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* Isn't this overkill?  UIP above should guarantee consistency */
 	do {
 		sec = CMOS_READ(RTC_SECONDS);
@@ -77,6 +93,7 @@ static unsigned long dec_rtc_get_time(void)
 	 * of unused BBU RAM locations.
 	 */
 	real_year = CMOS_READ(RTC_DEC_YEAR);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 	year += real_year - 72 + 2000;
 
 	return mktime(year, mon, day, hour, min, sec);
@@ -95,6 +112,8 @@ static int dec_rtc_set_mmss(unsigned long nowtime)
 	int real_seconds, real_minutes, cmos_minutes;
 	unsigned char save_control, save_freq_select;
 
+	/* irq are locally disabled here */
+	spin_lock(&rtc_lock);
 	/* tell the clock it's being set */
 	save_control = CMOS_READ(RTC_CONTROL);
 	CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL);
@@ -141,6 +160,7 @@ static int dec_rtc_set_mmss(unsigned long nowtime)
 	 */
 	CMOS_WRITE(save_control, RTC_CONTROL);
 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	spin_unlock(&rtc_lock);
 
 	return retval;
 }
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c
index 1ae4318e13..8b407d7dc4 100644
--- a/arch/mips/jmr3927/common/rtc_ds1742.c
+++ b/arch/mips/jmr3927/common/rtc_ds1742.c
@@ -57,7 +57,9 @@ rtc_ds1742_get_time(void)
 {
 	unsigned int year, month, day, hour, minute, second;
 	unsigned int century;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	CMOS_WRITE(RTC_READ, RTC_CONTROL);
 	second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
 	minute = BCD2BIN(CMOS_READ(RTC_MINUTES));
@@ -67,6 +69,7 @@ rtc_ds1742_get_time(void)
 	year = BCD2BIN(CMOS_READ(RTC_YEAR));
 	century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK);
 	CMOS_WRITE(0, RTC_CONTROL);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	year += century * 100;
 
@@ -81,7 +84,9 @@ rtc_ds1742_set_time(unsigned long t)
 	u8 year, month, day, hour, minute, second;
 	u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second;
 	int cmos_century;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	CMOS_WRITE(RTC_READ, RTC_CONTROL);
 	cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
 	cmos_minute = (u8)CMOS_READ(RTC_MINUTES);
@@ -139,6 +144,7 @@ rtc_ds1742_set_time(unsigned long t)
 
 	/* RTC_CENTURY and RTC_CONTROL share same address... */
 	CMOS_WRITE(cmos_century, RTC_CONTROL);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
index 9d7812e03d..7dced67c55 100644
--- a/arch/mips/lasat/ds1603.c
+++ b/arch/mips/lasat/ds1603.c
@@ -8,6 +8,7 @@
 #include <asm/lasat/lasat.h>
 #include <linux/delay.h>
 #include <asm/lasat/ds1603.h>
+#include <asm/time.h>
 
 #include "ds1603.h"
 
@@ -138,19 +139,27 @@ static void rtc_end_op(void)
 unsigned long ds1603_read(void)
 {
 	unsigned long word;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_lock, flags);
 	rtc_init_op();
 	rtc_write_byte(READ_TIME_CMD);
 	word = rtc_read_word();
 	rtc_end_op();
+	spin_unlock_irqrestore(&rtc_lock, flags);
 	return word;
 }
 
 int ds1603_set(unsigned long time)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_lock, flags);
 	rtc_init_op();
 	rtc_write_byte(SET_TIME_CMD);
 	rtc_write_word(time);
 	rtc_end_op();
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 768bf44064..bab192ddc1 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -149,7 +149,9 @@ arch_initcall(per_cpu_mappings);
 unsigned long m48t37y_get_time(void)
 {
 	unsigned int year, month, day, hour, min, sec;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* stop the update */
 	rtc_base[0x7ff8] = 0x40;
 
@@ -166,6 +168,7 @@ unsigned long m48t37y_get_time(void)
 
 	/* start the update */
 	rtc_base[0x7ff8] = 0x00;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return mktime(year, month, day, hour, min, sec);
 }
@@ -173,11 +176,13 @@ unsigned long m48t37y_get_time(void)
 int m48t37y_set_time(unsigned long sec)
 {
 	struct rtc_time tm;
+	unsigned long flags;
 
 	/* convert to a more useful format -- note months count from 0 */
 	to_tm(sec, &tm);
 	tm.tm_mon += 1;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* enable writing */
 	rtc_base[0x7ff8] = 0x80;
 
@@ -201,6 +206,7 @@ int m48t37y_set_time(unsigned long sec)
 
 	/* disable writing */
 	rtc_base[0x7ff8] = 0x00;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index a7803e08f9..c9b7ff8148 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -135,7 +135,9 @@ void setup_wired_tlb_entries(void)
 unsigned long m48t37y_get_time(void)
 {
 	unsigned int year, month, day, hour, min, sec;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* stop the update */
 	rtc_base[0x7ff8] = 0x40;
 
@@ -152,6 +154,7 @@ unsigned long m48t37y_get_time(void)
 
 	/* start the update */
 	rtc_base[0x7ff8] = 0x00;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return mktime(year, month, day, hour, min, sec);
 }
@@ -159,11 +162,13 @@ unsigned long m48t37y_get_time(void)
 int m48t37y_set_time(unsigned long sec)
 {
 	struct rtc_time tm;
+	unsigned long flags;
 
 	/* convert to a more useful format -- note months count from 0 */
 	to_tm(sec, &tm);
 	tm.tm_mon += 1;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* enable writing */
 	rtc_base[0x7ff8] = 0x80;
 
@@ -187,6 +192,7 @@ int m48t37y_set_time(unsigned long sec)
 
 	/* disable writing */
 	rtc_base[0x7ff8] = 0x00;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index ce70fc96f1..2755c15474 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -140,7 +140,9 @@ unsigned long m48t37y_get_time(void)
 	unsigned char* rtc_base = (unsigned char*)0xfc800000;
 #endif
 	unsigned int year, month, day, hour, min, sec;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* stop the update */
 	rtc_base[0x7ff8] = 0x40;
 
@@ -157,6 +159,7 @@ unsigned long m48t37y_get_time(void)
 
 	/* start the update */
 	rtc_base[0x7ff8] = 0x00;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return mktime(year, month, day, hour, min, sec);
 }
@@ -169,11 +172,13 @@ int m48t37y_set_time(unsigned long sec)
 	unsigned char* rtc_base = (unsigned char*)0xfc800000;
 #endif
 	struct rtc_time tm;
+	unsigned long flags;
 
 	/* convert to a more useful format -- note months count from 0 */
 	to_tm(sec, &tm);
 	tm.tm_mon += 1;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* enable writing */
 	rtc_base[0x7ff8] = 0x80;
 
@@ -197,6 +202,7 @@ int m48t37y_set_time(unsigned long sec)
 
 	/* disable writing */
 	rtc_base[0x7ff8] = 0x00;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index bdc2ab55be..059755b5ed 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -73,7 +73,9 @@ void __init bus_error_init(void)
 unsigned long m48t37y_get_time(void)
 {
 	unsigned int year, month, day, hour, min, sec;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* Stop the update to the time */
 	m48t37_base->control = 0x40;
 
@@ -88,6 +90,7 @@ unsigned long m48t37y_get_time(void)
 
 	/* Start the update to the time again */
 	m48t37_base->control = 0x00;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return mktime(year, month, day, hour, min, sec);
 }
@@ -95,11 +98,13 @@ unsigned long m48t37y_get_time(void)
 int m48t37y_set_time(unsigned long sec)
 {
 	struct rtc_time tm;
+	unsigned long flags;
 
 	/* convert to a more useful format -- note months count from 0 */
 	to_tm(sec, &tm);
 	tm.tm_mon += 1;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* enable writing */
 	m48t37_base->control = 0x80;
 
@@ -123,6 +128,7 @@ int m48t37y_set_time(unsigned long sec)
 
 	/* disable writing */
 	m48t37_base->control = 0x00;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index df9b569432..b7300cc5c5 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -35,7 +35,9 @@ static unsigned long indy_rtc_get_time(void)
 {
 	unsigned int yrs, mon, day, hrs, min, sec;
 	unsigned int save_control;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff;
 	hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE;
 
@@ -47,6 +49,7 @@ static unsigned long indy_rtc_get_time(void)
 	yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff);
 
 	hpc3c0->rtcregs[RTC_CMD] = save_control;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	if (yrs < 45)
 		yrs += 30;
@@ -60,6 +63,7 @@ static int indy_rtc_set_time(unsigned long tim)
 {
 	struct rtc_time tm;
 	unsigned int save_control;
+	unsigned long flags;
 
 	to_tm(tim, &tm);
 
@@ -68,6 +72,7 @@ static int indy_rtc_set_time(unsigned long tim)
 	if (tm.tm_year >= 100)
 		tm.tm_year -= 100;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff;
 	hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE;
 
@@ -80,6 +85,7 @@ static int indy_rtc_set_time(unsigned long tim)
 	hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0;
 
 	hpc3c0->rtcregs[RTC_CMD] = save_control;
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
index 5b4fc26c1b..c13914bdda 100644
--- a/arch/mips/sibyte/swarm/rtc_m41t81.c
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -144,6 +144,7 @@ static int m41t81_write(uint8_t addr, int b)
 int m41t81_set_time(unsigned long t)
 {
 	struct rtc_time tm;
+	unsigned long flags;
 
 	to_tm(t, &tm);
 
@@ -153,6 +154,7 @@ int m41t81_set_time(unsigned long t)
 	 * believe we should finish writing min within a second.
 	 */
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	tm.tm_sec = BIN2BCD(tm.tm_sec);
 	m41t81_write(M41T81REG_SC, tm.tm_sec);
 
@@ -180,6 +182,7 @@ int m41t81_set_time(unsigned long t)
 	tm.tm_year %= 100;
 	tm.tm_year = BIN2BCD(tm.tm_year);
 	m41t81_write(M41T81REG_YR, tm.tm_year);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
@@ -187,19 +190,23 @@ int m41t81_set_time(unsigned long t)
 unsigned long m41t81_get_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
+	unsigned long flags;
 
 	/*
 	 * min is valid if two reads of sec are the same.
 	 */
 	for (;;) {
+		spin_lock_irqsave(&rtc_lock, flags);
 		sec = m41t81_read(M41T81REG_SC);
 		min = m41t81_read(M41T81REG_MN);
 		if (sec == m41t81_read(M41T81REG_SC)) break;
+		spin_unlock_irqrestore(&rtc_lock, flags);
 	}
 	hour = m41t81_read(M41T81REG_HR) & 0x3f;
 	day = m41t81_read(M41T81REG_DT);
 	mon = m41t81_read(M41T81REG_MO);
 	year = m41t81_read(M41T81REG_YR);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	sec = BCD2BIN(sec);
 	min = BCD2BIN(min);
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c
index d9ff9323f2..f4a1788364 100644
--- a/arch/mips/sibyte/swarm/rtc_xicor1241.c
+++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c
@@ -113,9 +113,11 @@ int xicor_set_time(unsigned long t)
 {
 	struct rtc_time tm;
 	int tmp;
+	unsigned long flags;
 
 	to_tm(t, &tm);
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	/* unlock writes to the CCR */
 	xicor_write(X1241REG_SR, X1241REG_SR_WEL);
 	xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
@@ -160,6 +162,7 @@ int xicor_set_time(unsigned long t)
 	xicor_write(X1241REG_HR, tmp);
 
 	xicor_write(X1241REG_SR, 0);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
@@ -167,7 +170,9 @@ int xicor_set_time(unsigned long t)
 unsigned long xicor_get_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec, y2k;
+	unsigned long flags;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	sec = xicor_read(X1241REG_SC);
 	min = xicor_read(X1241REG_MN);
 	hour = xicor_read(X1241REG_HR);
@@ -183,6 +188,7 @@ unsigned long xicor_get_time(void)
 	mon = xicor_read(X1241REG_MO);
 	year = xicor_read(X1241REG_YR);
 	y2k = xicor_read(X1241REG_Y2K);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	sec = BCD2BIN(sec);
 	min = BCD2BIN(min);
-- 
cgit v1.2.2


From 0d959c260e98b6b046d268b5ef5b76caf0026ab2 Mon Sep 17 00:00:00 2001
From: Ralf Baechle <ralf@linux-mips.org>
Date: Sat, 5 Nov 2005 11:26:43 +0000
Subject: IRIX: Use schedule_timeout_interruptible.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/kernel/irixsig.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'arch')

diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 908e636842..dd118c60bc 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -502,8 +502,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long __user *set,
 	while(1) {
 		long tmp = 0;
 
-		current->state = TASK_INTERRUPTIBLE;
-		expire = schedule_timeout(expire);
+		expire = schedule_timeout_interruptible(expire);
 
 		for (i=0; i<=4; i++)
 			tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
-- 
cgit v1.2.2


From 16cd3951366a013d52006982108437d3343c2fae Mon Sep 17 00:00:00 2001
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Sat, 5 Nov 2005 23:00:58 +0900
Subject: Fix return type of setup_frame variants

Since 2.6.13-rc1 setup_frame and its variants return int.  But some bits
were missed in the conversion.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/kernel/signal.c   |  3 ---
 arch/mips/kernel/signal32.c | 13 ++++++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

(limited to 'arch')

diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 9202a17db8..05e09eedab 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -384,9 +384,6 @@ give_sigsegv:
 	return 0;
 }
 
-extern void setup_rt_frame_n32(struct k_sigaction * ka,
-	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info);
-
 static inline int handle_signal(unsigned long sig, siginfo_t *info,
 	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
 {
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index dbe8213031..e315d3f6aa 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -647,8 +647,8 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
 	return (void *)((sp - frame_size) & ALMASK);
 }
 
-void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
-			       int signr, sigset_t *set)
+int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
+	int signr, sigset_t *set)
 {
 	struct sigframe *frame;
 	int err = 0;
@@ -694,13 +694,15 @@ void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, frame->sf_code);
 #endif
-        return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
+	return 0;
 }
 
-void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr,	sigset_t *set, siginfo_t *info)
+int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
+	int signr, sigset_t *set, siginfo_t *info)
 {
 	struct rt_sigframe32 *frame;
 	int err = 0;
@@ -763,10 +765,11 @@ void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr,
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, frame->rs_code);
 #endif
-	return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
+	return 0;
 }
 
 static inline int handle_signal(unsigned long sig, siginfo_t *info,
-- 
cgit v1.2.2