From: <blaisorblade_spam@yahoo.it>

The main part of UML; it is the last distributed patch for 2.6.7 Removes skas
support from the main UML patch; apply or get conflicts.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 /dev/null                                         |  159 ---
 25-akpm/arch/um/Kconfig                           |   38 
 25-akpm/arch/um/Kconfig.debug                     |    4 
 25-akpm/arch/um/Kconfig_block                     |   14 
 25-akpm/arch/um/Kconfig_net                       |   70 -
 25-akpm/arch/um/Makefile                          |  108 +-
 25-akpm/arch/um/Makefile-i386                     |   23 
 25-akpm/arch/um/Makefile-skas                     |    6 
 25-akpm/arch/um/config.release                    |    1 
 25-akpm/arch/um/defconfig                         |  230 ++---
 25-akpm/arch/um/drivers/Makefile                  |   17 
 25-akpm/arch/um/drivers/chan_kern.c               |   16 
 25-akpm/arch/um/drivers/chan_user.c               |  100 +-
 25-akpm/arch/um/drivers/cow.h                     |   41 
 25-akpm/arch/um/drivers/cow_kern.c                |  630 +++++++++++++
 25-akpm/arch/um/drivers/cow_sys.h                 |   48 +
 25-akpm/arch/um/drivers/cow_user.c                |  375 ++++++++
 25-akpm/arch/um/drivers/daemon_user.c             |   26 
 25-akpm/arch/um/drivers/fd.c                      |    3 
 25-akpm/arch/um/drivers/harddog_user.c            |   62 -
 25-akpm/arch/um/drivers/hostaudio_kern.c          |  107 +-
 25-akpm/arch/um/drivers/hostaudio_user.c          |   63 -
 25-akpm/arch/um/drivers/line.c                    |  152 ++-
 25-akpm/arch/um/drivers/mcast_user.c              |   16 
 25-akpm/arch/um/drivers/mconsole_kern.c           |  140 ++-
 25-akpm/arch/um/drivers/mconsole_user.c           |   25 
 25-akpm/arch/um/drivers/mmapper_kern.c            |    5 
 25-akpm/arch/um/drivers/net_kern.c                |   89 -
 25-akpm/arch/um/drivers/net_user.c                |   46 -
 25-akpm/arch/um/drivers/null.c                    |    1 
 25-akpm/arch/um/drivers/port_kern.c               |   17 
 25-akpm/arch/um/drivers/port_user.c               |   31 
 25-akpm/arch/um/drivers/pty.c                     |   22 
 25-akpm/arch/um/drivers/slip_user.c               |   69 -
 25-akpm/arch/um/drivers/slirp_user.c              |   15 
 25-akpm/arch/um/drivers/ssl.c                     |   49 -
 25-akpm/arch/um/drivers/stdio_console.c           |   54 -
 25-akpm/arch/um/drivers/tty.c                     |    4 
 25-akpm/arch/um/drivers/ubd_kern.c                |  600 ++++++++++---
 25-akpm/arch/um/drivers/ubd_user.c                |  497 ++--------
 25-akpm/arch/um/drivers/xterm.c                   |   21 
 25-akpm/arch/um/drivers/xterm_kern.c              |   12 
 25-akpm/arch/um/dyn.lds.S                         |   15 
 25-akpm/arch/um/include/2_5compat.h               |   14 
 25-akpm/arch/um/include/irq_kern.h                |   28 
 25-akpm/arch/um/include/kern_util.h               |   11 
 25-akpm/arch/um/include/line.h                    |    4 
 25-akpm/arch/um/include/mconsole.h                |    6 
 25-akpm/arch/um/include/mem.h                     |   15 
 25-akpm/arch/um/include/mem_kern.h                |   30 
 25-akpm/arch/um/include/mem_user.h                |   31 
 25-akpm/arch/um/include/os.h                      |   53 +
 25-akpm/arch/um/include/signal_user.h             |    2 
 25-akpm/arch/um/include/skas_ptrace.h             |    2 
 25-akpm/arch/um/include/sysdep-i386/frame_user.h  |   28 
 25-akpm/arch/um/include/sysdep-i386/sigcontext.h  |    4 
 25-akpm/arch/um/include/sysdep-i386/syscalls.h    |   59 -
 25-akpm/arch/um/include/ubd_user.h                |    9 
 25-akpm/arch/um/include/um_uaccess.h              |   51 +
 25-akpm/arch/um/include/user.h                    |    1 
 25-akpm/arch/um/include/user_util.h               |    7 
 25-akpm/arch/um/kernel/Makefile                   |   44 
 25-akpm/arch/um/kernel/config.c.in                |    4 
 25-akpm/arch/um/kernel/exec_kern.c                |    5 
 25-akpm/arch/um/kernel/frame.c                    |    3 
 25-akpm/arch/um/kernel/frame_kern.c               |    6 
 25-akpm/arch/um/kernel/helper.c                   |   55 -
 25-akpm/arch/um/kernel/init_task.c                |   17 
 25-akpm/arch/um/kernel/initrd_user.c              |   13 
 25-akpm/arch/um/kernel/irq.c                      |  105 +-
 25-akpm/arch/um/kernel/irq_user.c                 |   37 
 25-akpm/arch/um/kernel/ksyms.c                    |   53 +
 25-akpm/arch/um/kernel/mem.c                      |  657 +-------------
 25-akpm/arch/um/kernel/mem_user.c                 |  230 ++---
 25-akpm/arch/um/kernel/physmem.c                  |  468 ++++++++++
 25-akpm/arch/um/kernel/process.c                  |   20 
 25-akpm/arch/um/kernel/process_kern.c             |   45 
 25-akpm/arch/um/kernel/ptrace.c                   |   23 
 25-akpm/arch/um/kernel/reboot.c                   |    2 
 25-akpm/arch/um/kernel/sigio_kern.c               |    7 
 25-akpm/arch/um/kernel/sigio_user.c               |   96 +-
 25-akpm/arch/um/kernel/signal_kern.c              |   60 +
 25-akpm/arch/um/kernel/skas/Makefile              |   24 
 25-akpm/arch/um/kernel/skas/include/mode.h        |    6 
 25-akpm/arch/um/kernel/skas/include/skas.h        |    4 
 25-akpm/arch/um/kernel/skas/include/uaccess.h     |  207 ----
 25-akpm/arch/um/kernel/skas/mem_user.c            |   32 
 25-akpm/arch/um/kernel/skas/mmu.c                 |    8 
 25-akpm/arch/um/kernel/skas/process.c             |  107 +-
 25-akpm/arch/um/kernel/skas/process_kern.c        |   26 
 25-akpm/arch/um/kernel/skas/sys-i386/Makefile     |    2 
 25-akpm/arch/um/kernel/skas/sys-i386/sigcontext.c |   15 
 25-akpm/arch/um/kernel/skas/syscall_kern.c        |    2 
 25-akpm/arch/um/kernel/skas/syscall_user.c        |    4 
 25-akpm/arch/um/kernel/skas/trap_user.c           |    6 
 25-akpm/arch/um/kernel/skas/uaccess.c             |  219 ++++
 25-akpm/arch/um/kernel/skas/util/Makefile         |    7 
 25-akpm/arch/um/kernel/skas/util/mk_ptregs.c      |    1 
 25-akpm/arch/um/kernel/smp.c                      |   63 -
 25-akpm/arch/um/kernel/sys_call_table.c           |  686 +++++---------
 25-akpm/arch/um/kernel/syscall_kern.c             |   64 -
 25-akpm/arch/um/kernel/sysrq.c                    |    5 
 25-akpm/arch/um/kernel/tempfile.c                 |    7 
 25-akpm/arch/um/kernel/time.c                     |   69 +
 25-akpm/arch/um/kernel/time_kern.c                |   77 +
 25-akpm/arch/um/kernel/trap_kern.c                |   58 +
 25-akpm/arch/um/kernel/trap_user.c                |    9 
 25-akpm/arch/um/kernel/tt/Makefile                |    6 
 25-akpm/arch/um/kernel/tt/exec_kern.c             |    7 
 25-akpm/arch/um/kernel/tt/include/mode.h          |    2 
 25-akpm/arch/um/kernel/tt/include/uaccess.h       |   60 -
 25-akpm/arch/um/kernel/tt/mem_user.c              |    7 
 25-akpm/arch/um/kernel/tt/process_kern.c          |   82 +
 25-akpm/arch/um/kernel/tt/ptproxy/Makefile        |    2 
 25-akpm/arch/um/kernel/tt/ptproxy/proxy.c         |   25 
 25-akpm/arch/um/kernel/tt/ptproxy/sysdep.c        |    1 
 25-akpm/arch/um/kernel/tt/ptproxy/wait.c          |   12 
 25-akpm/arch/um/kernel/tt/sys-i386/Makefile       |    2 
 25-akpm/arch/um/kernel/tt/syscall_kern.c          |    2 
 25-akpm/arch/um/kernel/tt/syscall_user.c          |    4 
 25-akpm/arch/um/kernel/tt/tlb.c                   |    1 
 25-akpm/arch/um/kernel/tt/tracer.c                |   27 
 25-akpm/arch/um/kernel/tt/uaccess.c               |   73 +
 25-akpm/arch/um/kernel/tt/uaccess_user.c          |   22 
 25-akpm/arch/um/kernel/tt/unmap.c                 |    3 
 25-akpm/arch/um/kernel/tty_log.c                  |  136 ++
 25-akpm/arch/um/kernel/uaccess_user.c             |    2 
 25-akpm/arch/um/kernel/um_arch.c                  |   76 +
 25-akpm/arch/um/kernel/umid.c                     |   80 +
 25-akpm/arch/um/kernel/user_util.c                |   15 
 25-akpm/arch/um/main.c                            |    7 
 25-akpm/arch/um/os-Linux/Makefile                 |    6 
 25-akpm/arch/um/os-Linux/drivers/ethertap_kern.c  |    1 
 25-akpm/arch/um/os-Linux/drivers/ethertap_user.c  |   56 -
 25-akpm/arch/um/os-Linux/drivers/tuntap_user.c    |   57 -
 25-akpm/arch/um/os-Linux/file.c                   |  450 ++++++++-
 25-akpm/arch/um/os-Linux/process.c                |   58 -
 25-akpm/arch/um/os-Linux/tty.c                    |   10 
 25-akpm/arch/um/os-Linux/user_syms.c              |   88 +
 25-akpm/arch/um/sys-i386/Makefile                 |   24 
 25-akpm/arch/um/sys-i386/bugs.c                   |  140 ++-
 25-akpm/arch/um/sys-i386/fault.c                  |   16 
 25-akpm/arch/um/sys-i386/ptrace_user.c            |    8 
 25-akpm/arch/um/sys-i386/time.c                   |   24 
 25-akpm/arch/um/sys-i386/util/Makefile            |   14 
 25-akpm/arch/um/sys-i386/util/mk_sc.c             |    1 
 25-akpm/arch/um/sys-ia64/Makefile                 |   15 
 25-akpm/arch/um/sys-ppc/Makefile                  |   11 
 25-akpm/arch/um/uml.lds.S                         |   10 
 25-akpm/arch/um/util/Makefile                     |   27 
 25-akpm/arch/um/util/mk_constants_kern.c          |    4 
 25-akpm/fs/Makefile                               |    2 
 25-akpm/fs/hostfs/Makefile                        |   26 
 25-akpm/fs/hostfs/hostfs.h                        |   79 +
 25-akpm/fs/hostfs/hostfs_kern.c                   | 1008 ++++++++++++++++++++++
 25-akpm/fs/hostfs/hostfs_user.c                   |  361 +++++++
 25-akpm/fs/hppfs/Makefile                         |   19 
 25-akpm/fs/hppfs/hppfs_kern.c                     |  811 +++++++++++++++++
 25-akpm/include/asm-um/archparam-i386.h           |   89 +
 25-akpm/include/asm-um/common.lds.S               |   48 -
 25-akpm/include/asm-um/cpufeature.h               |    6 
 25-akpm/include/asm-um/current.h                  |    6 
 25-akpm/include/asm-um/dma-mapping.h              |  120 ++
 25-akpm/include/asm-um/elf.h                      |   13 
 25-akpm/include/asm-um/fixmap.h                   |    8 
 25-akpm/include/asm-um/irq.h                      |   18 
 25-akpm/include/asm-um/local.h                    |    6 
 25-akpm/include/asm-um/module-generic.h           |    6 
 25-akpm/include/asm-um/module-i386.h              |   13 
 25-akpm/include/asm-um/page.h                     |   32 
 25-akpm/include/asm-um/pgtable.h                  |  111 +-
 25-akpm/include/asm-um/processor-generic.h        |   43 
 25-akpm/include/asm-um/processor-i386.h           |    4 
 25-akpm/include/asm-um/sections.h                 |    7 
 25-akpm/include/asm-um/smp.h                      |    2 
 25-akpm/include/asm-um/system-generic.h           |    9 
 25-akpm/include/asm-um/system-i386.h              |   31 
 25-akpm/include/asm-um/thread_info.h              |   16 
 25-akpm/include/asm-um/timex.h                    |    2 
 25-akpm/include/asm-um/uaccess.h                  |    2 
 25-akpm/include/asm-um/unistd.h                   |    5 
 25-akpm/include/linux/gfp.h                       |    5 
 25-akpm/include/linux/time.h                      |    2 
 25-akpm/mm/page_alloc.c                           |    4 
 184 files changed, 8685 insertions(+), 3937 deletions(-)

diff -puN arch/um/config.release~uml-base-patch arch/um/config.release
--- 25/arch/um/config.release~uml-base-patch	2004-08-15 20:45:08.305392320 -0700
+++ 25-akpm/arch/um/config.release	2004-08-15 20:46:03.191048432 -0700
@@ -227,7 +227,6 @@ CONFIG_ROMFS_FS=m
 CONFIG_EXT2_FS=y
 CONFIG_SYSV_FS=m
 CONFIG_UDF_FS=m
-# CONFIG_UDF_RW is not set
 CONFIG_UFS_FS=m
 # CONFIG_UFS_FS_WRITE is not set
 
diff -puN arch/um/defconfig~uml-base-patch arch/um/defconfig
--- 25/arch/um/defconfig~uml-base-patch	2004-08-15 20:45:08.306392168 -0700
+++ 25-akpm/arch/um/defconfig	2004-08-15 20:46:03.193048128 -0700
@@ -3,29 +3,19 @@
 #
 CONFIG_USERMODE=y
 CONFIG_MMU=y
-CONFIG_SWAP=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CONFIG_LOG_BUF_SHIFT=14
 
 #
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General Setup
+# UML-specific options
 #
 CONFIG_MODE_TT=y
 CONFIG_MODE_SKAS=y
 CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_HOSTFS=y
+CONFIG_HPPFS=y
 CONFIG_MCONSOLE=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_HOST_2G_2G is not set
@@ -36,12 +26,43 @@ CONFIG_KERNEL_HALF_GIGS=1
 # CONFIG_HIGHMEM is not set
 CONFIG_PROC_MM=y
 CONFIG_KERNEL_STACK_ORDER=2
+CONFIG_UML_REAL_TIME_CLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 
 #
 # Loadable module support
 #
-CONFIG_MODULES=y
-# CONFIG_KMOD is not set
+# CONFIG_MODULES is not set
+
+#
+# Generic Driver Options
+#
 
 #
 # Character Devices
@@ -69,6 +90,7 @@ CONFIG_HOSTAUDIO=y
 #
 CONFIG_BLK_DEV_UBD=y
 # CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_COW_COMMON=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
@@ -78,7 +100,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_NETDEVICES=y
 
 #
-# Network Devices
+# UML Network Devices
 #
 CONFIG_UML_NET=y
 CONFIG_UML_NET_ETHERTAP=y
@@ -88,22 +110,6 @@ CONFIG_UML_NET_DAEMON=y
 CONFIG_UML_NET_MCAST=y
 # CONFIG_UML_NET_PCAP is not set
 CONFIG_UML_NET_SLIRP=y
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-CONFIG_SLIP=y
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
 
 #
 # Networking support
@@ -115,8 +121,6 @@ CONFIG_SLIP=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 # CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -130,8 +134,11 @@ CONFIG_INET=y
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_INET_IPCOMP is not set
 # CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -140,9 +147,9 @@ CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -159,6 +166,10 @@ CONFIG_IPV6_SCTP__=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=y
 
 #
 # Ethernet (10 or 100Mbit)
@@ -170,12 +181,28 @@ CONFIG_IPV6_SCTP__=y
 #
 
 #
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=y
+# CONFIG_SLIP_COMPRESSED is not set
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+
+#
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Token Ring devices
 #
 # CONFIG_SHAPER is not set
 
@@ -185,68 +212,100 @@ CONFIG_IPV6_SCTP__=y
 # CONFIG_WAN is not set
 
 #
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
 # File systems
 #
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
 CONFIG_QUOTACTL=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
 # CONFIG_EFS_FS is not set
 CONFIG_JFFS_FS=y
 CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS_PROC_FS=y
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=m
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_MINIX_FS=m
 # CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
 
 #
 # Network File Systems
 #
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
 # CONFIG_EXPORTFS is not set
-# CONFIG_CIFS is not set
 # CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -254,11 +313,11 @@ CONFIG_EXT2_FS=y
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
 
 #
 # Native Language Support
 #
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
@@ -316,28 +375,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # SCSI support
 #
-CONFIG_SCSI=y
-CONFIG_GENERIC_ISA_DMA=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_DEBUG_QUEUES=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_DEBUG=y
+# CONFIG_SCSI is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -359,6 +397,7 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -373,20 +412,21 @@ CONFIG_MTD_BLOCK=y
 #
 # Mapping drivers for chip access
 #
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
 
 #
 # Self-contained MTD device drivers
 #
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-CONFIG_MTD_BLKMTD=m
+CONFIG_MTD_BLKMTD=y
 
 #
 # Disk-On-Chip Device Drivers
 #
-# CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
 
 #
 # NAND Flash Device Drivers
diff -puN arch/um/drivers/chan_kern.c~uml-base-patch arch/um/drivers/chan_kern.c
--- 25/arch/um/drivers/chan_kern.c~uml-base-patch	2004-08-15 20:45:08.308391864 -0700
+++ 25-akpm/arch/um/drivers/chan_kern.c	2004-08-15 20:46:03.194047976 -0700
@@ -8,6 +8,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
+#include <linux/string.h>
 #include <linux/tty_flip.h>
 #include <asm/irq.h>
 #include "chan_kern.h"
@@ -265,6 +266,11 @@ static int one_chan_config_string(struct
 {
 	int n = 0;
 
+	if(chan == NULL){
+		CONFIG_CHUNK(str, size, n, "none", 1);
+		return(n);
+	}
+
 	CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
 
 	if(chan->dev == NULL){
@@ -420,7 +426,8 @@ int parse_chan_pair(char *str, struct li
 		INIT_LIST_HEAD(chans);
 	}
 
-	if((out = strchr(str, ',')) != NULL){
+	out = strchr(str, ',');
+	if(out != NULL){
 		in = str;
 		*out = '\0';
 		out++;
@@ -475,12 +482,15 @@ void chan_interrupt(struct list_head *ch
 				goto out;
 			}
 			err = chan->ops->read(chan->fd, &c, chan->data);
-			if(err > 0) tty_receive_char(tty, c);
+			if(err > 0)
+				tty_receive_char(tty, c);
 		} while(err > 0);
+
 		if(err == 0) reactivate_fd(chan->fd, irq);
 		if(err == -EIO){
 			if(chan->primary){
-				if(tty != NULL) tty_hangup(tty);
+				if(tty != NULL)
+					tty_hangup(tty);
 				line_disable(dev, irq);
 				close_chan(chans);
 				free_chan(chans);
diff -puN arch/um/drivers/chan_user.c~uml-base-patch arch/um/drivers/chan_user.c
--- 25/arch/um/drivers/chan_user.c~uml-base-patch	2004-08-15 20:45:08.309391712 -0700
+++ 25-akpm/arch/um/drivers/chan_user.c	2004-08-15 20:46:03.195047824 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <termios.h>
-#include <fcntl.h>
 #include <string.h>
 #include <signal.h>
 #include <sys/stat.h>
@@ -24,29 +23,27 @@
 
 void generic_close(int fd, void *unused)
 {
-	close(fd);
+	os_close_file(fd);
 }
 
 int generic_read(int fd, char *c_out, void *unused)
 {
 	int n;
 
-	n = read(fd, c_out, sizeof(*c_out));
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-EIO);
-	return(1);
+	n = os_read_file(fd, c_out, sizeof(*c_out));
+
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-EIO);
+	return(n);
 }
 
+/* XXX Trivial wrapper around os_write_file */
+
 int generic_write(int fd, const char *buf, int n, void *unused)
 {
-	int count;
-
-	count = write(fd, buf, n);
-	if(count < 0) return(-errno);
-	return(count);
+	return(os_write_file(fd, buf, n));
 }
 
 int generic_console_write(int fd, const char *buf, int n, void *unused)
@@ -68,15 +65,18 @@ int generic_console_write(int fd, const 
 int generic_window_size(int fd, void *unused, unsigned short *rows_out,
 			unsigned short *cols_out)
 {
-	struct winsize size;
-	int ret = 0;
+	int rows, cols;
+	int ret;
+
+	ret = os_window_size(fd, &rows, &cols);
+	if(ret < 0)
+		return(ret);
+
+	ret = ((*rows_out != rows) || (*cols_out != cols));
+
+	*rows_out = rows;
+	*cols_out = cols;
 
-	if(ioctl(fd, TIOCGWINSZ, &size) == 0){
-		ret = ((*rows_out != size.ws_row) || 
-		       (*cols_out != size.ws_col));
-		*rows_out = size.ws_row;
-		*cols_out = size.ws_col;
-	}
 	return(ret);
 }
 
@@ -100,14 +100,16 @@ static int winch_thread(void *arg)
 	struct winch_data *data = arg;
 	sigset_t sigs;
 	int pty_fd, pipe_fd;
+	int count, err;
 	char c = 1;
 
-	close(data->close_me);
+	os_close_file(data->close_me);
 	pty_fd = data->pty_fd;
 	pipe_fd = data->pipe_fd;
-	if(write(pipe_fd, &c, sizeof(c)) != sizeof(c))
+	count = os_write_file(pipe_fd, &c, sizeof(c));
+	if(count != sizeof(c))
 		printk("winch_thread : failed to write synchronization "
-		       "byte, errno = %d\n", errno);
+		       "byte, err = %d\n", -count);
 
 	signal(SIGWINCH, winch_handler);
 	sigfillset(&sigs);
@@ -123,26 +125,24 @@ static int winch_thread(void *arg)
 		exit(1);
 	}
 
-	if(ioctl(pty_fd, TIOCSCTTY, 0) < 0){
-		printk("winch_thread : TIOCSCTTY failed, errno = %d\n", errno);
-		exit(1);
-	}
-	if(tcsetpgrp(pty_fd, os_getpid()) < 0){
-		printk("winch_thread : tcsetpgrp failed, errno = %d\n", errno);
+	err = os_new_tty_pgrp(pty_fd, os_getpid());
+	if(err < 0){
+		printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
 		exit(1);
 	}
 
-	if(read(pipe_fd, &c, sizeof(c)) != sizeof(c))
+	count = os_read_file(pipe_fd, &c, sizeof(c));
+	if(count != sizeof(c))
 		printk("winch_thread : failed to read synchronization byte, "
-		       "errno = %d\n", errno);
+		       "err = %d\n", -count);
 
 	while(1){
 		pause();
 
-		if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)){
-			printk("winch_thread : write failed, errno = %d\n",
-			       errno);
-		}
+		count = os_write_file(pipe_fd, &c, sizeof(c));
+		if(count != sizeof(c))
+			printk("winch_thread : write failed, err = %d\n",
+			       -count);
 	}
 }
 
@@ -154,8 +154,8 @@ static int winch_tramp(int fd, void *dev
 	char c;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("winch_tramp : os_pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("winch_tramp : os_pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -168,12 +168,12 @@ static int winch_tramp(int fd, void *dev
 		return(pid);
 	}
 
-	close(fds[1]);
+	os_close_file(fds[1]);
 	*fd_out = fds[0];
-	n = read(fds[0], &c, sizeof(c));
+	n = os_read_file(fds[0], &c, sizeof(c));
 	if(n != sizeof(c)){
 		printk("winch_tramp : failed to read synchronization byte\n");
-		printk("read returned %d, errno = %d\n", n, errno);
+		printk("read failed, err = %d\n", -n);
 		printk("fd %d will not support SIGWINCH\n", fd);
 		*fd_out = -1;
 	}
@@ -183,20 +183,24 @@ static int winch_tramp(int fd, void *dev
 void register_winch(int fd, void *device_data)
 {
 	int pid, thread, thread_fd;
+	int count;
 	char c = 1;
 
-	if(!isatty(fd)) return;
+	if(!isatty(fd))
+		return;
 
 	pid = tcgetpgrp(fd);
-	if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) && 
-	   (pid == -1)){
+	if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
+			     device_data) && (pid == -1)){
 		thread = winch_tramp(fd, device_data, &thread_fd);
 		if(fd != -1){
 			register_winch_irq(thread_fd, fd, thread, device_data);
 
-			if(write(thread_fd, &c, sizeof(c)) != sizeof(c))
+			count = os_write_file(thread_fd, &c, sizeof(c));
+			if(count != sizeof(c))
 				printk("register_winch : failed to write "
-				       "synchronization byte\n");
+				       "synchronization byte, err = %d\n",
+					-count);
 		}
 	}
 }
diff -puN /dev/null arch/um/drivers/cow.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/drivers/cow.h	2004-08-15 20:46:03.196047672 -0700
@@ -0,0 +1,41 @@
+#ifndef __COW_H__
+#define __COW_H__
+
+#include <asm/types.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define ntohll(x) (x)
+# define htonll(x) (x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+# define ntohll(x)  bswap_64(x)
+# define htonll(x)  bswap_64(x)
+#else
+#error "__BYTE_ORDER not defined"
+#endif
+
+extern int init_cow_file(int fd, char *cow_file, char *backing_file,
+			 int sectorsize, int alignment, int *bitmap_offset_out,
+			 unsigned long *bitmap_len_out, int *data_offset_out);
+
+extern int file_reader(__u64 offset, char *buf, int len, void *arg);
+extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
+			   void *arg, __u32 *version_out,
+			   char **backing_file_out, time_t *mtime_out,
+			   __u64 *size_out, int *sectorsize_out,
+			   __u32 *align_out, int *bitmap_offset_out);
+
+extern int write_cow_header(char *cow_file, int fd, char *backing_file,
+			    int sectorsize, int alignment, long long *size);
+
+extern void cow_sizes(int version, __u64 size, int sectorsize, int align,
+		      int bitmap_offset, unsigned long *bitmap_len_out,
+		      int *data_offset_out);
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -puN /dev/null arch/um/drivers/cow_kern.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/drivers/cow_kern.c	2004-08-15 20:46:03.198047368 -0700
@@ -0,0 +1,630 @@
+#define COW_MAJOR 60
+#define MAJOR_NR COW_MAJOR
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/stat.h>
+#include <linux/vmalloc.h>
+#include <linux/blkdev.h>
+#include <linux/blk.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/devfs_fs.h>
+#include <asm/uaccess.h>
+#include "2_5compat.h"
+#include "cow.h"
+#include "ubd_user.h"
+
+#define COW_SHIFT 4
+
+struct cow {
+	int count;
+	char *cow_path;
+	dev_t cow_dev;
+	struct block_device *cow_bdev;
+	char *backing_path;
+	dev_t backing_dev;
+	struct block_device *backing_bdev;
+	int sectorsize;
+	unsigned long *bitmap;
+	unsigned long bitmap_len;
+	int bitmap_offset;
+	int data_offset;
+	devfs_handle_t devfs;
+	struct semaphore sem;
+	struct semaphore io_sem;
+	atomic_t working;
+	spinlock_t io_lock;
+	struct buffer_head *bh;
+	struct buffer_head *bhtail;
+	void *end_io;
+};
+
+#define DEFAULT_COW { \
+	.count			= 0, \
+	.cow_path		= NULL, \
+	.cow_dev		= 0, \
+	.backing_path		= NULL, \
+	.backing_dev		= 0, \
+        .bitmap			= NULL, \
+	.bitmap_len		= 0, \
+	.bitmap_offset		= 0, \
+        .data_offset		= 0, \
+	.devfs			= NULL, \
+	.working		= ATOMIC_INIT(0), \
+	.io_lock		= SPIN_LOCK_UNLOCKED, \
+}
+
+#define MAX_DEV (8)
+#define MAX_MINOR (MAX_DEV << COW_SHIFT)
+
+struct cow cow_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_COW };
+
+/* Not modified by this driver */
+static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE };
+static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 };
+
+/* Protected by cow_lock */
+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 };
+
+static struct hd_struct	cow_part[MAX_MINOR] =
+	{ [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } };
+
+/* Protected by io_request_lock */
+static request_queue_t *cow_queue;
+
+static int cow_open(struct inode *inode, struct file *filp);
+static int cow_release(struct inode * inode, struct file * file);
+static int cow_ioctl(struct inode * inode, struct file * file,
+		     unsigned int cmd, unsigned long arg);
+static int cow_revalidate(kdev_t rdev);
+
+static struct block_device_operations cow_blops = {
+	.open		= cow_open,
+	.release	= cow_release,
+	.ioctl		= cow_ioctl,
+	.revalidate	= cow_revalidate,
+};
+
+/* Initialized in an initcall, and unchanged thereafter */
+devfs_handle_t cow_dir_handle;
+
+#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \
+{ \
+	.major 		= maj, \
+	.major_name  	= name, \
+	.minor_shift 	= shift, \
+	.max_p  	= 1 << shift, \
+	.part  		= parts, \
+	.sizes  	= bsizes, \
+	.nr_real  	= max, \
+	.real_devices  	= NULL, \
+	.next  		= NULL, \
+	.fops  		= blops, \
+	.de_arr  	= NULL, \
+	.flags  	= 0 \
+}
+
+static spinlock_t cow_lock = SPIN_LOCK_UNLOCKED;
+
+static struct gendisk cow_gendisk = INIT_GENDISK(MAJOR_NR, "cow", cow_part,
+						 COW_SHIFT, sizes, MAX_DEV,
+						 &cow_blops);
+
+static int cow_add(int n)
+{
+	struct cow *dev = &cow_dev[n];
+	char name[sizeof("nnnnnn\0")];
+	int err = -ENODEV;
+
+	if(dev->cow_path == NULL)
+		goto out;
+
+	sprintf(name, "%d", n);
+	dev->devfs = devfs_register(cow_dir_handle, name, DEVFS_FL_REMOVABLE,
+				    MAJOR_NR, n << COW_SHIFT, S_IFBLK |
+				    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+				    &cow_blops, NULL);
+
+	init_MUTEX_LOCKED(&dev->sem);
+	init_MUTEX(&dev->io_sem);
+
+	return(0);
+
+ out:
+	return(err);
+}
+
+/*
+ * Add buffer_head to back of pending list
+ */
+static void cow_add_bh(struct cow *cow, struct buffer_head *bh)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cow->io_lock, flags);
+	if(cow->bhtail != NULL){
+		cow->bhtail->b_reqnext = bh;
+		cow->bhtail = bh;
+	}
+	else {
+		cow->bh = bh;
+		cow->bhtail = bh;
+	}
+	spin_unlock_irqrestore(&cow->io_lock, flags);
+}
+
+/*
+* Grab first pending buffer
+*/
+static struct buffer_head *cow_get_bh(struct cow *cow)
+{
+	struct buffer_head *bh;
+
+	spin_lock_irq(&cow->io_lock);
+	bh = cow->bh;
+	if(bh != NULL){
+		if(bh == cow->bhtail)
+			cow->bhtail = NULL;
+		cow->bh = bh->b_reqnext;
+		bh->b_reqnext = NULL;
+	}
+	spin_unlock_irq(&cow->io_lock);
+
+	return(bh);
+}
+
+static void cow_handle_bh(struct cow *cow, struct buffer_head *bh,
+			  struct buffer_head **cow_bh, int ncow_bh)
+{
+	int i;
+
+	if(ncow_bh > 0)
+		ll_rw_block(WRITE, ncow_bh, cow_bh);
+
+	for(i = 0; i < ncow_bh ; i++){
+		wait_on_buffer(cow_bh[i]);
+		brelse(cow_bh[i]);
+	}
+
+	ll_rw_block(WRITE, 1, &bh);
+	brelse(bh);
+}
+
+static struct buffer_head *cow_new_bh(struct cow *dev, int sector)
+{
+	struct buffer_head *bh;
+
+	sector = (dev->bitmap_offset + sector / 8) / dev->sectorsize;
+	bh = getblk(dev->cow_dev, sector, dev->sectorsize);
+	memcpy(bh->b_data, dev->bitmap + sector / (8 * sizeof(dev->bitmap[0])),
+	       dev->sectorsize);
+	return(bh);
+}
+
+/* Copied from loop.c, needed to avoid deadlocking in make_request. */
+
+static int cow_thread(void *data)
+{
+	struct cow *dev = data;
+	struct buffer_head *bh;
+
+	daemonize();
+	exit_files(current);
+
+	sprintf(current->comm, "cow%d", dev - cow_dev);
+
+	spin_lock_irq(&current->sigmask_lock);
+	sigfillset(&current->blocked);
+	flush_signals(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	atomic_inc(&dev->working);
+
+	current->policy = SCHED_OTHER;
+	current->nice = -20;
+
+	current->flags |= PF_NOIO;
+
+	/*
+	 * up sem, we are running
+	 */
+	up(&dev->sem);
+
+	for(;;){
+		int start, len, nbh, i, update_bitmap = 0;
+		struct buffer_head *cow_bh[2];
+
+		down_interruptible(&dev->io_sem);
+		/*
+		 * could be upped because of tear-down, not because of
+		 * pending work
+		 */
+		if(!atomic_read(&dev->working))
+			break;
+
+		bh = cow_get_bh(dev);
+		if(bh == NULL){
+			printk(KERN_ERR "cow: missing bh\n");
+			continue;
+		}
+
+		start = bh->b_blocknr * bh->b_size / dev->sectorsize;
+		len = bh->b_size / dev->sectorsize;
+		for(i = 0; i < len ; i++){
+			if(ubd_test_bit(start + i,
+					(unsigned char *) dev->bitmap))
+				continue;
+
+			update_bitmap = 1;
+			ubd_set_bit(start + i, (unsigned char *) dev->bitmap);
+		}
+
+		cow_bh[0] = NULL;
+		cow_bh[1] = NULL;
+		nbh = 0;
+		if(update_bitmap){
+			cow_bh[0] = cow_new_bh(dev, start);
+			nbh++;
+			if(start / dev->sectorsize !=
+			   (start + len) / dev->sectorsize){
+				cow_bh[1] = cow_new_bh(dev, start + len);
+				nbh++;
+			}
+		}
+
+		bh->b_dev = dev->cow_dev;
+		bh->b_blocknr += dev->data_offset / dev->sectorsize;
+
+		cow_handle_bh(dev, bh, cow_bh, nbh);
+
+		/*
+		 * upped both for pending work and tear-down, lo_pending
+		 * will hit zero then
+		 */
+		if(atomic_dec_and_test(&dev->working))
+			break;
+	}
+
+	up(&dev->sem);
+	return(0);
+}
+
+static int cow_make_request(request_queue_t *q, int rw, struct buffer_head *bh)
+{
+	struct cow *dev;
+	int n, minor;
+
+	minor = MINOR(bh->b_rdev);
+	n = minor >> COW_SHIFT;
+	dev = &cow_dev[n];
+
+	dev->end_io = NULL;
+	if(ubd_test_bit(bh->b_rsector, (unsigned char *) dev->bitmap)){
+		bh->b_rdev = dev->cow_dev;
+		bh->b_rsector += dev->data_offset / dev->sectorsize;
+	}
+	else if(rw == WRITE){
+		bh->b_dev = dev->cow_dev;
+		bh->b_blocknr += dev->data_offset / dev->sectorsize;
+
+		cow_add_bh(dev, bh);
+		up(&dev->io_sem);
+		return(0);
+	}
+	else {
+		bh->b_rdev = dev->backing_dev;
+	}
+
+	return(1);
+}
+
+int cow_init(void)
+{
+	int i;
+
+	cow_dir_handle = devfs_mk_dir (NULL, "cow", NULL);
+	if (devfs_register_blkdev(MAJOR_NR, "cow", &cow_blops)) {
+		printk(KERN_ERR "cow: unable to get major %d\n", MAJOR_NR);
+		return -1;
+	}
+	read_ahead[MAJOR_NR] = 8;		/* 8 sector (4kB) read-ahead */
+	blksize_size[MAJOR_NR] = blk_sizes;
+	blk_size[MAJOR_NR] = sizes;
+	INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes);
+
+	cow_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
+	blk_init_queue(cow_queue, NULL);
+	INIT_ELV(cow_queue, &cow_queue->elevator);
+	blk_queue_make_request(cow_queue, cow_make_request);
+
+	add_gendisk(&cow_gendisk);
+
+	for(i=0;i<MAX_DEV;i++)
+		cow_add(i);
+
+	return(0);
+}
+
+__initcall(cow_init);
+
+static int reader(__u64 start, char *buf, int count, void *arg)
+{
+	dev_t dev = *((dev_t *) arg);
+	struct buffer_head *bh;
+	__u64 block;
+	int cur, offset, left, n, blocksize = get_hardsect_size(dev);
+
+	if(blocksize == 0)
+		panic("Zero blocksize");
+
+	block = start / blocksize;
+	offset = start % blocksize;
+	left = count;
+	cur = 0;
+	while(left > 0){
+		n = (left > blocksize) ? blocksize : left;
+
+		bh = bread(dev, block, (n < 512) ? 512 : n);
+		if(bh == NULL)
+			return(-EIO);
+
+		n -= offset;
+		memcpy(&buf[cur], bh->b_data + offset, n);
+		block++;
+		left -= n;
+		cur += n;
+		offset = 0;
+		brelse(bh);
+	}
+
+	return(count);
+}
+
+static int cow_open(struct inode *inode, struct file *filp)
+{
+	int (*dev_ioctl)(struct inode *, struct file *, unsigned int,
+			 unsigned long);
+	mm_segment_t fs;
+	struct cow *dev;
+	__u64 size;
+	__u32 version, align;
+	time_t mtime;
+	char *backing_file;
+	int n, offset, err = 0;
+
+	n = DEVICE_NR(inode->i_rdev);
+	if(n >= MAX_DEV)
+		return(-ENODEV);
+	dev = &cow_dev[n];
+	offset = n << COW_SHIFT;
+
+	spin_lock(&cow_lock);
+
+	if(dev->count == 0){
+		dev->cow_dev = name_to_kdev_t(dev->cow_path);
+		if(dev->cow_dev == 0){
+			printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
+			       "failed\n", dev->cow_path);
+			err = -ENODEV;
+		}
+
+		dev->backing_dev = name_to_kdev_t(dev->backing_path);
+		if(dev->backing_dev == 0){
+			printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
+			       "failed\n", dev->backing_path);
+			err = -ENODEV;
+		}
+
+		if(err)
+			goto out;
+
+		dev->cow_bdev = bdget(dev->cow_dev);
+		if(dev->cow_bdev == NULL){
+			printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n",
+			       dev->cow_path);
+			err = -ENOMEM;
+		}
+		dev->backing_bdev = bdget(dev->backing_dev);
+		if(dev->backing_bdev == NULL){
+			printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n",
+			       dev->backing_path);
+			err = -ENOMEM;
+		}
+
+		if(err)
+			goto out;
+
+		err = blkdev_get(dev->cow_bdev, FMODE_READ|FMODE_WRITE, 0,
+				 BDEV_RAW);
+		if(err){
+			printk("cow_open - blkdev_get of COW device failed, "
+			       "error = %d\n", err);
+			goto out;
+		}
+
+		err = blkdev_get(dev->backing_bdev, FMODE_READ, 0, BDEV_RAW);
+		if(err){
+			printk("cow_open - blkdev_get of backing device "
+			       "failed, error = %d\n", err);
+			goto out;
+		}
+
+		err = read_cow_header(reader, &dev->cow_dev, &version,
+				      &backing_file, &mtime, &size,
+				      &dev->sectorsize, &align,
+				      &dev->bitmap_offset);
+		if(err){
+			printk(KERN_ERR "cow_open - read_cow_header failed, "
+			       "err = %d\n", err);
+			goto out;
+		}
+
+		cow_sizes(version, size, dev->sectorsize, align,
+			  dev->bitmap_offset, &dev->bitmap_len,
+			  &dev->data_offset);
+		dev->bitmap = (void *) vmalloc(dev->bitmap_len);
+		if(dev->bitmap == NULL){
+			err = -ENOMEM;
+			printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
+			goto out;
+		}
+		flush_tlb_kernel_vm();
+
+		err = reader(dev->bitmap_offset, (char *) dev->bitmap,
+			     dev->bitmap_len, &dev->cow_dev);
+		if(err < 0){
+			printk(KERN_ERR "Failed to read COW bitmap\n");
+			vfree(dev->bitmap);
+			goto out;
+		}
+
+		dev_ioctl = dev->backing_bdev->bd_op->ioctl;
+		fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = (*dev_ioctl)(inode, filp, BLKGETSIZE,
+				   (unsigned long) &sizes[offset]);
+		set_fs(fs);
+		if(err){
+			printk(KERN_ERR "cow_open - BLKGETSIZE failed, "
+			       "error = %d\n", err);
+			goto out;
+		}
+
+		kernel_thread(cow_thread, dev,
+			      CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+		down(&dev->sem);
+	}
+	dev->count++;
+ out:
+	spin_unlock(&cow_lock);
+	return(err);
+}
+
+static int cow_release(struct inode * inode, struct file * file)
+{
+	struct cow *dev;
+	int n, err;
+
+	n = DEVICE_NR(inode->i_rdev);
+	if(n >= MAX_DEV)
+		return(-ENODEV);
+	dev = &cow_dev[n];
+
+	spin_lock(&cow_lock);
+
+	if(--dev->count > 0)
+		goto out;
+
+	err = blkdev_put(dev->cow_bdev, BDEV_RAW);
+	if(err)
+		printk("cow_release - blkdev_put of cow device failed, "
+		       "error = %d\n", err);
+	bdput(dev->cow_bdev);
+	dev->cow_bdev = 0;
+
+	err = blkdev_put(dev->backing_bdev, BDEV_RAW);
+	if(err)
+		printk("cow_release - blkdev_put of backing device failed, "
+		       "error = %d\n", err);
+	bdput(dev->backing_bdev);
+	dev->backing_bdev = 0;
+
+ out:
+	spin_unlock(&cow_lock);
+	return(0);
+}
+
+static int cow_ioctl(struct inode * inode, struct file * file,
+		     unsigned int cmd, unsigned long arg)
+{
+	struct cow *dev;
+	int (*dev_ioctl)(struct inode *, struct file *, unsigned int,
+			 unsigned long);
+	int n;
+
+	n = DEVICE_NR(inode->i_rdev);
+	if(n >= MAX_DEV)
+		return(-ENODEV);
+	dev = &cow_dev[n];
+
+	dev_ioctl = dev->backing_bdev->bd_op->ioctl;
+	return((*dev_ioctl)(inode, file, cmd, arg));
+}
+
+static int cow_revalidate(kdev_t rdev)
+{
+	printk(KERN_ERR "Need to implement cow_revalidate\n");
+	return(0);
+}
+
+static int parse_unit(char **ptr)
+{
+	char *str = *ptr, *end;
+	int n = -1;
+
+	if(isdigit(*str)) {
+		n = simple_strtoul(str, &end, 0);
+		if(end == str)
+			return(-1);
+		*ptr = end;
+	}
+	else if (('a' <= *str) && (*str <= 'h')) {
+		n = *str - 'a';
+		str++;
+		*ptr = str;
+	}
+	return(n);
+}
+
+static int cow_setup(char *str)
+{
+	struct cow *dev;
+	char *cow_name, *backing_name;
+	int unit;
+
+	unit = parse_unit(&str);
+	if(unit < 0){
+		printk(KERN_ERR "cow_setup - Couldn't parse unit number\n");
+		return(1);
+	}
+
+	if(*str != '='){
+		printk(KERN_ERR "cow_setup - Missing '=' after unit "
+		       "number\n");
+		return(1);
+	}
+	str++;
+
+	cow_name = str;
+	backing_name = strchr(str, ',');
+	if(backing_name == NULL){
+		printk(KERN_ERR "cow_setup - missing backing device name\n");
+		return(0);
+	}
+	*backing_name = '\0';
+	backing_name++;
+
+	spin_lock(&cow_lock);
+
+	dev = &cow_dev[unit];
+	dev->cow_path = cow_name;
+	dev->backing_path = backing_name;
+
+	spin_unlock(&cow_lock);
+	return(0);
+}
+
+__setup("cow", cow_setup);
+
+/*
+ * 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 -puN /dev/null arch/um/drivers/cow_sys.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/drivers/cow_sys.h	2004-08-15 20:46:03.198047368 -0700
@@ -0,0 +1,48 @@
+#ifndef __COW_SYS_H__
+#define __COW_SYS_H__
+
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+#include "user.h"
+
+static inline void *cow_malloc(int size)
+{
+	return(um_kmalloc(size));
+}
+
+static inline void cow_free(void *ptr)
+{
+	kfree(ptr);
+}
+
+#define cow_printf printk
+
+static inline char *cow_strdup(char *str)
+{
+	return(uml_strdup(str));
+}
+
+static inline int cow_seek_file(int fd, __u64 offset)
+{
+	return(os_seek_file(fd, offset));
+}
+
+static inline int cow_file_size(char *file, __u64 *size_out)
+{
+	return(os_file_size(file, size_out));
+}
+
+static inline int cow_write_file(int fd, char *buf, int size)
+{
+	return(os_write_file(fd, buf, size));
+}
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -puN /dev/null arch/um/drivers/cow_user.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/drivers/cow_user.c	2004-08-15 20:46:03.200047064 -0700
@@ -0,0 +1,375 @@
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <netinet/in.h>
+
+#include "os.h"
+
+#include "cow.h"
+#include "cow_sys.h"
+
+#define PATH_LEN_V1 256
+
+struct cow_header_v1 {
+	int magic;
+	int version;
+	char backing_file[PATH_LEN_V1];
+	time_t mtime;
+	__u64 size;
+	int sectorsize;
+};
+
+#define PATH_LEN_V2 MAXPATHLEN
+
+struct cow_header_v2 {
+	unsigned long magic;
+	unsigned long version;
+	char backing_file[PATH_LEN_V2];
+	time_t mtime;
+	__u64 size;
+	int sectorsize;
+};
+
+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
+ * case other systems have different values for MAXPATHLEN
+ */
+#define PATH_LEN_V3 4096
+
+/* Changes from V2 -
+ *	PATH_LEN_V3 as described above
+ *	Explicitly specify field bit lengths for systems with different
+ *		lengths for the usual C types.  Not sure whether char or
+ *		time_t should be changed, this can be changed later without
+ *		breaking compatibility
+ *	Add alignment field so that different alignments can be used for the
+ *		bitmap and data
+ * 	Add cow_format field to allow for the possibility of different ways
+ *		of specifying the COW blocks.  For now, the only value is 0,
+ * 		for the traditional COW bitmap.
+ *	Move the backing_file field to the end of the header.  This allows
+ *		for the possibility of expanding it into the padding required
+ *		by the bitmap alignment.
+ * 	The bitmap and data portions of the file will be aligned as specified
+ * 		by the alignment field.  This is to allow COW files to be
+ *		put on devices with restrictions on access alignments, such as
+ *		/dev/raw, with a 512 byte alignment restriction.  This also
+ *		allows the data to be more aligned more strictly than on
+ *		sector boundaries.  This is needed for ubd-mmap, which needs
+ *		the data to be page aligned.
+ *	Fixed (finally!) the rounding bug
+ */
+
+struct cow_header_v3 {
+	__u32 magic;
+	__u32 version;
+	time_t mtime;
+	__u64 size;
+	__u32 sectorsize;
+	__u32 alignment;
+	__u32 cow_format;
+	char backing_file[PATH_LEN_V3];
+};
+
+/* COW format definitions - for now, we have only the usual COW bitmap */
+#define COW_BITMAP 0
+
+union cow_header {
+	struct cow_header_v1 v1;
+	struct cow_header_v2 v2;
+	struct cow_header_v3 v3;
+};
+
+#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
+#define COW_VERSION 3
+
+#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len))
+#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align)
+
+void cow_sizes(int version, __u64 size, int sectorsize, int align,
+	       int bitmap_offset, unsigned long *bitmap_len_out,
+	       int *data_offset_out)
+{
+	if(version < 3){
+		*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
+
+		*data_offset_out = bitmap_offset + *bitmap_len_out;
+		*data_offset_out = (*data_offset_out + sectorsize - 1) /
+			sectorsize;
+		*data_offset_out *= sectorsize;
+	}
+	else {
+		*bitmap_len_out = DIV_ROUND(size, sectorsize);
+		*bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8);
+
+		*data_offset_out = bitmap_offset + *bitmap_len_out;
+		*data_offset_out = ROUND_UP(*data_offset_out, align);
+	}
+}
+
+static int absolutize(char *to, int size, char *from)
+{
+	char save_cwd[256], *slash;
+	int remaining;
+
+	if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
+		cow_printf("absolutize : unable to get cwd - errno = %d\n",
+			   errno);
+		return(-1);
+	}
+	slash = strrchr(from, '/');
+	if(slash != NULL){
+		*slash = '\0';
+		if(chdir(from)){
+			*slash = '/';
+			cow_printf("absolutize : Can't cd to '%s' - "
+				   "errno = %d\n", from, errno);
+			return(-1);
+		}
+		*slash = '/';
+		if(getcwd(to, size) == NULL){
+			cow_printf("absolutize : unable to get cwd of '%s' - "
+			       "errno = %d\n", from, errno);
+			return(-1);
+		}
+		remaining = size - strlen(to);
+		if(strlen(slash) + 1 > remaining){
+			cow_printf("absolutize : unable to fit '%s' into %d "
+			       "chars\n", from, size);
+			return(-1);
+		}
+		strcat(to, slash);
+	}
+	else {
+		if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
+			cow_printf("absolutize : unable to fit '%s' into %d "
+			       "chars\n", from, size);
+			return(-1);
+		}
+		strcpy(to, save_cwd);
+		strcat(to, "/");
+		strcat(to, from);
+	}
+	chdir(save_cwd);
+	return(0);
+}
+
+int write_cow_header(char *cow_file, int fd, char *backing_file,
+		     int sectorsize, int alignment, long long *size)
+{
+	struct cow_header_v3 *header;
+	unsigned long modtime;
+	int err;
+
+	err = cow_seek_file(fd, 0);
+	if(err < 0){
+		cow_printf("write_cow_header - lseek failed, err = %d\n", -err);
+		goto out;
+	}
+
+	err = -ENOMEM;
+	header = cow_malloc(sizeof(*header));
+	if(header == NULL){
+		cow_printf("Failed to allocate COW V3 header\n");
+		goto out;
+	}
+	header->magic = htonl(COW_MAGIC);
+	header->version = htonl(COW_VERSION);
+
+	err = -EINVAL;
+	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+		cow_printf("Backing file name \"%s\" is too long - names are "
+			   "limited to %d characters\n", backing_file,
+			   sizeof(header->backing_file) - 1);
+		goto out_free;
+	}
+
+	if(absolutize(header->backing_file, sizeof(header->backing_file),
+		      backing_file))
+		goto out_free;
+
+	err = os_file_modtime(header->backing_file, &modtime);
+	if(err < 0){
+		cow_printf("Backing file '%s' mtime request failed, "
+			   "err = %d\n", header->backing_file, -err);
+		goto out_free;
+	}
+
+	err = cow_file_size(header->backing_file, size);
+	if(err < 0){
+		cow_printf("Couldn't get size of backing file '%s', "
+			   "err = %d\n", header->backing_file, -err);
+		goto out_free;
+	}
+
+	header->mtime = htonl(modtime);
+	header->size = htonll(*size);
+	header->sectorsize = htonl(sectorsize);
+	header->alignment = htonl(alignment);
+	header->cow_format = COW_BITMAP;
+
+	err = os_write_file(fd, header, sizeof(*header));
+	if(err != sizeof(*header)){
+		cow_printf("Write of header to new COW file '%s' failed, "
+			   "err = %d\n", cow_file, -err);
+		goto out_free;
+	}
+	err = 0;
+ out_free:
+	cow_free(header);
+ out:
+	return(err);
+}
+
+int file_reader(__u64 offset, char *buf, int len, void *arg)
+{
+	int fd = *((int *) arg);
+
+	return(pread(fd, buf, len, offset));
+}
+
+/* XXX Need to sanity-check the values read from the header */
+
+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
+		    __u32 *version_out, char **backing_file_out,
+		    time_t *mtime_out, __u64 *size_out,
+		    int *sectorsize_out, __u32 *align_out,
+		    int *bitmap_offset_out)
+{
+	union cow_header *header;
+	char *file;
+	int err, n;
+	unsigned long version, magic;
+
+	header = cow_malloc(sizeof(*header));
+	if(header == NULL){
+	        cow_printf("read_cow_header - Failed to allocate header\n");
+		return(-ENOMEM);
+	}
+	err = -EINVAL;
+	n = (*reader)(0, (char *) header, sizeof(*header), arg);
+	if(n < offsetof(typeof(header->v1), backing_file)){
+		cow_printf("read_cow_header - short header\n");
+		goto out;
+	}
+
+	magic = header->v1.magic;
+	if(magic == COW_MAGIC) {
+		version = header->v1.version;
+	}
+	else if(magic == ntohl(COW_MAGIC)){
+		version = ntohl(header->v1.version);
+	}
+	/* No error printed because the non-COW case comes through here */
+	else goto out;
+
+	*version_out = version;
+
+	if(version == 1){
+		if(n < sizeof(header->v1)){
+			cow_printf("read_cow_header - failed to read V1 "
+				   "header\n");
+			goto out;
+		}
+		*mtime_out = header->v1.mtime;
+		*size_out = header->v1.size;
+		*sectorsize_out = header->v1.sectorsize;
+		*bitmap_offset_out = sizeof(header->v1);
+		*align_out = *sectorsize_out;
+		file = header->v1.backing_file;
+	}
+	else if(version == 2){
+		if(n < sizeof(header->v2)){
+			cow_printf("read_cow_header - failed to read V2 "
+				   "header\n");
+			goto out;
+		}
+		*mtime_out = ntohl(header->v2.mtime);
+		*size_out = ntohll(header->v2.size);
+		*sectorsize_out = ntohl(header->v2.sectorsize);
+		*bitmap_offset_out = sizeof(header->v2);
+		*align_out = *sectorsize_out;
+		file = header->v2.backing_file;
+	}
+	else if(version == 3){
+		if(n < sizeof(header->v3)){
+			cow_printf("read_cow_header - failed to read V2 "
+				   "header\n");
+			goto out;
+		}
+		*mtime_out = ntohl(header->v3.mtime);
+		*size_out = ntohll(header->v3.size);
+		*sectorsize_out = ntohl(header->v3.sectorsize);
+		*align_out = ntohl(header->v3.alignment);
+		*bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
+		file = header->v3.backing_file;
+	}
+	else {
+		cow_printf("read_cow_header - invalid COW version\n");
+		goto out;
+	}
+	err = -ENOMEM;
+	*backing_file_out = cow_strdup(file);
+	if(*backing_file_out == NULL){
+		cow_printf("read_cow_header - failed to allocate backing "
+			   "file\n");
+		goto out;
+	}
+	err = 0;
+ out:
+	cow_free(header);
+	return(err);
+}
+
+int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
+		  int alignment, int *bitmap_offset_out,
+		  unsigned long *bitmap_len_out, int *data_offset_out)
+{
+	__u64 size, offset;
+	char zero = 0;
+	int err;
+
+	err = write_cow_header(cow_file, fd, backing_file, sectorsize,
+			       alignment, &size);
+	if(err)
+		goto out;
+
+	*bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
+	cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out,
+		  bitmap_len_out, data_offset_out);
+
+	offset = *data_offset_out + size - sizeof(zero);
+	err = cow_seek_file(fd, offset);
+	if(err < 0){
+		cow_printf("cow bitmap lseek failed : err = %d\n", -err);
+		goto out;
+	}
+
+	/* does not really matter how much we write it is just to set EOF
+	 * this also sets the entire COW bitmap
+	 * to zero without having to allocate it
+	 */
+	err = cow_write_file(fd, &zero, sizeof(zero));
+	if(err != sizeof(zero)){
+		cow_printf("Write of bitmap to new COW file '%s' failed, "
+			   "err = %d\n", cow_file, -err);
+		err = -EINVAL;
+		goto out;
+	}
+
+	return(0);
+
+ out:
+	return(err);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -puN arch/um/drivers/daemon_user.c~uml-base-patch arch/um/drivers/daemon_user.c
--- 25/arch/um/drivers/daemon_user.c~uml-base-patch	2004-08-15 20:45:08.311391408 -0700
+++ 25-akpm/arch/um/drivers/daemon_user.c	2004-08-15 20:46:03.201046912 -0700
@@ -53,7 +53,8 @@ static int connect_to_switch(struct daem
 	struct request_v3 req;
 	int fd, n, err;
 
-	if((pri->control = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
+	pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
+	if(pri->control < 0){
 		printk("daemon_open : control socket failed, errno = %d\n", 
 		       errno);		
 		return(-errno);
@@ -67,7 +68,8 @@ static int connect_to_switch(struct daem
 		goto out;
 	}
 
-	if((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){
+	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if(fd < 0){
 		printk("daemon_open : data socket failed, errno = %d\n", 
 		       errno);
 		err = -errno;
@@ -91,18 +93,18 @@ static int connect_to_switch(struct daem
 	req.version = SWITCH_VERSION;
 	req.type = REQ_NEW_CONTROL;
 	req.sock = *local_addr;
-	n = write(pri->control, &req, sizeof(req));
+	n = os_write_file(pri->control, &req, sizeof(req));
 	if(n != sizeof(req)){
-		printk("daemon_open : control setup request returned %d, "
-		       "errno = %d\n", n, errno);
+		printk("daemon_open : control setup request failed, err = %d\n",
+		       -n);
 		err = -ENOTCONN;
 		goto out;		
 	}
 
-	n = read(pri->control, sun, sizeof(*sun));
+	n = os_read_file(pri->control, sun, sizeof(*sun));
 	if(n != sizeof(*sun)){
-		printk("daemon_open : read of data socket returned %d, "
-		       "errno = %d\n", n, errno);
+		printk("daemon_open : read of data socket failed, err = %d\n",
+		       -n);
 		err = -ENOTCONN;
 		goto out_close;		
 	}
@@ -111,9 +113,9 @@ static int connect_to_switch(struct daem
 	return(fd);
 
  out_close:
-	close(fd);
+	os_close_file(fd);
  out:
-	close(pri->control);
+	os_close_file(pri->control);
 	return(err);
 }
 
@@ -153,8 +155,8 @@ static void daemon_remove(void *data)
 {
 	struct daemon_data *pri = data;
 
-	close(pri->fd);
-	close(pri->control);
+	os_close_file(pri->fd);
+	os_close_file(pri->control);
 	if(pri->data_addr != NULL) kfree(pri->data_addr);
 	if(pri->ctl_addr != NULL) kfree(pri->ctl_addr);
 	if(pri->local_addr != NULL) kfree(pri->local_addr);
diff -puN arch/um/drivers/fd.c~uml-base-patch arch/um/drivers/fd.c
--- 25/arch/um/drivers/fd.c~uml-base-patch	2004-08-15 20:45:08.312391256 -0700
+++ 25-akpm/arch/um/drivers/fd.c	2004-08-15 20:46:03.201046912 -0700
@@ -35,7 +35,8 @@ void *fd_init(char *str, int device, str
 		printk("fd_init : couldn't parse file descriptor '%s'\n", str);
 		return(NULL);
 	}
-	if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct fd_chan) { .fd  	= n,
 				    .raw  	= opts->raw });
 	return(data);
diff -puN arch/um/drivers/harddog_user.c~uml-base-patch arch/um/drivers/harddog_user.c
--- 25/arch/um/drivers/harddog_user.c~uml-base-patch	2004-08-15 20:45:08.313391104 -0700
+++ 25-akpm/arch/um/drivers/harddog_user.c	2004-08-15 20:46:03.202046760 -0700
@@ -27,10 +27,10 @@ static void pre_exec(void *d)
 	dup2(data->stdin, 0);
 	dup2(data->stdout, 1);
 	dup2(data->stdout, 2);
-	close(data->stdin);
-	close(data->stdout);
-	close(data->close_me[0]);
-	close(data->close_me[1]);
+	os_close_file(data->stdin);
+	os_close_file(data->stdout);
+	os_close_file(data->close_me[0]);
+	os_close_file(data->close_me[1]);
 }
 
 int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
@@ -44,15 +44,15 @@ int start_watchdog(int *in_fd_ret, int *
 	char **args = NULL;
 
 	err = os_pipe(in_fds, 1, 0);
-	if(err){
-		printk("harddog_open - os_pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("harddog_open - os_pipe failed, err = %d\n", -err);
+		goto out;
 	}
 
 	err = os_pipe(out_fds, 1, 0);
-	if(err){
-		printk("harddog_open - os_pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("harddog_open - os_pipe failed, err = %d\n", -err);
+		goto out_close_in;
 	}
 
 	data.stdin = out_fds[0];
@@ -72,42 +72,47 @@ int start_watchdog(int *in_fd_ret, int *
 
 	pid = run_helper(pre_exec, &data, args, NULL);
 
-	close(out_fds[0]);
-	close(in_fds[1]);
+	os_close_file(out_fds[0]);
+	os_close_file(in_fds[1]);
 
 	if(pid < 0){
 		err = -pid;
-		printk("harddog_open - run_helper failed, errno = %d\n", err);
-		goto out;
+		printk("harddog_open - run_helper failed, errno = %d\n", -err);
+		goto out_close_out;
 	}
 
-	n = read(in_fds[0], &c, sizeof(c));
+	n = os_read_file(in_fds[0], &c, sizeof(c));
 	if(n == 0){
 		printk("harddog_open - EOF on watchdog pipe\n");
 		helper_wait(pid);
 		err = -EIO;
-		goto out;
+		goto out_close_out;
 	}
 	else if(n < 0){
 		printk("harddog_open - read of watchdog pipe failed, "
-		       "errno = %d\n", errno);
+		       "err = %d\n", -n);
 		helper_wait(pid);
-		err = -errno;
-		goto out;
+		err = n;
+		goto out_close_out;
 	}
 	*in_fd_ret = in_fds[0];
 	*out_fd_ret = out_fds[1];
 	return(0);
+
+ out_close_in:
+	os_close_file(in_fds[0]);
+	os_close_file(in_fds[1]);
+ out_close_out:
+	os_close_file(out_fds[0]);
+	os_close_file(out_fds[1]);
  out:
-	close(out_fds[1]);
-	close(in_fds[0]);
 	return(err);
 }
 
 void stop_watchdog(int in_fd, int out_fd)
 {
-	close(in_fd);
-	close(out_fd);
+	os_close_file(in_fd);
+	os_close_file(out_fd);
 }
 
 int ping_watchdog(int fd)
@@ -115,11 +120,12 @@ int ping_watchdog(int fd)
 	int n;
 	char c = '\n';
 
-	n = write(fd, &c, sizeof(c));
-	if(n < sizeof(c)){
-		printk("ping_watchdog - write failed, errno = %d\n",
-		       errno);
-		return(-errno);
+	n = os_write_file(fd, &c, sizeof(c));
+	if(n != sizeof(c)){
+		printk("ping_watchdog - write failed, err = %d\n", -n);
+		if(n < 0)
+			return(n);
+		return(-EIO);
 	}
 	return 1;
 
diff -puN arch/um/drivers/hostaudio_kern.c~uml-base-patch arch/um/drivers/hostaudio_kern.c
--- 25/arch/um/drivers/hostaudio_kern.c~uml-base-patch	2004-08-15 20:45:08.315390800 -0700
+++ 25-akpm/arch/um/drivers/hostaudio_kern.c	2004-08-15 20:46:03.203046608 -0700
@@ -5,12 +5,12 @@
 
 #include "linux/config.h"
 #include "linux/module.h"
-#include "linux/version.h"
 #include "linux/init.h"
 #include "linux/slab.h"
 #include "linux/fs.h"
 #include "linux/sound.h"
 #include "linux/soundcard.h"
+#include "asm/uaccess.h"
 #include "kern_util.h"
 #include "init.h"
 #include "hostaudio.h"
@@ -19,30 +19,39 @@
 char *dsp = HOSTAUDIO_DEV_DSP;
 char *mixer = HOSTAUDIO_DEV_MIXER;
 
+#define DSP_HELP \
+"    This is used to specify the host dsp device to the hostaudio driver.\n" \
+"    The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
+
+#define MIXER_HELP \
+"    This is used to specify the host mixer device to the hostaudio driver.\n" \
+"    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
+
 #ifndef MODULE
 static int set_dsp(char *name, int *add)
 {
-	dsp = uml_strdup(name);
+	dsp = name;
 	return(0);
 }
 
-__uml_setup("dsp=", set_dsp,
-"dsp=<dsp device>\n"
-"    This is used to specify the host dsp device to the hostaudio driver.\n"
-"    The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
-);
+__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
 
 static int set_mixer(char *name, int *add)
 {
-	mixer = uml_strdup(name);
+	mixer = name;
 	return(0);
 }
 
-__uml_setup("mixer=", set_mixer,
-"mixer=<mixer device>\n"
-"    This is used to specify the host mixer device to the hostaudio driver.\n"
-"    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
-);
+__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
+
+#else /*MODULE*/
+
+MODULE_PARM(dsp, "s");
+MODULE_PARM_DESC(dsp, DSP_HELP);
+
+MODULE_PARM(mixer, "s");
+MODULE_PARM_DESC(mixer, MIXER_HELP);
+
 #endif
 
 /* /dev/dsp file operations */
@@ -51,23 +60,55 @@ static ssize_t hostaudio_read(struct fil
 			      loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: read called, count = %d\n", count);
 #endif
 
-        return(hostaudio_read_user(state, buffer, count, ppos));
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if(kbuf == NULL)
+		return(-ENOMEM);
+
+        err = hostaudio_read_user(state, kbuf, count, ppos);
+	if(err < 0)
+		goto out;
+
+	if(copy_to_user(buffer, kbuf, err))
+		err = -EFAULT;
+
+ out:
+	kfree(kbuf);
+	return(err);
 }
 
 static ssize_t hostaudio_write(struct file *file, const char *buffer, 
 			       size_t count, loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: write called, count = %d\n", count);
 #endif
-        return(hostaudio_write_user(state, buffer, count, ppos));
+
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if(kbuf == NULL)
+		return(-ENOMEM);
+
+	err = -EFAULT;
+	if(copy_from_user(kbuf, buffer, count))
+		goto out;
+
+        err = hostaudio_write_user(state, kbuf, count, ppos);
+	if(err < 0)
+		goto out;
+
+ out:
+	kfree(kbuf);
+	return(err);
 }
 
 static unsigned int hostaudio_poll(struct file *file, 
@@ -86,12 +127,43 @@ static int hostaudio_ioctl(struct inode 
 			   unsigned int cmd, unsigned long arg)
 {
         struct hostaudio_state *state = file->private_data;
+	unsigned long data = 0;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: ioctl called, cmd = %u\n", cmd);
 #endif
+	switch(cmd){
+	case SNDCTL_DSP_SPEED:
+	case SNDCTL_DSP_STEREO:
+	case SNDCTL_DSP_GETBLKSIZE:
+	case SNDCTL_DSP_CHANNELS:
+	case SNDCTL_DSP_SUBDIVIDE:
+	case SNDCTL_DSP_SETFRAGMENT:
+		if(get_user(data, (int *) arg))
+			return(-EFAULT);
+		break;
+	default:
+		break;
+	}
+
+        err = hostaudio_ioctl_user(state, cmd, (unsigned long) &data);
+
+	switch(cmd){
+	case SNDCTL_DSP_SPEED:
+	case SNDCTL_DSP_STEREO:
+	case SNDCTL_DSP_GETBLKSIZE:
+	case SNDCTL_DSP_CHANNELS:
+	case SNDCTL_DSP_SUBDIVIDE:
+	case SNDCTL_DSP_SETFRAGMENT:
+		if(put_user(data, (int *) arg))
+			return(-EFAULT);
+		break;
+	default:
+		break;
+	}
 
-        return(hostaudio_ioctl_user(state, cmd, arg));
+	return(err);
 }
 
 static int hostaudio_open(struct inode *inode, struct file *file)
@@ -225,7 +297,8 @@ MODULE_LICENSE("GPL");
 
 static int __init hostaudio_init_module(void)
 {
-        printk(KERN_INFO "UML Audio Relay\n");
+        printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
+	       dsp, mixer);
 
 	module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
         if(module_data.dev_audio < 0){
diff -puN arch/um/drivers/hostaudio_user.c~uml-base-patch arch/um/drivers/hostaudio_user.c
--- 25/arch/um/drivers/hostaudio_user.c~uml-base-patch	2004-08-15 20:45:08.316390648 -0700
+++ 25-akpm/arch/um/drivers/hostaudio_user.c	2004-08-15 20:46:03.204046456 -0700
@@ -4,9 +4,6 @@
  */
 
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
 #include "hostaudio.h"
@@ -20,45 +17,31 @@
 ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer, 
 			    size_t count, loff_t *ppos)
 {
-	ssize_t ret;
-
 #ifdef DEBUG
         printk("hostaudio: read_user called, count = %d\n", count);
 #endif
 
-        ret = read(state->fd, buffer, count);
-
-        if(ret < 0) return(-errno);
-        return(ret);
+	return(os_read_file(state->fd, buffer, count));
 }
 
 ssize_t hostaudio_write_user(struct hostaudio_state *state, const char *buffer,
 			     size_t count, loff_t *ppos)
 {
-	ssize_t ret;
-
 #ifdef DEBUG
         printk("hostaudio: write_user called, count = %d\n", count);
 #endif
 
-        ret = write(state->fd, buffer, count);
-
-        if(ret < 0) return(-errno);
-        return(ret);
+	return(os_write_file(state->fd, buffer, count));
 }
 
 int hostaudio_ioctl_user(struct hostaudio_state *state, unsigned int cmd, 
 			 unsigned long arg)
 {
-	int ret;
 #ifdef DEBUG
         printk("hostaudio: ioctl_user called, cmd = %u\n", cmd);
 #endif
 
-        ret = ioctl(state->fd, cmd, arg);
-	
-        if(ret < 0) return(-errno);
-        return(ret);
+	return(os_ioctl_generic(state->fd, cmd, arg));
 }
 
 int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp)
@@ -67,14 +50,15 @@ int hostaudio_open_user(struct hostaudio
         printk("hostaudio: open_user called\n");
 #endif
 
-        state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-
-        if(state->fd >= 0) return(0);
+	state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
 
-        printk("hostaudio_open_user failed to open '%s', errno = %d\n",
-	       dsp, errno);
+	if(state->fd < 0) {
+		printk("hostaudio_open_user failed to open '%s', err = %d\n",
+		       dsp, -state->fd);
+		return(state->fd);
+	}
         
-        return(-errno); 
+	return(0);
 }
 
 int hostaudio_release_user(struct hostaudio_state *state)
@@ -82,10 +66,10 @@ int hostaudio_release_user(struct hostau
 #ifdef DEBUG
         printk("hostaudio: release called\n");
 #endif
-        if(state->fd >= 0){
-		close(state->fd);
-		state->fd=-1;
-        }
+	if(state->fd >= 0){
+		os_close_file(state->fd);
+		state->fd = -1;
+	}
 
         return(0);
 }
@@ -95,15 +79,11 @@ int hostaudio_release_user(struct hostau
 int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state, 
 				unsigned int cmd, unsigned long arg)
 {
-	int ret;
 #ifdef DEBUG
         printk("hostmixer: ioctl_user called cmd = %u\n",cmd);
 #endif
 
-        ret = ioctl(state->fd, cmd, arg);
-	if(ret < 0) 
-		return(-errno);
-	return(ret);
+	return(os_ioctl_generic(state->fd, cmd, arg));
 }
 
 int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w,
@@ -115,12 +95,13 @@ int hostmixer_open_mixdev_user(struct ho
 
         state->fd = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
 
-        if(state->fd >= 0) return(0);
-
-        printk("hostaudio_open_mixdev_user failed to open '%s', errno = %d\n",
-	       mixer, errno);
+	if(state->fd < 0) {
+	        printk("hostaudio_open_mixdev_user failed to open '%s', "
+		       "err = %d\n", mixer, state->fd);
+		return(state->fd);
+	}
         
-        return(-errno); 
+	return(0);
 }
 
 int hostmixer_release_mixdev_user(struct hostmixer_state *state)
@@ -130,7 +111,7 @@ int hostmixer_release_mixdev_user(struct
 #endif
 
         if(state->fd >= 0){
-		close(state->fd);
+		os_close_file(state->fd);
 		state->fd = -1;
         }
 
diff -puN arch/um/drivers/line.c~uml-base-patch arch/um/drivers/line.c
--- 25/arch/um/drivers/line.c~uml-base-patch	2004-08-15 20:45:08.317390496 -0700
+++ 25-akpm/arch/um/drivers/line.c	2004-08-15 20:46:03.206046152 -0700
@@ -6,8 +6,8 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/list.h"
+#include "linux/interrupt.h"
 #include "linux/devfs_fs_kernel.h"
-#include "asm/irq.h"
 #include "asm/uaccess.h"
 #include "chan_kern.h"
 #include "irq_user.h"
@@ -16,38 +16,55 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "os.h"
+#include "irq_kern.h"
 
 #define LINE_BUFSIZE 4096
 
-void line_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct line *dev = data;
 
 	if(dev->count > 0) 
 		chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq, 
 			       dev);
+	return IRQ_HANDLED;
 }
 
-void line_timer_cb(void *arg)
+static void line_timer_cb(void *arg)
 {
 	struct line *dev = arg;
 
 	line_interrupt(dev->driver->read_irq, dev, NULL);
 }
 
-static void buffer_data(struct line *line, const char *buf, int len)
+static int write_room(struct line *dev)
 {
-	int end;
+	int n;
+
+	if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
+
+	n = dev->head - dev->tail;
+	if(n <= 0) n = LINE_BUFSIZE + n;
+	return(n - 1);
+}
+
+static int buffer_data(struct line *line, const char *buf, int len)
+{
+	int end, room;
 
 	if(line->buffer == NULL){
 		line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
 		if(line->buffer == NULL){
 			printk("buffer_data - atomic allocation failed\n");
-			return;
+			return(0);
 		}
 		line->head = line->buffer;
 		line->tail = line->buffer;
 	}
+
+	room = write_room(line);
+	len = (len > room) ? room : len;
+
 	end = line->buffer + LINE_BUFSIZE - line->tail;
 	if(len < end){
 		memcpy(line->tail, buf, len);
@@ -60,6 +77,8 @@ static void buffer_data(struct line *lin
 		memcpy(line->buffer, buf, len);
 		line->tail = line->buffer + len;
 	}
+
+	return(len);
 }
 
 static int flush_buffer(struct line *line)
@@ -95,7 +114,7 @@ int line_write(struct line *lines, struc
 	struct line *line;
 	char *new;
 	unsigned long flags;
-	int n, err, i;
+	int n, err, i, ret = 0;
 
 	if(tty->stopped) return 0;
 
@@ -104,9 +123,13 @@ int line_write(struct line *lines, struc
 		if(new == NULL)
 			return(0);
 		n = copy_from_user(new, buf, len);
-		if(n == len)
-			return(-EFAULT);
 		buf = new;
+		if(n == len){
+			len = -EFAULT;
+			goto out_free;
+		}
+
+		len -= n;
 	}
 
 	i = tty->index;
@@ -115,41 +138,50 @@ int line_write(struct line *lines, struc
 	down(&line->sem);
 	if(line->head != line->tail){
 		local_irq_save(flags);
-		buffer_data(line, buf, len);
+		ret += buffer_data(line, buf, len);
 		err = flush_buffer(line);
 		local_irq_restore(flags);
 		if(err <= 0)
-			goto out;
+			goto out_up;
 	}
 	else {
 		n = write_chan(&line->chan_list, buf, len, 
 			       line->driver->write_irq);
 		if(n < 0){
-			len = n;
-			goto out;
+			ret = n;
+			goto out_up;
 		}
-		if(n < len)
-			buffer_data(line, buf + n, len - n);
+
+		len -= n;
+		ret += n;
+		if(len > 0)
+			ret += buffer_data(line, buf + n, len);
 	}
- out:
+ out_up:
 	up(&line->sem);
-	return(len);
+ out_free:
+	if(from_user)
+		kfree(buf);
+	return(ret);
 }
 
-void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_write_interrupt(int irq, void *data,
+					struct pt_regs *unused)
 {
 	struct line *dev = data;
 	struct tty_struct *tty = dev->tty;
 	int err;
 
 	err = flush_buffer(dev);
-	if(err == 0) return;
+	if(err == 0)
+		return(IRQ_NONE);
 	else if(err < 0){
 		dev->head = dev->buffer;
 		dev->tail = dev->buffer;
 	}
 
-	if(tty == NULL) return;
+	if(tty == NULL)
+		return(IRQ_NONE);
 
 	if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
 	   (tty->ldisc.write_wakeup != NULL))
@@ -161,21 +193,9 @@ void line_write_interrupt(int irq, void 
 	 * writes.
 	 */
 
-	if (waitqueue_active(&tty->write_wait))
+	if(waitqueue_active(&tty->write_wait))
 		wake_up_interruptible(&tty->write_wait);
-
-}
-
-int line_write_room(struct tty_struct *tty)
-{
-	struct line *dev = tty->driver_data;
-	int n;
-
-	if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
-
-	n = dev->head - dev->tail;
-	if(n <= 0) n = LINE_BUFSIZE + n;
-	return(n - 1);
+	return(IRQ_HANDLED);
 }
 
 int line_setup_irq(int fd, int input, int output, void *data)
@@ -305,7 +325,7 @@ int line_setup(struct line *lines, int n
 		if(*end != '='){
 			printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 
 			       init);
-			return(1);
+			return(0);
 		}
 		init = end;
 	}
@@ -313,12 +333,12 @@ int line_setup(struct line *lines, int n
 	if((n >= 0) && (n >= num)){
 		printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
 		       n, num);
-		return(1);
+		return(0);
 	}
 	else if(n >= 0){
 		if(lines[n].count > 0){
 			printk("line_setup - device %d is open\n", n);
-			return(1);
+			return(0);
 		}
 		if(lines[n].init_pri <= INIT_ONE){
 			lines[n].init_pri = INIT_ONE;
@@ -332,7 +352,7 @@ int line_setup(struct line *lines, int n
 	else if(!all_allowed){
 		printk("line_setup - can't configure all devices from "
 		       "mconsole\n");
-		return(1);
+		return(0);
 	}
 	else {
 		for(i = 0; i < num; i++){
@@ -346,7 +366,7 @@ int line_setup(struct line *lines, int n
 			}
 		}
 	}
-	return(0);
+	return(1);
 }
 
 int line_config(struct line *lines, int num, char *str)
@@ -357,7 +377,7 @@ int line_config(struct line *lines, int 
 		printk("line_config - uml_strdup failed\n");
 		return(-ENOMEM);
 	}
-	return(line_setup(lines, num, new, 0));
+	return(!line_setup(lines, num, new, 0));
 }
 
 int line_get_config(char *name, struct line *lines, int num, char *str, 
@@ -369,7 +389,7 @@ int line_get_config(char *name, struct l
 
 	dev = simple_strtoul(name, &end, 0);
 	if((*end != '\0') || (end == name)){
-		*error_out = "line_setup failed to parse device number";
+		*error_out = "line_get_config failed to parse device number";
 		return(0);
 	}
 
@@ -379,15 +399,15 @@ int line_get_config(char *name, struct l
 	}
 
 	line = &lines[dev];
+
 	down(&line->sem);
-	
 	if(!line->valid)
 		CONFIG_CHUNK(str, size, n, "none", 1);
 	else if(line->count == 0)
 		CONFIG_CHUNK(str, size, n, line->init_str, 1);
 	else n = chan_config_string(&line->chan_list, str, size, error_out);
-
 	up(&line->sem);
+
 	return(n);
 }
 
@@ -396,7 +416,14 @@ int line_remove(struct line *lines, int 
 	char config[sizeof("conxxxx=none\0")];
 
 	sprintf(config, "%s=none", str);
-	return(line_setup(lines, num, config, 0));
+	return(!line_setup(lines, num, config, 0));
+}
+
+int line_write_room(struct tty_struct *tty)
+{
+	struct line *dev = tty->driver_data;
+
+	return(write_room(dev));
 }
 
 struct tty_driver *line_register_devfs(struct lines *set,
@@ -412,7 +439,8 @@ struct tty_driver *line_register_devfs(s
 		return NULL;
 
 	driver->driver_name = line_driver->name;
-	driver->name = line_driver->devfs_name;
+	driver->name = line_driver->device_name;
+	driver->devfs_name = line_driver->devfs_name;
 	driver->major = line_driver->major;
 	driver->minor_start = line_driver->minor_start;
 	driver->type = line_driver->type;
@@ -432,7 +460,7 @@ struct tty_driver *line_register_devfs(s
 
 	for(i = 0; i < nlines; i++){
 		if(!lines[i].valid) 
-			tty_unregister_devfs(driver, i);
+			tty_unregister_device(driver, i);
 	}
 
 	mconsole_register_dev(&line_driver->mc);
@@ -465,24 +493,25 @@ struct winch {
 	struct line *line;
 };
 
-void winch_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct winch *winch = data;
 	struct tty_struct *tty;
 	int err;
 	char c;
 
-	err = generic_read(winch->fd, &c, NULL);
-	if(err < 0){
-		if(err != -EAGAIN){
-			printk("winch_interrupt : read failed, errno = %d\n", 
-			       -err);
-			printk("fd %d is losing SIGWINCH support\n", 
-			       winch->tty_fd);
-			free_irq(irq, data);
-			return;
+	if(winch->fd != -1){
+		err = generic_read(winch->fd, &c, NULL);
+		if(err < 0){
+			if(err != -EAGAIN){
+				printk("winch_interrupt : read failed, "
+				       "errno = %d\n", -err);
+				printk("fd %d is losing SIGWINCH support\n",
+				       winch->tty_fd);
+				return(IRQ_HANDLED);
+			}
+			goto out;
 		}
-		goto out;
 	}
 	tty = winch->line->tty;
 	if(tty != NULL){
@@ -492,7 +521,9 @@ void winch_interrupt(int irq, void *data
 		kill_pg(tty->pgrp, SIGWINCH, 1);
 	}
  out:
-	reactivate_fd(winch->fd, WINCH_IRQ);
+	if(winch->fd != -1)
+		reactivate_fd(winch->fd, WINCH_IRQ);
+	return(IRQ_HANDLED);
 }
 
 DECLARE_MUTEX(winch_handler_sem);
@@ -529,7 +560,10 @@ static void winch_cleanup(void)
 
 	list_for_each(ele, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
-		close(winch->fd);
+		if(winch->fd != -1){
+			deactivate_fd(winch->fd, WINCH_IRQ);
+			os_close_file(winch->fd);
+		}
 		if(winch->pid != -1) 
 			os_kill_process(winch->pid, 1);
 	}
diff -puN arch/um/drivers/Makefile~uml-base-patch arch/um/drivers/Makefile
--- 25/arch/um/drivers/Makefile~uml-base-patch	2004-08-15 20:45:08.319390192 -0700
+++ 25-akpm/arch/um/drivers/Makefile	2004-08-15 20:46:03.206046152 -0700
@@ -1,5 +1,5 @@
 # 
-# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
 
@@ -39,6 +39,8 @@ obj-$(CONFIG_PTY_CHAN) += pty.o
 obj-$(CONFIG_TTY_CHAN) += tty.o 
 obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
+obj-$(CONFIG_BLK_DEV_COW) += cow_kern.o
+obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
 
 obj-y += stdio_console.o $(CHAN_OBJS)
 
@@ -46,18 +48,7 @@ USER_SINGLE_OBJS = $(foreach f,$(patsubs
 
 USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
 	null.o pty.o tty.o xterm.o
-USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
-
-modules:
-
-fastdep:
-
-dep:
-
-archmrproper: clean
-
diff -puN arch/um/drivers/mcast_user.c~uml-base-patch arch/um/drivers/mcast_user.c
--- 25/arch/um/drivers/mcast_user.c~uml-base-patch	2004-08-15 20:45:08.320390040 -0700
+++ 25-akpm/arch/um/drivers/mcast_user.c	2004-08-15 20:46:03.207046000 -0700
@@ -23,6 +23,7 @@
 #include "kern_util.h"
 #include "user_util.h"
 #include "user.h"
+#include "os.h"
 
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
@@ -62,7 +63,8 @@ static int mcast_open(void *data)
 		goto out;
 	}
 
-	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd < 0){
 		printk("mcast_open : data socket failed, errno = %d\n", 
 		       errno);
 		fd = -ENOMEM;
@@ -72,7 +74,7 @@ static int mcast_open(void *data)
 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
 		printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -82,7 +84,7 @@ static int mcast_open(void *data)
 		       sizeof(pri->ttl)) < 0) {
 		printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -91,7 +93,7 @@ static int mcast_open(void *data)
 	if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
 		printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -99,7 +101,7 @@ static int mcast_open(void *data)
 	/* bind socket to mcast address */
 	if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
 		printk("mcast_open : data bind failed, errno = %d\n", errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}		
@@ -115,7 +117,7 @@ static int mcast_open(void *data)
 		       "interface on the host.\n");
 		printk("eth0 should be configured in order to use the "
 		       "multicast transport.\n");
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 	}
 
@@ -137,7 +139,7 @@ static void mcast_close(int fd, void *da
 			errno);
 	}
 
-	close(fd);
+	os_close_file(fd);
 }
 
 int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
diff -puN arch/um/drivers/mconsole_kern.c~uml-base-patch arch/um/drivers/mconsole_kern.c
--- 25/arch/um/drivers/mconsole_kern.c~uml-base-patch	2004-08-15 20:45:08.322389736 -0700
+++ 25-akpm/arch/um/drivers/mconsole_kern.c	2004-08-15 20:46:03.208045848 -0700
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -15,6 +15,9 @@
 #include "linux/sysrq.h"
 #include "linux/workqueue.h"
 #include "linux/module.h"
+#include "linux/file.h"
+#include "linux/fs.h"
+#include "linux/namei.h"
 #include "linux/proc_fs.h"
 #include "asm/irq.h"
 #include "asm/uaccess.h"
@@ -27,6 +30,7 @@
 #include "init.h"
 #include "os.h"
 #include "umid.h"
+#include "irq_kern.h"
 
 static int do_unlink_socket(struct notifier_block *notifier, 
 			    unsigned long what, void *data)
@@ -67,7 +71,7 @@ void mc_work_proc(void *unused)
 
 DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
 
-void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int fd;
 	struct mconsole_entry *new;
@@ -75,9 +79,10 @@ void mconsole_interrupt(int irq, void *d
 
 	fd = (int) dev_id;
 	while (mconsole_get_request(fd, &req)){
-		if(req.cmd->as_interrupt) (*req.cmd->handler)(&req);
+		if(req.cmd->context == MCONSOLE_INTR)
+			(*req.cmd->handler)(&req);
 		else {
-			new = kmalloc(sizeof(req), GFP_ATOMIC);
+			new = kmalloc(sizeof(*new), GFP_ATOMIC);
 			if(new == NULL)
 				mconsole_reply(&req, "Out of memory", 1, 0);
 			else {
@@ -88,6 +93,7 @@ void mconsole_interrupt(int irq, void *d
 	}
 	if(!list_empty(&mc_requests)) schedule_work(&mconsole_work);
 	reactivate_fd(fd, MCONSOLE_IRQ);
+	return(IRQ_HANDLED);
 }
 
 void mconsole_version(struct mc_request *req)
@@ -100,20 +106,109 @@ void mconsole_version(struct mc_request 
 	mconsole_reply(req, version, 0, 0);
 }
 
+void mconsole_log(struct mc_request *req)
+{
+	int len;
+	char *ptr = req->request.data;
+
+	ptr += strlen("log ");
+
+	len = req->len - (ptr - req->request.data);
+	printk("%.*s", len, ptr);
+	mconsole_reply(req, "", 0, 0);
+}
+
+void mconsole_proc(struct mc_request *req)
+{
+	struct nameidata nd;
+	struct file_system_type *proc;
+	struct super_block *super;
+	struct file *file;
+	int n, err;
+	char *ptr = req->request.data, *buf;
+
+	ptr += strlen("proc");
+	while(isspace(*ptr)) ptr++;
+
+	proc = get_fs_type("proc");
+	if(proc == NULL){
+		mconsole_reply(req, "procfs not registered", 1, 0);
+		goto out;
+	}
+
+	super = (*proc->get_sb)(proc, 0, NULL, NULL);
+	put_filesystem(proc);
+	if(super == NULL){
+		mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
+		goto out;
+	}
+	up_write(&super->s_umount);
+
+	nd.dentry = super->s_root;
+	nd.mnt = NULL;
+	nd.flags = O_RDONLY + 1;
+	nd.last_type = LAST_ROOT;
+
+	err = link_path_walk(ptr, &nd);
+	if(err){
+		mconsole_reply(req, "Failed to look up file", 1, 0);
+		goto out_kill;
+	}
+
+	file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+	if(IS_ERR(file)){
+		mconsole_reply(req, "Failed to open file", 1, 0);
+		goto out_kill;
+	}
+
+	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if(buf == NULL){
+		mconsole_reply(req, "Failed to allocate buffer", 1, 0);
+		goto out_fput;
+	}
+
+	if((file->f_op != NULL) && (file->f_op->read != NULL)){
+		do {
+			n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
+						&file->f_pos);
+			if(n >= 0){
+				buf[n] = '\0';
+				mconsole_reply(req, buf, 0, (n > 0));
+			}
+			else {
+				mconsole_reply(req, "Read of file failed",
+					       1, 0);
+				goto out_free;
+			}
+		} while(n > 0);
+	}
+	else mconsole_reply(req, "", 0, 0);
+
+ out_free:
+	kfree(buf);
+ out_fput:
+	fput(file);
+ out_kill:
+	deactivate_super(super);
+ out: ;
+}
+
 #define UML_MCONSOLE_HELPTEXT \
-"Commands:
-    version - Get kernel version
-    help - Print this message
-    halt - Halt UML
-    reboot - Reboot UML
-    config <dev>=<config> - Add a new device to UML; 
-	same syntax as command line
-    config <dev> - Query the configuration of a device
-    remove <dev> - Remove a device from UML
-    sysrq <letter> - Performs the SysRq action controlled by the letter
-    cad - invoke the Ctl-Alt-Del handler
-    stop - pause the UML; it will do nothing until it receives a 'go'
-    go - continue the UML after a 'stop'
+"Commands: \n\
+    version - Get kernel version \n\
+    help - Print this message \n\
+    halt - Halt UML \n\
+    reboot - Reboot UML \n\
+    config <dev>=<config> - Add a new device to UML;  \n\
+	same syntax as command line \n\
+    config <dev> - Query the configuration of a device \n\
+    remove <dev> - Remove a device from UML \n\
+    sysrq <letter> - Performs the SysRq action controlled by the letter \n\
+    cad - invoke the Ctl-Alt-Del handler \n\
+    stop - pause the UML; it will do nothing until it receives a 'go' \n\
+    go - continue the UML after a 'stop' \n\
+    log <string> - make UML enter <string> into the kernel log\n\
+    proc <file> - returns the contents of the UML's /proc/<file>\n\
 "
 
 void mconsole_help(struct mc_request *req)
@@ -302,7 +397,7 @@ int mconsole_init(void)
 	if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
 	snprintf(mconsole_socket_name, sizeof(file), "%s", file);
 
-	sock = create_unix_socket(file, sizeof(file));
+	sock = os_create_unix_socket(file, sizeof(file), 1);
 	if (sock < 0){
 		printk("Failed to initialize management console\n");
 		return(1);
@@ -344,11 +439,16 @@ static int write_proc_mconsole(struct fi
 	if(buf == NULL) 
 		return(-ENOMEM);
 
-	if(copy_from_user(buf, buffer, count))
-		return(-EFAULT);
+	if(copy_from_user(buf, buffer, count)){
+		count = -EFAULT;
+		goto out;
+	}
+
 	buf[count] = '\0';
 
 	mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count);
+ out:
+	kfree(buf);
 	return(count);
 }
 
diff -puN arch/um/drivers/mconsole_user.c~uml-base-patch arch/um/drivers/mconsole_user.c
--- 25/arch/um/drivers/mconsole_user.c~uml-base-patch	2004-08-15 20:45:08.323389584 -0700
+++ 25-akpm/arch/um/drivers/mconsole_user.c	2004-08-15 20:46:03.209045696 -0700
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -18,16 +18,18 @@
 #include "umid.h"
 
 static struct mconsole_command commands[] = {
-	{ "version", mconsole_version, 1 },
-	{ "halt", mconsole_halt, 0 },
-	{ "reboot", mconsole_reboot, 0 },
-	{ "config", mconsole_config, 0 },
-	{ "remove", mconsole_remove, 0 },
-	{ "sysrq", mconsole_sysrq, 1 },
-	{ "help", mconsole_help, 1 },
-	{ "cad", mconsole_cad, 1 },
-	{ "stop", mconsole_stop, 0 },
-	{ "go", mconsole_go, 1 },
+	{ "version", mconsole_version, MCONSOLE_INTR },
+	{ "halt", mconsole_halt, MCONSOLE_PROC },
+	{ "reboot", mconsole_reboot, MCONSOLE_PROC },
+	{ "config", mconsole_config, MCONSOLE_PROC },
+	{ "remove", mconsole_remove, MCONSOLE_PROC },
+	{ "sysrq", mconsole_sysrq, MCONSOLE_INTR },
+	{ "help", mconsole_help, MCONSOLE_INTR },
+	{ "cad", mconsole_cad, MCONSOLE_INTR },
+	{ "stop", mconsole_stop, MCONSOLE_PROC },
+	{ "go", mconsole_go, MCONSOLE_INTR },
+	{ "log", mconsole_log, MCONSOLE_INTR },
+	{ "proc", mconsole_proc, MCONSOLE_PROC },
 };
 
 /* Initialized in mconsole_init, which is an initcall */
@@ -139,6 +141,7 @@ int mconsole_reply(struct mc_request *re
 		memcpy(reply.data, str, len);
 		reply.data[len] = '\0';
 		total -= len;
+		str += len;
 		reply.len = len + 1;
 
 		len = sizeof(reply) + reply.len - sizeof(reply.data);
diff -puN arch/um/drivers/mmapper_kern.c~uml-base-patch arch/um/drivers/mmapper_kern.c
--- 25/arch/um/drivers/mmapper_kern.c~uml-base-patch	2004-08-15 20:45:08.324389432 -0700
+++ 25-akpm/arch/um/drivers/mmapper_kern.c	2004-08-15 20:46:03.209045696 -0700
@@ -120,7 +120,10 @@ static int __init mmapper_init(void)
 	printk(KERN_INFO "Mapper v0.1\n");
 
 	v_buf = (char *) find_iomem("mmapper", &mmapper_size);
-	if(mmapper_size == 0) return(0);
+	if(mmapper_size == 0){
+		printk(KERN_ERR "mmapper_init - find_iomem failed\n");
+		return(0);
+	}
 
 	p_buf = __pa(v_buf);
 
diff -puN arch/um/drivers/net_kern.c~uml-base-patch arch/um/drivers/net_kern.c
--- 25/arch/um/drivers/net_kern.c~uml-base-patch	2004-08-15 20:45:08.326389128 -0700
+++ 25-akpm/arch/um/drivers/net_kern.c	2004-08-15 20:46:03.211045392 -0700
@@ -26,6 +26,7 @@
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
 LIST_HEAD(opened);
@@ -37,7 +38,8 @@ static int uml_net_rx(struct net_device 
 	struct sk_buff *skb;
 
 	/* If we can't allocate memory, try again next round. */
-	if ((skb = dev_alloc_skb(dev->mtu)) == NULL) {
+	skb = dev_alloc_skb(dev->mtu);
+	if (skb == NULL) {
 		lp->stats.rx_dropped++;
 		return 0;
 	}
@@ -61,14 +63,14 @@ static int uml_net_rx(struct net_device 
 	return pkt_len;
 }
 
-void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct uml_net_private *lp = dev->priv;
 	int err;
 
 	if(!netif_running(dev))
-		return;
+		return(IRQ_NONE);
 
 	spin_lock(&lp->lock);
 	while((err = uml_net_rx(dev)) > 0) ;
@@ -83,6 +85,7 @@ void uml_net_interrupt(int irq, void *de
 
  out:
 	spin_unlock(&lp->lock);
+	return(IRQ_HANDLED);
 }
 
 static int uml_net_open(struct net_device *dev)
@@ -250,37 +253,6 @@ void uml_net_user_timer_expire(unsigned 
 #endif
 }
 
-/*
- * default do nothing hard header packet routines for struct net_device init.
- * real ethernet transports will overwrite with real routines.
- */
-static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
-                 unsigned short type, void *daddr, void *saddr, unsigned len)
-{
-	return(0); /* no change */
-}
-
-static int uml_net_rebuild_header(struct sk_buff *skb)
-{
-	return(0); /* ignore */ 
-}
-
-static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
-{
-	return(-1); /* fail */
-}
-
-static void uml_net_header_cache_update(struct hh_cache *hh,
-                 struct net_device *dev, unsigned char * haddr)
-{
-	/* ignore */
-}
-
-static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
-{
-	return(0); /* nothing */
-}
-
 static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
 static struct list_head devices = LIST_HEAD_INIT(devices);
 
@@ -290,7 +262,7 @@ static int eth_configure(int n, void *in
 	struct uml_net *device;
 	struct net_device *dev;
 	struct uml_net_private *lp;
-	int err, size;
+	int save, err, size;
 
 	size = transport->private_size + sizeof(struct uml_net_private) + 
 		sizeof(((struct uml_net_private *) 0)->user);
@@ -332,12 +304,6 @@ static int eth_configure(int n, void *in
 	snprintf(dev->name, sizeof(dev->name), "eth%d", n);
 	device->dev = dev;
 
-        dev->hard_header = uml_net_hard_header;
-        dev->rebuild_header = uml_net_rebuild_header;
-        dev->hard_header_cache = uml_net_header_cache;
-        dev->header_cache_update= uml_net_header_cache_update;
-        dev->hard_header_parse = uml_net_header_parse;
-
 	(*transport->kern->init)(dev, init);
 
 	dev->mtu = transport->user->max_packet;
@@ -364,21 +330,29 @@ static int eth_configure(int n, void *in
 	}
 	lp = dev->priv;
 
-	INIT_LIST_HEAD(&lp->list);
-	spin_lock_init(&lp->lock);
-	lp->dev = dev;
-	lp->fd = -1;
-	lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 };
-	lp->have_mac = device->have_mac;
-	lp->protocol = transport->kern->protocol;
-	lp->open = transport->user->open;
-	lp->close = transport->user->close;
-	lp->remove = transport->user->remove;
-	lp->read = transport->kern->read;
-	lp->write = transport->kern->write;
-	lp->add_address = transport->user->add_address;
-	lp->delete_address = transport->user->delete_address;
-	lp->set_mtu = transport->user->set_mtu;
+	/* lp.user is the first four bytes of the transport data, which
+	 * has already been initialized.  This structure assignment will
+	 * overwrite that, so we make sure that .user gets overwritten with
+	 * what it already has.
+	 */
+	save = lp->user[0];
+	*lp = ((struct uml_net_private)
+		{ .list  		= LIST_HEAD_INIT(lp->list),
+		  .lock 		= SPIN_LOCK_UNLOCKED,
+		  .dev 			= dev,
+		  .fd 			= -1,
+		  .mac 			= { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
+		  .have_mac 		= device->have_mac,
+		  .protocol 		= transport->kern->protocol,
+		  .open 		= transport->user->open,
+		  .close 		= transport->user->close,
+		  .remove 		= transport->user->remove,
+		  .read 		= transport->kern->read,
+		  .write 		= transport->kern->write,
+		  .add_address 		= transport->user->add_address,
+		  .delete_address  	= transport->user->delete_address,
+		  .set_mtu 		= transport->user->set_mtu,
+		  .user  		= { save } });
 
 	init_timer(&lp->tl);
 	lp->tl.function = uml_net_user_timer_expire;
@@ -611,7 +585,8 @@ static int net_remove(char *str)
 	unregister_netdev(dev);
 
 	list_del(&device->list);
-	free_netdev(device);
+	kfree(device);
+	free_netdev(dev);
 	return(0);
 }
 
diff -puN arch/um/drivers/net_user.c~uml-base-patch arch/um/drivers/net_user.c
--- 25/arch/um/drivers/net_user.c~uml-base-patch	2004-08-15 20:45:08.327388976 -0700
+++ 25-akpm/arch/um/drivers/net_user.c	2004-08-15 20:46:03.212045240 -0700
@@ -26,8 +26,7 @@ int tap_open_common(void *dev, char *gat
 	if(gate_addr == NULL) return(0);
 	if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], 
 		  &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
-		printk("Invalid tap IP address - '%s'\n", 
-		       gate_addr);
+		printk("Invalid tap IP address - '%s'\n", gate_addr);
 		return(-EINVAL);
 	}
 	return(0);
@@ -60,18 +59,18 @@ void read_output(int fd, char *output, i
 	}
 		
 	*output = '\0';
-	if(read(fd, &remain, sizeof(remain)) != sizeof(remain)){
-		printk("read_output - read of length failed, errno = %d\n",
-		       errno);
+	n = os_read_file(fd, &remain, sizeof(remain));
+	if(n != sizeof(remain)){
+		printk("read_output - read of length failed, err = %d\n", -n);
 		return;
 	}
 
 	while(remain != 0){
 		n = (remain < len) ? remain : len;
-		actual = read(fd, output, n);
+		actual = os_read_file(fd, output, n);
 		if(actual != n){
 			printk("read_output - read of data failed, "
-			       "errno = %d\n", errno);
+			       "err = %d\n", -actual);
 			return;
 		}
 		remain -= actual;
@@ -83,13 +82,12 @@ int net_read(int fd, void *buf, int len)
 {
 	int n;
 
-	while(((n = read(fd,  buf,  len)) < 0) && (errno == EINTR)) ;
+	n = os_read_file(fd,  buf,  len);
 
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-ENOTCONN);
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-ENOTCONN);
 	return(n);
 }
 
@@ -112,13 +110,13 @@ int net_write(int fd, void *buf, int len
 {
 	int n;
 
-	while(((n = write(fd, buf, len)) < 0) && (errno == EINTR)) ;
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-ENOTCONN);
-	return(n);	
+	n = os_write_file(fd, buf, len);
+
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-ENOTCONN);
+	return(n);
 }
 
 int net_send(int fd, void *buf, int len)
@@ -157,7 +155,7 @@ static void change_pre_exec(void *arg)
 {
 	struct change_pre_exec_data *data = arg;
 
-	close(data->close_me);
+	os_close_file(data->close_me);
 	dup2(data->stdout, 1);
 }
 
@@ -167,15 +165,15 @@ static int change_tramp(char **argv, cha
 	struct change_pre_exec_data pe_data;
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("change_tramp - pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("change_tramp - pipe failed, err = %d\n", -err);
 		return(err);
 	}
 	pe_data.close_me = fds[0];
 	pe_data.stdout = fds[1];
 	pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
 
-	close(fds[1]);
+	os_close_file(fds[1]);
 	read_output(fds[0], output, output_len);
 	waitpid(pid, NULL, 0);	
 	return(pid);
diff -puN arch/um/drivers/null.c~uml-base-patch arch/um/drivers/null.c
--- 25/arch/um/drivers/null.c~uml-base-patch	2004-08-15 20:45:08.328388824 -0700
+++ 25-akpm/arch/um/drivers/null.c	2004-08-15 20:46:03.212045240 -0700
@@ -5,7 +5,6 @@
 
 #include <stdlib.h>
 #include <errno.h>
-#include <fcntl.h>
 #include "chan_user.h"
 #include "os.h"
 
diff -puN arch/um/drivers/port_kern.c~uml-base-patch arch/um/drivers/port_kern.c
--- 25/arch/um/drivers/port_kern.c~uml-base-patch	2004-08-15 20:45:08.329388672 -0700
+++ 25-akpm/arch/um/drivers/port_kern.c	2004-08-15 20:46:03.213045088 -0700
@@ -6,6 +6,7 @@
 #include "linux/list.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
+#include "linux/interrupt.h"
 #include "linux/irq.h"
 #include "linux/spinlock.h"
 #include "linux/errno.h"
@@ -14,6 +15,7 @@
 #include "kern_util.h"
 #include "kern.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "port.h"
 #include "init.h"
 #include "os.h"
@@ -38,21 +40,21 @@ struct port_dev {
 struct connection {
 	struct list_head list;
 	int fd;
- 	int helper_pid;
+	int helper_pid;
 	int socket[2];
 	int telnetd_pid;
 	struct port_list *port;
 };
 
-static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct connection *conn = data;
 	int fd;
 
- 	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
+	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
 	if(fd < 0){
 		if(fd == -EAGAIN)
-			return;
+			return(IRQ_NONE);
 
 		printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", 
 		       -fd);
@@ -65,6 +67,7 @@ static void pipe_interrupt(int irq, void
 	list_add(&conn->list, &conn->port->connections);
 
 	up(&conn->port->sem);
+	return(IRQ_HANDLED);
 }
 
 static int port_accept(struct port_list *port)
@@ -102,8 +105,7 @@ static int port_accept(struct port_list 
 	}
 
 	list_add(&conn->list, &port->pending);
-	ret = 1;
-	goto out;
+	return(1);
 
  out_free:
 	kfree(conn);
@@ -138,12 +140,13 @@ void port_work_proc(void *unused)
 
 DECLARE_WORK(port_work, port_work_proc, NULL);
 
-static void port_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct port_list *port = data;
 
 	port->has_connection = 1;
 	schedule_work(&port_work);
+	return(IRQ_HANDLED);
 } 
 
 void *port_data(int port_num)
diff -puN arch/um/drivers/port_user.c~uml-base-patch arch/um/drivers/port_user.c
--- 25/arch/um/drivers/port_user.c~uml-base-patch	2004-08-15 20:45:08.331388368 -0700
+++ 25-akpm/arch/um/drivers/port_user.c	2004-08-15 20:46:03.213045088 -0700
@@ -47,10 +47,12 @@ void *port_init(char *str, int device, s
 		return(NULL);
 	}
 
-	if((kern_data = port_data(port)) == NULL) 
+	kern_data = port_data(port);
+	if(kern_data == NULL)
 		return(NULL);
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) 
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL)
 		goto err;
 
 	*data = ((struct port_chan) { .raw  		= opts->raw,
@@ -90,7 +92,7 @@ void port_close(int fd, void *d)
 	struct port_chan *data = d;
 
 	port_remove_dev(data->kernel_data);
-	close(fd);
+	os_close_file(fd);
 }
 
 int port_console_write(int fd, const char *buf, int n, void *d)
@@ -130,11 +132,15 @@ int port_listen_fd(int port)
 		goto out;
 	}
   
-	if((listen(fd, 1) < 0) || (os_set_fd_block(fd, 0))){
+	if(listen(fd, 1) < 0){
 		err = -errno;
 		goto out;
 	}
 
+	err = os_set_fd_block(fd, 0);
+	if(err < 0)
+		goto out;
+
 	return(fd);
  out:
 	os_close_file(fd);
@@ -153,10 +159,10 @@ void port_pre_exec(void *arg)
 	dup2(data->sock_fd, 0);
 	dup2(data->sock_fd, 1);
 	dup2(data->sock_fd, 2);
-	close(data->sock_fd);
+	os_close_file(data->sock_fd);
 	dup2(data->pipe_fd, 3);
 	os_shutdown_socket(3, 1, 0);
-	close(data->pipe_fd);
+	os_close_file(data->pipe_fd);
 }
 
 int port_connection(int fd, int *socket, int *pid_out)
@@ -166,11 +172,12 @@ int port_connection(int fd, int *socket,
 			 "/usr/lib/uml/port-helper", NULL };
 	struct port_pre_exec_data data;
 
-	if((new = os_accept_connection(fd)) < 0)
-		return(-errno);
+	new = os_accept_connection(fd);
+	if(new < 0)
+		return(new);
 
 	err = os_pipe(socket, 0, 0);
-	if(err) 
+	if(err < 0)
 		goto out_close;
 
 	data = ((struct port_pre_exec_data)
@@ -186,11 +193,11 @@ int port_connection(int fd, int *socket,
 
  out_shutdown:
 	os_shutdown_socket(socket[0], 1, 1);
-	close(socket[0]);
+	os_close_file(socket[0]);
 	os_shutdown_socket(socket[1], 1, 1);	
-	close(socket[1]);
+	os_close_file(socket[1]);
  out_close:
-	close(new);
+	os_close_file(new);
 	return(err);
 }
 
diff -puN arch/um/drivers/pty.c~uml-base-patch arch/um/drivers/pty.c
--- 25/arch/um/drivers/pty.c~uml-base-patch	2004-08-15 20:45:08.332388216 -0700
+++ 25-akpm/arch/um/drivers/pty.c	2004-08-15 20:46:03.214044936 -0700
@@ -7,12 +7,12 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <termios.h>
 #include "chan_user.h"
 #include "user.h"
 #include "user_util.h"
 #include "kern_util.h"
+#include "os.h"
 
 struct pty_chan {
 	void (*announce)(char *dev_name, int dev);
@@ -26,7 +26,8 @@ void *pty_chan_init(char *str, int devic
 {
 	struct pty_chan *data;
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct pty_chan) { .announce  	= opts->announce, 
 				     .dev  		= device,
 				     .raw  		= opts->raw });
@@ -39,7 +40,8 @@ int pts_open(int input, int output, int 
 	char *dev;
 	int fd;
 
-	if((fd = get_pty()) < 0){
+	fd = get_pty();
+	if(fd < 0){
 		printk("open_pts : Failed to open pts\n");
 		return(-errno);
 	}
@@ -57,29 +59,27 @@ int pts_open(int input, int output, int 
 
 int getmaster(char *line)
 {
-	struct stat stb;
 	char *pty, *bank, *cp;
-	int master;
+	int master, err;
 
 	pty = &line[strlen("/dev/ptyp")];
 	for (bank = "pqrs"; *bank; bank++) {
 		line[strlen("/dev/pty")] = *bank;
 		*pty = '0';
-		if (stat(line, &stb) < 0)
+		if (os_stat_file(line, NULL) < 0)
 			break;
 		for (cp = "0123456789abcdef"; *cp; cp++) {
 			*pty = *cp;
-			master = open(line, O_RDWR);
+			master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
 			if (master >= 0) {
 				char *tp = &line[strlen("/dev/")];
-				int ok;
 
 				/* verify slave side is usable */
 				*tp = 't';
-				ok = access(line, R_OK|W_OK) == 0;
+				err = os_access(line, OS_ACC_RW_OK);
 				*tp = 'p';
-				if (ok) return(master);
-				(void) close(master);
+				if(err == 0) return(master);
+				(void) os_close_file(master);
 			}
 		}
 	}
diff -puN arch/um/drivers/slip_user.c~uml-base-patch arch/um/drivers/slip_user.c
--- 25/arch/um/drivers/slip_user.c~uml-base-patch	2004-08-15 20:45:08.333388064 -0700
+++ 25-akpm/arch/um/drivers/slip_user.c	2004-08-15 20:46:03.215044784 -0700
@@ -4,11 +4,9 @@
 #include <stddef.h>
 #include <sched.h>
 #include <string.h>
-#include <sys/fcntl.h>
 #include <sys/errno.h>
 #include <sys/termios.h>
 #include <sys/wait.h>
-#include <sys/ioctl.h>
 #include <sys/signal.h>
 #include "user_util.h"
 #include "kern_util.h"
@@ -65,9 +63,9 @@ static void slip_pre_exec(void *arg)
 {
 	struct slip_pre_exec_data *data = arg;
 
-	if(data->stdin != -1) dup2(data->stdin, 0);
+	if(data->stdin >= 0) dup2(data->stdin, 0);
 	dup2(data->stdout, 1);
-	if(data->close_me != -1) close(data->close_me);
+	if(data->close_me >= 0) os_close_file(data->close_me);
 }
 
 static int slip_tramp(char **argv, int fd)
@@ -77,8 +75,8 @@ static int slip_tramp(char **argv, int f
 	int status, pid, fds[2], err, output_len;
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("slip_tramp : pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("slip_tramp : pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -96,7 +94,7 @@ static int slip_tramp(char **argv, int f
 			printk("slip_tramp : failed to allocate output "
 			       "buffer\n");
 
-		close(fds[1]);
+		os_close_file(fds[1]);
 		read_output(fds[0], output, output_len);
 		if(output != NULL){
 			printk("%s", output);
@@ -105,7 +103,7 @@ static int slip_tramp(char **argv, int f
 		if(waitpid(pid, &status, 0) < 0) err = errno;
 		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
 			printk("'%s' didn't exit with status 0\n", argv[0]);
-			err = EINVAL;
+			err = -EINVAL;
 		}
 	}
 	return(err);
@@ -118,15 +116,17 @@ static int slip_open(void *data)
 	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
 	char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, 
 			 NULL };
-	int sfd, mfd, disc, sencap, err;
+	int sfd, mfd, err;
 
-	if((mfd = get_pty()) < 0){
-		printk("umn : Failed to open pty\n");
-		return(-1);
+	mfd = get_pty();
+	if(mfd < 0){
+		printk("umn : Failed to open pty, err = %d\n", -mfd);
+		return(mfd);
 	}
-	if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){
-		printk("Couldn't open tty for slip line\n");
-		return(-1);
+	sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
+	if(sfd < 0){
+		printk("Couldn't open tty for slip line, err = %d\n", -sfd);
+		return(sfd);
 	}
 	if(set_up_tty(sfd)) return(-1);
 	pri->slave = sfd;
@@ -138,28 +138,23 @@ static int slip_open(void *data)
 
 		err = slip_tramp(argv, sfd);
 
-		if(err != 0){
-			printk("slip_tramp failed - errno = %d\n", err);
-			return(-err);
+		if(err < 0){
+			printk("slip_tramp failed - err = %d\n", -err);
+			return(err);
 		}
-		if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){
-			printk("SIOCGIFNAME failed, errno = %d\n", errno);
-			return(-errno);
+		err = os_get_ifname(pri->slave, pri->name);
+		if(err < 0){
+			printk("get_ifname failed, err = %d\n", -err);
+			return(err);
 		}
 		iter_addresses(pri->dev, open_addr, pri->name);
 	}
 	else {
-		disc = N_SLIP;
-		if(ioctl(sfd, TIOCSETD, &disc) < 0){
-			printk("Failed to set slip line discipline - "
-			       "errno = %d\n", errno);
-			return(-errno);
-		}
-		sencap = 0;
-		if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){
-			printk("Failed to set slip encapsulation - "
-			       "errno = %d\n", errno);
-			return(-errno);
+		err = os_set_slip(sfd);
+		if(err < 0){
+			printk("Failed to set slip discipline encapsulation - "
+			       "err = %d\n", -err);
+			return(err);
 		}
 	}
 	return(mfd);
@@ -181,9 +176,9 @@ static void slip_close(int fd, void *dat
 	err = slip_tramp(argv, -1);
 
 	if(err != 0)
-		printk("slip_tramp failed - errno = %d\n", err);
-	close(fd);
-	close(pri->slave);
+		printk("slip_tramp failed - errno = %d\n", -err);
+	os_close_file(fd);
+	os_close_file(pri->slave);
 	pri->slave = -1;
 }
 
@@ -243,7 +238,7 @@ static void slip_add_addr(unsigned char 
 {
 	struct slip_data *pri = data;
 
-	if(pri->slave == -1) return;
+	if(pri->slave < 0) return;
 	open_addr(addr, netmask, pri->name);
 }
 
@@ -252,7 +247,7 @@ static void slip_del_addr(unsigned char 
 {
 	struct slip_data *pri = data;
 
-	if(pri->slave == -1) return;
+	if(pri->slave < 0) return;
 	close_addr(addr, netmask, pri->name);
 }
 
diff -puN arch/um/drivers/slirp_user.c~uml-base-patch arch/um/drivers/slirp_user.c
--- 25/arch/um/drivers/slirp_user.c~uml-base-patch	2004-08-15 20:45:08.334387912 -0700
+++ 25-akpm/arch/um/drivers/slirp_user.c	2004-08-15 20:46:03.215044784 -0700
@@ -4,7 +4,6 @@
 #include <stddef.h>
 #include <sched.h>
 #include <string.h>
-#include <sys/fcntl.h>
 #include <sys/errno.h>
 #include <sys/wait.h>
 #include <sys/signal.h>
@@ -48,15 +47,15 @@ static int slirp_tramp(char **argv, int 
 
 	return(pid);
 }
- 
+
+/* XXX This is just a trivial wrapper around os_pipe */
 static int slirp_datachan(int *mfd, int *sfd)
 {
 	int fds[2], err;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("slirp_datachan: Failed to open pipe, errno = %d\n",
-		       -err);
+	if(err < 0){
+		printk("slirp_datachan: Failed to open pipe, err = %d\n", -err);
 		return(err);
 	}
 
@@ -77,7 +76,7 @@ static int slirp_open(void *data)
 	pid = slirp_tramp(pri->argw.argv, sfd);
 
 	if(pid < 0){
-		printk("slirp_tramp failed - errno = %d\n", pid);
+		printk("slirp_tramp failed - errno = %d\n", -pid);
 		os_close_file(sfd);	
 		os_close_file(mfd);	
 		return(pid);
@@ -97,8 +96,8 @@ static void slirp_close(int fd, void *da
 	struct slirp_data *pri = data;
 	int status,err;
 
-	close(fd);
-	close(pri->slave);
+	os_close_file(fd);
+	os_close_file(pri->slave);
 
 	pri->slave = -1;
 
diff -puN arch/um/drivers/ssl.c~uml-base-patch arch/um/drivers/ssl.c
--- 25/arch/um/drivers/ssl.c~uml-base-patch	2004-08-15 20:45:08.336387608 -0700
+++ 25-akpm/arch/um/drivers/ssl.c	2004-08-15 20:46:03.216044632 -0700
@@ -10,6 +10,7 @@
 #include "linux/major.h"
 #include "linux/mm.h"
 #include "linux/init.h"
+#include "linux/console.h"
 #include "asm/termbits.h"
 #include "asm/irq.h"
 #include "line.h"
@@ -53,8 +54,9 @@ static int ssl_remove(char *str);
 
 static struct line_driver driver = {
 	.name 			= "UML serial line",
-	.devfs_name 		= "tts/%d",
-	.major 			= TTYAUX_MAJOR,
+	.device_name 		= "ttS",
+	.devfs_name 		= "tts/",
+	.major 			= TTY_MAJOR,
 	.minor_start 		= 64,
 	.type 		 	= TTY_DRIVER_TYPE_SERIAL,
 	.subtype 	 	= 0,
@@ -149,6 +151,9 @@ static int ssl_ioctl(struct tty_struct *
 	case TCSETSW:
 	case TCGETA:
 	case TIOCMGET:
+	case TCSBRK:
+	case TCSBRKP:
+	case TIOCMSET:
 		ret = -ENOIOCTLCMD;
 		break;
 	default:
@@ -212,6 +217,37 @@ static struct tty_operations ssl_ops = {
  */
 static int ssl_init_done = 0;
 
+static void ssl_console_write(struct console *c, const char *string,
+			      unsigned len)
+{
+	struct line *line = &serial_lines[c->index];
+	if(ssl_init_done)
+		down(&line->sem);
+	console_write_chan(&line->chan_list, string, len);
+	if(ssl_init_done)
+		up(&line->sem);
+}
+
+static struct tty_driver *ssl_console_device(struct console *c, int *index)
+{
+	*index = c->index;
+	return ssl_driver;
+}
+
+static int ssl_console_setup(struct console *co, char *options)
+{
+	return(0);
+}
+
+static struct console ssl_cons = {
+	name:		"ttyS",
+	write:		ssl_console_write,
+	device:		ssl_console_device,
+	setup:		ssl_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
+
 int ssl_init(void)
 {
 	char *new_title;
@@ -227,17 +263,18 @@ int ssl_init(void)
 	new_title = add_xterm_umid(opts.xterm_title);
 	if(new_title != NULL) opts.xterm_title = new_title;
 
+	register_console(&ssl_cons);
 	ssl_init_done = 1;
 	return(0);
 }
 
-__initcall(ssl_init);
+late_initcall(ssl_init);
 
 static int ssl_chan_setup(char *str)
 {
-	line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]),
-		   str, 1);
-	return(1);
+	return(line_setup(serial_lines,
+			  sizeof(serial_lines)/sizeof(serial_lines[0]),
+			  str, 1));
 }
 
 __setup("ssl", ssl_chan_setup);
diff -puN arch/um/drivers/stdio_console.c~uml-base-patch arch/um/drivers/stdio_console.c
--- 25/arch/um/drivers/stdio_console.c~uml-base-patch	2004-08-15 20:45:08.337387456 -0700
+++ 25-akpm/arch/um/drivers/stdio_console.c	2004-08-15 20:46:03.217044480 -0700
@@ -83,7 +83,8 @@ static int con_remove(char *str);
 
 static struct line_driver driver = {
 	.name 			= "UML console",
-	.devfs_name 		= "vc/%d",
+	.device_name 		= "tty",
+	.devfs_name 		= "vc/",
 	.major 			= TTY_MAJOR,
 	.minor_start 		= 0,
 	.type 		 	= TTY_DRIVER_TYPE_CONSOLE,
@@ -159,6 +160,15 @@ static int chars_in_buffer(struct tty_st
 
 static int con_init_done = 0;
 
+static struct tty_operations console_ops = {
+	.open 	 		= con_open,
+	.close 	 		= con_close,
+	.write 	 		= con_write,
+	.chars_in_buffer 	= chars_in_buffer,
+	.set_termios 		= set_termios,
+	.write_room		= line_write_room,
+};
+
 int stdio_init(void)
 {
 	char *new_title;
@@ -166,7 +176,8 @@ int stdio_init(void)
 	printk(KERN_INFO "Initializing stdio console driver\n");
 
 	console_driver = line_register_devfs(&console_lines, &driver,
-				&console_ops, vts, sizeof(vts)/sizeof(vts[0]));
+					     &console_ops, vts,
+					     sizeof(vts)/sizeof(vts[0]));
 
 	lines_init(vts, sizeof(vts)/sizeof(vts[0]));
 
@@ -178,24 +189,19 @@ int stdio_init(void)
 	return(0);
 }
 
-__initcall(stdio_init);
+late_initcall(stdio_init);
 
 static void console_write(struct console *console, const char *string, 
 			  unsigned len)
 {
-	if(con_init_done) down(&vts[console->index].sem);
-	console_write_chan(&vts[console->index].chan_list, string, len);
-	if(con_init_done) up(&vts[console->index].sem);
-}
+	struct line *line = &vts[console->index];
 
-static struct tty_operations console_ops = {
-	.open 	 		= con_open,
-	.close 	 		= con_close,
-	.write 	 		= con_write,
-	.chars_in_buffer 	= chars_in_buffer,
-	.set_termios 		= set_termios,
-	.write_room		= line_write_room,
-};
+	if(con_init_done)
+		down(&line->sem);
+	console_write_chan(&line->chan_list, string, len);
+	if(con_init_done)
+		up(&line->sem);
+}
 
 static struct tty_driver *console_device(struct console *c, int *index)
 {
@@ -208,22 +214,28 @@ static int console_setup(struct console 
 	return(0);
 }
 
-static struct console stdiocons = INIT_CONSOLE("tty", console_write, 
-					       console_device, console_setup,
-					       CON_PRINTBUFFER);
+static struct console stdiocons = {
+	name:		"tty",
+	write:		console_write,
+	device:		console_device,
+	setup:		console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
 
-static void __init stdio_console_init(void)
+static int __init stdio_console_init(void)
 {
 	INIT_LIST_HEAD(&vts[0].chan_list);
 	list_add(&init_console_chan.list, &vts[0].chan_list);
 	register_console(&stdiocons);
+	return(0);
 }
+
 console_initcall(stdio_console_init);
 
 static int console_chan_setup(char *str)
 {
-	line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1);
-	return(1);
+	return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1));
 }
 
 __setup("con", console_chan_setup);
diff -puN arch/um/drivers/tty.c~uml-base-patch arch/um/drivers/tty.c
--- 25/arch/um/drivers/tty.c~uml-base-patch	2004-08-15 20:45:08.338387304 -0700
+++ 25-akpm/arch/um/drivers/tty.c	2004-08-15 20:46:03.217044480 -0700
@@ -5,7 +5,6 @@
 
 #include <stdio.h>
 #include <termios.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
 #include "chan_user.h"
@@ -30,7 +29,8 @@ void *tty_chan_init(char *str, int devic
 	}
 	str++;
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) 
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL)
 		return(NULL);
 	*data = ((struct tty_chan) { .dev 	= str,
 				     .raw 	= opts->raw });
diff -puN arch/um/drivers/ubd_kern.c~uml-base-patch arch/um/drivers/ubd_kern.c
--- 25/arch/um/drivers/ubd_kern.c~uml-base-patch	2004-08-15 20:45:08.340387000 -0700
+++ 25-akpm/arch/um/drivers/ubd_kern.c	2004-08-15 20:46:03.222043720 -0700
@@ -8,6 +8,13 @@
  * old style ubd by setting UBD_SHIFT to 0
  * 2002-09-27...2002-10-18 massive tinkering for 2.5
  * partitions have changed in 2.5
+ * 2003-01-29 more tinkering for 2.5.59-1
+ * This should now address the sysfs problems and has
+ * the symlink for devfs to allow for booting with
+ * the common /dev/ubd/discX/... names rather than
+ * only /dev/ubdN/discN this version also has lots of
+ * clean ups preparing for ubd-many.
+ * James McMechan
  */
 
 #define MAJOR_NR UBD_MAJOR
@@ -40,9 +47,12 @@
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "ubd_user.h"
 #include "2_5compat.h"
 #include "os.h"
+#include "mem.h"
+#include "mem_kern.h"
 
 static spinlock_t ubd_io_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED;
@@ -56,6 +66,10 @@ static int ubd_ioctl(struct inode * inod
 
 #define MAX_DEV (8)
 
+/* Changed in early boot */
+static int ubd_do_mmap = 0;
+#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
+
 static struct block_device_operations ubd_blops = {
         .owner		= THIS_MODULE,
         .open		= ubd_open,
@@ -67,7 +81,7 @@ static struct block_device_operations ub
 static request_queue_t *ubd_queue;
 
 /* Protected by ubd_lock */
-static int fake_major = 0;
+static int fake_major = MAJOR_NR;
 
 static struct gendisk *ubd_gendisk[MAX_DEV];
 static struct gendisk *fake_gendisk[MAX_DEV];
@@ -96,13 +110,19 @@ struct cow {
 
 struct ubd {
 	char *file;
-	int is_dir;
 	int count;
 	int fd;
 	__u64 size;
 	struct openflags boot_openflags;
 	struct openflags openflags;
+	int no_cow;
 	struct cow cow;
+
+	int map_writes;
+	int map_reads;
+	int nomap_writes;
+	int nomap_reads;
+	int write_maps;
 };
 
 #define DEFAULT_COW { \
@@ -115,21 +135,28 @@ struct ubd {
 
 #define DEFAULT_UBD { \
 	.file = 		NULL, \
-	.is_dir =		0, \
 	.count =		0, \
 	.fd =			-1, \
 	.size =			-1, \
 	.boot_openflags =	OPEN_FLAGS, \
 	.openflags =		OPEN_FLAGS, \
+        .no_cow =               0, \
         .cow =			DEFAULT_COW, \
+	.map_writes		= 0, \
+	.map_reads		= 0, \
+	.nomap_writes		= 0, \
+	.nomap_reads		= 0, \
+	.write_maps		= 0, \
 }
 
 struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
 
 static int ubd0_init(void)
 {
-	if(ubd_dev[0].file == NULL)
-		ubd_dev[0].file = "root_fs";
+	struct ubd *dev = &ubd_dev[0];
+
+	if(dev->file == NULL)
+		dev->file = "root_fs";
 	return(0);
 }
 
@@ -196,19 +223,46 @@ __uml_help(fake_ide_setup,
 "    Create ide0 entries that map onto ubd devices.\n\n"
 );
 
+static int parse_unit(char **ptr)
+{
+	char *str = *ptr, *end;
+	int n = -1;
+
+	if(isdigit(*str)) {
+		n = simple_strtoul(str, &end, 0);
+		if(end == str)
+			return(-1);
+		*ptr = end;
+	}
+	else if (('a' <= *str) && (*str <= 'h')) {
+		n = *str - 'a';
+		str++;
+		*ptr = str;
+	}
+	return(n);
+}
+
 static int ubd_setup_common(char *str, int *index_out)
 {
+	struct ubd *dev;
 	struct openflags flags = global_openflags;
 	char *backing_file;
 	int n, err;
 
 	if(index_out) *index_out = -1;
-	n = *str++;
+	n = *str;
 	if(n == '='){
-		static int fake_major_allowed = 1;
 		char *end;
 		int major;
 
+		str++;
+		if(!strcmp(str, "mmap")){
+			CHOOSE_MODE(printk("mmap not supported by the ubd "
+					   "driver in tt mode\n"),
+				    ubd_do_mmap = 1);
+			return(0);
+		}
+
 		if(!strcmp(str, "sync")){
 			global_openflags.s = 1;
 			return(0);
@@ -220,20 +274,14 @@ static int ubd_setup_common(char *str, i
 			return(1);
 		}
 
-		if(!fake_major_allowed){
-			printk(KERN_ERR "Can't assign a fake major twice\n");
-			return(1);
-		}
-
 		err = 1;
  		spin_lock(&ubd_lock);
- 		if(!fake_major_allowed){
+ 		if(fake_major != MAJOR_NR){
  			printk(KERN_ERR "Can't assign a fake major twice\n");
  			goto out1;
  		}
  
  		fake_major = major;
-		fake_major_allowed = 0;
 
 		printk(KERN_INFO "Setting extra ubd major number to %d\n",
 		       major);
@@ -243,25 +291,23 @@ static int ubd_setup_common(char *str, i
 		return(err);
 	}
 
-	if(n < '0'){
-		printk(KERN_ERR "ubd_setup : index out of range\n"); }
-
-	if((n >= '0') && (n <= '9')) n -= '0';
-	else if((n >= 'a') && (n <= 'z')) n -= 'a';
-	else {
-		printk(KERN_ERR "ubd_setup : device syntax invalid\n");
+	n = parse_unit(&str);
+	if(n < 0){
+		printk(KERN_ERR "ubd_setup : couldn't parse unit number "
+		       "'%s'\n", str);
 		return(1);
 	}
 	if(n >= MAX_DEV){
-		printk(KERN_ERR "ubd_setup : index out of range "
-		       "(%d devices)\n", MAX_DEV);	
+		printk(KERN_ERR "ubd_setup : index %d out of range "
+		       "(%d devices)\n", n, MAX_DEV);
 		return(1);
 	}
 
 	err = 1;
 	spin_lock(&ubd_lock);
 
-	if(ubd_dev[n].file != NULL){
+	dev = &ubd_dev[n];
+	if(dev->file != NULL){
 		printk(KERN_ERR "ubd_setup : device already configured\n");
 		goto out2;
 	}
@@ -276,6 +322,11 @@ static int ubd_setup_common(char *str, i
 		flags.s = 1;
 		str++;
 	}
+	if (*str == 'd'){
+		dev->no_cow = 1;
+		str++;
+	}
+
 	if(*str++ != '='){
 		printk(KERN_ERR "ubd_setup : Expected '='\n");
 		goto out2;
@@ -284,14 +335,17 @@ static int ubd_setup_common(char *str, i
 	err = 0;
 	backing_file = strchr(str, ',');
 	if(backing_file){
-		*backing_file = '\0';
-		backing_file++;
+		if(dev->no_cow)
+			printk(KERN_ERR "Can't specify both 'd' and a "
+			       "cow file\n");
+		else {
+			*backing_file = '\0';
+			backing_file++;
+		}
 	}
-	ubd_dev[n].file = str;
-	if(ubd_is_dir(ubd_dev[n].file))
-		ubd_dev[n].is_dir = 1;
-	ubd_dev[n].cow.file = backing_file;
-	ubd_dev[n].boot_openflags = flags;
+	dev->file = str;
+	dev->cow.file = backing_file;
+	dev->boot_openflags = flags;
  out2:
 	spin_unlock(&ubd_lock);
 	return(err);
@@ -321,8 +375,7 @@ __uml_help(ubd_setup,
 static int fakehd_set = 0;
 static int fakehd(char *str)
 {
-	printk(KERN_INFO 
-	       "fakehd : Changing ubd name to \"hd\".\n");
+	printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
 	fakehd_set = 1;
 	return 1;
 }
@@ -368,32 +421,42 @@ static void ubd_handler(void)
 {
 	struct io_thread_req req;
 	struct request *rq = elv_next_request(ubd_queue);
-	int n;
+	int n, err;
 
 	do_ubd = NULL;
 	intr_count++;
 	n = read_ubd_fs(thread_fd, &req, sizeof(req));
 	if(n != sizeof(req)){
 		printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
-		       "errno = %d\n", os_getpid(), -n);
+		       "err = %d\n", os_getpid(), -n);
 		spin_lock(&ubd_io_lock);
 		end_request(rq, 0);
 		spin_unlock(&ubd_io_lock);
 		return;
 	}
         
-        if((req.offset != ((__u64) (rq->sector)) << 9) ||
-	   (req.length != (rq->current_nr_sectors) << 9))
+	if((req.op != UBD_MMAP) &&
+	   ((req.offset != ((__u64) (rq->sector)) << 9) ||
+	    (req.length != (rq->current_nr_sectors) << 9)))
 		panic("I/O op mismatch");
 	
+	if(req.map_fd != -1){
+		err = physmem_subst_mapping(req.buffer, req.map_fd,
+					    req.map_offset, 1);
+		if(err)
+			printk("ubd_handler - physmem_subst_mapping failed, "
+			       "err = %d\n", -err);
+	}
+
 	ubd_finish(rq, req.error);
 	reactivate_fd(thread_fd, UBD_IRQ);	
 	do_ubd_request(ubd_queue);
 }
 
-static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
+static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
 {
 	ubd_handler();
+	return(IRQ_HANDLED);
 }
 
 /* Only changed by ubd_init, which is an initcall. */
@@ -417,10 +480,14 @@ static int ubd_file_size(struct ubd *dev
 
 static void ubd_close(struct ubd *dev)
 {
+	if(ubd_do_mmap)
+		physmem_forget_descriptor(dev->fd);
 	os_close_file(dev->fd);
 	if(dev->cow.file == NULL)
 		return;
 
+	if(ubd_do_mmap)
+		physmem_forget_descriptor(dev->cow.fd);
 	os_close_file(dev->cow.fd);
 	vfree(dev->cow.bitmap);
 	dev->cow.bitmap = NULL;
@@ -429,18 +496,20 @@ static void ubd_close(struct ubd *dev)
 static int ubd_open_dev(struct ubd *dev)
 {
 	struct openflags flags;
-	int err, n, create_cow, *create_ptr;
+	char **back_ptr;
+	int err, create_cow, *create_ptr;
 
+	dev->openflags = dev->boot_openflags;
 	create_cow = 0;
 	create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
-	dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
+	back_ptr = dev->no_cow ? NULL : &dev->cow.file;
+	dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
 				&dev->cow.bitmap_offset, &dev->cow.bitmap_len, 
 				&dev->cow.data_offset, create_ptr);
 
 	if((dev->fd == -ENOENT) && create_cow){
-		n = dev - ubd_dev;
 		dev->fd = create_cow_file(dev->file, dev->cow.file, 
-					  dev->openflags, 1 << 9,
+					  dev->openflags, 1 << 9, PAGE_SIZE,
 					  &dev->cow.bitmap_offset, 
 					  &dev->cow.bitmap_len,
 					  &dev->cow.data_offset);
@@ -455,13 +524,17 @@ static int ubd_open_dev(struct ubd *dev)
 	if(dev->cow.file != NULL){
 		err = -ENOMEM;
 		dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
-		if(dev->cow.bitmap == NULL) goto error;
+		if(dev->cow.bitmap == NULL){
+			printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
+			goto error;
+		}
 		flush_tlb_kernel_vm();
 
 		err = read_cow_bitmap(dev->fd, dev->cow.bitmap, 
 				      dev->cow.bitmap_offset, 
 				      dev->cow.bitmap_len);
-		if(err) goto error;
+		if(err < 0)
+			goto error;
 
 		flags = dev->openflags;
 		flags.w = 0;
@@ -481,17 +554,31 @@ static int ubd_new_disk(int major, u64 s
 			
 {
 	struct gendisk *disk;
+	char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")];
+	int err;
 
 	disk = alloc_disk(1 << UBD_SHIFT);
-	if (!disk)
-		return -ENOMEM;
+	if(disk == NULL)
+		return(-ENOMEM);
 
 	disk->major = major;
 	disk->first_minor = unit << UBD_SHIFT;
 	disk->fops = &ubd_blops;
 	set_capacity(disk, size / 512);
-	sprintf(disk->disk_name, "ubd");
-	sprintf(disk->devfs_name, "ubd/disc%d", unit);
+	if(major == MAJOR_NR){
+		sprintf(disk->disk_name, "ubd%c", 'a' + unit);
+		sprintf(disk->devfs_name, "ubd/disc%d", unit);
+		sprintf(from, "ubd/%d", unit);
+		sprintf(to, "disc%d/disc", unit);
+		err = devfs_mk_symlink(from, to);
+		if(err)
+			printk("ubd_new_disk failed to make link from %s to "
+			       "%s, error = %d\n", from, to, err);
+	}
+	else {
+		sprintf(disk->disk_name, "ubd_fake%d", unit);
+		sprintf(disk->devfs_name, "ubd_fake/disc%d", unit);
+	}
 
 	disk->private_data = &ubd_dev[unit];
 	disk->queue = ubd_queue;
@@ -506,24 +593,21 @@ static int ubd_add(int n)
 	struct ubd *dev = &ubd_dev[n];
 	int err;
 
-	if(dev->is_dir)
-		return(-EISDIR);
-
-	if (!dev->file)
+	if(dev->file == NULL)
 		return(-ENODEV);
 
 	if (ubd_open_dev(dev))
 		return(-ENODEV);
 
 	err = ubd_file_size(dev, &dev->size);
-	if(err)
+	if(err < 0)
 		return(err);
 
 	err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
 	if(err) 
 		return(err);
  
-	if(fake_major)
+	if(fake_major != MAJOR_NR)
 		ubd_new_disk(fake_major, dev->size, n, 
 			     &fake_gendisk[n]);
 
@@ -561,42 +645,42 @@ static int ubd_config(char *str)
 	return(err);
 }
 
-static int ubd_get_config(char *dev, char *str, int size, char **error_out)
+static int ubd_get_config(char *name, char *str, int size, char **error_out)
 {
-	struct ubd *ubd;
+	struct ubd *dev;
 	char *end;
-	int major, n = 0;
+	int n, len = 0;
 
-	major = simple_strtoul(dev, &end, 0);
-	if((*end != '\0') || (end == dev)){
-		*error_out = "ubd_get_config : didn't parse major number";
+	n = simple_strtoul(name, &end, 0);
+	if((*end != '\0') || (end == name)){
+		*error_out = "ubd_get_config : didn't parse device number";
 		return(-1);
 	}
 
-	if((major >= MAX_DEV) || (major < 0)){
-		*error_out = "ubd_get_config : major number out of range";
+	if((n >= MAX_DEV) || (n < 0)){
+		*error_out = "ubd_get_config : device number out of range";
 		return(-1);
 	}
 
-	ubd = &ubd_dev[major];
+	dev = &ubd_dev[n];
 	spin_lock(&ubd_lock);
 
-	if(ubd->file == NULL){
-		CONFIG_CHUNK(str, size, n, "", 1);
+	if(dev->file == NULL){
+		CONFIG_CHUNK(str, size, len, "", 1);
 		goto out;
 	}
 
-	CONFIG_CHUNK(str, size, n, ubd->file, 0);
+	CONFIG_CHUNK(str, size, len, dev->file, 0);
 
-	if(ubd->cow.file != NULL){
-		CONFIG_CHUNK(str, size, n, ",", 0);
-		CONFIG_CHUNK(str, size, n, ubd->cow.file, 1);
+	if(dev->cow.file != NULL){
+		CONFIG_CHUNK(str, size, len, ",", 0);
+		CONFIG_CHUNK(str, size, len, dev->cow.file, 1);
 	}
-	else CONFIG_CHUNK(str, size, n, "", 1);
+	else CONFIG_CHUNK(str, size, len, "", 1);
 
  out:
 	spin_unlock(&ubd_lock);
-	return(n);
+	return(len);
 }
 
 static int ubd_remove(char *str)
@@ -604,11 +688,9 @@ static int ubd_remove(char *str)
 	struct ubd *dev;
 	int n, err = -ENODEV;
 
-	if(!isdigit(*str))
-		return(err);	/* it should be a number 0-7/a-h */
+	n = parse_unit(&str);
 
-	n = *str - '0';
-	if(n >= MAX_DEV) 
+	if((n < 0) || (n >= MAX_DEV))
 		return(err);
 
 	dev = &ubd_dev[n];
@@ -669,7 +751,7 @@ int ubd_init(void)
 		
 	elevator_init(ubd_queue, &elevator_noop);
 
-	if (fake_major != 0) {
+	if (fake_major != MAJOR_NR) {
 		char name[sizeof("ubd_nnn\0")];
 
 		snprintf(name, sizeof(name), "ubd_%d", fake_major);
@@ -696,6 +778,7 @@ int ubd_driver_init(void){
 	io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), 
 				 &thread_fd);
 	if(io_pid < 0){
+		io_pid = -1;
 		printk(KERN_ERR 
 		       "ubd : Failed to start I/O thread (errno = %d) - "
 		       "falling back to synchronous I/O\n", -io_pid);
@@ -703,8 +786,8 @@ int ubd_driver_init(void){
 	}
 	err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, 
 			     SA_INTERRUPT, "ubd", ubd_dev);
-	if(err != 0) printk(KERN_ERR 
-			    "um_request_irq failed - errno = %d\n", -err);
+	if(err != 0)
+		printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
 	return(err);
 }
 
@@ -714,15 +797,9 @@ static int ubd_open(struct inode *inode,
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ubd *dev = disk->private_data;
-	int err = -EISDIR;
+	int err = 0;
 
-	if(dev->is_dir == 1)
-		goto out;
-
-	err = 0;
 	if(dev->count == 0){
-		dev->openflags = dev->boot_openflags;
-
 		err = ubd_open_dev(dev);
 		if(err){
 			printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
@@ -749,62 +826,156 @@ static int ubd_release(struct inode * in
 	return(0);
 }
 
-void cowify_req(struct io_thread_req *req, struct ubd *dev)
+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
+			  __u64 *cow_offset, unsigned long *bitmap,
+			  __u64 bitmap_offset, unsigned long *bitmap_words,
+			  __u64 bitmap_len)
+{
+	__u64 sector = io_offset >> 9;
+	int i, update_bitmap = 0;
+
+	for(i = 0; i < length >> 9; i++){
+		if(cow_mask != NULL)
+			ubd_set_bit(i, (unsigned char *) cow_mask);
+		if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
+			continue;
+
+		update_bitmap = 1;
+		ubd_set_bit(sector + i, (unsigned char *) bitmap);
+	}
+
+	if(!update_bitmap)
+		return;
+
+	*cow_offset = sector / (sizeof(unsigned long) * 8);
+
+	/* This takes care of the case where we're exactly at the end of the
+	 * device, and *cow_offset + 1 is off the end.  So, just back it up
+	 * by one word.  Thanks to Lynn Kerby for the fix and James McMechan
+	 * for the original diagnosis.
+	 */
+	if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
+			   sizeof(unsigned long) - 1))
+		(*cow_offset)--;
+
+	bitmap_words[0] = bitmap[*cow_offset];
+	bitmap_words[1] = bitmap[*cow_offset + 1];
+
+	*cow_offset *= sizeof(unsigned long);
+	*cow_offset += bitmap_offset;
+}
+
+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
+		       __u64 bitmap_offset, __u64 bitmap_len)
 {
-        int i, update_bitmap, sector = req->offset >> 9;
+	__u64 sector = req->offset >> 9;
+	int i;
 
 	if(req->length > (sizeof(req->sector_mask) * 8) << 9)
 		panic("Operation too long");
+
 	if(req->op == UBD_READ) {
 		for(i = 0; i < req->length >> 9; i++){
-			if(ubd_test_bit(sector + i, (unsigned char *) 
-					dev->cow.bitmap)){
+			if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
 				ubd_set_bit(i, (unsigned char *) 
 					    &req->sector_mask);
-			}
                 }
-        } 
-        else {
-		update_bitmap = 0;
-		for(i = 0; i < req->length >> 9; i++){
-			ubd_set_bit(i, (unsigned char *) 
-				    &req->sector_mask);
-			if(!ubd_test_bit(sector + i, (unsigned char *) 
-					 dev->cow.bitmap))
-				update_bitmap = 1;
-			ubd_set_bit(sector + i, (unsigned char *) 
-				    dev->cow.bitmap);
-		}
-		if(update_bitmap){
-			req->cow_offset = sector / (sizeof(unsigned long) * 8);
-			req->bitmap_words[0] = 
-				dev->cow.bitmap[req->cow_offset];
-			req->bitmap_words[1] = 
-				dev->cow.bitmap[req->cow_offset + 1];
-			req->cow_offset *= sizeof(unsigned long);
-			req->cow_offset += dev->cow.bitmap_offset;
+	}
+	else cowify_bitmap(req->offset, req->length, &req->sector_mask,
+			   &req->cow_offset, bitmap, bitmap_offset,
+			   req->bitmap_words, bitmap_len);
+}
+
+static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
+{
+	__u64 sector;
+	unsigned char *bitmap;
+	int bit, i;
+
+	/* mmap must have been requested on the command line */
+	if(!ubd_do_mmap)
+		return(-1);
+
+	/* The buffer must be page aligned */
+	if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
+		return(-1);
+
+	/* The request must be a page long */
+	if((req->current_nr_sectors << 9) != PAGE_SIZE)
+		return(-1);
+
+	if(dev->cow.file == NULL)
+		return(dev->fd);
+
+	sector = offset >> 9;
+	bitmap = (unsigned char *) dev->cow.bitmap;
+	bit = ubd_test_bit(sector, bitmap);
+
+	for(i = 1; i < req->current_nr_sectors; i++){
+		if(ubd_test_bit(sector + i, bitmap) != bit)
+			return(-1);
+	}
+
+	if(bit || (rq_data_dir(req) == WRITE))
+		offset += dev->cow.data_offset;
+
+	/* The data on disk must be page aligned */
+	if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
+		return(-1);
+
+	return(bit ? dev->fd : dev->cow.fd);
+}
+
+static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
+				struct request *req,
+				struct io_thread_req *io_req)
+{
+	int err;
+
+	if(rq_data_dir(req) == WRITE){
+		/* Writes are almost no-ops since the new data is already in the
+		 * host page cache
+		 */
+		dev->map_writes++;
+		if(dev->cow.file != NULL)
+			cowify_bitmap(io_req->offset, io_req->length,
+				      &io_req->sector_mask, &io_req->cow_offset,
+				      dev->cow.bitmap, dev->cow.bitmap_offset,
+				      io_req->bitmap_words,
+				      dev->cow.bitmap_len);
+	}
+	else {
+		int w;
+
+		if((dev->cow.file != NULL) && (fd == dev->cow.fd))
+			w = 0;
+		else w = dev->openflags.w;
+
+		if((dev->cow.file != NULL) && (fd == dev->fd))
+			offset += dev->cow.data_offset;
+
+		err = physmem_subst_mapping(req->buffer, fd, offset, w);
+		if(err){
+			printk("physmem_subst_mapping failed, err = %d\n",
+			       -err);
+			return(1);
 		}
+		dev->map_reads++;
 	}
+	io_req->op = UBD_MMAP;
+	io_req->buffer = req->buffer;
+	return(0);
 }
 
 static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
 	struct gendisk *disk = req->rq_disk;
 	struct ubd *dev = disk->private_data;
-	__u64 block;
-	int nsect;
+	__u64 offset;
+	int len, fd;
 
 	if(req->rq_status == RQ_INACTIVE) return(1);
 
-	if(dev->is_dir){
-		strcpy(req->buffer, "HOSTFS:");
-		strcat(req->buffer, dev->file);
- 		spin_lock(&ubd_io_lock);
-		end_request(req, 1);
- 		spin_unlock(&ubd_io_lock);
-		return(1);
-	}
-
 	if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
 		printk("Write attempted on readonly ubd device %s\n", 
 		       disk->disk_name);
@@ -814,23 +985,49 @@ static int prepare_request(struct reques
 		return(1);
 	}
 
-        block = req->sector;
-        nsect = req->current_nr_sectors;
+	offset = ((__u64) req->sector) << 9;
+	len = req->current_nr_sectors << 9;
 
-	io_req->op = rq_data_dir(req) == READ ? UBD_READ : UBD_WRITE;
 	io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
 	io_req->fds[1] = dev->fd;
+	io_req->map_fd = -1;
+	io_req->cow_offset = -1;
+	io_req->offset = offset;
+	io_req->length = len;
+	io_req->error = 0;
+	io_req->sector_mask = 0;
+
+	fd = mmap_fd(req, dev, io_req->offset);
+	if(fd > 0){
+		/* If mmapping is otherwise OK, but the first access to the
+		 * page is a write, then it's not mapped in yet.  So we have
+		 * to write the data to disk first, then we can map the disk
+		 * page in and continue normally from there.
+		 */
+		if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
+			io_req->map_fd = dev->fd;
+			io_req->map_offset = io_req->offset +
+				dev->cow.data_offset;
+			dev->write_maps++;
+		}
+		else return(prepare_mmap_request(dev, fd, io_req->offset, req,
+						 io_req));
+	}
+
+	if(rq_data_dir(req) == READ)
+		dev->nomap_reads++;
+	else dev->nomap_writes++;
+
+	io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
 	io_req->offsets[0] = 0;
 	io_req->offsets[1] = dev->cow.data_offset;
-	io_req->offset = ((__u64) block) << 9;
-	io_req->length = nsect << 9;
 	io_req->buffer = req->buffer;
 	io_req->sectorsize = 1 << 9;
-	io_req->sector_mask = 0;
-	io_req->cow_offset = -1;
-	io_req->error = 0;
 
-        if(dev->cow.file != NULL) cowify_req(io_req, dev);
+	if(dev->cow.file != NULL)
+		cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
+			   dev->cow.bitmap_len);
+
 	return(0);
 }
 
@@ -841,7 +1038,7 @@ static void do_ubd_request(request_queue
 	int err, n;
 
 	if(thread_fd == -1){
-		while(!list_empty(&q->queue_head)){
+		while(!elv_queue_empty(q)){
 			req = elv_next_request(q);
 			err = prepare_request(req, &io_req);
 			if(!err){
@@ -851,7 +1048,8 @@ static void do_ubd_request(request_queue
 		}
 	}
 	else {
-		if(do_ubd || list_empty(&q->queue_head)) return;
+		if(do_ubd || elv_queue_empty(q))
+			return;
 		req = elv_next_request(q);
 		err = prepare_request(req, &io_req);
 		if(!err){
@@ -885,7 +1083,7 @@ static int ubd_ioctl(struct inode * inod
 		g.heads = 128;
 		g.sectors = 32;
 		g.cylinders = dev->size / (128 * 32 * 512);
-		g.start = 2;
+		g.start = get_start_sect(inode->i_bdev);
 		return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
 
 	case HDIO_SET_UNMASKINTR:
@@ -935,6 +1133,142 @@ static int ubd_ioctl(struct inode * inod
 	return(-EINVAL);
 }
 
+static int ubd_check_remapped(int fd, unsigned long address, int is_write,
+			      __u64 offset)
+{
+	__u64 bitmap_offset;
+	unsigned long new_bitmap[2];
+	int i, err, n;
+
+	/* If it's not a write access, we can't do anything about it */
+	if(!is_write)
+		return(0);
+
+	/* We have a write */
+	for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
+		struct ubd *dev = &ubd_dev[i];
+
+		if((dev->fd != fd) && (dev->cow.fd != fd))
+			continue;
+
+		/* It's a write to a ubd device */
+
+		if(!dev->openflags.w){
+			/* It's a write access on a read-only device - probably
+			 * shouldn't happen.  If the kernel is trying to change
+			 * something with no intention of writing it back out,
+			 * then this message will clue us in that this needs
+			 * fixing
+			 */
+			printk("Write access to mapped page from readonly ubd "
+			       "device %d\n", i);
+			return(0);
+		}
+
+		/* It's a write to a writeable ubd device - it must be COWed
+		 * because, otherwise, the page would have been mapped in
+		 * writeable
+		 */
+
+		if(!dev->cow.file)
+			panic("Write fault on writeable non-COW ubd device %d",
+			      i);
+
+		/* It should also be an access to the backing file since the
+		 * COW pages should be mapped in read-write
+		 */
+
+		if(fd == dev->fd)
+			panic("Write fault on a backing page of ubd "
+			      "device %d\n", i);
+
+		/* So, we do the write, copying the backing data to the COW
+		 * file...
+		 */
+
+		err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
+		if(err < 0)
+			panic("Couldn't seek to %lld in COW file of ubd "
+			      "device %d, err = %d",
+			      offset + dev->cow.data_offset, i, -err);
+
+		n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
+		if(n != PAGE_SIZE)
+			panic("Couldn't copy data to COW file of ubd "
+			      "device %d, err = %d", i, -n);
+
+		/* ... updating the COW bitmap... */
+
+		cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
+			      dev->cow.bitmap, dev->cow.bitmap_offset,
+			      new_bitmap, dev->cow.bitmap_len);
+
+		err = os_seek_file(dev->fd, bitmap_offset);
+		if(err < 0)
+			panic("Couldn't seek to %lld in COW file of ubd "
+			      "device %d, err = %d", bitmap_offset, i, -err);
+
+		n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
+		if(n != sizeof(new_bitmap))
+			panic("Couldn't update bitmap  of ubd device %d, "
+			      "err = %d", i, -n);
+
+		/* Maybe we can map the COW page in, and maybe we can't.  If
+		 * it is a pre-V3 COW file, we can't, since the alignment will
+		 * be wrong.  If it is a V3 or later COW file which has been
+		 * moved to a system with a larger page size, then maybe we
+		 * can't, depending on the exact location of the page.
+		 */
+
+		offset += dev->cow.data_offset;
+
+		/* Remove the remapping, putting the original anonymous page
+		 * back.  If the COW file can be mapped in, that is done.
+		 * Otherwise, the COW page is read in.
+		 */
+
+		if(!physmem_remove_mapping((void *) address))
+			panic("Address 0x%lx not remapped by ubd device %d",
+			      address, i);
+		if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
+			physmem_subst_mapping((void *) address, dev->fd,
+					      offset, 1);
+		else {
+			err = os_seek_file(dev->fd, offset);
+			if(err < 0)
+				panic("Couldn't seek to %lld in COW file of "
+				      "ubd device %d, err = %d", offset, i,
+				      -err);
+
+			n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
+			if(n != PAGE_SIZE)
+				panic("Failed to read page from offset %llx of "
+				      "COW file of ubd device %d, err = %d",
+				      offset, i, -n);
+		}
+
+		return(1);
+	}
+
+	/* It's not a write on a ubd device */
+	return(0);
+}
+
+static struct remapper ubd_remapper = {
+	.list	= LIST_HEAD_INIT(ubd_remapper.list),
+	.proc	= ubd_check_remapped,
+};
+
+static int ubd_remapper_setup(void)
+{
+	if(ubd_do_mmap)
+		register_remapper(&ubd_remapper);
+
+	return(0);
+}
+
+__initcall(ubd_remapper_setup);
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN arch/um/drivers/ubd_user.c~uml-base-patch arch/um/drivers/ubd_user.c
--- 25/arch/um/drivers/ubd_user.c~uml-base-patch	2004-08-15 20:45:08.341386848 -0700
+++ 25-akpm/arch/um/drivers/ubd_user.c	2004-08-15 20:46:03.226043112 -0700
@@ -11,11 +11,8 @@
 #include <signal.h>
 #include <string.h>
 #include <netinet/in.h>
-#include <sys/stat.h>
 #include <sys/time.h>
-#include <sys/fcntl.h>
 #include <sys/socket.h>
-#include <string.h>
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "asm/types.h"
@@ -24,146 +21,30 @@
 #include "user.h"
 #include "ubd_user.h"
 #include "os.h"
+#include "cow.h"
 
 #include <endian.h>
 #include <byteswap.h>
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define ntohll(x) (x)
-# define htonll(x) (x)
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-# define ntohll(x)  bswap_64(x)
-# define htonll(x)  bswap_64(x)
-#else
-#error "__BYTE_ORDER not defined"
-#endif
-
-#define PATH_LEN_V1 256
-
-struct cow_header_v1 {
-	int magic;
-	int version;
-	char backing_file[PATH_LEN_V1];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
-
-#define PATH_LEN_V2 MAXPATHLEN
-
-struct cow_header_v2 {
-	unsigned long magic;
-	unsigned long version;
-	char backing_file[PATH_LEN_V2];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
-
-union cow_header {
-	struct cow_header_v1 v1;
-	struct cow_header_v2 v2;
-};
-
-#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
-#define COW_VERSION 2
-
-static void sizes(__u64 size, int sectorsize, int bitmap_offset, 
-		  unsigned long *bitmap_len_out, int *data_offset_out)
-{
-	*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
-
-	*data_offset_out = bitmap_offset + *bitmap_len_out;
-	*data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
-	*data_offset_out *= sectorsize;
-}
-
-static int read_cow_header(int fd, int *magic_out, char **backing_file_out, 
-			   time_t *mtime_out, __u64 *size_out, 
-			   int *sectorsize_out, int *bitmap_offset_out)
-{
-	union cow_header *header;
-	char *file;
-	int err, n;
-	unsigned long version, magic;
-
-	header = um_kmalloc(sizeof(*header));
-	if(header == NULL){
-		printk("read_cow_header - Failed to allocate header\n");
-		return(-ENOMEM);
-	}
-	err = -EINVAL;
-	n = read(fd, header, sizeof(*header));
-	if(n < offsetof(typeof(header->v1), backing_file)){
-		printk("read_cow_header - short header\n");
-		goto out;
-	}
-
-	magic = header->v1.magic;
-	if(magic == COW_MAGIC) {
-		version = header->v1.version;
-	}
-	else if(magic == ntohl(COW_MAGIC)){
-		version = ntohl(header->v1.version);
-	}
-	else goto out;
-
-	*magic_out = COW_MAGIC;
-
-	if(version == 1){
-		if(n < sizeof(header->v1)){
-			printk("read_cow_header - failed to read V1 header\n");
-			goto out;
-		}
-		*mtime_out = header->v1.mtime;
-		*size_out = header->v1.size;
-		*sectorsize_out = header->v1.sectorsize;
-		*bitmap_offset_out = sizeof(header->v1);
-		file = header->v1.backing_file;
-	}
-	else if(version == 2){
-		if(n < sizeof(header->v2)){
-			printk("read_cow_header - failed to read V2 header\n");
-			goto out;
-		}
-		*mtime_out = ntohl(header->v2.mtime);
-		*size_out = ntohll(header->v2.size);
-		*sectorsize_out = ntohl(header->v2.sectorsize);
-		*bitmap_offset_out = sizeof(header->v2);
-		file = header->v2.backing_file;
-	}
-	else {
-		printk("read_cow_header - invalid COW version\n");
-		goto out;
-	}
-	err = -ENOMEM;
-	*backing_file_out = uml_strdup(file);
-	if(*backing_file_out == NULL){
-		printk("read_cow_header - failed to allocate backing file\n");
-		goto out;
-	}
-	err = 0;
- out:
-	kfree(header);
-	return(err);
-}
 
 static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
 {
-	struct stat buf1, buf2;
+	struct uml_stat buf1, buf2;
+	int err;
 
 	if(from_cmdline == NULL) return(1);
 	if(!strcmp(from_cmdline, from_cow)) return(1);
 
-	if(stat(from_cmdline, &buf1) < 0){
-		printk("Couldn't stat '%s', errno = %d\n", from_cmdline, 
-		       errno);
+	err = os_stat_file(from_cmdline, &buf1);
+	if(err < 0){
+		printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
 		return(1);
 	}
-	if(stat(from_cow, &buf2) < 0){
-		printk("Couldn't stat '%s', errno = %d\n", from_cow, errno);
+	err = os_stat_file(from_cow, &buf2);
+	if(err < 0){
+		printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
 		return(1);
 	}
-	if((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino))
+	if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
 		return(1);
 
 	printk("Backing file mismatch - \"%s\" requested,\n"
@@ -174,20 +55,21 @@ static int same_backing_files(char *from
 
 static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
 {
-	struct stat64 buf;
+	unsigned long modtime;
 	long long actual;
 	int err;
 
-  	if(stat64(file, &buf) < 0){
-		printk("Failed to stat backing file \"%s\", errno = %d\n",
-		       file, errno);
-		return(-errno);
+	err = os_file_modtime(file, &modtime);
+	if(err < 0){
+		printk("Failed to get modification time of backing file "
+		       "\"%s\", err = %d\n", file, -err);
+		return(err);
 	}
 
 	err = os_file_size(file, &actual);
-	if(err){
+	if(err < 0){
 		printk("Failed to get size of backing file \"%s\", "
-		       "errno = %d\n", file, -err);
+		       "err = %d\n", file, -err);
 		return(err);
 	}
 
@@ -196,9 +78,9 @@ static int backing_file_mismatch(char *f
 		       "file\n", size, actual);
 		return(-EINVAL);
 	}
-	if(buf.st_mtime != mtime){
+	if(modtime != mtime){
 		printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
-		       "file\n", mtime, buf.st_mtime);
+		       "file\n", mtime, modtime);
 		return(-EINVAL);
 	}
 	return(0);
@@ -209,124 +91,16 @@ int read_cow_bitmap(int fd, void *buf, i
 	int err;
 
 	err = os_seek_file(fd, offset);
-	if(err != 0) return(-errno);
-	err = read(fd, buf, len);
-	if(err < 0) return(-errno);
-	return(0);
-}
+	if(err < 0)
+		return(err);
 
-static int absolutize(char *to, int size, char *from)
-{
-	char save_cwd[256], *slash;
-	int remaining;
+	err = os_read_file(fd, buf, len);
+	if(err < 0)
+		return(err);
 
-	if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
-		printk("absolutize : unable to get cwd - errno = %d\n", errno);
-		return(-1);
-	}
-	slash = strrchr(from, '/');
-	if(slash != NULL){
-		*slash = '\0';
-		if(chdir(from)){
-			*slash = '/';
-			printk("absolutize : Can't cd to '%s' - errno = %d\n",
-			       from, errno);
-			return(-1);
-		}
-		*slash = '/';
-		if(getcwd(to, size) == NULL){
-			printk("absolutize : unable to get cwd of '%s' - "
-			       "errno = %d\n", from, errno);
-			return(-1);
-		}
-		remaining = size - strlen(to);
-		if(strlen(slash) + 1 > remaining){
-			printk("absolutize : unable to fit '%s' into %d "
-			       "chars\n", from, size);
-			return(-1);
-		}
-		strcat(to, slash);
-	}
-	else {
-		if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
-			printk("absolutize : unable to fit '%s' into %d "
-			       "chars\n", from, size);
-			return(-1);
-		}
-		strcpy(to, save_cwd);
-		strcat(to, "/");
-		strcat(to, from);
-	}
-	chdir(save_cwd);
 	return(0);
 }
 
-static int write_cow_header(char *cow_file, int fd, char *backing_file, 
-			    int sectorsize, long long *size)
-{
-        struct cow_header_v2 *header;
-	struct stat64 buf;
-	int err;
-
-	err = os_seek_file(fd, 0);
-	if(err != 0){
-		printk("write_cow_header - lseek failed, errno = %d\n", errno);
-		return(-errno);
-	}
-
-	err = -ENOMEM;
-	header = um_kmalloc(sizeof(*header));
-	if(header == NULL){
-		printk("Failed to allocate COW V2 header\n");
-		goto out;
-	}
-	header->magic = htonl(COW_MAGIC);
-	header->version = htonl(COW_VERSION);
-
-	err = -EINVAL;
-	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
-		printk("Backing file name \"%s\" is too long - names are "
-		       "limited to %d characters\n", backing_file, 
-		       sizeof(header->backing_file) - 1);
-		goto out_free;
-	}
-
-	if(absolutize(header->backing_file, sizeof(header->backing_file), 
-		      backing_file))
-		goto out_free;
-
-	err = stat64(header->backing_file, &buf);
-	if(err < 0){
-		printk("Stat of backing file '%s' failed, errno = %d\n",
-		       header->backing_file, errno);
-		err = -errno;
-		goto out_free;
-	}
-
-	err = os_file_size(header->backing_file, size);
-	if(err){
-		printk("Couldn't get size of backing file '%s', errno = %d\n",
-		       header->backing_file, -*size);
-		goto out_free;
-	}
-
-	header->mtime = htonl(buf.st_mtime);
-	header->size = htonll(*size);
-	header->sectorsize = htonl(sectorsize);
-
-	err = write(fd, header, sizeof(*header));
-	if(err != sizeof(*header)){
-		printk("Write of header to new COW file '%s' failed, "
-		       "errno = %d\n", cow_file, errno);
-		goto out_free;
-	}
-	err = 0;
- out_free:
-	kfree(header);
- out:
-	return(err);
-}
-
 int open_ubd_file(char *file, struct openflags *openflags, 
 		  char **backing_file_out, int *bitmap_offset_out, 
 		  unsigned long *bitmap_len_out, int *data_offset_out, 
@@ -334,26 +108,36 @@ int open_ubd_file(char *file, struct ope
 {
 	time_t mtime;
 	__u64 size;
+	__u32 version, align;
 	char *backing_file;
-        int fd, err, sectorsize, magic, same, mode = 0644;
+	int fd, err, sectorsize, same, mode = 0644;
 
-        if((fd = os_open_file(file, *openflags, mode)) < 0){
+	fd = os_open_file(file, *openflags, mode);
+	if(fd < 0){
 		if((fd == -ENOENT) && (create_cow_out != NULL))
 			*create_cow_out = 1;
                 if(!openflags->w ||
                    ((errno != EROFS) && (errno != EACCES))) return(-errno);
 		openflags->w = 0;
-                if((fd = os_open_file(file, *openflags, mode)) < 0) 
+		fd = os_open_file(file, *openflags, mode);
+		if(fd < 0)
 			return(fd);
         }
+
+	err = os_lock_file(fd, openflags->w);
+	if(err < 0){
+		printk("Failed to lock '%s', err = %d\n", file, -err);
+		goto out_close;
+	}
+
 	if(backing_file_out == NULL) return(fd);
 
-	err = read_cow_header(fd, &magic, &backing_file, &mtime, &size, 
-			      &sectorsize, bitmap_offset_out);
+	err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
+			      &size, &sectorsize, &align, bitmap_offset_out);
 	if(err && (*backing_file_out != NULL)){
 		printk("Failed to read COW header from COW file \"%s\", "
-		       "errno = %d\n", file, err);
-		goto error;
+		       "errno = %d\n", file, -err);
+		goto out_close;
 	}
 	if(err) return(fd);
 
@@ -363,36 +147,33 @@ int open_ubd_file(char *file, struct ope
 
 	if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
 		printk("Switching backing file to '%s'\n", *backing_file_out);
-		err = write_cow_header(file, fd, *backing_file_out, 
-				       sectorsize, &size);
+		err = write_cow_header(file, fd, *backing_file_out,
+				       sectorsize, align, &size);
 		if(err){
-			printk("Switch failed, errno = %d\n", err);
+			printk("Switch failed, errno = %d\n", -err);
 			return(err);
 		}
 	}
 	else {
 		*backing_file_out = backing_file;
 		err = backing_file_mismatch(*backing_file_out, size, mtime);
-		if(err) goto error;
+		if(err) goto out_close;
 	}
 
-	sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, 
-	      data_offset_out);
+	cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
+		  bitmap_len_out, data_offset_out);
 
         return(fd);
- error:
-	close(fd);
+ out_close:
+	os_close_file(fd);
 	return(err);
 }
 
 int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
-		    int sectorsize, int *bitmap_offset_out, 
+		    int sectorsize, int alignment, int *bitmap_offset_out,
 		    unsigned long *bitmap_len_out, int *data_offset_out)
 {
-	__u64 blocks;
-	long zero;
-	int err, fd, i;
-	long long size;
+	int err, fd;
 
 	flags.c = 1;
 	fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
@@ -403,57 +184,49 @@ int create_cow_file(char *cow_file, char
 		goto out;
 	}
 
-	err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
-	if(err) goto out_close;
-
-	blocks = (size + sectorsize - 1) / sectorsize;
-	blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8);
-	zero = 0;
-	for(i = 0; i < blocks; i++){
-		err = write(fd, &zero, sizeof(zero));
-		if(err != sizeof(zero)){
-			printk("Write of bitmap to new COW file '%s' failed, "
-			       "errno = %d\n", cow_file, errno);
-			goto out_close;
-		}
-	}
-
-	sizes(size, sectorsize, sizeof(struct cow_header_v2), 
-	      bitmap_len_out, data_offset_out);
-	*bitmap_offset_out = sizeof(struct cow_header_v2);
-
-	return(fd);
-
- out_close:
-	close(fd);
+	err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
+			    bitmap_offset_out, bitmap_len_out,
+			    data_offset_out);
+	if(!err)
+		return(fd);
+	os_close_file(fd);
  out:
 	return(err);
 }
 
+/* XXX Just trivial wrappers around os_read_file and os_write_file */
 int read_ubd_fs(int fd, void *buffer, int len)
 {
-	int n;
-
-	n = read(fd, buffer, len);
-	if(n < 0) return(-errno);
-	else return(n);
+	return(os_read_file(fd, buffer, len));
 }
 
 int write_ubd_fs(int fd, char *buffer, int len)
 {
-	int n;
-
-	n = write(fd, buffer, len);
-	if(n < 0) return(-errno);
-	else return(n);
+	return(os_write_file(fd, buffer, len));
 }
 
-int ubd_is_dir(char *file)
+static int update_bitmap(struct io_thread_req *req)
 {
-	struct stat64 buf;
+	int n;
+
+	if(req->cow_offset == -1)
+		return(0);
+
+	n = os_seek_file(req->fds[1], req->cow_offset);
+	if(n < 0){
+		printk("do_io - bitmap lseek failed : err = %d\n", -n);
+		return(1);
+	}
+
+	n = os_write_file(req->fds[1], &req->bitmap_words,
+		          sizeof(req->bitmap_words));
+	if(n != sizeof(req->bitmap_words)){
+		printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
+		       req->fds[1]);
+		return(1);
+	}
 
-	if(stat64(file, &buf) < 0) return(0);
-	return(S_ISDIR(buf.st_mode));
+	return(0);
 }
 
 void do_io(struct io_thread_req *req)
@@ -461,8 +234,18 @@ void do_io(struct io_thread_req *req)
 	char *buf;
 	unsigned long len;
 	int n, nsectors, start, end, bit;
+	int err;
 	__u64 off;
 
+	if(req->op == UBD_MMAP){
+		/* Touch the page to force the host to do any necessary IO to
+		 * get it into memory
+		 */
+		n = *((volatile int *) req->buffer);
+		req->error = update_bitmap(req);
+		return;
+	}
+
 	nsectors = req->length / req->sectorsize;
 	start = 0;
 	do {
@@ -473,15 +256,14 @@ void do_io(struct io_thread_req *req)
 				    &req->sector_mask) == bit))
 			end++;
 
-		if(end != nsectors)
-			printk("end != nsectors\n");
 		off = req->offset + req->offsets[bit] + 
 			start * req->sectorsize;
 		len = (end - start) * req->sectorsize;
 		buf = &req->buffer[start * req->sectorsize];
 
-		if(os_seek_file(req->fds[bit], off) != 0){
-			printk("do_io - lseek failed : errno = %d\n", errno);
+		err = os_seek_file(req->fds[bit], off);
+		if(err < 0){
+			printk("do_io - lseek failed : err = %d\n", -err);
 			req->error = 1;
 			return;
 		}
@@ -490,11 +272,10 @@ void do_io(struct io_thread_req *req)
 			do {
 				buf = &buf[n];
 				len -= n;
-				n = read(req->fds[bit], buf, len);
+				n = os_read_file(req->fds[bit], buf, len);
 				if (n < 0) {
-					printk("do_io - read returned %d : "
-					       "errno = %d fd = %d\n", n,
-					       errno, req->fds[bit]);
+					printk("do_io - read failed, err = %d "
+					       "fd = %d\n", -n, req->fds[bit]);
 					req->error = 1;
 					return;
 				}
@@ -502,11 +283,10 @@ void do_io(struct io_thread_req *req)
 			if (n < len) memset(&buf[n], 0, len - n);
 		}
 		else {
-			n = write(req->fds[bit], buf, len);
+			n = os_write_file(req->fds[bit], buf, len);
 			if(n != len){
-				printk("do_io - write returned %d : "
-				       "errno = %d fd = %d\n", n, 
-				       errno, req->fds[bit]);
+				printk("do_io - write failed err = %d "
+				       "fd = %d\n", -n, req->fds[bit]);
 				req->error = 1;
 				return;
 			}
@@ -515,24 +295,7 @@ void do_io(struct io_thread_req *req)
 		start = end;
 	} while(start < nsectors);
 
-	if(req->cow_offset != -1){
-		if(os_seek_file(req->fds[1], req->cow_offset) != 0){
-			printk("do_io - bitmap lseek failed : errno = %d\n",
-			       errno);
-			req->error = 1;
-			return;
-		}
-		n = write(req->fds[1], &req->bitmap_words, 
-			  sizeof(req->bitmap_words));
-		if(n != sizeof(req->bitmap_words)){
-			printk("do_io - bitmap update returned %d : "
-			       "errno = %d fd = %d\n", n, errno, req->fds[1]);
-			req->error = 1;
-			return;
-		}
-	}
-	req->error = 0;
-	return;
+	req->error = update_bitmap(req);
 }
 
 /* Changed in start_io_thread, which is serialized by being called only
@@ -550,19 +313,23 @@ int io_thread(void *arg)
 
 	signal(SIGWINCH, SIG_IGN);
 	while(1){
-		n = read(kernel_fd, &req, sizeof(req));
-		if(n < 0) printk("io_thread - read returned %d, errno = %d\n",
-				 n, errno);
-		else if(n < sizeof(req)){
-			printk("io_thread - short read : length = %d\n", n);
+		n = os_read_file(kernel_fd, &req, sizeof(req));
+		if(n != sizeof(req)){
+			if(n < 0)
+				printk("io_thread - read failed, fd = %d, "
+				       "err = %d\n", kernel_fd, -n);
+			else {
+				printk("io_thread - short read, fd = %d, "
+				       "length = %d\n", kernel_fd, n);
+			}
 			continue;
 		}
 		io_count++;
 		do_io(&req);
-		n = write(kernel_fd, &req, sizeof(req));
+		n = os_write_file(kernel_fd, &req, sizeof(req));
 		if(n != sizeof(req))
-			printk("io_thread - write failed, errno = %d\n",
-			       errno);
+			printk("io_thread - write failed, fd = %d, err = %d\n",
+			       kernel_fd, -n);
 	}
 }
 
@@ -571,10 +338,11 @@ int start_io_thread(unsigned long sp, in
 	int pid, fds[2], err;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("start_io_thread - os_pipe failed, errno = %d\n", -err);
-		return(-1);
+	if(err < 0){
+		printk("start_io_thread - os_pipe failed, err = %d\n", -err);
+		goto out;
 	}
+
 	kernel_fd = fds[0];
 	*fd_out = fds[1];
 
@@ -582,32 +350,19 @@ int start_io_thread(unsigned long sp, in
 		    NULL);
 	if(pid < 0){
 		printk("start_io_thread - clone failed : errno = %d\n", errno);
-		return(-errno);
+		goto out_close;
 	}
-	return(pid);
-}
-
-#ifdef notdef
-int start_io_thread(unsigned long sp, int *fd_out)
-{
-	int pid;
 
-	if((kernel_fd = get_pty()) < 0) return(-1);
-	raw(kernel_fd, 0);
-	if((*fd_out = open(ptsname(kernel_fd), O_RDWR)) < 0){
-		printk("Couldn't open tty for IO\n");
-		return(-1);
-	}
-
-	pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
-		    NULL);
-	if(pid < 0){
-		printk("start_io_thread - clone failed : errno = %d\n", errno);
-		return(-errno);
-	}
 	return(pid);
+
+ out_close:
+	os_close_file(fds[0]);
+	os_close_file(fds[1]);
+	kernel_fd = -1;
+	*fd_out = -1;
+ out:
+	return(err);
 }
-#endif
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -puN arch/um/drivers/xterm.c~uml-base-patch arch/um/drivers/xterm.c
--- 25/arch/um/drivers/xterm.c~uml-base-patch	2004-08-15 20:45:08.343386544 -0700
+++ 25-akpm/arch/um/drivers/xterm.c	2004-08-15 20:46:03.227042960 -0700
@@ -8,7 +8,6 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <termios.h>
 #include <signal.h>
 #include <sched.h>
@@ -36,7 +35,8 @@ void *xterm_init(char *str, int device, 
 {
 	struct xterm_chan *data;
 
-	if((data = malloc(sizeof(*data))) == NULL) return(NULL);
+	data = malloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct xterm_chan) { .pid 		= -1, 
 				       .helper_pid 	= -1,
 				       .device 		= device, 
@@ -93,7 +93,7 @@ int xterm_open(int input, int output, in
 			 "/usr/lib/uml/port-helper", "-uml-socket",
 			 file, NULL };
 
-	if(access(argv[4], X_OK))
+	if(os_access(argv[4], OS_ACC_X_OK) < 0)
 		argv[4] = "port-helper";
 
 	fd = mkstemp(file);
@@ -106,13 +106,13 @@ int xterm_open(int input, int output, in
 		printk("xterm_open : unlink failed, errno = %d\n", errno);
 		return(-errno);
 	}
-	close(fd);
+	os_close_file(fd);
 
-	fd = create_unix_socket(file, sizeof(file));
+	fd = os_create_unix_socket(file, sizeof(file), 1);
 	if(fd < 0){
 		printk("xterm_open : create_unix_socket failed, errno = %d\n", 
 		       -fd);
-		return(-fd);
+		return(fd);
 	}
 
 	sprintf(title, data->title, data->device);
@@ -128,15 +128,16 @@ int xterm_open(int input, int output, in
 	if(data->direct_rcv)
 		new = os_rcv_fd(fd, &data->helper_pid);
 	else {
-		if((err = os_set_fd_block(fd, 0)) != 0){
+		err = os_set_fd_block(fd, 0);
+		if(err < 0){
 			printk("xterm_open : failed to set descriptor "
-			       "non-blocking, errno = %d\n", err);
+			       "non-blocking, err = %d\n", -err);
 			return(err);
 		}
 		new = xterm_fd(fd, &data->helper_pid);
 	}
 	if(new < 0){
-		printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new);
+		printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
 		goto out;
 	}
 
@@ -160,7 +161,7 @@ void xterm_close(int fd, void *d)
 	if(data->helper_pid != -1) 
 		os_kill_process(data->helper_pid, 0);
 	data->helper_pid = -1;
-	close(fd);
+	os_close_file(fd);
 }
 
 void xterm_free(void *d)
diff -puN arch/um/drivers/xterm_kern.c~uml-base-patch arch/um/drivers/xterm_kern.c
--- 25/arch/um/drivers/xterm_kern.c~uml-base-patch	2004-08-15 20:45:08.344386392 -0700
+++ 25-akpm/arch/um/drivers/xterm_kern.c	2004-08-15 20:46:03.228042808 -0700
@@ -5,9 +5,12 @@
 
 #include "linux/errno.h"
 #include "linux/slab.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
 #include "asm/semaphore.h"
 #include "asm/irq.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "kern_util.h"
 #include "os.h"
 #include "xterm.h"
@@ -19,17 +22,18 @@ struct xterm_wait {
 	int new_fd;
 };
 
-static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct xterm_wait *xterm = data;
 	int fd;
 
 	fd = os_rcv_fd(xterm->fd, &xterm->pid);
 	if(fd == -EAGAIN)
-		return;
+		return(IRQ_NONE);
 
 	xterm->new_fd = fd;
 	up(&xterm->sem);
+	return(IRQ_HANDLED);
 }
 
 int xterm_fd(int socket, int *pid_out)
@@ -54,7 +58,8 @@ int xterm_fd(int socket, int *pid_out)
 	if(err){
 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
 		       "err = %d\n",  err);
-		return(err);
+		ret = err;
+		goto out;
 	}
 	down(&data->sem);
 
@@ -62,6 +67,7 @@ int xterm_fd(int socket, int *pid_out)
 
 	ret = data->new_fd;
 	*pid_out = data->pid;
+ out:
 	kfree(data);
 
 	return(ret);
diff -puN arch/um/dyn.lds.S~uml-base-patch arch/um/dyn.lds.S
--- 25/arch/um/dyn.lds.S~uml-base-patch	2004-08-15 20:45:08.345386240 -0700
+++ 25-akpm/arch/um/dyn.lds.S	2004-08-15 20:46:03.228042808 -0700
@@ -1,3 +1,5 @@
+#include <asm-generic/vmlinux.lds.h>
+
 OUTPUT_FORMAT(ELF_FORMAT)
 OUTPUT_ARCH(ELF_ARCH)
 ENTRY(_start)
@@ -10,12 +12,15 @@ SECTIONS
 {
   . = START + SIZEOF_HEADERS;
   .interp         : { *(.interp) }
-  . = ALIGN(4096);
   __binary_start = .;
   . = ALIGN(4096);		/* Init code and data */
   _stext = .;
   __init_begin = .;
-  .text.init : { *(.text.init) }
+  .init.text : {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
 
   . = ALIGN(4096);
 
@@ -55,7 +60,9 @@ SECTIONS
   } =0x90909090
   .plt            : { *(.plt) }
   .text           : {
-    *(.text .stub .text.* .gnu.linkonce.t.*)
+    *(.text)
+    SCHED_TEXT
+    *(.stub .text.* .gnu.linkonce.t.*)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
   } =0x90909090
@@ -67,7 +74,7 @@ SECTIONS
 
   #include "asm/common.lds.S"
 
-  .data.init : { *(.data.init) }
+  init.data : { *(.init.data) }
 
   /* Ensure the __preinit_array_start label is properly aligned.  We
      could instead move the label definition inside the section, but
diff -puN arch/um/include/2_5compat.h~uml-base-patch arch/um/include/2_5compat.h
--- 25/arch/um/include/2_5compat.h~uml-base-patch	2004-08-15 20:45:08.346386088 -0700
+++ 25-akpm/arch/um/include/2_5compat.h	2004-08-15 20:46:03.228042808 -0700
@@ -6,20 +6,6 @@
 #ifndef __2_5_COMPAT_H__
 #define __2_5_COMPAT_H__
 
-#include "linux/version.h"
-
-#define INIT_CONSOLE(dev_name, write_proc, device_proc, setup_proc, f) { \
-	name :		dev_name, \
-	write :		write_proc, \
-	read :		NULL, \
-	device :	device_proc, \
-	setup :		setup_proc, \
-	flags :		f, \
-	index :		-1, \
-	cflag :		0, \
-	next :		NULL \
-}
-
 #define INIT_HARDSECT(arr, maj, sizes)
 
 #define SET_PRI(task) do ; while(0)
diff -puN /dev/null arch/um/include/irq_kern.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/include/irq_kern.h	2004-08-15 20:46:03.229042656 -0700
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __IRQ_KERN_H__
+#define __IRQ_KERN_H__
+
+#include "linux/interrupt.h"
+
+extern int um_request_irq(unsigned int irq, int fd, int type,
+			  irqreturn_t (*handler)(int, void *,
+						 struct pt_regs *),
+			  unsigned long irqflags,  const char * devname,
+			  void *dev_id);
+
+#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 -puN arch/um/include/kern_util.h~uml-base-patch arch/um/include/kern_util.h
--- 25/arch/um/include/kern_util.h~uml-base-patch	2004-08-15 20:45:08.348385784 -0700
+++ 25-akpm/arch/um/include/kern_util.h	2004-08-15 20:46:03.229042656 -0700
@@ -60,12 +60,11 @@ extern void finish_fork(void);
 extern void paging_init(void);
 extern void init_flush_vm(void);
 extern void *syscall_sp(void *t);
-extern void syscall_trace(void);
+extern void syscall_trace(union uml_pt_regs *regs, int entryexit);
 extern int hz(void);
-extern void idle_timer(void);
+extern void uml_idle_timer(void);
 extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
 extern int external_pid(void *t);
-extern int pid_to_processor_id(int pid);
 extern void boot_timer_handler(int sig);
 extern void interrupt_end(void);
 extern void initial_thread_cb(void (*proc)(void *), void *arg);
@@ -89,9 +88,7 @@ extern int remove_gdb(void);
 extern char *uml_strdup(char *string);
 extern void unprotect_kernel_mem(void);
 extern void protect_kernel_mem(void);
-extern void set_kmem_end(unsigned long);
 extern void uml_cleanup(void);
-extern int pid_to_processor_id(int pid);
 extern void set_current(void *t);
 extern void lock_signalled_task(void *t);
 extern void IPI_handler(int cpu);
@@ -100,7 +97,9 @@ extern void *get_init_task(void);
 extern int clear_user_proc(void *buf, int size);
 extern int copy_to_user_proc(void *to, void *from, int size);
 extern int copy_from_user_proc(void *to, void *from, int size);
+extern int strlen_user_proc(char *str);
 extern void bus_handler(int sig, union uml_pt_regs *regs);
+extern void winch(int sig, union uml_pt_regs *regs);
 extern long execute_syscall(void *r);
 extern int smp_sigio_handler(void);
 extern void *get_current(void);
@@ -111,6 +110,8 @@ extern void arch_switch(void);
 extern void free_irq(unsigned int, void *);
 extern int um_in_interrupt(void);
 extern int cpu(void);
+extern unsigned long long time_stamp(void);
+
 #endif
 
 /*
diff -puN arch/um/include/line.h~uml-base-patch arch/um/include/line.h
--- 25/arch/um/include/line.h~uml-base-patch	2004-08-15 20:45:08.349385632 -0700
+++ 25-akpm/arch/um/include/line.h	2004-08-15 20:46:03.230042504 -0700
@@ -9,12 +9,14 @@
 #include "linux/list.h"
 #include "linux/workqueue.h"
 #include "linux/tty.h"
+#include "linux/interrupt.h"
 #include "asm/semaphore.h"
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
 struct line_driver {
 	char *name;
+	char *device_name;
 	char *devfs_name;
 	short major;
 	short minor_start;
@@ -67,8 +69,6 @@ struct lines {
 
 #define LINES_INIT(n) {  num :		n }
 
-extern void line_interrupt(int irq, void *data, struct pt_regs *unused);
-extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused);
 extern void line_close(struct line *lines, struct tty_struct *tty);
 extern int line_open(struct line *lines, struct tty_struct *tty, 
 		     struct chan_opts *opts);
diff -puN arch/um/include/mconsole.h~uml-base-patch arch/um/include/mconsole.h
--- 25/arch/um/include/mconsole.h~uml-base-patch	2004-08-15 20:45:08.350385480 -0700
+++ 25-akpm/arch/um/include/mconsole.h	2004-08-15 20:46:03.230042504 -0700
@@ -41,11 +41,13 @@ struct mconsole_notify {
 
 struct mc_request;
 
+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
+
 struct mconsole_command
 {
 	char *command;
 	void (*handler)(struct mc_request *req);
-	int as_interrupt;
+	enum mc_context context;
 };
 
 struct mc_request
@@ -77,6 +79,8 @@ extern void mconsole_sysrq(struct mc_req
 extern void mconsole_cad(struct mc_request *req);
 extern void mconsole_stop(struct mc_request *req);
 extern void mconsole_go(struct mc_request *req);
+extern void mconsole_log(struct mc_request *req);
+extern void mconsole_proc(struct mc_request *req);
 
 extern int mconsole_get_request(int fd, struct mc_request *req);
 extern int mconsole_notify(char *sock_name, int type, const void *data, 
diff -puN arch/um/include/mem.h~uml-base-patch arch/um/include/mem.h
--- 25/arch/um/include/mem.h~uml-base-patch	2004-08-15 20:45:08.352385176 -0700
+++ 25-akpm/arch/um/include/mem.h	2004-08-15 20:46:03.231042352 -0700
@@ -1,19 +1,18 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #ifndef __MEM_H__
 #define __MEM_H__
 
-struct vm_reserved {
-	struct list_head list;
-	unsigned long start;
-	unsigned long end;
-};
+#include "linux/types.h"
 
-extern void set_usable_vm(unsigned long start, unsigned long end);
-extern void set_kmem_end(unsigned long new);
+extern int phys_mapping(unsigned long phys, __u64 *offset_out);
+extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
+extern int is_remapped(void *virt);
+extern int physmem_remove_mapping(void *virt);
+extern void physmem_forget_descriptor(int fd);
 
 #endif
 
diff -puN /dev/null arch/um/include/mem_kern.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/include/mem_kern.h	2004-08-15 20:46:03.231042352 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MEM_KERN_H__
+#define __MEM_KERN_H__
+
+#include "linux/list.h"
+#include "linux/types.h"
+
+struct remapper {
+	struct list_head list;
+	int (*proc)(int, unsigned long, int, __u64);
+};
+
+extern void register_remapper(struct remapper *info);
+
+#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 -puN arch/um/include/mem_user.h~uml-base-patch arch/um/include/mem_user.h
--- 25/arch/um/include/mem_user.h~uml-base-patch	2004-08-15 20:45:08.353385024 -0700
+++ 25-akpm/arch/um/include/mem_user.h	2004-08-15 20:46:03.231042352 -0700
@@ -32,43 +32,38 @@
 #ifndef _MEM_USER_H
 #define _MEM_USER_H
 
-struct mem_region {
+struct iomem_region {
+	struct iomem_region *next;
 	char *driver;
-	unsigned long start_pfn;
-	unsigned long start;
-	unsigned long len;
-	void *mem_map;
 	int fd;
+	int size;
+	unsigned long phys;
+	unsigned long virt;
 };
 
-extern struct mem_region *regions[];
-extern struct mem_region physmem_region;
+extern struct iomem_region *iomem_regions;
+extern int iomem_size;
 
 #define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
 
 extern unsigned long host_task_size;
 extern unsigned long task_size;
 
+extern void check_devanon(void);
 extern int init_mem_user(void);
 extern int create_mem_file(unsigned long len);
-extern void setup_range(int fd, char *driver, unsigned long start,
-			unsigned long pfn, unsigned long total, int need_vm, 
-			struct mem_region *region, void *reserved);
 extern void setup_memory(void *entry);
 extern unsigned long find_iomem(char *driver, unsigned long *len_out);
-extern int init_maps(struct mem_region *region);
-extern int nregions(void);
-extern int reserve_vm(unsigned long start, unsigned long end, void *e);
+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);
-extern int setup_region(struct mem_region *region, void *entry);
+			  unsigned long len, unsigned long highmem);
 extern void add_iomem(char *name, int fd, unsigned long size);
-extern struct mem_region *phys_region(unsigned long phys);
 extern unsigned long phys_offset(unsigned long phys);
 extern void unmap_physmem(void);
-extern int map_memory(unsigned long virt, unsigned long phys, 
-		      unsigned long len, int r, int w, int x);
+extern void map_memory(unsigned long virt, unsigned long phys,
+		       unsigned long len, int r, int w, int x);
 extern int protect_memory(unsigned long addr, unsigned long len, 
 			  int r, int w, int x, int must_succeed);
 extern unsigned long get_kmem_end(void);
diff -puN arch/um/include/os.h~uml-base-patch arch/um/include/os.h
--- 25/arch/um/include/os.h~uml-base-patch	2004-08-15 20:45:08.355384720 -0700
+++ 25-akpm/arch/um/include/os.h	2004-08-15 20:46:03.232042200 -0700
@@ -17,6 +17,32 @@
 #define OS_TYPE_FIFO 6
 #define OS_TYPE_SOCK 7
 
+/* os_access() flags */
+#define OS_ACC_F_OK    0       /* Test for existence.  */
+#define OS_ACC_X_OK    1       /* Test for execute permission.  */
+#define OS_ACC_W_OK    2       /* Test for write permission.  */
+#define OS_ACC_R_OK    4       /* Test for read permission.  */
+#define OS_ACC_RW_OK   (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */
+
+/*
+ * types taken from stat_file() in hostfs_user.c
+ * (if they are wrong here, they are wrong there...).
+ */
+struct uml_stat {
+	int                ust_dev;        /* device */
+	unsigned long long ust_ino;        /* inode */
+	int                ust_mode;       /* protection */
+	int                ust_nlink;      /* number of hard links */
+	int                ust_uid;        /* user ID of owner */
+	int                ust_gid;        /* group ID of owner */
+	unsigned long long ust_size;       /* total size, in bytes */
+	int                ust_blksize;    /* blocksize for filesystem I/O */
+	unsigned long long ust_blocks;     /* number of blocks allocated */
+	unsigned long      ust_atime;      /* time of last access */
+	unsigned long      ust_mtime;      /* time of last modification */
+	unsigned long      ust_ctime;      /* time of last change */
+};
+
 struct openflags {
 	unsigned int r : 1;
 	unsigned int w : 1;
@@ -84,29 +110,47 @@ static inline struct openflags of_excl(s
 	flags.e = 1; 
 	return(flags); 
 }
- 
+
 static inline struct openflags of_cloexec(struct openflags flags)
 { 
 	flags.cl = 1; 
 	return(flags); 
 }
   
+extern int os_stat_file(const char *file_name, struct uml_stat *buf);
+extern int os_stat_fd(const int fd, struct uml_stat *buf);
+extern int os_access(const char *file, int mode);
+extern void os_print_error(int error, const char* str);
+extern int os_get_exec_close(int fd, int *close_on_exec);
+extern int os_set_exec_close(int fd, int close_on_exec);
+extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
+extern int os_window_size(int fd, int *rows, int *cols);
+extern int os_new_tty_pgrp(int fd, int pid);
+extern int os_get_ifname(int fd, char *namebuf);
+extern int os_set_slip(int fd);
+extern int os_set_owner(int fd, int pid);
+extern int os_sigio_async(int master, int slave);
+extern int os_mode_fd(int fd, int mode);
+
 extern int os_seek_file(int fd, __u64 offset);
 extern int os_open_file(char *file, struct openflags flags, int mode);
 extern int os_read_file(int fd, void *buf, int len);
-extern int os_write_file(int fd, void *buf, int count);
+extern int os_write_file(int fd, const void *buf, int count);
 extern int os_file_size(char *file, long long *size_out);
+extern int os_file_modtime(char *file, unsigned long *modtime);
 extern int os_pipe(int *fd, int stream, int close_on_exec);
 extern int os_set_fd_async(int fd, int owner);
 extern int os_set_fd_block(int fd, int blocking);
 extern int os_accept_connection(int fd);
+extern int os_create_unix_socket(char *file, int len, int close_on_exec);
 extern int os_shutdown_socket(int fd, int r, int w);
 extern void os_close_file(int fd);
 extern int os_rcv_fd(int fd, int *helper_pid_out);
-extern int create_unix_socket(char *file, int len);
+extern int create_unix_socket(char *file, int len, int close_on_exec);
 extern int os_connect_socket(char *name);
 extern int os_file_type(char *file);
 extern int os_file_mode(char *file, struct openflags *mode_out);
+extern int os_lock_file(int fd, int excl);
 
 extern unsigned long os_process_pc(int pid);
 extern int os_process_parent(int pid);
@@ -115,11 +159,12 @@ extern void os_kill_process(int pid, int
 extern void os_usr1_process(int pid);
 extern int os_getpid(void);
 
-extern int os_map_memory(void *virt, int fd, unsigned long off, 
+extern int os_map_memory(void *virt, int fd, unsigned long long off,
 			 unsigned long len, int r, int w, int x);
 extern int os_protect_memory(void *addr, unsigned long len, 
 			     int r, int w, int x);
 extern int os_unmap_memory(void *addr, int len);
+extern void os_flush_stdout(void);
 
 #endif
 
diff -puN arch/um/include/signal_user.h~uml-base-patch arch/um/include/signal_user.h
--- 25/arch/um/include/signal_user.h~uml-base-patch	2004-08-15 20:45:08.356384568 -0700
+++ 25-akpm/arch/um/include/signal_user.h	2004-08-15 20:46:03.233042048 -0700
@@ -11,6 +11,8 @@ extern int signal_stack_size;
 extern int change_sig(int signal, int on);
 extern void set_sigstack(void *stack, int size);
 extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern int set_signals(int enable);
+extern int get_signals(void);
 
 #endif
 
diff -puN arch/um/include/skas_ptrace.h~uml-base-patch arch/um/include/skas_ptrace.h
--- 25/arch/um/include/skas_ptrace.h~uml-base-patch	2004-08-15 20:45:08.357384416 -0700
+++ 25-akpm/arch/um/include/skas_ptrace.h	2004-08-15 20:46:03.233042048 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 
diff -puN arch/um/include/sysdep-i386/frame_user.h~uml-base-patch arch/um/include/sysdep-i386/frame_user.h
--- 25/arch/um/include/sysdep-i386/frame_user.h~uml-base-patch	2004-08-15 20:45:08.358384264 -0700
+++ 25-akpm/arch/um/include/sysdep-i386/frame_user.h	2004-08-15 20:46:03.233042048 -0700
@@ -56,26 +56,26 @@ static inline void setup_arch_frame(stru
  * it would have to be __builtin_frame_address(1).
  */
 
-static inline unsigned long frame_restorer(void)
-{
-	unsigned long *fp;
-
-	fp = __builtin_frame_address(0);
-	return((unsigned long) (fp + 1));
-}
+#define frame_restorer() \
+({ \
+	unsigned long *fp; \
+\
+	fp = __builtin_frame_address(0); \
+	((unsigned long) (fp + 1)); \
+})
 
 /* Similarly, this returns the value of sp when the handler was first
  * entered.  This is used to calculate the proper sp when delivering
  * signals.
  */
 
-static inline unsigned long frame_sp(void)
-{
-	unsigned long *fp;
-
-	fp = __builtin_frame_address(0);
-	return((unsigned long) (fp + 1));
-}
+#define frame_sp() \
+({ \
+	unsigned long *fp; \
+\
+	fp = __builtin_frame_address(0); \
+	((unsigned long) (fp + 1)); \
+})
 
 #endif
 
diff -puN arch/um/include/sysdep-i386/sigcontext.h~uml-base-patch arch/um/include/sysdep-i386/sigcontext.h
--- 25/arch/um/include/sysdep-i386/sigcontext.h~uml-base-patch	2004-08-15 20:45:08.360383960 -0700
+++ 25-akpm/arch/um/include/sysdep-i386/sigcontext.h	2004-08-15 20:46:03.234041896 -0700
@@ -28,8 +28,8 @@
  */
 #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
 
-/* These are General Protection and Page Fault */
-#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14))
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(trap) (trap == 14)
 
 #define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
 
diff -puN arch/um/include/sysdep-i386/syscalls.h~uml-base-patch arch/um/include/sysdep-i386/syscalls.h
--- 25/arch/um/include/sysdep-i386/syscalls.h~uml-base-patch	2004-08-15 20:45:08.361383808 -0700
+++ 25-akpm/arch/um/include/sysdep-i386/syscalls.h	2004-08-15 20:46:03.234041896 -0700
@@ -11,39 +11,34 @@ typedef long syscall_handler_t(struct pt
 #define EXECUTE_SYSCALL(syscall, regs) \
 	((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
 
-extern syscall_handler_t sys_modify_ldt;
-extern syscall_handler_t old_mmap_i386;
-extern syscall_handler_t old_select;
-extern syscall_handler_t sys_ni_syscall;
-
 #define ARCH_SYSCALLS \
-	[ __NR_mmap ] = old_mmap_i386, \
-	[ __NR_select ] = old_select, \
-	[ __NR_vm86old ] = sys_ni_syscall, \
-        [ __NR_modify_ldt ] = sys_modify_ldt, \
-	[ __NR_lchown32 ] = sys_lchown, \
-	[ __NR_getuid32 ] = sys_getuid, \
-	[ __NR_getgid32 ] = sys_getgid, \
-	[ __NR_geteuid32 ] = sys_geteuid, \
-	[ __NR_getegid32 ] = sys_getegid, \
-	[ __NR_setreuid32 ] = sys_setreuid, \
-	[ __NR_setregid32 ] = sys_setregid, \
-	[ __NR_getgroups32 ] = sys_getgroups, \
-	[ __NR_setgroups32 ] = sys_setgroups, \
-	[ __NR_fchown32 ] = sys_fchown, \
-	[ __NR_setresuid32 ] = sys_setresuid, \
-	[ __NR_getresuid32 ] = sys_getresuid, \
-	[ __NR_setresgid32 ] = sys_setresgid, \
-	[ __NR_getresgid32 ] = sys_getresgid, \
-	[ __NR_chown32 ] = sys_chown, \
-	[ __NR_setuid32 ] = sys_setuid, \
-	[ __NR_setgid32 ] = sys_setgid, \
-	[ __NR_setfsuid32 ] = sys_setfsuid, \
-	[ __NR_setfsgid32 ] = sys_setfsgid, \
-	[ __NR_pivot_root ] = sys_pivot_root, \
-	[ __NR_mincore ] = sys_mincore, \
-	[ __NR_madvise ] = sys_madvise, \
-        [ 222 ] = sys_ni_syscall, 
+	[ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \
+	[ __NR_select ] = (syscall_handler_t *) old_select, \
+	[ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
+        [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
+	[ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
+	[ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
+	[ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
+	[ __NR_geteuid32 ] = (syscall_handler_t *) sys_geteuid, \
+	[ __NR_getegid32 ] = (syscall_handler_t *) sys_getegid, \
+	[ __NR_setreuid32 ] = (syscall_handler_t *) sys_setreuid, \
+	[ __NR_setregid32 ] = (syscall_handler_t *) sys_setregid, \
+	[ __NR_getgroups32 ] = (syscall_handler_t *) sys_getgroups, \
+	[ __NR_setgroups32 ] = (syscall_handler_t *) sys_setgroups, \
+	[ __NR_fchown32 ] = (syscall_handler_t *) sys_fchown, \
+	[ __NR_setresuid32 ] = (syscall_handler_t *) sys_setresuid, \
+	[ __NR_getresuid32 ] = (syscall_handler_t *) sys_getresuid, \
+	[ __NR_setresgid32 ] = (syscall_handler_t *) sys_setresgid, \
+	[ __NR_getresgid32 ] = (syscall_handler_t *) sys_getresgid, \
+	[ __NR_chown32 ] = (syscall_handler_t *) sys_chown, \
+	[ __NR_setuid32 ] = (syscall_handler_t *) sys_setuid, \
+	[ __NR_setgid32 ] = (syscall_handler_t *) sys_setgid, \
+	[ __NR_setfsuid32 ] = (syscall_handler_t *) sys_setfsuid, \
+	[ __NR_setfsgid32 ] = (syscall_handler_t *) sys_setfsgid, \
+	[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
+	[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
+	[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
+        [ 222 ] = (syscall_handler_t *) sys_ni_syscall,
         
 /* 222 doesn't yet have a name in include/asm-i386/unistd.h */
 
diff -puN arch/um/include/ubd_user.h~uml-base-patch arch/um/include/ubd_user.h
--- 25/arch/um/include/ubd_user.h~uml-base-patch	2004-08-15 20:45:08.362383656 -0700
+++ 25-akpm/arch/um/include/ubd_user.h	2004-08-15 20:46:03.235041744 -0700
@@ -9,7 +9,7 @@
 
 #include "os.h"
 
-enum ubd_req { UBD_READ, UBD_WRITE };
+enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
 
 struct io_thread_req {
 	enum ubd_req op;
@@ -20,8 +20,10 @@ struct io_thread_req {
 	char *buffer;
 	int sectorsize;
 	unsigned long sector_mask;
-	unsigned long cow_offset;
+	unsigned long long cow_offset;
 	unsigned long bitmap_words[2];
+	int map_fd;
+	unsigned long long map_offset;
 	int error;
 };
 
@@ -31,7 +33,7 @@ extern int open_ubd_file(char *file, str
 			 int *create_cow_out);
 extern int create_cow_file(char *cow_file, char *backing_file, 
 			   struct openflags flags, int sectorsize, 
-			   int *bitmap_offset_out, 
+			   int alignment, int *bitmap_offset_out,
 			   unsigned long *bitmap_len_out,
 			   int *data_offset_out);
 extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
@@ -39,7 +41,6 @@ extern int read_ubd_fs(int fd, void *buf
 extern int write_ubd_fs(int fd, char *buffer, int len);
 extern int start_io_thread(unsigned long sp, int *fds_out);
 extern void do_io(struct io_thread_req *req);
-extern int ubd_is_dir(char *file);
 
 static inline int ubd_test_bit(__u64 bit, unsigned char *data)
 {
diff -puN arch/um/include/um_uaccess.h~uml-base-patch arch/um/include/um_uaccess.h
--- 25/arch/um/include/um_uaccess.h~uml-base-patch	2004-08-15 20:45:08.364383352 -0700
+++ 25-akpm/arch/um/include/um_uaccess.h	2004-08-15 20:46:03.236041592 -0700
@@ -38,22 +38,73 @@ static inline int copy_to_user(void *to,
 				from, n));
 }
 
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+
 static inline int strncpy_from_user(char *dst, const char *src, int count)
 {
 	return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas,
 				dst, src, count));
 }
 
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
 static inline int __clear_user(void *mem, int len)
 {
 	return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len));
 }
 
+/*
+ * clear_user: - Zero a block of memory in user space.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
 static inline int clear_user(void *mem, int len)
 {
 	return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len));
 }
 
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ * @n:   The maximum valid length
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
 static inline int strnlen_user(const void *str, int len)
 {
 	return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len));
diff -puN arch/um/include/user.h~uml-base-patch arch/um/include/user.h
--- 25/arch/um/include/user.h~uml-base-patch	2004-08-15 20:45:08.365383200 -0700
+++ 25-akpm/arch/um/include/user.h	2004-08-15 20:46:03.236041592 -0700
@@ -14,6 +14,7 @@ extern void *um_kmalloc_atomic(int size)
 extern void kfree(void *ptr);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
+extern int strlcpy(char *, const char *, int);
 
 #endif
 
diff -puN arch/um/include/user_util.h~uml-base-patch arch/um/include/user_util.h
--- 25/arch/um/include/user_util.h~uml-base-patch	2004-08-15 20:45:08.366383048 -0700
+++ 25-akpm/arch/um/include/user_util.h	2004-08-15 20:46:03.236041592 -0700
@@ -14,8 +14,6 @@ extern int grantpt(int __fd);
 extern int unlockpt(int __fd);
 extern char *ptsname(int __fd);
 
-enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-
 struct cpu_task {
 	int pid;
 	void *task;
@@ -59,7 +57,6 @@ extern int wait_for_stop(int pid, int si
 extern void *add_signal_handler(int sig, void (*handler)(int));
 extern int start_fork_tramp(void *arg, unsigned long temp_stack, 
 			    int clone_flags, int (*tramp)(void *));
-extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
 extern int linux_main(int argc, char **argv);
 extern void set_cmdline(char *cmd);
 extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
@@ -86,11 +83,13 @@ extern void check_sigio(void);
 extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
 extern void write_sigio_workaround(void);
 extern void arch_check_bugs(void);
+extern int cpu_feature(char *what, char *buf, int len);
 extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
 extern int arch_fixup(unsigned long address, void *sc_ptr);
 extern void forward_pending_sigio(int target);
 extern int can_do_skas(void);
- 
+extern void arch_init_thread(void);
+
 #endif
 
 /*
diff -puN arch/um/Kconfig~uml-base-patch arch/um/Kconfig
--- 25/arch/um/Kconfig~uml-base-patch	2004-08-15 20:45:08.368382744 -0700
+++ 25-akpm/arch/um/Kconfig	2004-08-15 20:46:03.237041440 -0700
@@ -61,6 +61,20 @@ config MODE_SKAS
 
 config NET
 	bool "Networking support"
+	help
+	Unless you really know what you are doing, you should say Y here.
+	The reason is that some programs need kernel networking support even
+	when running on a stand-alone machine that isn't connected to any
+	other computer. If you are upgrading from an older kernel, you
+	should consider updating your networking tools too because changes
+	in the kernel and the tools often go hand in hand. The tools are
+	contained in the package net-tools, the location and version number
+	of which are given in Documentation/Changes.
+
+	For a general introduction to Linux networking, it is highly
+	recommended to read the NET-HOWTO, available from
+	<http://www.tldp.org/docs.html#howto>.
+
 
 source "fs/Kconfig.binfmt"
 
@@ -85,6 +99,19 @@ config HOSTFS
         If you'd like to be able to work with files stored on the host,
         say Y or M here; otherwise say N.
 
+config HPPFS
+	tristate "HoneyPot ProcFS"
+	help
+	hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
+	entries to be overridden, removed, or fabricated from the host.
+	Its purpose is to allow a UML to appear to be a physical machine
+	by removing or changing anything in /proc which gives away the
+	identity of a UML.
+
+	See http://user-mode-linux.sf.net/hppfs.html for more information.
+
+	You only need this if you are setting up a UML honeypot.  Otherwise,
+	it is safe to say 'N' here.
 
 config MCONSOLE
 	bool "Management console"
@@ -164,6 +191,17 @@ config KERNEL_STACK_ORDER
 	be 1 << order pages.  The default is OK unless you're running Valgrind
 	on UML, in which case, set this to 3.
 
+config UML_REAL_TIME_CLOCK
+	bool "Real-time Clock"
+	default y
+	help
+	This option makes UML time deltas match wall clock deltas.  This should
+	normally be enabled.  The exception would be if you are debugging with
+	UML and spend long times with UML stopped at a breakpoint.  In this
+	case, when UML is restarted, it will call the timer enough times to make
+	up for the time spent at the breakpoint.  This could result in a
+	noticable lag.  If this is a problem, then disable this option.
+
 endmenu
 
 source "init/Kconfig"
diff -puN arch/um/Kconfig_block~uml-base-patch arch/um/Kconfig_block
--- 25/arch/um/Kconfig_block~uml-base-patch	2004-08-15 20:45:08.369382592 -0700
+++ 25-akpm/arch/um/Kconfig_block	2004-08-15 20:46:03.238041288 -0700
@@ -29,6 +29,20 @@ config BLK_DEV_UBD_SYNC
         wise choice too.  In all other cases (for example, if you're just
         playing around with User-Mode Linux) you can choose N.
 
+# Turn this back on when the driver actually works
+#
+#config BLK_DEV_COW
+#	tristate "COW block device"
+#	help
+#	This is a layered driver which sits above two other block devices.
+#	One is read-only, and the other is a read-write layer which stores
+#	all changes.  This provides the illusion that the read-only layer
+#	can be mounted read-write and changed.
+
+config BLK_DEV_COW_COMMON
+	bool
+	default BLK_DEV_COW || BLK_DEV_UBD
+
 config BLK_DEV_LOOP
 	tristate "Loopback device support"
 
diff -puN arch/um/Kconfig_net~uml-base-patch arch/um/Kconfig_net
--- 25/arch/um/Kconfig_net~uml-base-patch	2004-08-15 20:45:08.370382440 -0700
+++ 25-akpm/arch/um/Kconfig_net	2004-08-15 20:46:03.239041136 -0700
@@ -1,5 +1,5 @@
 
-menu "Network Devices"
+menu "UML Network Devices"
 	depends on NET
 
 # UML virtual driver
@@ -176,73 +176,5 @@ config UML_NET_SLIRP
 	
         Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
 
-
-# Below are hardware-independent drivers mirrored from
-# drivers/net/Config.in. It would be nice if Linux
-# had HW independent drivers separated from the other
-# but it does not. Until then each non-ISA/PCI arch
-# needs to provide it's own menu of network drivers
-config DUMMY
-	tristate "Dummy net driver support"
-
-config BONDING
-	tristate "Bonding driver support"
-
-config EQUALIZER
-	tristate "EQL (serial line load balancing) support"
-
-config TUN
-	tristate "Universal TUN/TAP device driver support"
-
-config ETHERTAP
-	tristate "Ethertap network tap (OBSOLETE)"
-	depends on EXPERIMENTAL && NETLINK
-
-config PPP
-	tristate "PPP (point-to-point protocol) support"
-
-config PPP_MULTILINK
-	bool "PPP multilink support (EXPERIMENTAL)"
-	depends on PPP && EXPERIMENTAL
-
-config PPP_FILTER
-	bool "PPP filtering"
-	depends on PPP && FILTER
-
-config PPP_ASYNC
-	tristate "PPP support for async serial ports"
-	depends on PPP
-
-config PPP_SYNC_TTY
-	tristate "PPP support for sync tty ports"
-	depends on PPP
-
-config PPP_DEFLATE
-	tristate "PPP Deflate compression"
-	depends on PPP
-
-config PPP_BSDCOMP
-	tristate "PPP BSD-Compress compression"
-	depends on PPP
-
-config PPPOE
-	tristate "PPP over Ethernet (EXPERIMENTAL)"
-	depends on PPP && EXPERIMENTAL
-
-config SLIP
-	tristate "SLIP (serial line) support"
-
-config SLIP_COMPRESSED
-	bool "CSLIP compressed headers"
-	depends on SLIP=y
-
-config SLIP_SMART
-	bool "Keepalive and linefill"
-	depends on SLIP=y
-
-config SLIP_MODE_SLIP6
-	bool "Six bit SLIP encapsulation"
-	depends on SLIP=y
-
 endmenu
 
diff -puN arch/um/kernel/config.c.in~uml-base-patch arch/um/kernel/config.c.in
--- 25/arch/um/kernel/config.c.in~uml-base-patch	2004-08-15 20:45:08.371382288 -0700
+++ 25-akpm/arch/um/kernel/config.c.in	2004-08-15 20:46:03.239041136 -0700
@@ -7,9 +7,7 @@
 #include <stdlib.h>
 #include "init.h"
 
-static __initdata char *config = "
-CONFIG
-";
+static __initdata char *config = "CONFIG";
 
 static int __init print_config(char *line, int *add)
 {
diff -puN arch/um/kernel/exec_kern.c~uml-base-patch arch/um/kernel/exec_kern.c
--- 25/arch/um/kernel/exec_kern.c~uml-base-patch	2004-08-15 20:45:08.373381984 -0700
+++ 25-akpm/arch/um/kernel/exec_kern.c	2004-08-15 20:46:03.239041136 -0700
@@ -32,10 +32,15 @@ void start_thread(struct pt_regs *regs, 
 	CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
 }
 
+extern void log_exec(char **argv, void *tty);
+
 static int execve1(char *file, char **argv, char **env)
 {
         int error;
 
+#ifdef CONFIG_TTY_LOG
+	log_exec(argv, current->tty);
+#endif
         error = do_execve(file, argv, env, &current->thread.regs);
         if (error == 0){
                 current->ptrace &= ~PT_DTRACE;
diff -puN arch/um/kernel/frame.c~uml-base-patch arch/um/kernel/frame.c
--- 25/arch/um/kernel/frame.c~uml-base-patch	2004-08-15 20:45:08.374381832 -0700
+++ 25-akpm/arch/um/kernel/frame.c	2004-08-15 20:46:03.240040984 -0700
@@ -279,7 +279,7 @@ void capture_signal_stack(void)
 	struct sc_frame_raw raw_sc;
 	struct si_frame_raw raw_si;
 	void *stack, *sigstack;
-	unsigned long top, sig_top, base;
+	unsigned long top, base;
 
 	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -292,7 +292,6 @@ void capture_signal_stack(void)
 	}
 
 	top = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
-	sig_top = (unsigned long) sigstack + PAGE_SIZE;
 
 	/* Get the sigcontext, no sigrestorer layout */
 	raw_sc.restorer = 0;
diff -puN arch/um/kernel/frame_kern.c~uml-base-patch arch/um/kernel/frame_kern.c
--- 25/arch/um/kernel/frame_kern.c~uml-base-patch	2004-08-15 20:45:08.375381680 -0700
+++ 25-akpm/arch/um/kernel/frame_kern.c	2004-08-15 20:46:03.240040984 -0700
@@ -6,7 +6,6 @@
 #include "asm/ptrace.h"
 #include "asm/uaccess.h"
 #include "asm/signal.h"
-#include "asm/uaccess.h"
 #include "asm/ucontext.h"
 #include "frame_kern.h"
 #include "sigcontext.h"
@@ -29,12 +28,15 @@ static int copy_restorer(void (*restorer
 			    sizeof(restorer)));
 }
 
+extern int userspace_pid[];
+
 static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, 
 			   struct arch_frame_data *arch)
 {
 	return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 
 					      arch),
-			   copy_sc_to_user_skas(to, fp, &from->regs,
+			   copy_sc_to_user_skas(userspace_pid[0], to, fp,
+						&from->regs,
 						current->thread.cr2,
 						current->thread.err)));
 }
diff -puN arch/um/kernel/helper.c~uml-base-patch arch/um/kernel/helper.c
--- 25/arch/um/kernel/helper.c~uml-base-patch	2004-08-15 20:45:08.377381376 -0700
+++ 25-akpm/arch/um/kernel/helper.c	2004-08-15 20:46:03.241040832 -0700
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sched.h>
 #include <sys/signal.h>
 #include <sys/wait.h>
@@ -33,6 +32,7 @@ static int helper_child(void *arg)
 {
 	struct helper_data *data = arg;
 	char **argv = data->argv;
+	int errval;
 
 	if(helper_pause){
 		signal(SIGHUP, helper_hup);
@@ -41,8 +41,9 @@ static int helper_child(void *arg)
 	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);
-	write(data->fd, &errno, sizeof(errno));
+	os_write_file(data->fd, &errval, sizeof(errval));
 	os_kill_process(os_getpid(), 0);
 	return(0);
 }
@@ -59,17 +60,20 @@ int run_helper(void (*pre_exec)(void *),
 	if((stack_out != NULL) && (*stack_out != 0))
 		stack = *stack_out;
 	else stack = alloc_stack(0, um_in_interrupt());
-	if(stack == 0) return(-ENOMEM);
+	if(stack == 0)
+		return(-ENOMEM);
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("run_helper : pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("run_helper : pipe failed, err = %d\n", -err);
+		goto out_free;
 	}
-	if(fcntl(fds[1], F_SETFD, 1) != 0){
-		printk("run_helper : setting FD_CLOEXEC failed, errno = %d\n",
-		       errno);
-		return(-errno);
+
+	err = os_set_exec_close(fds[1], 1);
+	if(err < 0){
+		printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
+		       -err);
+		goto out_close;
 	}
 
 	sp = stack + page_size() - sizeof(void *);
@@ -80,23 +84,34 @@ int run_helper(void (*pre_exec)(void *),
 	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
 	if(pid < 0){
 		printk("run_helper : clone failed, errno = %d\n", errno);
-		return(-errno);
+		err = -errno;
+		goto out_close;
 	}
-	close(fds[1]);
-	n = read(fds[0], &err, sizeof(err));
+
+	os_close_file(fds[1]);
+	n = os_read_file(fds[0], &err, sizeof(err));
 	if(n < 0){
-		printk("run_helper : read on pipe failed, errno = %d\n", 
-		       errno);
-		return(-errno);
+		printk("run_helper : read on pipe failed, err = %d\n", -n);
+		err = n;
+		goto out_kill;
 	}
 	else if(n != 0){
 		waitpid(pid, NULL, 0);
-		pid = -err;
+		pid = -errno;
 	}
 
 	if(stack_out == NULL) free_stack(stack, 0);
         else *stack_out = stack;
 	return(pid);
+
+ out_kill:
+	os_kill_process(pid, 1);
+ out_close:
+	os_close_file(fds[0]);
+	os_close_file(fds[1]);
+ out_free:
+	free_stack(stack, 0);
+	return(err);
 }
 
 int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, 
@@ -117,9 +132,11 @@ int run_helper_thread(int (*proc)(void *
 	}
 	if(stack_out == NULL){
 		pid = waitpid(pid, &status, 0);
-		if(pid < 0)
+		if(pid < 0){
 			printk("run_helper_thread - wait failed, errno = %d\n",
-			       pid);
+			       errno);
+			pid = -errno;
+		}
 		if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
 			printk("run_helper_thread - thread returned status "
 			       "0x%x\n", status);
diff -puN arch/um/kernel/initrd_user.c~uml-base-patch arch/um/kernel/initrd_user.c
--- 25/arch/um/kernel/initrd_user.c~uml-base-patch	2004-08-15 20:45:08.378381224 -0700
+++ 25-akpm/arch/um/kernel/initrd_user.c	2004-08-15 20:46:03.241040832 -0700
@@ -6,7 +6,6 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
 #include <errno.h>
 
 #include "user_util.h"
@@ -19,13 +18,15 @@ int load_initrd(char *filename, void *bu
 {
 	int fd, n;
 
-	if((fd = os_open_file(filename, of_read(OPENFLAGS()), 0)) < 0){
-		printk("Opening '%s' failed - errno = %d\n", filename, errno);
+	fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Opening '%s' failed - err = %d\n", filename, -fd);
 		return(-1);
 	}
-	if((n = read(fd, buf, size)) != size){
-		printk("Read of %d bytes from '%s' returned %d, errno = %d\n",
-		       size, filename, n, errno);
+	n = os_read_file(fd, buf, size);
+	if(n != size){
+		printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+		       filename, -n);
 		return(-1);
 	}
 	return(0);
diff -puN arch/um/kernel/init_task.c~uml-base-patch arch/um/kernel/init_task.c
--- 25/arch/um/kernel/init_task.c~uml-base-patch	2004-08-15 20:45:08.379381072 -0700
+++ 25-akpm/arch/um/kernel/init_task.c	2004-08-15 20:46:03.242040680 -0700
@@ -8,7 +8,6 @@
 #include "linux/module.h"
 #include "linux/sched.h"
 #include "linux/init_task.h"
-#include "linux/version.h"
 #include "linux/mqueue.h"
 #include "asm/uaccess.h"
 #include "asm/pgtable.h"
@@ -19,7 +18,7 @@ static struct fs_struct init_fs = INIT_F
 struct mm_struct init_mm = INIT_MM(init_mm);
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 EXPORT_SYMBOL(init_mm);
 
 /*
@@ -44,26 +43,12 @@ union thread_union init_thread_union 
 __attribute__((__section__(".data.init_task"))) = 
 { INIT_THREAD_INFO(init_task) };
 
-struct task_struct *alloc_task_struct(void)
-{
-	return((struct task_struct *) 
-	       __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER));
-}
-
 void unprotect_stack(unsigned long stack)
 {
 	protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, 
 		       1, 1, 0, 1);
 }
 
-void free_task_struct(struct task_struct *task)
-{
-	/* free_pages decrements the page counter and only actually frees
-	 * the pages if they are now not accessed by anything.
-	 */
-	free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER);
-}
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN arch/um/kernel/irq.c~uml-base-patch arch/um/kernel/irq.c
--- 25/arch/um/kernel/irq.c~uml-base-patch	2004-08-15 20:45:08.380380920 -0700
+++ 25-akpm/arch/um/kernel/irq.c	2004-08-15 20:46:03.243040528 -0700
@@ -29,6 +29,7 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 static void register_irq_proc (unsigned int irq);
 
@@ -83,65 +84,55 @@ struct hw_interrupt_type no_irq_type = {
 	end_none
 };
 
-/* Not changed */
-volatile unsigned long irq_err_count;
-
 /*
  * Generic, controller-independent functions:
  */
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
-	unsigned long flags;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
-	char *p = buf;
+	unsigned long flags;
 
-	p += sprintf(p, "           ");
-	for (j=0; j<num_online_cpus(); j++)
-		p += sprintf(p, "CPU%d       ",j);
-	*p++ = '\n';
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			goto end;
-		p += sprintf(p, "%3d: ",i);
+			goto skip;
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for (j = 0; j < num_online_cpus(); j++)
-			p += sprintf(p, "%10u ",
-				kstat_cpu(cpu_logical_map(j)).irqs[i]);
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-			p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
-	end:
+			seq_printf(p, ", %s", action->name);
+
+		seq_putc(p, '\n');
+skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+	} else if (i == NR_IRQS) {
+		seq_printf(p, "NMI: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", nmi_count(j));
+		seq_putc(p, '\n');
 	}
-	p += sprintf(p, "\n");
-#ifdef notdef
-#ifdef CONFIG_SMP
-	p += sprintf(p, "LOC: ");
-	for (j = 0; j < num_online_cpus(); j++)
-		p += sprintf(p, "%10u ",
-			apic_timer_irqs[cpu_logical_map(j)]);
-	p += sprintf(p, "\n");
-#endif
-#endif
-	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
-	return p - buf;
-}
-
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-	return(0);
+	return 0;
 }
 
 /*
@@ -282,13 +273,12 @@ unsigned int do_IRQ(int irq, union uml_p
 	 * 0 return value means that this irq is already being
 	 * handled by some other CPU. (or is disabled)
 	 */
-	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
 	unsigned int status;
 
 	irq_enter();
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_this_cpu.irqs[irq]++;
 	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
 	/*
@@ -385,7 +375,7 @@ out:
  */
  
 int request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		unsigned long irqflags, 
 		const char * devname,
 		void *dev_id)
@@ -433,15 +423,19 @@ int request_irq(unsigned int irq,
 EXPORT_SYMBOL(request_irq);
 
 int um_request_irq(unsigned int irq, int fd, int type,
-		   void (*handler)(int, void *, struct pt_regs *),
+		   irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		   unsigned long irqflags, const char * devname,
 		   void *dev_id)
 {
-	int retval;
+	int err;
 
-	retval = request_irq(irq, handler, irqflags, devname, dev_id);
-	if(retval) return(retval);
-	return(activate_fd(irq, fd, type, dev_id));
+	err = request_irq(irq, handler, irqflags, devname, dev_id);
+	if(err)
+		return(err);
+
+	if(fd != -1)
+		err = activate_fd(irq, fd, type, dev_id);
+	return(err);
 }
 
 /* this was setup_x86_irq but it seems pretty generic */
@@ -474,7 +468,8 @@ int setup_irq(unsigned int irq, struct i
 	 */
 	spin_lock_irqsave(&desc->lock,flags);
 	p = &desc->action;
-	if ((old = *p) != NULL) {
+	old = *p;
+	if (old != NULL) {
 		/* Can't share interrupts unless both agree to */
 		if (!(old->flags & new->flags & SA_SHIRQ)) {
 			spin_unlock_irqrestore(&desc->lock,flags);
@@ -586,12 +581,14 @@ static int irq_affinity_write_proc (stru
 					unsigned long count, void *data)
 {
 	int irq = (long) data, full_count = count, err;
-	cpumask_t new_value, tmp;
+	cpumask_t new_value;
 
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
 	err = cpumask_parse(buffer, count, new_value);
+	if(err)
+		return(err);
 
 #ifdef CONFIG_SMP
 	/*
@@ -599,9 +596,11 @@ static int irq_affinity_write_proc (stru
 	 * way to make the system unusable accidentally :-) At least
 	 * one online CPU still has to be targeted.
 	 */
-	cpus_and(tmp, new_value, cpu_online_map);
-	if (cpus_empty(tmp))
-		return -EINVAL;
+	{ cpumask_t tmp;
+	  cpus_and(tmp, new_value, cpu_online_map);
+	  if (cpus_empty(tmp))
+		  return -EINVAL;
+	}
 #endif
 
 	irq_affinity[irq] = new_value;
diff -puN arch/um/kernel/irq_user.c~uml-base-patch arch/um/kernel/irq_user.c
--- 25/arch/um/kernel/irq_user.c~uml-base-patch	2004-08-15 20:45:08.382380616 -0700
+++ 25-akpm/arch/um/kernel/irq_user.c	2004-08-15 20:46:03.244040376 -0700
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <signal.h>
 #include <string.h>
 #include <sys/poll.h>
@@ -49,7 +48,8 @@ void sigio_handler(int sig, union uml_pt
 
 	if(smp_sigio_handler()) return;
 	while(1){
-		if((n = poll(pollfds, pollfds_num, 0)) < 0){
+		n = poll(pollfds, pollfds_num, 0);
+		if(n < 0){
 			if(errno == EINTR) continue;
 			printk("sigio_handler : poll returned %d, "
 			       "errno = %d\n", n, errno);
@@ -366,34 +366,31 @@ void deactivate_fd(int fd, int irqnum)
 
 void forward_ipi(int fd, int pid)
 {
-	if(fcntl(fd, F_SETOWN, pid) < 0){
-		int save_errno = errno;
-		if(fcntl(fd, F_GETOWN, 0) != pid){
-			printk("forward_ipi: F_SETOWN failed, fd = %d, "
-			       "me = %d, target = %d, errno = %d\n", fd, 
-			       os_getpid(), pid, save_errno);
-		}
-	}
+	int err;
+
+	err = os_set_owner(fd, pid);
+	if(err < 0)
+		printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
+		       "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
 }
 
 void forward_interrupts(int pid)
 {
 	struct irq_fd *irq;
 	unsigned long flags;
+	int err;
 
 	flags = irq_lock();
 	for(irq=active_fds;irq != NULL;irq = irq->next){
-		if(fcntl(irq->fd, F_SETOWN, pid) < 0){
-			int save_errno = errno;
-			if(fcntl(irq->fd, F_GETOWN, 0) != pid){
-				/* XXX Just remove the irq rather than
-				 * print out an infinite stream of these
-				 */
-				printk("Failed to forward %d to pid %d, "
-				       "errno = %d\n", irq->fd, pid, 
-				       save_errno);
-			}
+		err = os_set_owner(irq->fd, pid);
+		if(err < 0){
+			/* XXX Just remove the irq rather than
+			 * print out an infinite stream of these
+			 */
+			printk("Failed to forward %d to pid %d, err = %d\n",
+			       irq->fd, pid, -err);
 		}
+
 		irq->pid = pid;
 	}
 	irq_unlock(flags);
diff -puN arch/um/kernel/ksyms.c~uml-base-patch arch/um/kernel/ksyms.c
--- 25/arch/um/kernel/ksyms.c~uml-base-patch	2004-08-15 20:45:08.383380464 -0700
+++ 25-akpm/arch/um/kernel/ksyms.c	2004-08-15 20:46:03.245040224 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -8,7 +8,7 @@
 #include "linux/string.h"
 #include "linux/smp_lock.h"
 #include "linux/spinlock.h"
-#include <linux/highmem.h>
+#include "linux/highmem.h"
 #include "asm/current.h"
 #include "asm/delay.h"
 #include "asm/processor.h"
@@ -19,6 +19,7 @@
 #include "asm/tlbflush.h"
 #include "kern_util.h"
 #include "user_util.h"
+#include "mem_user.h"
 #include "os.h"
 #include "helper.h"
 
@@ -34,34 +35,64 @@ EXPORT_SYMBOL(task_size);
 EXPORT_SYMBOL(flush_tlb_range);
 EXPORT_SYMBOL(host_task_size);
 EXPORT_SYMBOL(arch_validate);
+EXPORT_SYMBOL(get_kmem_end);
 
-EXPORT_SYMBOL(region_pa);
-EXPORT_SYMBOL(region_va);
-EXPORT_SYMBOL(phys_mem_map);
-EXPORT_SYMBOL(page_mem_map);
 EXPORT_SYMBOL(page_to_phys);
 EXPORT_SYMBOL(phys_to_page);
 EXPORT_SYMBOL(high_physmem);
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(um_virt_to_phys);
+EXPORT_SYMBOL(__virt_to_page);
+EXPORT_SYMBOL(to_phys);
+EXPORT_SYMBOL(to_virt);
 EXPORT_SYMBOL(mode_tt);
 EXPORT_SYMBOL(handle_page_fault);
+EXPORT_SYMBOL(find_iomem);
 
+#ifdef CONFIG_MODE_TT
+EXPORT_SYMBOL(copy_from_user_tt);
+EXPORT_SYMBOL(copy_to_user_tt);
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+EXPORT_SYMBOL(copy_to_user_skas);
+EXPORT_SYMBOL(copy_from_user_skas);
+#endif
+
+EXPORT_SYMBOL(os_stat_fd);
+EXPORT_SYMBOL(os_stat_file);
+EXPORT_SYMBOL(os_access);
+EXPORT_SYMBOL(os_print_error);
+EXPORT_SYMBOL(os_get_exec_close);
+EXPORT_SYMBOL(os_set_exec_close);
 EXPORT_SYMBOL(os_getpid);
 EXPORT_SYMBOL(os_open_file);
 EXPORT_SYMBOL(os_read_file);
 EXPORT_SYMBOL(os_write_file);
 EXPORT_SYMBOL(os_seek_file);
+EXPORT_SYMBOL(os_lock_file);
+EXPORT_SYMBOL(os_ioctl_generic);
 EXPORT_SYMBOL(os_pipe);
 EXPORT_SYMBOL(os_file_type);
+EXPORT_SYMBOL(os_file_mode);
+EXPORT_SYMBOL(os_file_size);
+EXPORT_SYMBOL(os_flush_stdout);
 EXPORT_SYMBOL(os_close_file);
+EXPORT_SYMBOL(os_set_fd_async);
+EXPORT_SYMBOL(os_set_fd_block);
 EXPORT_SYMBOL(helper_wait);
 EXPORT_SYMBOL(os_shutdown_socket);
+EXPORT_SYMBOL(os_create_unix_socket);
 EXPORT_SYMBOL(os_connect_socket);
+EXPORT_SYMBOL(os_accept_connection);
+EXPORT_SYMBOL(os_rcv_fd);
 EXPORT_SYMBOL(run_helper);
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(dump_thread);
 
+EXPORT_SYMBOL(do_gettimeofday);
+EXPORT_SYMBOL(do_settimeofday);
+
 /* This is here because UML expands open to sys_open, not to a system
  * call instruction.
  */
@@ -90,3 +121,13 @@ EXPORT_SYMBOL(kunmap_atomic);
 EXPORT_SYMBOL(kmap_atomic_to_page);
 #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 -puN arch/um/kernel/Makefile~uml-base-patch arch/um/kernel/Makefile
--- 25/arch/um/kernel/Makefile~uml-base-patch	2004-08-15 20:45:08.384380312 -0700
+++ 25-akpm/arch/um/kernel/Makefile	2004-08-15 20:46:03.246040072 -0700
@@ -7,11 +7,11 @@ extra-y := vmlinux.lds
 
 obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \
 	helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \
-	process.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 \
-	syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \
-	time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
-	umid.o user_syms.o user_util.o
+	physmem.o process.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 syscall_user.o sysrq.o sys_call_table.o tempfile.o \
+	time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
+	um_arch.o umid.o user_util.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
@@ -24,43 +24,27 @@ obj-$(CONFIG_MODE_SKAS) += skas/
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
 USER_OBJS := $(filter %_user.o,$(obj-y))  $(user-objs-y) config.o helper.o \
-	process.o tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o
+	process.o tempfile.o time.o tty_log.o umid.o user_util.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
-DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
-
-
-CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \
-	-I/usr/include -I../include
-
 CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS))
 
-$(USER_OBJS) : %.o: %.c
-	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
 # This has to be separate because it needs be compiled with frame pointers
 # regardless of how the rest of the kernel is built.
 
 $(obj)/frame.o: $(src)/frame.c
 	$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
 
-QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
+$(USER_OBJS) : %.o: %.c
+	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
 
-$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
-	$(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
 
 $(obj)/config.o : $(obj)/config.c
 
-clean:
-	rm -f config.c
-	for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
-
-modules:
-
-fastdep:
-
-dep:
-
-archmrproper: clean
+quiet_cmd_quote = QUOTE $@
+cmd_quote = $(PERL) -e $(QUOTE) < $< > $@
 
+targets += config.c
+$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config FORCE
+	$(call if_changed,quote)
diff -puN arch/um/kernel/mem.c~uml-base-patch arch/um/kernel/mem.c
--- 25/arch/um/kernel/mem.c~uml-base-patch	2004-08-15 20:45:08.386380008 -0700
+++ 25-akpm/arch/um/kernel/mem.c	2004-08-15 20:46:03.249039616 -0700
@@ -1,74 +1,66 @@
 /* 
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
-#include "linux/config.h"
-#include "linux/module.h"
-#include "linux/types.h"
+#include "linux/stddef.h"
+#include "linux/kernel.h"
 #include "linux/mm.h"
-#include "linux/fs.h"
-#include "linux/init.h"
 #include "linux/bootmem.h"
 #include "linux/swap.h"
-#include "linux/slab.h"
-#include "linux/vmalloc.h"
 #include "linux/highmem.h"
+#include "linux/gfp.h"
 #include "asm/page.h"
-#include "asm/pgtable.h"
+#include "asm/fixmap.h"
 #include "asm/pgalloc.h"
-#include "asm/bitops.h"
-#include "asm/uaccess.h"
-#include "asm/tlb.h"
 #include "user_util.h"
 #include "kern_util.h"
-#include "mem_user.h"
-#include "mem.h"
 #include "kern.h"
-#include "init.h"
-#include "os.h"
-#include "mode_kern.h"
+#include "mem_user.h"
 #include "uml_uaccess.h"
+#include "os.h"
+
+extern char __binary_start;
 
 /* Changed during early boot */
-pgd_t swapper_pg_dir[1024];
-unsigned long high_physmem;
-unsigned long vm_start;
-unsigned long vm_end;
-unsigned long highmem;
 unsigned long *empty_zero_page = NULL;
 unsigned long *empty_bad_page = NULL;
-
-/* Not modified */
-const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
-
-extern char __init_begin, __init_end;
-extern long physmem_size;
-
-/* Not changed by UML */
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
-/* Changed during early boot */
+pgd_t swapper_pg_dir[1024];
+unsigned long highmem;
 int kmalloc_ok = 0;
 
-#define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1)
-struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL };
-#define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1)
-
-/* Changed during early boot */
 static unsigned long brk_end;
 
+void unmap_physmem(void)
+{
+	os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
+}
+
 static void map_cb(void *unused)
 {
 	map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
 }
 
-void unmap_physmem(void)
+#ifdef CONFIG_HIGHMEM
+static void setup_highmem(unsigned long highmem_start,
+			  unsigned long highmem_len)
 {
-	os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
-}
+	struct page *page;
+	unsigned long highmem_pfn;
+	int i;
 
-extern char __binary_start;
+	highmem_start_page = virt_to_page(highmem_start);
+
+	highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
+	for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
+		page = &mem_map[highmem_pfn + i];
+		ClearPageReserved(page);
+		set_bit(PG_highmem, &page->flags);
+		set_page_count(page, 1);
+		__free_page(page);
+	}
+}
+#endif
 
 void mem_init(void)
 {
@@ -103,50 +95,15 @@ void mem_init(void)
 	totalhigh_pages = highmem >> PAGE_SHIFT;
 	totalram_pages += totalhigh_pages;
 	num_physpages = totalram_pages;
-	max_mapnr = totalram_pages;
 	max_pfn = totalram_pages;
 	printk(KERN_INFO "Memory: %luk available\n", 
 	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
 	kmalloc_ok = 1;
-}
-
-/* Changed during early boot */
-static unsigned long kmem_top = 0;
-
-unsigned long get_kmem_end(void)
-{
-	if(kmem_top == 0)
-		kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
-	return(kmem_top);
-}
-
-void set_kmem_end(unsigned long new)
-{
-	kmem_top = new;
-}
 
 #ifdef CONFIG_HIGHMEM
-/* Changed during early boot */
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
-
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
-#define kmap_get_fixmap_pte(vaddr)					\
-	pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-
-void __init kmap_init(void)
-{
-	unsigned long kmap_vstart;
-
-	/* cache the first kmap pte */
-	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
-	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
-	kmap_prot = PAGE_KERNEL;
+	setup_highmem(end_iomem, highmem);
+#endif
 }
-#endif /* CONFIG_HIGHMEM */
 
 static void __init fixrange_init(unsigned long start, unsigned long end, 
 				 pgd_t *pgd_base)
@@ -178,76 +135,24 @@ static void __init fixrange_init(unsigne
 	}
 }
 
-int init_maps(struct mem_region *region)
-{
-	struct page *p, *map;
-	int i, n, len;
-
-	if(region == &physmem_region){
-		region->mem_map = mem_map;
-		return(0);
-	}
-	else if(region->mem_map != NULL) return(0);
-
-	n = region->len >> PAGE_SHIFT;
-	len = n * sizeof(struct page);
-	if(kmalloc_ok){
-		map = kmalloc(len, GFP_KERNEL);
-		if(map == NULL) map = vmalloc(len);
-	}
-	else map = alloc_bootmem_low_pages(len);
-
-	if(map == NULL)
-		return(-ENOMEM);
-	for(i = 0; i < n; i++){
-		p = &map[i];
-		set_page_count(p, 0);
-		SetPageReserved(p);
-		INIT_LIST_HEAD(&p->list);
-	}
-	region->mem_map = map;
-	return(0);
-}
+#if CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
 
-DECLARE_MUTEX(regions_sem);
+#define kmap_get_fixmap_pte(vaddr)					\
+	pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
 
-static int setup_one_range(int fd, char *driver, unsigned long start, 
-			   unsigned long pfn, int len, 
-			   struct mem_region *region)
+void __init kmap_init(void)
 {
-	int i;
-
-	down(&regions_sem);
-	for(i = 0; i < NREGIONS; i++){
-		if(regions[i] == NULL) break;		
-	}
-	if(i == NREGIONS){
-		printk("setup_range : no free regions\n");
-		i = -1;
-		goto out;
-	}
-
-	if(fd == -1)
-		fd = create_mem_file(len);
+	unsigned long kmap_vstart;
 
-	if(region == NULL){
-		region = alloc_bootmem_low_pages(sizeof(*region));
-		if(region == NULL)
-			panic("Failed to allocating mem_region");
-	}
+	/* cache the first kmap pte */
+	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
 
-	*region = ((struct mem_region) { .driver 	= driver,
-					 .start_pfn 	= pfn,
-					 .start 	= start, 
-					 .len 		= len, 
-					 .fd 		= fd } );
-	regions[i] = region;
- out:
-	up(&regions_sem);
-	return(i);
+	kmap_prot = PAGE_KERNEL;
 }
 
-#ifdef CONFIG_HIGHMEM
 static void init_highmem(void)
 {
 	pgd_t *pgd;
@@ -268,63 +173,20 @@ static void init_highmem(void)
 
 	kmap_init();
 }
-
-void setup_highmem(unsigned long len)
-{
-	struct mem_region *region;
-	struct page *page, *map;
-	unsigned long phys;
-	int i, cur, index;
-
-	phys = physmem_size;
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		i = setup_one_range(-1, NULL, -1, phys >> PAGE_SHIFT, cur, 
-				    NULL);
-		if(i == -1){
-			printk("setup_highmem - setup_one_range failed\n");
-			return;
-		}
-		region = regions[i];
-		index = phys / PAGE_SIZE;
-		region->mem_map = &mem_map[index];
-
-		map = region->mem_map;
-		for(i = 0; i < (cur >> PAGE_SHIFT); i++){
-			page = &map[i];
-			ClearPageReserved(page);
-			set_bit(PG_highmem, &page->flags);
-			set_page_count(page, 1);
-			__free_page(page);
-		}
-		phys += cur;
-		len -= cur;
-	} while(len > 0);
-}
-#endif
+#endif /* CONFIG_HIGHMEM */
 
 void paging_init(void)
 {
-	struct mem_region *region;
-	unsigned long zones_size[MAX_NR_ZONES], start, end, vaddr;
-	int i, index;
+	unsigned long zones_size[MAX_NR_ZONES], vaddr;
+	int i;
 
 	empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
 	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] = (high_physmem >> PAGE_SHIFT) - 
-		(uml_physmem >> PAGE_SHIFT);
+	zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
 	zones_size[2] = highmem >> PAGE_SHIFT;
 	free_area_init(zones_size);
-	start = phys_region_index(__pa(uml_physmem));
-	end = phys_region_index(__pa(high_physmem - 1));
-	for(i = start; i <= end; i++){
-		region = regions[i];
-		index = (region->start - uml_physmem) / PAGE_SIZE;
-		region->mem_map = &mem_map[index];
-		if(i > start) free_bootmem(__pa(region->start), region->len);
-	}
 
 	/*
 	 * Fixed mappings, only the page table structure has to be
@@ -335,15 +197,33 @@ void paging_init(void)
 
 #ifdef CONFIG_HIGHMEM
 	init_highmem();
-	setup_highmem(highmem);
 #endif
 }
 
-pte_t __bad_page(void)
+struct page *arch_validate(struct page *page, int mask, int order)
 {
-	clear_page(empty_bad_page);
-        return pte_mkdirty(mk_pte((struct page *) empty_bad_page, 
-				  PAGE_SHARED));
+	unsigned long addr, zero = 0;
+	int i;
+
+ again:
+	if(page == NULL) return(page);
+	if(PageHighMem(page)) return(page);
+
+	addr = (unsigned long) page_address(page);
+	for(i = 0; i < (1 << order); i++){
+		current->thread.fault_addr = (void *) addr;
+		if(__do_copy_to_user((void *) addr, &zero,
+				     sizeof(zero),
+				     &current->thread.fault_addr,
+				     &current->thread.fault_catcher)){
+			if(!(mask & __GFP_WAIT)) return(NULL);
+			else break;
+		}
+		addr += PAGE_SIZE;
+	}
+	if(i == (1 << order)) return(page);
+	page = alloc_pages(mask, order);
+	goto again;
 }
 
 /* This can't do anything because nothing in the kernel image can be freed
@@ -401,395 +281,6 @@ void show_mem(void)
         printk("%d pages swap cached\n", cached);
 }
 
-static int __init uml_mem_setup(char *line, int *add)
-{
-	char *retptr;
-	physmem_size = memparse(line,&retptr);
-	return 0;
-}
-__uml_setup("mem=", uml_mem_setup,
-"mem=<Amount of desired ram>\n"
-"    This controls how much \"physical\" memory the kernel allocates\n"
-"    for the system. The size is specified as a number followed by\n"
-"    one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
-"    This is not related to the amount of memory in the physical\n"
-"    machine. It can be more, and the excess, if it's ever used, will\n"
-"    just be swapped out.\n        Example: mem=64M\n\n"
-);
-
-struct page *arch_validate(struct page *page, int mask, int order)
-{
-	unsigned long addr, zero = 0;
-	int i;
-
- again:
-	if(page == NULL) return(page);
-	if(PageHighMem(page)) return(page);
-
-	addr = (unsigned long) page_address(page);
-	for(i = 0; i < (1 << order); i++){
-		current->thread.fault_addr = (void *) addr;
-		if(__do_copy_to_user((void *) addr, &zero, 
-				     sizeof(zero),
-				     &current->thread.fault_addr,
-				     &current->thread.fault_catcher)){
-			if(!(mask & __GFP_WAIT)) return(NULL);
-			else break;
-		}
-		addr += PAGE_SIZE;
-	}
-	if(i == (1 << order)) return(page);
-	page = alloc_pages(mask, order);
-	goto again;
-}
-
-DECLARE_MUTEX(vm_reserved_sem);
-static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved);
-
-/* Static structures, linked in to the list in early boot */
-static struct vm_reserved head = {
-	.list 		= LIST_HEAD_INIT(head.list),
-	.start 		= 0,
-	.end 		= 0xffffffff
-};
-
-static struct vm_reserved tail = {
-	.list 		= LIST_HEAD_INIT(tail.list),
-	.start 		= 0,
-	.end 		= 0xffffffff
-};
-
-void set_usable_vm(unsigned long start, unsigned long end)
-{
-	list_add(&head.list, &vm_reserved);
-	list_add(&tail.list, &head.list);
-	head.end = start;
-	tail.start = end;
-}
-
-int reserve_vm(unsigned long start, unsigned long end, void *e)
-	       
-{
-	struct vm_reserved *entry = e, *reserved, *prev;
-	struct list_head *ele;
-	int err;
-
-	down(&vm_reserved_sem);
-	list_for_each(ele, &vm_reserved){
-		reserved = list_entry(ele, struct vm_reserved, list);
-		if(reserved->start >= end) goto found;
-	}
-	panic("Reserved vm out of range");
- found:
-	prev = list_entry(ele->prev, struct vm_reserved, list);
-	if(prev->end > start)
-		panic("Can't reserve vm");
-	if(entry == NULL)
-		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-	if(entry == NULL){
-		printk("reserve_vm : Failed to allocate entry\n");
-		err = -ENOMEM;
-		goto out;
-	}
-	*entry = ((struct vm_reserved) 
-		{ .list 	= LIST_HEAD_INIT(entry->list),
-		  .start 	= start,
-		  .end 		= end });
-	list_add(&entry->list, &prev->list);
-	err = 0;
- out:
-	up(&vm_reserved_sem);
-	return(0);
-}
-
-unsigned long get_vm(unsigned long len)
-{
-	struct vm_reserved *this, *next;
-	struct list_head *ele;
-	unsigned long start;
-	int err;
-	
-	down(&vm_reserved_sem);
-	list_for_each(ele, &vm_reserved){
-		this = list_entry(ele, struct vm_reserved, list);
-		next = list_entry(ele->next, struct vm_reserved, list);
-		if((this->start < next->start) && 
-		   (this->end + len + PAGE_SIZE <= next->start))
-			goto found;
-	}
-	up(&vm_reserved_sem);
-	return(0);
- found:
-	up(&vm_reserved_sem);
-	start = (unsigned long) UML_ROUND_UP(this->end) + PAGE_SIZE;
-	err = reserve_vm(start, start + len, NULL);
-	if(err) return(0);
-	return(start);
-}
-
-int nregions(void)
-{
-	return(NREGIONS);
-}
-
-void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn,
-		 unsigned long len, int need_vm, struct mem_region *region, 
-		 void *reserved)
-{
-	int i, cur;
-
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		i = setup_one_range(fd, driver, start, pfn, cur, region);
-		region = regions[i];
-		if(need_vm && setup_region(region, reserved)){
-			kfree(region);
-			regions[i] = NULL;
-			return;
-		}
-		start += cur;
-		if(pfn != -1) pfn += cur;
-		len -= cur;
-	} while(len > 0);
-}
-
-struct iomem {
-	char *name;
-	int fd;
-	unsigned long size;
-};
-
-/* iomem regions can only be added on the command line at the moment.  
- * Locking will be needed when they can be added via mconsole.
- */
-
-struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] =
-					 { .name  	= NULL,
-					   .fd  	= -1,
-					   .size 	= 0 } };
-
-int num_iomem_regions = 0;
-
-void add_iomem(char *name, int fd, unsigned long size)
-{
-	if(num_iomem_regions == sizeof(iomem_regions)/sizeof(iomem_regions[0]))
-		return;
-	size = (size + PAGE_SIZE - 1) & PAGE_MASK;
-	iomem_regions[num_iomem_regions++] = 
-		((struct iomem) { .name 	= name,
-				  .fd 		= fd,
-				  .size 	= size } );
-}
-
-int setup_iomem(void)
-{
-	struct iomem *iomem;
-	int i;
-
-	for(i = 0; i < num_iomem_regions; i++){
-		iomem = &iomem_regions[i];
-		setup_range(iomem->fd, iomem->name, -1, -1, iomem->size, 1, 
-			    NULL, NULL);
-	}
-	return(0);
-}
-
-__initcall(setup_iomem);
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-
-/* Changed during early boot */
-static struct mem_region physmem_region;
-static struct vm_reserved physmem_reserved;
-
-void setup_physmem(unsigned long start, unsigned long reserve_end,
-		   unsigned long len)
-{
-	struct mem_region *region = &physmem_region;
-	struct vm_reserved *reserved = &physmem_reserved;
-	unsigned long cur, pfn = 0;
-	int do_free = 1, bootmap_size;
-
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		if(region == NULL) 
-			region = alloc_bootmem_low_pages(sizeof(*region));
-		if(reserved == NULL) 
-			reserved = alloc_bootmem_low_pages(sizeof(*reserved));
-		if((region == NULL) || (reserved == NULL))
-			panic("Couldn't allocate physmem region or vm "
-			      "reservation\n");
-		setup_range(-1, NULL, start, pfn, cur, 1, region, reserved);
-
-		if(do_free){
-			unsigned long reserve = reserve_end - start;
-			int pfn = PFN_UP(__pa(reserve_end));
-			int delta = (len - reserve) >> PAGE_SHIFT;
-
-			bootmap_size = init_bootmem(pfn, pfn + delta);
-			free_bootmem(__pa(reserve_end) + bootmap_size,
-				     cur - bootmap_size - reserve);
-			do_free = 0;
-		}
-		start += cur;
-		pfn += cur >> PAGE_SHIFT;
-		len -= cur;
-		region = NULL;
-		reserved = NULL;
-	} while(len > 0);
-}
-
-struct mem_region *phys_region(unsigned long phys)
-{
-	unsigned int n = phys_region_index(phys);
-
-	if(regions[n] == NULL) 
-		panic("Physical address in uninitialized region");
-	return(regions[n]);
-}
-
-unsigned long phys_offset(unsigned long phys)
-{
-	return(phys_addr(phys));
-}
-
-struct page *phys_mem_map(unsigned long phys)
-{
-	return((struct page *) phys_region(phys)->mem_map);
-}
-
-struct page *pte_mem_map(pte_t pte)
-{
-	return(phys_mem_map(pte_val(pte)));
-}
-
-struct mem_region *page_region(struct page *page, int *index_out)
-{
-	int i;
-	struct mem_region *region;
-	struct page *map;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		map = region->mem_map;
-		if((page >= map) && (page < &map[region->len >> PAGE_SHIFT])){
-			if(index_out != NULL) *index_out = i;
-			return(region);
-		}
-	}
-	panic("No region found for page");
-	return(NULL);
-}
-
-unsigned long page_to_pfn(struct page *page)
-{
-	struct mem_region *region = page_region(page, NULL);
-
-	return(region->start_pfn + (page - (struct page *) region->mem_map));
-}
-
-struct mem_region *pfn_to_region(unsigned long pfn, int *index_out)
-{
-	struct mem_region *region;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL)
-			continue;
-
-		if((region->start_pfn <= pfn) &&
-		   (region->start_pfn + (region->len >> PAGE_SHIFT) > pfn)){
-			if(index_out != NULL) 
-				*index_out = i;
-			return(region);
-		}
-	}
-	return(NULL);
-}
-
-struct page *pfn_to_page(unsigned long pfn)
-{
-	struct mem_region *region = pfn_to_region(pfn, NULL);
-	struct page *mem_map = (struct page *) region->mem_map;
-
-	return(&mem_map[pfn - region->start_pfn]);
-}
-
-unsigned long phys_to_pfn(unsigned long p)
-{
-	struct mem_region *region = regions[phys_region_index(p)];
-
-	return(region->start_pfn + (phys_addr(p) >> PAGE_SHIFT));
-}
-
-unsigned long pfn_to_phys(unsigned long pfn)
-{
-	int n;
-	struct mem_region *region = pfn_to_region(pfn, &n);
-
-	return(mk_phys((pfn - region->start_pfn) << PAGE_SHIFT, n));
-}
-
-struct page *page_mem_map(struct page *page)
-{
-	return((struct page *) page_region(page, NULL)->mem_map);
-}
-
-extern unsigned long region_pa(void *virt)
-{
-	struct mem_region *region;
-	unsigned long addr = (unsigned long) virt;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		if((region->start <= addr) && 
-		   (addr <= region->start + region->len))
-			return(mk_phys(addr - region->start, i));
-	}
-	panic("region_pa : no region for virtual address");
-	return(0);
-}
-
-extern void *region_va(unsigned long phys)
-{
-	return((void *) (phys_region(phys)->start + phys_addr(phys)));
-}
-
-unsigned long page_to_phys(struct page *page)
-{
-	int n;
-	struct mem_region *region = page_region(page, &n);
-	struct page *map = region->mem_map;
-	return(mk_phys((page - map) << PAGE_SHIFT, n));
-}
-
-struct page *phys_to_page(unsigned long phys)
-{
-	struct page *mem_map;
-
-	mem_map = phys_mem_map(phys);
-	return(mem_map + (phys_offset(phys) >> PAGE_SHIFT));
-}
-
-static int setup_mem_maps(void)
-{
-	struct mem_region *region;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if((region != NULL) && (region->fd > 0)) init_maps(region);
-	}
-	return(0);
-}
-
-__initcall(setup_mem_maps);
-
 /*
  * Allocate and free page tables.
  */
diff -puN arch/um/kernel/mem_user.c~uml-base-patch arch/um/kernel/mem_user.c
--- 25/arch/um/kernel/mem_user.c~uml-base-patch	2004-08-15 20:45:08.387379856 -0700
+++ 25-akpm/arch/um/kernel/mem_user.c	2004-08-15 20:46:03.250039464 -0700
@@ -34,10 +34,9 @@
 #include <stddef.h>
 #include <stdarg.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
-#include <sys/stat.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 #include "kern_util.h"
@@ -47,105 +46,145 @@
 #include "init.h"
 #include "os.h"
 #include "tempfile.h"
+#include "kern_constants.h"
 
 extern struct mem_region physmem_region;
 
 #define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
 
-int create_mem_file(unsigned long len)
+static int create_tmp_file(unsigned long len)
 {
-	int fd;
+	int fd, err;
 	char zero;
 
 	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
-	if (fchmod(fd, 0777) < 0){
-		perror("fchmod");
+	if(fd < 0) {
+		os_print_error(fd, "make_tempfile");
+		exit(1);
+	}
+
+	err = os_mode_fd(fd, 0777);
+	if(err < 0){
+		os_print_error(err, "os_mode_fd");
 		exit(1);
 	}
-	if(os_seek_file(fd, len) < 0){
-		perror("lseek");
+	err = os_seek_file(fd, len);
+	if(err < 0){
+		os_print_error(err, "os_seek_file");
 		exit(1);
 	}
 	zero = 0;
-	if(write(fd, &zero, 1) != 1){
-		perror("write");
+	err = os_write_file(fd, &zero, 1);
+	if(err != 1){
+		os_print_error(err, "os_write_file");
 		exit(1);
 	}
-	if(fcntl(fd, F_SETFD, 1) != 0)
-		perror("Setting FD_CLOEXEC failed");
+
 	return(fd);
 }
 
-int setup_region(struct mem_region *region, void *entry)
+static int have_devanon = 0;
+
+void check_devanon(void)
+{
+	int fd;
+
+	printk("Checking for /dev/anon on the host...");
+	fd = open("/dev/anon", O_RDWR);
+	if(fd < 0){
+		printk("Not available (open failed with errno %d)\n", errno);
+		return;
+	}
+
+	printk("OK\n");
+	have_devanon = 1;
+}
+
+static int create_anon_file(unsigned long len)
 {
-	void *loc, *start;
-	char *driver;
-	int err, offset;
-
-	if(region->start != -1){
-		err = reserve_vm(region->start, 
-				 region->start + region->len, entry);
-		if(err){
-			printk("setup_region : failed to reserve "
-			       "0x%x - 0x%x for driver '%s'\n",
-			       region->start, 
-			       region->start + region->len,
-			       region->driver);
-			return(-1);
-		}
-	}
-	else region->start = get_vm(region->len);
-	if(region->start == 0){
-		if(region->driver == NULL) driver = "physmem";
-		else driver = region->driver;
-		printk("setup_region : failed to find vm for "
-		       "driver '%s' (length %d)\n", driver, region->len);
-		return(-1);
-	}
-	if(region->start == uml_physmem){
-		start = (void *) uml_reserved;
-		offset = uml_reserved - uml_physmem;
-	}
-	else {
-		start = (void *) region->start;
-		offset = 0;
-	}
-
-	loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE, 
-		   MAP_SHARED | MAP_FIXED, region->fd, offset);
-	if(loc != start){
-		perror("Mapping memory");
+	void *addr;
+	int fd;
+
+	fd = open("/dev/anon", O_RDWR);
+	if(fd < 0) {
+		os_print_error(fd, "opening /dev/anon");
 		exit(1);
 	}
-	return(0);
+
+	addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0);
+	if(addr == MAP_FAILED){
+		os_print_error((int) addr, "mapping physmem file");
+		exit(1);
+	}
+	munmap(addr, len);
+
+	return(fd);
+}
+
+int create_mem_file(unsigned long len)
+{
+	int err, fd;
+
+	if(have_devanon)
+		fd = create_anon_file(len);
+	else fd = create_tmp_file(len);
+
+	err = os_set_exec_close(fd, 1);
+	if(err < 0)
+		os_print_error(err, "exec_close");
+	return(fd);
 }
 
+struct iomem_region *iomem_regions = NULL;
+int iomem_size = 0;
+
 static int __init parse_iomem(char *str, int *add)
 {
-	struct stat buf;
+	struct iomem_region *new;
+	struct uml_stat buf;
 	char *file, *driver;
-	int fd;
+	int fd, err;
 
 	driver = str;
 	file = strchr(str,',');
 	if(file == NULL){
-		printk("parse_iomem : failed to parse iomem\n");
-		return(1);
+		printf("parse_iomem : failed to parse iomem\n");
+		goto out;
 	}
 	*file = '\0';
 	file++;
 	fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("parse_iomem - Couldn't open io file, errno = %d\n", 
-		       errno);
-		return(1);
-	}
-	if(fstat(fd, &buf) < 0) {
-		printk("parse_iomem - cannot fstat file, errno = %d\n", errno);
-		return(1);
+		os_print_error(fd, "parse_iomem - Couldn't open io file");
+		goto out;
 	}
-	add_iomem(driver, fd, buf.st_size);
+
+	err = os_stat_fd(fd, &buf);
+	if(err < 0){
+		os_print_error(err, "parse_iomem - cannot stat_fd file");
+		goto out_close;
+	}
+
+	new = malloc(sizeof(*new));
+	if(new == NULL){
+		perror("Couldn't allocate iomem_region struct");
+		goto out_close;
+	}
+
+	*new = ((struct iomem_region) { .next		= iomem_regions,
+					.driver		= driver,
+					.fd		= fd,
+					.size		= buf.ust_size,
+					.phys		= 0,
+					.virt		= 0 });
+	iomem_regions = new;
+	iomem_size += new->size + UM_KERN_PAGE_SIZE;
+
 	return(0);
+ out_close:
+	os_close_file(fd);
+ out:
+	return(1);
 }
 
 __uml_setup("iomem=", parse_iomem,
@@ -153,73 +192,20 @@ __uml_setup("iomem=", parse_iomem,
 "    Configure <file> as an IO memory region named <name>.\n\n"
 );
 
-#ifdef notdef
-int logging = 0;
-int logging_fd = -1;
-
-int logging_line = 0;
-char logging_buf[256];
-
-void log(char *fmt, ...)
-{
-	va_list ap;
-	struct timeval tv;
-	struct openflags flags;
-
-	if(logging == 0) return;
-	if(logging_fd < 0){
-		flags = of_create(of_trunc(of_rdrw(OPENFLAGS())));
-		logging_fd = os_open_file("log", flags, 0644);
-	}
-	gettimeofday(&tv, NULL);
-	sprintf(logging_buf, "%d\t %u.%u  ", logging_line++, tv.tv_sec, 
-		tv.tv_usec);
-	va_start(ap, fmt);
-	vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
-	va_end(ap);
-	write(logging_fd, logging_buf, strlen(logging_buf));
-}
-#endif
-
-int map_memory(unsigned long virt, unsigned long phys, unsigned long len, 
-	       int r, int w, int x)
-{
-	struct mem_region *region = phys_region(phys);
-
-	return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len,
-			     r, w, x));
-}
-
 int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
 		   int must_succeed)
 {
-	if(os_protect_memory((void *) addr, len, r, w, x) < 0){
+	int err;
+
+	err = os_protect_memory((void *) addr, len, r, w, x);
+	if(err < 0){
                 if(must_succeed)
-                        panic("protect failed, errno = %d", errno);
-                else return(-errno);
+			panic("protect failed, err = %d", -err);
+		else return(err);
 	}
 	return(0);
 }
 
-unsigned long find_iomem(char *driver, unsigned long *len_out)
-{
-	struct mem_region *region;
-	int i, n;
-
-	n = nregions();
-	for(i = 0; i < n; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		if((region->driver != NULL) &&
-		   !strcmp(region->driver, driver)){
-			*len_out = region->len;
-			return(region->start);
-		}
-	}
-	*len_out = 0;
-	return 0;
-}
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN /dev/null arch/um/kernel/physmem.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/kernel/physmem.c	2004-08-15 20:46:03.252039160 -0700
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/mm.h"
+#include "linux/ghash.h"
+#include "linux/slab.h"
+#include "linux/vmalloc.h"
+#include "linux/bootmem.h"
+#include "asm/types.h"
+#include "asm/pgtable.h"
+#include "kern_util.h"
+#include "user_util.h"
+#include "mode_kern.h"
+#include "mem.h"
+#include "mem_user.h"
+#include "os.h"
+#include "kern.h"
+#include "init.h"
+
+#if 0
+static pgd_t physmem_pgd[PTRS_PER_PGD];
+
+static struct phys_desc *lookup_mapping(void *addr)
+{
+	pgd = &physmem_pgd[pgd_index(addr)];
+	if(pgd_none(pgd))
+		return(NULL);
+
+	pmd = pmd_offset(pgd, addr);
+	if(pmd_none(pmd))
+		return(NULL);
+
+	pte = pte_offset_kernel(pmd, addr);
+	return((struct phys_desc *) pte_val(pte));
+}
+
+static struct add_mapping(void *addr, struct phys_desc *new)
+{
+}
+#endif
+
+#define PHYS_HASHSIZE (8192)
+
+struct phys_desc;
+
+DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc);
+
+struct phys_desc {
+	struct virtmem_ptrs virt_ptrs;
+	int fd;
+	__u64 offset;
+	void *virt;
+	unsigned long phys;
+	struct list_head list;
+};
+
+struct virtmem_table virtmem_hash;
+
+static int virt_cmp(void *virt1, void *virt2)
+{
+	return(virt1 != virt2);
+}
+
+static int virt_hash(void *virt)
+{
+	unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT;
+	return(addr % PHYS_HASHSIZE);
+}
+
+DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp,
+	 virt_hash);
+
+LIST_HEAD(descriptor_mappings);
+
+struct desc_mapping {
+	int fd;
+	struct list_head list;
+	struct list_head pages;
+};
+
+static struct desc_mapping *find_mapping(int fd)
+{
+	struct desc_mapping *desc;
+	struct list_head *ele;
+
+	list_for_each(ele, &descriptor_mappings){
+		desc = list_entry(ele, struct desc_mapping, list);
+		if(desc->fd == fd)
+			return(desc);
+	}
+
+	return(NULL);
+}
+
+static struct desc_mapping *descriptor_mapping(int fd)
+{
+	struct desc_mapping *desc;
+
+	desc = find_mapping(fd);
+	if(desc != NULL)
+		return(desc);
+
+	desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
+	if(desc == NULL)
+		return(NULL);
+
+	*desc = ((struct desc_mapping)
+		{ .fd =		fd,
+		  .list =	LIST_HEAD_INIT(desc->list),
+		  .pages =	LIST_HEAD_INIT(desc->pages) });
+	list_add(&desc->list, &descriptor_mappings);
+
+	return(desc);
+}
+
+int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
+{
+	struct desc_mapping *fd_maps;
+	struct phys_desc *desc;
+	unsigned long phys;
+	int err;
+
+	fd_maps = descriptor_mapping(fd);
+	if(fd_maps == NULL)
+		return(-ENOMEM);
+
+	phys = __pa(virt);
+	if(find_virtmem_hash(&virtmem_hash, virt) != NULL)
+		panic("Address 0x%p is already substituted\n", virt);
+
+	err = -ENOMEM;
+	desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
+	if(desc == NULL)
+		goto out;
+
+	*desc = ((struct phys_desc)
+		{ .virt_ptrs =	{ NULL, NULL },
+		  .fd =		fd,
+		  .offset =		offset,
+		  .virt =		virt,
+		  .phys =		__pa(virt),
+		  .list = 		LIST_HEAD_INIT(desc->list) });
+	insert_virtmem_hash(&virtmem_hash, desc);
+
+	list_add(&desc->list, &fd_maps->pages);
+
+	virt = (void *) ((unsigned long) virt & PAGE_MASK);
+	err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0);
+	if(!err)
+		goto out;
+
+	remove_virtmem_hash(&virtmem_hash, desc);
+	kfree(desc);
+ out:
+	return(err);
+}
+
+static int physmem_fd = -1;
+
+static void remove_mapping(struct phys_desc *desc)
+{
+	void *virt = desc->virt;
+	int err;
+
+	remove_virtmem_hash(&virtmem_hash, desc);
+	list_del(&desc->list);
+	kfree(desc);
+
+	err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0);
+	if(err)
+		panic("Failed to unmap block device page from physical memory, "
+		      "errno = %d", -err);
+}
+
+int physmem_remove_mapping(void *virt)
+{
+	struct phys_desc *desc;
+
+	virt = (void *) ((unsigned long) virt & PAGE_MASK);
+	desc = find_virtmem_hash(&virtmem_hash, virt);
+	if(desc == NULL)
+		return(0);
+
+	remove_mapping(desc);
+	return(1);
+}
+
+void physmem_forget_descriptor(int fd)
+{
+	struct desc_mapping *desc;
+	struct phys_desc *page;
+	struct list_head *ele, *next;
+	__u64 offset;
+	void *addr;
+	int err;
+
+	desc = find_mapping(fd);
+	if(desc == NULL)
+		return;
+
+	list_for_each_safe(ele, next, &desc->pages){
+		page = list_entry(ele, struct phys_desc, list);
+		offset = page->offset;
+		addr = page->virt;
+		remove_mapping(page);
+		err = os_seek_file(fd, offset);
+		if(err)
+			panic("physmem_forget_descriptor - failed to seek "
+			      "to %lld in fd %d, error = %d\n",
+			      offset, fd, -err);
+		err = os_read_file(fd, addr, PAGE_SIZE);
+		if(err < 0)
+			panic("physmem_forget_descriptor - failed to read "
+			      "from fd %d to 0x%p, error = %d\n",
+			      fd, addr, -err);
+	}
+
+	list_del(&desc->list);
+	kfree(desc);
+}
+
+void arch_free_page(struct page *page, int order)
+{
+	void *virt;
+	int i;
+
+	for(i = 0; i < (1 << order); i++){
+		virt = __va(page_to_phys(page + i));
+		physmem_remove_mapping(virt);
+	}
+}
+
+int is_remapped(void *virt)
+{
+	return(find_virtmem_hash(&virtmem_hash, virt) != NULL);
+}
+
+/* Changed during early boot */
+unsigned long high_physmem;
+
+extern unsigned long physmem_size;
+
+void *to_virt(unsigned long phys)
+{
+	return((void *) uml_physmem + phys);
+}
+
+unsigned long to_phys(void *virt)
+{
+	return(((unsigned long) virt) - uml_physmem);
+}
+
+int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
+{
+	struct page *p, *map;
+	unsigned long phys_len, phys_pages, highmem_len, highmem_pages;
+	unsigned long iomem_len, iomem_pages, total_len, total_pages;
+	int i;
+
+	phys_pages = physmem >> PAGE_SHIFT;
+	phys_len = phys_pages * sizeof(struct page);
+
+	iomem_pages = iomem >> PAGE_SHIFT;
+	iomem_len = iomem_pages * sizeof(struct page);
+
+	highmem_pages = highmem >> PAGE_SHIFT;
+	highmem_len = highmem_pages * sizeof(struct page);
+
+	total_pages = phys_pages + iomem_pages + highmem_pages;
+	total_len = phys_len + iomem_pages + highmem_len;
+
+	if(kmalloc_ok){
+		map = kmalloc(total_len, GFP_KERNEL);
+		if(map == NULL)
+			map = vmalloc(total_len);
+	}
+	else map = alloc_bootmem_low_pages(total_len);
+
+	if(map == NULL)
+		return(-ENOMEM);
+
+	for(i = 0; i < total_pages; i++){
+		p = &map[i];
+		set_page_count(p, 0);
+		SetPageReserved(p);
+		INIT_LIST_HEAD(&p->lru);
+	}
+
+	mem_map = map;
+	max_mapnr = total_pages;
+	return(0);
+}
+
+struct page *phys_to_page(const unsigned long phys)
+{
+	return(&mem_map[phys >> PAGE_SHIFT]);
+}
+
+struct page *__virt_to_page(const unsigned long virt)
+{
+	return(&mem_map[__pa(virt) >> PAGE_SHIFT]);
+}
+
+unsigned long page_to_phys(struct page *page)
+{
+	return((page - mem_map) << PAGE_SHIFT);
+}
+
+pte_t mk_pte(struct page *page, pgprot_t pgprot)
+{
+	pte_t pte;
+
+	pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot);
+	if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte));
+	return(pte);
+}
+
+/* Changed during early boot */
+static unsigned long kmem_top = 0;
+
+unsigned long get_kmem_end(void)
+{
+	if(kmem_top == 0)
+		kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
+	return(kmem_top);
+}
+
+void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
+		int r, int w, int x)
+{
+	__u64 offset;
+	int fd, err;
+
+	fd = phys_mapping(phys, &offset);
+	err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
+	if(err)
+		panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
+		      "err = %d\n", virt, fd, offset, len, r, w, x, err);
+}
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+
+void setup_physmem(unsigned long start, unsigned long reserve_end,
+		   unsigned long len, unsigned long highmem)
+{
+	unsigned long reserve = reserve_end - start;
+	int pfn = PFN_UP(__pa(reserve_end));
+	int delta = (len - reserve) >> PAGE_SHIFT;
+	int err, offset, bootmap_size;
+
+	physmem_fd = create_mem_file(len + highmem);
+
+	offset = uml_reserved - uml_physmem;
+	err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
+			    len - offset, 1, 1, 0);
+	if(err < 0){
+		os_print_error(err, "Mapping memory");
+		exit(1);
+	}
+
+	bootmap_size = init_bootmem(pfn, pfn + delta);
+	free_bootmem(__pa(reserve_end) + bootmap_size,
+		     len - bootmap_size - reserve);
+}
+
+int phys_mapping(unsigned long phys, __u64 *offset_out)
+{
+	struct phys_desc *desc = find_virtmem_hash(&virtmem_hash,
+						   __va(phys & PAGE_MASK));
+	int fd = -1;
+
+	if(desc != NULL){
+		fd = desc->fd;
+		*offset_out = desc->offset;
+	}
+	else if(phys < physmem_size){
+		fd = physmem_fd;
+		*offset_out = phys;
+	}
+	else if(phys < __pa(end_iomem)){
+		struct iomem_region *region = iomem_regions;
+
+		while(region != NULL){
+			if((phys >= region->phys) &&
+			   (phys < region->phys + region->size)){
+				fd = region->fd;
+				*offset_out = phys - region->phys;
+				break;
+			}
+			region = region->next;
+		}
+	}
+	else if(phys < __pa(end_iomem) + highmem){
+		fd = physmem_fd;
+		*offset_out = phys - iomem_size;
+	}
+
+	return(fd);
+}
+
+static int __init uml_mem_setup(char *line, int *add)
+{
+	char *retptr;
+	physmem_size = memparse(line,&retptr);
+	return 0;
+}
+__uml_setup("mem=", uml_mem_setup,
+"mem=<Amount of desired ram>\n"
+"    This controls how much \"physical\" memory the kernel allocates\n"
+"    for the system. The size is specified as a number followed by\n"
+"    one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
+"    This is not related to the amount of memory in the host.  It can\n"
+"    be more, and the excess, if it's ever used, will just be swapped out.\n"
+"	Example: mem=64M\n\n"
+);
+
+unsigned long find_iomem(char *driver, unsigned long *len_out)
+{
+	struct iomem_region *region = iomem_regions;
+
+	while(region != NULL){
+		if(!strcmp(region->driver, driver)){
+			*len_out = region->size;
+			return(region->virt);
+		}
+	}
+
+	return(0);
+}
+
+int setup_iomem(void)
+{
+	struct iomem_region *region = iomem_regions;
+	unsigned long iomem_start = high_physmem + PAGE_SIZE;
+	int err;
+
+	while(region != NULL){
+		err = os_map_memory((void *) iomem_start, region->fd, 0,
+				    region->size, 1, 1, 0);
+		if(err)
+			printk("Mapping iomem region for driver '%s' failed, "
+			       "errno = %d\n", region->driver, -err);
+		else {
+			region->virt = iomem_start;
+			region->phys = __pa(region->virt);
+		}
+
+		iomem_start += region->size + PAGE_SIZE;
+		region = region->next;
+	}
+
+	return(0);
+}
+
+__initcall(setup_iomem);
+
+/*
+ * 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 -puN arch/um/kernel/process.c~uml-base-patch arch/um/kernel/process.c
--- 25/arch/um/kernel/process.c~uml-base-patch	2004-08-15 20:45:08.389379552 -0700
+++ 25-akpm/arch/um/kernel/process.c	2004-08-15 20:46:03.253039008 -0700
@@ -9,12 +9,10 @@
 #include <sched.h>
 #include <errno.h>
 #include <stdarg.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <setjmp.h>
 #include <sys/time.h>
 #include <sys/ptrace.h>
-#include <sys/ioctl.h>
 #include <sys/wait.h>
 #include <sys/mman.h>
 #include <asm/ptrace.h>
@@ -58,7 +56,11 @@ void init_new_thread_signals(int altstac
 {
 	int flags = altstack ? SA_ONSTACK : 0;
 
-	set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+	/* NODEFER is set here because SEGV isn't turned back on when the
+	 * handler is ready to receive signals.  This causes any segfault
+	 * during a copy_user to kill the process because the fault is blocked.
+	 */
+	set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags | SA_NODEFER,
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, 
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
@@ -72,7 +74,6 @@ void init_new_thread_signals(int altstac
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGUSR2, (__sighandler_t) sig_handler, 
 		    SA_NOMASK | flags, -1);
-	(void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0);
 	signal(SIGHUP, SIG_IGN);
 
 	init_irq_signals(altstack);
@@ -123,11 +124,12 @@ int start_fork_tramp(void *thread_arg, u
 	/* Start the process and wait for it to kill itself */
 	new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg);
 	if(new_pid < 0) return(-errno);
-	while((err = waitpid(new_pid, &status, 0) < 0) && (errno == EINTR)) ;
+	while(((err = waitpid(new_pid, &status, 0)) < 0) && (errno == EINTR)) ;
 	if(err < 0) panic("Waiting for outer trampoline failed - errno = %d", 
 			  errno);
 	if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
-		panic("outer trampoline didn't exit with SIGKILL");
+		panic("outer trampoline didn't exit with SIGKILL, "
+		      "status = %d", status);
 
 	return(arg.pid);
 }
@@ -138,7 +140,7 @@ void suspend_new_thread(int fd)
 
 	os_stop_process(os_getpid());
 
-	if(read(fd, &c, sizeof(c)) != sizeof(c))
+	if(os_read_file(fd, &c, sizeof(c)) != sizeof(c))
 		panic("read failed in suspend_new_thread");
 }
 
@@ -233,7 +235,7 @@ int run_kernel_thread(int (*fn)(void *),
 	int n;
 
 	*jmp_ptr = &buf;
-	n = setjmp(buf);
+	n = sigsetjmp(buf, 1);
 	if(n != 0)
 		return(n);
 	(*fn)(arg);
@@ -273,7 +275,7 @@ int can_do_skas(void)
 	stop_ptraced_child(pid, stack, 1);
 
 	printf("Checking for /proc/mm...");
-	if(access("/proc/mm", W_OK)){
+	if(os_access("/proc/mm", OS_ACC_W_OK) < 0){
 		printf("not found\n");
 		ret = 0;
 	}
diff -puN arch/um/kernel/process_kern.c~uml-base-patch arch/um/kernel/process_kern.c
--- 25/arch/um/kernel/process_kern.c~uml-base-patch	2004-08-15 20:45:08.390379400 -0700
+++ 25-akpm/arch/um/kernel/process_kern.c	2004-08-15 20:46:03.254038856 -0700
@@ -16,6 +16,7 @@
 #include "linux/module.h"
 #include "linux/init.h"
 #include "linux/capability.h"
+#include "linux/spinlock.h"
 #include "asm/unistd.h"
 #include "asm/mman.h"
 #include "asm/segment.h"
@@ -23,7 +24,6 @@
 #include "asm/pgtable.h"
 #include "asm/processor.h"
 #include "asm/tlbflush.h"
-#include "asm/spinlock.h"
 #include "asm/uaccess.h"
 #include "asm/user.h"
 #include "user_util.h"
@@ -52,17 +52,12 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [
 
 struct task_struct *get_task(int pid, int require)
 {
-        struct task_struct *task, *ret;
+        struct task_struct *ret;
 
-        ret = NULL;
         read_lock(&tasklist_lock);
-        for_each_process(task){
-                if(task->pid == pid){
-                        ret = task;
-                        break;
-                }
-        }
+	ret = find_task_by_pid(pid);
         read_unlock(&tasklist_lock);
+
         if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
         return(ret);
 }
@@ -95,7 +90,8 @@ unsigned long alloc_stack(int order, int
 	int flags = GFP_KERNEL;
 
 	if(atomic) flags |= GFP_ATOMIC;
-	if((page = __get_free_pages(flags, order)) == 0)
+	page = __get_free_pages(flags, order);
+	if(page == 0)
 		return(0);
 	stack_protections(page);
 	return(page);
@@ -103,13 +99,15 @@ unsigned long alloc_stack(int order, int
 
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-	struct task_struct *p;
+	int pid;
 
 	current->thread.request.u.thread.proc = fn;
 	current->thread.request.u.thread.arg = arg;
-	p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
-	if(IS_ERR(p)) panic("do_fork failed in kernel_thread");
-	return(p->pid);
+	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL,
+		      NULL);
+	if(pid < 0)
+		panic("do_fork failed in kernel_thread, errno = %d", pid);
+	return(pid);
 }
 
 void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
@@ -129,7 +127,7 @@ void set_current(void *t)
 		{ external_pid(task), task });
 }
 
-void *switch_to(void *prev, void *next, void *last)
+void *_switch_to(void *prev, void *next, void *last)
 {
 	return(CHOOSE_MODE(switch_to_tt(prev, next), 
 			   switch_to_skas(prev, next)));
@@ -149,7 +147,7 @@ void release_thread(struct task_struct *
 void exit_thread(void)
 {
 	CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
-	unprotect_stack((unsigned long) current->thread_info);
+	unprotect_stack((unsigned long) current_thread);
 }
  
 void *get_current(void)
@@ -157,6 +155,10 @@ void *get_current(void)
 	return(current);
 }
 
+void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
 		unsigned long stack_top, struct task_struct * p, 
 		struct pt_regs *regs)
@@ -190,7 +192,7 @@ int current_pid(void)
 
 void default_idle(void)
 {
-	idle_timer();
+	uml_idle_timer();
 
 	atomic_inc(&init_mm.mm_count);
 	current->mm = &init_mm;
@@ -367,10 +369,15 @@ int clear_user_proc(void *buf, int size)
 	return(clear_user(buf, size));
 }
 
+int strlen_user_proc(char *str)
+{
+	return(strlen_user(str));
+}
+
 int smp_sigio_handler(void)
 {
 #ifdef CONFIG_SMP
-	int cpu = current->thread_info->cpu;
+	int cpu = current_thread->cpu;
 	IPI_handler(cpu);
 	if(cpu != 0)
 		return(1);
@@ -385,7 +392,7 @@ int um_in_interrupt(void)
 
 int cpu(void)
 {
-	return(current->thread_info->cpu);
+	return(current_thread->cpu);
 }
 
 /*
diff -puN arch/um/kernel/ptrace.c~uml-base-patch arch/um/kernel/ptrace.c
--- 25/arch/um/kernel/ptrace.c~uml-base-patch	2004-08-15 20:45:08.391379248 -0700
+++ 25-akpm/arch/um/kernel/ptrace.c	2004-08-15 20:46:03.255038704 -0700
@@ -24,11 +24,6 @@ void ptrace_disable(struct task_struct *
 { 
 }
 
-extern long do_mmap2(struct task_struct *task, unsigned long addr, 
-		     unsigned long len, unsigned long prot, 
-		     unsigned long flags, unsigned long fd,
-		     unsigned long pgoff);
-
 int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -302,8 +297,17 @@ int sys_ptrace(long request, long pid, l
 	return ret;
 }
 
-void syscall_trace(void)
+void syscall_trace(union uml_pt_regs *regs, int entryexit)
 {
+	if (unlikely(current->audit_context)) {
+		if (!entryexit)
+			audit_syscall_entry(current, regs->orig_eax,
+					    regs->ebx, regs->ecx,
+					    regs->edx, regs->esi);
+		else
+			audit_syscall_exit(current, regs->eax);
+	}
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return;
 	if (!(current->ptrace & PT_PTRACED))
@@ -311,11 +315,8 @@ void syscall_trace(void)
 
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
- 	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- 					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
diff -puN arch/um/kernel/reboot.c~uml-base-patch arch/um/kernel/reboot.c
--- 25/arch/um/kernel/reboot.c~uml-base-patch	2004-08-15 20:45:08.393378944 -0700
+++ 25-akpm/arch/um/kernel/reboot.c	2004-08-15 20:46:03.255038704 -0700
@@ -15,6 +15,7 @@
 #ifdef CONFIG_SMP
 static void kill_idlers(int me)
 {
+#ifdef CONFIG_MODE_TT
 	struct task_struct *p;
 	int i;
 
@@ -23,6 +24,7 @@ static void kill_idlers(int me)
 		if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
 			os_kill_process(p->thread.mode.tt.extern_pid, 0);
 	}
+#endif
 }
 #endif
 
diff -puN arch/um/kernel/sigio_kern.c~uml-base-patch arch/um/kernel/sigio_kern.c
--- 25/arch/um/kernel/sigio_kern.c~uml-base-patch	2004-08-15 20:45:08.395378640 -0700
+++ 25-akpm/arch/um/kernel/sigio_kern.c	2004-08-15 20:46:03.255038704 -0700
@@ -6,18 +6,21 @@
 #include "linux/kernel.h"
 #include "linux/list.h"
 #include "linux/slab.h"
-#include "asm/irq.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
 #include "init.h"
 #include "sigio.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 /* Protected by sigio_lock() called from write_sigio_workaround */
 static int sigio_irq_fd = -1;
 
-void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	read_sigio_fd(sigio_irq_fd);
 	reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
+	return(IRQ_HANDLED);
 }
 
 int write_sigio_irq(int fd)
diff -puN arch/um/kernel/sigio_user.c~uml-base-patch arch/um/kernel/sigio_user.c
--- 25/arch/um/kernel/sigio_user.c~uml-base-patch	2004-08-15 20:45:08.396378488 -0700
+++ 25-akpm/arch/um/kernel/sigio_user.c	2004-08-15 20:46:03.257038400 -0700
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <termios.h>
 #include <pty.h>
-#include <fcntl.h>
 #include <signal.h>
 #include <errno.h>
 #include <string.h>
@@ -26,7 +25,7 @@ int pty_output_sigio = 0;
 int pty_close_sigio = 0;
 
 /* Used as a flag during SIGIO testing early in boot */
-static int got_sigio = 0;
+static volatile int got_sigio = 0;
 
 void __init handler(int sig)
 {
@@ -45,7 +44,7 @@ static void openpty_cb(void *arg)
 
 	info->err = 0;
 	if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
-		info->err = errno;
+		info->err = -errno;
 }
 
 void __init check_one_sigio(void (*proc)(int, int))
@@ -53,11 +52,11 @@ void __init check_one_sigio(void (*proc)
 	struct sigaction old, new;
 	struct termios tt;
 	struct openpty_arg pty = { .master = -1, .slave = -1 };
-	int master, slave, flags;
+	int master, slave, err;
 
 	initial_thread_cb(openpty_cb, &pty);
 	if(pty.err){
-		printk("openpty failed, errno = %d\n", pty.err);
+		printk("openpty failed, errno = %d\n", -pty.err);
 		return;
 	}
 
@@ -69,23 +68,16 @@ void __init check_one_sigio(void (*proc)
 		return;
 	}
 
+	/* XXX These can fail with EINTR */
 	if(tcgetattr(master, &tt) < 0)
 		panic("check_sigio : tcgetattr failed, errno = %d\n", errno);
 	cfmakeraw(&tt);
 	if(tcsetattr(master, TCSADRAIN, &tt) < 0)
 		panic("check_sigio : tcsetattr failed, errno = %d\n", errno);
 
-	if((flags = fcntl(master, F_GETFL)) < 0)
-		panic("tty_fds : fcntl F_GETFL failed, errno = %d\n", errno);
-
-	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
-	   (fcntl(master, F_SETOWN, os_getpid()) < 0))
-		panic("check_sigio : fcntl F_SETFL or F_SETOWN failed, "
-		      "errno = %d\n", errno);
-
-	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
-		panic("check_sigio : fcntl F_SETFL failed, errno = %d\n", 
-		      errno);
+	err = os_sigio_async(master, slave);
+	if(err < 0)
+		panic("tty_fds : sigio_async failed, err = %d\n", -err);
 
 	if(sigaction(SIGIO, NULL, &old) < 0)
 		panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
@@ -97,8 +89,8 @@ void __init check_one_sigio(void (*proc)
 	got_sigio = 0;
 	(*proc)(master, slave);
 		
-	close(master);
-	close(slave);
+	os_close_file(master);
+	os_close_file(slave);
 
 	if(sigaction(SIGIO, &old, NULL) < 0)
 		panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
@@ -112,25 +104,25 @@ static void tty_output(int master, int s
 	printk("Checking that host ptys support output SIGIO...");
 
 	memset(buf, 0, sizeof(buf));
-	while(write(master, buf, sizeof(buf)) > 0) ;
+
+	while(os_write_file(master, buf, sizeof(buf)) > 0) ;
 	if(errno != EAGAIN)
 		panic("check_sigio : write failed, errno = %d\n", errno);
-
-	while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+	while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
 
 	if(got_sigio){
 		printk("Yes\n");
 		pty_output_sigio = 1;
 	}
-	else if(errno == EAGAIN) printk("No, enabling workaround\n");
-	else panic("check_sigio : read failed, errno = %d\n", errno);
+	else if(n == -EAGAIN) printk("No, enabling workaround\n");
+	else panic("check_sigio : read failed, err = %d\n", n);
 }
 
 static void tty_close(int master, int slave)
 {
 	printk("Checking that host ptys support SIGIO on close...");
 
-	close(slave);
+	os_close_file(slave);
 	if(got_sigio){
 		printk("Yes\n");
 		pty_close_sigio = 1;
@@ -140,7 +132,8 @@ static void tty_close(int master, int sl
 
 void __init check_sigio(void)
 {
-	if(access("/dev/ptmx", R_OK) && access("/dev/ptyp0", R_OK)){
+	if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
+	   (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
 		printk("No pseudo-terminals available - skipping pty SIGIO "
 		       "check\n");
 		return;
@@ -201,11 +194,10 @@ static int write_sigio_thread(void *unus
 			p = &fds->poll[i];
 			if(p->revents == 0) continue;
 			if(p->fd == sigio_private[1]){
-				n = read(sigio_private[1], &c, sizeof(c));
+				n = os_read_file(sigio_private[1], &c, sizeof(c));
 				if(n != sizeof(c))
 					printk("write_sigio_thread : "
-					       "read failed, errno = %d\n",
-					       errno);
+					       "read failed, err = %d\n", -n);
 				tmp = current_poll;
 				current_poll = next_poll;
 				next_poll = tmp;
@@ -218,10 +210,10 @@ static int write_sigio_thread(void *unus
 					(fds->used - i) * sizeof(*fds->poll));
 			}
 
-			n = write(respond_fd, &c, sizeof(c));
+			n = os_write_file(respond_fd, &c, sizeof(c));
 			if(n != sizeof(c))
 				printk("write_sigio_thread : write failed, "
-				       "errno = %d\n", errno);
+				       "err = %d\n", -n);
 		}
 	}
 }
@@ -252,15 +244,15 @@ static void update_thread(void)
 	char c;
 
 	flags = set_signals(0);
-	n = write(sigio_private[0], &c, sizeof(c));
+	n = os_write_file(sigio_private[0], &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("update_thread : write failed, errno = %d\n", errno);
+		printk("update_thread : write failed, err = %d\n", -n);
 		goto fail;
 	}
 
-	n = read(sigio_private[0], &c, sizeof(c));
+	n = os_read_file(sigio_private[0], &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("update_thread : read failed, errno = %d\n", errno);
+		printk("update_thread : read failed, err = %d\n", -n);
 		goto fail;
 	}
 
@@ -271,10 +263,10 @@ static void update_thread(void)
 	if(write_sigio_pid != -1) 
 		os_kill_process(write_sigio_pid, 1);
 	write_sigio_pid = -1;
-	close(sigio_private[0]);
-	close(sigio_private[1]);	
-	close(write_sigio_fds[0]);
-	close(write_sigio_fds[1]);
+	os_close_file(sigio_private[0]);
+	os_close_file(sigio_private[1]);
+	os_close_file(write_sigio_fds[0]);
+	os_close_file(write_sigio_fds[1]);
 	sigio_unlock();
 	set_signals(flags);
 }
@@ -369,15 +361,15 @@ void write_sigio_workaround(void)
 		goto out;
 
 	err = os_pipe(write_sigio_fds, 1, 1);
-	if(err){
+	if(err < 0){
 		printk("write_sigio_workaround - os_pipe 1 failed, "
-		       "errno = %d\n", -err);
+		       "err = %d\n", -err);
 		goto out;
 	}
 	err = os_pipe(sigio_private, 1, 1);
-	if(err){
+	if(err < 0){
 		printk("write_sigio_workaround - os_pipe 2 failed, "
-		       "errno = %d\n", -err);
+		       "err = %d\n", -err);
 		goto out_close1;
 	}
 	if(setup_initial_poll(sigio_private[1]))
@@ -399,11 +391,11 @@ void write_sigio_workaround(void)
 	os_kill_process(write_sigio_pid, 1);
 	write_sigio_pid = -1;
  out_close2:
-	close(sigio_private[0]);
-	close(sigio_private[1]);	
+	os_close_file(sigio_private[0]);
+	os_close_file(sigio_private[1]);
  out_close1:
-	close(write_sigio_fds[0]);
-	close(write_sigio_fds[1]);
+	os_close_file(write_sigio_fds[0]);
+	os_close_file(write_sigio_fds[1]);
 	sigio_unlock();
 }
 
@@ -412,10 +404,16 @@ int read_sigio_fd(int fd)
 	int n;
 	char c;
 
-	n = read(fd, &c, sizeof(c));
+	n = os_read_file(fd, &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("read_sigio_fd - read failed, errno = %d\n", errno);
-		return(-errno);
+		if(n < 0) {
+			printk("read_sigio_fd - read failed, err = %d\n", -n);
+			return(n);
+		}
+		else {
+			printk("read_sigio_fd - short read, bytes = %d\n", n);
+			return(-EIO);
+		}
 	}
 	return(n);
 }
diff -puN arch/um/kernel/signal_kern.c~uml-base-patch arch/um/kernel/signal_kern.c
--- 25/arch/um/kernel/signal_kern.c~uml-base-patch	2004-08-15 20:45:08.397378336 -0700
+++ 25-akpm/arch/um/kernel/signal_kern.c	2004-08-15 20:46:03.258038248 -0700
@@ -36,7 +36,7 @@ static void force_segv(int sig)
 	if(sig == SIGSEGV){
 		struct k_sigaction *ka;
 
-		ka = &current->sig->action[SIGSEGV - 1];
+		ka = &current->sighand->action[SIGSEGV - 1];
 		ka->sa.sa_handler = SIG_DFL;
 	}
 	force_sig(SIGSEGV, current);
@@ -60,10 +60,10 @@ static int handle_signal(struct pt_regs 
 	int err, ret;
 
 	ret = 0;
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 	switch(error){
 	case -ERESTART_RESTARTBLOCK:
-		current_thread_info()->restart_block.fn = 
-			do_no_restart_syscall;
 	case -ERESTARTNOHAND:
 		ret = -EINTR;
 		break;
@@ -142,7 +142,7 @@ static int kern_do_signal(struct pt_regs
 		return(0);
 
 	/* Whee!  Actually deliver the signal.  */
-	ka = &current->sig->action[sig -1 ];
+	ka = &current->sighand->action[sig -1 ];
 	err = handle_signal(regs, sig, ka, &info, oldset, error);
 	if(!err) return(1);
 
@@ -201,7 +201,7 @@ int sys_sigsuspend(int history0, int his
 	}
 }
 
-int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
+int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 {
 	sigset_t saveset, newset;
 
@@ -227,20 +227,59 @@ int sys_rt_sigsuspend(sigset_t *unewset,
 	}
 }
 
+int sys_sigaction(int sig, const struct old_sigaction __user *act,
+			 struct old_sigaction __user *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
+}
+
+extern int userspace_pid[];
+
 static int copy_sc_from_user(struct pt_regs *to, void *from, 
 			     struct arch_frame_data *arch)
 {
 	int ret;
 
 	ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
-			  copy_sc_from_user_skas(&to->regs, from));
+			  copy_sc_from_user_skas(userspace_pid[0],
+						 &to->regs, from));
 	return(ret);
 }
 
 int sys_sigreturn(struct pt_regs regs)
 {
-	void *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
-	void *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
+	void __user *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
+	void __user *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
 	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -257,8 +296,8 @@ int sys_sigreturn(struct pt_regs regs)
 
 int sys_rt_sigreturn(struct pt_regs regs)
 {
-	struct ucontext *uc = sp_to_uc(PT_REGS_SP(&current->thread.regs));
-	void *fp;
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct ucontext __user *uc = sp_to_uc(sp);
 	int sig_size = _NSIG_WORDS * sizeof(unsigned long);
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -266,7 +305,6 @@ int sys_rt_sigreturn(struct pt_regs regs
 	sigdelsetmask(&current->blocked, ~_BLOCKABLE);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
-	fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext));
 	copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
 			  &signal_frame_si.common.arch);
 	return(PT_REGS_SYSCALL_RET(&current->thread.regs));
diff -puN arch/um/kernel/skas/include/mode.h~uml-base-patch arch/um/kernel/skas/include/mode.h
--- 25/arch/um/kernel/skas/include/mode.h~uml-base-patch	2004-08-15 20:45:08.399378032 -0700
+++ 25-akpm/arch/um/kernel/skas/include/mode.h	2004-08-15 20:46:03.258038248 -0700
@@ -12,14 +12,16 @@ extern unsigned long exec_fpx_regs[];
 extern int have_fpx_regs;
 
 extern void user_time_init_skas(void);
-extern int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr);
-extern int copy_sc_to_user_skas(void *to_ptr, void *fp, 
+extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs,
+				  void *from_ptr);
+extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
 				union uml_pt_regs *regs, 
 				unsigned long fault_addr, int fault_type);
 extern void sig_handler_common_skas(int sig, void *sc_ptr);
 extern void halt_skas(void);
 extern void reboot_skas(void);
 extern void kill_off_processes_skas(void);
+extern int is_skas_winch(int pid, int fd, void *data);
 
 #endif
 
diff -puN arch/um/kernel/skas/include/skas.h~uml-base-patch arch/um/kernel/skas/include/skas.h
--- 25/arch/um/kernel/skas/include/skas.h~uml-base-patch	2004-08-15 20:45:08.400377880 -0700
+++ 25-akpm/arch/um/kernel/skas/include/skas.h	2004-08-15 20:46:03.259038096 -0700
@@ -8,7 +8,7 @@
 
 #include "sysdep/ptrace.h"
 
-extern int userspace_pid;
+extern int userspace_pid[];
 
 extern void switch_threads(void *me, void *next);
 extern void thread_wait(void *sw, void *fb);
@@ -32,7 +32,7 @@ extern int singlestepping_skas(void);
 extern int new_mm(int from);
 extern void save_registers(union uml_pt_regs *regs);
 extern void restore_registers(union uml_pt_regs *regs);
-extern void start_userspace(void);
+extern void start_userspace(int cpu);
 extern void init_registers(int pid);
 
 #endif
diff -puN arch/um/kernel/skas/include/uaccess.h~uml-base-patch arch/um/kernel/skas/include/uaccess.h
--- 25/arch/um/kernel/skas/include/uaccess.h~uml-base-patch	2004-08-15 20:45:08.401377728 -0700
+++ 25-akpm/arch/um/kernel/skas/include/uaccess.h	2004-08-15 20:46:03.260037944 -0700
@@ -6,20 +6,12 @@
 #ifndef __SKAS_UACCESS_H
 #define __SKAS_UACCESS_H
 
-#include "linux/string.h"
-#include "linux/sched.h"
-#include "linux/err.h"
-#include "asm/processor.h"
-#include "asm/pgtable.h"
 #include "asm/errno.h"
-#include "asm/current.h"
-#include "asm/a.out.h"
-#include "kern_util.h"
 
 #define access_ok_skas(type, addr, size) \
 	((segment_eq(get_fs(), KERNEL_DS)) || \
 	 (((unsigned long) (addr) < TASK_SIZE) && \
-	  ((unsigned long) (addr) + (size) < TASK_SIZE)))
+	  ((unsigned long) (addr) + (size) <= TASK_SIZE)))
 
 static inline int verify_area_skas(int type, const void * addr, 
 				   unsigned long size)
@@ -27,197 +19,12 @@ static inline int verify_area_skas(int t
 	return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
 }
 
-static inline unsigned long maybe_map(unsigned long virt, int is_write)
-{
-	pte_t pte;
-
-	void *phys = um_virt_to_phys(current, virt, &pte);
-	int dummy_code;
-
-	if(IS_ERR(phys) || (is_write && !pte_write(pte))){
-		if(handle_page_fault(virt, 0, is_write, 0, &dummy_code))
-			return(0);
-		phys = um_virt_to_phys(current, virt, NULL);
-	}
-	return((unsigned long) __va((unsigned long) phys));
-}
-
-static inline int buffer_op(unsigned long addr, int len, 
-			    int (*op)(unsigned long addr, int len, void *arg),
-			    void *arg)
-{
-	int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
-	int remain = len, n;
-
-	n = (*op)(addr, size, arg);
-	if(n != 0)
-		return(n < 0 ? remain : 0);
-
-	addr += size;
-	remain -= size;
-	if(remain == 0) 
-		return(0);
-
-	while(addr < ((addr + remain) & PAGE_MASK)){
-		n = (*op)(addr, PAGE_SIZE, arg);
-		if(n != 0)
-			return(n < 0 ? remain : 0);
-
-		addr += PAGE_SIZE;
-		remain -= PAGE_SIZE;
-	}
-	if(remain == 0)
-		return(0);
-
-	n = (*op)(addr, remain, arg);
-	if(n != 0)
-		return(n < 0 ? remain : 0);
-	return(0);
-}
-
-static inline int copy_chunk_from_user(unsigned long from, int len, void *arg)
-{
-	unsigned long *to_ptr = arg, to = *to_ptr;
-
-	from = maybe_map(from, 0);
-	if(from == 0)
-		return(-1);
-
-	memcpy((void *) to, (void *) from, len);
-	*to_ptr += len;
-	return(0);
-}
-
-static inline int copy_from_user_skas(void *to, const void *from, int n)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memcpy(to, from, n);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_READ, from, n) ?
-	       buffer_op((unsigned long) from, n, copy_chunk_from_user, &to) :
-	       n);
-}
-
-static inline int copy_chunk_to_user(unsigned long to, int len, void *arg)
-{
-	unsigned long *from_ptr = arg, from = *from_ptr;
-
-	to = maybe_map(to, 1);
-	if(to == 0)
-		return(-1);
-
-	memcpy((void *) to, (void *) from, len);
-	*from_ptr += len;
-	return(0);
-}
-
-static inline int copy_to_user_skas(void *to, const void *from, int n)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memcpy(to, from, n);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_WRITE, to, n) ?
-	       buffer_op((unsigned long) to, n, copy_chunk_to_user, &from) :
-	       n);
-}
-
-static inline int strncpy_chunk_from_user(unsigned long from, int len, 
-					  void *arg)
-{
-        char **to_ptr = arg, *to = *to_ptr;
-	int n;
-
-	from = maybe_map(from, 0);
-	if(from == 0)
-		return(-1);
-
-	strncpy(to, (void *) from, len);
-	n = strnlen(to, len);
-	*to_ptr += n;
-
-	if(n < len) 
-	        return(1);
-	return(0);
-}
-
-static inline int strncpy_from_user_skas(char *dst, const char *src, int count)
-{
-	int n;
-	char *ptr = dst;
-
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		strncpy(dst, src, count);
-		return(strnlen(dst, count));
-	}
-
-	if(!access_ok_skas(VERIFY_READ, src, 1))
-		return(-EFAULT);
-
-	n = buffer_op((unsigned long) src, count, strncpy_chunk_from_user, 
-		      &ptr);
-	if(n != 0)
-		return(-EFAULT);
-	return(strnlen(dst, count));
-}
-
-static inline int clear_chunk(unsigned long addr, int len, void *unused)
-{
-	addr = maybe_map(addr, 1);
-	if(addr == 0) 
-		return(-1);
-
-	memset((void *) addr, 0, len);
-	return(0);
-}
-
-static inline int __clear_user_skas(void *mem, int len)
-{
-	return(buffer_op((unsigned long) mem, len, clear_chunk, NULL));
-}
-
-static inline int clear_user_skas(void *mem, int len)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memset(mem, 0, len);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_WRITE, mem, len) ? 
-	       buffer_op((unsigned long) mem, len, clear_chunk, NULL) : len);
-}
-
-static inline int strnlen_chunk(unsigned long str, int len, void *arg)
-{
-	int *len_ptr = arg, n;
-
-	str = maybe_map(str, 0);
-	if(str == 0) 
-		return(-1);
-
-	n = strnlen((void *) str, len);
-	*len_ptr += n;
-
-	if(n < len)
-		return(1);
-	return(0);
-}
-
-static inline int strnlen_user_skas(const void *str, int len)
-{
-	int count = 0, n;
-
-	if(segment_eq(get_fs(), KERNEL_DS))
-		return(strnlen(str, len) + 1);
-
-	n = buffer_op((unsigned long) str, len, strnlen_chunk, &count);
-	if(n == 0)
-		return(count + 1);
-	return(-EFAULT);
-}
+extern int copy_from_user_skas(void *to, const void *from, int n);
+extern int copy_to_user_skas(void *to, const void *from, int n);
+extern int strncpy_from_user_skas(char *dst, const char *src, int count);
+extern int __clear_user_skas(void *mem, int len);
+extern int clear_user_skas(void *mem, int len);
+extern int strnlen_user_skas(const void *str, int len);
 
 #endif
 
diff -puN arch/um/kernel/skas/Makefile~uml-base-patch arch/um/kernel/skas/Makefile
--- 25/arch/um/kernel/skas/Makefile~uml-base-patch	2004-08-15 20:45:08.403377424 -0700
+++ 25-akpm/arch/um/kernel/skas/Makefile	2004-08-15 20:46:03.260037944 -0700
@@ -5,20 +5,24 @@
 
 obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \
 	process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \
-	sys-$(SUBARCH)/
+	uaccess.o sys-$(SUBARCH)/
+
+host-progs	:= util/mk_ptregs
+clean-files	:= include/skas_ptregs.h
 
 USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-include/skas_ptregs.h : util/mk_ptregs
-	util/mk_ptregs > $@
-
-util/mk_ptregs :
-	$(MAKE) -C util
+$(TOPDIR)/arch/um/include/skas_ptregs.h : $(src)/util/mk_ptregs
+	@echo -n '  Generating $@'
+	@$< > $@.tmp
+	@if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+		echo ' (unchanged)'; \
+		rm -f $@.tmp; \
+	else \
+		echo ' (updated)'; \
+		mv -f $@.tmp $@; \
+	fi
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-	$(MAKE) -C util clean
-	$(RM) -f include/skas_ptregs.h
diff -puN arch/um/kernel/skas/mem_user.c~uml-base-patch arch/um/kernel/skas/mem_user.c
--- 25/arch/um/kernel/skas/mem_user.c~uml-base-patch	2004-08-15 20:45:08.404377272 -0700
+++ 25-akpm/arch/um/kernel/skas/mem_user.c	2004-08-15 20:46:03.261037792 -0700
@@ -7,6 +7,7 @@
 #include <sys/mman.h>
 #include <sys/ptrace.h>
 #include "mem_user.h"
+#include "mem.h"
 #include "user.h"
 #include "os.h"
 #include "proc_mm.h"
@@ -15,12 +16,12 @@ void map(int fd, unsigned long virt, uns
 	 int r, int w, int x)
 {
 	struct proc_mm_op map;
-	struct mem_region *region;
-	int prot, n;
+	__u64 offset;
+	int prot, n, phys_fd;
 
 	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
 		(x ? PROT_EXEC : 0);
-	region = phys_region(phys);
+	phys_fd = phys_mapping(phys, &offset);
 
 	map = ((struct proc_mm_op) { .op 	= MM_MMAP,
 				     .u 	= 
@@ -30,12 +31,12 @@ void map(int fd, unsigned long virt, uns
 					 .prot		= prot,
 					 .flags		= MAP_SHARED | 
 					                  MAP_FIXED,
-					 .fd		= region->fd,
-					 .offset	= phys_offset(phys)
+					 .fd		= phys_fd,
+					 .offset	= offset
 				       } } } );
 	n = os_write_file(fd, &map, sizeof(map));
 	if(n != sizeof(map)) 
-		printk("map : /proc/mm map failed, errno = %d\n", errno);
+		printk("map : /proc/mm map failed, err = %d\n", -n);
 }
 
 int unmap(int fd, void *addr, int len)
@@ -49,8 +50,13 @@ int unmap(int fd, void *addr, int len)
 					 { .addr 	= (unsigned long) addr,
 					   .len		= len } } } );
 	n = os_write_file(fd, &unmap, sizeof(unmap));
-	if((n != 0) && (n != sizeof(unmap)))
-		return(-errno);
+	if(n != sizeof(unmap)) {
+		if(n < 0)
+			return(n);
+		else if(n > 0)
+			return(-EIO);
+	}
+
 	return(0);
 }
 
@@ -71,11 +77,15 @@ int protect(int fd, unsigned long addr, 
 					   .prot	= prot } } } );
 
 	n = os_write_file(fd, &protect, sizeof(protect));
-	if((n != 0) && (n != sizeof(protect))){
+	if(n != sizeof(protect)) {
+		if(n == 0) return(0);
+
 		if(must_succeed)
-			panic("protect failed, errno = %d", errno);
-		return(-errno);
+			panic("protect failed, err = %d", -n);
+
+		return(-EIO);
 	}
+
 	return(0);
 }
 
diff -puN arch/um/kernel/skas/mmu.c~uml-base-patch arch/um/kernel/skas/mmu.c
--- 25/arch/um/kernel/skas/mmu.c~uml-base-patch	2004-08-15 20:45:08.405377120 -0700
+++ 25-akpm/arch/um/kernel/skas/mmu.c	2004-08-15 20:46:03.261037792 -0700
@@ -22,9 +22,11 @@ int init_new_context_skas(struct task_st
 	else from = -1;
 
 	mm->context.skas.mm_fd = new_mm(from);
-	if(mm->context.skas.mm_fd < 0)
-		panic("init_new_context_skas - new_mm failed, errno = %d\n",
-		      mm->context.skas.mm_fd);
+	if(mm->context.skas.mm_fd < 0){
+		printk("init_new_context_skas - new_mm failed, errno = %d\n",
+		       mm->context.skas.mm_fd);
+		return(mm->context.skas.mm_fd);
+	}
 
 	return(0);
 }
diff -puN arch/um/kernel/skas/process.c~uml-base-patch arch/um/kernel/skas/process.c
--- 25/arch/um/kernel/skas/process.c~uml-base-patch	2004-08-15 20:45:08.406376968 -0700
+++ 25-akpm/arch/um/kernel/skas/process.c	2004-08-15 20:46:03.263037488 -0700
@@ -4,6 +4,7 @@
  */
 
 #include <stdlib.h>
+#include <unistd.h>
 #include <errno.h>
 #include <signal.h>
 #include <setjmp.h>
@@ -24,6 +25,19 @@
 #include "os.h"
 #include "proc_mm.h"
 #include "skas_ptrace.h"
+#include "chan_user.h"
+#include "signal_user.h"
+
+int is_skas_winch(int pid, int fd, void *data)
+{
+	if(pid != getpid())
+		return(0);
+
+	register_winch_irq(-1, fd, -1, data);
+	return(1);
+}
+
+/* These are set once at boot time and not changed thereafter */
 
 unsigned long exec_regs[FRAME_SIZE];
 unsigned long exec_fp_regs[HOST_FP_SIZE];
@@ -48,11 +62,11 @@ static void handle_trap(int pid, union u
 	int err, syscall_nr, status;
 
 	syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
+	UPT_SYSCALL_NR(regs) = syscall_nr;
 	if(syscall_nr < 1){
 		relay_signal(SIGTRAP, regs);
 		return;
 	}
-	UPT_SYSCALL_NR(regs) = syscall_nr;
 
 	err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
 	if(err < 0)
@@ -72,8 +86,6 @@ static void handle_trap(int pid, union u
 	handle_syscall(regs);
 }
 
-int userspace_pid;
-
 static int userspace_tramp(void *arg)
 {
 	init_new_thread_signals(0);
@@ -83,7 +95,11 @@ static int userspace_tramp(void *arg)
 	return(0);
 }
 
-void start_userspace(void)
+/* Each element set once, and only accessed by a single processor anyway */
+#define NR_CPUS 1
+int userspace_pid[NR_CPUS];
+
+void start_userspace(int cpu)
 {
 	void *stack;
 	unsigned long sp;
@@ -114,21 +130,21 @@ void start_userspace(void)
 	if(munmap(stack, PAGE_SIZE) < 0)
 		panic("start_userspace : munmap failed, errno = %d\n", errno);
 
-	userspace_pid = pid;
+	userspace_pid[cpu] = pid;
 }
 
 void userspace(union uml_pt_regs *regs)
 {
-	int err, status, op;
+	int err, status, op, pid = userspace_pid[0];
 
 	restore_registers(regs);
 		
-	err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0);
+	err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
 	if(err)
 		panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", 
 		       errno);
 	while(1){
-		err = waitpid(userspace_pid, &status, WUNTRACED);
+		err = waitpid(pid, &status, WUNTRACED);
 		if(err < 0)
 			panic("userspace - waitpid failed, errno = %d\n", 
 			      errno);
@@ -139,16 +155,17 @@ void userspace(union uml_pt_regs *regs)
 		if(WIFSTOPPED(status)){
 		  	switch(WSTOPSIG(status)){
 			case SIGSEGV:
-				handle_segv(userspace_pid);
+				handle_segv(pid);
 				break;
 			case SIGTRAP:
-			        handle_trap(userspace_pid, regs);
+			        handle_trap(pid, regs);
 				break;
 			case SIGIO:
 			case SIGVTALRM:
 			case SIGILL:
 			case SIGBUS:
 			case SIGFPE:
+			case SIGWINCH:
 				user_signal(WSTOPSIG(status), regs);
 				break;
 			default:
@@ -162,7 +179,7 @@ void userspace(union uml_pt_regs *regs)
 
 		op = singlestepping_skas() ? PTRACE_SINGLESTEP : 
 			PTRACE_SYSCALL;
-		err = ptrace(op, userspace_pid, 0, 0);
+		err = ptrace(op, pid, 0, 0);
 		if(err)
 			panic("userspace - PTRACE_SYSCALL failed, "
 			      "errno = %d\n", errno);
@@ -172,13 +189,25 @@ void userspace(union uml_pt_regs *regs)
 void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
 		void (*handler)(int))
 {
+	unsigned long flags;
 	jmp_buf switch_buf, fork_buf;
 
 	*switch_buf_ptr = &switch_buf;
 	*fork_buf_ptr = &fork_buf;
 
-	if(setjmp(fork_buf) == 0)
+	/* Somewhat subtle - siglongjmp restores the signal mask before doing
+	 * the longjmp.  This means that when jumping from one stack to another
+	 * when the target stack has interrupts enabled, an interrupt may occur
+	 * on the source stack.  This is bad when starting up a process because
+	 * it's not supposed to get timer ticks until it has been scheduled.
+	 * So, we disable interrupts around the sigsetjmp to ensure that
+	 * they can't happen until we get back here where they are safe.
+	 */
+	flags = get_signals();
+	block_signals();
+	if(sigsetjmp(fork_buf, 1) == 0)
 		new_thread_proc(stack, handler);
+	set_signals(flags);
 
 	remove_sigstack();
 }
@@ -189,16 +218,16 @@ void thread_wait(void *sw, void *fb)
 
 	*switch_buf = &buf;
 	fork_buf = fb;
-	if(setjmp(buf) == 0)
-		longjmp(*fork_buf, 1);
+	if(sigsetjmp(buf, 1) == 0)
+		siglongjmp(*fork_buf, 1);
 }
 
-static int move_registers(int int_op, int fp_op, union uml_pt_regs *regs,
-			  unsigned long *fp_regs)
+static int move_registers(int pid, int int_op, int fp_op,
+			  union uml_pt_regs *regs, unsigned long *fp_regs)
 {
-	if(ptrace(int_op, userspace_pid, 0, regs->skas.regs) < 0)
+	if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
 		return(-errno);
-	if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0)
+	if(ptrace(fp_op, pid, 0, fp_regs) < 0)
 		return(-errno);
 	return(0);
 }
@@ -217,10 +246,11 @@ void save_registers(union uml_pt_regs *r
 		fp_regs = regs->skas.fp;
 	}
 
-	err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs);
+	err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs,
+			     fp_regs);
 	if(err)
 		panic("save_registers - saving registers failed, errno = %d\n",
-		      err);
+		      -err);
 }
 
 void restore_registers(union uml_pt_regs *regs)
@@ -237,10 +267,11 @@ void restore_registers(union uml_pt_regs
 		fp_regs = regs->skas.fp;
 	}
 
-	err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs);
+	err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs,
+			     fp_regs);
 	if(err)
 		panic("restore_registers - saving registers failed, "
-		      "errno = %d\n", err);
+		      "errno = %d\n", -err);
 }
 
 void switch_threads(void *me, void *next)
@@ -248,8 +279,8 @@ void switch_threads(void *me, void *next
 	jmp_buf my_buf, **me_ptr = me, *next_buf = next;
 	
 	*me_ptr = &my_buf;
-	if(setjmp(my_buf) == 0)
-		longjmp(*next_buf, 1);
+	if(sigsetjmp(my_buf, 1) == 0)
+		siglongjmp(*next_buf, 1);
 }
 
 static jmp_buf initial_jmpbuf;
@@ -265,14 +296,14 @@ int start_idle_thread(void *stack, void 
 	int n;
 
 	*fork_buf_ptr = &initial_jmpbuf;
-	n = setjmp(initial_jmpbuf);
+	n = sigsetjmp(initial_jmpbuf, 1);
 	if(n == 0)
 		new_thread_proc((void *) stack, new_thread_handler);
 	else if(n == 1)
 		remove_sigstack();
 	else if(n == 2){
 		(*cb_proc)(cb_arg);
-		longjmp(*cb_back, 1);
+		siglongjmp(*cb_back, 1);
 	}
 	else if(n == 3){
 		kmalloc_ok = 0;
@@ -282,7 +313,7 @@ int start_idle_thread(void *stack, void 
 		kmalloc_ok = 0;
 		return(1);
 	}
-	longjmp(**switch_buf, 1);
+	siglongjmp(**switch_buf, 1);
 }
 
 void remove_sigstack(void)
@@ -304,8 +335,8 @@ void initial_thread_cb_skas(void (*proc)
 	cb_back = &here;
 
 	block_signals();
-	if(setjmp(here) == 0)
-		longjmp(initial_jmpbuf, 2);
+	if(sigsetjmp(here, 1) == 0)
+		siglongjmp(initial_jmpbuf, 2);
 	unblock_signals();
 
 	cb_proc = NULL;
@@ -316,22 +347,23 @@ void initial_thread_cb_skas(void (*proc)
 void halt_skas(void)
 {
 	block_signals();
-	longjmp(initial_jmpbuf, 3);
+	siglongjmp(initial_jmpbuf, 3);
 }
 
 void reboot_skas(void)
 {
 	block_signals();
-	longjmp(initial_jmpbuf, 4);
+	siglongjmp(initial_jmpbuf, 4);
 }
 
 int new_mm(int from)
 {
 	struct proc_mm_op copy;
-	int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0);
+	int n, fd = os_open_file("/proc/mm",
+				 of_cloexec(of_write(OPENFLAGS())), 0);
 
 	if(fd < 0)
-		return(-errno);
+		return(fd);
 
 	if(from != -1){
 		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
@@ -340,8 +372,9 @@ int new_mm(int from)
 		n = os_write_file(fd, &copy, sizeof(copy));
 		if(n != sizeof(copy)) 
 			printk("new_mm : /proc/mm copy_segments failed, "
-			       "errno = %d\n", errno);
+			       "err = %d\n", -n);
 	}
+
 	return(fd);
 }
 
@@ -349,7 +382,8 @@ void switch_mm_skas(int mm_fd)
 {
 	int err;
 
-	err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd);
+#warning need cpu pid in switch_mm_skas
+	err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd);
 	if(err)
 		panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
 		      errno);
@@ -357,7 +391,8 @@ void switch_mm_skas(int mm_fd)
 
 void kill_off_processes_skas(void)
 {
-	os_kill_process(userspace_pid, 1);
+#warning need to loop over userspace_pids in kill_off_processes_skas
+	os_kill_process(userspace_pid[0], 1);
 }
 
 void init_registers(int pid)
diff -puN arch/um/kernel/skas/process_kern.c~uml-base-patch arch/um/kernel/skas/process_kern.c
--- 25/arch/um/kernel/skas/process_kern.c~uml-base-patch	2004-08-15 20:45:08.408376664 -0700
+++ 25-akpm/arch/um/kernel/skas/process_kern.c	2004-08-15 20:46:03.264037336 -0700
@@ -61,11 +61,13 @@ void new_thread_handler(int sig)
 	thread_wait(&current->thread.mode.skas.switch_buf, 
 		    current->thread.mode.skas.fork_buf);
 
-#ifdef CONFIG_SMP
-	schedule_tail(NULL);
-#endif
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
 	current->thread.prev_sched = NULL;
 
+	/* The return value is 1 if the kernel thread execs a process,
+	 * 0 if it just exits
+	 */
 	n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
 	if(n == 1)
 		userspace(&current->thread.regs.regs);
@@ -93,11 +95,11 @@ void fork_handler(int sig)
 		    current->thread.mode.skas.fork_buf);
   	
 	force_flush_all();
-#ifdef CONFIG_SMP
+	if(current->thread.prev_sched == NULL)
+		panic("blech");
+
 	schedule_tail(current->thread.prev_sched);
-#endif
 	current->thread.prev_sched = NULL;
-	unblock_signals();
 
 	userspace(&current->thread.regs.regs);
 }
@@ -136,7 +138,7 @@ int copy_thread_skas(int nr, unsigned lo
 
 void init_idle_skas(void)
 {
-	cpu_tasks[current->thread_info->cpu].pid = os_getpid();
+	cpu_tasks[current_thread->cpu].pid = os_getpid();
 	default_idle();
 }
 
@@ -160,11 +162,11 @@ static int start_kernel_proc(void *unuse
 
 int start_uml_skas(void)
 {
-	start_userspace();
+	start_userspace(0);
 	capture_signal_stack();
+	uml_idle_timer();
 
 	init_new_thread_signals(1);
-	idle_timer();
 
 	init_task.thread.request.u.thread.proc = start_kernel_proc;
 	init_task.thread.request.u.thread.arg = NULL;
@@ -175,12 +177,14 @@ int start_uml_skas(void)
 
 int external_pid_skas(struct task_struct *task)
 {
-	return(userspace_pid);
+#warning Need to look up userspace_pid by cpu
+	return(userspace_pid[0]);
 }
 
 int thread_pid_skas(struct task_struct *task)
 {
-	return(userspace_pid);
+#warning Need to look up userspace_pid by cpu
+	return(userspace_pid[0]);
 }
 
 /*
diff -puN arch/um/kernel/skas/syscall_kern.c~uml-base-patch arch/um/kernel/skas/syscall_kern.c
--- 25/arch/um/kernel/skas/syscall_kern.c~uml-base-patch	2004-08-15 20:45:08.409376512 -0700
+++ 25-akpm/arch/um/kernel/skas/syscall_kern.c	2004-08-15 20:46:03.264037336 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
diff -puN arch/um/kernel/skas/syscall_user.c~uml-base-patch arch/um/kernel/skas/syscall_user.c
--- 25/arch/um/kernel/skas/syscall_user.c~uml-base-patch	2004-08-15 20:45:08.410376360 -0700
+++ 25-akpm/arch/um/kernel/skas/syscall_user.c	2004-08-15 20:46:03.265037184 -0700
@@ -22,7 +22,7 @@ void handle_syscall(union uml_pt_regs *r
 
 	index = record_syscall_start(UPT_SYSCALL_NR(regs));
 
-	syscall_trace();
+	syscall_trace(regs, 1);
 	result = execute_syscall(regs);
 
 	REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
@@ -30,7 +30,7 @@ void handle_syscall(union uml_pt_regs *r
 	   (result == -ERESTARTNOINTR))
 		do_signal(result);
 
-	syscall_trace();
+	syscall_trace(regs, 0);
 	record_syscall_end(index, result);
 }
 
diff -puN arch/um/kernel/skas/sys-i386/Makefile~uml-base-patch arch/um/kernel/skas/sys-i386/Makefile
--- 25/arch/um/kernel/skas/sys-i386/Makefile~uml-base-patch	2004-08-15 20:45:08.412376056 -0700
+++ 25-akpm/arch/um/kernel/skas/sys-i386/Makefile	2004-08-15 20:46:03.265037184 -0700
@@ -10,5 +10,3 @@ USER_OBJS := $(foreach file,$(USER_OBJS)
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
diff -puN arch/um/kernel/skas/sys-i386/sigcontext.c~uml-base-patch arch/um/kernel/skas/sys-i386/sigcontext.c
--- 25/arch/um/kernel/skas/sys-i386/sigcontext.c~uml-base-patch	2004-08-15 20:45:08.413375904 -0700
+++ 25-akpm/arch/um/kernel/skas/sys-i386/sigcontext.c	2004-08-15 20:46:03.265037184 -0700
@@ -12,10 +12,9 @@
 #include "kern_util.h"
 #include "user.h"
 #include "sigcontext.h"
+#include "mode.h"
 
-extern int userspace_pid;
-
-int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr)
+int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr)
 {
   	struct sigcontext sc, *from = from_ptr;
 	unsigned long fpregs[FP_FRAME_SIZE];
@@ -41,13 +40,12 @@ int copy_sc_from_user_skas(union uml_pt_
 	regs->skas.regs[EIP] = sc.eip;
 	regs->skas.regs[CS] = sc.cs;
 	regs->skas.regs[EFL] = sc.eflags;
-	regs->skas.regs[UESP] = sc.esp_at_signal;
 	regs->skas.regs[SS] = sc.ss;
 	regs->skas.fault_addr = sc.cr2;
 	regs->skas.fault_type = FAULT_WRITE(sc.err);
 	regs->skas.trap_type = sc.trapno;
 
-	err = ptrace(PTRACE_SETFPREGS, userspace_pid, 0, fpregs);
+	err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs);
 	if(err < 0){
 	  	printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
 		       "errno = %d\n", errno);
@@ -57,8 +55,9 @@ int copy_sc_from_user_skas(union uml_pt_
 	return(0);
 }
 
-int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs, 
-			 unsigned long fault_addr, int fault_type)
+int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
+			 union uml_pt_regs *regs, unsigned long fault_addr,
+			 int fault_type)
 {
   	struct sigcontext sc, *to = to_ptr;
 	struct _fpstate *to_fp;
@@ -86,7 +85,7 @@ int copy_sc_to_user_skas(void *to_ptr, v
 	sc.err = TO_SC_ERR(fault_type);
 	sc.trapno = regs->skas.trap_type;
 
-	err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs);
+	err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs);
 	if(err < 0){
 	  	printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
 		       "errno = %d\n", errno);
diff -puN arch/um/kernel/skas/trap_user.c~uml-base-patch arch/um/kernel/skas/trap_user.c
--- 25/arch/um/kernel/skas/trap_user.c~uml-base-patch	2004-08-15 20:45:08.414375752 -0700
+++ 25-akpm/arch/um/kernel/skas/trap_user.c	2004-08-15 20:46:03.266037032 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -35,14 +35,10 @@ void sig_handler_common_skas(int sig, vo
 	errno = save_errno;
 }
 
-extern int missed_ticks[];
-
 void user_signal(int sig, union uml_pt_regs *regs)
 {
 	struct signal_info *info;
 
-	if(sig == SIGVTALRM)
-		missed_ticks[cpu()]++;
 	regs->skas.is_user = 1;
 	regs->skas.fault_addr = 0;
 	regs->skas.fault_type = 0;
diff -puN /dev/null arch/um/kernel/skas/uaccess.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/kernel/skas/uaccess.c	2004-08-15 20:46:03.267036880 -0700
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/stddef.h"
+#include "linux/kernel.h"
+#include "linux/string.h"
+#include "linux/fs.h"
+#include "linux/highmem.h"
+#include "asm/page.h"
+#include "asm/pgtable.h"
+#include "asm/uaccess.h"
+#include "kern_util.h"
+
+extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+			     pte_t *pte_out);
+
+static unsigned long maybe_map(unsigned long virt, int is_write)
+{
+	pte_t pte;
+	int err;
+
+	void *phys = um_virt_to_phys(current, virt, &pte);
+	int dummy_code;
+
+	if(IS_ERR(phys) || (is_write && !pte_write(pte))){
+		err = handle_page_fault(virt, 0, is_write, 0, &dummy_code);
+		if(err)
+			return(0);
+		phys = um_virt_to_phys(current, virt, NULL);
+	}
+	return((unsigned long) phys);
+}
+
+static int do_op(unsigned long addr, int len, int is_write,
+		 int (*op)(unsigned long addr, int len, void *arg), void *arg)
+{
+	struct page *page;
+	int n;
+
+	addr = maybe_map(addr, is_write);
+	if(addr == -1)
+		return(-1);
+
+	page = phys_to_page(addr);
+	addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
+	n = (*op)(addr, len, arg);
+	kunmap(page);
+
+	return(n);
+}
+
+static int buffer_op(unsigned long addr, int len, int is_write,
+		     int (*op)(unsigned long addr, int len, void *arg),
+		     void *arg)
+{
+	int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
+	int remain = len, n;
+
+	n = do_op(addr, size, is_write, op, arg);
+	if(n != 0)
+		return(n < 0 ? remain : 0);
+
+	addr += size;
+	remain -= size;
+	if(remain == 0)
+		return(0);
+
+	while(addr < ((addr + remain) & PAGE_MASK)){
+		n = do_op(addr, PAGE_SIZE, is_write, op, arg);
+		if(n != 0)
+			return(n < 0 ? remain : 0);
+
+		addr += PAGE_SIZE;
+		remain -= PAGE_SIZE;
+	}
+	if(remain == 0)
+		return(0);
+
+	n = do_op(addr, remain, is_write, op, arg);
+	if(n != 0)
+		return(n < 0 ? remain : 0);
+	return(0);
+}
+
+static int copy_chunk_from_user(unsigned long from, int len, void *arg)
+{
+	unsigned long *to_ptr = arg, to = *to_ptr;
+
+	memcpy((void *) to, (void *) from, len);
+	*to_ptr += len;
+	return(0);
+}
+
+int copy_from_user_skas(void *to, const void *from, int n)
+{
+	if(segment_eq(get_fs(), KERNEL_DS)){
+		memcpy(to, from, n);
+		return(0);
+	}
+
+	return(access_ok_skas(VERIFY_READ, from, n) ?
+	       buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
+	       n);
+}
+
+static int copy_chunk_to_user(unsigned long to, int len, void *arg)
+{
+	unsigned long *from_ptr = arg, from = *from_ptr;
+
+	memcpy((void *) to, (void *) from, len);
+	*from_ptr += len;
+	return(0);
+}
+
+int copy_to_user_skas(void *to, const void *from, int n)
+{
+	if(segment_eq(get_fs(), KERNEL_DS)){
+		memcpy(to, from, n);
+		return(0);
+	}
+
+	return(access_ok_skas(VERIFY_WRITE, to, n) ?
+	       buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
+	       n);
+}
+
+static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
+{
+	char **to_ptr = arg, *to = *to_ptr;
+	int n;
+
+	strncpy(to, (void *) from, len);
+	n = strnlen(to, len);
+	*to_ptr += n;
+
+	if(n < len)
+	        return(1);
+	return(0);
+}
+
+int strncpy_from_user_skas(char *dst, const char *src, int count)
+{
+	int n;
+	char *ptr = dst;
+
+	if(segment_eq(get_fs(), KERNEL_DS)){
+		strncpy(dst, src, count);
+		return(strnlen(dst, count));
+	}
+
+	if(!access_ok_skas(VERIFY_READ, src, 1))
+		return(-EFAULT);
+
+	n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
+		      &ptr);
+	if(n != 0)
+		return(-EFAULT);
+	return(strnlen(dst, count));
+}
+
+static int clear_chunk(unsigned long addr, int len, void *unused)
+{
+	memset((void *) addr, 0, len);
+	return(0);
+}
+
+int __clear_user_skas(void *mem, int len)
+{
+	return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL));
+}
+
+int clear_user_skas(void *mem, int len)
+{
+	if(segment_eq(get_fs(), KERNEL_DS)){
+		memset(mem, 0, len);
+		return(0);
+	}
+
+	return(access_ok_skas(VERIFY_WRITE, mem, len) ?
+	       buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
+}
+
+static int strnlen_chunk(unsigned long str, int len, void *arg)
+{
+	int *len_ptr = arg, n;
+
+	n = strnlen((void *) str, len);
+	*len_ptr += n;
+
+	if(n < len)
+		return(1);
+	return(0);
+}
+
+int strnlen_user_skas(const void *str, int len)
+{
+	int count = 0, n;
+
+	if(segment_eq(get_fs(), KERNEL_DS))
+		return(strnlen(str, len) + 1);
+
+	n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count);
+	if(n == 0)
+		return(count + 1);
+	return(-EFAULT);
+}
+
+/*
+ * 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 -puN arch/um/kernel/skas/util/Makefile~uml-base-patch arch/um/kernel/skas/util/Makefile
--- 25/arch/um/kernel/skas/util/Makefile~uml-base-patch	2004-08-15 20:45:08.416375448 -0700
+++ 25-akpm/arch/um/kernel/skas/util/Makefile	2004-08-15 20:46:03.267036880 -0700
@@ -1,10 +1,9 @@
 all: mk_ptregs
 
 mk_ptregs : mk_ptregs.o
-	$(CC) -o mk_ptregs mk_ptregs.o
+	$(HOSTCC) -o mk_ptregs mk_ptregs.o
 
 mk_ptregs.o : mk_ptregs.c
-	$(CC) -c $< 
+	$(HOSTCC) -c $<
 
-clean : 
-	$(RM) -f mk_ptregs *.o *~
+clean-files := mk_ptregs *.o *~
diff -puN arch/um/kernel/skas/util/mk_ptregs.c~uml-base-patch arch/um/kernel/skas/util/mk_ptregs.c
--- 25/arch/um/kernel/skas/util/mk_ptregs.c~uml-base-patch	2004-08-15 20:45:08.417375296 -0700
+++ 25-akpm/arch/um/kernel/skas/util/mk_ptregs.c	2004-08-15 20:46:03.267036880 -0700
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
diff -puN arch/um/kernel/smp.c~uml-base-patch arch/um/kernel/smp.c
--- 25/arch/um/kernel/smp.c~uml-base-patch	2004-08-15 20:45:08.419374992 -0700
+++ 25-akpm/arch/um/kernel/smp.c	2004-08-15 20:46:03.269036576 -0700
@@ -1,9 +1,15 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #include "linux/config.h"
+#include "linux/percpu.h"
+#include "asm/pgalloc.h"
+#include "asm/tlb.h"
+
+/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 #ifdef CONFIG_SMP
 
@@ -23,7 +29,7 @@
 #include "os.h"
 
 /* CPU online map, set by smp_boot_cpus */
-unsigned long cpu_online_map = cpumask_of_cpu(0);
+unsigned long cpu_online_map = CPU_MASK_NONE;
 
 EXPORT_SYMBOL(cpu_online_map);
 
@@ -55,7 +61,7 @@ struct task_struct *idle_threads[NR_CPUS
 
 void smp_send_reschedule(int cpu)
 {
-	write(cpu_data[cpu].ipi_pipe[1], "R", 1);
+	os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1);
 	num_reschedules_sent++;
 }
 
@@ -100,35 +106,34 @@ void smp_send_stop(void)
 
 	printk(KERN_INFO "Stopping all CPUs...");
 	for(i = 0; i < num_online_cpus(); i++){
-		if(i == current->thread_info->cpu)
+		if(i == current_thread->cpu)
 			continue;
-		write(cpu_data[i].ipi_pipe[1], "S", 1);
+		os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
 	}
 	printk("done\n");
 }
 
-static cpumask_t smp_commenced_mask;
-static cpumask_t smp_callin_map = CPU_MASK_NONE;
+static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
+static cpumask_t cpu_callin_map = CPU_MASK_NONE;
 
 static int idle_proc(void *cpup)
 {
 	int cpu = (int) cpup, err;
 
 	err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
-	if(err)
-		panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, 
-		      -err);
+	if(err < 0)
+		panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
 
 	activate_ipi(cpu_data[cpu].ipi_pipe[0], 
 		     current->thread.mode.tt.extern_pid);
  
 	wmb();
-	if (cpu_test_and_set(cpu, &smp_callin_map)) {
+	if (cpu_test_and_set(cpu, cpu_callin_map)) {
 		printk("huh, CPU#%d already present??\n", cpu);
 		BUG();
 	}
 
-	while (!cpu_isset(cpu, &smp_commenced_mask))
+	while (!cpu_isset(cpu, smp_commenced_mask))
 		cpu_relax();
 
 	cpu_set(cpu, cpu_online_map);
@@ -143,16 +148,20 @@ static struct task_struct *idle_thread(i
 
         current->thread.request.u.thread.proc = idle_proc;
         current->thread.request.u.thread.arg = (void *) cpu;
-	new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, NULL);
-	if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
+	new_task = copy_process(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL,
+				NULL);
+	if(IS_ERR(new_task))
+		panic("copy_process failed in idle_thread, error = %ld",
+		      PTR_ERR(new_task));
 
 	cpu_tasks[cpu] = ((struct cpu_task) 
 		          { .pid = 	new_task->thread.mode.tt.extern_pid,
 			    .task = 	new_task } );
 	idle_threads[cpu] = new_task;
-	CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c, 
+	CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
 			  sizeof(c)),
 		    ({ panic("skas mode doesn't support SMP"); }));
+	wake_up_forked_process(new_task);
 	return(new_task);
 }
 
@@ -160,15 +169,17 @@ void smp_prepare_cpus(unsigned int maxcp
 {
 	struct task_struct *idle;
 	unsigned long waittime;
-	int err, cpu;
+	int err, cpu, me = smp_processor_id();
 
-	cpu_set(0, cpu_online_map);
-	cpu_set(0, smp_callin_map);
+	cpu_clear(me, cpu_online_map);
+	cpu_set(me, cpu_online_map);
+	cpu_set(me, cpu_callin_map);
 
-	err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
-	if(err)	panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
+	err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
+	if(err < 0)
+		panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
 
-	activate_ipi(cpu_data[0].ipi_pipe[0], 
+	activate_ipi(cpu_data[me].ipi_pipe[0],
 		     current->thread.mode.tt.extern_pid);
 
 	for(cpu = 1; cpu < ncpus; cpu++){
@@ -180,10 +191,10 @@ void smp_prepare_cpus(unsigned int maxcp
 		unhash_process(idle);
 
 		waittime = 200000000;
-		while (waittime-- && !cpu_isset(cpu, smp_callin_map))
+		while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
 			cpu_relax();
 
-		if (cpu_isset(cpu, smp_callin_map))
+		if (cpu_isset(cpu, cpu_callin_map))
 			printk("done\n");
 		else printk("failed\n");
 	}
@@ -216,7 +227,7 @@ void IPI_handler(int cpu)
 	int fd;
 
 	fd = cpu_data[cpu].ipi_pipe[0];
-	while (read(fd, &c, 1) == 1) {
+	while (os_read_file(fd, &c, 1) == 1) {
 		switch (c) {
 		case 'C':
 			smp_call_function_slave(cpu);
@@ -276,9 +287,9 @@ int smp_call_function(void (*_func)(void
 	info = _info;
 
 	for (i=0;i<NR_CPUS;i++)
-		if((i != current->thread_info->cpu) && 
+		if((i != current_thread->cpu) &&
 		   cpu_isset(i, cpu_online_map))
-			write(cpu_data[i].ipi_pipe[1], "C", 1);
+			os_write_file(cpu_data[i].ipi_pipe[1], "C", 1);
 
 	while (atomic_read(&scf_started) != cpus)
 		barrier();
diff -puN arch/um/kernel/syscall_kern.c~uml-base-patch arch/um/kernel/syscall_kern.c
--- 25/arch/um/kernel/syscall_kern.c~uml-base-patch	2004-08-15 20:45:08.420374840 -0700
+++ 25-akpm/arch/um/kernel/syscall_kern.c	2004-08-15 20:46:03.270036424 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -36,32 +36,34 @@ long um_mount(char * dev_name, char * di
 
 long sys_fork(void)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-        p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
+        ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
-long sys_clone(unsigned long clone_flags, unsigned long newsp)
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       int *parent_tid, int *child_tid)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-	p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL);
+	ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
 long sys_vfork(void)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL);
+	ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
+		      NULL);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
 /* common code for old and new mmaps */
@@ -136,43 +138,12 @@ int sys_pipe(unsigned long * fildes)
 
         error = do_pipe(fd);
         if (!error) {
-                if (copy_to_user(fildes, fd, 2*sizeof(int)))
+		if (copy_to_user(fildes, fd, sizeof(fd)))
                         error = -EFAULT;
         }
         return error;
 }
 
-int sys_sigaction(int sig, const struct old_sigaction *act,
-			 struct old_sigaction *oact)
-{
-	struct k_sigaction new_ka, old_ka;
-	int ret;
-
-	if (act) {
-		old_sigset_t mask;
-		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
-
 /*
  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  *
@@ -254,7 +225,7 @@ int sys_ipc (uint call, int first, int s
 		return sys_shmctl (first, second,
 				   (struct shmid_ds *) ptr);
 	default:
-		return -EINVAL;
+		return -ENOSYS;
 	}
 }
 
@@ -303,11 +274,6 @@ int sys_olduname(struct oldold_utsname *
 	return error;
 }
 
-int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
-{
-	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
-}
-
 long execute_syscall(void *r)
 {
 	return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
diff -puN arch/um/kernel/sys_call_table.c~uml-base-patch arch/um/kernel/sys_call_table.c
--- 25/arch/um/kernel/sys_call_table.c~uml-base-patch	2004-08-15 20:45:08.421374688 -0700
+++ 25-akpm/arch/um/kernel/sys_call_table.c	2004-08-15 20:46:03.275035664 -0700
@@ -5,7 +5,6 @@
 
 #include "linux/config.h"
 #include "linux/unistd.h"
-#include "linux/version.h"
 #include "linux/sys.h"
 #include "linux/swap.h"
 #include "linux/syscalls.h"
@@ -14,251 +13,50 @@
 #include "sysdep/syscalls.h"
 #include "kern_util.h"
 
-extern syscall_handler_t sys_restart_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_exit;
+#ifdef CONFIG_NFSD
+#define NFSSERVCTL sys_nfsservctl
+#else
+#define NFSSERVCTL sys_ni_syscall
+#endif
+
+#define LAST_GENERIC_SYSCALL __NR_vserver
+
+#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
+#define LAST_SYSCALL LAST_GENERIC_SYSCALL
+#else
+#define LAST_SYSCALL LAST_ARCH_SYSCALL
+#endif
+
 extern syscall_handler_t sys_fork;
-extern syscall_handler_t sys_creat;
-extern syscall_handler_t sys_link;
-extern syscall_handler_t sys_unlink;
-extern syscall_handler_t sys_chdir;
-extern syscall_handler_t sys_mknod;
-extern syscall_handler_t sys_chmod;
-extern syscall_handler_t sys_lchown16;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_stat;
-extern syscall_handler_t sys_getpid;
-extern syscall_handler_t sys_oldumount;
-extern syscall_handler_t sys_setuid16;
-extern syscall_handler_t sys_getuid16;
+extern syscall_handler_t sys_execve;
+extern syscall_handler_t um_time;
+extern syscall_handler_t um_mount;
+extern syscall_handler_t um_stime;
 extern syscall_handler_t sys_ptrace;
-extern syscall_handler_t sys_alarm;
-extern syscall_handler_t sys_fstat;
-extern syscall_handler_t sys_pause;
-extern syscall_handler_t sys_utime;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_access;
-extern syscall_handler_t sys_nice;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_sync;
-extern syscall_handler_t sys_kill;
-extern syscall_handler_t sys_rename;
-extern syscall_handler_t sys_mkdir;
-extern syscall_handler_t sys_rmdir;
 extern syscall_handler_t sys_pipe;
-extern syscall_handler_t sys_times;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_brk;
-extern syscall_handler_t sys_setgid16;
-extern syscall_handler_t sys_getgid16;
-extern syscall_handler_t sys_signal;
-extern syscall_handler_t sys_geteuid16;
-extern syscall_handler_t sys_getegid16;
-extern syscall_handler_t sys_acct;
-extern syscall_handler_t sys_umount;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ioctl;
-extern syscall_handler_t sys_fcntl;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_setpgid;
-extern syscall_handler_t sys_ni_syscall;
 extern syscall_handler_t sys_olduname;
-extern syscall_handler_t sys_umask;
-extern syscall_handler_t sys_chroot;
-extern syscall_handler_t sys_ustat;
-extern syscall_handler_t sys_dup2;
-extern syscall_handler_t sys_getppid;
-extern syscall_handler_t sys_getpgrp;
 extern syscall_handler_t sys_sigaction;
-extern syscall_handler_t sys_sgetmask;
-extern syscall_handler_t sys_ssetmask;
-extern syscall_handler_t sys_setreuid16;
-extern syscall_handler_t sys_setregid16;
 extern syscall_handler_t sys_sigsuspend;
-extern syscall_handler_t sys_sigpending;
-extern syscall_handler_t sys_sethostname;
-extern syscall_handler_t sys_setrlimit;
-extern syscall_handler_t sys_old_getrlimit;
-extern syscall_handler_t sys_getrusage;
-extern syscall_handler_t sys_gettimeofday;
-extern syscall_handler_t sys_settimeofday;
-extern syscall_handler_t sys_getgroups16;
-extern syscall_handler_t sys_setgroups16;
-extern syscall_handler_t sys_symlink;
-extern syscall_handler_t sys_lstat;
-extern syscall_handler_t sys_readlink;
-extern syscall_handler_t sys_swapon;
-extern syscall_handler_t sys_uselib;
-extern syscall_handler_t sys_reboot;
 extern syscall_handler_t old_readdir;
-extern syscall_handler_t sys_munmap;
-extern syscall_handler_t sys_truncate;
-extern syscall_handler_t sys_ftruncate;
-extern syscall_handler_t sys_fchmod;
-extern syscall_handler_t sys_fchown16;
-extern syscall_handler_t sys_getpriority;
-extern syscall_handler_t sys_setpriority;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_statfs;
-extern syscall_handler_t sys_fstatfs;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_socketcall;
-extern syscall_handler_t sys_syslog;
-extern syscall_handler_t sys_setitimer;
-extern syscall_handler_t sys_getitimer;
-extern syscall_handler_t sys_newstat;
-extern syscall_handler_t sys_newlstat;
-extern syscall_handler_t sys_newfstat;
 extern syscall_handler_t sys_uname;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_vhangup;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_swapoff;
-extern syscall_handler_t sys_sysinfo;
 extern syscall_handler_t sys_ipc;
-extern syscall_handler_t sys_fsync;
 extern syscall_handler_t sys_sigreturn;
-extern syscall_handler_t sys_rt_sigreturn;
 extern syscall_handler_t sys_clone;
-extern syscall_handler_t sys_setdomainname;
-extern syscall_handler_t sys_newuname;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_adjtimex;
-extern syscall_handler_t sys_mprotect;
-extern syscall_handler_t sys_sigprocmask;
-extern syscall_handler_t sys_init_module;
-extern syscall_handler_t sys_delete_module;
-extern syscall_handler_t sys_quotactl;
-extern syscall_handler_t sys_getpgid;
-extern syscall_handler_t sys_fchdir;
-extern syscall_handler_t sys_bdflush;
-extern syscall_handler_t sys_sysfs;
-extern syscall_handler_t sys_personality;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_setfsuid16;
-extern syscall_handler_t sys_setfsgid16;
-extern syscall_handler_t sys_llseek;
-extern syscall_handler_t sys_getdents;
-extern syscall_handler_t sys_flock;
-extern syscall_handler_t sys_msync;
-extern syscall_handler_t sys_readv;
-extern syscall_handler_t sys_writev;
-extern syscall_handler_t sys_getsid;
-extern syscall_handler_t sys_fdatasync;
-extern syscall_handler_t sys_mlock;
-extern syscall_handler_t sys_munlock;
-extern syscall_handler_t sys_mlockall;
-extern syscall_handler_t sys_munlockall;
-extern syscall_handler_t sys_sched_setparam;
-extern syscall_handler_t sys_sched_getparam;
-extern syscall_handler_t sys_sched_setscheduler;
-extern syscall_handler_t sys_sched_getscheduler;
-extern syscall_handler_t sys_sched_get_priority_max;
-extern syscall_handler_t sys_sched_get_priority_min;
-extern syscall_handler_t sys_sched_rr_get_interval;
-extern syscall_handler_t sys_nanosleep;
-extern syscall_handler_t sys_mremap;
-extern syscall_handler_t sys_setresuid16;
-extern syscall_handler_t sys_getresuid16;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_poll;
-extern syscall_handler_t sys_nfsservctl;
-extern syscall_handler_t sys_setresgid16;
-extern syscall_handler_t sys_getresgid16;
-extern syscall_handler_t sys_prctl;
-extern syscall_handler_t sys_ni_syscall;
+extern syscall_handler_t sys_rt_sigreturn;
 extern syscall_handler_t sys_rt_sigaction;
-extern syscall_handler_t sys_rt_sigprocmask;
-extern syscall_handler_t sys_rt_sigpending;
-extern syscall_handler_t sys_rt_sigtimedwait;
-extern syscall_handler_t sys_rt_sigqueueinfo;
-extern syscall_handler_t sys_rt_sigsuspend;
-extern syscall_handler_t sys_pread64;
-extern syscall_handler_t sys_pwrite64;
-extern syscall_handler_t sys_chown16;
-extern syscall_handler_t sys_getcwd;
-extern syscall_handler_t sys_capget;
-extern syscall_handler_t sys_capset;
 extern syscall_handler_t sys_sigaltstack;
-extern syscall_handler_t sys_sendfile;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
 extern syscall_handler_t sys_vfork;
-extern syscall_handler_t sys_getrlimit;
 extern syscall_handler_t sys_mmap2;
-extern syscall_handler_t sys_truncate64;
-extern syscall_handler_t sys_ftruncate64;
-extern syscall_handler_t sys_stat64;
-extern syscall_handler_t sys_lstat64;
-extern syscall_handler_t sys_fstat64;
-extern syscall_handler_t sys_lchown;
-extern syscall_handler_t sys_getuid;
-extern syscall_handler_t sys_getgid;
-extern syscall_handler_t sys_geteuid;
-extern syscall_handler_t sys_getegid;
-extern syscall_handler_t sys_setreuid;
-extern syscall_handler_t sys_setregid;
-extern syscall_handler_t sys_getgroups;
-extern syscall_handler_t sys_setgroups;
-extern syscall_handler_t sys_fchown;
-extern syscall_handler_t sys_setresuid;
-extern syscall_handler_t sys_getresuid;
-extern syscall_handler_t sys_setresgid;
-extern syscall_handler_t sys_getresgid;
-extern syscall_handler_t sys_chown;
-extern syscall_handler_t sys_setuid;
-extern syscall_handler_t sys_setgid;
-extern syscall_handler_t sys_setfsuid;
-extern syscall_handler_t sys_setfsgid;
-extern syscall_handler_t sys_pivot_root;
-extern syscall_handler_t sys_mincore;
-extern syscall_handler_t sys_madvise;
-extern syscall_handler_t sys_fcntl64;
-extern syscall_handler_t sys_getdents64;
-extern syscall_handler_t sys_gettid;
-extern syscall_handler_t sys_readahead;
-extern syscall_handler_t sys_tkill;
-extern syscall_handler_t sys_sendfile64;
-extern syscall_handler_t sys_futex;
-extern syscall_handler_t sys_sched_setaffinity;
-extern syscall_handler_t sys_sched_getaffinity;
-extern syscall_handler_t sys_io_setup;
-extern syscall_handler_t sys_io_destroy;
-extern syscall_handler_t sys_io_getevents;
-extern syscall_handler_t sys_io_submit;
-extern syscall_handler_t sys_io_cancel;
-extern syscall_handler_t sys_exit_group;
-extern syscall_handler_t sys_lookup_dcookie;
-extern syscall_handler_t sys_epoll_create;
-extern syscall_handler_t sys_epoll_ctl;
-extern syscall_handler_t sys_epoll_wait;
-extern syscall_handler_t sys_remap_file_pages;
-extern syscall_handler_t sys_set_tid_address;
-
-#ifdef CONFIG_NFSD
-#define NFSSERVCTL sys_nfsservctl
-#else
-#define NFSSERVCTL sys_ni_syscall
-#endif
-
-extern syscall_handler_t um_mount;
-extern syscall_handler_t um_time;
-extern syscall_handler_t um_stime;
-
-#define LAST_GENERIC_SYSCALL __NR_set_tid_address
-
-#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
-#define LAST_SYSCALL LAST_GENERIC_SYSCALL
-#else
-#define LAST_SYSCALL LAST_ARCH_SYSCALL
-#endif
+extern syscall_handler_t sys_timer_create;
+extern syscall_handler_t old_mmap_i386;
+extern syscall_handler_t old_select;
+extern syscall_handler_t sys_modify_ldt;
+extern syscall_handler_t sys_rt_sigsuspend;
 
 syscall_handler_t *sys_call_table[] = {
-	[ __NR_restart_syscall ] = sys_restart_syscall,
-	[ __NR_exit ] = sys_exit,
-	[ __NR_fork ] = sys_fork,
+	[ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
+	[ __NR_exit ] (syscall_handler_t *) sys_exit,
+	[ __NR_fork ] (syscall_handler_t *) sys_fork,
 	[ __NR_read ] = (syscall_handler_t *) sys_read,
 	[ __NR_write ] = (syscall_handler_t *) sys_write,
 
@@ -266,229 +64,249 @@ syscall_handler_t *sys_call_table[] = {
 	[ __NR_open ] = (syscall_handler_t *) sys_open,
 	[ __NR_close ] = (syscall_handler_t *) sys_close,
 	[ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid,
-	[ __NR_creat ] = sys_creat,
-	[ __NR_link ] = sys_link,
-	[ __NR_unlink ] = sys_unlink,
+	[ __NR_creat ] (syscall_handler_t *) sys_creat,
+	[ __NR_link ] (syscall_handler_t *) sys_link,
+	[ __NR_unlink ] (syscall_handler_t *) sys_unlink,
 	[ __NR_execve ] = (syscall_handler_t *) sys_execve,
 
 	/* declared differently in kern_util.h */
-	[ __NR_chdir ] = sys_chdir,
+	[ __NR_chdir ] (syscall_handler_t *) sys_chdir,
 	[ __NR_time ] = um_time,
-	[ __NR_mknod ] = sys_mknod,
-	[ __NR_chmod ] = sys_chmod,
-	[ __NR_lchown ] = sys_lchown16,
-	[ __NR_break ] = sys_ni_syscall,
-	[ __NR_oldstat ] = sys_stat,
+	[ __NR_mknod ] (syscall_handler_t *) sys_mknod,
+	[ __NR_chmod ] (syscall_handler_t *) sys_chmod,
+	[ __NR_lchown ] (syscall_handler_t *) sys_lchown16,
+	[ __NR_break ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_oldstat ] (syscall_handler_t *) sys_stat,
 	[ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
-	[ __NR_getpid ] = sys_getpid,
+	[ __NR_getpid ] (syscall_handler_t *) sys_getpid,
 	[ __NR_mount ] = um_mount,
-	[ __NR_umount ] = sys_oldumount,
-	[ __NR_setuid ] = sys_setuid16,
-	[ __NR_getuid ] = sys_getuid16,
+	[ __NR_umount ] (syscall_handler_t *) sys_oldumount,
+	[ __NR_setuid ] (syscall_handler_t *) sys_setuid16,
+	[ __NR_getuid ] (syscall_handler_t *) sys_getuid16,
 	[ __NR_stime ] = um_stime,
-	[ __NR_ptrace ] = sys_ptrace,
-	[ __NR_alarm ] = sys_alarm,
-	[ __NR_oldfstat ] = sys_fstat,
-	[ __NR_pause ] = sys_pause,
-	[ __NR_utime ] = sys_utime,
-	[ __NR_stty ] = sys_ni_syscall,
-	[ __NR_gtty ] = sys_ni_syscall,
-	[ __NR_access ] = sys_access,
-	[ __NR_nice ] = sys_nice,
-	[ __NR_ftime ] = sys_ni_syscall,
-	[ __NR_sync ] = sys_sync,
-	[ __NR_kill ] = sys_kill,
-	[ __NR_rename ] = sys_rename,
-	[ __NR_mkdir ] = sys_mkdir,
-	[ __NR_rmdir ] = sys_rmdir,
+	[ __NR_ptrace ] (syscall_handler_t *) sys_ptrace,
+	[ __NR_alarm ] (syscall_handler_t *) sys_alarm,
+	[ __NR_oldfstat ] (syscall_handler_t *) sys_fstat,
+	[ __NR_pause ] (syscall_handler_t *) sys_pause,
+	[ __NR_utime ] (syscall_handler_t *) sys_utime,
+	[ __NR_stty ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_gtty ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_access ] (syscall_handler_t *) sys_access,
+	[ __NR_nice ] (syscall_handler_t *) sys_nice,
+	[ __NR_ftime ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_sync ] (syscall_handler_t *) sys_sync,
+	[ __NR_kill ] (syscall_handler_t *) sys_kill,
+	[ __NR_rename ] (syscall_handler_t *) sys_rename,
+	[ __NR_mkdir ] (syscall_handler_t *) sys_mkdir,
+	[ __NR_rmdir ] (syscall_handler_t *) sys_rmdir,
 
 	/* Declared differently in asm/unistd.h */
 	[ __NR_dup ] = (syscall_handler_t *) sys_dup,
-	[ __NR_pipe ] = sys_pipe,
-	[ __NR_times ] = sys_times,
-	[ __NR_prof ] = sys_ni_syscall,
-	[ __NR_brk ] = sys_brk,
-	[ __NR_setgid ] = sys_setgid16,
-	[ __NR_getgid ] = sys_getgid16,
-	[ __NR_signal ] = sys_signal,
-	[ __NR_geteuid ] = sys_geteuid16,
-	[ __NR_getegid ] = sys_getegid16,
-	[ __NR_acct ] = sys_acct,
-	[ __NR_umount2 ] = sys_umount,
-	[ __NR_lock ] = sys_ni_syscall,
-	[ __NR_ioctl ] = sys_ioctl,
-	[ __NR_fcntl ] = sys_fcntl,
-	[ __NR_mpx ] = sys_ni_syscall,
-	[ __NR_setpgid ] = sys_setpgid,
-	[ __NR_ulimit ] = sys_ni_syscall,
-	[ __NR_oldolduname ] = sys_olduname,
-	[ __NR_umask ] = sys_umask,
-	[ __NR_chroot ] = sys_chroot,
-	[ __NR_ustat ] = sys_ustat,
-	[ __NR_dup2 ] = sys_dup2,
-	[ __NR_getppid ] = sys_getppid,
-	[ __NR_getpgrp ] = sys_getpgrp,
+	[ __NR_pipe ] (syscall_handler_t *) sys_pipe,
+	[ __NR_times ] (syscall_handler_t *) sys_times,
+	[ __NR_prof ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_brk ] (syscall_handler_t *) sys_brk,
+	[ __NR_setgid ] (syscall_handler_t *) sys_setgid16,
+	[ __NR_getgid ] (syscall_handler_t *) sys_getgid16,
+	[ __NR_signal ] (syscall_handler_t *) sys_signal,
+	[ __NR_geteuid ] (syscall_handler_t *) sys_geteuid16,
+	[ __NR_getegid ] (syscall_handler_t *) sys_getegid16,
+	[ __NR_acct ] (syscall_handler_t *) sys_acct,
+	[ __NR_umount2 ] (syscall_handler_t *) sys_umount,
+	[ __NR_lock ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_ioctl ] (syscall_handler_t *) sys_ioctl,
+	[ __NR_fcntl ] (syscall_handler_t *) sys_fcntl,
+	[ __NR_mpx ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_setpgid ] (syscall_handler_t *) sys_setpgid,
+	[ __NR_ulimit ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_oldolduname ] (syscall_handler_t *) sys_olduname,
+	[ __NR_umask ] (syscall_handler_t *) sys_umask,
+	[ __NR_chroot ] (syscall_handler_t *) sys_chroot,
+	[ __NR_ustat ] (syscall_handler_t *) sys_ustat,
+	[ __NR_dup2 ] (syscall_handler_t *) sys_dup2,
+	[ __NR_getppid ] (syscall_handler_t *) sys_getppid,
+	[ __NR_getpgrp ] (syscall_handler_t *) sys_getpgrp,
 	[ __NR_setsid ] = (syscall_handler_t *) sys_setsid,
-	[ __NR_sigaction ] = sys_sigaction,
-	[ __NR_sgetmask ] = sys_sgetmask,
-	[ __NR_ssetmask ] = sys_ssetmask,
-	[ __NR_setreuid ] = sys_setreuid16,
-	[ __NR_setregid ] = sys_setregid16,
-	[ __NR_sigsuspend ] = sys_sigsuspend,
-	[ __NR_sigpending ] = sys_sigpending,
-	[ __NR_sethostname ] = sys_sethostname,
-	[ __NR_setrlimit ] = sys_setrlimit,
-	[ __NR_getrlimit ] = sys_old_getrlimit,
-	[ __NR_getrusage ] = sys_getrusage,
-	[ __NR_gettimeofday ] = sys_gettimeofday,
-	[ __NR_settimeofday ] = sys_settimeofday,
-	[ __NR_getgroups ] = sys_getgroups16,
-	[ __NR_setgroups ] = sys_setgroups16,
-	[ __NR_symlink ] = sys_symlink,
-	[ __NR_oldlstat ] = sys_lstat,
-	[ __NR_readlink ] = sys_readlink,
-	[ __NR_uselib ] = sys_uselib,
+	[ __NR_sigaction ] (syscall_handler_t *) sys_sigaction,
+	[ __NR_sgetmask ] (syscall_handler_t *) sys_sgetmask,
+	[ __NR_ssetmask ] (syscall_handler_t *) sys_ssetmask,
+	[ __NR_setreuid ] (syscall_handler_t *) sys_setreuid16,
+	[ __NR_setregid ] (syscall_handler_t *) sys_setregid16,
+	[ __NR_sigsuspend ] (syscall_handler_t *) sys_sigsuspend,
+	[ __NR_sigpending ] (syscall_handler_t *) sys_sigpending,
+	[ __NR_sethostname ] (syscall_handler_t *) sys_sethostname,
+	[ __NR_setrlimit ] (syscall_handler_t *) sys_setrlimit,
+	[ __NR_getrlimit ] (syscall_handler_t *) sys_old_getrlimit,
+	[ __NR_getrusage ] (syscall_handler_t *) sys_getrusage,
+	[ __NR_gettimeofday ] (syscall_handler_t *) sys_gettimeofday,
+	[ __NR_settimeofday ] (syscall_handler_t *) sys_settimeofday,
+	[ __NR_getgroups ] (syscall_handler_t *) sys_getgroups16,
+	[ __NR_setgroups ] (syscall_handler_t *) sys_setgroups16,
+	[ __NR_symlink ] (syscall_handler_t *) sys_symlink,
+	[ __NR_oldlstat ] (syscall_handler_t *) sys_lstat,
+	[ __NR_readlink ] (syscall_handler_t *) sys_readlink,
+	[ __NR_uselib ] (syscall_handler_t *) sys_uselib,
 	[ __NR_swapon ] = (syscall_handler_t *) sys_swapon,
-	[ __NR_reboot ] = sys_reboot,
+	[ __NR_reboot ] (syscall_handler_t *) sys_reboot,
 	[ __NR_readdir ] = old_readdir,
-	[ __NR_munmap ] = sys_munmap,
-	[ __NR_truncate ] = sys_truncate,
-	[ __NR_ftruncate ] = sys_ftruncate,
-	[ __NR_fchmod ] = sys_fchmod,
-	[ __NR_fchown ] = sys_fchown16,
-	[ __NR_getpriority ] = sys_getpriority,
-	[ __NR_setpriority ] = sys_setpriority,
-	[ __NR_profil ] = sys_ni_syscall,
-	[ __NR_statfs ] = sys_statfs,
-	[ __NR_fstatfs ] = sys_fstatfs,
-	[ __NR_ioperm ] = sys_ni_syscall,
-	[ __NR_socketcall ] = sys_socketcall,
-	[ __NR_syslog ] = sys_syslog,
-	[ __NR_setitimer ] = sys_setitimer,
-	[ __NR_getitimer ] = sys_getitimer,
-	[ __NR_stat ] = sys_newstat,
-	[ __NR_lstat ] = sys_newlstat,
-	[ __NR_fstat ] = sys_newfstat,
-	[ __NR_olduname ] = sys_uname,
-	[ __NR_iopl ] = sys_ni_syscall,
-	[ __NR_vhangup ] = sys_vhangup,
-	[ __NR_idle ] = sys_ni_syscall,
+	[ __NR_munmap ] (syscall_handler_t *) sys_munmap,
+	[ __NR_truncate ] (syscall_handler_t *) sys_truncate,
+	[ __NR_ftruncate ] (syscall_handler_t *) sys_ftruncate,
+	[ __NR_fchmod ] (syscall_handler_t *) sys_fchmod,
+	[ __NR_fchown ] (syscall_handler_t *) sys_fchown16,
+	[ __NR_getpriority ] (syscall_handler_t *) sys_getpriority,
+	[ __NR_setpriority ] (syscall_handler_t *) sys_setpriority,
+	[ __NR_profil ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_statfs ] (syscall_handler_t *) sys_statfs,
+	[ __NR_fstatfs ] (syscall_handler_t *) sys_fstatfs,
+	[ __NR_ioperm ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_socketcall ] (syscall_handler_t *) sys_socketcall,
+	[ __NR_syslog ] (syscall_handler_t *) sys_syslog,
+	[ __NR_setitimer ] (syscall_handler_t *) sys_setitimer,
+	[ __NR_getitimer ] (syscall_handler_t *) sys_getitimer,
+	[ __NR_stat ] (syscall_handler_t *) sys_newstat,
+	[ __NR_lstat ] (syscall_handler_t *) sys_newlstat,
+	[ __NR_fstat ] (syscall_handler_t *) sys_newfstat,
+	[ __NR_olduname ] (syscall_handler_t *) sys_uname,
+	[ __NR_iopl ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_vhangup ] (syscall_handler_t *) sys_vhangup,
+	[ __NR_idle ] (syscall_handler_t *) sys_ni_syscall,
 	[ __NR_wait4 ] = (syscall_handler_t *) sys_wait4,
 	[ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff,
-	[ __NR_sysinfo ] = sys_sysinfo,
-	[ __NR_ipc ] = sys_ipc,
-	[ __NR_fsync ] = sys_fsync,
-	[ __NR_sigreturn ] = sys_sigreturn,
-	[ __NR_clone ] = sys_clone,
-	[ __NR_setdomainname ] = sys_setdomainname,
-	[ __NR_uname ] = sys_newuname,
-	[ __NR_adjtimex ] = sys_adjtimex,
-	[ __NR_mprotect ] = sys_mprotect,
-	[ __NR_sigprocmask ] = sys_sigprocmask,
-	[ __NR_create_module ] = sys_ni_syscall,
-	[ __NR_init_module ] = sys_init_module,
-	[ __NR_delete_module ] = sys_delete_module,
-	[ __NR_get_kernel_syms ] = sys_ni_syscall,
-	[ __NR_quotactl ] = sys_quotactl,
-	[ __NR_getpgid ] = sys_getpgid,
-	[ __NR_fchdir ] = sys_fchdir,
-	[ __NR_bdflush ] = sys_bdflush,
-	[ __NR_sysfs ] = sys_sysfs,
-	[ __NR_personality ] = sys_personality,
-	[ __NR_afs_syscall ] = sys_ni_syscall,
-	[ __NR_setfsuid ] = sys_setfsuid16,
-	[ __NR_setfsgid ] = sys_setfsgid16,
-	[ __NR__llseek ] = sys_llseek,
-	[ __NR_getdents ] = sys_getdents,
+	[ __NR_sysinfo ] (syscall_handler_t *) sys_sysinfo,
+	[ __NR_ipc ] (syscall_handler_t *) sys_ipc,
+	[ __NR_fsync ] (syscall_handler_t *) sys_fsync,
+	[ __NR_sigreturn ] (syscall_handler_t *) sys_sigreturn,
+	[ __NR_clone ] (syscall_handler_t *) sys_clone,
+	[ __NR_setdomainname ] (syscall_handler_t *) sys_setdomainname,
+	[ __NR_uname ] (syscall_handler_t *) sys_newuname,
+	[ __NR_adjtimex ] (syscall_handler_t *) sys_adjtimex,
+	[ __NR_mprotect ] (syscall_handler_t *) sys_mprotect,
+	[ __NR_sigprocmask ] (syscall_handler_t *) sys_sigprocmask,
+	[ __NR_create_module ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_init_module ] (syscall_handler_t *) sys_init_module,
+	[ __NR_delete_module ] (syscall_handler_t *) sys_delete_module,
+	[ __NR_get_kernel_syms ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_quotactl ] (syscall_handler_t *) sys_quotactl,
+	[ __NR_getpgid ] (syscall_handler_t *) sys_getpgid,
+	[ __NR_fchdir ] (syscall_handler_t *) sys_fchdir,
+	[ __NR_bdflush ] (syscall_handler_t *) sys_bdflush,
+	[ __NR_sysfs ] (syscall_handler_t *) sys_sysfs,
+	[ __NR_personality ] (syscall_handler_t *) sys_personality,
+	[ __NR_afs_syscall ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_setfsuid ] (syscall_handler_t *) sys_setfsuid16,
+	[ __NR_setfsgid ] (syscall_handler_t *) sys_setfsgid16,
+	[ __NR__llseek ] (syscall_handler_t *) sys_llseek,
+	[ __NR_getdents ] (syscall_handler_t *) sys_getdents,
 	[ __NR__newselect ] = (syscall_handler_t *) sys_select,
-	[ __NR_flock ] = sys_flock,
-	[ __NR_msync ] = sys_msync,
-	[ __NR_readv ] = sys_readv,
-	[ __NR_writev ] = sys_writev,
-	[ __NR_getsid ] = sys_getsid,
-	[ __NR_fdatasync ] = sys_fdatasync,
+	[ __NR_flock ] (syscall_handler_t *) sys_flock,
+	[ __NR_msync ] (syscall_handler_t *) sys_msync,
+	[ __NR_readv ] (syscall_handler_t *) sys_readv,
+	[ __NR_writev ] (syscall_handler_t *) sys_writev,
+	[ __NR_getsid ] (syscall_handler_t *) sys_getsid,
+	[ __NR_fdatasync ] (syscall_handler_t *) sys_fdatasync,
 	[ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl,
-	[ __NR_mlock ] = sys_mlock,
-	[ __NR_munlock ] = sys_munlock,
-	[ __NR_mlockall ] = sys_mlockall,
-	[ __NR_munlockall ] = sys_munlockall,
-	[ __NR_sched_setparam ] = sys_sched_setparam,
-	[ __NR_sched_getparam ] = sys_sched_getparam,
-	[ __NR_sched_setscheduler ] = sys_sched_setscheduler,
-	[ __NR_sched_getscheduler ] = sys_sched_getscheduler,
+	[ __NR_mlock ] (syscall_handler_t *) sys_mlock,
+	[ __NR_munlock ] (syscall_handler_t *) sys_munlock,
+	[ __NR_mlockall ] (syscall_handler_t *) sys_mlockall,
+	[ __NR_munlockall ] (syscall_handler_t *) sys_munlockall,
+	[ __NR_sched_setparam ] (syscall_handler_t *) sys_sched_setparam,
+	[ __NR_sched_getparam ] (syscall_handler_t *) sys_sched_getparam,
+	[ __NR_sched_setscheduler ] (syscall_handler_t *) sys_sched_setscheduler,
+	[ __NR_sched_getscheduler ] (syscall_handler_t *) sys_sched_getscheduler,
 	[ __NR_sched_yield ] = (syscall_handler_t *) yield,
-	[ __NR_sched_get_priority_max ] = sys_sched_get_priority_max,
-	[ __NR_sched_get_priority_min ] = sys_sched_get_priority_min,
-	[ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval,
-	[ __NR_nanosleep ] = sys_nanosleep,
-	[ __NR_mremap ] = sys_mremap,
-	[ __NR_setresuid ] = sys_setresuid16,
-	[ __NR_getresuid ] = sys_getresuid16,
-	[ __NR_vm86 ] = sys_ni_syscall,
-	[ __NR_query_module ] = sys_ni_syscall,
-	[ __NR_poll ] = sys_poll,
-	[ __NR_nfsservctl ] = NFSSERVCTL,
-	[ __NR_setresgid ] = sys_setresgid16,
-	[ __NR_getresgid ] = sys_getresgid16,
-	[ __NR_prctl ] = sys_prctl,
-	[ __NR_rt_sigreturn ] = sys_rt_sigreturn,
-	[ __NR_rt_sigaction ] = sys_rt_sigaction,
-	[ __NR_rt_sigprocmask ] = sys_rt_sigprocmask,
-	[ __NR_rt_sigpending ] = sys_rt_sigpending,
-	[ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait,
-	[ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo,
-	[ __NR_rt_sigsuspend ] = sys_rt_sigsuspend,
-	[ __NR_pread64 ] = sys_pread64,
-	[ __NR_pwrite64 ] = sys_pwrite64,
-	[ __NR_chown ] = sys_chown16,
-	[ __NR_getcwd ] = sys_getcwd,
-	[ __NR_capget ] = sys_capget,
-	[ __NR_capset ] = sys_capset,
-	[ __NR_sigaltstack ] = sys_sigaltstack,
-	[ __NR_sendfile ] = sys_sendfile,
-	[ __NR_getpmsg ] = sys_ni_syscall,
-	[ __NR_putpmsg ] = sys_ni_syscall,
-	[ __NR_vfork ] = sys_vfork,
-	[ __NR_ugetrlimit ] = sys_getrlimit,
-	[ __NR_mmap2 ] = sys_mmap2,
-	[ __NR_truncate64 ] = sys_truncate64,
-	[ __NR_ftruncate64 ] = sys_ftruncate64,
-	[ __NR_stat64 ] = sys_stat64,
-	[ __NR_lstat64 ] = sys_lstat64,
-	[ __NR_fstat64 ] = sys_fstat64,
-	[ __NR_fcntl64 ] = sys_fcntl64,
-	[ __NR_getdents64 ] = sys_getdents64,
-	[ __NR_gettid ] = sys_gettid,
-	[ __NR_readahead ] = sys_readahead,
-	[ __NR_setxattr ] = sys_ni_syscall,
-	[ __NR_lsetxattr ] = sys_ni_syscall,
-	[ __NR_fsetxattr ] = sys_ni_syscall,
-	[ __NR_getxattr ] = sys_ni_syscall,
-	[ __NR_lgetxattr ] = sys_ni_syscall,
-	[ __NR_fgetxattr ] = sys_ni_syscall,
-	[ __NR_listxattr ] = sys_ni_syscall,
-	[ __NR_llistxattr ] = sys_ni_syscall,
-	[ __NR_flistxattr ] = sys_ni_syscall,
-	[ __NR_removexattr ] = sys_ni_syscall,
-	[ __NR_lremovexattr ] = sys_ni_syscall,
-	[ __NR_fremovexattr ] = sys_ni_syscall,
-	[ __NR_tkill ] = sys_tkill,
-	[ __NR_sendfile64 ] = sys_sendfile64,
-	[ __NR_futex ] = sys_futex,
-	[ __NR_sched_setaffinity ] = sys_sched_setaffinity,
-	[ __NR_sched_getaffinity ] = sys_sched_getaffinity,
-	[ __NR_io_setup ] = sys_io_setup,
-	[ __NR_io_destroy ] = sys_io_destroy,
-	[ __NR_io_getevents ] = sys_io_getevents,
-	[ __NR_io_submit ] = sys_io_submit,
-	[ __NR_io_cancel ] = sys_io_cancel,
-	[ __NR_exit_group ] = sys_exit_group,
-	[ __NR_lookup_dcookie ] = sys_lookup_dcookie,
-	[ __NR_epoll_create ] = sys_epoll_create,
-	[ __NR_epoll_ctl ] = sys_epoll_ctl,
-	[ __NR_epoll_wait ] = sys_epoll_wait,
-        [ __NR_remap_file_pages ] = sys_remap_file_pages,
-        [ __NR_set_tid_address ] = sys_set_tid_address,
+	[ __NR_sched_get_priority_max ] (syscall_handler_t *) sys_sched_get_priority_max,
+	[ __NR_sched_get_priority_min ] (syscall_handler_t *) sys_sched_get_priority_min,
+	[ __NR_sched_rr_get_interval ] (syscall_handler_t *) sys_sched_rr_get_interval,
+	[ __NR_nanosleep ] (syscall_handler_t *) sys_nanosleep,
+	[ __NR_mremap ] (syscall_handler_t *) sys_mremap,
+	[ __NR_setresuid ] (syscall_handler_t *) sys_setresuid16,
+	[ __NR_getresuid ] (syscall_handler_t *) sys_getresuid16,
+	[ __NR_vm86 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_query_module ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_poll ] (syscall_handler_t *) sys_poll,
+	[ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL,
+	[ __NR_setresgid ] (syscall_handler_t *) sys_setresgid16,
+	[ __NR_getresgid ] (syscall_handler_t *) sys_getresgid16,
+	[ __NR_prctl ] (syscall_handler_t *) sys_prctl,
+	[ __NR_rt_sigreturn ] (syscall_handler_t *) sys_rt_sigreturn,
+	[ __NR_rt_sigaction ] (syscall_handler_t *) sys_rt_sigaction,
+	[ __NR_rt_sigprocmask ] (syscall_handler_t *) sys_rt_sigprocmask,
+	[ __NR_rt_sigpending ] (syscall_handler_t *) sys_rt_sigpending,
+	[ __NR_rt_sigtimedwait ] (syscall_handler_t *) sys_rt_sigtimedwait,
+	[ __NR_rt_sigqueueinfo ] (syscall_handler_t *) sys_rt_sigqueueinfo,
+	[ __NR_rt_sigsuspend ] (syscall_handler_t *) sys_rt_sigsuspend,
+	[ __NR_pread64 ] (syscall_handler_t *) sys_pread64,
+	[ __NR_pwrite64 ] (syscall_handler_t *) sys_pwrite64,
+	[ __NR_chown ] (syscall_handler_t *) sys_chown16,
+	[ __NR_getcwd ] (syscall_handler_t *) sys_getcwd,
+	[ __NR_capget ] (syscall_handler_t *) sys_capget,
+	[ __NR_capset ] (syscall_handler_t *) sys_capset,
+	[ __NR_sigaltstack ] (syscall_handler_t *) sys_sigaltstack,
+	[ __NR_sendfile ] (syscall_handler_t *) sys_sendfile,
+	[ __NR_getpmsg ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_putpmsg ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_vfork ] (syscall_handler_t *) sys_vfork,
+	[ __NR_ugetrlimit ] (syscall_handler_t *) sys_getrlimit,
+	[ __NR_mmap2 ] (syscall_handler_t *) sys_mmap2,
+	[ __NR_truncate64 ] (syscall_handler_t *) sys_truncate64,
+	[ __NR_ftruncate64 ] (syscall_handler_t *) sys_ftruncate64,
+	[ __NR_stat64 ] (syscall_handler_t *) sys_stat64,
+	[ __NR_lstat64 ] (syscall_handler_t *) sys_lstat64,
+	[ __NR_fstat64 ] (syscall_handler_t *) sys_fstat64,
+	[ __NR_getdents64 ] (syscall_handler_t *) sys_getdents64,
+	[ __NR_fcntl64 ] (syscall_handler_t *) sys_fcntl64,
+	[ 223 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_gettid ] (syscall_handler_t *) sys_gettid,
+	[ __NR_readahead ] (syscall_handler_t *) sys_readahead,
+	[ __NR_setxattr ] (syscall_handler_t *) sys_setxattr,
+	[ __NR_lsetxattr ] (syscall_handler_t *) sys_lsetxattr,
+	[ __NR_fsetxattr ] (syscall_handler_t *) sys_fsetxattr,
+	[ __NR_getxattr ] (syscall_handler_t *) sys_getxattr,
+	[ __NR_lgetxattr ] (syscall_handler_t *) sys_lgetxattr,
+	[ __NR_fgetxattr ] (syscall_handler_t *) sys_fgetxattr,
+	[ __NR_listxattr ] (syscall_handler_t *) sys_listxattr,
+	[ __NR_llistxattr ] (syscall_handler_t *) sys_llistxattr,
+	[ __NR_flistxattr ] (syscall_handler_t *) sys_flistxattr,
+	[ __NR_removexattr ] (syscall_handler_t *) sys_removexattr,
+	[ __NR_lremovexattr ] (syscall_handler_t *) sys_lremovexattr,
+	[ __NR_fremovexattr ] (syscall_handler_t *) sys_fremovexattr,
+	[ __NR_tkill ] (syscall_handler_t *) sys_tkill,
+	[ __NR_sendfile64 ] (syscall_handler_t *) sys_sendfile64,
+	[ __NR_futex ] (syscall_handler_t *) sys_futex,
+	[ __NR_sched_setaffinity ] (syscall_handler_t *) sys_sched_setaffinity,
+	[ __NR_sched_getaffinity ] (syscall_handler_t *) sys_sched_getaffinity,
+	[ __NR_set_thread_area ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_get_thread_area ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_io_setup ] (syscall_handler_t *) sys_io_setup,
+	[ __NR_io_destroy ] (syscall_handler_t *) sys_io_destroy,
+	[ __NR_io_getevents ] (syscall_handler_t *) sys_io_getevents,
+	[ __NR_io_submit ] (syscall_handler_t *) sys_io_submit,
+	[ __NR_io_cancel ] (syscall_handler_t *) sys_io_cancel,
+	[ __NR_fadvise64 ] (syscall_handler_t *) sys_fadvise64,
+	[ 251 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_exit_group ] (syscall_handler_t *) sys_exit_group,
+	[ __NR_lookup_dcookie ] (syscall_handler_t *) sys_lookup_dcookie,
+	[ __NR_epoll_create ] (syscall_handler_t *) sys_epoll_create,
+	[ __NR_epoll_ctl ] (syscall_handler_t *) sys_epoll_ctl,
+	[ __NR_epoll_wait ] (syscall_handler_t *) sys_epoll_wait,
+        [ __NR_remap_file_pages ] (syscall_handler_t *) sys_remap_file_pages,
+        [ __NR_set_tid_address ] (syscall_handler_t *) sys_set_tid_address,
+	[ __NR_timer_create ] (syscall_handler_t *) sys_timer_create,
+	[ __NR_timer_settime ] (syscall_handler_t *) sys_timer_settime,
+	[ __NR_timer_gettime ] (syscall_handler_t *) sys_timer_gettime,
+	[ __NR_timer_getoverrun ] (syscall_handler_t *) sys_timer_getoverrun,
+	[ __NR_timer_delete ] (syscall_handler_t *) sys_timer_delete,
+	[ __NR_clock_settime ] (syscall_handler_t *) sys_clock_settime,
+	[ __NR_clock_gettime ] (syscall_handler_t *) sys_clock_gettime,
+	[ __NR_clock_getres ] (syscall_handler_t *) sys_clock_getres,
+	[ __NR_clock_nanosleep ] (syscall_handler_t *) sys_clock_nanosleep,
+	[ __NR_statfs64 ] (syscall_handler_t *) sys_statfs64,
+	[ __NR_fstatfs64 ] (syscall_handler_t *) sys_fstatfs64,
+	[ __NR_tgkill ] (syscall_handler_t *) sys_tgkill,
+	[ __NR_utimes ] (syscall_handler_t *) sys_utimes,
+	[ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64,
+	[ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall,
 
 	ARCH_SYSCALLS
 	[ LAST_SYSCALL + 1 ... NR_syscalls ] = 
diff -puN arch/um/kernel/sysrq.c~uml-base-patch arch/um/kernel/sysrq.c
--- 25/arch/um/kernel/sysrq.c~uml-base-patch	2004-08-15 20:45:08.423374384 -0700
+++ 25-akpm/arch/um/kernel/sysrq.c	2004-08-15 20:46:03.275035664 -0700
@@ -44,6 +44,11 @@ void dump_stack(void)
 }
 EXPORT_SYMBOL(dump_stack);
 
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+	show_trace(sp);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN arch/um/kernel/tempfile.c~uml-base-patch arch/um/kernel/tempfile.c
--- 25/arch/um/kernel/tempfile.c~uml-base-patch	2004-08-15 20:45:08.424374232 -0700
+++ 25-akpm/arch/um/kernel/tempfile.c	2004-08-15 20:46:03.276035512 -0700
@@ -28,6 +28,7 @@ static void __init find_tempdir(void)
 	}
 	if((dir == NULL) || (*dir == '\0')) 
 		dir = "/tmp";
+
 	tempdir = malloc(strlen(dir) + 2);
 	if(tempdir == NULL){
 		fprintf(stderr, "Failed to malloc tempdir, "
@@ -49,7 +50,8 @@ int make_tempfile(const char *template, 
 	else
 		*tempname = 0;
 	strcat(tempname, template);
-	if((fd = mkstemp(tempname)) < 0){
+	fd = mkstemp(tempname);
+	if(fd < 0){
 		fprintf(stderr, "open - cannot create %s: %s\n", tempname, 
 			strerror(errno));
 		return -1;
@@ -59,7 +61,8 @@ int make_tempfile(const char *template, 
 		return -1;
 	}
 	if(out_tempname){
-		if((*out_tempname = strdup(tempname)) == NULL){
+		*out_tempname = strdup(tempname);
+		if(*out_tempname == NULL){
 			perror("strdup");
 			return -1;
 		}
diff -puN arch/um/kernel/time.c~uml-base-patch arch/um/kernel/time.c
--- 25/arch/um/kernel/time.c~uml-base-patch	2004-08-15 20:45:08.425374080 -0700
+++ 25-akpm/arch/um/kernel/time.c	2004-08-15 20:46:03.276035512 -0700
@@ -4,24 +4,33 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <time.h>
 #include <sys/time.h>
 #include <signal.h>
 #include <errno.h>
-#include "linux/module.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "process.h"
 #include "signal_user.h"
 #include "time_user.h"
+#include "kern_constants.h"
+
+/* XXX This really needs to be declared and initialized in a kernel file since
+ * it's in <linux/time.h>
+ */
+extern struct timespec wall_to_monotonic;
 
 extern struct timeval xtime;
 
+struct timeval local_offset = { 0, 0 };
+
 void timer(void)
 {
 	gettimeofday(&xtime, NULL);
+	timeradd(&xtime, &local_offset, &xtime);
 }
 
 void set_interval(int timer_type)
@@ -66,7 +75,7 @@ void switch_timers(int to_real)
 		       errno);
 }
 
-void idle_timer(void)
+void uml_idle_timer(void)
 {
 	if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
 		panic("Couldn't unset SIGVTALRM handler");
@@ -76,14 +85,60 @@ void idle_timer(void)
 	set_interval(ITIMER_REAL);
 }
 
+static unsigned long long get_host_hz(void)
+{
+	char mhzline[16], *end;
+	unsigned long long mhz;
+	int ret, mult, rest, len;
+
+	ret = cpu_feature("cpu MHz", mhzline,
+			  sizeof(mhzline) / sizeof(mhzline[0]));
+	if(!ret)
+		panic ("Could not get host MHZ");
+
+	mhz = strtoul(mhzline, &end, 10);
+
+	/* This business is to parse a floating point number without using
+	 * floating types.
+	 */
+
+	rest = 0;
+	mult = 0;
+	if(*end == '.'){
+		end++;
+		len = strlen(end);
+		if(len < 6)
+			mult = 6 - len;
+		else if(len > 6)
+			end[6] = '\0';
+		rest = strtoul(end, NULL, 10);
+		while(mult-- > 0)
+			rest *= 10;
+	}
+
+	return(1000000 * mhz + rest);
+}
+
+unsigned long long host_hz = 0;
+
+extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
+
 void time_init(void)
 {
+	struct timespec now;
+
+	host_hz = get_host_hz();
 	if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
 		panic("Couldn't set SIGVTALRM handler");
 	set_interval(ITIMER_VIRTUAL);
+
+	do_posix_clock_monotonic_gettime(&now);
+	wall_to_monotonic.tv_sec = -now.tv_sec;
+	wall_to_monotonic.tv_nsec = -now.tv_nsec;
 }
 
-struct timeval local_offset = { 0, 0 };
+/* Declared in linux/time.h, which can't be included here */
+extern void clock_was_set(void);
 
 void do_gettimeofday(struct timeval *tv)
 {
@@ -96,15 +151,13 @@ void do_gettimeofday(struct timeval *tv)
 	clock_was_set();
 }
 
-EXPORT_SYMBOL(do_gettimeofday);
-
 int do_settimeofday(struct timespec *tv)
 {
 	struct timeval now;
 	unsigned long flags;
 	struct timeval tv_in;
 
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+	if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC)
 		return -EINVAL;
 
 	tv_in.tv_sec = tv->tv_sec;
@@ -114,9 +167,9 @@ int do_settimeofday(struct timespec *tv)
 	gettimeofday(&now, NULL);
 	timersub(&tv_in, &now, &local_offset);
 	time_unlock(flags);
-}
 
-EXPORT_SYMBOL(do_settimeofday);
+	return(0);
+}
 
 void idle_sleep(int secs)
 {
diff -puN arch/um/kernel/time_kern.c~uml-base-patch arch/um/kernel/time_kern.c
--- 25/arch/um/kernel/time_kern.c~uml-base-patch	2004-08-15 20:45:08.427373776 -0700
+++ 25-akpm/arch/um/kernel/time_kern.c	2004-08-15 20:46:03.277035360 -0700
@@ -30,22 +30,58 @@ int hz(void)
 	return(HZ);
 }
 
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+	return (unsigned long long)jiffies_64 * (1000000000 / HZ);
+}
+
 /* Changed at early boot */
 int timer_irq_inited = 0;
 
-/* missed_ticks will be modified after kernel memory has been 
- * write-protected, so this puts it in a section which will be left 
- * write-enabled.
- */
-int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS];
+static int first_tick;
+static unsigned long long prev_tsc;
+static long long delta;   		/* Deviation per interval */
+
+extern unsigned long long host_hz;
 
 void timer_irq(union uml_pt_regs *regs)
 {
-	int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu];
+	unsigned long long ticks = 0;
+
+	if(!timer_irq_inited){
+		/* This is to ensure that ticks don't pile up when
+		 * the timer handler is suspended */
+		first_tick = 0;
+		return;
+	}
 
-        if(!timer_irq_inited) return;
-	missed_ticks[cpu] = 0;
-	while(ticks--) do_IRQ(TIMER_IRQ, regs);
+	if(first_tick){
+#if defined(CONFIG_UML_REAL_TIME_CLOCK)
+		unsigned long long tsc;
+		/* We've had 1 tick */
+		tsc = time_stamp();
+
+		delta += tsc - prev_tsc;
+		prev_tsc = tsc;
+
+		ticks += (delta * HZ) / host_hz;
+		delta -= (ticks * host_hz) / HZ;
+#else
+		ticks = 1;
+#endif
+	}
+	else {
+		prev_tsc = time_stamp();
+		first_tick = 1;
+	}
+
+	while(ticks > 0){
+		do_IRQ(TIMER_IRQ, regs);
+		ticks--;
+	}
 }
 
 void boot_timer_handler(int sig)
@@ -58,12 +94,15 @@ void boot_timer_handler(int sig)
 	do_timer(&regs);
 }
 
-void um_timer(int irq, void *dev, struct pt_regs *regs)
+irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
 {
+	unsigned long flags;
+
 	do_timer(regs);
-	write_seqlock(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock, flags);
 	timer();
-	write_sequnlock(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+	return(IRQ_HANDLED);
 }
 
 long um_time(int * tloc)
@@ -81,12 +120,12 @@ long um_time(int * tloc)
 long um_stime(int * tptr)
 {
 	int value;
-	struct timeval new;
+	struct timespec new;
 
 	if (get_user(value, tptr))
                 return -EFAULT;
 	new.tv_sec = value;
-	new.tv_usec = 0;
+	new.tv_nsec = 0;
 	do_settimeofday(&new);
 	return 0;
 }
@@ -125,9 +164,11 @@ void __const_udelay(um_udelay_t usecs)
 void timer_handler(int sig, union uml_pt_regs *regs)
 {
 #ifdef CONFIG_SMP
+	local_irq_disable();
 	update_process_times(user_context(UPT_SP(regs)));
+	local_irq_enable();
 #endif
-	if(current->thread_info->cpu == 0)
+	if(current_thread->cpu == 0)
 		timer_irq(regs);
 }
 
@@ -136,6 +177,7 @@ static spinlock_t timer_spinlock = SPIN_
 unsigned long time_lock(void)
 {
 	unsigned long flags;
+
 	spin_lock_irqsave(&timer_spinlock, flags);
 	return(flags);
 }
@@ -150,8 +192,8 @@ int __init timer_init(void)
 	int err;
 
 	CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
-	if((err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", 
-			      NULL)) != 0)
+	err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
+	if(err != 0)
 		printk(KERN_ERR "timer_init : request_irq failed - "
 		       "errno = %d\n", -err);
 	timer_irq_inited = 1;
@@ -160,7 +202,6 @@ int __init timer_init(void)
 
 __initcall(timer_init);
 
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN arch/um/kernel/trap_kern.c~uml-base-patch arch/um/kernel/trap_kern.c
--- 25/arch/um/kernel/trap_kern.c~uml-base-patch	2004-08-15 20:45:08.428373624 -0700
+++ 25-akpm/arch/um/kernel/trap_kern.c	2004-08-15 20:46:03.278035208 -0700
@@ -16,12 +16,15 @@
 #include "asm/tlbflush.h"
 #include "asm/a.out.h"
 #include "asm/current.h"
+#include "asm/irq.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
 #include "chan_kern.h"
 #include "mconsole_kern.h"
 #include "2_5compat.h"
+#include "mem.h"
+#include "mem_kern.h"
 
 int handle_page_fault(unsigned long address, unsigned long ip, 
 		      int is_write, int is_user, int *code_out)
@@ -51,12 +54,12 @@ int handle_page_fault(unsigned long addr
 	if(is_write && !(vma->vm_flags & VM_WRITE)) 
 		goto out;
 	page = address & PAGE_MASK;
-	if(page == (unsigned long) current->thread_info + PAGE_SIZE)
+	if(page == (unsigned long) current_thread + PAGE_SIZE)
 		panic("Kernel stack overflow");
 	pgd = pgd_offset(mm, page);
 	pmd = pmd_offset(pgd, page);
- survive:
 	do {
+ survive:
 		switch (handle_mm_fault(mm, vma, address, is_write)){
 		case VM_FAULT_MINOR:
 			current->min_flt++;
@@ -71,14 +74,20 @@ int handle_page_fault(unsigned long addr
 			err = -ENOMEM;
 			goto out_of_memory;
 		default:
-			BUG();
+			if (current->pid == 1) {
+				up_read(&mm->mmap_sem);
+				yield();
+				down_read(&mm->mmap_sem);
+				goto survive;
+			}
+			goto out;
 		}
 		pte = pte_offset_kernel(pmd, page);
 	} while(!pte_present(*pte));
+	err = 0;
 	*pte = pte_mkyoung(*pte);
 	if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
 	flush_tlb_page(vma, page);
-	err = 0;
  out:
 	up_read(&mm->mmap_sem);
 	return(err);
@@ -98,6 +107,33 @@ out_of_memory:
 	goto out;
 }
 
+LIST_HEAD(physmem_remappers);
+
+void register_remapper(struct remapper *info)
+{
+	list_add(&info->list, &physmem_remappers);
+}
+
+static int check_remapped_addr(unsigned long address, int is_write)
+{
+	struct remapper *remapper;
+	struct list_head *ele;
+	__u64 offset;
+	int fd;
+
+	fd = phys_mapping(__pa(address), &offset);
+	if(fd == -1)
+		return(0);
+
+	list_for_each(ele, &physmem_remappers){
+		remapper = list_entry(ele, struct remapper, list);
+		if((*remapper->proc)(fd, address, is_write, offset))
+			return(1);
+	}
+
+	return(0);
+}
+
 unsigned long segv(unsigned long address, unsigned long ip, int is_write, 
 		   int is_user, void *sc)
 {
@@ -109,7 +145,9 @@ unsigned long segv(unsigned long address
                 flush_tlb_kernel_vm();
                 return(0);
         }
-        if(current->mm == NULL)
+	else if(check_remapped_addr(address & PAGE_MASK, is_write))
+		return(0);
+	else if(current->mm == NULL)
 		panic("Segfault with no mm");
 	err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
 
@@ -120,9 +158,8 @@ unsigned long segv(unsigned long address
 		current->thread.fault_addr = (void *) address;
 		do_longjmp(catcher, 1);
 	} 
-	else if(current->thread.fault_addr != NULL){
+	else if(current->thread.fault_addr != NULL)
 		panic("fault_addr set but no fault catcher");
-	}
 	else if(arch_fixup(ip, sc))
 		return(0);
 
@@ -155,8 +192,6 @@ void bad_segv(unsigned long address, uns
 {
 	struct siginfo si;
 
-	printk(KERN_ERR "Unfixable SEGV in '%s' (pid %d) at 0x%lx "
-	       "(ip 0x%lx)\n", current->comm, current->pid, address, ip);
 	si.si_signo = SIGSEGV;
 	si.si_code = SEGV_ACCERR;
 	si.si_addr = (void *) address;
@@ -180,6 +215,11 @@ void bus_handler(int sig, union uml_pt_r
 	else relay_signal(sig, regs);
 }
 
+void winch(int sig, union uml_pt_regs *regs)
+{
+	do_IRQ(WINCH_IRQ, regs);
+}
+
 void trap_init(void)
 {
 }
diff -puN arch/um/kernel/trap_user.c~uml-base-patch arch/um/kernel/trap_user.c
--- 25/arch/um/kernel/trap_user.c~uml-base-patch	2004-08-15 20:45:08.429373472 -0700
+++ 25-akpm/arch/um/kernel/trap_user.c	2004-08-15 20:46:03.279035056 -0700
@@ -5,11 +5,9 @@
 
 #include <stdlib.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/time.h>
-#include <sys/ioctl.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <asm/page.h>
@@ -82,6 +80,8 @@ struct signal_info sig_info[] = {
 		     .is_irq 		= 0 },
 	[ SIGILL ] { .handler 		= relay_signal,
 		     .is_irq 		= 0 },
+	[ SIGWINCH ] { .handler		= winch,
+		       .is_irq		= 1 },
 	[ SIGBUS ] { .handler 		= bus_handler,
 		     .is_irq 		= 0 },
 	[ SIGSEGV] { .handler 		= segv_handler,
@@ -102,12 +102,11 @@ void sig_handler(int sig, struct sigcont
 			 sig, &sc);
 }
 
-extern int timer_irq_inited, missed_ticks[];
+extern int timer_irq_inited;
 
 void alarm_handler(int sig, struct sigcontext sc)
 {
 	if(!timer_irq_inited) return;
-	missed_ticks[cpu()]++;
 
 	if(sig == SIGALRM)
 		switch_timers(0);
@@ -123,7 +122,7 @@ void do_longjmp(void *b, int val)
 {
 	jmp_buf *buf = b;
 
-	longjmp(*buf, val);
+	siglongjmp(*buf, val);
 }
 
 /*
diff -puN arch/um/kernel/tt/exec_kern.c~uml-base-patch arch/um/kernel/tt/exec_kern.c
--- 25/arch/um/kernel/tt/exec_kern.c~uml-base-patch	2004-08-15 20:45:08.430373320 -0700
+++ 25-akpm/arch/um/kernel/tt/exec_kern.c	2004-08-15 20:46:03.279035056 -0700
@@ -17,6 +17,7 @@
 #include "mem_user.h"
 #include "os.h"
 #include "tlb.h"
+#include "mode.h"
 
 static int exec_tramp(void *sig_stack)
 {
@@ -47,17 +48,17 @@ void flush_thread_tt(void)
 		do_exit(SIGKILL);
 	}
 
-	if(current->thread_info->cpu == 0)
+	if(current_thread->cpu == 0)
 		forward_interrupts(new_pid);
 	current->thread.request.op = OP_EXEC;
 	current->thread.request.u.exec.pid = new_pid;
-	unprotect_stack((unsigned long) current->thread_info);
+	unprotect_stack((unsigned long) current_thread);
 	os_usr1_process(os_getpid());
 
 	enable_timer();
 	free_page(stack);
 	protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
-	task_protections((unsigned long) current->thread_info);
+	task_protections((unsigned long) current_thread);
 	force_flush_all();
 	unblock_signals();
 }
diff -puN arch/um/kernel/tt/include/mode.h~uml-base-patch arch/um/kernel/tt/include/mode.h
--- 25/arch/um/kernel/tt/include/mode.h~uml-base-patch	2004-08-15 20:45:08.432373016 -0700
+++ 25-akpm/arch/um/kernel/tt/include/mode.h	2004-08-15 20:46:03.279035056 -0700
@@ -8,6 +8,8 @@
 
 #include "sysdep/ptrace.h"
 
+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
+
 extern int tracing_pid;
 
 extern int tracer(int (*init_proc)(void *), void *sp);
diff -puN arch/um/kernel/tt/include/uaccess.h~uml-base-patch arch/um/kernel/tt/include/uaccess.h
--- 25/arch/um/kernel/tt/include/uaccess.h~uml-base-patch	2004-08-15 20:45:08.433372864 -0700
+++ 25-akpm/arch/um/kernel/tt/include/uaccess.h	2004-08-15 20:46:03.280034904 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -43,65 +43,19 @@ extern unsigned long get_fault_addr(void
 
 extern int __do_copy_from_user(void *to, const void *from, int n,
 			       void **fault_addr, void **fault_catcher);
-
-static inline int copy_from_user_tt(void *to, const void *from, int n)
-{
-	return(access_ok_tt(VERIFY_READ, from, n) ?
-	       __do_copy_from_user(to, from, n, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher) : n);
-}
-
-static inline int copy_to_user_tt(void *to, const void *from, int n)
-{
-	return(access_ok_tt(VERIFY_WRITE, to, n) ?
-	       __do_copy_to_user(to, from, n, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher) : n);
-}
-
 extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
 				  void **fault_addr, void **fault_catcher);
-
-static inline int strncpy_from_user_tt(char *dst, const char *src, int count)
-{
-	int n;
-
-	if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT);
-	n = __do_strncpy_from_user(dst, src, count, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher);
-	if(n < 0) return(-EFAULT);
-	return(n);
-}
-
 extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
 			   void **fault_catcher);
-
-static inline int __clear_user_tt(void *mem, int len)
-{
-	return(__do_clear_user(mem, len,
-			       &current->thread.fault_addr,
-			       &current->thread.fault_catcher));
-}
-
-static inline int clear_user_tt(void *mem, int len)
-{
-	return(access_ok_tt(VERIFY_WRITE, mem, len) ? 
-	       __do_clear_user(mem, len, 
-			       &current->thread.fault_addr,
-			       &current->thread.fault_catcher) : len);
-}
-
 extern int __do_strnlen_user(const char *str, unsigned long n,
 			     void **fault_addr, void **fault_catcher);
 
-static inline int strnlen_user_tt(const void *str, int len)
-{
-	return(__do_strnlen_user(str, len,
-				 &current->thread.fault_addr,
-				 &current->thread.fault_catcher));
-}
+extern int copy_from_user_tt(void *to, const void *from, int n);
+extern int copy_to_user_tt(void *to, const void *from, int n);
+extern int strncpy_from_user_tt(char *dst, const char *src, int count);
+extern int __clear_user_tt(void *mem, int len);
+extern int clear_user_tt(void *mem, int len);
+extern int strnlen_user_tt(const void *str, int len);
 
 #endif
 
diff -puN arch/um/kernel/tt/Makefile~uml-base-patch arch/um/kernel/tt/Makefile
--- 25/arch/um/kernel/tt/Makefile~uml-base-patch	2004-08-15 20:45:08.434372712 -0700
+++ 25-akpm/arch/um/kernel/tt/Makefile	2004-08-15 20:46:03.280034904 -0700
@@ -1,5 +1,5 @@
 # 
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
 # Licensed under the GPL
 #
 
@@ -7,7 +7,7 @@ extra-y := unmap_fin.o
 
 obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
 	syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
-	uaccess_user.o sys-$(SUBARCH)/
+	uaccess.o uaccess_user.o sys-$(SUBARCH)/
 
 obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
 
@@ -27,5 +27,3 @@ $(obj)/unmap.o: $(src)/unmap.c
 
 $(obj)/unmap_fin.o : $(src)/unmap.o
 	ld -r -o $@ $< -lc -L/usr/lib
-
-clean :
diff -puN arch/um/kernel/tt/mem_user.c~uml-base-patch arch/um/kernel/tt/mem_user.c
--- 25/arch/um/kernel/tt/mem_user.c~uml-base-patch	2004-08-15 20:45:08.436372408 -0700
+++ 25-akpm/arch/um/kernel/tt/mem_user.c	2004-08-15 20:46:03.281034752 -0700
@@ -25,14 +25,13 @@ void remap_data(void *segment_start, voi
 	size = (unsigned long) segment_end - 
 		(unsigned long) segment_start;
 	data = create_mem_file(size);
-	if((addr = mmap(NULL, size, PROT_WRITE | PROT_READ, 
-			MAP_SHARED, data, 0)) == MAP_FAILED){
+	addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0);
+	if(addr == MAP_FAILED){
 		perror("mapping new data segment");
 		exit(1);
 	}
 	memcpy(addr, segment_start, size);
-	if(switcheroo(data, prot, addr, segment_start, 
-		      size) < 0){
+	if(switcheroo(data, prot, addr, segment_start, size) < 0){
 		printf("switcheroo failed\n");
 		exit(1);
 	}
diff -puN arch/um/kernel/tt/process_kern.c~uml-base-patch arch/um/kernel/tt/process_kern.c
--- 25/arch/um/kernel/tt/process_kern.c~uml-base-patch	2004-08-15 20:45:08.437372256 -0700
+++ 25-akpm/arch/um/kernel/tt/process_kern.c	2004-08-15 20:46:03.283034448 -0700
@@ -62,7 +62,7 @@ void *switch_to_tt(void *prev, void *nex
 	reading = 0;
 	err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
 	if(err != sizeof(c))
-		panic("write of switch_pipe failed, errno = %d", -err);
+		panic("write of switch_pipe failed, err = %d", -err);
 
 	reading = 1;
 	if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD))
@@ -104,48 +104,72 @@ void *switch_to_tt(void *prev, void *nex
 
 void release_thread_tt(struct task_struct *task)
 {
-	os_kill_process(task->thread.mode.tt.extern_pid, 0);
+	int pid = task->thread.mode.tt.extern_pid;
+
+	if(os_getpid() != pid)
+		os_kill_process(pid, 0);
 }
 
 void exit_thread_tt(void)
 {
-	close(current->thread.mode.tt.switch_pipe[0]);
-	close(current->thread.mode.tt.switch_pipe[1]);
+	os_close_file(current->thread.mode.tt.switch_pipe[0]);
+	os_close_file(current->thread.mode.tt.switch_pipe[1]);
 }
 
 void schedule_tail(task_t *prev);
 
 static void new_thread_handler(int sig)
 {
+	unsigned long disable;
 	int (*fn)(void *);
 	void *arg;
 
 	fn = current->thread.request.u.thread.proc;
 	arg = current->thread.request.u.thread.arg;
+
 	UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
+	disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
+		(1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
+	SC_SIGMASK(UPT_SC(&current->thread.regs.regs)) &= ~disable;
+
 	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 
-	block_signals();
+	force_flush_all();
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
+	current->thread.prev_sched = NULL;
+
 	init_new_thread_signals(1);
-#ifdef CONFIG_SMP
-	schedule_tail(current->thread.prev_sched);
-#endif
 	enable_timer();
 	free_page(current->thread.temp_stack);
 	set_cmdline("(kernel thread)");
-	force_flush_all();
 
-	current->thread.prev_sched = NULL;
 	change_sig(SIGUSR1, 1);
 	change_sig(SIGVTALRM, 1);
 	change_sig(SIGPROF, 1);
-	unblock_signals();
+	local_irq_enable();
 	if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
 		do_exit(0);
 }
 
 static int new_thread_proc(void *stack)
 {
+	/* local_irq_disable is needed to block out signals until this thread is
+	 * properly scheduled.  Otherwise, the tracing thread will get mighty
+	 * upset about any signals that arrive before that.
+	 * This has the complication that it sets the saved signal mask in
+	 * the sigcontext to block signals.  This gets restored when this
+	 * thread (or a descendant, since they get a copy of this sigcontext)
+	 * returns to userspace.
+	 * So, this is compensated for elsewhere.
+	 * XXX There is still a small window until local_irq_disable() actually
+	 * finishes where signals are possible - shouldn't be a problem in
+	 * practice since SIGIO hasn't been forwarded here yet, and the
+	 * local_irq_disable should finish before a SIGVTALRM has time to be
+	 * delivered.
+	 */
+
+	local_irq_disable();
 	init_new_thread_stack(stack, new_thread_handler);
 	os_usr1_process(os_getpid());
 	return(0);
@@ -156,7 +180,7 @@ static int new_thread_proc(void *stack)
  * itself with a SIGUSR1.  set_user_mode has to be run with SIGUSR1 off,
  * so it is blocked before it's called.  They are re-enabled on sigreturn
  * despite the fact that they were blocked when the SIGUSR1 was issued because
- * copy_thread copies the parent's signcontext, including the signal mask
+ * copy_thread copies the parent's sigcontext, including the signal mask
  * onto the signal frame.
  */
 
@@ -165,35 +189,32 @@ void finish_fork_handler(int sig)
  	UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
 	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 
-#ifdef CONFIG_SMP	
-	schedule_tail(NULL);
-#endif
+	force_flush_all();
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
+	current->thread.prev_sched = NULL;
+
 	enable_timer();
 	change_sig(SIGVTALRM, 1);
 	local_irq_enable();
-	force_flush_all();
 	if(current->mm != current->parent->mm)
 		protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 
 			       1, 0, 1);
-	task_protections((unsigned long) current->thread_info);
-
-	current->thread.prev_sched = NULL;
+	task_protections((unsigned long) current_thread);
 
 	free_page(current->thread.temp_stack);
+	local_irq_disable();
 	change_sig(SIGUSR1, 0);
 	set_user_mode(current);
 }
 
-static int sigusr1 = SIGUSR1;
-
 int fork_tramp(void *stack)
 {
-	int sig = sigusr1;
-
 	local_irq_disable();
+	arch_init_thread();
 	init_new_thread_stack(stack, finish_fork_handler);
 
-	kill(os_getpid(), sig);
+	os_usr1_process(os_getpid());
 	return(0);
 }
 
@@ -213,8 +234,8 @@ int copy_thread_tt(int nr, unsigned long
 	}
 
 	err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
-	if(err){
-		printk("copy_thread : pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("copy_thread : pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -377,8 +398,8 @@ static void mprotect_kernel_mem(int w)
 
 	pages = (1 << CONFIG_KERNEL_STACK_ORDER);
 
-	start = (unsigned long) current->thread_info + PAGE_SIZE;
-	end = (unsigned long) current + PAGE_SIZE * pages;
+	start = (unsigned long) current_thread + PAGE_SIZE;
+	end = (unsigned long) current_thread + PAGE_SIZE * pages;
 	protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
 	protect_memory(end, high_physmem - end, 1, w, 1, 1);
 
@@ -454,8 +475,9 @@ void set_init_pid(int pid)
 
 	init_task.thread.mode.tt.extern_pid = pid;
 	err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
-	if(err)	panic("Can't create switch pipe for init_task, errno = %d", 
-		      err);
+	if(err)
+		panic("Can't create switch pipe for init_task, errno = %d",
+		      -err);
 }
 
 int singlestepping_tt(void *t)
diff -puN arch/um/kernel/tt/ptproxy/Makefile~uml-base-patch arch/um/kernel/tt/ptproxy/Makefile
--- 25/arch/um/kernel/tt/ptproxy/Makefile~uml-base-patch	2004-08-15 20:45:08.438372104 -0700
+++ 25-akpm/arch/um/kernel/tt/ptproxy/Makefile	2004-08-15 20:46:03.283034448 -0700
@@ -9,5 +9,3 @@ USER_OBJS := $(foreach file,$(obj-y),$(s
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
diff -puN arch/um/kernel/tt/ptproxy/proxy.c~uml-base-patch arch/um/kernel/tt/ptproxy/proxy.c
--- 25/arch/um/kernel/tt/ptproxy/proxy.c~uml-base-patch	2004-08-15 20:45:08.440371800 -0700
+++ 25-akpm/arch/um/kernel/tt/ptproxy/proxy.c	2004-08-15 20:46:03.284034296 -0700
@@ -15,7 +15,6 @@ Jeff Dike (jdike@karaya.com) : Modified 
 #include <unistd.h>
 #include <signal.h>
 #include <string.h>
-#include <fcntl.h>
 #include <termios.h>
 #include <sys/wait.h>
 #include <sys/types.h>
@@ -293,10 +292,10 @@ void fake_child_exit(void)
 }
 
 char gdb_init_string[] = 
-"att 1
-b panic
-b stop
-handle SIGWINCH nostop noprint pass
+"att 1 \n\
+b panic \n\
+b stop \n\
+handle SIGWINCH nostop noprint pass \n\
 ";
 
 int start_debugger(char *prog, int startup, int stop, int *fd_out)
@@ -304,7 +303,8 @@ int start_debugger(char *prog, int start
 	int slave, child;
 
 	slave = open_gdb_chan();
-	if((child = fork()) == 0){
+	child = fork();
+	if(child == 0){
 		char *tempname = NULL;
 		int fd;
 
@@ -327,18 +327,19 @@ int start_debugger(char *prog, int start
 			exit(1);
 #endif
 		}
-		if((fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0)) < 0){
-			printk("start_debugger : make_tempfile failed, errno = %d\n",
-			       errno);
+		fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
+		if(fd < 0){
+			printk("start_debugger : make_tempfile failed,"
+			       "err = %d\n", -fd);
 			exit(1);
 		}
-		write(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
+		os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
 		if(startup){
 			if(stop){
-				write(fd, "b start_kernel\n",
+				os_write_file(fd, "b start_kernel\n",
 				      strlen("b start_kernel\n"));
 			}
-			write(fd, "c\n", strlen("c\n"));
+			os_write_file(fd, "c\n", strlen("c\n"));
 		}
 		if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
 			printk("start_debugger :  PTRACE_TRACEME failed, "
diff -puN arch/um/kernel/tt/ptproxy/sysdep.c~uml-base-patch arch/um/kernel/tt/ptproxy/sysdep.c
--- 25/arch/um/kernel/tt/ptproxy/sysdep.c~uml-base-patch	2004-08-15 20:45:08.441371648 -0700
+++ 25-akpm/arch/um/kernel/tt/ptproxy/sysdep.c	2004-08-15 20:46:03.284034296 -0700
@@ -9,6 +9,7 @@ terms and conditions.
 #include <string.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <asm/ptrace.h>
diff -puN arch/um/kernel/tt/ptproxy/wait.c~uml-base-patch arch/um/kernel/tt/ptproxy/wait.c
--- 25/arch/um/kernel/tt/ptproxy/wait.c~uml-base-patch	2004-08-15 20:45:08.442371496 -0700
+++ 25-akpm/arch/um/kernel/tt/ptproxy/wait.c	2004-08-15 20:46:03.285034144 -0700
@@ -56,21 +56,23 @@ int parent_wait_return(struct debugger *
 int real_wait_return(struct debugger *debugger)
 {
 	unsigned long ip;
-	int err, pid;
+	int pid;
 
 	pid = debugger->pid;
+
 	ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
-	ip = IP_RESTART_SYSCALL(ip);
-	err = ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip);
+	IP_RESTART_SYSCALL(ip);
+
 	if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0)
 		tracer_panic("real_wait_return : Failed to restart system "
-			     "call, errno = %d\n");
+			     "call, errno = %d\n", errno);
+
 	if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
 	   (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
 	   (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
 	   debugger_normal_return(debugger, -1))
 		tracer_panic("real_wait_return : gdb failed to wait, "
-			     "errno = %d\n");
+			     "errno = %d\n", errno);
 	return(0);
 }
 
diff -puN arch/um/kernel/tt/syscall_kern.c~uml-base-patch arch/um/kernel/tt/syscall_kern.c
--- 25/arch/um/kernel/tt/syscall_kern.c~uml-base-patch	2004-08-15 20:45:08.443371344 -0700
+++ 25-akpm/arch/um/kernel/tt/syscall_kern.c	2004-08-15 20:46:03.285034144 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
diff -puN arch/um/kernel/tt/syscall_user.c~uml-base-patch arch/um/kernel/tt/syscall_user.c
--- 25/arch/um/kernel/tt/syscall_user.c~uml-base-patch	2004-08-15 20:45:08.445371040 -0700
+++ 25-akpm/arch/um/kernel/tt/syscall_user.c	2004-08-15 20:46:03.286033992 -0700
@@ -33,7 +33,7 @@ void syscall_handler_tt(int sig, union u
 	SC_START_SYSCALL(sc);
 
 	index = record_syscall_start(syscall);
-	syscall_trace();
+	syscall_trace(regs, 1);
 	result = execute_syscall(regs);
 
 	/* regs->sc may have changed while the system call ran (there may
@@ -46,7 +46,7 @@ void syscall_handler_tt(int sig, union u
 	   (result == -ERESTARTNOINTR))
 		do_signal(result);
 
-	syscall_trace();
+	syscall_trace(regs, 0);
 	record_syscall_end(index, result);
 }
 
diff -puN arch/um/kernel/tt/sys-i386/Makefile~uml-base-patch arch/um/kernel/tt/sys-i386/Makefile
--- 25/arch/um/kernel/tt/sys-i386/Makefile~uml-base-patch	2004-08-15 20:45:08.446370888 -0700
+++ 25-akpm/arch/um/kernel/tt/sys-i386/Makefile	2004-08-15 20:46:03.286033992 -0700
@@ -10,5 +10,3 @@ USER_OBJS := $(foreach file,$(USER_OBJS)
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
diff -puN arch/um/kernel/tt/tlb.c~uml-base-patch arch/um/kernel/tt/tlb.c
--- 25/arch/um/kernel/tt/tlb.c~uml-base-patch	2004-08-15 20:45:08.447370736 -0700
+++ 25-akpm/arch/um/kernel/tt/tlb.c	2004-08-15 20:46:03.286033992 -0700
@@ -10,6 +10,7 @@
 #include "asm/page.h"
 #include "asm/pgtable.h"
 #include "asm/uaccess.h"
+#include "asm/tlbflush.h"
 #include "user_util.h"
 #include "mem_user.h"
 #include "os.h"
diff -puN arch/um/kernel/tt/tracer.c~uml-base-patch arch/um/kernel/tt/tracer.c
--- 25/arch/um/kernel/tt/tracer.c~uml-base-patch	2004-08-15 20:45:08.449370432 -0700
+++ 25-akpm/arch/um/kernel/tt/tracer.c	2004-08-15 20:46:03.287033840 -0700
@@ -39,16 +39,17 @@ int is_tracer_winch(int pid, int fd, voi
 		return(0);
 
 	register_winch_irq(tracer_winch[0], fd, -1, data);
-	return(0);
+	return(1);
 }
 
 static void tracer_winch_handler(int sig)
 {
+	int n;
 	char c = 1;
 
-	if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c))
-		printk("tracer_winch_handler - write failed, errno = %d\n",
-		       errno);
+	n = os_write_file(tracer_winch[1], &c, sizeof(c));
+	if(n != sizeof(c))
+		printk("tracer_winch_handler - write failed, err = %d\n", -n);
 }
 
 /* Called only by the tracing thread during initialization */
@@ -58,9 +59,8 @@ static void setup_tracer_winch(void)
 	int err;
 
 	err = os_pipe(tracer_winch, 1, 1);
-	if(err){
-		printk("setup_tracer_winch : os_pipe failed, errno = %d\n", 
-		       -err);
+	if(err < 0){
+		printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
 		return;
 	}
 	signal(SIGWINCH, tracer_winch_handler);
@@ -130,8 +130,8 @@ static void sleeping_process_signal(int 
 	case SIGTSTP:
 		if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
 			tracer_panic("sleeping_process_signal : Failed to "
-				     "continue pid %d, errno = %d\n", pid,
-				     sig);
+				     "continue pid %d, signal = %d, "
+				     "errno = %d\n", pid, sig, errno);
 		break;
 
 	/* This happens when the debugger (e.g. strace) is doing system call 
@@ -145,7 +145,7 @@ static void sleeping_process_signal(int 
 		if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
 			tracer_panic("sleeping_process_signal : Failed to "
 				     "PTRACE_SYSCALL pid %d, errno = %d\n",
-				     pid, sig);
+				     pid, errno);
 		break;
 	case SIGSTOP:
 		break;
@@ -218,7 +218,7 @@ int tracer(int (*init_proc)(void *), voi
 			err = attach(debugger_parent);
 			if(err){
 				printf("Failed to attach debugger parent %d, "
-				       "errno = %d\n", debugger_parent, err);
+				       "errno = %d\n", debugger_parent, -err);
 				debugger_parent = -1;
 			}
 			else {
@@ -233,7 +233,8 @@ int tracer(int (*init_proc)(void *), voi
 	}
 	set_cmdline("(tracing thread)");
 	while(1){
-		if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){
+		pid = waitpid(-1, &status, WUNTRACED);
+		if(pid <= 0){
 			if(errno != ECHILD){
 				printf("wait failed - errno = %d\n", errno);
 			}
@@ -401,7 +402,7 @@ static int __init uml_debug_setup(char *
 		
 		if(!strcmp(line, "go"))	debug_stop = 0;
 		else if(!strcmp(line, "parent")) debug_parent = 1;
-		else printk("Unknown debug option : '%s'\n", line);
+		else printf("Unknown debug option : '%s'\n", line);
 
 		line = next;
 	}
diff -puN /dev/null arch/um/kernel/tt/uaccess.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/kernel/tt/uaccess.c	2004-08-15 20:46:03.288033688 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "asm/uaccess.h"
+
+int copy_from_user_tt(void *to, const void *from, int n)
+{
+	if(!access_ok_tt(VERIFY_READ, from, n))
+		return(n);
+
+	return(__do_copy_from_user(to, from, n, &current->thread.fault_addr,
+				   &current->thread.fault_catcher));
+}
+
+int copy_to_user_tt(void *to, const void *from, int n)
+{
+	if(!access_ok_tt(VERIFY_WRITE, to, n))
+		return(n);
+
+	return(__do_copy_to_user(to, from, n, &current->thread.fault_addr,
+				 &current->thread.fault_catcher));
+}
+
+int strncpy_from_user_tt(char *dst, const char *src, int count)
+{
+	int n;
+
+	if(!access_ok_tt(VERIFY_READ, src, 1))
+		return(-EFAULT);
+
+	n = __do_strncpy_from_user(dst, src, count,
+				   &current->thread.fault_addr,
+				   &current->thread.fault_catcher);
+	if(n < 0) return(-EFAULT);
+	return(n);
+}
+
+int __clear_user_tt(void *mem, int len)
+{
+	return(__do_clear_user(mem, len,
+			       &current->thread.fault_addr,
+			       &current->thread.fault_catcher));
+}
+
+int clear_user_tt(void *mem, int len)
+{
+	if(!access_ok_tt(VERIFY_WRITE, mem, len))
+		return(len);
+
+	return(__do_clear_user(mem, len, &current->thread.fault_addr,
+			       &current->thread.fault_catcher));
+}
+
+int strnlen_user_tt(const void *str, int len)
+{
+	return(__do_strnlen_user(str, len,
+				 &current->thread.fault_addr,
+				 &current->thread.fault_catcher));
+}
+
+/*
+ * 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 -puN arch/um/kernel/tt/uaccess_user.c~uml-base-patch arch/um/kernel/tt/uaccess_user.c
--- 25/arch/um/kernel/tt/uaccess_user.c~uml-base-patch	2004-08-15 20:45:08.450370280 -0700
+++ 25-akpm/arch/um/kernel/tt/uaccess_user.c	2004-08-15 20:46:03.289033536 -0700
@@ -8,15 +8,20 @@
 #include <string.h>
 #include "user_util.h"
 #include "uml_uaccess.h"
+#include "task.h"
+#include "kern_util.h"
 
 int __do_copy_from_user(void *to, const void *from, int n,
 			void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
 			       __do_copy, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(0);
 	else return(n - (fault - (unsigned long) from));
 }
@@ -29,11 +34,14 @@ static void __do_strncpy(void *dst, cons
 int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
 			   void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
 			       __do_strncpy, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(strlen(dst));
 	else return(-1);
 }
@@ -46,11 +54,14 @@ static void __do_clear(void *to, const v
 int __do_clear_user(void *mem, unsigned long len,
 		    void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
 			       __do_clear, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(0);
 	else return(len - (fault - (unsigned long) mem));
 }
@@ -58,19 +69,20 @@ int __do_clear_user(void *mem, unsigned 
 int __do_strnlen_user(const char *str, unsigned long n,
 		      void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	int ret;
 	unsigned long *faddrp = (unsigned long *)fault_addr;
 	jmp_buf jbuf;
 
 	*fault_catcher = &jbuf;
-	if(setjmp(jbuf) == 0){
+	if(sigsetjmp(jbuf, 1) == 0)
 		ret = strlen(str) + 1;
-	} 
-	else {
-		ret = *faddrp - (unsigned long) str;
-	}
+	else ret = *faddrp - (unsigned long) str;
+
 	*fault_addr = NULL;
 	*fault_catcher = NULL;
+
+	TASK_REGS(get_current())->tt = save;
 	return ret;
 }
 
diff -puN arch/um/kernel/tt/unmap.c~uml-base-patch arch/um/kernel/tt/unmap.c
--- 25/arch/um/kernel/tt/unmap.c~uml-base-patch	2004-08-15 20:45:08.452369976 -0700
+++ 25-akpm/arch/um/kernel/tt/unmap.c	2004-08-15 20:46:03.289033536 -0700
@@ -3,10 +3,7 @@
  * Licensed under the GPL
  */
 
-#include <stdio.h>
-#include <errno.h>
 #include <sys/mman.h>
-#include "user.h"
 
 int switcheroo(int fd, int prot, void *from, void *to, int size)
 {
diff -puN arch/um/kernel/tty_log.c~uml-base-patch arch/um/kernel/tty_log.c
--- 25/arch/um/kernel/tty_log.c~uml-base-patch	2004-08-15 20:45:08.453369824 -0700
+++ 25-akpm/arch/um/kernel/tty_log.c	2004-08-15 20:46:03.290033384 -0700
@@ -9,10 +9,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <sys/time.h>
 #include "init.h"
 #include "user.h"
+#include "kern_util.h"
 #include "os.h"
 
 #define TTY_LOG_DIR "./"
@@ -24,29 +24,40 @@ static int tty_log_fd = -1;
 #define TTY_LOG_OPEN 1
 #define TTY_LOG_CLOSE 2
 #define TTY_LOG_WRITE 3
+#define TTY_LOG_EXEC 4
+
+#define TTY_READ 1
+#define TTY_WRITE 2
 
 struct tty_log_buf {
 	int what;
 	unsigned long tty;
 	int len;
+	int direction;
+	unsigned long sec;
+	unsigned long usec;
 };
 
-int open_tty_log(void *tty)
+int open_tty_log(void *tty, void *current_tty)
 {
 	struct timeval tv;
 	struct tty_log_buf data;
 	char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
 	int fd;
 
+	gettimeofday(&tv, NULL);
 	if(tty_log_fd != -1){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_OPEN,
-					       tty : (unsigned long) tty,
-					       len : 0 });
-		write(tty_log_fd, &data, sizeof(data));
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_OPEN,
+					       .tty  = (unsigned long) tty,
+					       .len  = sizeof(current_tty),
+					       .direction = 0,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
+		os_write_file(tty_log_fd, &current_tty, data.len);
 		return(tty_log_fd);
 	}
 
-	gettimeofday(&tv, NULL);
 	sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, 
  		(unsigned int) tv.tv_usec);
 
@@ -62,30 +73,117 @@ int open_tty_log(void *tty)
 void close_tty_log(int fd, void *tty)
 {
 	struct tty_log_buf data;
+	struct timeval tv;
 
 	if(tty_log_fd != -1){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_CLOSE,
-					       tty : (unsigned long) tty,
-					       len : 0 });
-		write(tty_log_fd, &data, sizeof(data));
+		gettimeofday(&tv, NULL);
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_CLOSE,
+					       .tty  = (unsigned long) tty,
+					       .len  = 0,
+					       .direction = 0,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
 		return;
 	}
-	close(fd);
+	os_close_file(fd);
 }
 
-int write_tty_log(int fd, char *buf, int len, void *tty)
+static int log_chunk(int fd, const char *buf, int len)
 {
+	int total = 0, try, missed, n;
+	char chunk[64];
+
+	while(len > 0){
+		try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
+		missed = copy_from_user_proc(chunk, (char *) buf, try);
+		try -= missed;
+		n = os_write_file(fd, chunk, try);
+		if(n != try) {
+			if(n < 0)
+				return(n);
+			return(-EIO);
+		}
+		if(missed != 0)
+			return(-EFAULT);
+
+		len -= try;
+		total += try;
+		buf += try;
+	}
+
+	return(total);
+}
+
+int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
+{
+	struct timeval tv;
 	struct tty_log_buf data;
+	int direction;
 
 	if(fd == tty_log_fd){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_WRITE,
-					       tty : (unsigned long) tty,
-					       len : len });
-		write(tty_log_fd, &data, sizeof(data));
+		gettimeofday(&tv, NULL);
+		direction = is_read ? TTY_READ : TTY_WRITE;
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_WRITE,
+					       .tty  = (unsigned long) tty,
+					       .len  = len,
+					       .direction = direction,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
+	}
+
+	return(log_chunk(fd, buf, len));
+}
+
+void log_exec(char **argv, void *tty)
+{
+	struct timeval tv;
+	struct tty_log_buf data;
+	char **ptr,*arg;
+	int len;
+
+	if(tty_log_fd == -1) return;
+
+	gettimeofday(&tv, NULL);
+
+	len = 0;
+	for(ptr = argv; ; ptr++){
+		if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
+			return;
+		if(arg == NULL) break;
+		len += strlen_user_proc(arg);
+	}
+
+	data = ((struct tty_log_buf) { .what 	= TTY_LOG_EXEC,
+				       .tty  = (unsigned long) tty,
+				       .len  = len,
+				       .direction = 0,
+				       .sec = tv.tv_sec,
+				       .usec = tv.tv_usec } );
+	os_write_file(tty_log_fd, &data, sizeof(data));
+
+	for(ptr = argv; ; ptr++){
+		if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
+			return;
+		if(arg == NULL) break;
+		log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
 	}
-	return(write(fd, buf, len));
 }
 
+extern void register_tty_logger(int (*opener)(void *, void *),
+				int (*writer)(int, const char *, int,
+					      void *, int),
+				void (*closer)(int, void *));
+
+static int register_logger(void)
+{
+	register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
+	return(0);
+}
+
+__uml_initcall(register_logger);
+
 static int __init set_tty_log_dir(char *name, int *add)
 {
 	tty_log_dir = name;
@@ -104,7 +202,7 @@ static int __init set_tty_log_fd(char *n
 
 	tty_log_fd = strtoul(name, &end, 0);
 	if((*end != '\0') || (end == name)){
-		printk("set_tty_log_fd - strtoul failed on '%s'\n", name);
+		printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
 		tty_log_fd = -1;
 	}
 	return 0;
diff -puN arch/um/kernel/uaccess_user.c~uml-base-patch arch/um/kernel/uaccess_user.c
--- 25/arch/um/kernel/uaccess_user.c~uml-base-patch	2004-08-15 20:45:08.454369672 -0700
+++ 25-akpm/arch/um/kernel/uaccess_user.c	2004-08-15 20:46:03.290033384 -0700
@@ -20,7 +20,7 @@ unsigned long __do_user_copy(void *to, c
 
 	jmp_buf jbuf;
 	*fault_catcher = &jbuf;
-	if(setjmp(jbuf) == 0){
+	if(sigsetjmp(jbuf, 1) == 0){
 		(*op)(to, from, n);
 		ret = 0;
 		*faulted_out = 0;
diff -puN arch/um/kernel/um_arch.c~uml-base-patch arch/um/kernel/um_arch.c
--- 25/arch/um/kernel/um_arch.c~uml-base-patch	2004-08-15 20:45:08.456369368 -0700
+++ 25-akpm/arch/um/kernel/um_arch.c	2004-08-15 20:46:03.292033080 -0700
@@ -38,13 +38,18 @@
 #include "mode_kern.h"
 #include "mode.h"
 
-#define DEFAULT_COMMAND_LINE "root=6200"
+#define DEFAULT_COMMAND_LINE "root=98:0"
 
 struct cpuinfo_um boot_cpu_data = { 
 	.loops_per_jiffy	= 0,
 	.ipi_pipe		= { -1, -1 }
 };
 
+/* Placeholder to make UML link until the vsyscall stuff is actually
+ * implemented
+ */
+void *__kernel_vsyscall;
+
 unsigned long thread_saved_pc(struct task_struct *task)
 {
 	return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
@@ -53,18 +58,22 @@ unsigned long thread_saved_pc(struct tas
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-	int index;
+	int index = 0;
 
-	index = (struct cpuinfo_um *)v - cpu_data;
 #ifdef CONFIG_SMP
+	index = (struct cpuinfo_um *) v - cpu_data;
 	if (!cpu_online(index))
 		return 0;
 #endif
 
-	seq_printf(m, "bogomips\t: %lu.%02lu\n",
+	seq_printf(m, "processor\t: %d\n", index);
+	seq_printf(m, "vendor_id\t: User Mode Linux\n");
+	seq_printf(m, "model name\t: UML\n");
+	seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
+	seq_printf(m, "host\t\t: %s\n", host_info);
+	seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
 		   loops_per_jiffy/(500000/HZ),
 		   (loops_per_jiffy/(5000/HZ)) % 100);
-	seq_printf(m, "host\t\t: %s\n", host_info);
 
 	return(0);
 }
@@ -134,12 +143,12 @@ void set_cmdline(char *cmd)
 	if(umid != NULL){
 		snprintf(argv1_begin, 
 			 (argv1_end - argv1_begin) * sizeof(*ptr), 
-			 "(%s)", umid);
+			 "(%s) ", umid);
 		ptr = &argv1_begin[strlen(argv1_begin)];
 	}
 	else ptr = argv1_begin;
 
-	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), " [%s]", cmd);
+	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
 	memset(argv1_begin + strlen(argv1_begin), '\0', 
 	       argv1_end - argv1_begin - strlen(argv1_begin));
 #endif
@@ -179,7 +188,7 @@ __uml_setup("root=", uml_root_setup,
 static int __init uml_ncpus_setup(char *line, int *add)
 {
        if (!sscanf(line, "%d", &ncpus)) {
-               printk("Couldn't parse [%s]\n", line);
+               printf("Couldn't parse [%s]\n", line);
                return -1;
        }
 
@@ -210,7 +219,7 @@ static int __init mode_tt_setup(char *li
 
 static int __init mode_tt_setup(char *line, int *add)
 {
-	printk("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
+	printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
 	return(0);
 }
 
@@ -221,7 +230,7 @@ static int __init mode_tt_setup(char *li
 
 static int __init mode_tt_setup(char *line, int *add)
 {
-	printk("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
+	printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
 	return(0);
 }
 
@@ -291,7 +300,7 @@ static void __init uml_postsetup(void)
 
 /* Set during early boot */
 unsigned long brk_start;
-static struct vm_reserved kernel_vm_reserved;
+unsigned long end_iomem;
 
 #define MIN_VMALLOC (32 * 1024 * 1024)
 
@@ -299,7 +308,7 @@ int linux_main(int argc, char **argv)
 {
 	unsigned long avail;
 	unsigned long virtmem_size, max_physmem;
-	unsigned int i, add, err;
+	unsigned int i, add;
 
 	for (i = 1; i < argc; i++){
 		if((i == 1) && (argv[i][0] == ' ')) continue;
@@ -328,12 +337,16 @@ int linux_main(int argc, char **argv)
 	argv1_end = &argv[1][strlen(argv[1])];
 #endif
   
-	set_usable_vm(uml_physmem, get_kmem_end());
-
 	highmem = 0;
-	max_physmem = get_kmem_end() - uml_physmem - MIN_VMALLOC;
-	if(physmem_size > max_physmem){
-		highmem = physmem_size - max_physmem;
+	iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
+	max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
+
+	/* Zones have to begin on a 1 << MAX_ORDER page boundary,
+	 * so this makes sure that's true for highmem
+	 */
+	max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
+	if(physmem_size + iomem_size > max_physmem){
+		highmem = physmem_size + iomem_size - max_physmem;
 		physmem_size -= highmem;
 #ifndef CONFIG_HIGHMEM
 		highmem = 0;
@@ -343,11 +356,19 @@ int linux_main(int argc, char **argv)
 	}
 
 	high_physmem = uml_physmem + physmem_size;
-	high_memory = (void *) high_physmem;
+	end_iomem = high_physmem + iomem_size;
+	high_memory = (void *) end_iomem;
 
 	start_vm = VMALLOC_START;
 
-	setup_physmem(uml_physmem, uml_reserved, physmem_size);
+	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,
+		       highmem);
+		exit(1);
+	}
+
 	virtmem_size = physmem_size;
 	avail = get_kmem_end() - start_vm;
 	if(physmem_size > avail) virtmem_size = avail;
@@ -357,28 +378,26 @@ int linux_main(int argc, char **argv)
 		printf("Kernel virtual memory size shrunk to %ld bytes\n",
 		       virtmem_size);
 
-	err = reserve_vm(high_physmem, end_vm, &kernel_vm_reserved);
-	if(err){
-		printf("Failed to reserve VM area for kernel VM\n");
-		exit(1);
-	}
-
   	uml_postsetup();
 
 	init_task.thread.kernel_stack = (unsigned long) &init_thread_info + 
 		2 * PAGE_SIZE;
 
 	task_protections((unsigned long) &init_thread_info);
+	os_flush_stdout();
 
 	return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
 }
 
+extern int uml_exitcode;
+
 static int panic_exit(struct notifier_block *self, unsigned long unused1,
 		      void *unused2)
 {
 #ifdef CONFIG_MAGIC_SYSRQ
-	handle_sysrq('p', &current->thread.regs, NULL, NULL);
+	handle_sysrq('p', &current->thread.regs, NULL);
 #endif
+	uml_exitcode = 1;
 	machine_halt();
 	return(0);
 }
@@ -403,6 +422,11 @@ void __init check_bugs(void)
 	arch_check_bugs();
 	check_ptrace();
 	check_sigio();
+	check_devanon();
+}
+
+void apply_alternatives(void *start, void *end)
+{
 }
 
 /*
diff -puN arch/um/kernel/umid.c~uml-base-patch arch/um/kernel/umid.c
--- 25/arch/um/kernel/umid.c~uml-base-patch	2004-08-15 20:45:08.458369064 -0700
+++ 25-akpm/arch/um/kernel/umid.c	2004-08-15 20:46:03.293032928 -0700
@@ -5,7 +5,6 @@
 
 #include <stdio.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
@@ -33,18 +32,19 @@ static char *uml_dir = UML_DIR;
 static int umid_is_random = 1;
 static int umid_inited = 0;
 
-static int make_umid(void);
+static int make_umid(int (*printer)(const char *fmt, ...));
 
-static int __init set_umid(char *name, int is_random)
+static int __init set_umid(char *name, int is_random,
+			   int (*printer)(const char *fmt, ...))
 {
 	if(umid_inited){
-		printk("Unique machine name can't be set twice\n");
+		(*printer)("Unique machine name can't be set twice\n");
 		return(-1);
 	}
 
 	if(strlen(name) > UMID_LEN - 1)
-		printk("Unique machine name is being truncated to %s "
-		       "characters\n", UMID_LEN);
+		(*printer)("Unique machine name is being truncated to %s "
+			   "characters\n", UMID_LEN);
 	strlcpy(umid, name, sizeof(umid));
 
 	umid_is_random = is_random;
@@ -54,7 +54,7 @@ static int __init set_umid(char *name, i
 
 static int __init set_umid_arg(char *name, int *add)
 {
-	return(set_umid(name, 0));
+	return(set_umid(name, 0, printf));
 }
 
 __uml_setup("umid=", set_umid_arg,
@@ -67,7 +67,7 @@ int __init umid_file_name(char *name, ch
 {
 	int n;
 
-	if(!umid_inited && make_umid()) return(-1);
+	if(!umid_inited && make_umid(printk)) return(-1);
 
 	n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
 	if(n > len){
@@ -85,22 +85,23 @@ static int __init create_pid_file(void)
 {
 	char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
 	char pid[sizeof("nnnnn\0")];
-	int fd;
+	int fd, n;
 
 	if(umid_file_name("pid", file, sizeof(file))) return 0;
 
 	fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 
 			  0644);
 	if(fd < 0){
-		printk("Open of machine pid file \"%s\" failed - "
-		       "errno = %d\n", file, -fd);
+		printf("Open of machine pid file \"%s\" failed - "
+		       "err = %d\n", file, -fd);
 		return 0;
 	}
 
 	sprintf(pid, "%d\n", os_getpid());
-	if(write(fd, pid, strlen(pid)) != strlen(pid))
-		printk("Write of pid file failed - errno = %d\n", errno);
-	close(fd);
+	n = os_write_file(fd, pid, strlen(pid));
+	if(n != strlen(pid))
+		printf("Write of pid file failed - err = %d\n", -n);
+	os_close_file(fd);
 	return 0;
 }
 
@@ -111,7 +112,8 @@ static int actually_do_remove(char *dir)
 	int len;
 	char file[256];
 
-	if((directory = opendir(dir)) == NULL){
+	directory = opendir(dir);
+	if(directory == NULL){
 		printk("actually_do_remove : couldn't open directory '%s', "
 		       "errno = %d\n", dir, errno);
 		return(1);
@@ -160,22 +162,24 @@ int not_dead_yet(char *dir)
 {
 	char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
 	char pid[sizeof("nnnnn\0")], *end;
-	int dead, fd, p;
+	int dead, fd, p, n;
 
 	sprintf(file, "%s/pid", dir);
 	dead = 0;
-	if((fd = os_open_file(file, of_read(OPENFLAGS()), 0)) < 0){
+	fd = os_open_file(file, of_read(OPENFLAGS()), 0);
+	if(fd < 0){
 		if(fd != -ENOENT){
 			printk("not_dead_yet : couldn't open pid file '%s', "
-			       "errno = %d\n", file, -fd);
+			       "err = %d\n", file, -fd);
 			return(1);
 		}
 		dead = 1;
 	}
 	if(fd > 0){
-		if(read(fd, pid, sizeof(pid)) < 0){
+		n = os_read_file(fd, pid, sizeof(pid));
+		if(n < 0){
 			printk("not_dead_yet : couldn't read pid file '%s', "
-			       "errno = %d\n", file, errno);
+			       "err = %d\n", file, -n);
 			return(1);
 		}
 		p = strtoul(pid, &end, 0);
@@ -197,7 +201,7 @@ static int __init set_uml_dir(char *name
 	if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
 		uml_dir = malloc(strlen(name) + 1);
 		if(uml_dir == NULL){
-			printk("Failed to malloc uml_dir - error = %d\n",
+			printf("Failed to malloc uml_dir - error = %d\n",
 			       errno);
 			uml_dir = name;
 			return(0);
@@ -217,7 +221,7 @@ static int __init make_uml_dir(void)
 		char *home = getenv("HOME");
 
 		if(home == NULL){
-			printk("make_uml_dir : no value in environment for "
+			printf("make_uml_dir : no value in environment for "
 			       "$HOME\n");
 			exit(1);
 		}
@@ -232,57 +236,59 @@ static int __init make_uml_dir(void)
 		dir[len + 1] = '\0';
 	}
 
-	if((uml_dir = malloc(strlen(dir) + 1)) == NULL){
+	uml_dir = malloc(strlen(dir) + 1);
+	if(uml_dir == NULL){
 		printf("make_uml_dir : malloc failed, errno = %d\n", errno);
 		exit(1);
 	}
 	strcpy(uml_dir, dir);
 	
 	if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
-	        printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
+	        printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
 		return(-1);
 	}
 	return 0;
 }
 
-static int __init make_umid(void)
+static int __init make_umid(int (*printer)(const char *fmt, ...))
 {
 	int fd, err;
 	char tmp[strlen(uml_dir) + UMID_LEN + 1];
 
 	strlcpy(tmp, uml_dir, sizeof(tmp));
 
-	if(*umid == 0){
+	if(!umid_inited){
 		strcat(tmp, "XXXXXX");
 		fd = mkstemp(tmp);
 		if(fd < 0){
-			printk("make_umid - mkstemp failed, errno = %d\n",
-			       errno);
+			(*printer)("make_umid - mkstemp failed, errno = %d\n",
+				   errno);
 			return(1);
 		}
 
-		close(fd);
+		os_close_file(fd);
 		/* There's a nice tiny little race between this unlink and
 		 * the mkdir below.  It'd be nice if there were a mkstemp
 		 * for directories.
 		 */
 		unlink(tmp);
-		set_umid(&tmp[strlen(uml_dir)], 1);
+		set_umid(&tmp[strlen(uml_dir)], 1, printer);
 	}
 	
 	sprintf(tmp, "%s%s", uml_dir, umid);
 
-	if((err = mkdir(tmp, 0777)) < 0){
+	err = mkdir(tmp, 0777);
+	if(err < 0){
 		if(errno == EEXIST){
 			if(not_dead_yet(tmp)){
-				printk("umid '%s' is in use\n", umid);
+				(*printer)("umid '%s' is in use\n", umid);
 				return(-1);
 			}
 			err = mkdir(tmp, 0777);
 		}
 	}
 	if(err < 0){
-		printk("Failed to create %s - errno = %d\n", umid, errno);
+		(*printer)("Failed to create %s - errno = %d\n", umid, errno);
 		return(-1);
 	}
 
@@ -295,7 +301,13 @@ __uml_setup("uml_dir=", set_uml_dir,
 );
 
 __uml_postsetup(make_uml_dir);
-__uml_postsetup(make_umid);
+
+static int __init make_umid_setup(void)
+{
+	return(make_umid(printf));
+}
+
+__uml_postsetup(make_umid_setup);
 __uml_postsetup(create_pid_file);
 
 /*
diff -L arch/um/kernel/user_syms.c -puN arch/um/kernel/user_syms.c~uml-base-patch /dev/null
--- 25/arch/um/kernel/user_syms.c
+++ /dev/null	2003-09-15 06:40:47.000000000 -0700
@@ -1,113 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <utime.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/vfs.h>
-#include <sys/ioctl.h>
-#include "user_util.h"
-#include "mem_user.h"
-#include "uml-config.h"
-
-/* Had to steal this from linux/module.h because that file can't be included
- * since this includes various user-level headers.
- */
-
-struct module_symbol
-{
-	unsigned long value;
-	const char *name;
-};
-
-/* Indirect stringification.  */
-
-#define __MODULE_STRING_1(x)	#x
-#define __MODULE_STRING(x)	__MODULE_STRING_1(x)
-
-#if !defined(__AUTOCONF_INCLUDED__)
-
-#define __EXPORT_SYMBOL(sym,str)   error config_must_be_included_before_module
-#define EXPORT_SYMBOL(var)	   error config_must_be_included_before_module
-#define EXPORT_SYMBOL_NOVERS(var)  error config_must_be_included_before_module
-
-#elif !defined(UML_CONFIG_MODULES)
-
-#define __EXPORT_SYMBOL(sym,str)
-#define EXPORT_SYMBOL(var)
-#define EXPORT_SYMBOL_NOVERS(var)
-
-#else
-
-#define __EXPORT_SYMBOL(sym, str)			\
-const char __kstrtab_##sym[]				\
-__attribute__((section(".kstrtab"))) = str;		\
-const struct module_symbol __ksymtab_##sym 		\
-__attribute__((section("__ksymtab"))) =			\
-{ (unsigned long)&sym, __kstrtab_##sym }
-
-#if defined(__MODVERSIONS__) || !defined(UML_CONFIG_MODVERSIONS)
-#define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
-#else
-#define EXPORT_SYMBOL(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
-#endif
-
-#define EXPORT_SYMBOL_NOVERS(var)  __EXPORT_SYMBOL(var, __MODULE_STRING(var))
-
-#endif
-
-EXPORT_SYMBOL(__errno_location);
-
-EXPORT_SYMBOL(access);
-EXPORT_SYMBOL(open);
-EXPORT_SYMBOL(open64);
-EXPORT_SYMBOL(close);
-EXPORT_SYMBOL(read);
-EXPORT_SYMBOL(write);
-EXPORT_SYMBOL(dup2);
-EXPORT_SYMBOL(__xstat);
-EXPORT_SYMBOL(__lxstat);
-EXPORT_SYMBOL(__lxstat64);
-EXPORT_SYMBOL(lseek);
-EXPORT_SYMBOL(lseek64);
-EXPORT_SYMBOL(chown);
-EXPORT_SYMBOL(truncate);
-EXPORT_SYMBOL(utime);
-EXPORT_SYMBOL(chmod);
-EXPORT_SYMBOL(rename);
-EXPORT_SYMBOL(__xmknod);
-
-EXPORT_SYMBOL(symlink);
-EXPORT_SYMBOL(link);
-EXPORT_SYMBOL(unlink);
-EXPORT_SYMBOL(readlink);
-
-EXPORT_SYMBOL(mkdir);
-EXPORT_SYMBOL(rmdir);
-EXPORT_SYMBOL(opendir);
-EXPORT_SYMBOL(readdir);
-EXPORT_SYMBOL(closedir);
-EXPORT_SYMBOL(seekdir);
-EXPORT_SYMBOL(telldir);
-
-EXPORT_SYMBOL(ioctl);
-
-extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes,
-			__off64_t __offset);
-extern ssize_t pwrite64 (int __fd, __const void *__buf, size_t __n,
-			 __off64_t __offset);
-EXPORT_SYMBOL(pread64);
-EXPORT_SYMBOL(pwrite64);
-
-EXPORT_SYMBOL(statfs);
-EXPORT_SYMBOL(statfs64);
-
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(getuid);
-
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strstr);
-
-EXPORT_SYMBOL(find_iomem);
diff -puN arch/um/kernel/user_util.c~uml-base-patch arch/um/kernel/user_util.c
--- 25/arch/um/kernel/user_util.c~uml-base-patch	2004-08-15 20:45:08.461368608 -0700
+++ 25-akpm/arch/um/kernel/user_util.c	2004-08-15 20:46:03.295032624 -0700
@@ -5,7 +5,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
 #include <sys/mman.h> 
@@ -81,7 +80,8 @@ int wait_for_stop(int pid, int sig, int 
 	int status, ret;
 
 	while(1){
-		if(((ret = waitpid(pid, &status, WUNTRACED)) < 0) ||
+		ret = waitpid(pid, &status, WUNTRACED);
+		if((ret < 0) ||
 		   !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
 			if(ret < 0){
 				if(errno == EINTR) continue;
@@ -118,17 +118,6 @@ int wait_for_stop(int pid, int sig, int 
 	}
 }
 
-int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags)
-{
-	int pid;
-
-	pid = clone(fn, sp, flags, arg);
- 	if(pid < 0) return(-1);
-	wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
-	ptrace(PTRACE_CONT, pid, 0, 0);
-	return(pid);
-}
-
 int raw(int fd, int complain)
 {
 	struct termios tt;
diff -puN arch/um/main.c~uml-base-patch arch/um/main.c
--- 25/arch/um/main.c~uml-base-patch	2004-08-15 20:45:08.462368456 -0700
+++ 25-akpm/arch/um/main.c	2004-08-15 20:46:03.295032624 -0700
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
+#include <errno.h>
 #include <sys/resource.h>
 #include <sys/mman.h>
 #include <sys/user.h>
@@ -123,12 +124,14 @@ int main(int argc, char **argv, char **e
 
 	set_stklim();
 
-	if((new_argv = malloc((argc + 1) * sizeof(char *))) == NULL){
+	new_argv = malloc((argc + 1) * sizeof(char *));
+	if(new_argv == NULL){
 		perror("Mallocing argv");
 		exit(1);
 	}
 	for(i=0;i<argc;i++){
-		if((new_argv[i] = strdup(argv[i])) == NULL){
+		new_argv[i] = strdup(argv[i]);
+		if(new_argv[i] == NULL){
 			perror("Mallocing an arg");
 			exit(1);
 		}
diff -puN arch/um/Makefile~uml-base-patch arch/um/Makefile
--- 25/arch/um/Makefile~uml-base-patch	2004-08-15 20:45:08.464368152 -0700
+++ 25-akpm/arch/um/Makefile	2004-08-15 20:48:13.560229304 -0700
@@ -22,17 +22,21 @@ core-y			+= $(ARCH_DIR)/kernel/		 \
 			   $(ARCH_DIR)/sys-$(SUBARCH)/
 
 # Have to precede the include because the included Makefiles reference them.
-SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
-	include/asm-um/sigcontext.h include/asm-um/processor.h \
-	include/asm-um/ptrace.h include/asm-um/arch-signal.h
+SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \
+	arch-signal.h module.h
+SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
 
 ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
 	$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
 
 GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
 
-include $(ARCH_DIR)/Makefile-$(SUBARCH)
-include $(ARCH_DIR)/Makefile-os-$(OS)
+# This target adds dependencies to "prepare". They are defined in the included
+# Makefiles (see Makefile-i386).
+
+.PHONY: sys_prepare
+sys_prepare:
+	@:
 
 MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
 MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
@@ -41,6 +45,9 @@ ifneq ($(MAKEFILE-y),)
   include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
 endif
 
+include $(ARCH_DIR)/Makefile-$(SUBARCH)
+include $(ARCH_DIR)/Makefile-os-$(OS)
+
 EXTRAVERSION := $(EXTRAVERSION)-1um
 
 ARCH_INCLUDE = -I$(ARCH_DIR)/include
@@ -52,14 +59,20 @@ ARCH_INCLUDE = -I$(ARCH_DIR)/include
 
 CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
 	-D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
-	$(MODE_INCLUDE)
+	-Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE)
 
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
+# These are needed for clean and mrproper, since in that case .config is not
+# included; the values here are meaningless
+
+CONFIG_NEST_LEVEL ?= 0
+CONFIG_KERNEL_HALF_GIGS ?=  0
+
 SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
 
 ifeq ($(CONFIG_MODE_SKAS), y)
-$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+$(SYS_HEADERS) : $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
 endif
 
 include/linux/version.h: arch/$(ARCH)/Makefile
@@ -98,17 +111,17 @@ CPP_MODE_TT := $(shell [ "$(CONFIG_MODE_
 CONFIG_KERNEL_STACK_ORDER ?= 2
 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
 
-CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \
+CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \
 	-DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
 	-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
-	-DKERNEL_STACK_SIZE=$(STACK_SIZE)
+	-DKERNEL_STACK_SIZE=$(STACK_SIZE))
 
-CPPFLAGS_$(LD_SCRIPT-y) = $(CPPFLAGS_vmlinux.lds) -P -C -Uum
+export CPPFLAGS_$(LD_SCRIPT-y) = $(CPPFLAGS_vmlinux.lds) -P -C -Uum
 
 LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
 
-$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
-	$(call if_changed_dep,as_s_S)
+#$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
+#	$(call if_changed_dep,as_s_S)
 
 linux: vmlinux $(LD_SCRIPT-y)
 	$(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \
@@ -116,37 +129,47 @@ linux: vmlinux $(LD_SCRIPT-y)
 
 USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
 USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
+USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS))
 USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
 	$(MODE_INCLUDE)
 
 # To get a definition of F_SETSIG
 USER_CFLAGS += -D_GNU_SOURCE
 
+# From main Makefile, these options are set after including the ARCH makefile.
+# So copy them here.
+
+ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+USER_CFLAGS		+= -Os
+else
+USER_CFLAGS		+= -O2
+endif
+
+ifndef CONFIG_FRAME_POINTER
+USER_CFLAGS		+= -fomit-frame-pointer
+endif
+
+ifdef CONFIG_DEBUG_INFO
+USER_CFLAGS		+= -g
+endif
+
 CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds \
-	$(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS)
+	$(ARCH_DIR)/dyn_link.ld.s $(ARCH_DIR)/include/uml-config.h \
+	$(GEN_HEADERS)
 
-$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
-	$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
+	$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
+
+$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c sys_prepare
+	@ echo '  MAIN    $@'
+	@ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
 
 archmrproper:
-	for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
-	do \
-		$(MAKE) -C $$d archmrproper; \
-	done
-	rm -f $(CLEAN_FILES) $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \
-		$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
-
-archclean: sysclean
-	for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
-	do \
-		$(MAKE) -C $$d clean; \
-	done
-	find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-		-o -name '*.gcov' \) -type f -print | xargs rm -f
-	rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
+	@:
 
-archdep: 
-	for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done
+archclean:
+	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
+		-o -name '*.gcov' \) -type f -print | xargs rm -f
 
 $(SYMLINK_HEADERS):
 	cd $(TOPDIR)/$(dir $@) ; \
@@ -161,19 +184,26 @@ $(ARCH_DIR)/include/sysdep:
 $(ARCH_DIR)/os:
 	cd $(ARCH_DIR) && ln -sf os-$(OS) os
 
-$(ARCH_DIR)/include/uml-config.h :
-	sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
+# Generated files
+define filechk_umlconfig
+	sed 's/ CONFIG/ UML_CONFIG/'
+endef
+
+$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h
+	$(call filechk,umlconfig)
+
+filechk_gen_header = $<
 
 $(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
-	$< > $@
+	$(call filechk,gen_header)
 
 $(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
-	$< > $@
+	$(call filechk,gen_header)
 
-$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
-	$(ARCH_DIR)/util FORCE ;
+$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util \
+	sys_prepare FORCE ;
 
 $(ARCH_DIR)/util: FORCE
-	@$(call descend,$@,)
+	$(Q)$(MAKE) $(build)=$@
 
 export SUBARCH USER_CFLAGS OS
diff -puN arch/um/Makefile-i386~uml-base-patch arch/um/Makefile-i386
--- 25/arch/um/Makefile-i386~uml-base-patch	2004-08-15 20:45:08.465368000 -0700
+++ 25-akpm/arch/um/Makefile-i386	2004-08-15 20:46:03.297032320 -0700
@@ -16,22 +16,27 @@ SYS_UTIL_DIR	:= $(ARCH_DIR)/sys-i386/uti
 
 SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
 
+sys_prepare: $(SYS_DIR)/sc.h
+
 prepare: $(SYS_HEADERS)
 
+filechk_$(SYS_DIR)/sc.h := $(SYS_UTIL_DIR)/mk_sc
+
 $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
-	$< > $@
+	$(call filechk,$@)
+
+filechk_$(SYS_DIR)/thread.h := $(SYS_UTIL_DIR)/mk_thread
 
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 
-	$< > $@
+	$(call filechk,$@)
 
-$(SYS_UTIL_DIR)/mk_sc: FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_sc: scripts/basic/fixdep include/config/MARKER FORCE ;
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) sys_prepare FORCE ;
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
 $(SYS_UTIL_DIR): include/asm FORCE
-	@$(call descend,$@,)
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR)
 
-sysclean :
-	rm -f $(SYS_HEADERS)
+CLEAN_FILES += $(SYS_HEADERS)
diff -puN arch/um/Makefile-skas~uml-base-patch arch/um/Makefile-skas
--- 25/arch/um/Makefile-skas~uml-base-patch	2004-08-15 20:45:08.466367848 -0700
+++ 25-akpm/arch/um/Makefile-skas	2004-08-15 20:46:03.298032168 -0700
@@ -14,7 +14,7 @@ MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/
 LINK_SKAS = -Wl,-rpath,/lib 
 LD_SCRIPT_SKAS = dyn.lds
 
-GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+GEN_HEADERS += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
 
-$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
-	$(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
+$(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h :
+	$(Q)$(MAKE) $(build)=$(ARCH_DIR)/kernel/skas $@
diff -puN arch/um/os-Linux/drivers/ethertap_kern.c~uml-base-patch arch/um/os-Linux/drivers/ethertap_kern.c
--- 25/arch/um/os-Linux/drivers/ethertap_kern.c~uml-base-patch	2004-08-15 20:45:08.468367544 -0700
+++ 25-akpm/arch/um/os-Linux/drivers/ethertap_kern.c	2004-08-15 20:46:03.298032168 -0700
@@ -8,7 +8,6 @@
 #include "linux/init.h"
 #include "linux/netdevice.h"
 #include "linux/etherdevice.h"
-#include "linux/init.h"
 #include "net_kern.h"
 #include "net_user.h"
 #include "etap.h"
diff -puN arch/um/os-Linux/drivers/ethertap_user.c~uml-base-patch arch/um/os-Linux/drivers/ethertap_user.c
--- 25/arch/um/os-Linux/drivers/ethertap_user.c~uml-base-patch	2004-08-15 20:45:08.469367392 -0700
+++ 25-akpm/arch/um/os-Linux/drivers/ethertap_user.c	2004-08-15 20:46:03.299032016 -0700
@@ -8,7 +8,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <stddef.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <sys/errno.h>
 #include <sys/socket.h>
@@ -42,13 +41,14 @@ static void etap_change(int op, unsigned
 {
 	struct addr_change change;
 	void *output;
+	int n;
 
 	change.what = op;
 	memcpy(change.addr, addr, sizeof(change.addr));
 	memcpy(change.netmask, netmask, sizeof(change.netmask));
-	if(write(fd, &change, sizeof(change)) != sizeof(change))
-		printk("etap_change - request failed, errno = %d\n",
-		       errno);
+	n = os_write_file(fd, &change, sizeof(change));
+	if(n != sizeof(change))
+		printk("etap_change - request failed, err = %d\n", -n);
 	output = um_kmalloc(page_size());
 	if(output == NULL)
 		printk("etap_change : Failed to allocate output buffer\n");
@@ -82,15 +82,15 @@ static void etap_pre_exec(void *arg)
 	struct etap_pre_exec_data *data = arg;
 
 	dup2(data->control_remote, 1);
-	close(data->data_me);
-	close(data->control_me);
+	os_close_file(data->data_me);
+	os_close_file(data->control_me);
 }
 
 static int etap_tramp(char *dev, char *gate, int control_me, 
 		      int control_remote, int data_me, int data_remote)
 {
 	struct etap_pre_exec_data pe_data;
-	int pid, status, err;
+	int pid, status, err, n;
 	char version_buf[sizeof("nnnnn\0")];
 	char data_fd_buf[sizeof("nnnnnn\0")];
 	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
@@ -114,21 +114,21 @@ static int etap_tramp(char *dev, char *g
 	pe_data.data_me = data_me;
 	pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
 
-	if(pid < 0) err = errno;
-	close(data_remote);
-	close(control_remote);
-	if(read(control_me, &c, sizeof(c)) != sizeof(c)){
-		printk("etap_tramp : read of status failed, errno = %d\n",
-		       errno);
-		return(EINVAL);
+	if(pid < 0) err = pid;
+	os_close_file(data_remote);
+	os_close_file(control_remote);
+	n = os_read_file(control_me, &c, sizeof(c));
+	if(n != sizeof(c)){
+		printk("etap_tramp : read of status failed, err = %d\n", -n);
+		return(-EINVAL);
 	}
 	if(c != 1){
 		printk("etap_tramp : uml_net failed\n");
-		err = EINVAL;
-		if(waitpid(pid, &status, 0) < 0) err = errno;
-		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)){
+		err = -EINVAL;
+		if(waitpid(pid, &status, 0) < 0)
+			err = -errno;
+		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
 			printk("uml_net didn't exit with status 1\n");
-		}
 	}
 	return(err);
 }
@@ -143,14 +143,14 @@ static int etap_open(void *data)
 	if(err) return(err);
 
 	err = os_pipe(data_fds, 0, 0);
-	if(err){
-		printk("data os_pipe failed - errno = %d\n", -err);
+	if(err < 0){
+		printk("data os_pipe failed - err = %d\n", -err);
 		return(err);
 	}
 
 	err = os_pipe(control_fds, 1, 0);
-	if(err){
-		printk("control os_pipe failed - errno = %d\n", -err);
+	if(err < 0){
+		printk("control os_pipe failed - err = %d\n", -err);
 		return(err);
 	}
 	
@@ -167,9 +167,9 @@ static int etap_open(void *data)
 		kfree(output);
 	}
 
-	if(err != 0){
-		printk("etap_tramp failed - errno = %d\n", err);
-		return(-err);
+	if(err < 0){
+		printk("etap_tramp failed - err = %d\n", -err);
+		return(err);
 	}
 
 	pri->data_fd = data_fds[0];
@@ -183,11 +183,11 @@ static void etap_close(int fd, void *dat
 	struct ethertap_data *pri = data;
 
 	iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
-	close(fd);
+	os_close_file(fd);
 	os_shutdown_socket(pri->data_fd, 1, 1);
-	close(pri->data_fd);
+	os_close_file(pri->data_fd);
 	pri->data_fd = -1;
-	close(pri->control_fd);
+	os_close_file(pri->control_fd);
 	pri->control_fd = -1;
 }
 
diff -puN arch/um/os-Linux/drivers/tuntap_user.c~uml-base-patch arch/um/os-Linux/drivers/tuntap_user.c
--- 25/arch/um/os-Linux/drivers/tuntap_user.c~uml-base-patch	2004-08-15 20:45:08.470367240 -0700
+++ 25-akpm/arch/um/os-Linux/drivers/tuntap_user.c	2004-08-15 20:46:03.300031864 -0700
@@ -8,7 +8,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -61,7 +60,7 @@ static void tuntap_pre_exec(void *arg)
 	struct tuntap_pre_exec_data *data = arg;
 	
 	dup2(data->stdout, 1);
-	close(data->close_me);
+	os_close_file(data->close_me);
 }
 
 static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
@@ -86,7 +85,7 @@ static int tuntap_open_tramp(char *gate,
 
 	if(pid < 0) return(-pid);
 
-	close(remote);
+	os_close_file(remote);
 
 	msg.msg_name = NULL;
 	msg.msg_namelen = 0;
@@ -107,19 +106,19 @@ static int tuntap_open_tramp(char *gate,
 	if(n < 0){
 		printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", 
 		       errno);
-		return(errno);
+		return(-errno);
 	}
 	waitpid(pid, NULL, 0);
 
 	cmsg = CMSG_FIRSTHDR(&msg);
 	if(cmsg == NULL){
 		printk("tuntap_open_tramp : didn't receive a message\n");
-		return(EINVAL);
+		return(-EINVAL);
 	}
 	if((cmsg->cmsg_level != SOL_SOCKET) || 
 	   (cmsg->cmsg_type != SCM_RIGHTS)){
 		printk("tuntap_open_tramp : didn't receive a descriptor\n");
-		return(EINVAL);
+		return(-EINVAL);
 	}
 	*fd_out = ((int *) CMSG_DATA(cmsg))[0];
 	return(0);
@@ -133,27 +132,29 @@ static int tuntap_open(void *data)
 	int err, fds[2], len, used;
 
 	err = tap_open_common(pri->dev, pri->gate_addr);
-	if(err) return(err);
+	if(err < 0)
+		return(err);
 
 	if(pri->fixed_config){
-		if((pri->fd = open("/dev/net/tun", O_RDWR)) < 0){
-			printk("Failed to open /dev/net/tun, errno = %d\n",
-			       errno);
-			return(-errno);
+		pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0);
+		if(pri->fd < 0){
+			printk("Failed to open /dev/net/tun, err = %d\n",
+			       -pri->fd);
+			return(pri->fd);
 		}
 		memset(&ifr, 0, sizeof(ifr));
-		ifr.ifr_flags = IFF_TAP;
+		ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 		strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
 		if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
-			printk("TUNSETIFF failed, errno = %d", errno);
-			close(pri->fd);
+			printk("TUNSETIFF failed, errno = %d\n", errno);
+			os_close_file(pri->fd);
 			return(-errno);
 		}
 	}
 	else {
 		err = os_pipe(fds, 0, 0);
-		if(err){
-			printk("tuntap_open : os_pipe failed - errno = %d\n",
+		if(err < 0){
+			printk("tuntap_open : os_pipe failed - err = %d\n",
 			       -err);
 			return(err);
 		}
@@ -166,19 +167,19 @@ static int tuntap_open(void *data)
 					fds[1], buffer, len, &used);
 
 		output = buffer;
-		if(err == 0){
-			pri->dev_name = uml_strdup(buffer);
-			output += IFNAMSIZ;
-			printk(output);
-			free_output_buffer(buffer);
-		}
-		else {
-			printk(output);
+		if(err < 0) {
+			printk("%s", output);
 			free_output_buffer(buffer);
-			printk("tuntap_open_tramp failed - errno = %d\n", err);
-			return(-err);
+			printk("tuntap_open_tramp failed - err = %d\n", -err);
+			return(err);
 		}
-		close(fds[0]);
+
+		pri->dev_name = uml_strdup(buffer);
+		output += IFNAMSIZ;
+		printk("%s", output);
+		free_output_buffer(buffer);
+
+		os_close_file(fds[0]);
 		iter_addresses(pri->dev, open_addr, pri->dev_name);
 	}
 
@@ -191,7 +192,7 @@ static void tuntap_close(int fd, void *d
 
 	if(!pri->fixed_config) 
 		iter_addresses(pri->dev, close_addr, pri->dev_name);
-	close(fd);
+	os_close_file(fd);
 	pri->fd = -1;
 }
 
diff -puN arch/um/os-Linux/file.c~uml-base-patch arch/um/os-Linux/file.c
--- 25/arch/um/os-Linux/file.c~uml-base-patch	2004-08-15 20:45:08.471367088 -0700
+++ 25-akpm/arch/um/os-Linux/file.c	2004-08-15 20:46:03.302031560 -0700
@@ -8,6 +8,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/ioctl.h>
@@ -17,33 +19,235 @@
 #include "user.h"
 #include "kern_util.h"
 
-int os_file_type(char *file)
+static void copy_stat(struct uml_stat *dst, struct stat64 *src)
+{
+	*dst = ((struct uml_stat) {
+		.ust_dev     = src->st_dev,     /* device */
+		.ust_ino     = src->st_ino,     /* inode */
+		.ust_mode    = src->st_mode,    /* protection */
+		.ust_nlink   = src->st_nlink,   /* number of hard links */
+		.ust_uid     = src->st_uid,     /* user ID of owner */
+		.ust_gid     = src->st_gid,     /* group ID of owner */
+		.ust_size    = src->st_size,    /* total size, in bytes */
+		.ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
+		.ust_blocks  = src->st_blocks,  /* number of blocks allocated */
+		.ust_atime   = src->st_atime,   /* time of last access */
+		.ust_mtime   = src->st_mtime,   /* time of last modification */
+		.ust_ctime   = src->st_ctime,   /* time of last change */
+	});
+}
+
+int os_stat_fd(const int fd, struct uml_stat *ubuf)
+{
+	struct stat64 sbuf;
+	int err;
+
+	do {
+		err = fstat64(fd, &sbuf);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	if(ubuf != NULL)
+		copy_stat(ubuf, &sbuf);
+	return(err);
+}
+
+int os_stat_file(const char *file_name, struct uml_stat *ubuf)
+{
+	struct stat64 sbuf;
+	int err;
+
+	do {
+		err = stat64(file_name, &sbuf);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	if(ubuf != NULL)
+		copy_stat(ubuf, &sbuf);
+	return(err);
+}
+
+int os_access(const char* file, int mode)
+{
+	int amode, err;
+
+	amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
+	      (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
+
+	err = access(file, amode);
+	if(err < 0)
+		return(-errno);
+
+	return(0);
+}
+
+void os_print_error(int error, const char* str)
+{
+	errno = error < 0 ? -error : error;
+
+	perror(str);
+}
+
+/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
+int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
+{
+	int err;
+
+	err = ioctl(fd, cmd, arg);
+	if(err < 0)
+		return(-errno);
+
+	return(err);
+}
+
+int os_window_size(int fd, int *rows, int *cols)
+{
+	struct winsize size;
+
+	if(ioctl(fd, TIOCGWINSZ, &size) < 0)
+		return(-errno);
+
+	*rows = size.ws_row;
+	*cols = size.ws_col;
+
+	return(0);
+}
+
+int os_new_tty_pgrp(int fd, int pid)
 {
-	struct stat64 buf;
+	if(ioctl(fd, TIOCSCTTY, 0) < 0){
+		printk("TIOCSCTTY failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	if(tcsetpgrp(fd, pid) < 0){
+		printk("tcsetpgrp failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	return(0);
+}
+
+/* FIXME: ensure namebuf in os_get_if_name is big enough */
+int os_get_ifname(int fd, char* namebuf)
+{
+	if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
+		return(-errno);
+
+	return(0);
+}
+
+int os_set_slip(int fd)
+{
+	int disc, sencap;
+
+	disc = N_SLIP;
+	if(ioctl(fd, TIOCSETD, &disc) < 0){
+		printk("Failed to set slip line discipline - "
+		       "errno = %d\n", errno);
+		return(-errno);
+	}
+
+	sencap = 0;
+	if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
+		printk("Failed to set slip encapsulation - "
+		       "errno = %d\n", errno);
+		return(-errno);
+	}
+
+	return(0);
+}
+
+int os_set_owner(int fd, int pid)
+{
+	if(fcntl(fd, F_SETOWN, pid) < 0){
+		int save_errno = errno;
+
+		if(fcntl(fd, F_GETOWN, 0) != pid)
+			return(-save_errno);
+	}
+
+	return(0);
+}
+
+/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
+int os_sigio_async(int master, int slave)
+{
+	int flags;
 
-	if(stat64(file, &buf) == -1)
+	flags = fcntl(master, F_GETFL);
+	if(flags < 0) {
+		printk("fcntl F_GETFL failed, errno = %d\n", errno);
 		return(-errno);
+	}
+
+	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+	   (fcntl(master, F_SETOWN, os_getpid()) < 0)){
+		printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
+		printk("fcntl F_SETFL failed, errno = %d\n", errno);
+		return(-errno);
+	}
 
-	if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
-	else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
-	else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
-	else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
-	else if(S_ISFIFO(buf.st_mode)) return(OS_TYPE_FIFO);
-	else if(S_ISSOCK(buf.st_mode)) return(OS_TYPE_SOCK);
+	return(0);
+}
+
+int os_mode_fd(int fd, int mode)
+{
+	int err;
+
+	do {
+		err = fchmod(fd, mode);
+	} while((err < 0) && (errno==EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	return(0);
+}
+
+int os_file_type(char *file)
+{
+	struct uml_stat buf;
+	int err;
+
+	err = os_stat_file(file, &buf);
+	if(err < 0)
+		return(err);
+
+	if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
+	else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
+	else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
+	else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
+	else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
+	else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
 	else return(OS_TYPE_FILE);
 }
 
 int os_file_mode(char *file, struct openflags *mode_out)
 {
+	int err;
+
 	*mode_out = OPENFLAGS();
 
-	if(!access(file, W_OK)) *mode_out = of_write(*mode_out);
-	else if(errno != EACCES) 
-		return(-errno);
+	err = os_access(file, OS_ACC_W_OK);
+	if((err < 0) && (err != -EACCES))
+		return(err);
 
-	if(!access(file, R_OK)) *mode_out = of_read(*mode_out);
-	else if(errno != EACCES) 
-		return(-errno);
+	*mode_out = of_write(*mode_out);
+
+	err = os_access(file, OS_ACC_R_OK);
+	if((err < 0) && (err != -EACCES))
+		return(err);
+
+	*mode_out = of_read(*mode_out);
 
 	return(0);
 }
@@ -63,16 +267,14 @@ int os_open_file(char *file, struct open
 	if(flags.e) f |= O_EXCL;
 
 	fd = open64(file, f, mode);
-	if(fd < 0) return(-errno);
-	
-	if(flags.cl){
-		if(fcntl(fd, F_SETFD, 1)){
-			close(fd);
-			return(-errno);
-		}
+	if(fd < 0)
+		return(-errno);
+
+	if(flags.cl && fcntl(fd, F_SETFD, 1)){
+		os_close_file(fd);
+		return(-errno);
 	}
 
- 	return(fd);
 	return(fd);
 }
 
@@ -90,7 +292,7 @@ int os_connect_socket(char *name)
 
 	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
 	if(err)
-		return(err);
+		return(-errno);
 
 	return(fd);
 }
@@ -109,88 +311,162 @@ int os_seek_file(int fd, __u64 offset)
 	return(0);
 }
 
-int os_read_file(int fd, void *buf, int len)
+static int fault_buffer(void *start, int len,
+			int (*copy_proc)(void *addr, void *buf, int len))
 {
-	int n;
+	int page = getpagesize(), i;
+	char c;
 
-	/* Force buf into memory if it's not already. */
+	for(i = 0; i < len; i += page){
+		if((*copy_proc)(start + i, &c, sizeof(c)))
+			return(-EFAULT);
+	}
+	if((len % page) != 0){
+		if((*copy_proc)(start + len - 1, &c, sizeof(c)))
+			return(-EFAULT);
+	}
+	return(0);
+}
 
-	/* XXX This fails if buf is kernel memory */
-#ifdef notdef
-	if(copy_to_user_proc(buf, &c, sizeof(c)))
-		return(-EFAULT);
-#endif
+static int file_io(int fd, void *buf, int len,
+		   int (*io_proc)(int fd, void *buf, int len),
+		   int (*copy_user_proc)(void *addr, void *buf, int len))
+{
+	int n, err;
+
+	do {
+		n = (*io_proc)(fd, buf, len);
+		if((n < 0) && (errno == EFAULT)){
+			err = fault_buffer(buf, len, copy_user_proc);
+			if(err)
+				return(err);
+			n = (*io_proc)(fd, buf, len);
+		}
+	} while((n < 0) && (errno == EINTR));
 
-	n = read(fd, buf, len);
 	if(n < 0)
 		return(-errno);
 	return(n);
 }
 
-int os_write_file(int fd, void *buf, int count)
+int os_read_file(int fd, void *buf, int len)
 {
-	int n;
-
-	/* Force buf into memory if it's not already. */
-	
-	/* XXX This fails if buf is kernel memory */
-#ifdef notdef
-	if(copy_to_user_proc(buf, buf, buf[0]))
-		return(-EFAULT);
-#endif
+	return(file_io(fd, buf, len, (int (*)(int, void *, int)) read,
+		       copy_from_user_proc));
+}
 
-	n = write(fd, buf, count);
-	if(n < 0)
-		return(-errno);
-	return(n);
+int os_write_file(int fd, const void *buf, int len)
+{
+	return(file_io(fd, (void *) buf, len,
+		       (int (*)(int, void *, int)) write, copy_to_user_proc));
 }
 
 int os_file_size(char *file, long long *size_out)
 {
-	struct stat64 buf;
+	struct uml_stat buf;
+	int err;
 
-	if(stat64(file, &buf) == -1){
-		printk("Couldn't stat \"%s\" : errno = %d\n", file, errno);
-		return(-errno);
+	err = os_stat_file(file, &buf);
+	if(err < 0){
+		printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+		return(err);
 	}
-	if(S_ISBLK(buf.st_mode)){
+
+	if(S_ISBLK(buf.ust_mode)){
 		int fd, blocks;
 
-		if((fd = open64(file, O_RDONLY)) < 0){
-			printk("Couldn't open \"%s\", errno = %d\n", file,
-			       errno);
-			return(-errno);
+		fd = os_open_file(file, of_read(OPENFLAGS()), 0);
+		if(fd < 0){
+			printk("Couldn't open \"%s\", errno = %d\n", file, -fd);
+			return(fd);
 		}
 		if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
 			printk("Couldn't get the block size of \"%s\", "
 			       "errno = %d\n", file, errno);
-			close(fd);
-			return(-errno);
+			err = -errno;
+			os_close_file(fd);
+			return(err);
 		}
 		*size_out = ((long long) blocks) * 512;
-		close(fd);
+		os_close_file(fd);
 		return(0);
 	}
-	*size_out = buf.st_size;
+	*size_out = buf.ust_size;
+	return(0);
+}
+
+int os_file_modtime(char *file, unsigned long *modtime)
+{
+	struct uml_stat buf;
+	int err;
+
+	err = os_stat_file(file, &buf);
+	if(err < 0){
+		printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+		return(err);
+	}
+
+	*modtime = buf.ust_mtime;
 	return(0);
 }
 
+int os_get_exec_close(int fd, int* close_on_exec)
+{
+	int ret;
+
+	do {
+		ret = fcntl(fd, F_GETFD);
+	} while((ret < 0) && (errno == EINTR)) ;
+
+	if(ret < 0)
+		return(-errno);
+
+	*close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
+	return(ret);
+}
+
+int os_set_exec_close(int fd, int close_on_exec)
+{
+	int flag, err;
+
+	if(close_on_exec) flag = FD_CLOEXEC;
+	else flag = 0;
+
+	do {
+		err = fcntl(fd, F_SETFD, flag);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+	return(err);
+}
+
 int os_pipe(int *fds, int stream, int close_on_exec)
 {
 	int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
 
 	err = socketpair(AF_UNIX, type, 0, fds);
-	if(err) 
+	if(err < 0)
 		return(-errno);
 
 	if(!close_on_exec)
 		return(0);
 
-	if((fcntl(fds[0], F_SETFD, 1) < 0) || (fcntl(fds[1], F_SETFD, 1) < 0))
-		printk("os_pipe : Setting FD_CLOEXEC failed, errno = %d", 
-		       errno);
+	err = os_set_exec_close(fds[0], 1);
+	if(err < 0)
+		goto error;
+
+	err = os_set_exec_close(fds[1], 1);
+	if(err < 0)
+		goto error;
 
 	return(0);
+
+ error:
+	printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
+	os_close_file(fds[1]);
+	os_close_file(fds[0]);
+	return(err);
 }
 
 int os_set_fd_async(int fd, int owner)
@@ -270,7 +546,7 @@ int os_shutdown_socket(int fd, int r, in
 		return(-EINVAL);
 	}
 	err = shutdown(fd, what);
-	if(err)
+	if(err < 0)
 		return(-errno);
 	return(0);
 }
@@ -315,7 +591,7 @@ int os_rcv_fd(int fd, int *helper_pid_ou
 	return(new);
 }
 
-int create_unix_socket(char *file, int len)
+int os_create_unix_socket(char *file, int len, int close_on_exec)
 {
 	struct sockaddr_un addr;
 	int sock, err;
@@ -327,6 +603,13 @@ int create_unix_socket(char *file, int l
 		return(-errno);
 	}
 
+	if(close_on_exec) {
+		err = os_set_exec_close(sock, 1);
+		if(err < 0)
+			printk("create_unix_socket : close_on_exec failed, "
+		       "err = %d", -err);
+	}
+
 	addr.sun_family = AF_UNIX;
 
 	/* XXX Be more careful about overflow */
@@ -334,14 +617,45 @@ int create_unix_socket(char *file, int l
 
 	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
 	if (err < 0){
-		printk("create_listening_socket - bind failed, errno = %d\n",
-		       errno);
+		printk("create_listening_socket at '%s' - bind failed, "
+		       "errno = %d\n", file, errno);
 		return(-errno);
 	}
 
 	return(sock);
 }
 
+void os_flush_stdout(void)
+{
+	fflush(stdout);
+}
+
+int os_lock_file(int fd, int excl)
+{
+	int type = excl ? F_WRLCK : F_RDLCK;
+	struct flock lock = ((struct flock) { .l_type	= type,
+					      .l_whence	= SEEK_SET,
+					      .l_start	= 0,
+					      .l_len	= 0 } );
+	int err, save;
+
+	err = fcntl(fd, F_SETLK, &lock);
+	if(!err)
+		goto out;
+
+	save = -errno;
+	err = fcntl(fd, F_GETLK, &lock);
+	if(err){
+		err = -errno;
+		goto out;
+	}
+
+	printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
+	err = save;
+ out:
+	return(err);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -puN arch/um/os-Linux/Makefile~uml-base-patch arch/um/os-Linux/Makefile
--- 25/arch/um/os-Linux/Makefile~uml-base-patch	2004-08-15 20:45:08.473366784 -0700
+++ 25-akpm/arch/um/os-Linux/Makefile	2004-08-15 20:46:03.303031408 -0700
@@ -3,13 +3,9 @@
 # Licensed under the GPL
 #
 
-obj-y = file.o process.o tty.o drivers/
+obj-y = file.o process.o tty.o user_syms.o drivers/
 
 USER_OBJS := $(foreach file,file.o process.o tty.o,$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-
-archmrproper:
diff -puN arch/um/os-Linux/process.c~uml-base-patch arch/um/os-Linux/process.c
--- 25/arch/um/os-Linux/process.c~uml-base-patch	2004-08-15 20:45:08.474366632 -0700
+++ 25-akpm/arch/um/os-Linux/process.c	2004-08-15 20:46:03.304031256 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,32 +7,37 @@
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
+#include <linux/unistd.h>
 #include <sys/mman.h>
 #include <sys/wait.h>
 #include "os.h"
 #include "user.h"
 
+#define ARBITRARY_ADDR -1
+#define FAILURE_PID    -1
+
 unsigned long os_process_pc(int pid)
 {
 	char proc_stat[sizeof("/proc/#####/stat\0")], buf[256];
 	unsigned long pc;
-	int fd;
+	int fd, err;
 
 	sprintf(proc_stat, "/proc/%d/stat", pid);
 	fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("os_process_pc - couldn't open '%s', errno = %d\n", 
-		       proc_stat, errno);
-		return(-1);
+		printk("os_process_pc - couldn't open '%s', err = %d\n",
+		       proc_stat, -fd);
+		return(ARBITRARY_ADDR);
 	}
-	if(read(fd, buf, sizeof(buf)) < 0){
-		printk("os_process_pc - couldn't read '%s', errno = %d\n", 
-		       proc_stat, errno);
-		close(fd);
-		return(-1);
+	err = os_read_file(fd, buf, sizeof(buf));
+	if(err < 0){
+		printk("os_process_pc - couldn't read '%s', err = %d\n",
+		       proc_stat, -err);
+		os_close_file(fd);
+		return(ARBITRARY_ADDR);
 	}
-	close(fd);
-	pc = -1;
+	os_close_file(fd);
+	pc = ARBITRARY_ADDR;
 	if(sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d "
 		  "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
 		  "%*d %*d %*d %*d %ld", &pc) != 1){
@@ -52,22 +57,23 @@ int os_process_parent(int pid)
 	snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
 	fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("Couldn't open '%s', errno = %d\n", stat, -fd);
-		return(-1);
+		printk("Couldn't open '%s', err = %d\n", stat, -fd);
+		return(FAILURE_PID);
 	}
 
-	n = read(fd, data, sizeof(data));
-	close(fd);
+	n = os_read_file(fd, data, sizeof(data));
+	os_close_file(fd);
 
 	if(n < 0){
-		printk("Couldn't read '%s', errno = %d\n", stat);
-		return(-1);
+		printk("Couldn't read '%s', err = %d\n", stat, -n);
+		return(FAILURE_PID);
 	}
 
-	parent = -1;
+	parent = FAILURE_PID;
 	/* XXX This will break if there is a space in the command */
 	n = sscanf(data, "%*d %*s %*c %d", &parent);
-	if(n != 1) printk("Failed to scan '%s'\n", data);
+	if(n != 1)
+		printk("Failed to scan '%s'\n", data);
 
 	return(parent);
 }
@@ -87,7 +93,8 @@ void os_kill_process(int pid, int reap_c
 
 void os_usr1_process(int pid)
 {
-	kill(pid, SIGUSR1);
+	syscall(__NR_tkill, pid, SIGUSR1);
+	/* kill(pid, SIGUSR1); */
 }
 
 int os_getpid(void)
@@ -95,7 +102,7 @@ int os_getpid(void)
 	return(getpid());
 }
 
-int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len, 
+int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
 		  int r, int w, int x)
 {
 	void *loc;
@@ -104,8 +111,8 @@ int os_map_memory(void *virt, int fd, un
 	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
 		(x ? PROT_EXEC : 0);
 
-	loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, 
-		   fd, off);
+	loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
+		     fd, off);
 	if(loc == MAP_FAILED)
 		return(-errno);
 	return(0);
@@ -126,7 +133,8 @@ int os_unmap_memory(void *addr, int len)
         int err;
 
         err = munmap(addr, len);
-        if(err < 0) return(-errno);
+	if(err < 0)
+		return(-errno);
         return(0);
 }
 
diff -puN arch/um/os-Linux/tty.c~uml-base-patch arch/um/os-Linux/tty.c
--- 25/arch/um/os-Linux/tty.c~uml-base-patch	2004-08-15 20:45:08.475366480 -0700
+++ 25-akpm/arch/um/os-Linux/tty.c	2004-08-15 20:46:03.304031256 -0700
@@ -28,10 +28,10 @@ int get_pty(void)
 	struct grantpt_info info;
 	int fd;
 
-	if((fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0)) < 0){
-		printk("get_pty : Couldn't open /dev/ptmx - errno = %d\n",
-		       errno);
-		return(-1);
+	fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
+		return(fd);
 	}
 
 	info.fd = fd;
@@ -39,7 +39,7 @@ int get_pty(void)
 
 	if(info.res < 0){
 		printk("get_pty : Couldn't grant pty - errno = %d\n", 
-		       info.err);
+		       -info.err);
 		return(-1);
 	}
 	if(unlockpt(fd) < 0){
diff -puN /dev/null arch/um/os-Linux/user_syms.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/os-Linux/user_syms.c	2004-08-15 20:46:03.305031104 -0700
@@ -0,0 +1,88 @@
+#include "linux/types.h"
+#include "linux/module.h"
+
+/* Some of this are builtin function (some are not but could in the future),
+ * so I *must* declare good prototypes for them and then EXPORT them.
+ * The kernel code uses the macro defined by include/linux/string.h,
+ * so I undef macros; the userspace code does not include that and I
+ * add an EXPORT for the glibc one.*/
+
+#undef strlen
+#undef strstr
+#undef memcpy
+#undef memset
+
+extern size_t strlen(const char *);
+extern void *memcpy(void *, const void *, size_t);
+extern void *memset(void *, int, size_t);
+extern int printf(const char *, ...);
+
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(printf);
+
+EXPORT_SYMBOL(strstr);
+
+/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
+ * However, the modules will use the CRC defined *here*, no matter if it is
+ * good; so the versions of these symbols will always match
+ */
+#define EXPORT_SYMBOL_PROTO(sym)       \
+       int sym(void);                  \
+       EXPORT_SYMBOL(sym);
+
+EXPORT_SYMBOL_PROTO(__errno_location);
+
+EXPORT_SYMBOL_PROTO(access);
+EXPORT_SYMBOL_PROTO(open);
+EXPORT_SYMBOL_PROTO(open64);
+EXPORT_SYMBOL_PROTO(close);
+EXPORT_SYMBOL_PROTO(read);
+EXPORT_SYMBOL_PROTO(write);
+EXPORT_SYMBOL_PROTO(dup2);
+EXPORT_SYMBOL_PROTO(__xstat);
+EXPORT_SYMBOL_PROTO(__lxstat);
+EXPORT_SYMBOL_PROTO(__lxstat64);
+EXPORT_SYMBOL_PROTO(lseek);
+EXPORT_SYMBOL_PROTO(lseek64);
+EXPORT_SYMBOL_PROTO(chown);
+EXPORT_SYMBOL_PROTO(truncate);
+EXPORT_SYMBOL_PROTO(utime);
+EXPORT_SYMBOL_PROTO(chmod);
+EXPORT_SYMBOL_PROTO(rename);
+EXPORT_SYMBOL_PROTO(__xmknod);
+
+EXPORT_SYMBOL_PROTO(symlink);
+EXPORT_SYMBOL_PROTO(link);
+EXPORT_SYMBOL_PROTO(unlink);
+EXPORT_SYMBOL_PROTO(readlink);
+
+EXPORT_SYMBOL_PROTO(mkdir);
+EXPORT_SYMBOL_PROTO(rmdir);
+EXPORT_SYMBOL_PROTO(opendir);
+EXPORT_SYMBOL_PROTO(readdir);
+EXPORT_SYMBOL_PROTO(closedir);
+EXPORT_SYMBOL_PROTO(seekdir);
+EXPORT_SYMBOL_PROTO(telldir);
+
+EXPORT_SYMBOL_PROTO(ioctl);
+
+EXPORT_SYMBOL_PROTO(pread64);
+EXPORT_SYMBOL_PROTO(pwrite64);
+
+EXPORT_SYMBOL_PROTO(statfs);
+EXPORT_SYMBOL_PROTO(statfs64);
+
+EXPORT_SYMBOL_PROTO(getuid);
+
+/*
+ * 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 -puN arch/um/sys-i386/bugs.c~uml-base-patch arch/um/sys-i386/bugs.c
--- 25/arch/um/sys-i386/bugs.c~uml-base-patch	2004-08-15 20:45:08.477366176 -0700
+++ 25-akpm/arch/um/sys-i386/bugs.c	2004-08-15 20:46:03.306030952 -0700
@@ -4,20 +4,21 @@
  */
 
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/signal.h>
+#include <asm/ldt.h>
 #include "kern_util.h"
 #include "user.h"
 #include "sysdep/ptrace.h"
 #include "task.h"
+#include "os.h"
 
 #define MAXTOKEN 64
 
 /* Set during early boot */
-int cpu_has_cmov = 1;
-int cpu_has_xmm = 0;
+int host_has_cmov = 1;
+int host_has_xmm = 0;
 
 static char token(int fd, char *buf, int len, char stop)
 {
@@ -27,13 +28,15 @@ static char token(int fd, char *buf, int
 	ptr = buf;
 	end = &buf[len];
 	do {
-		n = read(fd, ptr, sizeof(*ptr));
+		n = os_read_file(fd, ptr, sizeof(*ptr));
 		c = *ptr++;
-		if(n == 0) return(0);
-		else if(n != sizeof(*ptr)){
-			printk("Reading /proc/cpuinfo failed, "
-			       "errno = %d\n", errno);
-			return(-errno);
+		if(n != sizeof(*ptr)){
+			if(n == 0) return(0);
+			printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
+			if(n < 0)
+				return(n);
+			else
+				return(-EIO);
 		}
 	} while((c != '\n') && (c != stop) && (ptr < end));
 
@@ -45,45 +48,79 @@ static char token(int fd, char *buf, int
 	return(c);
 }
 
-static int check_cpu_feature(char *feature, int *have_it)
+static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
 {
-	char buf[MAXTOKEN], c;
-	int fd, len = sizeof(buf)/sizeof(buf[0]), n;
-
-	printk("Checking for host processor %s support...", feature);
-	fd = open("/proc/cpuinfo", O_RDONLY);
-	if(fd < 0){
-		printk("Couldn't open /proc/cpuinfo, errno = %d\n", errno);
-		return(0);
-	}
+	int n;
+	char c;
 
-	*have_it = 0;
-	buf[len - 1] = '\0';
+	scratch[len - 1] = '\0';
 	while(1){
-		c = token(fd, buf, len - 1, ':');
-		if(c <= 0) goto out;
+		c = token(fd, scratch, len - 1, ':');
+		if(c <= 0)
+			return(0);
 		else if(c != ':'){
 			printk("Failed to find ':' in /proc/cpuinfo\n");
-			goto out;
+			return(0);
 		}
 
-		if(!strncmp(buf, "flags", strlen("flags"))) break;
+		if(!strncmp(scratch, key, strlen(key)))
+			return(1);
 
 		do {
-			n = read(fd, &c, sizeof(c));
+			n = os_read_file(fd, &c, sizeof(c));
 			if(n != sizeof(c)){
 				printk("Failed to find newline in "
-				       "/proc/cpuinfo, n = %d, errno = %d\n",
-				       n, errno);
-				goto out;
+				       "/proc/cpuinfo, err = %d\n", -n);
+				return(0);
 			}
 		} while(c != '\n');
 	}
+	return(0);
+}
+
+int cpu_feature(char *what, char *buf, int len)
+{
+	int fd, ret = 0;
+
+	fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+		return(0);
+	}
+
+	if(!find_cpuinfo_line(fd, what, buf, len)){
+		printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
+		goto out_close;
+	}
+
+	token(fd, buf, len, '\n');
+	ret = 1;
+
+ out_close:
+	os_close_file(fd);
+	return(ret);
+}
+
+static int check_cpu_flag(char *feature, int *have_it)
+{
+	char buf[MAXTOKEN], c;
+	int fd, len = sizeof(buf)/sizeof(buf[0]);
+
+	printk("Checking for host processor %s support...", feature);
+	fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+		return(0);
+	}
+
+	*have_it = 0;
+	if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0])))
+		goto out;
 
 	c = token(fd, buf, len - 1, ' ');
 	if(c < 0) goto out;
 	else if(c != ' '){
-		printk("Failed to find ':' in /proc/cpuinfo\n");
+		printk("Failed to find ' ' in /proc/cpuinfo\n");
 		goto out;
 	}
 
@@ -100,21 +137,48 @@ static int check_cpu_feature(char *featu
  out:
 	if(*have_it == 0) printk("No\n");
 	else if(*have_it == 1) printk("Yes\n");
-	close(fd);
+	os_close_file(fd);
 	return(1);
 }
 
+#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
+       * for some people.
+       */
+static void disable_lcall(void)
+{
+	struct modify_ldt_ldt_s ldt;
+	int err;
+
+	bzero(&ldt, sizeof(ldt));
+	ldt.entry_number = 7;
+	ldt.base_addr = 0;
+	ldt.limit = 0;
+	err = modify_ldt(1, &ldt, sizeof(ldt));
+	if(err)
+		printk("Failed to disable lcall7 - errno = %d\n", errno);
+}
+#endif
+
+void arch_init_thread(void)
+{
+#if 0
+	disable_lcall();
+#endif
+}
+
 void arch_check_bugs(void)
 {
 	int have_it;
 
-	if(access("/proc/cpuinfo", R_OK)){
+	if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){
 		printk("/proc/cpuinfo not available - skipping CPU capability "
 		       "checks\n");
 		return;
 	}
-	if(check_cpu_feature("cmov", &have_it)) cpu_has_cmov = have_it;
-	if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it;
+	if(check_cpu_flag("cmov", &have_it))
+		host_has_cmov = have_it;
+	if(check_cpu_flag("xmm", &have_it))
+		host_has_xmm = have_it;
 }
 
 int arch_handle_signal(int sig, union uml_pt_regs *regs)
@@ -130,18 +194,18 @@ int arch_handle_signal(int sig, union um
 	if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40))
 		return(0);
 
-	if(cpu_has_cmov == 0)
+	if(host_has_cmov == 0)
 		panic("SIGILL caused by cmov, which this processor doesn't "
 		      "implement, boot a filesystem compiled for older "
 		      "processors");
-	else if(cpu_has_cmov == 1)
+	else if(host_has_cmov == 1)
 		panic("SIGILL caused by cmov, which this processor claims to "
 		      "implement");
-	else if(cpu_has_cmov == -1)
+	else if(host_has_cmov == -1)
 		panic("SIGILL caused by cmov, couldn't tell if this processor "
 		      "implements it, boot a filesystem compiled for older "
 		      "processors");
-	else panic("Bad value for cpu_has_cmov (%d)", cpu_has_cmov);
+	else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
 	return(0);
 }
 
diff -L arch/um/sys-i386/extable.c -puN arch/um/sys-i386/extable.c~uml-base-patch /dev/null
--- 25/arch/um/sys-i386/extable.c
+++ /dev/null	2003-09-15 06:40:47.000000000 -0700
@@ -1,30 +0,0 @@
-/*
- * linux/arch/i386/mm/extable.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
-	       const struct exception_table_entry *last,
-	       unsigned long value)
-{
-        while (first <= last) {
-		const struct exception_table_entry *mid;
-		long diff;
-
-		mid = (last - first) / 2 + first;
-		diff = mid->insn - value;
-                if (diff == 0)
-                        return mid;
-                else if (diff < 0)
-                        first = mid+1;
-                else
-                        last = mid-1;
-        }
-        return NULL;
-}
diff -puN arch/um/sys-i386/fault.c~uml-base-patch arch/um/sys-i386/fault.c
--- 25/arch/um/sys-i386/fault.c~uml-base-patch	2004-08-15 20:45:08.479365872 -0700
+++ 25-akpm/arch/um/sys-i386/fault.c	2004-08-15 20:46:03.307030800 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,16 +7,24 @@
 #include "sysdep/ptrace.h"
 #include "sysdep/sigcontext.h"
 
-extern unsigned long search_exception_table(unsigned long addr);
+/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
+struct exception_table_entry
+{
+	unsigned long insn;
+	unsigned long fixup;
+};
 
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
+/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
 int arch_fixup(unsigned long address, void *sc_ptr)
 {
 	struct sigcontext *sc = sc_ptr;
-	unsigned long fixup;
+	const struct exception_table_entry *fixup;
 
 	fixup = search_exception_tables(address);
 	if(fixup != 0){
-		sc->eip = fixup;
+		sc->eip = fixup->fixup;
 		return(1);
 	}
 	return(0);
diff -puN arch/um/sys-i386/Makefile~uml-base-patch arch/um/sys-i386/Makefile
--- 25/arch/um/sys-i386/Makefile~uml-base-patch	2004-08-15 20:45:08.481365568 -0700
+++ 25-akpm/arch/um/sys-i386/Makefile	2004-08-15 20:46:03.307030800 -0700
@@ -1,7 +1,8 @@
-obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \
-	ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
+obj-y = bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o ptrace_user.o \
+	semaphore.o sigcontext.o syscalls.o sysrq.o time.o
 
 obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_MODULES) += module.o
 
 USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
@@ -9,6 +10,8 @@ USER_OBJS := $(foreach file,$(USER_OBJS)
 SYMLINKS = semaphore.c highmem.c module.c
 SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
 
+clean-files := $(SYMLINKS)
+
 semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
@@ -24,19 +27,4 @@ $(USER_OBJS) : %.o: %.c
 $(SYMLINKS): 
 	$(call make_link,$@)
 
-clean:
-	$(MAKE) -C util clean
-
-fastdep:
-
-dep:
-
-archmrproper:
-	rm -f $(SYMLINKS)
-
-archclean:
-
-archdep:
-
-modules:
-
+subdir- := util
diff -puN arch/um/sys-i386/ptrace_user.c~uml-base-patch arch/um/sys-i386/ptrace_user.c
--- 25/arch/um/sys-i386/ptrace_user.c~uml-base-patch	2004-08-15 20:45:08.482365416 -0700
+++ 25-akpm/arch/um/sys-i386/ptrace_user.c	2004-08-15 20:46:03.308030648 -0700
@@ -39,10 +39,10 @@ static void write_debugregs(int pid, uns
 	nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
 	for(i = 0; i < nregs; i++){
 		if((i == 4) || (i == 5)) continue;
-		if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
+		if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i],
 			  regs[i]) < 0)
-			printk("write_debugregs - ptrace failed, "
-			       "errno = %d\n", errno);
+			printk("write_debugregs - ptrace failed on "
+			       "register %d, errno = %d\n", errno);
 	}
 }
 
@@ -54,7 +54,7 @@ static void read_debugregs(int pid, unsi
 	dummy = NULL;
 	nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
 	for(i = 0; i < nregs; i++){
-		regs[i] = ptrace(PTRACE_PEEKUSR, pid, 
+		regs[i] = ptrace(PTRACE_PEEKUSER, pid,
 				 &dummy->u_debugreg[i], 0);
 	}
 }
diff -puN /dev/null arch/um/sys-i386/time.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/um/sys-i386/time.c	2004-08-15 20:46:03.308030648 -0700
@@ -0,0 +1,24 @@
+/*
+ * sys-i386/time.c
+ * Created 		25.9.2002	Sapan Bhatia
+ *
+ */
+
+unsigned long long time_stamp(void)
+{
+	unsigned long low, high;
+
+	asm("rdtsc" : "=a" (low), "=d" (high));
+	return((((unsigned long long) high) << 32) + low);
+}
+
+/*
+ * 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 -puN arch/um/sys-i386/util/Makefile~uml-base-patch arch/um/sys-i386/util/Makefile
--- 25/arch/um/sys-i386/util/Makefile~uml-base-patch	2004-08-15 20:45:08.484365112 -0700
+++ 25-akpm/arch/um/sys-i386/util/Makefile	2004-08-15 20:46:03.308030648 -0700
@@ -1,15 +1,11 @@
 
-hostprogs-y	:= mk_sc
-always		:= $(hostprogs-y) mk_thread
-targets		:= mk_thread_kern.o mk_thread_user.o
+hostprogs-y	:= mk_sc mk_thread
+always		:= $(hostprogs-y)
 
-mk_sc-objs	:= mk_sc.o
+mk_thread-objs	:= mk_thread_kern.o mk_thread_user.o
 
-$(obj)/mk_thread : $(obj)/mk_thread_kern.o $(obj)/mk_thread_user.o
-	$(CC) $(CFLAGS) -o $@ $^
-
-$(obj)/mk_thread_user.o : $(src)/mk_thread_user.c
-	$(CC) $(USER_CFLAGS) -c -o $@ $<
+HOSTCFLAGS_mk_thread_kern.o	:= $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_thread_user.o	:= $(USER_CFLAGS)
 
 clean :
 	$(RM) -f $(build-targets)
diff -puN arch/um/sys-i386/util/mk_sc.c~uml-base-patch arch/um/sys-i386/util/mk_sc.c
--- 25/arch/um/sys-i386/util/mk_sc.c~uml-base-patch	2004-08-15 20:45:08.486364808 -0700
+++ 25-akpm/arch/um/sys-i386/util/mk_sc.c	2004-08-15 20:46:03.309030496 -0700
@@ -38,6 +38,7 @@ int main(int argc, char **argv)
   SC_OFFSET("SC_ERR", err);
   SC_OFFSET("SC_CR2", cr2);
   SC_OFFSET("SC_FPSTATE", fpstate);
+  SC_OFFSET("SC_SIGMASK", oldmask);
   SC_FP_OFFSET("SC_FP_CW", cw);
   SC_FP_OFFSET("SC_FP_SW", sw);
   SC_FP_OFFSET("SC_FP_TAG", tag);
diff -puN arch/um/sys-ia64/Makefile~uml-base-patch arch/um/sys-ia64/Makefile
--- 25/arch/um/sys-ia64/Makefile~uml-base-patch	2004-08-15 20:45:08.488364504 -0700
+++ 25-akpm/arch/um/sys-ia64/Makefile	2004-08-15 20:46:03.309030496 -0700
@@ -7,18 +7,5 @@ all: $(OBJ)
 $(OBJ): $(OBJS)
 	rm -f $@
 	$(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
-clean:
-	rm -f $(OBJS)
 
-fastdep:
-
-archmrproper:
-
-archclean:
-	rm -f link.ld
-	@$(MAKEBOOT) clean
-
-archdep:
-	@$(MAKEBOOT) dep
-
-modules:
+clean-files := $(OBJS) link.ld
diff -puN arch/um/sys-ppc/Makefile~uml-base-patch arch/um/sys-ppc/Makefile
--- 25/arch/um/sys-ppc/Makefile~uml-base-patch	2004-08-15 20:45:08.489364352 -0700
+++ 25-akpm/arch/um/sys-ppc/Makefile	2004-08-15 20:46:03.310030344 -0700
@@ -66,13 +66,4 @@ misc.o: misc.S ppc_defs.h
 	$(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
 	rm -f asm
 
-clean:
-	rm -f $(OBJS)
-	rm -f ppc_defs.h
-	rm -f checksum.S semaphore.c mk_defs.c
-
-fastdep:
-
-dep:
-
-modules:
+clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c
diff -puN arch/um/uml.lds.S~uml-base-patch arch/um/uml.lds.S
--- 25/arch/um/uml.lds.S~uml-base-patch	2004-08-15 20:45:08.491364048 -0700
+++ 25-akpm/arch/um/uml.lds.S	2004-08-15 20:46:03.310030344 -0700
@@ -9,7 +9,6 @@ SECTIONS
 {
   . = START + SIZEOF_HEADERS;
 
-  . = ALIGN(4096);
   __binary_start = .;
 #ifdef MODE_TT
   .thread_private : {
@@ -26,11 +25,16 @@ SECTIONS
   . = ALIGN(4096);		/* Init code and data */
   _stext = .;
   __init_begin = .;
-  .text.init : { *(.text.init) }
+  .init.text : {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
   . = ALIGN(4096);
   .text      :
   {
     *(.text)
+    SCHED_TEXT
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
     *(.gnu.linkonce.t*)
@@ -38,7 +42,7 @@ SECTIONS
 
   #include "asm/common.lds.S"
 
-  .data.init : { *(.data.init) }
+  init.data : { *(init.data) }
   .data    :
   {
     . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
diff -puN arch/um/util/Makefile~uml-base-patch arch/um/util/Makefile
--- 25/arch/um/util/Makefile~uml-base-patch	2004-08-15 20:45:08.492363896 -0700
+++ 25-akpm/arch/um/util/Makefile	2004-08-15 20:46:03.310030344 -0700
@@ -1,23 +1,8 @@
-always		:= mk_task mk_constants
-targets		:= mk_task_user.o mk_task_kern.o \
-		   mk_constants_user.o mk_constants_kern.o
+host-progs		:= mk_task mk_constants
+always			:= $(host-progs)
 
-$(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o
-	$(CC) -o $@ $^
+mk_task-objs		:= mk_task_user.o mk_task_kern.o
+mk_constants-objs	:= mk_constants_user.o mk_constants_kern.o
 
-$(obj)/mk_task_user.o: $(src)/mk_task_user.c
-	$(CC) -o $@ -c $< 
-
-$(obj)/mk_constants : $(obj)/mk_constants_user.o $(obj)/mk_constants_kern.o
-	$(CC) -o $@ $^
-
-$(obj)/mk_constants_user.o : $(src)/mk_constants_user.c
-	$(CC) -c $< -o $@
-
-$(obj)/mk_constants_kern.o : $(src)/mk_constants_kern.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-clean:
-	$(RM) $(build-targets)
-
-archmrproper:
+HOSTCFLAGS_mk_task_kern.o	:= $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_constants_kern.o	:= $(CFLAGS) $(CPPFLAGS)
diff -puN arch/um/util/mk_constants_kern.c~uml-base-patch arch/um/util/mk_constants_kern.c
--- 25/arch/um/util/mk_constants_kern.c~uml-base-patch	2004-08-15 20:45:08.493363744 -0700
+++ 25-akpm/arch/um/util/mk_constants_kern.c	2004-08-15 20:46:03.311030192 -0700
@@ -1,5 +1,6 @@
 #include "linux/kernel.h"
 #include "linux/stringify.h"
+#include "linux/time.h"
 #include "asm/page.h"
 
 extern void print_head(void);
@@ -11,6 +12,7 @@ int main(int argc, char **argv)
 {
   print_head();
   print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
+
   print_constant_str("UM_KERN_EMERG", KERN_EMERG);
   print_constant_str("UM_KERN_ALERT", KERN_ALERT);
   print_constant_str("UM_KERN_CRIT", KERN_CRIT);
@@ -19,6 +21,8 @@ int main(int argc, char **argv)
   print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
   print_constant_str("UM_KERN_INFO", KERN_INFO);
   print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
+
+  print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC);
   print_tail();
   return(0);
 }
diff -puN /dev/null fs/hostfs/hostfs.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/fs/hostfs/hostfs.h	2004-08-15 20:46:03.312030040 -0700
@@ -0,0 +1,79 @@
+#ifndef __UM_FS_HOSTFS
+#define __UM_FS_HOSTFS
+
+#include "os.h"
+
+/* These are exactly the same definitions as in fs.h, but the names are
+ * changed so that this file can be included in both kernel and user files.
+ */
+
+#define HOSTFS_ATTR_MODE	1
+#define HOSTFS_ATTR_UID 	2
+#define HOSTFS_ATTR_GID 	4
+#define HOSTFS_ATTR_SIZE	8
+#define HOSTFS_ATTR_ATIME	16
+#define HOSTFS_ATTR_MTIME	32
+#define HOSTFS_ATTR_CTIME	64
+#define HOSTFS_ATTR_ATIME_SET	128
+#define HOSTFS_ATTR_MTIME_SET	256
+#define HOSTFS_ATTR_FORCE	512	/* Not a change, but a change it */
+#define HOSTFS_ATTR_ATTR_FLAG	1024
+
+struct hostfs_iattr {
+	unsigned int	ia_valid;
+	mode_t		ia_mode;
+	uid_t		ia_uid;
+	gid_t		ia_gid;
+	loff_t		ia_size;
+	struct timespec	ia_atime;
+	struct timespec	ia_mtime;
+	struct timespec	ia_ctime;
+	unsigned int	ia_attr_flags;
+};
+
+extern int stat_file(const char *path, unsigned long long *inode_out,
+		     int *mode_out, int *nlink_out, int *uid_out, int *gid_out,
+		     unsigned long long *size_out, struct timespec *atime_out,
+		     struct timespec *mtime_out, struct timespec *ctime_out,
+		     int *blksize_out, unsigned long long *blocks_out);
+extern int access_file(char *path, int r, int w, int x);
+extern int open_file(char *path, int r, int w, int append);
+extern int file_type(const char *path, int *rdev);
+extern void *open_dir(char *path, int *err_out);
+extern char *read_dir(void *stream, unsigned long long *pos,
+		      unsigned long long *ino_out, int *len_out);
+extern void close_file(void *stream);
+extern void close_dir(void *stream);
+extern int read_file(int fd, unsigned long long *offset, char *buf, int len);
+extern int write_file(int fd, unsigned long long *offset, const char *buf,
+		      int len);
+extern int lseek_file(int fd, long long offset, int whence);
+extern int file_create(char *name, int ur, int uw, int ux, int gr,
+		       int gw, int gx, int or, int ow, int ox);
+extern int set_attr(const char *file, struct hostfs_iattr *attrs);
+extern int make_symlink(const char *from, const char *to);
+extern int unlink_file(const char *file);
+extern int do_mkdir(const char *file, int mode);
+extern int do_rmdir(const char *file);
+extern int do_mknod(const char *file, int mode, int dev);
+extern int link_file(const char *from, const char *to);
+extern int do_readlink(char *file, char *buf, int size);
+extern int rename_file(char *from, char *to);
+extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
+		     long long *bfree_out, long long *bavail_out,
+		     long long *files_out, long long *ffree_out,
+		     void *fsid_out, int fsid_size, long *namelen_out,
+		     long *spare_out);
+
+#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 -puN /dev/null fs/hostfs/hostfs_kern.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/fs/hostfs/hostfs_kern.c	2004-08-15 20:46:03.316029432 -0700
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ *
+ * Ported the filesystem routines to 2.5.
+ * 2003-02-10 Petr Baudis <pasky@ucw.cz>
+ */
+
+#include <linux/stddef.h>
+#include <linux/fs.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/blkdev.h>
+#include <linux/list.h>
+#include <linux/buffer_head.h>
+#include <linux/root_dev.h>
+#include <linux/statfs.h>
+#include <asm/uaccess.h>
+#include "hostfs.h"
+#include "kern_util.h"
+#include "kern.h"
+#include "user_util.h"
+#include "2_5compat.h"
+#include "init.h"
+
+struct hostfs_inode_info {
+	char *host_filename;
+	int fd;
+	int mode;
+	struct inode vfs_inode;
+};
+
+static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
+{
+	return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
+}
+
+#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode)
+
+int hostfs_d_delete(struct dentry *dentry)
+{
+	return(1);
+}
+
+struct dentry_operations hostfs_dentry_ops = {
+	.d_delete		= hostfs_d_delete,
+};
+
+/* Changed in hostfs_args before the kernel starts running */
+static char *root_ino = "/";
+static int append = 0;
+
+#define HOSTFS_SUPER_MAGIC 0x00c0ffee
+
+static struct inode_operations hostfs_iops;
+static struct inode_operations hostfs_dir_iops;
+static struct address_space_operations hostfs_link_aops;
+
+static int __init hostfs_args(char *options, int *add)
+{
+	char *ptr;
+
+	ptr = strchr(options, ',');
+	if(ptr != NULL)
+		*ptr++ = '\0';
+	if(*options != '\0')
+		root_ino = options;
+
+	options = ptr;
+	while(options){
+		ptr = strchr(options, ',');
+		if(ptr != NULL)
+			*ptr++ = '\0';
+		if(*options != '\0'){
+			if(!strcmp(options, "append"))
+				append = 1;
+			else printf("hostfs_args - unsupported option - %s\n",
+				    options);
+		}
+		options = ptr;
+	}
+	return(0);
+}
+
+__uml_setup("hostfs=", hostfs_args,
+"hostfs=<root dir>,<flags>,...\n"
+"    This is used to set hostfs parameters.  The root directory argument\n"
+"    is used to confine all hostfs mounts to within the specified directory\n"
+"    tree on the host.  If this isn't specified, then a user inside UML can\n"
+"    mount anything on the host that's accessible to the user that's running\n"
+"    it.\n"
+"    The only flag currently supported is 'append', which specifies that all\n"
+"    files opened by hostfs will be opened in append mode.\n\n"
+);
+
+static char *dentry_name(struct dentry *dentry, int extra)
+{
+	struct dentry *parent;
+	char *root, *name;
+	int len;
+
+	len = 0;
+	parent = dentry;
+	while(parent->d_parent != parent){
+		len += parent->d_name.len + 1;
+		parent = parent->d_parent;
+	}
+
+	root = HOSTFS_I(parent->d_inode)->host_filename;
+	len += strlen(root);
+	name = kmalloc(len + extra + 1, GFP_KERNEL);
+	if(name == NULL) return(NULL);
+
+	name[len] = '\0';
+	parent = dentry;
+	while(parent->d_parent != parent){
+		len -= parent->d_name.len + 1;
+		name[len] = '/';
+		strncpy(&name[len + 1], parent->d_name.name,
+			parent->d_name.len);
+		parent = parent->d_parent;
+	}
+	strncpy(name, root, strlen(root));
+	return(name);
+}
+
+static char *inode_name(struct inode *ino, int extra)
+{
+	struct dentry *dentry;
+
+	dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
+	return(dentry_name(dentry, extra));
+}
+
+static int read_name(struct inode *ino, char *name)
+{
+	/* The non-int inode fields are copied into ints by stat_file and
+	 * then copied into the inode because passing the actual pointers
+	 * in and having them treated as int * breaks on big-endian machines
+	 */
+	int err;
+	int i_mode, i_nlink, i_blksize;
+	unsigned long long i_size;
+	unsigned long long i_ino;
+	unsigned long long i_blocks;
+
+	err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid,
+			&ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime,
+			&ino->i_ctime, &i_blksize, &i_blocks);
+	if(err)
+		return(err);
+
+	ino->i_ino = i_ino;
+	ino->i_mode = i_mode;
+	ino->i_nlink = i_nlink;
+	ino->i_size = i_size;
+	ino->i_blksize = i_blksize;
+	ino->i_blocks = i_blocks;
+	if((ino->i_sb->s_dev == ROOT_DEV) && (ino->i_uid == getuid()))
+		ino->i_uid = 0;
+	return(0);
+}
+
+static char *follow_link(char *link)
+{
+	int len, n;
+	char *name, *resolved, *end;
+
+	len = 64;
+	while(1){
+		n = -ENOMEM;
+		name = kmalloc(len, GFP_KERNEL);
+		if(name == NULL)
+			goto out;
+
+		n = do_readlink(link, name, len);
+		if(n < len)
+			break;
+		len *= 2;
+		kfree(name);
+	}
+	if(n < 0)
+		goto out_free;
+
+	if(*name == '/')
+		return(name);
+
+	end = strrchr(link, '/');
+	if(end == NULL)
+		return(name);
+
+	*(end + 1) = '\0';
+	len = strlen(link) + strlen(name) + 1;
+
+	resolved = kmalloc(len, GFP_KERNEL);
+	if(resolved == NULL){
+		n = -ENOMEM;
+		goto out_free;
+	}
+
+	sprintf(resolved, "%s%s", link, name);
+	kfree(name);
+	kfree(link);
+	return(resolved);
+
+ out_free:
+	kfree(name);
+ out:
+	return(ERR_PTR(n));
+}
+
+static int read_inode(struct inode *ino)
+{
+	char *name;
+	int err = 0;
+
+	/* Unfortunately, we are called from iget() when we don't have a dentry
+	 * allocated yet.
+	 */
+	if(list_empty(&ino->i_dentry))
+		goto out;
+
+	err = -ENOMEM;
+	name = inode_name(ino, 0);
+	if(name == NULL)
+		goto out;
+
+	if(file_type(name, NULL) == OS_TYPE_SYMLINK){
+		name = follow_link(name);
+		if(IS_ERR(name)){
+			err = PTR_ERR(name);
+			goto out;
+		}
+	}
+
+	err = read_name(ino, name);
+	kfree(name);
+ out:
+	return(err);
+}
+
+int hostfs_statfs(struct super_block *sb, struct kstatfs *sf)
+{
+	/* do_statfs uses struct statfs64 internally, but the linux kernel
+	 * struct statfs still has 32-bit versions for most of these fields,
+	 * so we convert them here
+	 */
+	int err;
+	long long f_blocks;
+	long long f_bfree;
+	long long f_bavail;
+	long long f_files;
+	long long f_ffree;
+
+	err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename,
+			&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
+			&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
+			&sf->f_namelen, sf->f_spare);
+	if(err) return(err);
+	sf->f_blocks = f_blocks;
+	sf->f_bfree = f_bfree;
+	sf->f_bavail = f_bavail;
+	sf->f_files = f_files;
+	sf->f_ffree = f_ffree;
+	sf->f_type = HOSTFS_SUPER_MAGIC;
+	return(0);
+}
+
+static struct inode *hostfs_alloc_inode(struct super_block *sb)
+{
+	struct hostfs_inode_info *hi;
+
+	hi = kmalloc(sizeof(*hi), GFP_KERNEL);
+	if(hi == NULL)
+		return(NULL);
+
+	*hi = ((struct hostfs_inode_info) { .host_filename	= NULL,
+					    .fd			= -1,
+					    .mode		= 0 });
+	inode_init_once(&hi->vfs_inode);
+	return(&hi->vfs_inode);
+}
+
+static void hostfs_destroy_inode(struct inode *inode)
+{
+	if(HOSTFS_I(inode)->host_filename)
+		kfree(HOSTFS_I(inode)->host_filename);
+
+	if(HOSTFS_I(inode)->fd != -1)
+		close_file(&HOSTFS_I(inode)->fd);
+
+	kfree(HOSTFS_I(inode));
+}
+
+static void hostfs_read_inode(struct inode *inode)
+{
+	read_inode(inode);
+}
+
+static struct super_operations hostfs_sbops = {
+	.alloc_inode	= hostfs_alloc_inode,
+	.destroy_inode	= hostfs_destroy_inode,
+	.read_inode	= hostfs_read_inode,
+	.statfs		= hostfs_statfs,
+};
+
+int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
+{
+	void *dir;
+	char *name;
+	unsigned long long next, ino;
+	int error, len;
+
+	name = dentry_name(file->f_dentry, 0);
+	if(name == NULL) return(-ENOMEM);
+	dir = open_dir(name, &error);
+	kfree(name);
+	if(dir == NULL) return(-error);
+	next = file->f_pos;
+	while((name = read_dir(dir, &next, &ino, &len)) != NULL){
+		error = (*filldir)(ent, name, len, file->f_pos,
+				   ino, DT_UNKNOWN);
+		if(error) break;
+		file->f_pos = next;
+	}
+	close_dir(dir);
+	return(0);
+}
+
+int hostfs_file_open(struct inode *ino, struct file *file)
+{
+	char *name;
+	int mode = 0, r = 0, w = 0, fd;
+
+	mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
+	if((mode & HOSTFS_I(ino)->mode) == mode)
+		return(0);
+
+	/* The file may already have been opened, but with the wrong access,
+	 * so this resets things and reopens the file with the new access.
+	 */
+	if(HOSTFS_I(ino)->fd != -1){
+		close_file(&HOSTFS_I(ino)->fd);
+		HOSTFS_I(ino)->fd = -1;
+	}
+
+	HOSTFS_I(ino)->mode |= mode;
+	if(HOSTFS_I(ino)->mode & FMODE_READ)
+		r = 1;
+	if(HOSTFS_I(ino)->mode & FMODE_WRITE)
+		w = 1;
+	if(w)
+		r = 1;
+
+	name = dentry_name(file->f_dentry, 0);
+	if(name == NULL)
+		return(-ENOMEM);
+
+	fd = open_file(name, r, w, append);
+	kfree(name);
+	if(fd < 0) return(fd);
+	FILE_HOSTFS_I(file)->fd = fd;
+
+	return(0);
+}
+
+int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	return(0);
+}
+
+static struct file_operations hostfs_file_fops = {
+	.llseek		= generic_file_llseek,
+	.read		= generic_file_read,
+	.write		= generic_file_write,
+	.mmap		= generic_file_mmap,
+	.open		= hostfs_file_open,
+	.release	= NULL,
+	.fsync		= hostfs_fsync,
+};
+
+static struct file_operations hostfs_dir_fops = {
+	.readdir	= hostfs_readdir,
+	.read		= generic_read_dir,
+};
+
+int hostfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = mapping->host;
+	char *buffer;
+	unsigned long long base;
+	int count = PAGE_CACHE_SIZE;
+	int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	int err;
+
+	if (page->index >= end_index)
+		count = inode->i_size & (PAGE_CACHE_SIZE-1);
+
+	buffer = kmap(page);
+	base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
+
+	err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
+	if(err != count){
+		ClearPageUptodate(page);
+		goto out;
+	}
+
+	if (base > inode->i_size)
+		inode->i_size = base;
+
+	if (PageError(page))
+		ClearPageError(page);
+	err = 0;
+
+ out:
+	kunmap(page);
+
+	unlock_page(page);
+	return err;
+}
+
+int hostfs_readpage(struct file *file, struct page *page)
+{
+	char *buffer;
+	long long start;
+	int err = 0;
+
+	start = (long long) page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
+			PAGE_CACHE_SIZE);
+	if(err < 0) goto out;
+
+	memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
+
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	if (PageError(page)) ClearPageError(page);
+	err = 0;
+ out:
+	kunmap(page);
+	unlock_page(page);
+	return(err);
+}
+
+int hostfs_prepare_write(struct file *file, struct page *page,
+			 unsigned int from, unsigned int to)
+{
+	char *buffer;
+	long long start, tmp;
+	int err;
+
+	start = (long long) page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	if(from != 0){
+		tmp = start;
+		err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer,
+				from);
+		if(err < 0) goto out;
+	}
+	if(to != PAGE_CACHE_SIZE){
+		start += to;
+		err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to,
+				PAGE_CACHE_SIZE - to);
+		if(err < 0) goto out;
+	}
+	err = 0;
+ out:
+	kunmap(page);
+	return(err);
+}
+
+int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
+		 unsigned to)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = mapping->host;
+	char *buffer;
+	long long start;
+	int err = 0;
+
+	start = (long long) (page->index << PAGE_CACHE_SHIFT) + from;
+	buffer = kmap(page);
+	err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
+			 to - from);
+	if(err > 0) err = 0;
+	if(!err && (start > inode->i_size))
+		inode->i_size = start;
+
+	kunmap(page);
+	return(err);
+}
+
+static struct address_space_operations hostfs_aops = {
+	.writepage 	= hostfs_writepage,
+	.readpage	= hostfs_readpage,
+/* 	.set_page_dirty = __set_page_dirty_nobuffers, */
+	.prepare_write	= hostfs_prepare_write,
+	.commit_write	= hostfs_commit_write
+};
+
+static int init_inode(struct inode *inode, struct dentry *dentry)
+{
+	char *name;
+	int type, err = -ENOMEM, rdev;
+
+	if(dentry){
+		name = dentry_name(dentry, 0);
+		if(name == NULL)
+			goto out;
+		type = file_type(name, &rdev);
+		kfree(name);
+	}
+	else type = OS_TYPE_DIR;
+
+	err = 0;
+	if(type == OS_TYPE_SYMLINK)
+		inode->i_op = &page_symlink_inode_operations;
+	else if(type == OS_TYPE_DIR)
+		inode->i_op = &hostfs_dir_iops;
+	else inode->i_op = &hostfs_iops;
+
+	if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
+	else inode->i_fop = &hostfs_file_fops;
+
+	if(type == OS_TYPE_SYMLINK)
+		inode->i_mapping->a_ops = &hostfs_link_aops;
+	else inode->i_mapping->a_ops = &hostfs_aops;
+
+	switch (type) {
+	case OS_TYPE_CHARDEV:
+		init_special_inode(inode, S_IFCHR, rdev);
+		break;
+	case OS_TYPE_BLOCKDEV:
+		init_special_inode(inode, S_IFBLK, rdev);
+		break;
+	case OS_TYPE_FIFO:
+		init_special_inode(inode, S_IFIFO, 0);
+		break;
+	case OS_TYPE_SOCK:
+		init_special_inode(inode, S_IFSOCK, 0);
+		break;
+	}
+ out:
+	return(err);
+}
+
+int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
+                 struct nameidata *nd)
+{
+	struct inode *inode;
+	char *name;
+	int error, fd;
+
+	error = -ENOMEM;
+	inode = iget(dir->i_sb, 0);
+	if(inode == NULL) goto out;
+
+	error = init_inode(inode, dentry);
+	if(error)
+		goto out_put;
+
+	error = -ENOMEM;
+	name = dentry_name(dentry, 0);
+	if(name == NULL)
+		goto out_put;
+
+	fd = file_create(name,
+			 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
+			 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
+			 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
+	if(fd < 0)
+		error = fd;
+	else error = read_name(inode, name);
+
+	kfree(name);
+	if(error)
+		goto out_put;
+
+	HOSTFS_I(inode)->fd = fd;
+	HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
+	d_instantiate(dentry, inode);
+	return(0);
+
+ out_put:
+	iput(inode);
+ out:
+	return(error);
+}
+
+struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
+                            struct nameidata *nd)
+{
+	struct inode *inode;
+	char *name;
+	int err;
+
+	err = -ENOMEM;
+	inode = iget(ino->i_sb, 0);
+	if(inode == NULL)
+		goto out;
+
+	err = init_inode(inode, dentry);
+	if(err)
+		goto out_put;
+
+	err = -ENOMEM;
+	name = dentry_name(dentry, 0);
+	if(name == NULL)
+		goto out_put;
+
+	err = read_name(inode, name);
+	kfree(name);
+	if(err == -ENOENT){
+		iput(inode);
+		inode = NULL;
+	}
+	else if(err)
+		goto out_put;
+
+	d_add(dentry, inode);
+	dentry->d_op = &hostfs_dentry_ops;
+	return(NULL);
+
+ out_put:
+	iput(inode);
+ out:
+	return(ERR_PTR(err));
+}
+
+static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
+{
+        char *file;
+	int len;
+
+	file = inode_name(ino, dentry->d_name.len + 1);
+	if(file == NULL) return(NULL);
+        strcat(file, "/");
+	len = strlen(file);
+        strncat(file, dentry->d_name.name, dentry->d_name.len);
+	file[len + dentry->d_name.len] = '\0';
+        return(file);
+}
+
+int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
+{
+        char *from_name, *to_name;
+        int err;
+
+        if((from_name = inode_dentry_name(ino, from)) == NULL)
+                return(-ENOMEM);
+        to_name = dentry_name(to, 0);
+	if(to_name == NULL){
+		kfree(from_name);
+		return(-ENOMEM);
+	}
+        err = link_file(to_name, from_name);
+        kfree(from_name);
+        kfree(to_name);
+        return(err);
+}
+
+int hostfs_unlink(struct inode *ino, struct dentry *dentry)
+{
+	char *file;
+	int err;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	if(append)
+		return(-EPERM);
+
+	err = unlink_file(file);
+	kfree(file);
+	return(err);
+}
+
+int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
+{
+	char *file;
+	int err;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	err = make_symlink(file, to);
+	kfree(file);
+	return(err);
+}
+
+int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
+{
+	char *file;
+	int err;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	err = do_mkdir(file, mode);
+	kfree(file);
+	return(err);
+}
+
+int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
+{
+	char *file;
+	int err;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	err = do_rmdir(file);
+	kfree(file);
+	return(err);
+}
+
+int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+	struct inode *inode;
+	char *name;
+	int err = -ENOMEM;
+
+	inode = iget(dir->i_sb, 0);
+	if(inode == NULL)
+		goto out;
+
+	err = init_inode(inode, dentry);
+	if(err)
+		goto out_put;
+
+	err = -ENOMEM;
+	name = dentry_name(dentry, 0);
+	if(name == NULL)
+		goto out_put;
+
+	init_special_inode(inode, mode, dev);
+	err = do_mknod(name, mode, dev);
+	if(err)
+		goto out_free;
+
+	err = read_name(inode, name);
+	kfree(name);
+	if(err)
+		goto out_put;
+
+	d_instantiate(dentry, inode);
+	return(0);
+
+ out_free:
+	kfree(name);
+ out_put:
+	iput(inode);
+ out:
+	return(err);
+}
+
+int hostfs_rename(struct inode *from_ino, struct dentry *from,
+		  struct inode *to_ino, struct dentry *to)
+{
+	char *from_name, *to_name;
+	int err;
+
+	if((from_name = inode_dentry_name(from_ino, from)) == NULL)
+		return(-ENOMEM);
+	if((to_name = inode_dentry_name(to_ino, to)) == NULL){
+		kfree(from_name);
+		return(-ENOMEM);
+	}
+	err = rename_file(from_name, to_name);
+	kfree(from_name);
+	kfree(to_name);
+	return(err);
+}
+
+void hostfs_truncate(struct inode *ino)
+{
+	not_implemented();
+}
+
+int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
+{
+	char *name;
+	int r = 0, w = 0, x = 0, err;
+
+	if(desired & MAY_READ) r = 1;
+	if(desired & MAY_WRITE) w = 1;
+	if(desired & MAY_EXEC) x = 1;
+	name = inode_name(ino, 0);
+	if(name == NULL) return(-ENOMEM);
+	err = access_file(name, r, w, x);
+	kfree(name);
+	if(!err) err = vfs_permission(ino, desired);
+	return(err);
+}
+
+int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct hostfs_iattr attrs;
+	char *name;
+	int err;
+
+	if(append)
+		attr->ia_valid &= ~ATTR_SIZE;
+
+	attrs.ia_valid = 0;
+	if(attr->ia_valid & ATTR_MODE){
+		attrs.ia_valid |= HOSTFS_ATTR_MODE;
+		attrs.ia_mode = attr->ia_mode;
+	}
+	if(attr->ia_valid & ATTR_UID){
+		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
+		   (attr->ia_uid == 0))
+			attr->ia_uid = getuid();
+		attrs.ia_valid |= HOSTFS_ATTR_UID;
+		attrs.ia_uid = attr->ia_uid;
+	}
+	if(attr->ia_valid & ATTR_GID){
+		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
+		   (attr->ia_gid == 0))
+			attr->ia_gid = getuid();
+		attrs.ia_valid |= HOSTFS_ATTR_GID;
+		attrs.ia_gid = attr->ia_gid;
+	}
+	if(attr->ia_valid & ATTR_SIZE){
+		attrs.ia_valid |= HOSTFS_ATTR_SIZE;
+		attrs.ia_size = attr->ia_size;
+	}
+	if(attr->ia_valid & ATTR_ATIME){
+		attrs.ia_valid |= HOSTFS_ATTR_ATIME;
+		attrs.ia_atime = attr->ia_atime;
+	}
+	if(attr->ia_valid & ATTR_MTIME){
+		attrs.ia_valid |= HOSTFS_ATTR_MTIME;
+		attrs.ia_mtime = attr->ia_mtime;
+	}
+	if(attr->ia_valid & ATTR_CTIME){
+		attrs.ia_valid |= HOSTFS_ATTR_CTIME;
+		attrs.ia_ctime = attr->ia_ctime;
+	}
+	if(attr->ia_valid & ATTR_ATIME_SET){
+		attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
+	}
+	if(attr->ia_valid & ATTR_MTIME_SET){
+		attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
+	}
+	name = dentry_name(dentry, 0);
+	if(name == NULL) return(-ENOMEM);
+	err = set_attr(name, &attrs);
+	kfree(name);
+	if(err)
+		return(err);
+
+	return(inode_setattr(dentry->d_inode, attr));
+}
+
+int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+	   struct kstat *stat)
+{
+	generic_fillattr(dentry->d_inode, stat);
+	return(0);
+}
+
+static struct inode_operations hostfs_iops = {
+	.create		= hostfs_create,
+	.link		= hostfs_link,
+	.unlink		= hostfs_unlink,
+	.symlink	= hostfs_symlink,
+	.mkdir		= hostfs_mkdir,
+	.rmdir		= hostfs_rmdir,
+	.mknod		= hostfs_mknod,
+	.rename		= hostfs_rename,
+	.truncate	= hostfs_truncate,
+	.permission	= hostfs_permission,
+	.setattr	= hostfs_setattr,
+	.getattr	= hostfs_getattr,
+};
+
+static struct inode_operations hostfs_dir_iops = {
+	.create		= hostfs_create,
+	.lookup		= hostfs_lookup,
+	.link		= hostfs_link,
+	.unlink		= hostfs_unlink,
+	.symlink	= hostfs_symlink,
+	.mkdir		= hostfs_mkdir,
+	.rmdir		= hostfs_rmdir,
+	.mknod		= hostfs_mknod,
+	.rename		= hostfs_rename,
+	.truncate	= hostfs_truncate,
+	.permission	= hostfs_permission,
+	.setattr	= hostfs_setattr,
+	.getattr	= hostfs_getattr,
+};
+
+int hostfs_link_readpage(struct file *file, struct page *page)
+{
+	char *buffer, *name;
+	long long start;
+	int err;
+
+	start = page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	name = inode_name(page->mapping->host, 0);
+	if(name == NULL) return(-ENOMEM);
+	err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
+	kfree(name);
+	if(err == PAGE_CACHE_SIZE)
+		err = -E2BIG;
+	else if(err > 0){
+		flush_dcache_page(page);
+		SetPageUptodate(page);
+		if (PageError(page)) ClearPageError(page);
+		err = 0;
+	}
+	kunmap(page);
+	unlock_page(page);
+	return(err);
+}
+
+static struct address_space_operations hostfs_link_aops = {
+	.readpage	= hostfs_link_readpage,
+};
+
+static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
+{
+	struct inode *root_inode;
+	char *name, *data = d;
+	int err;
+
+	sb->s_blocksize = 1024;
+	sb->s_blocksize_bits = 10;
+	sb->s_magic = HOSTFS_SUPER_MAGIC;
+	sb->s_op = &hostfs_sbops;
+
+	if((data == NULL) || (*data == '\0'))
+		data = root_ino;
+
+	err = -ENOMEM;
+	name = kmalloc(strlen(data) + 1, GFP_KERNEL);
+	if(name == NULL)
+		goto out;
+
+	strcpy(name, data);
+
+	root_inode = iget(sb, 0);
+	if(root_inode == NULL)
+		goto out_free;
+
+	err = init_inode(root_inode, NULL);
+	if(err)
+		goto out_put;
+
+	HOSTFS_I(root_inode)->host_filename = name;
+
+	err = -ENOMEM;
+	sb->s_root = d_alloc_root(root_inode);
+	if(sb->s_root == NULL)
+		goto out_put;
+
+	err = read_inode(root_inode);
+	if(err)
+		goto out_put;
+
+	return(0);
+
+ out_put:
+	iput(root_inode);
+ out_free:
+	kfree(name);
+ out:
+	return(err);
+}
+
+static struct super_block *hostfs_read_sb(struct file_system_type *type,
+					     int flags, const char *dev_name,
+					     void *data)
+{
+	return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common));
+}
+
+static struct file_system_type hostfs_type = {
+	.owner 		= THIS_MODULE,
+	.name 		= "hostfs",
+	.get_sb 	= hostfs_read_sb,
+	.kill_sb	= kill_anon_super,
+	.fs_flags 	= 0,
+};
+
+static int __init init_hostfs(void)
+{
+	return(register_filesystem(&hostfs_type));
+}
+
+static void __exit exit_hostfs(void)
+{
+	unregister_filesystem(&hostfs_type);
+}
+
+module_init(init_hostfs)
+module_exit(exit_hostfs)
+MODULE_LICENSE("GPL");
+
+/*
+ * 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 -puN /dev/null fs/hostfs/hostfs_user.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/fs/hostfs/hostfs_user.c	2004-08-15 20:46:03.317029280 -0700
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <utime.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/vfs.h>
+#include "hostfs.h"
+#include "kern_util.h"
+#include "user.h"
+
+int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
+	      int *nlink_out, int *uid_out, int *gid_out,
+	      unsigned long long *size_out, struct timespec *atime_out,
+	      struct timespec *mtime_out, struct timespec *ctime_out,
+	      int *blksize_out, unsigned long long *blocks_out)
+{
+	struct stat64 buf;
+
+	if(lstat64(path, &buf) < 0)
+		return(-errno);
+
+	/* See the Makefile for why STAT64_INO_FIELD is passed in
+	 * by the build
+	 */
+	if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD;
+	if(mode_out != NULL) *mode_out = buf.st_mode;
+	if(nlink_out != NULL) *nlink_out = buf.st_nlink;
+	if(uid_out != NULL) *uid_out = buf.st_uid;
+	if(gid_out != NULL) *gid_out = buf.st_gid;
+	if(size_out != NULL) *size_out = buf.st_size;
+	if(atime_out != NULL) {
+		atime_out->tv_sec = buf.st_atime;
+		atime_out->tv_nsec = 0;
+	}
+	if(mtime_out != NULL) {
+		mtime_out->tv_sec = buf.st_mtime;
+		mtime_out->tv_nsec = 0;
+	}
+	if(ctime_out != NULL) {
+		ctime_out->tv_sec = buf.st_ctime;
+		ctime_out->tv_nsec = 0;
+	}
+	if(blksize_out != NULL) *blksize_out = buf.st_blksize;
+	if(blocks_out != NULL) *blocks_out = buf.st_blocks;
+	return(0);
+}
+
+int file_type(const char *path, int *rdev)
+{
+ 	struct stat64 buf;
+
+	if(lstat64(path, &buf) < 0)
+		return(-errno);
+	if(rdev != NULL)
+		*rdev = buf.st_rdev;
+
+	if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
+	else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
+	else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
+	else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
+	else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO);
+	else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK);
+	else return(OS_TYPE_FILE);
+}
+
+int access_file(char *path, int r, int w, int x)
+{
+	int mode = 0;
+
+	if(r) mode = R_OK;
+	if(w) mode |= W_OK;
+	if(x) mode |= X_OK;
+	if(access(path, mode) != 0) return(-errno);
+	else return(0);
+}
+
+int open_file(char *path, int r, int w, int append)
+{
+	int mode = 0, fd;
+
+	if(r && !w)
+		mode = O_RDONLY;
+	else if(!r && w)
+		mode = O_WRONLY;
+	else if(r && w)
+		mode = O_RDWR;
+	else panic("Impossible mode in open_file");
+
+	if(append)
+		mode |= O_APPEND;
+	fd = open64(path, mode);
+	if(fd < 0) return(-errno);
+	else return(fd);
+}
+
+void *open_dir(char *path, int *err_out)
+{
+	DIR *dir;
+
+	dir = opendir(path);
+	*err_out = errno;
+	if(dir == NULL) return(NULL);
+	return(dir);
+}
+
+char *read_dir(void *stream, unsigned long long *pos,
+	       unsigned long long *ino_out, int *len_out)
+{
+	DIR *dir = stream;
+	struct dirent *ent;
+
+	seekdir(dir, *pos);
+	ent = readdir(dir);
+	if(ent == NULL) return(NULL);
+	*len_out = strlen(ent->d_name);
+	*ino_out = ent->d_ino;
+	*pos = telldir(dir);
+	return(ent->d_name);
+}
+
+int read_file(int fd, unsigned long long *offset, char *buf, int len)
+{
+	int n;
+
+	n = pread64(fd, buf, len, *offset);
+	if(n < 0) return(-errno);
+	*offset += n;
+	return(n);
+}
+
+int write_file(int fd, unsigned long long *offset, const char *buf, int len)
+{
+	int n;
+
+	n = pwrite64(fd, buf, len, *offset);
+	if(n < 0) return(-errno);
+	*offset += n;
+	return(n);
+}
+
+int lseek_file(int fd, long long offset, int whence)
+{
+	int ret;
+
+	ret = lseek64(fd, offset, whence);
+	if(ret < 0) return(-errno);
+	return(0);
+}
+
+void close_file(void *stream)
+{
+	close(*((int *) stream));
+}
+
+void close_dir(void *stream)
+{
+	closedir(stream);
+}
+
+int file_create(char *name, int ur, int uw, int ux, int gr,
+		int gw, int gx, int or, int ow, int ox)
+{
+	int mode, fd;
+
+	mode = 0;
+	mode |= ur ? S_IRUSR : 0;
+	mode |= uw ? S_IWUSR : 0;
+	mode |= ux ? S_IXUSR : 0;
+	mode |= gr ? S_IRGRP : 0;
+	mode |= gw ? S_IWGRP : 0;
+	mode |= gx ? S_IXGRP : 0;
+	mode |= or ? S_IROTH : 0;
+	mode |= ow ? S_IWOTH : 0;
+	mode |= ox ? S_IXOTH : 0;
+	fd = open64(name, O_CREAT | O_RDWR, mode);
+	if(fd < 0)
+		return(-errno);
+	return(fd);
+}
+
+int set_attr(const char *file, struct hostfs_iattr *attrs)
+{
+	struct utimbuf buf;
+	int err, ma;
+
+	if(attrs->ia_valid & HOSTFS_ATTR_MODE){
+		if(chmod(file, attrs->ia_mode) != 0) return(-errno);
+	}
+	if(attrs->ia_valid & HOSTFS_ATTR_UID){
+		if(chown(file, attrs->ia_uid, -1)) return(-errno);
+	}
+	if(attrs->ia_valid & HOSTFS_ATTR_GID){
+		if(chown(file, -1, attrs->ia_gid)) return(-errno);
+	}
+	if(attrs->ia_valid & HOSTFS_ATTR_SIZE){
+		if(truncate(file, attrs->ia_size)) return(-errno);
+	}
+	ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET;
+	if((attrs->ia_valid & ma) == ma){
+		buf.actime = attrs->ia_atime.tv_sec;
+		buf.modtime = attrs->ia_mtime.tv_sec;
+		if(utime(file, &buf) != 0) return(-errno);
+	}
+	else {
+		struct timespec ts;
+
+		if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){
+			err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
+					NULL, NULL, &ts, NULL, NULL, NULL);
+			if(err != 0)
+				return(err);
+			buf.actime = attrs->ia_atime.tv_sec;
+			buf.modtime = ts.tv_sec;
+			if(utime(file, &buf) != 0)
+				return(-errno);
+		}
+		if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){
+			err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
+					NULL, &ts, NULL, NULL, NULL, NULL);
+			if(err != 0)
+				return(err);
+			buf.actime = ts.tv_sec;
+			buf.modtime = attrs->ia_mtime.tv_sec;
+			if(utime(file, &buf) != 0)
+				return(-errno);
+		}
+	}
+	if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ;
+	if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){
+		err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
+				&attrs->ia_atime, &attrs->ia_mtime, NULL,
+				NULL, NULL);
+		if(err != 0) return(err);
+	}
+	return(0);
+}
+
+int make_symlink(const char *from, const char *to)
+{
+	int err;
+
+	err = symlink(to, from);
+	if(err) return(-errno);
+	return(0);
+}
+
+int unlink_file(const char *file)
+{
+	int err;
+
+	err = unlink(file);
+	if(err) return(-errno);
+	return(0);
+}
+
+int do_mkdir(const char *file, int mode)
+{
+	int err;
+
+	err = mkdir(file, mode);
+	if(err) return(-errno);
+	return(0);
+}
+
+int do_rmdir(const char *file)
+{
+	int err;
+
+	err = rmdir(file);
+	if(err) return(-errno);
+	return(0);
+}
+
+int do_mknod(const char *file, int mode, int dev)
+{
+	int err;
+
+	err = mknod(file, mode, dev);
+	if(err) return(-errno);
+	return(0);
+}
+
+int link_file(const char *to, const char *from)
+{
+	int err;
+
+	err = link(to, from);
+	if(err) return(-errno);
+	return(0);
+}
+
+int do_readlink(char *file, char *buf, int size)
+{
+	int n;
+
+	n = readlink(file, buf, size);
+	if(n < 0)
+		return(-errno);
+	if(n < size)
+		buf[n] = '\0';
+	return(n);
+}
+
+int rename_file(char *from, char *to)
+{
+	int err;
+
+	err = rename(from, to);
+	if(err < 0) return(-errno);
+	return(0);
+}
+
+int do_statfs(char *root, long *bsize_out, long long *blocks_out,
+	      long long *bfree_out, long long *bavail_out,
+	      long long *files_out, long long *ffree_out,
+	      void *fsid_out, int fsid_size, long *namelen_out,
+	      long *spare_out)
+{
+	struct statfs64 buf;
+	int err;
+
+	err = statfs64(root, &buf);
+	if(err < 0) return(-errno);
+	*bsize_out = buf.f_bsize;
+	*blocks_out = buf.f_blocks;
+	*bfree_out = buf.f_bfree;
+	*bavail_out = buf.f_bavail;
+	*files_out = buf.f_files;
+	*ffree_out = buf.f_ffree;
+	memcpy(fsid_out, &buf.f_fsid,
+	       sizeof(buf.f_fsid) > fsid_size ? fsid_size :
+	       sizeof(buf.f_fsid));
+	*namelen_out = buf.f_namelen;
+	spare_out[0] = buf.f_spare[0];
+	spare_out[1] = buf.f_spare[1];
+	spare_out[2] = buf.f_spare[2];
+	spare_out[3] = buf.f_spare[3];
+	spare_out[4] = buf.f_spare[4];
+	spare_out[5] = buf.f_spare[5];
+	return(0);
+}
+
+/*
+ * 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 -puN /dev/null fs/hostfs/Makefile
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/fs/hostfs/Makefile	2004-08-15 20:46:03.318029128 -0700
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino
+# to __st_ino.  It stayed in the same place, so as long as the correct name
+# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa.
+
+STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \
+				echo __)st_ino
+
+hostfs-objs := hostfs_kern.o hostfs_user.o
+
+obj-y =
+obj-$(CONFIG_HOSTFS) += hostfs.o
+
+SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
+
+USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(SINGLE_OBJS))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+USER_CFLAGS += -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD)
+
+$(USER_OBJS) : %.o: %.c
+	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff -puN /dev/null fs/hppfs/hppfs_kern.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/fs/hppfs/hppfs_kern.c	2004-08-15 20:46:03.321028672 -0700
@@ -0,0 +1,811 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/dcache.h>
+#include <linux/statfs.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+#include "os.h"
+
+static int init_inode(struct inode *inode, struct dentry *dentry);
+
+struct hppfs_data {
+	struct list_head list;
+	char contents[PAGE_SIZE - sizeof(struct list_head)];
+};
+
+struct hppfs_private {
+	struct file proc_file;
+	int host_fd;
+	loff_t len;
+	struct hppfs_data *contents;
+};
+
+struct hppfs_inode_info {
+        struct dentry *proc_dentry;
+	struct inode vfs_inode;
+};
+
+static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode)
+{
+	return(list_entry(inode, struct hppfs_inode_info, vfs_inode));
+}
+
+#define HPPFS_SUPER_MAGIC 0xb00000ee
+
+static struct super_operations hppfs_sbops;
+
+static int is_pid(struct dentry *dentry)
+{
+	struct super_block *sb;
+	int i;
+
+	sb = dentry->d_sb;
+	if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root))
+		return(0);
+
+	for(i = 0; i < dentry->d_name.len; i++){
+		if(!isdigit(dentry->d_name.name[i]))
+			return(0);
+	}
+	return(1);
+}
+
+static char *dentry_name(struct dentry *dentry, int extra)
+{
+	struct dentry *parent;
+	char *root, *name;
+	const char *seg_name;
+	int len, seg_len;
+
+	len = 0;
+	parent = dentry;
+	while(parent->d_parent != parent){
+		if(is_pid(parent))
+			len += strlen("pid") + 1;
+		else len += parent->d_name.len + 1;
+		parent = parent->d_parent;
+	}
+
+	root = "proc";
+	len += strlen(root);
+	name = kmalloc(len + extra + 1, GFP_KERNEL);
+	if(name == NULL) return(NULL);
+
+	name[len] = '\0';
+	parent = dentry;
+	while(parent->d_parent != parent){
+		if(is_pid(parent)){
+			seg_name = "pid";
+			seg_len = strlen("pid");
+		}
+		else {
+			seg_name = parent->d_name.name;
+			seg_len = parent->d_name.len;
+		}
+
+		len -= seg_len + 1;
+		name[len] = '/';
+		strncpy(&name[len + 1], seg_name, seg_len);
+		parent = parent->d_parent;
+	}
+	strncpy(name, root, strlen(root));
+	return(name);
+}
+
+struct dentry_operations hppfs_dentry_ops = {
+};
+
+static int file_removed(struct dentry *dentry, const char *file)
+{
+	char *host_file;
+	int extra, fd;
+
+	extra = 0;
+	if(file != NULL) extra += strlen(file) + 1;
+
+	host_file = dentry_name(dentry, extra + strlen("/remove"));
+	if(host_file == NULL){
+		printk("file_removed : allocation failed\n");
+		return(-ENOMEM);
+	}
+
+	if(file != NULL){
+		strcat(host_file, "/");
+		strcat(host_file, file);
+	}
+	strcat(host_file, "/remove");
+
+	fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
+	kfree(host_file);
+	if(fd > 0){
+		os_close_file(fd);
+		return(1);
+	}
+	return(0);
+}
+
+static void hppfs_read_inode(struct inode *ino)
+{
+	struct inode *proc_ino;
+
+	if(HPPFS_I(ino)->proc_dentry == NULL)
+		return;
+
+	proc_ino = HPPFS_I(ino)->proc_dentry->d_inode;
+	ino->i_uid = proc_ino->i_uid;
+	ino->i_gid = proc_ino->i_gid;
+	ino->i_atime = proc_ino->i_atime;
+	ino->i_mtime = proc_ino->i_mtime;
+	ino->i_ctime = proc_ino->i_ctime;
+	ino->i_ino = proc_ino->i_ino;
+	ino->i_mode = proc_ino->i_mode;
+	ino->i_nlink = proc_ino->i_nlink;
+	ino->i_size = proc_ino->i_size;
+	ino->i_blksize = proc_ino->i_blksize;
+	ino->i_blocks = proc_ino->i_blocks;
+}
+
+static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
+                                  struct nameidata *nd)
+{
+	struct dentry *proc_dentry, *new, *parent;
+	struct inode *inode;
+	int err, deleted;
+
+	deleted = file_removed(dentry, NULL);
+	if(deleted < 0)
+		return(ERR_PTR(deleted));
+	else if(deleted)
+		return(ERR_PTR(-ENOENT));
+
+	err = -ENOMEM;
+	parent = HPPFS_I(ino)->proc_dentry;
+	down(&parent->d_inode->i_sem);
+	proc_dentry = d_lookup(parent, &dentry->d_name);
+	if(proc_dentry == NULL){
+		proc_dentry = d_alloc(parent, &dentry->d_name);
+		if(proc_dentry == NULL){
+			up(&parent->d_inode->i_sem);
+			goto out;
+		}
+		new = (*parent->d_inode->i_op->lookup)(parent->d_inode,
+						       proc_dentry, NULL);
+		if(new){
+			dput(proc_dentry);
+			proc_dentry = new;
+		}
+	}
+	up(&parent->d_inode->i_sem);
+
+	if(IS_ERR(proc_dentry))
+		return(proc_dentry);
+
+	inode = iget(ino->i_sb, 0);
+	if(inode == NULL)
+		goto out_dput;
+
+	err = init_inode(inode, proc_dentry);
+	if(err)
+		goto out_put;
+
+	hppfs_read_inode(inode);
+
+ 	d_add(dentry, inode);
+	dentry->d_op = &hppfs_dentry_ops;
+	return(NULL);
+
+ out_put:
+	iput(inode);
+ out_dput:
+	dput(proc_dentry);
+ out:
+	return(ERR_PTR(err));
+}
+
+static struct inode_operations hppfs_file_iops = {
+};
+
+static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
+			 loff_t *ppos, int is_user)
+{
+	ssize_t (*read)(struct file *, char *, size_t, loff_t *);
+	ssize_t n;
+
+	read = file->f_dentry->d_inode->i_fop->read;
+
+	if(!is_user)
+		set_fs(KERNEL_DS);
+
+	n = (*read)(file, buf, count, &file->f_pos);
+
+	if(!is_user)
+		set_fs(USER_DS);
+
+	if(ppos) *ppos = file->f_pos;
+	return(n);
+}
+
+static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
+{
+	ssize_t n;
+	int cur, err;
+	char *new_buf;
+
+	n = -ENOMEM;
+	new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if(new_buf == NULL){
+		printk("hppfs_read_file : kmalloc failed\n");
+		goto out;
+	}
+	n = 0;
+	while(count > 0){
+		cur = min_t(ssize_t, count, PAGE_SIZE);
+		err = os_read_file(fd, new_buf, cur);
+		if(err < 0){
+			printk("hppfs_read : read failed, errno = %d\n",
+			       count);
+			n = err;
+			goto out_free;
+		}
+		else if(err == 0)
+			break;
+
+		if(copy_to_user(buf, new_buf, err)){
+			n = -EFAULT;
+			goto out_free;
+		}
+		n += err;
+		count -= err;
+	}
+ out_free:
+	kfree(new_buf);
+ out:
+	return(n);
+}
+
+static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
+			  loff_t *ppos)
+{
+	struct hppfs_private *hppfs = file->private_data;
+	struct hppfs_data *data;
+	loff_t off;
+	int err;
+
+	if(hppfs->contents != NULL){
+		if(*ppos >= hppfs->len) return(0);
+
+		data = hppfs->contents;
+		off = *ppos;
+		while(off >= sizeof(data->contents)){
+			data = list_entry(data->list.next, struct hppfs_data,
+					  list);
+			off -= sizeof(data->contents);
+		}
+
+		if(off + count > hppfs->len)
+			count = hppfs->len - off;
+		copy_to_user(buf, &data->contents[off], count);
+		*ppos += count;
+	}
+	else if(hppfs->host_fd != -1){
+		err = os_seek_file(hppfs->host_fd, *ppos);
+		if(err){
+			printk("hppfs_read : seek failed, errno = %d\n", err);
+			return(err);
+		}
+		count = hppfs_read_file(hppfs->host_fd, buf, count);
+		if(count > 0)
+			*ppos += count;
+	}
+	else count = read_proc(&hppfs->proc_file, buf, count, ppos, 1);
+
+	return(count);
+}
+
+static ssize_t hppfs_write(struct file *file, const char *buf, size_t len,
+			   loff_t *ppos)
+{
+	struct hppfs_private *data = file->private_data;
+	struct file *proc_file = &data->proc_file;
+	ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
+	int err;
+
+	write = proc_file->f_dentry->d_inode->i_fop->write;
+
+	proc_file->f_pos = file->f_pos;
+	err = (*write)(proc_file, buf, len, &proc_file->f_pos);
+	file->f_pos = proc_file->f_pos;
+
+	return(err);
+}
+
+static int open_host_sock(char *host_file, int *filter_out)
+{
+	char *end;
+	int fd;
+
+	end = &host_file[strlen(host_file)];
+	strcpy(end, "/rw");
+	*filter_out = 1;
+	fd = os_connect_socket(host_file);
+	if(fd > 0)
+		return(fd);
+
+	strcpy(end, "/r");
+	*filter_out = 0;
+	fd = os_connect_socket(host_file);
+	return(fd);
+}
+
+static void free_contents(struct hppfs_data *head)
+{
+	struct hppfs_data *data;
+	struct list_head *ele, *next;
+
+	if(head == NULL) return;
+
+	list_for_each_safe(ele, next, &head->list){
+		data = list_entry(ele, struct hppfs_data, list);
+		kfree(data);
+	}
+	kfree(head);
+}
+
+static struct hppfs_data *hppfs_get_data(int fd, int filter,
+					 struct file *proc_file,
+					 struct file *hppfs_file,
+					 loff_t *size_out)
+{
+	struct hppfs_data *data, *new, *head;
+	int n, err;
+
+	err = -ENOMEM;
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if(data == NULL){
+		printk("hppfs_get_data : head allocation failed\n");
+		goto failed;
+	}
+
+	INIT_LIST_HEAD(&data->list);
+
+	head = data;
+	*size_out = 0;
+
+	if(filter){
+		while((n = read_proc(proc_file, data->contents,
+				     sizeof(data->contents), NULL, 0)) > 0)
+			os_write_file(fd, data->contents, n);
+		err = os_shutdown_socket(fd, 0, 1);
+		if(err){
+			printk("hppfs_get_data : failed to shut down "
+			       "socket\n");
+			goto failed_free;
+		}
+	}
+	while(1){
+		n = os_read_file(fd, data->contents, sizeof(data->contents));
+		if(n < 0){
+			err = n;
+			printk("hppfs_get_data : read failed, errno = %d\n",
+			       err);
+			goto failed_free;
+		}
+		else if(n == 0)
+			break;
+
+		*size_out += n;
+
+		if(n < sizeof(data->contents))
+			break;
+
+		new = kmalloc(sizeof(*data), GFP_KERNEL);
+		if(new == 0){
+			printk("hppfs_get_data : data allocation failed\n");
+			err = -ENOMEM;
+			goto failed_free;
+		}
+
+		INIT_LIST_HEAD(&new->list);
+		list_add(&new->list, &data->list);
+		data = new;
+	}
+	return(head);
+
+ failed_free:
+	free_contents(head);
+ failed:
+	return(ERR_PTR(err));
+}
+
+static struct hppfs_private *hppfs_data(void)
+{
+	struct hppfs_private *data;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if(data == NULL)
+		return(data);
+
+	*data = ((struct hppfs_private ) { .host_fd  		= -1,
+					   .len  		= -1,
+					   .contents 		= NULL } );
+	return(data);
+}
+
+static int file_mode(int fmode)
+{
+	if(fmode == (FMODE_READ | FMODE_WRITE))
+		return(O_RDWR);
+	if(fmode == FMODE_READ)
+		return(O_RDONLY);
+	if(fmode == FMODE_WRITE)
+		return(O_WRONLY);
+	return(0);
+}
+
+static int hppfs_open(struct inode *inode, struct file *file)
+{
+	struct hppfs_private *data;
+	struct dentry *proc_dentry;
+	char *host_file;
+	int err, fd, type, filter;
+
+	err = -ENOMEM;
+	data = hppfs_data();
+	if(data == NULL)
+		goto out;
+
+	host_file = dentry_name(file->f_dentry, strlen("/rw"));
+	if(host_file == NULL)
+		goto out_free2;
+
+	proc_dentry = HPPFS_I(inode)->proc_dentry;
+
+	/* XXX This isn't closed anywhere */
+	err = open_private_file(&data->proc_file, proc_dentry,
+				file_mode(file->f_mode));
+	if(err)
+		goto out_free1;
+
+	type = os_file_type(host_file);
+	if(type == OS_TYPE_FILE){
+		fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
+		if(fd >= 0)
+			data->host_fd = fd;
+		else printk("hppfs_open : failed to open '%s', errno = %d\n",
+			    host_file, -fd);
+
+		data->contents = NULL;
+	}
+	else if(type == OS_TYPE_DIR){
+		fd = open_host_sock(host_file, &filter);
+		if(fd > 0){
+			data->contents = hppfs_get_data(fd, filter,
+							&data->proc_file,
+							file, &data->len);
+			if(!IS_ERR(data->contents))
+				data->host_fd = fd;
+		}
+		else printk("hppfs_open : failed to open a socket in "
+			    "'%s', errno = %d\n", host_file, -fd);
+	}
+	kfree(host_file);
+
+	file->private_data = data;
+	return(0);
+
+ out_free1:
+	kfree(host_file);
+ out_free2:
+	free_contents(data->contents);
+	kfree(data);
+ out:
+	return(err);
+}
+
+static int hppfs_dir_open(struct inode *inode, struct file *file)
+{
+	struct hppfs_private *data;
+	struct dentry *proc_dentry;
+	int err;
+
+	err = -ENOMEM;
+	data = hppfs_data();
+	if(data == NULL)
+		goto out;
+
+	proc_dentry = HPPFS_I(inode)->proc_dentry;
+	err = open_private_file(&data->proc_file, proc_dentry,
+				file_mode(file->f_mode));
+	if(err)
+		goto out_free;
+
+	file->private_data = data;
+	return(0);
+
+ out_free:
+	kfree(data);
+ out:
+	return(err);
+}
+
+static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
+{
+	struct hppfs_private *data = file->private_data;
+	struct file *proc_file = &data->proc_file;
+	loff_t (*llseek)(struct file *, loff_t, int);
+	loff_t ret;
+
+	llseek = proc_file->f_dentry->d_inode->i_fop->llseek;
+	if(llseek != NULL){
+		ret = (*llseek)(proc_file, off, where);
+		if(ret < 0)
+			return(ret);
+	}
+
+	return(default_llseek(file, off, where));
+}
+
+static struct file_operations hppfs_file_fops = {
+	.owner		= NULL,
+	.llseek		= hppfs_llseek,
+	.read		= hppfs_read,
+	.write		= hppfs_write,
+	.open		= hppfs_open,
+};
+
+struct hppfs_dirent {
+	void *vfs_dirent;
+	filldir_t filldir;
+	struct dentry *dentry;
+};
+
+static int hppfs_filldir(void *d, const char *name, int size,
+			 loff_t offset, ino_t inode, unsigned int type)
+{
+	struct hppfs_dirent *dirent = d;
+
+	if(file_removed(dirent->dentry, name))
+		return(0);
+
+	return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset,
+				  inode, type));
+}
+
+static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
+{
+	struct hppfs_private *data = file->private_data;
+	struct file *proc_file = &data->proc_file;
+	int (*readdir)(struct file *, void *, filldir_t);
+	struct hppfs_dirent dirent = ((struct hppfs_dirent)
+		                      { .vfs_dirent  	= ent,
+					.filldir 	= filldir,
+					.dentry  	= file->f_dentry } );
+	int err;
+
+	readdir = proc_file->f_dentry->d_inode->i_fop->readdir;
+
+	proc_file->f_pos = file->f_pos;
+	err = (*readdir)(proc_file, &dirent, hppfs_filldir);
+	file->f_pos = proc_file->f_pos;
+
+	return(err);
+}
+
+static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	return(0);
+}
+
+static struct file_operations hppfs_dir_fops = {
+	.owner		= NULL,
+	.readdir	= hppfs_readdir,
+	.open		= hppfs_dir_open,
+	.fsync		= hppfs_fsync,
+};
+
+static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf)
+{
+	sf->f_blocks = 0;
+	sf->f_bfree = 0;
+	sf->f_bavail = 0;
+	sf->f_files = 0;
+	sf->f_ffree = 0;
+	sf->f_type = HPPFS_SUPER_MAGIC;
+	return(0);
+}
+
+static struct inode *hppfs_alloc_inode(struct super_block *sb)
+{
+	struct hppfs_inode_info *hi;
+
+	hi = kmalloc(sizeof(*hi), GFP_KERNEL);
+	if(hi == NULL)
+		return(NULL);
+
+	*hi = ((struct hppfs_inode_info) { .proc_dentry	= NULL });
+	inode_init_once(&hi->vfs_inode);
+	return(&hi->vfs_inode);
+}
+
+void hppfs_delete_inode(struct inode *ino)
+{
+	clear_inode(ino);
+}
+
+static void hppfs_destroy_inode(struct inode *inode)
+{
+	kfree(HPPFS_I(inode));
+}
+
+static struct super_operations hppfs_sbops = {
+	.alloc_inode	= hppfs_alloc_inode,
+	.destroy_inode	= hppfs_destroy_inode,
+	.read_inode	= hppfs_read_inode,
+	.delete_inode	= hppfs_delete_inode,
+	.statfs		= hppfs_statfs,
+};
+
+static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+	struct file proc_file;
+	struct dentry *proc_dentry;
+	int (*readlink)(struct dentry *, char *, int);
+	int err, n;
+
+	proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
+	err = open_private_file(&proc_file, proc_dentry, O_RDONLY);
+	if(err)
+		return(err);
+
+	readlink = proc_dentry->d_inode->i_op->readlink;
+	n = (*readlink)(proc_dentry, buffer, buflen);
+
+	close_private_file(&proc_file);
+
+	return(n);
+}
+
+static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	struct file proc_file;
+	struct dentry *proc_dentry;
+	int (*follow_link)(struct dentry *, struct nameidata *);
+	int err, n;
+
+	proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
+	err = open_private_file(&proc_file, proc_dentry, O_RDONLY);
+	if(err)
+		return(err);
+
+	follow_link = proc_dentry->d_inode->i_op->follow_link;
+	n = (*follow_link)(proc_dentry, nd);
+
+	close_private_file(&proc_file);
+
+	return(n);
+}
+
+static struct inode_operations hppfs_dir_iops = {
+	.lookup		= hppfs_lookup,
+};
+
+static struct inode_operations hppfs_link_iops = {
+	.readlink	= hppfs_readlink,
+	.follow_link	= hppfs_follow_link,
+};
+
+static int init_inode(struct inode *inode, struct dentry *dentry)
+{
+	if(S_ISDIR(dentry->d_inode->i_mode)){
+		inode->i_op = &hppfs_dir_iops;
+		inode->i_fop = &hppfs_dir_fops;
+	}
+	else if(S_ISLNK(dentry->d_inode->i_mode)){
+		inode->i_op = &hppfs_link_iops;
+		inode->i_fop = &hppfs_file_fops;
+	}
+	else {
+		inode->i_op = &hppfs_file_iops;
+		inode->i_fop = &hppfs_file_fops;
+	}
+
+	HPPFS_I(inode)->proc_dentry = dentry;
+
+	return(0);
+}
+
+static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
+{
+	struct inode *root_inode;
+	struct file_system_type *procfs;
+	struct super_block *proc_sb;
+	int err;
+
+	err = -ENOENT;
+	procfs = get_fs_type("proc");
+	if(procfs == NULL)
+		goto out;
+
+	if(list_empty(&procfs->fs_supers))
+		goto out;
+
+	proc_sb = list_entry(procfs->fs_supers.next, struct super_block,
+			     s_instances);
+
+	sb->s_blocksize = 1024;
+	sb->s_blocksize_bits = 10;
+	sb->s_magic = HPPFS_SUPER_MAGIC;
+	sb->s_op = &hppfs_sbops;
+
+	root_inode = iget(sb, 0);
+	if(root_inode == NULL)
+		goto out;
+
+	err = init_inode(root_inode, proc_sb->s_root);
+	if(err)
+		goto out_put;
+
+	err = -ENOMEM;
+	sb->s_root = d_alloc_root(root_inode);
+	if(sb->s_root == NULL)
+		goto out_put;
+
+	hppfs_read_inode(root_inode);
+
+	return(0);
+
+ out_put:
+	iput(root_inode);
+ out:
+	return(err);
+}
+
+static struct super_block *hppfs_read_super(struct file_system_type *type,
+					     int flags, const char *dev_name,
+					     void *data)
+{
+	return(get_sb_nodev(type, flags, data, hppfs_fill_super));
+}
+
+static struct file_system_type hppfs_type = {
+	.owner 		= THIS_MODULE,
+	.name 		= "hppfs",
+	.get_sb 	= hppfs_read_super,
+	.kill_sb	= kill_anon_super,
+	.fs_flags 	= 0,
+};
+
+static int __init init_hppfs(void)
+{
+	return(register_filesystem(&hppfs_type));
+}
+
+static void __exit exit_hppfs(void)
+{
+	unregister_filesystem(&hppfs_type);
+}
+
+module_init(init_hppfs)
+module_exit(exit_hppfs)
+MODULE_LICENSE("GPL");
+
+/*
+ * 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 -puN /dev/null fs/hppfs/Makefile
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/fs/hppfs/Makefile	2004-08-15 20:46:03.321028672 -0700
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2002, 2003 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+hppfs-objs := hppfs_kern.o
+
+obj-y =
+obj-$(CONFIG_HPPFS) += hppfs.o
+
+clean:
+
+modules:
+
+fastdep:
+
+dep:
+
+archmrproper: clean
diff -puN fs/Makefile~uml-base-patch fs/Makefile
--- 25/fs/Makefile~uml-base-patch	2004-08-15 20:45:08.495363440 -0700
+++ 25-akpm/fs/Makefile	2004-08-15 20:46:03.322028520 -0700
@@ -91,3 +91,5 @@ obj-$(CONFIG_JFS_FS)		+= jfs/
 obj-$(CONFIG_XFS_FS)		+= xfs/
 obj-$(CONFIG_AFS_FS)		+= afs/
 obj-$(CONFIG_BEFS_FS)		+= befs/
+obj-$(CONFIG_HOSTFS)		+= hostfs/
+obj-$(CONFIG_HPPFS)		+= hppfs/
diff -puN include/asm-um/archparam-i386.h~uml-base-patch include/asm-um/archparam-i386.h
--- 25/include/asm-um/archparam-i386.h~uml-base-patch	2004-08-15 20:45:08.497363136 -0700
+++ 25-akpm/include/asm-um/archparam-i386.h	2004-08-15 20:46:03.323028368 -0700
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -56,6 +56,93 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
 	pr_reg[16] = PT_REGS_SS(regs);		\
 } while(0);
 
+#if 0 /* Turn this back on when UML has VSYSCALL working */
+#define VSYSCALL_BASE	(__fix_to_virt(FIX_VSYSCALL))
+#else
+#define VSYSCALL_BASE	0
+#endif
+
+#define VSYSCALL_EHDR	((const struct elfhdr *) VSYSCALL_BASE)
+#define VSYSCALL_ENTRY	((unsigned long) &__kernel_vsyscall)
+extern void *__kernel_vsyscall;
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO		32
+#define AT_SYSINFO_EHDR		33
+
+#define ARCH_DLINFO						\
+do {								\
+		NEW_AUX_ENT(AT_SYSINFO,	VSYSCALL_ENTRY);	\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);	\
+} while (0)
+
+/*
+ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the vsyscall DSO contents.  Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the vsyscall DSO was being used.
+ */
+#if 0
+#define ELF_CORE_EXTRA_PHDRS		(VSYSCALL_EHDR->e_phnum)
+#endif
+
+#undef ELF_CORE_EXTRA_PHDRS
+
+#if 0
+#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
+do {									      \
+	const struct elf_phdr *const vsyscall_phdrs =			      \
+		(const struct elf_phdr *) (VSYSCALL_BASE		      \
+					   + VSYSCALL_EHDR->e_phoff);	      \
+	int i;								      \
+	Elf32_Off ofs = 0;						      \
+	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+		struct elf_phdr phdr = vsyscall_phdrs[i];		      \
+		if (phdr.p_type == PT_LOAD) {				      \
+			ofs = phdr.p_offset = offset;			      \
+			offset += phdr.p_filesz;			      \
+		}							      \
+		else							      \
+			phdr.p_offset += ofs;				      \
+		phdr.p_paddr = 0; /* match other core phdrs */		      \
+		DUMP_WRITE(&phdr, sizeof(phdr));			      \
+	}								      \
+} while (0)
+#define ELF_CORE_WRITE_EXTRA_DATA					      \
+do {									      \
+	const struct elf_phdr *const vsyscall_phdrs =			      \
+		(const struct elf_phdr *) (VSYSCALL_BASE		      \
+					   + VSYSCALL_EHDR->e_phoff);	      \
+	int i;								      \
+	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+		if (vsyscall_phdrs[i].p_type == PT_LOAD)		      \
+			DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,	      \
+				   vsyscall_phdrs[i].p_filesz);		      \
+	}								      \
+} while (0)
+#endif
+
+#undef ELF_CORE_WRITE_EXTRA_PHDRS
+#undef ELF_CORE_WRITE_EXTRA_DATA
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
 /********* Bits for asm-um/delay.h **********/
 
 typedef unsigned long um_udelay_t;
diff -puN include/asm-um/common.lds.S~uml-base-patch include/asm-um/common.lds.S
--- 25/include/asm-um/common.lds.S~uml-base-patch	2004-08-15 20:45:08.498362984 -0700
+++ 25-akpm/include/asm-um/common.lds.S	2004-08-15 20:46:03.323028368 -0700
@@ -1,3 +1,5 @@
+#include <asm-generic/vmlinux.lds.h>
+
   .fini      : { *(.fini)    } =0x9090
   _etext = .;
   PROVIDE (etext = .);
@@ -13,18 +15,6 @@
 
   RODATA
 
-  __start___ksymtab = .;	/* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
-  __gpl_ksymtab : { *(__gpl_ksymtab) }
-  __stop___gpl_ksymtab = .;
-
-  __start___kallsyms = .;       /* All kernel symbols */
-  __kallsyms : { *(__kallsyms) }
-  __stop___kallsyms = .;
-
   .unprotected : { *(.unprotected) }
   . = ALIGN(4096);
   PROVIDE (_unprotected_end = .);
@@ -67,11 +57,17 @@
   }
   __initcall_end = .;
 
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+
   __uml_initcall_start = .;
   .uml.initcall.init : { *(.uml.initcall.init) }
   __uml_initcall_end = .;
   __init_end = .;
 
+  SECURITY_INIT
+
   __exitcall_begin = .;
   .exitcall : { *(.exitcall.exit) }
   __exitcall_end = .;
@@ -80,7 +76,33 @@
   .uml.exitcall : { *(.uml.exitcall.exit) }
   __uml_exitcall_end = .;
 
-  . = ALIGN(4096);
+  . = ALIGN(4);
+  __alt_instructions = .;
+  .altinstructions : { *(.altinstructions) }
+  __alt_instructions_end = .;
+  .altinstr_replacement : { *(.altinstr_replacement) }
+  /* .exit.text is discard at runtime, not link time, to deal with references
+     from .altinstructions and .eh_frame */
+  .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
+
+  __preinit_array_start = .;
+  .preinit_array : { *(.preinit_array) }
+  __preinit_array_end = .;
+  __init_array_start = .;
+  .init_array : { *(.init_array) }
+  __init_array_end = .;
+  __fini_array_start = .;
+  .fini_array : { *(.fini_array) }
+  __fini_array_end = .;
+
+   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+ 	*(.exitcall.exit)
+  }
+
diff -puN /dev/null include/asm-um/cpufeature.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-um/cpufeature.h	2004-08-15 20:46:03.323028368 -0700
@@ -0,0 +1,6 @@
+#ifndef __UM_CPUFEATURE_H
+#define __UM_CPUFEATURE_H
+
+#include "asm/arch/cpufeature.h"
+
+#endif
diff -puN include/asm-um/current.h~uml-base-patch include/asm-um/current.h
--- 25/include/asm-um/current.h~uml-base-patch	2004-08-15 20:45:08.499362832 -0700
+++ 25-akpm/include/asm-um/current.h	2004-08-15 20:46:03.324028216 -0700
@@ -16,8 +16,10 @@ struct thread_info;
 #define CURRENT_THREAD(dummy) (((unsigned long) &dummy) & \
 			        (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER))
 
-#define current ({ int dummy; \
-                   ((struct thread_info *) CURRENT_THREAD(dummy))->task; })
+#define current_thread \
+	({ int dummy; ((struct thread_info *) CURRENT_THREAD(dummy)); })
+
+#define current (current_thread->task)
 
 #endif /* __ASSEMBLY__ */
 
diff -puN include/asm-um/dma-mapping.h~uml-base-patch include/asm-um/dma-mapping.h
--- 25/include/asm-um/dma-mapping.h~uml-base-patch	2004-08-15 20:45:08.501362528 -0700
+++ 25-akpm/include/asm-um/dma-mapping.h	2004-08-15 20:46:03.324028216 -0700
@@ -1 +1,119 @@
-#include <asm-generic/dma-mapping.h>
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+	BUG();
+	return(0);
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	BUG();
+	return(0);
+}
+
+static inline void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		   int flag)
+{
+	BUG();
+	return((void *) 0);
+}
+
+static inline void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+		  dma_addr_t dma_handle)
+{
+	BUG();
+}
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+	     unsigned long offset, size_t size,
+	     enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+	    enum dma_data_direction direction)
+{
+	BUG();
+}
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d) (1)
+
+static inline int
+dma_get_cache_alignment(void)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
+		      unsigned long offset, size_t size,
+		      enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+}
+
+#endif
diff -puN include/asm-um/elf.h~uml-base-patch include/asm-um/elf.h
--- 25/include/asm-um/elf.h~uml-base-patch	2004-08-15 20:45:08.502362376 -0700
+++ 25-akpm/include/asm-um/elf.h	2004-08-15 20:46:03.325028064 -0700
@@ -15,4 +15,17 @@
 
 #define USE_ELF_CORE_DUMP
 
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
 #endif
diff -puN include/asm-um/fixmap.h~uml-base-patch include/asm-um/fixmap.h
--- 25/include/asm-um/fixmap.h~uml-base-patch	2004-08-15 20:45:08.503362224 -0700
+++ 25-akpm/include/asm-um/fixmap.h	2004-08-15 20:46:03.325028064 -0700
@@ -34,6 +34,7 @@ enum fixed_addresses {
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
+	FIX_VSYSCALL,
 	__end_of_fixed_addresses
 };
 
@@ -63,6 +64,13 @@ extern unsigned long get_kmem_end(void);
 #define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x)      ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
 
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START	(__fix_to_virt(FIX_VSYSCALL))
+#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
+
 extern void __this_fixmap_does_not_exist(void);
 
 /*
diff -puN include/asm-um/irq.h~uml-base-patch include/asm-um/irq.h
--- 25/include/asm-um/irq.h~uml-base-patch	2004-08-15 20:45:08.505361920 -0700
+++ 25-akpm/include/asm-um/irq.h	2004-08-15 20:46:03.326027912 -0700
@@ -1,15 +1,6 @@
 #ifndef __UM_IRQ_H
 #define __UM_IRQ_H
 
-/* The i386 irq.h has a struct task_struct in a prototype without including
- * sched.h.  This forward declaration kills the resulting warning.
- */
-struct task_struct;
-
-#include "asm/ptrace.h"
-
-#undef NR_IRQS
-
 #define TIMER_IRQ		0
 #define UMN_IRQ			1
 #define CONSOLE_IRQ		2
@@ -28,13 +19,4 @@ struct task_struct;
 #define LAST_IRQ XTERM_IRQ
 #define NR_IRQS (LAST_IRQ + 1)
 
-extern int um_request_irq(unsigned int irq, int fd, int type,
-			  void (*handler)(int, void *, struct pt_regs *),
-			  unsigned long irqflags,  const char * devname,
-			  void *dev_id);
-
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif
diff -puN /dev/null include/asm-um/local.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-um/local.h	2004-08-15 20:46:03.326027912 -0700
@@ -0,0 +1,6 @@
+#ifndef __UM_LOCAL_H
+#define __UM_LOCAL_H
+
+#include "asm/arch/local.h"
+
+#endif
diff -puN /dev/null include/asm-um/module-generic.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-um/module-generic.h	2004-08-15 20:46:03.326027912 -0700
@@ -0,0 +1,6 @@
+#ifndef __UM_MODULE_GENERIC_H
+#define __UM_MODULE_GENERIC_H
+
+#include "asm/arch/module.h"
+
+#endif
diff -puN /dev/null include/asm-um/module-i386.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-um/module-i386.h	2004-08-15 20:46:03.327027760 -0700
@@ -0,0 +1,13 @@
+#ifndef __UM_MODULE_I386_H
+#define __UM_MODULE_I386_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#endif
diff -puN include/asm-um/page.h~uml-base-patch include/asm-um/page.h
--- 25/include/asm-um/page.h~uml-base-patch	2004-08-15 20:45:08.507361616 -0700
+++ 25-akpm/include/asm-um/page.h	2004-08-15 20:46:03.327027760 -0700
@@ -1,10 +1,14 @@
+/*
+ *  Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
 #ifndef __UM_PAGE_H
 #define __UM_PAGE_H
 
 struct page;
 
 #include "asm/arch/page.h"
-#include "asm/bug.h"
 
 #undef __pa
 #undef __va
@@ -24,26 +28,26 @@ extern unsigned long uml_physmem;
 
 #define __va_space (8*1024*1024)
 
-extern unsigned long region_pa(void *virt);
-extern void *region_va(unsigned long phys);
-
-#define __pa(virt) region_pa((void *) (virt))
-#define __va(phys) region_va((unsigned long) (phys))
+extern unsigned long to_phys(void *virt);
+extern void *to_virt(unsigned long phys);
 
-extern unsigned long page_to_pfn(struct page *page);
-extern struct page *pfn_to_page(unsigned long pfn);
+#define __pa(virt) to_phys((void *) virt)
+#define __va(phys) to_virt((unsigned long) phys)
 
-extern struct page *phys_to_page(unsigned long phys);
+#define page_to_pfn(page) ((page) - mem_map)
+#define pfn_to_page(pfn) (mem_map + (pfn))
 
-#define virt_to_page(v) (phys_to_page(__pa(v)))
+#define phys_to_pfn(p) ((p) >> PAGE_SHIFT)
+#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
 
-extern struct page *page_mem_map(struct page *page);
-
-#define pfn_valid(pfn) (page_mem_map(pfn_to_page(pfn)) != NULL)
-#define virt_addr_valid(v) pfn_valid(__pa(v) >> PAGE_SHIFT)
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
 
 extern struct page *arch_validate(struct page *page, int mask, int order);
 #define HAVE_ARCH_VALIDATE
 #define devmem_is_allowed(x) 1
 
+extern void arch_free_page(struct page *page, int order);
+#define HAVE_ARCH_FREE_PAGE
+
 #endif
diff -puN include/asm-um/pgtable.h~uml-base-patch include/asm-um/pgtable.h
--- 25/include/asm-um/pgtable.h~uml-base-patch	2004-08-15 20:45:08.509361312 -0700
+++ 25-akpm/include/asm-um/pgtable.h	2004-08-15 20:46:03.329027456 -0700
@@ -12,8 +12,6 @@
 #include "asm/page.h"
 #include "asm/fixmap.h"
 
-extern pgd_t swapper_pg_dir[1024];
-
 extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt,
 			     pte_t *pte_out);
 
@@ -49,6 +47,8 @@ extern unsigned long *empty_zero_page;
 #define pgd_ERROR(e) \
         printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
 /*
  * pgd entries used up by user/kernel:
  */
@@ -65,10 +65,10 @@ extern unsigned long *empty_zero_page;
  * area for the same reason. ;)
  */
 
-extern unsigned long high_physmem;
+extern unsigned long end_iomem;
 
 #define VMALLOC_OFFSET	(__va_space)
-#define VMALLOC_START	(((unsigned long) high_physmem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_START	((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 
 #ifdef CONFIG_HIGHMEM
 # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
@@ -78,12 +78,13 @@ extern unsigned long high_physmem;
 
 #define _PAGE_PRESENT	0x001
 #define _PAGE_NEWPAGE	0x002
-#define _PAGE_PROTNONE	0x004	/* If not present */
-#define _PAGE_RW	0x008
-#define _PAGE_USER	0x010
-#define _PAGE_ACCESSED	0x020
-#define _PAGE_DIRTY	0x040
-#define _PAGE_NEWPROT   0x080
+#define _PAGE_NEWPROT   0x004
+#define _PAGE_FILE	0x008   /* set:pagecache unset:swap */
+#define _PAGE_PROTNONE	0x010	/* If not present */
+#define _PAGE_RW	0x020
+#define _PAGE_USER	0x040
+#define _PAGE_ACCESSED	0x080
+#define _PAGE_DIRTY	0x100
 
 #define REGION_MASK	0xf0000000
 #define REGION_SHIFT	28
@@ -143,7 +144,8 @@ extern pte_t * __bad_pagetable(void);
 
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
@@ -164,9 +166,6 @@ extern pte_t * __bad_pagetable(void);
 
 #define pte_clear(xp)	do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
 
-#define phys_region_index(x) (((x) & REGION_MASK) >> REGION_SHIFT)
-#define pte_region_index(x) phys_region_index(pte_val(x))
-
 #define pmd_none(x)	(!(pmd_val(x) & ~_PAGE_NEWPAGE))
 #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
@@ -188,19 +187,25 @@ static inline void pgd_clear(pgd_t * pgd
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
 
-extern struct page *pte_mem_map(pte_t pte);
-extern struct page *phys_mem_map(unsigned long phys);
-extern unsigned long phys_to_pfn(unsigned long p);
-extern unsigned long pfn_to_phys(unsigned long pfn);
-
-#define pte_page(x) pfn_to_page(pte_pfn(x))
-#define pte_address(x) (__va(pte_val(x) & PAGE_MASK))
-#define mk_phys(a, r) ((a) + (r << REGION_SHIFT))
-#define phys_addr(p) ((p) & ~REGION_MASK)
-#define phys_page(p) (phys_mem_map(p) + ((phys_addr(p)) >> PAGE_SHIFT))
+#define pte_page(pte) phys_to_page(pte_val(pte))
+#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
+
 #define pte_pfn(x) phys_to_pfn(pte_val(x))
 #define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
-#define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
+
+extern struct page *phys_to_page(const unsigned long phys);
+extern struct page *__virt_to_page(const unsigned long virt);
+#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
+
+/*
+ * Bits 0 through 3 are taken
+ */
+#define PTE_FILE_MAX_BITS	28
+
+#define pte_to_pgoff(pte) ((pte).pte_low >> 4)
+
+#define pgoff_to_pte(off) \
+	((pte_t) { ((off) << 4) + _PAGE_FILE })
 
 static inline pte_t pte_mknewprot(pte_t pte)
 {
@@ -235,6 +240,12 @@ static inline void set_pte(pte_t *pteptr
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
+static inline int pte_user(pte_t pte)
+{
+	return((pte_val(pte) & _PAGE_USER) &&
+	       !(pte_val(pte) & _PAGE_PROTNONE));
+}
+
 static inline int pte_read(pte_t pte)
 { 
 	return((pte_val(pte) & _PAGE_USER) && 
@@ -252,6 +263,14 @@ static inline int pte_write(pte_t pte)
 	       !(pte_val(pte) & _PAGE_PROTNONE));
 }
 
+/*
+ * The following only works if pte_present() is not true.
+ */
+static inline int pte_file(pte_t pte)
+{
+	return (pte).pte_low & _PAGE_FILE;
+}
+
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
@@ -334,14 +353,7 @@ extern unsigned long page_to_phys(struct
  * and a page entry and page directory to the page they refer to.
  */
 
-#define mk_pte(page, pgprot) \
-({					\
-	pte_t __pte;                    \
-                                        \
-	pte_val(__pte) = page_to_phys(page) + pgprot_val(pgprot);\
-	if(pte_present(__pte)) pte_mknewprot(pte_mknewpage(__pte)); \
-	__pte;                          \
-})
+extern pte_t mk_pte(struct page *page, pgprot_t pgprot);
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
@@ -351,17 +363,27 @@ static inline pte_t pte_modify(pte_t pte
 }
 
 #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
-#define pmd_page(pmd) (phys_mem_map(pmd_val(pmd) & PAGE_MASK) + \
-		       ((phys_addr(pmd_val(pmd)) >> PAGE_SHIFT)))
 
-/* to find an entry in a page-table-directory. */
+/*
+ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+ *
+ * this macro returns the index of the entry in the pgd page which would
+ * control the given virtual address
+ */
 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 
-/* to find an entry in a page-table-directory */
+/*
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
 #define pgd_offset(mm, address) \
 ((mm)->pgd + ((address) >> PGDIR_SHIFT))
 
-/* to find an entry in a kernel page-table-directory */
+
+/*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+ */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 #define pmd_index(address) \
@@ -373,7 +395,12 @@ static inline pmd_t * pmd_offset(pgd_t *
 	return (pmd_t *) dir;
 }
 
-/* Find an entry in the third-level page table.. */ 
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
 #define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
 	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
@@ -387,11 +414,11 @@ static inline pmd_t * pmd_offset(pgd_t *
 #define update_mmu_cache(vma,address,pte) do ; while (0)
 
 /* Encode and de-code a swap entry */
-#define __swp_type(x)			(((x).val >> 3) & 0x7f)
-#define __swp_offset(x)			((x).val >> 10)
+#define __swp_type(x)			(((x).val >> 4) & 0x3f)
+#define __swp_offset(x)			((x).val >> 11)
 
 #define __swp_entry(type, offset) \
-	((swp_entry_t) { ((type) << 3) | ((offset) << 10) })
+	((swp_entry_t) { ((type) << 4) | ((offset) << 11) })
 #define __pte_to_swp_entry(pte) \
 	((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })
diff -puN include/asm-um/processor-generic.h~uml-base-patch include/asm-um/processor-generic.h
--- 25/include/asm-um/processor-generic.h~uml-base-patch	2004-08-15 20:45:08.510361160 -0700
+++ 25-akpm/include/asm-um/processor-generic.h	2004-08-15 20:46:03.329027456 -0700
@@ -11,33 +11,14 @@ struct pt_regs;
 struct task_struct;
 
 #include "linux/config.h"
-#include "linux/signal.h"
 #include "asm/ptrace.h"
-#include "asm/siginfo.h"
 #include "choose-mode.h"
 
 struct mm_struct;
 
 #define current_text_addr() ((void *) 0)
 
-#define cpu_relax()	do ; while (0)
-
-#ifdef CONFIG_MODE_TT
-struct proc_tt_mode {
-	int extern_pid;
-	int tracing;
-	int switch_pipe[2];
-	int singlestep_syscall;
-	int vm_seq;
-};
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-struct proc_skas_mode {
-	void *switch_buf;
-	void *fork_buf;
-};
-#endif
+#define cpu_relax()   barrier()
 
 struct thread_struct {
 	int forking;
@@ -46,6 +27,7 @@ struct thread_struct {
 	struct pt_regs regs;
 	unsigned long cr2;
 	int err;
+	unsigned long trap_no;
 	void *fault_addr;
 	void *fault_catcher;
 	struct task_struct *prev_sched;
@@ -54,10 +36,20 @@ struct thread_struct {
 	struct arch_thread arch;
 	union {
 #ifdef CONFIG_MODE_TT
-		struct proc_tt_mode tt;
+		struct {
+			int extern_pid;
+			int tracing;
+			int switch_pipe[2];
+			int singlestep_syscall;
+			int vm_seq;
+		} tt;
 #endif
 #ifdef CONFIG_MODE_SKAS
-		struct proc_skas_mode skas;
+		struct {
+			void *switch_buf;
+			void *fork_buf;
+			int mm_count;
+		} skas;
 #endif
 	} mode;
 	struct {
@@ -99,14 +91,19 @@ typedef struct {
 } mm_segment_t;
 
 extern struct task_struct *alloc_task_struct(void);
-extern void free_task_struct(struct task_struct *task);
 
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern void dump_thread(struct pt_regs *regs, struct user *u);
+extern void prepare_to_copy(struct task_struct *tsk);
 
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
+static inline void mm_copy_segments(struct mm_struct *from_mm,
+				    struct mm_struct *new_mm)
+{
+}
+
 #define init_stack	(init_thread_union.stack)
 
 /*
diff -puN include/asm-um/processor-i386.h~uml-base-patch include/asm-um/processor-i386.h
--- 25/include/asm-um/processor-i386.h~uml-base-patch	2004-08-15 20:45:08.512360856 -0700
+++ 25-akpm/include/asm-um/processor-i386.h	2004-08-15 20:46:03.330027304 -0700
@@ -6,8 +6,8 @@
 #ifndef __UM_PROCESSOR_I386_H
 #define __UM_PROCESSOR_I386_H
 
-extern int cpu_has_xmm;
-extern int cpu_has_cmov;
+extern int host_has_xmm;
+extern int host_has_cmov;
 
 struct arch_thread {
 	unsigned long debugregs[8];
diff -puN /dev/null include/asm-um/sections.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-um/sections.h	2004-08-15 20:46:03.330027304 -0700
@@ -0,0 +1,7 @@
+#ifndef _UM_SECTIONS_H
+#define _UM_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif
diff -puN include/asm-um/smp.h~uml-base-patch include/asm-um/smp.h
--- 25/include/asm-um/smp.h~uml-base-patch	2004-08-15 20:45:08.514360552 -0700
+++ 25-akpm/include/asm-um/smp.h	2004-08-15 20:46:03.330027304 -0700
@@ -10,7 +10,7 @@
 
 extern cpumask_t cpu_online_map;
 
-#define smp_processor_id() (current->thread_info->cpu)
+#define smp_processor_id() (current_thread->cpu)
 #define cpu_logical_map(n) (n)
 #define cpu_number_map(n) (n)
 #define PROC_CHANGE_PENALTY	15 /* Pick a number, any number */
diff -L include/asm-um/smplock.h -puN include/asm-um/smplock.h~uml-base-patch /dev/null
--- 25/include/asm-um/smplock.h
+++ /dev/null	2003-09-15 06:40:47.000000000 -0700
@@ -1,6 +0,0 @@
-#ifndef __UM_SMPLOCK_H
-#define __UM_SMPLOCK_H
-
-#include "asm/arch/smplock.h"
-
-#endif
diff -L include/asm-um/spinlock.h -puN include/asm-um/spinlock.h~uml-base-patch /dev/null
--- 25/include/asm-um/spinlock.h
+++ /dev/null	2003-09-15 06:40:47.000000000 -0700
@@ -1,10 +0,0 @@
-#ifndef __UM_SPINLOCK_H
-#define __UM_SPINLOCK_H
-
-#include "linux/config.h"
-
-#ifdef CONFIG_SMP
-#include "asm/arch/spinlock.h"
-#endif
-
-#endif
diff -puN include/asm-um/system-generic.h~uml-base-patch include/asm-um/system-generic.h
--- 25/include/asm-um/system-generic.h~uml-base-patch	2004-08-15 20:45:08.519359792 -0700
+++ 25-akpm/include/asm-um/system-generic.h	2004-08-15 20:46:03.331027152 -0700
@@ -23,8 +23,10 @@ extern int get_signals(void);
 extern void block_signals(void);
 extern void unblock_signals(void);
 
-#define local_save_flags(flags) do { (flags) = get_signals(); } while(0)
-#define local_irq_restore(flags) do { set_signals(flags); } while(0)
+#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
+				     (flags) = get_signals(); } while(0)
+#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
+				      set_signals(flags); } while(0)
 
 #define local_irq_save(flags) do { local_save_flags(flags); \
                                    local_irq_disable(); } while(0)
@@ -39,4 +41,7 @@ extern void unblock_signals(void);
         (flags == 0);                   \
 })
 
+extern void *_switch_to(void *prev, void *next, void *last);
+#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
+
 #endif
diff -puN include/asm-um/system-i386.h~uml-base-patch include/asm-um/system-i386.h
--- 25/include/asm-um/system-i386.h~uml-base-patch	2004-08-15 20:45:08.520359640 -0700
+++ 25-akpm/include/asm-um/system-i386.h	2004-08-15 20:46:03.332027000 -0700
@@ -2,36 +2,5 @@
 #define __UM_SYSTEM_I386_H
 
 #include "asm/system-generic.h"
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-				      unsigned long new, int size)
-{
-	unsigned long prev;
-	switch (size) {
-	case 1:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 2:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 4:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	}
-	return old;
-}
-
-#define cmpxchg(ptr,o,n)\
-	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
-					(unsigned long)(n),sizeof(*(ptr))))
     
 #endif
diff -puN include/asm-um/thread_info.h~uml-base-patch include/asm-um/thread_info.h
--- 25/include/asm-um/thread_info.h~uml-base-patch	2004-08-15 20:45:08.521359488 -0700
+++ 25-akpm/include/asm-um/thread_info.h	2004-08-15 20:46:03.332027000 -0700
@@ -9,6 +9,7 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/processor.h>
+#include <asm/types.h>
 
 struct thread_info {
 	struct task_struct	*task;		/* main task structure */
@@ -43,15 +44,18 @@ struct thread_info {
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~16383UL));
+	unsigned long mask = PAGE_SIZE *
+		(1 << CONFIG_KERNEL_STACK_ORDER) - 1;
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask));
 	return ti;
 }
 
 /* thread information allocation */
-#define THREAD_SIZE (4*PAGE_SIZE)
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-	__get_free_pages(GFP_KERNEL,2))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 2)
+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
+#define alloc_thread_info(tsk) \
+	((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
+#define free_thread_info(ti) kfree(ti)
+
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
@@ -65,11 +69,13 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling 
 					 * TIF_NEED_RESCHED 
 					 */
+#define TIF_RESTART_BLOCK 	4
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
+#define _TIF_RESTART_BLOCK	(1 << TIF_RESTART_BLOCK)
 
 #endif
 
diff -puN include/asm-um/timex.h~uml-base-patch include/asm-um/timex.h
--- 25/include/asm-um/timex.h~uml-base-patch	2004-08-15 20:45:08.523359184 -0700
+++ 25-akpm/include/asm-um/timex.h	2004-08-15 20:46:03.333026848 -0700
@@ -1,8 +1,6 @@
 #ifndef __UM_TIMEX_H
 #define __UM_TIMEX_H
 
-#include "linux/time.h"
-
 typedef unsigned long cycles_t;
 
 #define cacheflush_time (0)
diff -puN include/asm-um/uaccess.h~uml-base-patch include/asm-um/uaccess.h
--- 25/include/asm-um/uaccess.h~uml-base-patch	2004-08-15 20:45:08.524359032 -0700
+++ 25-akpm/include/asm-um/uaccess.h	2004-08-15 20:46:03.333026848 -0700
@@ -6,6 +6,8 @@
 #ifndef __UM_UACCESS_H
 #define __UM_UACCESS_H
 
+#include "linux/sched.h"
+
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
diff -puN include/asm-um/unistd.h~uml-base-patch include/asm-um/unistd.h
--- 25/include/asm-um/unistd.h~uml-base-patch	2004-08-15 20:45:08.525358880 -0700
+++ 25-akpm/include/asm-um/unistd.h	2004-08-15 20:46:03.334026696 -0700
@@ -48,7 +48,10 @@ extern int um_execve(const char *file, c
 	set_fs(KERNEL_DS);			\
 	ret = sys(args);			\
 	set_fs(fs);				\
-	return ret;
+	if (ret >= 0)				\
+		return ret;			\
+	errno = -(long)ret;			\
+	return -1;
 
 static inline long open(const char *pathname, int flags, int mode) 
 {
diff -puN include/linux/gfp.h~uml-base-patch include/linux/gfp.h
--- 25/include/linux/gfp.h~uml-base-patch	2004-08-15 20:45:08.537357056 -0700
+++ 25-akpm/include/linux/gfp.h	2004-08-15 20:46:03.334026696 -0700
@@ -73,6 +73,11 @@ struct vm_area_struct;
  * For the normal case of non-DISCONTIGMEM systems the NODE_DATA() gets
  * optimized to &contig_page_data at compile-time.
  */
+
+#ifndef HAVE_ARCH_FREE_PAGE
+static inline void arch_free_page(struct page *page, int order) { }
+#endif
+
 extern struct page *
 FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *));
 
diff -puN include/linux/time.h~uml-base-patch include/linux/time.h
--- 25/include/linux/time.h~uml-base-patch	2004-08-15 20:45:08.538356904 -0700
+++ 25-akpm/include/linux/time.h	2004-08-15 20:46:03.335026544 -0700
@@ -41,7 +41,7 @@ struct timezone {
  * Have the 32 bit jiffies value wrap 5 minutes after boot
  * so jiffies wrap bugs show up earlier.
  */
-#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
+#define INITIAL_JIFFIES ((unsigned long)(0))
 
 /*
  * Change timeval to jiffies, trying to avoid the
diff -puN mm/page_alloc.c~uml-base-patch mm/page_alloc.c
--- 25/mm/page_alloc.c~uml-base-patch	2004-08-15 20:45:08.540356600 -0700
+++ 25-akpm/mm/page_alloc.c	2004-08-15 20:46:03.336026392 -0700
@@ -279,6 +279,8 @@ void __free_pages_ok(struct page *page, 
 	LIST_HEAD(list);
 	int i;
 
+	arch_free_page(page, order);
+
 	mod_page_state(pgfree, 1 << order);
 	for (i = 0 ; i < (1 << order) ; ++i)
 		free_pages_check(__FUNCTION__, page + i);
@@ -509,6 +511,8 @@ static void fastcall free_hot_cold_page(
 	struct per_cpu_pages *pcp;
 	unsigned long flags;
 
+	arch_free_page(page, 0);
+
 	kernel_map_pages(page, 1, 0);
 	inc_page_state(pgfree);
 	free_pages_check(__FUNCTION__, page);
diff -puN arch/um/Kconfig.debug~uml-base-patch arch/um/Kconfig.debug
--- 25/arch/um/Kconfig.debug~uml-base-patch	2004-08-15 20:45:08.541356448 -0700
+++ 25-akpm/arch/um/Kconfig.debug	2004-08-15 20:46:38.503680096 -0700
@@ -9,6 +9,10 @@ config FRAME_POINTER
 config PT_PROXY
 	bool "Enable ptrace proxy"
 	depends on XTERM_CHAN && DEBUG_INFO
+	help
+	This option enables a debugging interface which allows gdb to debug
+	the kernel without needing to actually attach to kernel threads.
+	If you want to do kernel debugging, say Y here; otherwise say N.
 
 config GPROF
 	bool "Enable gprof support"
_