diff options
Diffstat (limited to 'linux-uml/linux-uml-2.6.7/Main-uml-patch-no-skas.patch')
-rw-r--r-- | linux-uml/linux-uml-2.6.7/Main-uml-patch-no-skas.patch | 19521 |
1 files changed, 19521 insertions, 0 deletions
diff --git a/linux-uml/linux-uml-2.6.7/Main-uml-patch-no-skas.patch b/linux-uml/linux-uml-2.6.7/Main-uml-patch-no-skas.patch index e69de29bb2..1a7ab95d4c 100644 --- a/linux-uml/linux-uml-2.6.7/Main-uml-patch-no-skas.patch +++ b/linux-uml/linux-uml-2.6.7/Main-uml-patch-no-skas.patch @@ -0,0 +1,19521 @@ + +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> +--- + + uml-linux-2.6.7-paolo/arch/um/Kconfig | 52 + uml-linux-2.6.7-paolo/arch/um/Kconfig_block | 14 + uml-linux-2.6.7-paolo/arch/um/Kconfig_net | 70 + uml-linux-2.6.7-paolo/arch/um/Makefile | 110 - + uml-linux-2.6.7-paolo/arch/um/Makefile-i386 | 23 + uml-linux-2.6.7-paolo/arch/um/Makefile-skas | 6 + uml-linux-2.6.7-paolo/arch/um/config.release | 1 + uml-linux-2.6.7-paolo/arch/um/defconfig | 230 +- + uml-linux-2.6.7-paolo/arch/um/drivers/Makefile | 17 + uml-linux-2.6.7-paolo/arch/um/drivers/chan_kern.c | 16 + uml-linux-2.6.7-paolo/arch/um/drivers/chan_user.c | 100 + uml-linux-2.6.7-paolo/arch/um/drivers/cow.h | 41 + uml-linux-2.6.7-paolo/arch/um/drivers/cow_kern.c | 630 ++++++ + uml-linux-2.6.7-paolo/arch/um/drivers/cow_sys.h | 48 + uml-linux-2.6.7-paolo/arch/um/drivers/cow_user.c | 375 +++ + uml-linux-2.6.7-paolo/arch/um/drivers/daemon_user.c | 26 + uml-linux-2.6.7-paolo/arch/um/drivers/fd.c | 3 + uml-linux-2.6.7-paolo/arch/um/drivers/harddog_user.c | 62 + uml-linux-2.6.7-paolo/arch/um/drivers/hostaudio_kern.c | 107 - + uml-linux-2.6.7-paolo/arch/um/drivers/hostaudio_user.c | 63 + uml-linux-2.6.7-paolo/arch/um/drivers/line.c | 152 - + uml-linux-2.6.7-paolo/arch/um/drivers/mcast_user.c | 16 + uml-linux-2.6.7-paolo/arch/um/drivers/mconsole_kern.c | 140 + + uml-linux-2.6.7-paolo/arch/um/drivers/mconsole_user.c | 25 + uml-linux-2.6.7-paolo/arch/um/drivers/mmapper_kern.c | 5 + uml-linux-2.6.7-paolo/arch/um/drivers/net_kern.c | 89 + uml-linux-2.6.7-paolo/arch/um/drivers/net_user.c | 46 + uml-linux-2.6.7-paolo/arch/um/drivers/null.c | 1 + uml-linux-2.6.7-paolo/arch/um/drivers/port_kern.c | 17 + uml-linux-2.6.7-paolo/arch/um/drivers/port_user.c | 31 + uml-linux-2.6.7-paolo/arch/um/drivers/pty.c | 22 + uml-linux-2.6.7-paolo/arch/um/drivers/slip_user.c | 69 + uml-linux-2.6.7-paolo/arch/um/drivers/slirp_user.c | 15 + uml-linux-2.6.7-paolo/arch/um/drivers/ssl.c | 49 + uml-linux-2.6.7-paolo/arch/um/drivers/stdio_console.c | 54 + uml-linux-2.6.7-paolo/arch/um/drivers/tty.c | 4 + uml-linux-2.6.7-paolo/arch/um/drivers/ubd_kern.c | 600 ++++- + uml-linux-2.6.7-paolo/arch/um/drivers/ubd_user.c | 497 +--- + uml-linux-2.6.7-paolo/arch/um/drivers/xterm.c | 21 + uml-linux-2.6.7-paolo/arch/um/drivers/xterm_kern.c | 12 + uml-linux-2.6.7-paolo/arch/um/dyn.lds.S | 15 + uml-linux-2.6.7-paolo/arch/um/include/2_5compat.h | 14 + uml-linux-2.6.7-paolo/arch/um/include/irq_kern.h | 28 + uml-linux-2.6.7-paolo/arch/um/include/kern_util.h | 11 + uml-linux-2.6.7-paolo/arch/um/include/line.h | 4 + uml-linux-2.6.7-paolo/arch/um/include/mconsole.h | 6 + uml-linux-2.6.7-paolo/arch/um/include/mem.h | 15 + uml-linux-2.6.7-paolo/arch/um/include/mem_kern.h | 30 + uml-linux-2.6.7-paolo/arch/um/include/mem_user.h | 31 + uml-linux-2.6.7-paolo/arch/um/include/os.h | 53 + uml-linux-2.6.7-paolo/arch/um/include/signal_user.h | 2 + uml-linux-2.6.7-paolo/arch/um/include/skas_ptrace.h | 2 + uml-linux-2.6.7-paolo/arch/um/include/sysdep-i386/frame_user.h | 28 + uml-linux-2.6.7-paolo/arch/um/include/sysdep-i386/sigcontext.h | 4 + uml-linux-2.6.7-paolo/arch/um/include/sysdep-i386/syscalls.h | 59 + uml-linux-2.6.7-paolo/arch/um/include/ubd_user.h | 9 + uml-linux-2.6.7-paolo/arch/um/include/um_uaccess.h | 51 + uml-linux-2.6.7-paolo/arch/um/include/user.h | 1 + uml-linux-2.6.7-paolo/arch/um/include/user_util.h | 7 + uml-linux-2.6.7-paolo/arch/um/kernel/Makefile | 44 + uml-linux-2.6.7-paolo/arch/um/kernel/config.c.in | 4 + uml-linux-2.6.7-paolo/arch/um/kernel/exec_kern.c | 5 + uml-linux-2.6.7-paolo/arch/um/kernel/frame.c | 3 + uml-linux-2.6.7-paolo/arch/um/kernel/frame_kern.c | 6 + uml-linux-2.6.7-paolo/arch/um/kernel/helper.c | 55 + uml-linux-2.6.7-paolo/arch/um/kernel/init_task.c | 17 + uml-linux-2.6.7-paolo/arch/um/kernel/initrd_user.c | 13 + uml-linux-2.6.7-paolo/arch/um/kernel/irq.c | 105 - + uml-linux-2.6.7-paolo/arch/um/kernel/irq_user.c | 37 + uml-linux-2.6.7-paolo/arch/um/kernel/ksyms.c | 53 + uml-linux-2.6.7-paolo/arch/um/kernel/mem.c | 657 ------ + uml-linux-2.6.7-paolo/arch/um/kernel/mem_user.c | 230 +- + uml-linux-2.6.7-paolo/arch/um/kernel/physmem.c | 468 ++++ + uml-linux-2.6.7-paolo/arch/um/kernel/process.c | 20 + uml-linux-2.6.7-paolo/arch/um/kernel/process_kern.c | 45 + uml-linux-2.6.7-paolo/arch/um/kernel/ptrace.c | 23 + uml-linux-2.6.7-paolo/arch/um/kernel/reboot.c | 2 + uml-linux-2.6.7-paolo/arch/um/kernel/sigio_kern.c | 7 + uml-linux-2.6.7-paolo/arch/um/kernel/sigio_user.c | 96 + uml-linux-2.6.7-paolo/arch/um/kernel/signal_kern.c | 60 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/Makefile | 24 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/include/mode.h | 6 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/include/skas.h | 4 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/include/uaccess.h | 207 -- + uml-linux-2.6.7-paolo/arch/um/kernel/skas/mem_user.c | 32 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/mmu.c | 8 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/process.c | 107 - + uml-linux-2.6.7-paolo/arch/um/kernel/skas/process_kern.c | 26 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/sys-i386/Makefile | 2 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/sys-i386/sigcontext.c | 15 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/syscall_kern.c | 2 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/syscall_user.c | 4 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/trap_user.c | 6 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/uaccess.c | 219 ++ + uml-linux-2.6.7-paolo/arch/um/kernel/skas/util/Makefile | 7 + uml-linux-2.6.7-paolo/arch/um/kernel/skas/util/mk_ptregs.c | 1 + uml-linux-2.6.7-paolo/arch/um/kernel/smp.c | 63 + uml-linux-2.6.7-paolo/arch/um/kernel/sys_call_table.c | 686 ++---- + uml-linux-2.6.7-paolo/arch/um/kernel/syscall_kern.c | 64 + uml-linux-2.6.7-paolo/arch/um/kernel/sysrq.c | 5 + uml-linux-2.6.7-paolo/arch/um/kernel/tempfile.c | 7 + uml-linux-2.6.7-paolo/arch/um/kernel/time.c | 69 + uml-linux-2.6.7-paolo/arch/um/kernel/time_kern.c | 77 + uml-linux-2.6.7-paolo/arch/um/kernel/trap_kern.c | 58 + uml-linux-2.6.7-paolo/arch/um/kernel/trap_user.c | 9 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/Makefile | 6 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/exec_kern.c | 7 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/include/mode.h | 2 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/include/uaccess.h | 60 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/mem_user.c | 7 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/process_kern.c | 82 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/ptproxy/Makefile | 2 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/ptproxy/proxy.c | 25 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/ptproxy/sysdep.c | 1 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/ptproxy/wait.c | 12 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/sys-i386/Makefile | 2 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/syscall_kern.c | 2 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/syscall_user.c | 4 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/tlb.c | 1 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/tracer.c | 27 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/uaccess.c | 73 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/uaccess_user.c | 22 + uml-linux-2.6.7-paolo/arch/um/kernel/tt/unmap.c | 3 + uml-linux-2.6.7-paolo/arch/um/kernel/tty_log.c | 136 + + uml-linux-2.6.7-paolo/arch/um/kernel/uaccess_user.c | 2 + uml-linux-2.6.7-paolo/arch/um/kernel/um_arch.c | 76 + uml-linux-2.6.7-paolo/arch/um/kernel/umid.c | 80 + uml-linux-2.6.7-paolo/arch/um/kernel/user_util.c | 15 + uml-linux-2.6.7-paolo/arch/um/main.c | 7 + uml-linux-2.6.7-paolo/arch/um/os-Linux/Makefile | 6 + uml-linux-2.6.7-paolo/arch/um/os-Linux/drivers/ethertap_kern.c | 1 + uml-linux-2.6.7-paolo/arch/um/os-Linux/drivers/ethertap_user.c | 56 + uml-linux-2.6.7-paolo/arch/um/os-Linux/drivers/tuntap_user.c | 57 + uml-linux-2.6.7-paolo/arch/um/os-Linux/file.c | 450 +++- + uml-linux-2.6.7-paolo/arch/um/os-Linux/process.c | 58 + uml-linux-2.6.7-paolo/arch/um/os-Linux/tty.c | 10 + uml-linux-2.6.7-paolo/arch/um/os-Linux/user_syms.c | 88 + uml-linux-2.6.7-paolo/arch/um/sys-i386/Makefile | 24 + uml-linux-2.6.7-paolo/arch/um/sys-i386/bugs.c | 140 + + uml-linux-2.6.7-paolo/arch/um/sys-i386/fault.c | 16 + uml-linux-2.6.7-paolo/arch/um/sys-i386/ptrace_user.c | 8 + uml-linux-2.6.7-paolo/arch/um/sys-i386/time.c | 24 + uml-linux-2.6.7-paolo/arch/um/sys-i386/util/Makefile | 15 + uml-linux-2.6.7-paolo/arch/um/sys-i386/util/mk_sc.c | 1 + uml-linux-2.6.7-paolo/arch/um/sys-ia64/Makefile | 15 + uml-linux-2.6.7-paolo/arch/um/sys-ppc/Makefile | 11 + uml-linux-2.6.7-paolo/arch/um/uml.lds.S | 10 + uml-linux-2.6.7-paolo/arch/um/util/Makefile | 27 + uml-linux-2.6.7-paolo/arch/um/util/mk_constants_kern.c | 4 + uml-linux-2.6.7-paolo/fs/Makefile | 2 + uml-linux-2.6.7-paolo/fs/hostfs/Makefile | 26 + uml-linux-2.6.7-paolo/fs/hostfs/hostfs.h | 79 + uml-linux-2.6.7-paolo/fs/hostfs/hostfs_kern.c | 1008 ++++++++++ + uml-linux-2.6.7-paolo/fs/hostfs/hostfs_user.c | 361 +++ + uml-linux-2.6.7-paolo/fs/hppfs/Makefile | 19 + uml-linux-2.6.7-paolo/fs/hppfs/hppfs_kern.c | 811 ++++++++ + uml-linux-2.6.7-paolo/include/asm-um/archparam-i386.h | 89 + uml-linux-2.6.7-paolo/include/asm-um/common.lds.S | 48 + uml-linux-2.6.7-paolo/include/asm-um/cpufeature.h | 6 + uml-linux-2.6.7-paolo/include/asm-um/current.h | 6 + uml-linux-2.6.7-paolo/include/asm-um/dma-mapping.h | 120 + + uml-linux-2.6.7-paolo/include/asm-um/elf.h | 13 + uml-linux-2.6.7-paolo/include/asm-um/fixmap.h | 8 + uml-linux-2.6.7-paolo/include/asm-um/irq.h | 18 + uml-linux-2.6.7-paolo/include/asm-um/local.h | 6 + uml-linux-2.6.7-paolo/include/asm-um/module-generic.h | 6 + uml-linux-2.6.7-paolo/include/asm-um/module-i386.h | 13 + uml-linux-2.6.7-paolo/include/asm-um/page.h | 43 + uml-linux-2.6.7-paolo/include/asm-um/pgtable.h | 111 - + uml-linux-2.6.7-paolo/include/asm-um/processor-generic.h | 43 + uml-linux-2.6.7-paolo/include/asm-um/processor-i386.h | 4 + uml-linux-2.6.7-paolo/include/asm-um/sections.h | 7 + uml-linux-2.6.7-paolo/include/asm-um/smp.h | 2 + uml-linux-2.6.7-paolo/include/asm-um/system-generic.h | 9 + uml-linux-2.6.7-paolo/include/asm-um/system-i386.h | 31 + uml-linux-2.6.7-paolo/include/asm-um/thread_info.h | 16 + uml-linux-2.6.7-paolo/include/asm-um/timex.h | 2 + uml-linux-2.6.7-paolo/include/asm-um/uaccess.h | 2 + uml-linux-2.6.7-paolo/include/asm-um/unistd.h | 5 + uml-linux-2.6.7-paolo/include/linux/gfp.h | 5 + uml-linux-2.6.7-paolo/include/linux/time.h | 2 + uml-linux-2.6.7-paolo/mm/page_alloc.c | 4 + uml-linux-2.6.7/arch/um/kernel/user_syms.c | 113 - + uml-linux-2.6.7/arch/um/sys-i386/extable.c | 30 + uml-linux-2.6.7/include/asm-um/smplock.h | 6 + uml-linux-2.6.7/include/asm-um/spinlock.h | 10 + 186 files changed, 8707 insertions(+), 3939 deletions(-) + +diff -puN arch/um/config.release~Main-uml-patch-no-skas arch/um/config.release +--- uml-linux-2.6.7/arch/um/config.release~Main-uml-patch-no-skas 2004-06-29 21:02:55.437331000 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/config.release 2004-06-29 21:02:55.704290416 +0200 +@@ -228,7 +228,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~Main-uml-patch-no-skas arch/um/defconfig +--- uml-linux-2.6.7/arch/um/defconfig~Main-uml-patch-no-skas 2004-06-29 21:02:55.438330848 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/defconfig 2004-06-29 21:02:55.705290264 +0200 +@@ -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 +@@ -160,6 +167,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) +@@ -171,12 +182,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 + +@@ -186,68 +213,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 + + # +@@ -255,11 +314,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 +@@ -317,28 +376,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) +@@ -360,6 +398,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 +@@ -374,20 +413,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~Main-uml-patch-no-skas arch/um/drivers/chan_kern.c +--- uml-linux-2.6.7/arch/um/drivers/chan_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.440330544 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/chan_kern.c 2004-06-29 21:02:55.705290264 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/chan_user.c +--- uml-linux-2.6.7/arch/um/drivers/chan_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.441330392 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/chan_user.c 2004-06-29 21:02:55.706290112 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/cow.h 2004-06-29 21:02:55.706290112 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/cow_kern.c 2004-06-29 21:02:55.707289960 +0200 +@@ -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(¤t->sigmask_lock); ++ sigfillset(¤t->blocked); ++ flush_signals(current); ++ spin_unlock_irq(¤t->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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/cow_sys.h 2004-06-29 21:02:55.707289960 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/cow_user.c 2004-06-29 21:02:55.708289808 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/daemon_user.c +--- uml-linux-2.6.7/arch/um/drivers/daemon_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.443330088 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/daemon_user.c 2004-06-29 21:02:55.708289808 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/fd.c +--- uml-linux-2.6.7/arch/um/drivers/fd.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.444329936 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/fd.c 2004-06-29 21:02:55.708289808 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/harddog_user.c +--- uml-linux-2.6.7/arch/um/drivers/harddog_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.445329784 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/harddog_user.c 2004-06-29 21:02:55.709289656 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/hostaudio_kern.c +--- uml-linux-2.6.7/arch/um/drivers/hostaudio_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.459327656 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/hostaudio_kern.c 2004-06-29 21:02:55.709289656 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/hostaudio_user.c +--- uml-linux-2.6.7/arch/um/drivers/hostaudio_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.460327504 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/hostaudio_user.c 2004-06-29 21:02:55.709289656 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/line.c +--- uml-linux-2.6.7/arch/um/drivers/line.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.462327200 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/line.c 2004-06-29 21:02:55.710289504 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/Makefile +--- uml-linux-2.6.7/arch/um/drivers/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.463327048 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/Makefile 2004-06-29 21:02:55.710289504 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/mcast_user.c +--- uml-linux-2.6.7/arch/um/drivers/mcast_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.464326896 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/mcast_user.c 2004-06-29 21:02:55.711289352 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/mconsole_kern.c +--- uml-linux-2.6.7/arch/um/drivers/mconsole_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.465326744 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/mconsole_kern.c 2004-06-29 21:02:55.711289352 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/mconsole_user.c +--- uml-linux-2.6.7/arch/um/drivers/mconsole_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.466326592 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/mconsole_user.c 2004-06-29 21:02:55.712289200 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/mmapper_kern.c +--- uml-linux-2.6.7/arch/um/drivers/mmapper_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.467326440 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/mmapper_kern.c 2004-06-29 21:02:55.712289200 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/net_kern.c +--- uml-linux-2.6.7/arch/um/drivers/net_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.468326288 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/net_kern.c 2004-06-29 21:02:55.712289200 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/net_user.c +--- uml-linux-2.6.7/arch/um/drivers/net_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.469326136 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/net_user.c 2004-06-29 21:02:55.713289048 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/null.c +--- uml-linux-2.6.7/arch/um/drivers/null.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.470325984 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/null.c 2004-06-29 21:02:55.713289048 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/port_kern.c +--- uml-linux-2.6.7/arch/um/drivers/port_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.471325832 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/port_kern.c 2004-06-29 21:02:55.713289048 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/port_user.c +--- uml-linux-2.6.7/arch/um/drivers/port_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.473325528 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/port_user.c 2004-06-29 21:02:55.714288896 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/pty.c +--- uml-linux-2.6.7/arch/um/drivers/pty.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.474325376 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/pty.c 2004-06-29 21:02:55.714288896 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/slip_user.c +--- uml-linux-2.6.7/arch/um/drivers/slip_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.475325224 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/slip_user.c 2004-06-29 21:02:55.714288896 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/slirp_user.c +--- uml-linux-2.6.7/arch/um/drivers/slirp_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.476325072 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/slirp_user.c 2004-06-29 21:02:55.715288744 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/ssl.c +--- uml-linux-2.6.7/arch/um/drivers/ssl.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.477324920 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/ssl.c 2004-06-29 21:02:55.715288744 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/stdio_console.c +--- uml-linux-2.6.7/arch/um/drivers/stdio_console.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.478324768 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/stdio_console.c 2004-06-29 21:02:55.715288744 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/tty.c +--- uml-linux-2.6.7/arch/um/drivers/tty.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.479324616 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/tty.c 2004-06-29 21:02:55.715288744 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/ubd_kern.c +--- uml-linux-2.6.7/arch/um/drivers/ubd_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.480324464 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/ubd_kern.c 2004-06-29 21:02:55.717288440 +0200 +@@ -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; +- +- if(dev->is_dir == 1) +- goto out; ++ int err = 0; + +- 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~Main-uml-patch-no-skas arch/um/drivers/ubd_user.c +--- uml-linux-2.6.7/arch/um/drivers/ubd_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.481324312 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/ubd_user.c 2004-06-29 21:02:55.718288288 +0200 +@@ -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, +- §orsize, bitmap_offset_out); ++ err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, ++ &size, §orsize, &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~Main-uml-patch-no-skas arch/um/drivers/xterm.c +--- uml-linux-2.6.7/arch/um/drivers/xterm.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.483324008 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/xterm.c 2004-06-29 21:02:55.718288288 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/drivers/xterm_kern.c +--- uml-linux-2.6.7/arch/um/drivers/xterm_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.484323856 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/drivers/xterm_kern.c 2004-06-29 21:02:55.719288136 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/dyn.lds.S +--- uml-linux-2.6.7/arch/um/dyn.lds.S~Main-uml-patch-no-skas 2004-06-29 21:02:55.485323704 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/dyn.lds.S 2004-06-29 21:02:55.719288136 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/2_5compat.h +--- uml-linux-2.6.7/arch/um/include/2_5compat.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.486323552 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/2_5compat.h 2004-06-29 21:02:55.719288136 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/include/irq_kern.h 2004-06-29 21:02:55.719288136 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/kern_util.h +--- uml-linux-2.6.7/arch/um/include/kern_util.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.487323400 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/kern_util.h 2004-06-29 21:02:55.720287984 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/line.h +--- uml-linux-2.6.7/arch/um/include/line.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.488323248 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/line.h 2004-06-29 21:02:55.720287984 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/mconsole.h +--- uml-linux-2.6.7/arch/um/include/mconsole.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.489323096 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/mconsole.h 2004-06-29 21:02:55.720287984 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/mem.h +--- uml-linux-2.6.7/arch/um/include/mem.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.490322944 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/mem.h 2004-06-29 21:02:55.720287984 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/include/mem_kern.h 2004-06-29 21:02:55.721287832 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/mem_user.h +--- uml-linux-2.6.7/arch/um/include/mem_user.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.492322640 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/mem_user.h 2004-06-29 21:02:55.721287832 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/os.h +--- uml-linux-2.6.7/arch/um/include/os.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.493322488 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/os.h 2004-06-29 21:02:55.721287832 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/signal_user.h +--- uml-linux-2.6.7/arch/um/include/signal_user.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.494322336 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/signal_user.h 2004-06-29 21:02:55.722287680 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/skas_ptrace.h +--- uml-linux-2.6.7/arch/um/include/skas_ptrace.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.495322184 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/skas_ptrace.h 2004-06-29 21:02:55.722287680 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/sysdep-i386/frame_user.h +--- uml-linux-2.6.7/arch/um/include/sysdep-i386/frame_user.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.496322032 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/sysdep-i386/frame_user.h 2004-06-29 21:02:55.722287680 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/sysdep-i386/sigcontext.h +--- uml-linux-2.6.7/arch/um/include/sysdep-i386/sigcontext.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.497321880 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/sysdep-i386/sigcontext.h 2004-06-29 21:02:55.722287680 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/sysdep-i386/syscalls.h +--- uml-linux-2.6.7/arch/um/include/sysdep-i386/syscalls.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.498321728 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/sysdep-i386/syscalls.h 2004-06-29 21:02:55.723287528 +0200 +@@ -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(®s->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~Main-uml-patch-no-skas arch/um/include/ubd_user.h +--- uml-linux-2.6.7/arch/um/include/ubd_user.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.500321424 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/ubd_user.h 2004-06-29 21:02:55.723287528 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/um_uaccess.h +--- uml-linux-2.6.7/arch/um/include/um_uaccess.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.501321272 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/um_uaccess.h 2004-06-29 21:02:55.723287528 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/user.h +--- uml-linux-2.6.7/arch/um/include/user.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.513319448 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/user.h 2004-06-29 21:02:55.723287528 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/include/user_util.h +--- uml-linux-2.6.7/arch/um/include/user_util.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.515319144 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/include/user_util.h 2004-06-29 21:02:55.724287376 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/Kconfig +--- uml-linux-2.6.7/arch/um/Kconfig~Main-uml-patch-no-skas 2004-06-29 21:02:55.516318992 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/Kconfig 2004-06-29 21:02:55.724287376 +0200 +@@ -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" +@@ -105,6 +132,16 @@ config MCONSOLE + config MAGIC_SYSRQ + bool "Magic SysRq key" + depends on MCONSOLE ++ help ++ If you say Y here, you will have some control over the system even ++ if the system crashes for example during kernel debugging (e.g., you ++ will be able to flush the buffer cache to disk, reboot the system ++ immediately or dump some status information). This is accomplished ++ by pressing various keys while holding SysRq (Alt+PrintScreen). It ++ also works on a serial console (on PC hardware at least), if you ++ send a BREAK and then within 5 seconds a command keypress. The ++ keys are documented in Documentation/sysrq.txt. Don't say Y ++ unless you really know what this hack does. + + config HOST_2G_2G + bool "2G/2G host address space split" +@@ -168,6 +205,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" +@@ -240,6 +288,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" +diff -puN arch/um/Kconfig_block~Main-uml-patch-no-skas arch/um/Kconfig_block +--- uml-linux-2.6.7/arch/um/Kconfig_block~Main-uml-patch-no-skas 2004-06-29 21:02:55.517318840 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/Kconfig_block 2004-06-29 21:02:55.724287376 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/Kconfig_net +--- uml-linux-2.6.7/arch/um/Kconfig_net~Main-uml-patch-no-skas 2004-06-29 21:02:55.518318688 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/Kconfig_net 2004-06-29 21:02:55.725287224 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/config.c.in +--- uml-linux-2.6.7/arch/um/kernel/config.c.in~Main-uml-patch-no-skas 2004-06-29 21:02:55.519318536 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/config.c.in 2004-06-29 21:02:55.725287224 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/exec_kern.c +--- uml-linux-2.6.7/arch/um/kernel/exec_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.520318384 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/exec_kern.c 2004-06-29 21:02:55.725287224 +0200 +@@ -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, ¤t->thread.regs); + if (error == 0){ + current->ptrace &= ~PT_DTRACE; +diff -puN arch/um/kernel/frame.c~Main-uml-patch-no-skas arch/um/kernel/frame.c +--- uml-linux-2.6.7/arch/um/kernel/frame.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.521318232 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/frame.c 2004-06-29 21:02:55.725287224 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/frame_kern.c +--- uml-linux-2.6.7/arch/um/kernel/frame_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.522318080 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/frame_kern.c 2004-06-29 21:02:55.726287072 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/helper.c +--- uml-linux-2.6.7/arch/um/kernel/helper.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.524317776 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/helper.c 2004-06-29 21:02:55.726287072 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/initrd_user.c +--- uml-linux-2.6.7/arch/um/kernel/initrd_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.525317624 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/initrd_user.c 2004-06-29 21:02:55.726287072 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/init_task.c +--- uml-linux-2.6.7/arch/um/kernel/init_task.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.526317472 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/init_task.c 2004-06-29 21:02:55.726287072 +0200 +@@ -8,7 +8,6 @@ + #include "linux/module.h" + #include "linux/sched.h" + #include "linux/init_task.h" +-#include "linux/version.h" + #include "asm/uaccess.h" + #include "asm/pgtable.h" + #include "user_util.h" +@@ -18,7 +17,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); + + /* +@@ -43,26 +42,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~Main-uml-patch-no-skas arch/um/kernel/irq.c +--- uml-linux-2.6.7/arch/um/kernel/irq.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.527317320 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/irq.c 2004-06-29 21:02:55.727286920 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/irq_user.c +--- uml-linux-2.6.7/arch/um/kernel/irq_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.528317168 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/irq_user.c 2004-06-29 21:02:55.727286920 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/ksyms.c +--- uml-linux-2.6.7/arch/um/kernel/ksyms.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.529317016 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/ksyms.c 2004-06-29 21:02:55.728286768 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/Makefile +--- uml-linux-2.6.7/arch/um/kernel/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.530316864 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/Makefile 2004-06-29 21:02:55.728286768 +0200 +@@ -7,11 +7,11 @@ extra-y := vmlinux.lds.s + + 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~Main-uml-patch-no-skas arch/um/kernel/mem.c +--- uml-linux-2.6.7/arch/um/kernel/mem.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.532316560 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/mem.c 2004-06-29 21:02:55.729286616 +0200 +@@ -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(®ions_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(®ions_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), ++ ¤t->thread.fault_addr, ++ ¤t->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), +- ¤t->thread.fault_addr, +- ¤t->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~Main-uml-patch-no-skas arch/um/kernel/mem_user.c +--- uml-linux-2.6.7/arch/um/kernel/mem_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.533316408 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/mem_user.c 2004-06-29 21:02:55.729286616 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/physmem.c 2004-06-29 21:02:55.730286464 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/process.c +--- uml-linux-2.6.7/arch/um/kernel/process.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.534316256 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/process.c 2004-06-29 21:02:55.731286312 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/process_kern.c +--- uml-linux-2.6.7/arch/um/kernel/process_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.535316104 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/process_kern.c 2004-06-29 21:02:55.731286312 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/ptrace.c +--- uml-linux-2.6.7/arch/um/kernel/ptrace.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.536315952 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/ptrace.c 2004-06-29 21:02:55.731286312 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/reboot.c +--- uml-linux-2.6.7/arch/um/kernel/reboot.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.537315800 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/reboot.c 2004-06-29 21:02:55.732286160 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/sigio_kern.c +--- uml-linux-2.6.7/arch/um/kernel/sigio_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.539315496 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/sigio_kern.c 2004-06-29 21:02:55.732286160 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/sigio_user.c +--- uml-linux-2.6.7/arch/um/kernel/sigio_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.540315344 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/sigio_user.c 2004-06-29 21:02:55.733286008 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/signal_kern.c +--- uml-linux-2.6.7/arch/um/kernel/signal_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.541315192 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/signal_kern.c 2004-06-29 21:02:55.733286008 +0200 +@@ -36,7 +36,7 @@ static void force_segv(int sig) + if(sig == SIGSEGV){ + struct k_sigaction *ka; + +- ka = ¤t->sig->action[SIGSEGV - 1]; ++ ka = ¤t->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 = ¤t->sig->action[sig -1 ]; ++ ka = ¤t->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(¤t->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(¤t->thread.regs)); +- void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); ++ void __user *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs)); ++ void __user *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); + int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); + + spin_lock_irq(¤t->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(¤t->thread.regs)); +- void *fp; ++ unsigned long sp = PT_REGS_SP(¤t->thread.regs); ++ struct ucontext __user *uc = sp_to_uc(sp); + int sig_size = _NSIG_WORDS * sizeof(unsigned long); + + spin_lock_irq(¤t->sighand->siglock); +@@ -266,7 +305,6 @@ int sys_rt_sigreturn(struct pt_regs regs + sigdelsetmask(¤t->blocked, ~_BLOCKABLE); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); +- fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext)); + copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, + &signal_frame_si.common.arch); + return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); +diff -puN arch/um/kernel/skas/include/mode.h~Main-uml-patch-no-skas arch/um/kernel/skas/include/mode.h +--- uml-linux-2.6.7/arch/um/kernel/skas/include/mode.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.542315040 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/include/mode.h 2004-06-29 21:02:55.733286008 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/include/skas.h +--- uml-linux-2.6.7/arch/um/kernel/skas/include/skas.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.543314888 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/include/skas.h 2004-06-29 21:02:55.733286008 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/include/uaccess.h +--- uml-linux-2.6.7/arch/um/kernel/skas/include/uaccess.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.555313064 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/include/uaccess.h 2004-06-29 21:02:55.734285856 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/Makefile +--- uml-linux-2.6.7/arch/um/kernel/skas/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.557312760 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/Makefile 2004-06-29 21:02:55.734285856 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/mem_user.c +--- uml-linux-2.6.7/arch/um/kernel/skas/mem_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.558312608 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/mem_user.c 2004-06-29 21:02:55.734285856 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/mmu.c +--- uml-linux-2.6.7/arch/um/kernel/skas/mmu.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.559312456 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/mmu.c 2004-06-29 21:02:55.735285704 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/process.c +--- uml-linux-2.6.7/arch/um/kernel/skas/process.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.560312304 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/process.c 2004-06-29 21:02:55.735285704 +0200 +@@ -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, ©, 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~Main-uml-patch-no-skas arch/um/kernel/skas/process_kern.c +--- uml-linux-2.6.7/arch/um/kernel/skas/process_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.561312152 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/process_kern.c 2004-06-29 21:02:55.736285552 +0200 +@@ -61,11 +61,13 @@ void new_thread_handler(int sig) + thread_wait(¤t->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, ¤t->thread.exec_buf); + if(n == 1) + userspace(¤t->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(¤t->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~Main-uml-patch-no-skas arch/um/kernel/skas/syscall_kern.c +--- uml-linux-2.6.7/arch/um/kernel/skas/syscall_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.562312000 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/syscall_kern.c 2004-06-29 21:02:55.736285552 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/syscall_user.c +--- uml-linux-2.6.7/arch/um/kernel/skas/syscall_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.563311848 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/syscall_user.c 2004-06-29 21:02:55.736285552 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/sys-i386/Makefile +--- uml-linux-2.6.7/arch/um/kernel/skas/sys-i386/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.564311696 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/sys-i386/Makefile 2004-06-29 21:02:55.736285552 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/sys-i386/sigcontext.c +--- uml-linux-2.6.7/arch/um/kernel/skas/sys-i386/sigcontext.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.566311392 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/sys-i386/sigcontext.c 2004-06-29 21:02:55.737285400 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/trap_user.c +--- uml-linux-2.6.7/arch/um/kernel/skas/trap_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.567311240 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/trap_user.c 2004-06-29 21:02:55.737285400 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/uaccess.c 2004-06-29 21:02:55.737285400 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/util/Makefile +--- uml-linux-2.6.7/arch/um/kernel/skas/util/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.568311088 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/util/Makefile 2004-06-29 21:02:55.737285400 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/skas/util/mk_ptregs.c +--- uml-linux-2.6.7/arch/um/kernel/skas/util/mk_ptregs.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.569310936 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/skas/util/mk_ptregs.c 2004-06-29 21:02:55.738285248 +0200 +@@ -1,3 +1,4 @@ ++#include <stdio.h> + #include <asm/ptrace.h> + #include <asm/user.h> + +diff -puN arch/um/kernel/smp.c~Main-uml-patch-no-skas arch/um/kernel/smp.c +--- uml-linux-2.6.7/arch/um/kernel/smp.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.571310632 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/smp.c 2004-06-29 21:02:55.738285248 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/syscall_kern.c +--- uml-linux-2.6.7/arch/um/kernel/syscall_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.572310480 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/syscall_kern.c 2004-06-29 21:02:55.739285096 +0200 +@@ -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(¤t->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~Main-uml-patch-no-skas arch/um/kernel/sys_call_table.c +--- uml-linux-2.6.7/arch/um/kernel/sys_call_table.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.573310328 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/sys_call_table.c 2004-06-29 21:02:55.740284944 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/sysrq.c +--- uml-linux-2.6.7/arch/um/kernel/sysrq.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.574310176 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/sysrq.c 2004-06-29 21:02:55.740284944 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tempfile.c +--- uml-linux-2.6.7/arch/um/kernel/tempfile.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.575310024 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tempfile.c 2004-06-29 21:02:55.740284944 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/time.c +--- uml-linux-2.6.7/arch/um/kernel/time.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.576309872 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/time.c 2004-06-29 21:02:55.741284792 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/time_kern.c +--- uml-linux-2.6.7/arch/um/kernel/time_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.577309720 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/time_kern.c 2004-06-29 21:02:55.741284792 +0200 +@@ -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(®s); + } + +-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~Main-uml-patch-no-skas arch/um/kernel/trap_kern.c +--- uml-linux-2.6.7/arch/um/kernel/trap_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.590307744 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/trap_kern.c 2004-06-29 21:02:55.741284792 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/trap_user.c +--- uml-linux-2.6.7/arch/um/kernel/trap_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.591307592 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/trap_user.c 2004-06-29 21:02:55.742284640 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/exec_kern.c +--- uml-linux-2.6.7/arch/um/kernel/tt/exec_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.592307440 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/exec_kern.c 2004-06-29 21:02:55.742284640 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/include/mode.h +--- uml-linux-2.6.7/arch/um/kernel/tt/include/mode.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.593307288 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/include/mode.h 2004-06-29 21:02:55.742284640 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/include/uaccess.h +--- uml-linux-2.6.7/arch/um/kernel/tt/include/uaccess.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.594307136 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/include/uaccess.h 2004-06-29 21:02:55.743284488 +0200 +@@ -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, +- ¤t->thread.fault_addr, +- ¤t->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, +- ¤t->thread.fault_addr, +- ¤t->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, +- ¤t->thread.fault_addr, +- ¤t->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, +- ¤t->thread.fault_addr, +- ¤t->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, +- ¤t->thread.fault_addr, +- ¤t->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, +- ¤t->thread.fault_addr, +- ¤t->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~Main-uml-patch-no-skas arch/um/kernel/tt/Makefile +--- uml-linux-2.6.7/arch/um/kernel/tt/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.595306984 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/Makefile 2004-06-29 21:02:55.743284488 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/mem_user.c +--- uml-linux-2.6.7/arch/um/kernel/tt/mem_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.597306680 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/mem_user.c 2004-06-29 21:02:55.743284488 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/process_kern.c +--- uml-linux-2.6.7/arch/um/kernel/tt/process_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.598306528 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/process_kern.c 2004-06-29 21:02:55.744284336 +0200 +@@ -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(¤t->thread.regs.regs) = (void *) (&sig + 1); ++ disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | ++ (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); ++ SC_SIGMASK(UPT_SC(¤t->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, ¤t->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(¤t->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~Main-uml-patch-no-skas arch/um/kernel/tt/ptproxy/Makefile +--- uml-linux-2.6.7/arch/um/kernel/tt/ptproxy/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.599306376 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/ptproxy/Makefile 2004-06-29 21:02:55.744284336 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/ptproxy/proxy.c +--- uml-linux-2.6.7/arch/um/kernel/tt/ptproxy/proxy.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.600306224 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/ptproxy/proxy.c 2004-06-29 21:02:55.744284336 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/ptproxy/sysdep.c +--- uml-linux-2.6.7/arch/um/kernel/tt/ptproxy/sysdep.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.601306072 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/ptproxy/sysdep.c 2004-06-29 21:02:55.744284336 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/ptproxy/wait.c +--- uml-linux-2.6.7/arch/um/kernel/tt/ptproxy/wait.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.602305920 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/ptproxy/wait.c 2004-06-29 21:02:55.745284184 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/syscall_kern.c +--- uml-linux-2.6.7/arch/um/kernel/tt/syscall_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.603305768 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/syscall_kern.c 2004-06-29 21:02:55.745284184 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/syscall_user.c +--- uml-linux-2.6.7/arch/um/kernel/tt/syscall_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.604305616 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/syscall_user.c 2004-06-29 21:02:55.745284184 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/sys-i386/Makefile +--- uml-linux-2.6.7/arch/um/kernel/tt/sys-i386/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.605305464 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/sys-i386/Makefile 2004-06-29 21:02:55.745284184 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/tlb.c +--- uml-linux-2.6.7/arch/um/kernel/tt/tlb.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.606305312 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/tlb.c 2004-06-29 21:02:55.746284032 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/tracer.c +--- uml-linux-2.6.7/arch/um/kernel/tt/tracer.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.608305008 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/tracer.c 2004-06-29 21:02:55.746284032 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/uaccess.c 2004-06-29 21:02:55.746284032 +0200 +@@ -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, ¤t->thread.fault_addr, ++ ¤t->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, ¤t->thread.fault_addr, ++ ¤t->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, ++ ¤t->thread.fault_addr, ++ ¤t->thread.fault_catcher); ++ if(n < 0) return(-EFAULT); ++ return(n); ++} ++ ++int __clear_user_tt(void *mem, int len) ++{ ++ return(__do_clear_user(mem, len, ++ ¤t->thread.fault_addr, ++ ¤t->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, ¤t->thread.fault_addr, ++ ¤t->thread.fault_catcher)); ++} ++ ++int strnlen_user_tt(const void *str, int len) ++{ ++ return(__do_strnlen_user(str, len, ++ ¤t->thread.fault_addr, ++ ¤t->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~Main-uml-patch-no-skas arch/um/kernel/tt/uaccess_user.c +--- uml-linux-2.6.7/arch/um/kernel/tt/uaccess_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.609304856 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/uaccess_user.c 2004-06-29 21:02:55.747283880 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tt/unmap.c +--- uml-linux-2.6.7/arch/um/kernel/tt/unmap.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.610304704 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tt/unmap.c 2004-06-29 21:02:55.747283880 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/tty_log.c +--- uml-linux-2.6.7/arch/um/kernel/tty_log.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.611304552 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/tty_log.c 2004-06-29 21:02:55.747283880 +0200 +@@ -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, ¤t_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(write(fd, buf, len)); ++ ++ 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)); ++ } ++} ++ ++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~Main-uml-patch-no-skas arch/um/kernel/uaccess_user.c +--- uml-linux-2.6.7/arch/um/kernel/uaccess_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.612304400 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/uaccess_user.c 2004-06-29 21:02:55.747283880 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/um_arch.c +--- uml-linux-2.6.7/arch/um/kernel/um_arch.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.614304096 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/um_arch.c 2004-06-29 21:02:55.748283728 +0200 +@@ -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', ¤t->thread.regs, NULL, NULL); ++ handle_sysrq('p', ¤t->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~Main-uml-patch-no-skas arch/um/kernel/umid.c +--- uml-linux-2.6.7/arch/um/kernel/umid.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.615303944 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/umid.c 2004-06-29 21:02:55.749283576 +0200 +@@ -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~Main-uml-patch-no-skas /dev/null +--- uml-linux-2.6.7/arch/um/kernel/user_syms.c ++++ /dev/null 1970-01-01 01:00:00.000000000 +0100 +@@ -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~Main-uml-patch-no-skas arch/um/kernel/user_util.c +--- uml-linux-2.6.7/arch/um/kernel/user_util.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.617303640 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/kernel/user_util.c 2004-06-29 21:02:55.749283576 +0200 +@@ -5,7 +5,6 @@ + + #include <stdio.h> + #include <stdlib.h> +-#include <fcntl.h> + #include <unistd.h> + #include <limits.h> + #include <sys/mman.h> +@@ -82,7 +81,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; +@@ -119,17 +119,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~Main-uml-patch-no-skas arch/um/main.c +--- uml-linux-2.6.7/arch/um/main.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.618303488 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/main.c 2004-06-29 21:02:55.750283424 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/Makefile +--- uml-linux-2.6.7/arch/um/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.631301512 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/Makefile 2004-06-29 21:02:55.750283424 +0200 +@@ -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)) ] ) + +-AFLAGS_vmlinux.lds.o = -U$(SUBARCH) \ ++AFLAGS_vmlinux.lds.o = $(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)) + +-AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum ++export AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -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.s \ +- $(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 ++export SUBARCH USER_CFLAGS OS +diff -puN arch/um/Makefile-i386~Main-uml-patch-no-skas arch/um/Makefile-i386 +--- uml-linux-2.6.7/arch/um/Makefile-i386~Main-uml-patch-no-skas 2004-06-29 21:02:55.632301360 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/Makefile-i386 2004-06-29 21:02:55.750283424 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/Makefile-skas +--- uml-linux-2.6.7/arch/um/Makefile-skas~Main-uml-patch-no-skas 2004-06-29 21:02:55.633301208 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/Makefile-skas 2004-06-29 21:02:55.750283424 +0200 +@@ -14,7 +14,7 @@ MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/ + LINK_SKAS = -Wl,-rpath,/lib + LD_SCRIPT_SKAS = dyn.lds.s + +-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~Main-uml-patch-no-skas arch/um/os-Linux/drivers/ethertap_kern.c +--- uml-linux-2.6.7/arch/um/os-Linux/drivers/ethertap_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.634301056 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/os-Linux/drivers/ethertap_kern.c 2004-06-29 21:02:55.751283272 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/os-Linux/drivers/ethertap_user.c +--- uml-linux-2.6.7/arch/um/os-Linux/drivers/ethertap_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.635300904 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/os-Linux/drivers/ethertap_user.c 2004-06-29 21:02:55.751283272 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/os-Linux/drivers/tuntap_user.c +--- uml-linux-2.6.7/arch/um/os-Linux/drivers/tuntap_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.637300600 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/os-Linux/drivers/tuntap_user.c 2004-06-29 21:02:55.752283120 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/os-Linux/file.c +--- uml-linux-2.6.7/arch/um/os-Linux/file.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.638300448 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/os-Linux/file.c 2004-06-29 21:02:55.752283120 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/os-Linux/Makefile +--- uml-linux-2.6.7/arch/um/os-Linux/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.639300296 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/os-Linux/Makefile 2004-06-29 21:02:55.752283120 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/os-Linux/process.c +--- uml-linux-2.6.7/arch/um/os-Linux/process.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.640300144 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/os-Linux/process.c 2004-06-29 21:02:55.753282968 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/os-Linux/tty.c +--- uml-linux-2.6.7/arch/um/os-Linux/tty.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.641299992 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/os-Linux/tty.c 2004-06-29 21:02:55.753282968 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/os-Linux/user_syms.c 2004-06-29 21:02:55.753282968 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/sys-i386/bugs.c +--- uml-linux-2.6.7/arch/um/sys-i386/bugs.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.642299840 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/sys-i386/bugs.c 2004-06-29 21:02:55.754282816 +0200 +@@ -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~Main-uml-patch-no-skas /dev/null +--- uml-linux-2.6.7/arch/um/sys-i386/extable.c ++++ /dev/null 1970-01-01 01:00:00.000000000 +0100 +@@ -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~Main-uml-patch-no-skas arch/um/sys-i386/fault.c +--- uml-linux-2.6.7/arch/um/sys-i386/fault.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.645299384 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/sys-i386/fault.c 2004-06-29 21:02:55.754282816 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/sys-i386/Makefile +--- uml-linux-2.6.7/arch/um/sys-i386/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.646299232 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/sys-i386/Makefile 2004-06-29 21:02:55.755282664 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/sys-i386/ptrace_user.c +--- uml-linux-2.6.7/arch/um/sys-i386/ptrace_user.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.647299080 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/sys-i386/ptrace_user.c 2004-06-29 21:02:55.755282664 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/arch/um/sys-i386/time.c 2004-06-29 21:02:55.755282664 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/sys-i386/util/Makefile +--- uml-linux-2.6.7/arch/um/sys-i386/util/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.648298928 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/sys-i386/util/Makefile 2004-06-29 21:02:55.755282664 +0200 +@@ -1,15 +1,10 @@ ++host-progs := mk_sc mk_thread ++always := $(host-progs) + +-host-progs := mk_sc +-always := $(host-progs) mk_thread +-targets := mk_thread_kern.o mk_thread_user.o ++mk_thread-objs := mk_thread_kern.o mk_thread_user.o + +-mk_sc-objs := mk_sc.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~Main-uml-patch-no-skas arch/um/sys-i386/util/mk_sc.c +--- uml-linux-2.6.7/arch/um/sys-i386/util/mk_sc.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.649298776 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/sys-i386/util/mk_sc.c 2004-06-29 21:02:55.755282664 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/sys-ia64/Makefile +--- uml-linux-2.6.7/arch/um/sys-ia64/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.650298624 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/sys-ia64/Makefile 2004-06-29 21:02:55.756282512 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/sys-ppc/Makefile +--- uml-linux-2.6.7/arch/um/sys-ppc/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.652298320 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/sys-ppc/Makefile 2004-06-29 21:02:55.756282512 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/uml.lds.S +--- uml-linux-2.6.7/arch/um/uml.lds.S~Main-uml-patch-no-skas 2004-06-29 21:02:55.653298168 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/uml.lds.S 2004-06-29 21:02:55.756282512 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/util/Makefile +--- uml-linux-2.6.7/arch/um/util/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.654298016 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/util/Makefile 2004-06-29 21:02:55.756282512 +0200 +@@ -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~Main-uml-patch-no-skas arch/um/util/mk_constants_kern.c +--- uml-linux-2.6.7/arch/um/util/mk_constants_kern.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.655297864 +0200 ++++ uml-linux-2.6.7-paolo/arch/um/util/mk_constants_kern.c 2004-06-29 21:02:55.757282360 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/fs/hostfs/hostfs.h 2004-06-29 21:02:55.757282360 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/fs/hostfs/hostfs_kern.c 2004-06-29 21:02:55.758282208 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/fs/hostfs/hostfs_user.c 2004-06-29 21:02:55.758282208 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/fs/hostfs/Makefile 2004-06-29 21:02:55.759282056 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/fs/hppfs/hppfs_kern.c 2004-06-29 21:02:55.760281904 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/fs/hppfs/Makefile 2004-06-29 21:02:55.760281904 +0200 +@@ -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~Main-uml-patch-no-skas fs/Makefile +--- uml-linux-2.6.7/fs/Makefile~Main-uml-patch-no-skas 2004-06-29 21:02:55.657297560 +0200 ++++ uml-linux-2.6.7-paolo/fs/Makefile 2004-06-29 21:02:55.760281904 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/archparam-i386.h +--- uml-linux-2.6.7/include/asm-um/archparam-i386.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.658297408 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/archparam-i386.h 2004-06-29 21:02:55.760281904 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/common.lds.S +--- uml-linux-2.6.7/include/asm-um/common.lds.S~Main-uml-patch-no-skas 2004-06-29 21:02:55.659297256 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/common.lds.S 2004-06-29 21:02:55.761281752 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/include/asm-um/cpufeature.h 2004-06-29 21:02:55.761281752 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/current.h +--- uml-linux-2.6.7/include/asm-um/current.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.661296952 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/current.h 2004-06-29 21:02:55.761281752 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/dma-mapping.h +--- uml-linux-2.6.7/include/asm-um/dma-mapping.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.662296800 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/dma-mapping.h 2004-06-29 21:02:55.761281752 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/elf.h +--- uml-linux-2.6.7/include/asm-um/elf.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.663296648 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/elf.h 2004-06-29 21:02:55.762281600 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/fixmap.h +--- uml-linux-2.6.7/include/asm-um/fixmap.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.664296496 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/fixmap.h 2004-06-29 21:02:55.762281600 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/irq.h +--- uml-linux-2.6.7/include/asm-um/irq.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.665296344 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/irq.h 2004-06-29 21:02:55.762281600 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/include/asm-um/local.h 2004-06-29 21:02:55.762281600 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/include/asm-um/module-generic.h 2004-06-29 21:02:55.762281600 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/include/asm-um/module-i386.h 2004-06-29 21:02:55.763281448 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/page.h +--- uml-linux-2.6.7/include/asm-um/page.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.667296040 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/page.h 2004-06-29 21:02:55.763281448 +0200 +@@ -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,25 +28,36 @@ 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 page_to_pfn(struct page *page); +-extern struct page *pfn_to_page(unsigned long pfn); ++extern unsigned long to_phys(void *virt); ++extern void *to_virt(unsigned long phys); + +-extern struct page *phys_to_page(unsigned long phys); ++#define __pa(virt) to_phys((void *) virt) ++#define __va(phys) to_virt((unsigned long) phys) + +-#define virt_to_page(v) (phys_to_page(__pa(v))) ++#define page_to_pfn(page) ((page) - mem_map) ++#define pfn_to_page(pfn) (mem_map + (pfn)) + +-extern struct page *page_mem_map(struct page *page); ++#define phys_to_pfn(p) ((p) >> PAGE_SHIFT) ++#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) + +-#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 + ++extern void arch_free_page(struct page *page, int order); ++#define HAVE_ARCH_FREE_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 include/asm-um/pgtable.h~Main-uml-patch-no-skas include/asm-um/pgtable.h +--- uml-linux-2.6.7/include/asm-um/pgtable.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.668295888 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/pgtable.h 2004-06-29 21:02:55.763281448 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/processor-generic.h +--- uml-linux-2.6.7/include/asm-um/processor-generic.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.669295736 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/processor-generic.h 2004-06-29 21:02:55.764281296 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/processor-i386.h +--- uml-linux-2.6.7/include/asm-um/processor-i386.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.670295584 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/processor-i386.h 2004-06-29 21:02:55.764281296 +0200 +@@ -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 1970-01-01 01:00:00.000000000 +0100 ++++ uml-linux-2.6.7-paolo/include/asm-um/sections.h 2004-06-29 21:02:55.764281296 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/smp.h +--- uml-linux-2.6.7/include/asm-um/smp.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.672295280 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/smp.h 2004-06-29 21:02:55.764281296 +0200 +@@ -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~Main-uml-patch-no-skas /dev/null +--- uml-linux-2.6.7/include/asm-um/smplock.h ++++ /dev/null 1970-01-01 01:00:00.000000000 +0100 +@@ -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~Main-uml-patch-no-skas /dev/null +--- uml-linux-2.6.7/include/asm-um/spinlock.h ++++ /dev/null 1970-01-01 01:00:00.000000000 +0100 +@@ -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~Main-uml-patch-no-skas include/asm-um/system-generic.h +--- uml-linux-2.6.7/include/asm-um/system-generic.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.675294824 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/system-generic.h 2004-06-29 21:02:55.765281144 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/system-i386.h +--- uml-linux-2.6.7/include/asm-um/system-i386.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.676294672 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/system-i386.h 2004-06-29 21:02:55.765281144 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/thread_info.h +--- uml-linux-2.6.7/include/asm-um/thread_info.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.677294520 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/thread_info.h 2004-06-29 21:02:55.765281144 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/timex.h +--- uml-linux-2.6.7/include/asm-um/timex.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.678294368 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/timex.h 2004-06-29 21:02:55.766280992 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/uaccess.h +--- uml-linux-2.6.7/include/asm-um/uaccess.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.680294064 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/uaccess.h 2004-06-29 21:02:55.766280992 +0200 +@@ -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~Main-uml-patch-no-skas include/asm-um/unistd.h +--- uml-linux-2.6.7/include/asm-um/unistd.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.681293912 +0200 ++++ uml-linux-2.6.7-paolo/include/asm-um/unistd.h 2004-06-29 21:02:55.766280992 +0200 +@@ -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~Main-uml-patch-no-skas include/linux/gfp.h +--- uml-linux-2.6.7/include/linux/gfp.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.697291480 +0200 ++++ uml-linux-2.6.7-paolo/include/linux/gfp.h 2004-06-29 21:02:55.766280992 +0200 +@@ -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~Main-uml-patch-no-skas include/linux/time.h +--- uml-linux-2.6.7/include/linux/time.h~Main-uml-patch-no-skas 2004-06-29 21:02:55.698291328 +0200 ++++ uml-linux-2.6.7-paolo/include/linux/time.h 2004-06-29 21:02:55.767280840 +0200 +@@ -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~Main-uml-patch-no-skas mm/page_alloc.c +--- uml-linux-2.6.7/mm/page_alloc.c~Main-uml-patch-no-skas 2004-06-29 21:02:55.699291176 +0200 ++++ uml-linux-2.6.7-paolo/mm/page_alloc.c 2004-06-29 21:02:55.767280840 +0200 +@@ -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); +@@ -497,6 +499,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); +_ |