From c8a7a1a82e66674f081d61db60c3af4e5a281883 Mon Sep 17 00:00:00 2001 From: braam Date: Sun, 4 May 2003 05:04:40 +0000 Subject: [PATCH] - fixes to b_open - new UML patch 2.4.20-4 which works with Red Hat 9 - minor fixes to handling handles in open/close to avoid oopsing - fix erroneous mds_mfd_put in mds_open - fix the CVS tests added to sanity - the tests exposed more problem in this branch, probably related to the lack of a file handle cache. Only good parts of the branch will be merged. --- .../patches/uml-patch-2.4.20-3.patch | 39249 ------------------- .../patches/uml-patch-2.4.20-tmp.patch | 16 - lustre/kernel_patches/series/vanilla-2.4.20 | 3 +- 3 files changed, 1 insertion(+), 39267 deletions(-) delete mode 100644 lustre/kernel_patches/patches/uml-patch-2.4.20-3.patch delete mode 100644 lustre/kernel_patches/patches/uml-patch-2.4.20-tmp.patch diff --git a/lustre/kernel_patches/patches/uml-patch-2.4.20-3.patch b/lustre/kernel_patches/patches/uml-patch-2.4.20-3.patch deleted file mode 100644 index 2a0effb..0000000 --- a/lustre/kernel_patches/patches/uml-patch-2.4.20-3.patch +++ /dev/null @@ -1,39249 +0,0 @@ -diff -Naur -X ../exclude-files orig/CREDITS um/CREDITS ---- orig/CREDITS Thu Feb 27 13:04:11 2003 -+++ um/CREDITS Thu Feb 27 13:05:17 2003 -@@ -432,6 +432,7 @@ - E: lars@nocrew.org - W: http://lars.nocrew.org/ - D: dsp56k device driver -+D: ptrace proxy in user mode kernel port - S: Kopmansg 2 - S: 411 13 Goteborg - S: Sweden -@@ -721,7 +722,7 @@ - E: jdike@karaya.com - W: http://user-mode-linux.sourceforge.net - D: User mode kernel port --S: RR1 Box 67C -+S: 375 Tubbs Hill Rd - S: Deering NH 03244 - S: USA - -diff -Naur -X ../exclude-files orig/Documentation/Configure.help um/Documentation/Configure.help ---- orig/Documentation/Configure.help Thu Feb 27 13:04:11 2003 -+++ um/Documentation/Configure.help Thu Feb 27 13:05:17 2003 -@@ -14690,19 +14690,23 @@ - The module will be called dsbr100.o. If you want to compile it as a - module, say M here and read . - --Always do synchronous disk IO for UBD --CONFIG_BLK_DEV_UBD_SYNC -+CONFIG_BLK_DEV_UBD - The User-Mode Linux port includes a driver called UBD which will let - you access arbitrary files on the host computer as block devices. -- Writes to such a block device are not immediately written to the -- host's disk; this may cause problems if, for example, the User-Mode -- Linux 'Virtual Machine' uses a journalling file system and the host -- computer crashes. -+ Unless you know that you do not need such virtual block devices say -+ Y here. -+ -+Always do synchronous disk IO for UBD -+CONFIG_BLK_DEV_UBD_SYNC -+ Writes to the virtual block device are not immediately written to the host's -+ disk; this may cause problems if, for example, the User-Mode Linux -+ 'Virtual Machine' uses a journalling filesystem and the host computer -+ crashes. - - Synchronous operation (i.e. always writing data to the host's disk - immediately) is configurable on a per-UBD basis by using a special - kernel command line option. Alternatively, you can say Y here to -- turn on synchronous operation by default for all block. -+ turn on synchronous operation by default for all block devices. - - If you're running a journalling file system (like reiserfs, for - example) in your virtual machine, you will want to say Y here. If -@@ -14714,6 +14718,7 @@ - CONFIG_PT_PROXY - This option enables a debugging interface which allows gdb to debug - the kernel without needing to actually attach to kernel threads. -+ CONFIG_XTERM_CHAN must be enabled in order to enable CONFIG_PT_PROXY. - If you want to do kernel debugging, say Y here; otherwise say N. - - Management console -@@ -14908,25 +14913,173 @@ - - SLIP transport - CONFIG_UML_NET_SLIP -- The Slip User-Mode Linux network transport allows a running UML to -+ The slip User-Mode Linux network transport allows a running UML to - network with its host over a point-to-point link. Unlike Ethertap, - which can carry any Ethernet frame (and hence even non-IP packets), -- the Slip transport can only carry IP packets. -+ the slip transport can only carry IP packets. - -- To use this, your host must support Slip devices. -+ To use this, your host must support slip devices. - - For more information, see - . That site -- has examples of the UML command line to use to enable Slip -+ has examples of the UML command line to use to enable slip - networking, and details of a few quirks with it. - -- The Ethertap Transport is preferred over Slip because of its -- limitation. If you prefer Slip, however, say Y here. Otherwise -+ The Ethertap Transport is preferred over slip because of its -+ limitations. If you prefer slip, however, say Y here. Otherwise - choose the Multicast transport (to network multiple UMLs on - multiple hosts), Ethertap (to network with the host and the - outside world), and/or the Daemon transport (to network multiple - UMLs on a single host). You may choose more than one without - conflict. If you don't need UML networking, say N. -+ -+SLiRP transport -+CONFIG_UML_NET_SLIRP -+ The SLiRP User-Mode Linux network transport allows a running UML -+ to network by invoking a program that can handle SLIP encapsulated -+ packets. This is commonly (but not limited to) the application -+ known as SLiRP, a program that can re-socket IP packets back onto -+ the host on which it is run. Only IP packets are supported, -+ unlike other network transports that can handle all Ethernet -+ frames. In general, slirp allows the UML the same IP connectivity -+ to the outside world that the host user is permitted, and unlike -+ other transports, SLiRP works without the need of root level -+ privleges, setuid binaries, or SLIP devices on the host. This -+ also means not every type of connection is possible, but most -+ situations can be accomodated with carefully crafted slirp -+ commands that can be passed along as part of the network device's -+ setup string. The effect of this transport on the UML is similar -+ that of a host behind a firewall that masquerades all network -+ connections passing through it (but is less secure). -+ -+ To use this you should first have slirp compiled somewhere -+ accessible on the host, and have read its documentation. If you -+ don't need UML networking, say N. -+ -+ Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp" -+ -+Default main console channel initialization -+CONFIG_CON_ZERO_CHAN -+ This is the string describing the channel to which the main console -+ will be attached by default. This value can be overridden from the -+ command line. The default value is "fd:0,fd:1", which attaches the -+ main console to stdin and stdout. -+ It is safe to leave this unchanged. -+ -+Default console channel initialization -+CONFIG_CON_CHAN -+ This is the string describing the channel to which all consoles -+ except the main console will be attached by default. This value can -+ be overridden from the command line. The default value is "xterm", -+ which brings them up in xterms. -+ It is safe to leave this unchanged, although you may wish to change -+ this if you expect the UML that you build to be run in environments -+ which don't have X or xterm available. -+ -+Default serial line channel initialization -+CONFIG_SSL_CHAN -+ This is the string describing the channel to which the serial lines -+ will be attached by default. This value can be overridden from the -+ command line. The default value is "pty", which attaches them to -+ traditional pseudo-terminals. -+ It is safe to leave this unchanged, although you may wish to change -+ this if you expect the UML that you build to be run in environments -+ which don't have a set of /dev/pty* devices. -+ -+Nesting level -+CONFIG_NEST_LEVEL -+ This is set to the number of layers of UMLs that this UML will be run -+ in. Normally, this is zero, meaning that it will run directly on the -+ host. Setting it to one will build a UML that can run inside a UML -+ that is running on the host. Generally, if you intend this UML to run -+ inside another UML, set CONFIG_NEST_LEVEL to one more than the host UML. -+ Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to -+ greater than one, then the guest UML should have its CONFIG_NEST_LEVEL -+ set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS. -+ Only change this if you are running nested UMLs. -+ -+Kernel address space size (in .5G units) -+CONFIG_KERNEL_HALF_GIGS -+ This determines the amount of address space that UML will allocate for -+ its own, measured in half Gigabyte units. The default is 1. -+ Change this only if you need to boot UML with an unusually large amount -+ of physical memory. -+ -+UML sound support -+CONFIG_UML_SOUND -+ This option enables UML sound support. If enabled, it will pull in -+ soundcore and the UML hostaudio relay, which acts as a intermediary -+ between the host's dsp and mixer devices and the UML sound system. -+ It is safe to say 'Y' here. -+ -+UML SMP support -+CONFIG_UML_SMP -+ This option enables UML SMP support. UML implements virtual SMP by -+ allowing as many processes to run simultaneously on the host as -+ there are virtual processors configured. Obviously, if the host is -+ a uniprocessor, those processes will timeshare, but, inside UML, -+ will appear to be running simultaneously. If the host is a -+ multiprocessor, then UML processes may run simultaneously, depending -+ on the host scheduler. -+ CONFIG_SMP will be set to whatever this option is set to. -+ It is safe to leave this unchanged. -+ -+file descriptor channel support -+CONFIG_FD_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to already set up file descriptors. Generally, the main -+ console is attached to file descriptors 0 and 1 (stdin and stdout), -+ so it would be wise to leave this enabled unless you intend to -+ attach it to some other host device. -+ -+null device channel support -+CONFIG_NULL_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to a device similar to /dev/null. Data written to it disappears -+ and there is never any data to be read. -+ -+port channel support -+CONFIG_PORT_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host portals. They may be accessed with 'telnet -+ '. Any number of consoles and serial lines may be -+ attached to a single portal, although what UML device you get when -+ you telnet to that portal will be unpredictable. -+ It is safe to say 'Y' here. -+ -+pty channel support -+CONFIG_PTY_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host pseudo-terminals. Access to both traditional -+ pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled -+ with this option. The assignment of UML devices to host devices -+ will be announced in the kernel message log. -+ It is safe to say 'Y' here. -+ -+tty channel support -+CONFIG_TTY_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host terminals. Access to both virtual consoles -+ (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and -+ /dev/pts/*) are controlled by this option. -+ It is safe to say 'Y' here. -+ -+xterm channel support -+CONFIG_XTERM_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to xterms. Each UML device so assigned will be brought up in -+ its own xterm. -+ If you disable this option, then CONFIG_PT_PROXY will be disabled as -+ well, since UML's gdb currently requires an xterm. -+ It is safe to say 'Y' here. -+ -+tty logging -+CONFIG_TTY_LOG -+ This option enables logging of all data going through pseudo-terminals -+ to the host. This is primarily useful for honeypots, where you want -+ secure keystroke logging that can't be detected or disabled by root. -+ Say 'N' unless you are setting up a UML honeypot or otherwise know that -+ you want this option. - - Microtek USB scanner support - CONFIG_USB_MICROTEK -diff -Naur -X ../exclude-files orig/MAINTAINERS um/MAINTAINERS ---- orig/MAINTAINERS Thu Feb 27 13:04:12 2003 -+++ um/MAINTAINERS Thu Feb 27 13:05:17 2003 -@@ -1841,6 +1841,14 @@ - L: linux-usb-devel@lists.sourceforge.net - W: http://usb.in.tum.de - S: Maintained -+ -+USER-MODE PORT -+P: Jeff Dike -+M: jdike@karaya.com -+L: user-mode-linux-devel@lists.sourceforge.net -+L: user-mode-linux-user@lists.sourceforge.net -+W: http://user-mode-linux.sourceforge.net -+S: Maintained - - USB "USBNET" DRIVER - P: David Brownell -diff -Naur -X ../exclude-files orig/Makefile um/Makefile ---- orig/Makefile Thu Feb 27 13:04:12 2003 -+++ um/Makefile Thu Feb 27 13:05:17 2003 -@@ -5,7 +5,15 @@ - - KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) - --ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) -+# SUBARCH tells the usermode build what the underlying arch is. That is set -+# first, and if a usermode build is happening, the "ARCH=um" on the command -+# line overrides the setting of ARCH below. If a native build is happening, -+# then ARCH is assigned, getting whatever value it gets normally, and -+# SUBARCH is subsequently ignored. -+ -+SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) -+ARCH := $(SUBARCH) -+ - KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") - - CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ -diff -Naur -X ../exclude-files orig/arch/um/Makefile um/arch/um/Makefile ---- orig/arch/um/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/Makefile Mon Mar 24 16:48:47 2003 -@@ -0,0 +1,168 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+OS := $(shell uname -s) -+ -+ARCH_DIR = arch/um -+ -+core-y := kernel sys-$(SUBARCH) os-$(OS) -+drivers-y := fs drivers -+subdir-y := $(core-y) $(drivers-y) -+SUBDIRS += $(foreach dir,$(subdir-y),$(ARCH_DIR)/$(dir)) -+ -+CORE_FILES += $(foreach dir,$(core-y),$(ARCH_DIR)/$(dir)/built-in.o) -+DRIVERS += $(foreach dir,$(drivers-y),$(ARCH_DIR)/$(dir)/built-in.o) -+ -+include $(ARCH_DIR)/Makefile-$(SUBARCH) -+include $(ARCH_DIR)/Makefile-os-$(OS) -+ -+MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt -+MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas -+ -+ifneq ($(MAKEFILE-y),) -+ include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y)) -+endif -+ -+EXTRAVERSION := $(EXTRAVERSION)-3um -+ -+include/linux/version.h: arch/$(ARCH)/Makefile -+ -+# Recalculate MODLIB to reflect the EXTRAVERSION changes (via KERNELRELEASE) -+# The way the toplevel Makefile is written EXTRAVERSION is not supposed -+# to be changed outside the toplevel Makefile, but recalculating MODLIB is -+# a sufficient workaround until we no longer need architecture dependent -+# EXTRAVERSION... -+MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) -+ -+ifeq ($(CONFIG_DEBUGSYM),y) -+CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -+endif -+ -+CFLAGS-$(CONFIG_DEBUGSYM) += -g -+ -+ARCH_INCLUDE = -I$(TOPDIR)/$(ARCH_DIR)/include -+ -+# -Derrno=kernel_errno - This turns all kernel references to errno into -+# kernel_errno to separate them from the libc errno. This allows -fno-common -+# in CFLAGS. Otherwise, it would cause ld to complain about the two different -+# errnos. -+ -+CFLAGS += $(ARCH_CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ -+ -D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \ -+ $(MODE_INCLUDE) -+ -+LINKFLAGS += -r -+ -+LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc -+ -+SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) -+ -+# These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT + -+# CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case. -+ -+LINK_TT = -static -+LD_SCRIPT_TT := link.ld -+ -+ifeq ($(CONFIG_STATIC_LINK),y) -+ LINK-y += $(LINK_TT) -+ LD_SCRIPT-y := $(LD_SCRIPT_TT) -+else -+ifeq ($(CONFIG_MODE_TT),y) -+ LINK-y += $(LINK_TT) -+ LD_SCRIPT-y := $(LD_SCRIPT_TT) -+else -+ifeq ($(CONFIG_MODE_SKAS),y) -+ LINK-y += $(LINK_SKAS) -+ LD_SCRIPT-y := $(LD_SCRIPT_SKAS) -+endif -+endif -+endif -+ -+LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y) -+M4_MODE_TT := $(shell [ "$(CONFIG_MODE_TT)" = "y" ] && echo -DMODE_TT) -+ -+$(LD_SCRIPT-y): $(LD_SCRIPT-y).in -+ pages=$$(( 1 << $(CONFIG_KERNEL_STACK_ORDER) )) ; \ -+ m4 -DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \ -+ -DELF_FORMAT=$(ELF_FORMAT) $(M4_MODE_TT) \ -+ -DKERNEL_STACK_SIZE=$$(( 4096 * $$pages )) $< > $@ -+ -+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 -+ -+ARCH_SYMLINKS = include/asm-um/arch arch/um/include/sysdep arch/um/os \ -+ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h -+ -+ifeq ($(CONFIG_MODE_SKAS), y) -+$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h -+endif -+ -+GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h -+ -+setup: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) -+ -+linux: setup $(ARCH_DIR)/main.o vmlinux $(LD_SCRIPT-y) -+ mv vmlinux vmlinux.o -+ $(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \ -+ -o linux $(ARCH_DIR)/main.o vmlinux.o -L/usr/lib -lutil -+ -+USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) -+USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(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 -+ -+CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/link.ld $(ARCH_DIR)/dyn_link.ld \ -+ $(GEN_HEADERS) $(ARCH_DIR)/include/uml-config.h -+ -+$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c -+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< -+ -+archmrproper: -+ rm -f $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \ -+ $(LD_SCRIPT) $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) -+ -+archclean: sysclean -+ find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ -+ -o -name '*.gcov' \) -type f -print | xargs rm -f -+ cd $(ARCH_DIR) ; \ -+ for dir in $(subdir-y) util ; do $(MAKE) -C $$dir clean; done -+ -+archdep: -+ -+$(SYMLINK_HEADERS): -+ cd $(TOPDIR)/$(dir $@) ; \ -+ ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@) -+ -+include/asm-um/arch: -+ cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch -+ -+arch/um/include/sysdep: -+ cd $(TOPDIR)/arch/um/include && ln -sf sysdep-$(SUBARCH) sysdep -+ -+arch/um/os: -+ cd $(ARCH_DIR) && ln -sf os-$(OS) os -+ -+$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task -+ $< > $@ -+ -+$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants -+ $< > $@ -+ -+$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h -+ sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@ -+ -+$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/util/mk_task_user.c \ -+ $(ARCH_DIR)/util/mk_task_kern.c $(SYS_HEADERS) -+ $(MAKE) $(MFLAGS) -C $(ARCH_DIR)/util mk_task -+ -+$(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util/mk_constants_user.c \ -+ $(ARCH_DIR)/util/mk_constants_kern.c -+ $(MAKE) $(MFLAGS) -C $(ARCH_DIR)/util mk_constants -+ -+export SUBARCH USER_CFLAGS OS -diff -Naur -X ../exclude-files orig/arch/um/Makefile-i386 um/arch/um/Makefile-i386 ---- orig/arch/um/Makefile-i386 Wed Dec 31 19:00:00 1969 -+++ um/arch/um/Makefile-i386 Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,35 @@ -+ifeq ($(CONFIG_HOST_2G_2G), y) -+TOP_ADDR = 0x80000000 -+else -+TOP_ADDR = 0xc0000000 -+endif -+ -+ARCH_CFLAGS = -U__$(SUBARCH)__ -U$(SUBARCH) -DUM_FASTCALL -+ELF_ARCH = $(SUBARCH) -+ELF_FORMAT = elf32-$(SUBARCH) -+ -+I386_H = $(ARCH_DIR)/include/sysdep-i386 -+SYS = $(ARCH_DIR)/sys-i386 -+UTIL = $(SYS)/util -+SUBDIRS += $(UTIL) -+ -+SYS_HEADERS = $(I386_H)/sc.h $(I386_H)/thread.h -+ -+$(I386_H)/sc.h : $(UTIL)/mk_sc -+ $(UTIL)/mk_sc > $@ -+ -+$(I386_H)/thread.h : $(UTIL)/mk_thread -+ $(UTIL)/mk_thread > $@ -+ -+$(UTIL)/mk_sc : $(UTIL)/mk_sc.c -+ $(MAKE) -C $(UTIL) mk_sc -+ -+$(UTIL)/mk_thread : $(UTIL)/mk_thread_user.c $(UTIL)/mk_thread_kern.c \ -+ $(I386_H)/sc.h -+ $(MAKE) -C $(UTIL) mk_thread -+ -+sysclean : -+ rm -f $(SYS_HEADERS) -+ $(MAKE) -C $(UTIL) clean -+ $(MAKE) -C $(SYS) clean -+ -diff -Naur -X ../exclude-files orig/arch/um/Makefile-ia64 um/arch/um/Makefile-ia64 ---- orig/arch/um/Makefile-ia64 Wed Dec 31 19:00:00 1969 -+++ um/arch/um/Makefile-ia64 Wed Oct 23 21:08:04 2002 -@@ -0,0 +1 @@ -+START_ADDR = 0x1000000000000000 -diff -Naur -X ../exclude-files orig/arch/um/Makefile-os-Linux um/arch/um/Makefile-os-Linux ---- orig/arch/um/Makefile-os-Linux Wed Dec 31 19:00:00 1969 -+++ um/arch/um/Makefile-os-Linux Mon Dec 9 14:21:51 2002 -@@ -0,0 +1,7 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+SUBDIRS += $(ARCH_DIR)/os-$(OS)/drivers -+DRIVERS += $(ARCH_DIR)/os-$(OS)/drivers/drivers.o -diff -Naur -X ../exclude-files orig/arch/um/Makefile-ppc um/arch/um/Makefile-ppc ---- orig/arch/um/Makefile-ppc Wed Dec 31 19:00:00 1969 -+++ um/arch/um/Makefile-ppc Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,9 @@ -+ifeq ($(CONFIG_HOST_2G_2G), y) -+START_ADDR = 0x80000000 -+else -+START_ADDR = 0xc0000000 -+endif -+ARCH_CFLAGS = -U__powerpc__ -D__UM_PPC__ -+ -+# The arch is ppc, but the elf32 name is powerpc -+ELF_SUBARCH = powerpc -diff -Naur -X ../exclude-files orig/arch/um/Makefile-skas um/arch/um/Makefile-skas ---- orig/arch/um/Makefile-skas Wed Dec 31 19:00:00 1969 -+++ um/arch/um/Makefile-skas Sun Dec 15 22:02:57 2002 -@@ -0,0 +1,20 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+PROFILE += -pg -+ -+CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage -+CFLAGS-$(CONFIG_GPROF) += $(PROFILE) -+LINK-$(CONFIG_GPROF) += $(PROFILE) -+ -+MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/skas/include -+ -+LINK_SKAS = -Wl,-rpath,/lib -+LD_SCRIPT_SKAS = dyn_link.ld -+ -+GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h -+ -+$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h : -+ $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h -diff -Naur -X ../exclude-files orig/arch/um/Makefile-tt um/arch/um/Makefile-tt ---- orig/arch/um/Makefile-tt Wed Dec 31 19:00:00 1969 -+++ um/arch/um/Makefile-tt Mon Dec 16 20:22:23 2002 -@@ -0,0 +1,7 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/tt/include -+ -diff -Naur -X ../exclude-files orig/arch/um/common.ld.in um/arch/um/common.ld.in ---- orig/arch/um/common.ld.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/common.ld.in Tue Feb 4 19:35:13 2003 -@@ -0,0 +1,53 @@ -+ .kstrtab : { *(.kstrtab) } -+ -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ __start___ksymtab = .; /* Kernel symbol table */ -+ __ksymtab : { *(__ksymtab) } -+ __stop___ksymtab = .; -+ -+ .unprotected : { *(.unprotected) } -+ . = ALIGN(4096); -+ PROVIDE (_unprotected_end = .); -+ -+ . = ALIGN(4096); -+ __uml_setup_start = .; -+ .uml.setup.init : { *(.uml.setup.init) } -+ __uml_setup_end = .; -+ __uml_help_start = .; -+ .uml.help.init : { *(.uml.help.init) } -+ __uml_help_end = .; -+ __uml_postsetup_start = .; -+ .uml.postsetup.init : { *(.uml.postsetup.init) } -+ __uml_postsetup_end = .; -+ __setup_start = .; -+ .setup.init : { *(.setup.init) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { *(.initcall.init) } -+ __initcall_end = .; -+ __uml_initcall_start = .; -+ .uml.initcall.init : { *(.uml.initcall.init) } -+ __uml_initcall_end = .; -+ __init_end = .; -+ __exitcall_begin = .; -+ .exitcall : { *(.exitcall.exit) } -+ __exitcall_end = .; -+ __uml_exitcall_begin = .; -+ .uml.exitcall : { *(.uml.exitcall.exit) } -+ __uml_exitcall_end = .; -+ -+ __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 = .; -+ -+ .data.init : { *(.data.init) } -diff -Naur -X ../exclude-files orig/arch/um/config.in um/arch/um/config.in ---- orig/arch/um/config.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/config.in Thu Feb 27 13:12:39 2003 -@@ -0,0 +1,104 @@ -+define_bool CONFIG_USERMODE y -+ -+mainmenu_name "Linux/Usermode Kernel Configuration" -+ -+define_bool CONFIG_ISA n -+define_bool CONFIG_SBUS n -+define_bool CONFIG_PCI n -+ -+define_bool CONFIG_UID16 y -+ -+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y -+ -+mainmenu_option next_comment -+comment 'Code maturity level options' -+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL -+endmenu -+ -+mainmenu_option next_comment -+comment 'General Setup' -+ -+bool 'Separate kernel address space support' CONFIG_MODE_SKAS -+ -+# This is to ensure that at least one of the modes is enabled. When neither -+# is present in defconfig, they default to N, which is bad. -+if [ "$CONFIG_MODE_SKAS" != "y" ]; then -+ define_bool CONFIG_MODE_TT y -+fi -+ -+bool 'Tracing thread support' CONFIG_MODE_TT -+if [ "$CONFIG_MODE_TT" != "y" ]; then -+ bool 'Statically linked binary when CONFIG_MODE_TT is disabled' CONFIG_STATIC_LINK -+fi -+bool 'Networking support' CONFIG_NET -+bool 'System V IPC' CONFIG_SYSVIPC -+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT -+bool 'Sysctl support' CONFIG_SYSCTL -+tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT -+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF -+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -+tristate 'Host filesystem' CONFIG_HOSTFS -+tristate 'Honeypot proc filesystem' CONFIG_HPPFS -+bool 'Management console' CONFIG_MCONSOLE -+dep_bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_MCONSOLE -+bool '2G/2G host address space split' CONFIG_HOST_2G_2G -+bool 'Symmetric multi-processing support' CONFIG_UML_SMP -+define_bool CONFIG_SMP $CONFIG_UML_SMP -+int 'Nesting level' CONFIG_NEST_LEVEL 0 -+int 'Kernel address space size (in .5G units)' CONFIG_KERNEL_HALF_GIGS 1 -+bool 'Highmem support' CONFIG_HIGHMEM -+bool '/proc/mm' CONFIG_PROC_MM -+int 'Kernel stack size order' CONFIG_KERNEL_STACK_ORDER 2 -+endmenu -+ -+mainmenu_option next_comment -+comment 'Loadable module support' -+bool 'Enable loadable module support' CONFIG_MODULES -+if [ "$CONFIG_MODULES" = "y" ]; then -+# MODVERSIONS does not yet work in this architecture -+# bool ' Set version information on all module symbols' CONFIG_MODVERSIONS -+ bool ' Kernel module loader' CONFIG_KMOD -+fi -+endmenu -+ -+source arch/um/config_char.in -+ -+source arch/um/config_block.in -+ -+define_bool CONFIG_NETDEVICES $CONFIG_NET -+ -+if [ "$CONFIG_NET" = "y" ]; then -+ source arch/um/config_net.in -+ source net/Config.in -+fi -+ -+source fs/Config.in -+ -+mainmenu_option next_comment -+comment 'SCSI support' -+ -+tristate 'SCSI support' CONFIG_SCSI -+ -+if [ "$CONFIG_SCSI" != "n" ]; then -+ source arch/um/config_scsi.in -+fi -+endmenu -+ -+source drivers/md/Config.in -+ -+source drivers/mtd/Config.in -+ -+source lib/Config.in -+ -+mainmenu_option next_comment -+comment 'Kernel hacking' -+bool 'Debug memory allocations' CONFIG_DEBUG_SLAB -+bool 'Enable kernel debugging symbols' CONFIG_DEBUGSYM -+if [ "$CONFIG_XTERM_CHAN" = "y" ]; then -+ dep_bool 'Enable ptrace proxy' CONFIG_PT_PROXY $CONFIG_DEBUGSYM -+else -+ define_bool CONFIG_PT_PROXY n -+fi -+dep_bool 'Enable gprof support' CONFIG_GPROF $CONFIG_DEBUGSYM -+dep_bool 'Enable gcov support' CONFIG_GCOV $CONFIG_DEBUGSYM -+endmenu -diff -Naur -X ../exclude-files orig/arch/um/config.release um/arch/um/config.release ---- orig/arch/um/config.release Wed Dec 31 19:00:00 1969 -+++ um/arch/um/config.release Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,302 @@ -+# -+# Automatically generated make config: don't edit -+# -+CONFIG_USERMODE=y -+# CONFIG_ISA is not set -+# CONFIG_SBUS is not set -+# CONFIG_PCI is not set -+CONFIG_UID16=y -+CONFIG_RWSEM_XCHGADD_ALGORITHM=y -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+ -+# -+# General Setup -+# -+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 is not set -+CONFIG_MCONSOLE=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_HOST_2G_2G is not set -+# CONFIG_UML_SMP is not set -+# CONFIG_SMP is not set -+CONFIG_NEST_LEVEL=0 -+CONFIG_KERNEL_HALF_GIGS=1 -+ -+# -+# Loadable module support -+# -+CONFIG_MODULES=y -+CONFIG_KMOD=y -+ -+# -+# Character Devices -+# -+CONFIG_STDIO_CONSOLE=y -+CONFIG_SSL=y -+CONFIG_FD_CHAN=y -+# CONFIG_NULL_CHAN is not set -+CONFIG_PORT_CHAN=y -+CONFIG_PTY_CHAN=y -+CONFIG_TTY_CHAN=y -+CONFIG_XTERM_CHAN=y -+CONFIG_CON_ZERO_CHAN="fd:0,fd:1" -+CONFIG_CON_CHAN="xterm" -+CONFIG_SSL_CHAN="pty" -+CONFIG_UNIX98_PTYS=y -+CONFIG_UNIX98_PTY_COUNT=256 -+# CONFIG_WATCHDOG is not set -+CONFIG_UML_SOUND=y -+CONFIG_SOUND=y -+CONFIG_HOSTAUDIO=y -+# CONFIG_TTY_LOG is not set -+ -+# -+# Block Devices -+# -+CONFIG_BLK_DEV_UBD=y -+# CONFIG_BLK_DEV_UBD_SYNC is not set -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_NBD=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=4096 -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_MMAPPER is not set -+CONFIG_NETDEVICES=y -+ -+# -+# Network Devices -+# -+CONFIG_UML_NET=y -+CONFIG_UML_NET_ETHERTAP=y -+CONFIG_UML_NET_TUNTAP=y -+CONFIG_UML_NET_SLIP=y -+CONFIG_UML_NET_DAEMON=y -+CONFIG_UML_NET_MCAST=y -+CONFIG_DUMMY=y -+CONFIG_BONDING=m -+CONFIG_EQUALIZER=m -+CONFIG_TUN=y -+CONFIG_PPP=m -+CONFIG_PPP_MULTILINK=y -+# CONFIG_PPP_ASYNC is not set -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPPOE=m -+CONFIG_SLIP=m -+ -+# -+# Networking options -+# -+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_INET=y -+# CONFIG_IP_MULTICAST is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set -+# CONFIG_IP_PNP is not set -+# CONFIG_NET_IPIP is not set -+# CONFIG_NET_IPGRE is not set -+# CONFIG_ARPD is not set -+# CONFIG_INET_ECN is not set -+# CONFIG_SYN_COOKIES is not set -+# CONFIG_IPV6 is not set -+# CONFIG_KHTTPD is not set -+# CONFIG_ATM is not set -+# CONFIG_VLAN_8021Q is not set -+ -+# -+# -+# -+# CONFIG_IPX is not set -+# CONFIG_ATALK is not set -+ -+# -+# Appletalk devices -+# -+# CONFIG_DECNET is not set -+# CONFIG_BRIDGE is not set -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_LLC is not set -+# CONFIG_NET_DIVERT is not set -+# CONFIG_ECONET is not set -+# CONFIG_WAN_ROUTER is not set -+# CONFIG_NET_FASTROUTE is not set -+# CONFIG_NET_HW_FLOWCONTROL is not set -+ -+# -+# QoS and/or fair queueing -+# -+# CONFIG_NET_SCHED is not set -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+ -+# -+# File systems -+# -+CONFIG_QUOTA=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_ADFS_FS=m -+# CONFIG_ADFS_FS_RW is not set -+CONFIG_AFFS_FS=m -+CONFIG_HFS_FS=m -+CONFIG_BFS_FS=m -+CONFIG_EXT3_FS=y -+CONFIG_JBD=y -+# CONFIG_JBD_DEBUG is not set -+CONFIG_FAT_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_UMSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_EFS_FS=m -+CONFIG_CRAMFS=m -+CONFIG_TMPFS=y -+CONFIG_RAMFS=y -+CONFIG_ISO9660_FS=y -+# CONFIG_JOLIET is not set -+# CONFIG_ZISOFS is not set -+CONFIG_MINIX_FS=m -+CONFIG_VXFS_FS=m -+# CONFIG_NTFS_FS is not set -+CONFIG_HPFS_FS=m -+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=m -+# CONFIG_QNX4FS_RW is not set -+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 -+ -+# -+# Network File Systems -+# -+# CONFIG_CODA_FS is not set -+# CONFIG_INTERMEZZO_FS is not set -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3=y -+CONFIG_NFSD=y -+CONFIG_NFSD_V3=y -+CONFIG_SUNRPC=y -+CONFIG_LOCKD=y -+CONFIG_LOCKD_V4=y -+# CONFIG_SMB_FS is not set -+# CONFIG_NCP_FS is not set -+# CONFIG_ZISOFS_FS is not set -+CONFIG_ZLIB_FS_INFLATE=m -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+# CONFIG_SMB_NLS is not set -+CONFIG_NLS=y -+ -+# -+# Native Language Support -+# -+CONFIG_NLS_DEFAULT="iso8859-1" -+# CONFIG_NLS_CODEPAGE_437 is not set -+# CONFIG_NLS_CODEPAGE_737 is not set -+# CONFIG_NLS_CODEPAGE_775 is not set -+# CONFIG_NLS_CODEPAGE_850 is not set -+# CONFIG_NLS_CODEPAGE_852 is not set -+# CONFIG_NLS_CODEPAGE_855 is not set -+# CONFIG_NLS_CODEPAGE_857 is not set -+# CONFIG_NLS_CODEPAGE_860 is not set -+# CONFIG_NLS_CODEPAGE_861 is not set -+# CONFIG_NLS_CODEPAGE_862 is not set -+# CONFIG_NLS_CODEPAGE_863 is not set -+# CONFIG_NLS_CODEPAGE_864 is not set -+# CONFIG_NLS_CODEPAGE_865 is not set -+# CONFIG_NLS_CODEPAGE_866 is not set -+# CONFIG_NLS_CODEPAGE_869 is not set -+# CONFIG_NLS_CODEPAGE_936 is not set -+# CONFIG_NLS_CODEPAGE_950 is not set -+# CONFIG_NLS_CODEPAGE_932 is not set -+# CONFIG_NLS_CODEPAGE_949 is not set -+# CONFIG_NLS_CODEPAGE_874 is not set -+# CONFIG_NLS_ISO8859_8 is not set -+# CONFIG_NLS_CODEPAGE_1250 is not set -+# CONFIG_NLS_CODEPAGE_1251 is not set -+# CONFIG_NLS_ISO8859_1 is not set -+# CONFIG_NLS_ISO8859_2 is not set -+# CONFIG_NLS_ISO8859_3 is not set -+# CONFIG_NLS_ISO8859_4 is not set -+# CONFIG_NLS_ISO8859_5 is not set -+# CONFIG_NLS_ISO8859_6 is not set -+# CONFIG_NLS_ISO8859_7 is not set -+# CONFIG_NLS_ISO8859_9 is not set -+# CONFIG_NLS_ISO8859_13 is not set -+# CONFIG_NLS_ISO8859_14 is not set -+# CONFIG_NLS_ISO8859_15 is not set -+# CONFIG_NLS_KOI8_R is not set -+# CONFIG_NLS_KOI8_U is not set -+# CONFIG_NLS_UTF8 is not set -+ -+# -+# SCSI support -+# -+CONFIG_SCSI=y -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+# CONFIG_BLK_DEV_SD is not set -+# CONFIG_CHR_DEV_ST is not set -+# CONFIG_BLK_DEV_SR is not set -+# CONFIG_CHR_DEV_SG is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+# CONFIG_SCSI_DEBUG_QUEUES is not set -+# CONFIG_SCSI_MULTI_LUN is not set -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+CONFIG_SCSI_DEBUG=m -+ -+# -+# Multi-device support (RAID and LVM) -+# -+# CONFIG_MD is not set -+ -+# -+# Memory Technology Devices (MTD) -+# -+# CONFIG_MTD is not set -+ -+# -+# Kernel hacking -+# -+# CONFIG_DEBUG_SLAB is not set -+# CONFIG_DEBUGSYM is not set -diff -Naur -X ../exclude-files orig/arch/um/config_block.in um/arch/um/config_block.in ---- orig/arch/um/config_block.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/config_block.in Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,16 @@ -+mainmenu_option next_comment -+comment 'Block Devices' -+ -+bool 'Virtual block device' CONFIG_BLK_DEV_UBD -+dep_bool ' Always do synchronous disk IO for UBD' CONFIG_BLK_DEV_UBD_SYNC $CONFIG_BLK_DEV_UBD -+tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -+dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET -+tristate 'RAM disk support' CONFIG_BLK_DEV_RAM -+if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then -+ int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096 -+fi -+dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM -+ -+tristate 'Example IO memory driver' CONFIG_MMAPPER -+ -+endmenu -diff -Naur -X ../exclude-files orig/arch/um/config_char.in um/arch/um/config_char.in ---- orig/arch/um/config_char.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/config_char.in Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,37 @@ -+mainmenu_option next_comment -+comment 'Character Devices' -+ -+define_bool CONFIG_STDIO_CONSOLE y -+ -+bool 'Virtual serial line' CONFIG_SSL -+ -+bool 'file descriptor channel support' CONFIG_FD_CHAN -+bool 'null channel support' CONFIG_NULL_CHAN -+bool 'port channel support' CONFIG_PORT_CHAN -+bool 'pty channel support' CONFIG_PTY_CHAN -+bool 'tty channel support' CONFIG_TTY_CHAN -+bool 'xterm channel support' CONFIG_XTERM_CHAN -+string 'Default main console channel initialization' CONFIG_CON_ZERO_CHAN \ -+ "fd:0,fd:1" -+string 'Default console channel initialization' CONFIG_CON_CHAN "xterm" -+string 'Default serial line channel initialization' CONFIG_SSL_CHAN "pty" -+ -+ -+bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS -+if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then -+ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 -+fi -+ -+bool 'Watchdog Timer Support' CONFIG_WATCHDOG -+dep_bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT \ -+ $CONFIG_WATCHDOG -+dep_tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG $CONFIG_WATCHDOG -+dep_tristate ' UML watchdog' CONFIG_UML_WATCHDOG $CONFIG_WATCHDOG -+ -+tristate 'Sound support' CONFIG_UML_SOUND -+define_tristate CONFIG_SOUND $CONFIG_UML_SOUND -+define_tristate CONFIG_HOSTAUDIO $CONFIG_UML_SOUND -+ -+bool 'Enable tty logging' CONFIG_TTY_LOG -+ -+endmenu -diff -Naur -X ../exclude-files orig/arch/um/config_net.in um/arch/um/config_net.in ---- orig/arch/um/config_net.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/config_net.in Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,47 @@ -+mainmenu_option next_comment -+comment 'Network Devices' -+ -+# UML virtual driver -+bool 'Virtual network device' CONFIG_UML_NET -+ -+dep_bool ' Ethertap transport' CONFIG_UML_NET_ETHERTAP $CONFIG_UML_NET -+dep_bool ' TUN/TAP transport' CONFIG_UML_NET_TUNTAP $CONFIG_UML_NET -+dep_bool ' SLIP transport' CONFIG_UML_NET_SLIP $CONFIG_UML_NET -+dep_bool ' SLiRP transport' CONFIG_UML_NET_SLIRP $CONFIG_UML_NET -+dep_bool ' Daemon transport' CONFIG_UML_NET_DAEMON $CONFIG_UML_NET -+dep_bool ' Multicast transport' CONFIG_UML_NET_MCAST $CONFIG_UML_NET -+dep_bool ' pcap transport' CONFIG_UML_NET_PCAP $CONFIG_UML_NET -+ -+# 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 -+ -+tristate 'Dummy net driver support' CONFIG_DUMMY -+tristate 'Bonding driver support' CONFIG_BONDING -+tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER -+tristate 'Universal TUN/TAP device driver support' CONFIG_TUN -+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ if [ "$CONFIG_NETLINK" = "y" ]; then -+ tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP -+ fi -+fi -+ -+tristate 'PPP (point-to-point protocol) support' CONFIG_PPP -+if [ ! "$CONFIG_PPP" = "n" ]; then -+ dep_bool ' PPP multilink support (EXPERIMENTAL)' CONFIG_PPP_MULTILINK $CONFIG_EXPERIMENTAL -+ dep_bool ' PPP filtering' CONFIG_PPP_FILTER $CONFIG_FILTER -+ dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP -+ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP -+ dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP -+ dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP -+ dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP $CONFIG_EXPERIMENTAL -+fi -+ -+tristate 'SLIP (serial line) support' CONFIG_SLIP -+dep_bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED $CONFIG_SLIP -+dep_bool ' Keepalive and linefill' CONFIG_SLIP_SMART $CONFIG_SLIP -+dep_bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6 $CONFIG_SLIP -+ -+endmenu -diff -Naur -X ../exclude-files orig/arch/um/config_scsi.in um/arch/um/config_scsi.in ---- orig/arch/um/config_scsi.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/config_scsi.in Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,30 @@ -+comment 'SCSI support type (disk, tape, CD-ROM)' -+ -+dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI -+ -+if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then -+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40 -+fi -+ -+dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI -+ -+dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI -+ -+if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then -+ bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR -+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2 -+fi -+dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI -+ -+comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' -+ -+#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ bool ' Enable extra checks in new queueing code' CONFIG_SCSI_DEBUG_QUEUES -+#fi -+ -+bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN -+ -+bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS -+bool ' SCSI logging facility' CONFIG_SCSI_LOGGING -+ -+dep_tristate 'SCSI debugging host simulator (EXPERIMENTAL)' CONFIG_SCSI_DEBUG $CONFIG_SCSI -diff -Naur -X ../exclude-files orig/arch/um/defconfig um/arch/um/defconfig ---- orig/arch/um/defconfig Wed Dec 31 19:00:00 1969 -+++ um/arch/um/defconfig Mon Jan 20 11:26:54 2003 -@@ -0,0 +1,396 @@ -+# -+# Automatically generated make config: don't edit -+# -+CONFIG_USERMODE=y -+# CONFIG_ISA is not set -+# CONFIG_SBUS is not set -+# CONFIG_PCI is not set -+CONFIG_UID16=y -+CONFIG_RWSEM_XCHGADD_ALGORITHM=y -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+ -+# -+# General Setup -+# -+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 -+# CONFIG_UML_SMP is not set -+# CONFIG_SMP is not set -+CONFIG_NEST_LEVEL=0 -+CONFIG_KERNEL_HALF_GIGS=1 -+# CONFIG_HIGHMEM is not set -+CONFIG_PROC_MM=y -+CONFIG_KERNEL_STACK_ORDER=2 -+ -+# -+# Loadable module support -+# -+CONFIG_MODULES=y -+# CONFIG_KMOD is not set -+ -+# -+# Character Devices -+# -+CONFIG_STDIO_CONSOLE=y -+CONFIG_SSL=y -+CONFIG_FD_CHAN=y -+CONFIG_NULL_CHAN=y -+CONFIG_PORT_CHAN=y -+CONFIG_PTY_CHAN=y -+CONFIG_TTY_CHAN=y -+CONFIG_XTERM_CHAN=y -+CONFIG_CON_ZERO_CHAN="fd:0,fd:1" -+CONFIG_CON_CHAN="xterm" -+CONFIG_SSL_CHAN="pty" -+CONFIG_UNIX98_PTYS=y -+CONFIG_UNIX98_PTY_COUNT=256 -+# CONFIG_WATCHDOG is not set -+# CONFIG_WATCHDOG_NOWAYOUT is not set -+# CONFIG_SOFT_WATCHDOG is not set -+# CONFIG_UML_WATCHDOG is not set -+CONFIG_UML_SOUND=y -+CONFIG_SOUND=y -+CONFIG_HOSTAUDIO=y -+# CONFIG_TTY_LOG is not set -+ -+# -+# Block Devices -+# -+CONFIG_BLK_DEV_UBD=y -+# CONFIG_BLK_DEV_UBD_SYNC is not set -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_NBD=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=4096 -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_MMAPPER is not set -+CONFIG_NETDEVICES=y -+ -+# -+# Network Devices -+# -+CONFIG_UML_NET=y -+CONFIG_UML_NET_ETHERTAP=y -+CONFIG_UML_NET_TUNTAP=y -+CONFIG_UML_NET_SLIP=y -+CONFIG_UML_NET_SLIRP=y -+CONFIG_UML_NET_DAEMON=y -+CONFIG_UML_NET_MCAST=y -+# CONFIG_UML_NET_PCAP is not set -+CONFIG_DUMMY=y -+# CONFIG_BONDING is not set -+# CONFIG_EQUALIZER is not set -+CONFIG_TUN=y -+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 -+ -+# -+# Networking options -+# -+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_INET=y -+# CONFIG_IP_MULTICAST is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set -+# CONFIG_IP_PNP is not set -+# CONFIG_NET_IPIP is not set -+# CONFIG_NET_IPGRE is not set -+# CONFIG_ARPD is not set -+# CONFIG_INET_ECN is not set -+# CONFIG_SYN_COOKIES is not set -+# CONFIG_IPV6 is not set -+# CONFIG_KHTTPD is not set -+# CONFIG_ATM is not set -+# CONFIG_VLAN_8021Q is not set -+ -+# -+# -+# -+# CONFIG_IPX is not set -+# CONFIG_ATALK is not set -+ -+# -+# Appletalk devices -+# -+# CONFIG_DEV_APPLETALK is not set -+# CONFIG_DECNET is not set -+# CONFIG_BRIDGE is not set -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_LLC is not set -+# CONFIG_NET_DIVERT is not set -+# CONFIG_ECONET is not set -+# CONFIG_WAN_ROUTER is not set -+# CONFIG_NET_FASTROUTE is not set -+# CONFIG_NET_HW_FLOWCONTROL is not set -+ -+# -+# QoS and/or fair queueing -+# -+# CONFIG_NET_SCHED is not set -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+ -+# -+# File systems -+# -+CONFIG_QUOTA=y -+CONFIG_AUTOFS_FS=y -+CONFIG_AUTOFS4_FS=y -+CONFIG_REISERFS_FS=y -+# CONFIG_REISERFS_CHECK is not set -+# CONFIG_REISERFS_PROC_INFO is not set -+# CONFIG_ADFS_FS is not set -+# CONFIG_ADFS_FS_RW is not set -+# CONFIG_AFFS_FS is not set -+# CONFIG_HFS_FS is not set -+# CONFIG_BFS_FS is not set -+# CONFIG_EXT3_FS is not set -+# CONFIG_JBD is not set -+# CONFIG_JBD_DEBUG is not set -+CONFIG_FAT_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_UMSDOS_FS=y -+CONFIG_VFAT_FS=y -+# CONFIG_EFS_FS is not set -+CONFIG_JFFS_FS=y -+CONFIG_JFFS_FS_VERBOSE=0 -+CONFIG_JFFS_PROC_FS=y -+CONFIG_JFFS2_FS=y -+CONFIG_JFFS2_FS_DEBUG=0 -+# CONFIG_CRAMFS is not set -+# CONFIG_TMPFS is not set -+CONFIG_RAMFS=y -+CONFIG_ISO9660_FS=y -+# CONFIG_JOLIET is not set -+# CONFIG_ZISOFS is not set -+CONFIG_MINIX_FS=y -+# CONFIG_VXFS_FS is not set -+# CONFIG_NTFS_FS is not set -+# CONFIG_NTFS_RW 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_QNX4FS_RW is not set -+# CONFIG_ROMFS_FS is not set -+CONFIG_EXT2_FS=y -+# CONFIG_SYSV_FS is not set -+# CONFIG_UDF_FS is not set -+# CONFIG_UDF_RW is not set -+# CONFIG_UFS_FS is not set -+# CONFIG_UFS_FS_WRITE 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_NFS_V3 is not set -+# CONFIG_ROOT_NFS is not set -+# CONFIG_NFSD is not set -+# CONFIG_NFSD_V3 is not set -+# CONFIG_SUNRPC is not set -+# CONFIG_LOCKD is not set -+# CONFIG_SMB_FS is not set -+# CONFIG_NCP_FS is not set -+# CONFIG_NCPFS_PACKET_SIGNING is not set -+# CONFIG_NCPFS_IOCTL_LOCKING is not set -+# CONFIG_NCPFS_STRONG is not set -+# CONFIG_NCPFS_NFS_NS is not set -+# CONFIG_NCPFS_OS2_NS is not set -+# CONFIG_NCPFS_SMALLDOS is not set -+# CONFIG_NCPFS_NLS is not set -+# CONFIG_NCPFS_EXTRAS is not set -+# CONFIG_ZISOFS_FS is not set -+# CONFIG_ZLIB_FS_INFLATE is not set -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+# CONFIG_SMB_NLS is not set -+CONFIG_NLS=y -+ -+# -+# Native Language Support -+# -+CONFIG_NLS_DEFAULT="iso8859-1" -+# CONFIG_NLS_CODEPAGE_437 is not set -+# CONFIG_NLS_CODEPAGE_737 is not set -+# CONFIG_NLS_CODEPAGE_775 is not set -+# CONFIG_NLS_CODEPAGE_850 is not set -+# CONFIG_NLS_CODEPAGE_852 is not set -+# CONFIG_NLS_CODEPAGE_855 is not set -+# CONFIG_NLS_CODEPAGE_857 is not set -+# CONFIG_NLS_CODEPAGE_860 is not set -+# CONFIG_NLS_CODEPAGE_861 is not set -+# CONFIG_NLS_CODEPAGE_862 is not set -+# CONFIG_NLS_CODEPAGE_863 is not set -+# CONFIG_NLS_CODEPAGE_864 is not set -+# CONFIG_NLS_CODEPAGE_865 is not set -+# CONFIG_NLS_CODEPAGE_866 is not set -+# CONFIG_NLS_CODEPAGE_869 is not set -+# CONFIG_NLS_CODEPAGE_936 is not set -+# CONFIG_NLS_CODEPAGE_950 is not set -+# CONFIG_NLS_CODEPAGE_932 is not set -+# CONFIG_NLS_CODEPAGE_949 is not set -+# CONFIG_NLS_CODEPAGE_874 is not set -+# CONFIG_NLS_ISO8859_8 is not set -+# CONFIG_NLS_CODEPAGE_1250 is not set -+# CONFIG_NLS_CODEPAGE_1251 is not set -+# CONFIG_NLS_ISO8859_1 is not set -+# CONFIG_NLS_ISO8859_2 is not set -+# CONFIG_NLS_ISO8859_3 is not set -+# CONFIG_NLS_ISO8859_4 is not set -+# CONFIG_NLS_ISO8859_5 is not set -+# CONFIG_NLS_ISO8859_6 is not set -+# CONFIG_NLS_ISO8859_7 is not set -+# CONFIG_NLS_ISO8859_9 is not set -+# CONFIG_NLS_ISO8859_13 is not set -+# CONFIG_NLS_ISO8859_14 is not set -+# CONFIG_NLS_ISO8859_15 is not set -+# CONFIG_NLS_KOI8_R is not set -+# CONFIG_NLS_KOI8_U is not set -+# CONFIG_NLS_UTF8 is not set -+ -+# -+# SCSI support -+# -+CONFIG_SCSI=y -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+# CONFIG_BLK_DEV_SD is not set -+# CONFIG_CHR_DEV_ST is not set -+# CONFIG_BLK_DEV_SR is not set -+# CONFIG_CHR_DEV_SG is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+# CONFIG_SCSI_DEBUG_QUEUES is not set -+# CONFIG_SCSI_MULTI_LUN is not set -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+CONFIG_SCSI_DEBUG=y -+ -+# -+# Multi-device support (RAID and LVM) -+# -+# CONFIG_MD is not set -+# CONFIG_BLK_DEV_MD is not set -+# CONFIG_MD_LINEAR is not set -+# CONFIG_MD_RAID0 is not set -+# CONFIG_MD_RAID1 is not set -+# CONFIG_MD_RAID5 is not set -+# CONFIG_MD_MULTIPATH is not set -+# CONFIG_BLK_DEV_LVM is not set -+ -+# -+# Memory Technology Devices (MTD) -+# -+CONFIG_MTD=y -+# CONFIG_MTD_DEBUG is not set -+# CONFIG_MTD_PARTITIONS is not set -+# CONFIG_MTD_CONCAT is not set -+# CONFIG_MTD_REDBOOT_PARTS is not set -+ -+# -+# User Modules And Translation Layers -+# -+CONFIG_MTD_CHAR=y -+CONFIG_MTD_BLOCK=y -+# CONFIG_FTL is not set -+# CONFIG_NFTL is not set -+ -+# -+# RAM/ROM/Flash chip drivers -+# -+# CONFIG_MTD_CFI is not set -+# CONFIG_MTD_JEDECPROBE is not set -+# CONFIG_MTD_GEN_PROBE is not set -+# CONFIG_MTD_CFI_INTELEXT is not set -+# CONFIG_MTD_CFI_AMDSTD is not set -+# CONFIG_MTD_RAM is not set -+# CONFIG_MTD_ROM is not set -+# CONFIG_MTD_ABSENT is not set -+# CONFIG_MTD_OBSOLETE_CHIPS is not set -+# CONFIG_MTD_AMDSTD is not set -+# CONFIG_MTD_SHARP is not set -+# CONFIG_MTD_JEDEC is not set -+ -+# -+# Mapping drivers for chip access -+# -+# CONFIG_MTD_PHYSMAP is not set -+# CONFIG_MTD_PCI is not set -+ -+# -+# Self-contained MTD device drivers -+# -+# CONFIG_MTD_PMC551 is not set -+# CONFIG_MTD_SLRAM is not set -+# CONFIG_MTD_MTDRAM is not set -+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_DOCPROBE is not set -+ -+# -+# NAND Flash Device Drivers -+# -+# CONFIG_MTD_NAND is not set -+ -+# -+# Kernel hacking -+# -+# CONFIG_DEBUG_SLAB is not set -+CONFIG_DEBUGSYM=y -+CONFIG_PT_PROXY=y -+# CONFIG_GPROF is not set -+# CONFIG_GCOV is not set -diff -Naur -X ../exclude-files orig/arch/um/drivers/Makefile um/arch/um/drivers/Makefile ---- orig/arch/um/drivers/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,94 @@ -+# -+# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := built-in.o -+ -+CHAN_OBJS := chan_kern.o chan_user.o line.o -+ -+list-multi := slip.o slirp.o daemon.o mcast.o mconsole.o net.o ubd.o \ -+ hostaudio.o pcap.o port.o harddog.o -+ -+slip-objs := slip_kern.o slip_user.o -+slirp-objs := slirp_kern.o slirp_user.o -+daemon-objs := daemon_kern.o daemon_user.o -+mcast-objs := mcast_kern.o mcast_user.o -+pcap-objs := pcap_kern.o pcap_user.o -lpcap -L/usr/lib -+net-objs := net_kern.o net_user.o -+mconsole-objs := mconsole_kern.o mconsole_user.o -+hostaudio-objs := hostaudio_kern.o hostaudio_user.o -+ubd-objs := ubd_kern.o ubd_user.o -+port-objs := port_kern.o port_user.o -+harddog-objs := harddog_kern.o harddog_user.o -+ -+export-objs := mconsole_kern.o -+ -+obj-y = -+obj-$(CONFIG_SSL) += ssl.o -+obj-$(CONFIG_UML_NET_SLIP) += slip.o -+obj-$(CONFIG_UML_NET_SLIRP) += slirp.o -+obj-$(CONFIG_UML_NET_DAEMON) += daemon.o -+obj-$(CONFIG_UML_NET_MCAST) += mcast.o -+obj-$(CONFIG_UML_NET_PCAP) += pcap.o -+obj-$(CONFIG_UML_NET) += net.o -+obj-$(CONFIG_MCONSOLE) += mconsole.o -+obj-$(CONFIG_MMAPPER) += mmapper_kern.o -+obj-$(CONFIG_BLK_DEV_UBD) += ubd.o -+obj-$(CONFIG_HOSTAUDIO) += hostaudio.o -+obj-$(CONFIG_FD_CHAN) += fd.o -+obj-$(CONFIG_NULL_CHAN) += null.o -+obj-$(CONFIG_PORT_CHAN) += port.o -+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 -+ -+CFLAGS_pcap_user.o = -I/usr/include/pcap -+ -+obj-y += stdio_console.o $(CHAN_OBJS) -+ -+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \ -+ null.o pty.o tty.o xterm.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean: -+ -+modules: -+ -+fastdep: -+ -+dep: -+ -+archmrproper: -+ -+daemon.o : $(daemon-objs) -+ -+slip.o : $(slip-objs) -+ -+slirp.o : $(slirp-objs) -+ -+mcast.o : $(mcast-objs) -+ -+pcap.o : $(pcap-objs) -+ -+mconsole.o : $(mconsole-objs) -+ -+net.o : $(net-objs) -+ -+hostaudio.o : $(hostaudio-objs) -+ -+ubd.o : $(ubd-objs) -+ -+port.o : $(port-objs) -+ -+harddog.o : $(harddog-objs) -+ -+$(list-multi) : # This doesn't work, but should : '%.o : $(%-objs)' -+ $(LD) $(LD_RFLAG) -r -o $@ $($(patsubst %.o,%,$@)-objs) -diff -Naur -X ../exclude-files orig/arch/um/drivers/chan_kern.c um/arch/um/drivers/chan_kern.c ---- orig/arch/um/drivers/chan_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/chan_kern.c Thu Mar 6 19:25:16 2003 -@@ -0,0 +1,510 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "sigio.h" -+#include "line.h" -+ -+static void *not_configged_init(char *str, int device, struct chan_opts *opts) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(NULL); -+} -+ -+static int not_configged_open(int input, int output, int primary, void *data, -+ char **dev_out) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-ENODEV); -+} -+ -+static void not_configged_close(int fd, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+} -+ -+static int not_configged_read(int fd, char *c_out, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_write(int fd, const char *buf, int len, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_console_write(int fd, const char *buf, int len, -+ void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_window_size(int fd, void *data, unsigned short *rows, -+ unsigned short *cols) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-ENODEV); -+} -+ -+static void not_configged_free(void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+} -+ -+static struct chan_ops not_configged_ops = { -+ .init = not_configged_init, -+ .open = not_configged_open, -+ .close = not_configged_close, -+ .read = not_configged_read, -+ .write = not_configged_write, -+ .console_write = not_configged_console_write, -+ .window_size = not_configged_window_size, -+ .free = not_configged_free, -+ .winch = 0, -+}; -+ -+static void tty_receive_char(struct tty_struct *tty, char ch) -+{ -+ if(tty == NULL) return; -+ -+ if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { -+ if(ch == STOP_CHAR(tty)){ -+ stop_tty(tty); -+ return; -+ } -+ else if(ch == START_CHAR(tty)){ -+ start_tty(tty); -+ return; -+ } -+ } -+ -+ if((tty->flip.flag_buf_ptr == NULL) || -+ (tty->flip.char_buf_ptr == NULL)) -+ return; -+ tty_insert_flip_char(tty, ch, TTY_NORMAL); -+} -+ -+static int open_one_chan(struct chan *chan, int input, int output, int primary) -+{ -+ int fd; -+ -+ if(chan->opened) return(0); -+ if(chan->ops->open == NULL) fd = 0; -+ else fd = (*chan->ops->open)(input, output, primary, chan->data, -+ &chan->dev); -+ if(fd < 0) return(fd); -+ chan->fd = fd; -+ -+ chan->opened = 1; -+ return(0); -+} -+ -+int open_chan(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int ret, err = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ ret = open_one_chan(chan, chan->input, chan->output, -+ chan->primary); -+ if(chan->primary) err = ret; -+ } -+ return(err); -+} -+ -+void chan_enable_winch(struct list_head *chans, void *line) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary && chan->output && chan->ops->winch){ -+ register_winch(chan->fd, line); -+ return; -+ } -+ } -+} -+ -+void enable_chan(struct list_head *chans, void *data) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->opened) continue; -+ -+ line_setup_irq(chan->fd, chan->input, chan->output, data); -+ } -+} -+ -+void close_chan(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ /* Close in reverse order as open in case more than one of them -+ * refers to the same device and they save and restore that device's -+ * state. Then, the first one opened will have the original state, -+ * so it must be the last closed. -+ */ -+ for(ele = chans->prev; ele != chans; ele = ele->prev){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->opened) continue; -+ if(chan->ops->close != NULL) -+ (*chan->ops->close)(chan->fd, chan->data); -+ chan->opened = 0; -+ chan->fd = -1; -+ } -+} -+ -+int write_chan(struct list_head *chans, const char *buf, int len, -+ int write_irq) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int n, ret = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->output || (chan->ops->write == NULL)) continue; -+ n = chan->ops->write(chan->fd, buf, len, chan->data); -+ if(chan->primary){ -+ ret = n; -+ if((ret == -EAGAIN) || ((ret >= 0) && (ret < len))){ -+ reactivate_fd(chan->fd, write_irq); -+ if(ret == -EAGAIN) ret = 0; -+ } -+ } -+ } -+ return(ret); -+} -+ -+int console_write_chan(struct list_head *chans, const char *buf, int len) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int n, ret = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->output || (chan->ops->console_write == NULL)) -+ continue; -+ n = chan->ops->console_write(chan->fd, buf, len, chan->data); -+ if(chan->primary) ret = n; -+ } -+ return(ret); -+} -+ -+int chan_window_size(struct list_head *chans, unsigned short *rows_out, -+ unsigned short *cols_out) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary){ -+ if(chan->ops->window_size == NULL) return(0); -+ return(chan->ops->window_size(chan->fd, chan->data, -+ rows_out, cols_out)); -+ } -+ } -+ return(0); -+} -+ -+void free_one_chan(struct chan *chan) -+{ -+ list_del(&chan->list); -+ if(chan->ops->free != NULL) -+ (*chan->ops->free)(chan->data); -+ free_irq_by_fd(chan->fd); -+ if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); -+ kfree(chan); -+} -+ -+void free_chan(struct list_head *chans) -+{ -+ struct list_head *ele, *next; -+ struct chan *chan; -+ -+ list_for_each_safe(ele, next, chans){ -+ chan = list_entry(ele, struct chan, list); -+ free_one_chan(chan); -+ } -+} -+ -+static int one_chan_config_string(struct chan *chan, char *str, int size, -+ char **error_out) -+{ -+ int n = 0; -+ -+ CONFIG_CHUNK(str, size, n, chan->ops->type, 0); -+ -+ if(chan->dev == NULL){ -+ CONFIG_CHUNK(str, size, n, "", 1); -+ return(n); -+ } -+ -+ CONFIG_CHUNK(str, size, n, ":", 0); -+ CONFIG_CHUNK(str, size, n, chan->dev, 0); -+ -+ return(n); -+} -+ -+static int chan_pair_config_string(struct chan *in, struct chan *out, -+ char *str, int size, char **error_out) -+{ -+ int n; -+ -+ n = one_chan_config_string(in, str, size, error_out); -+ str += n; -+ size -= n; -+ -+ if(in == out){ -+ CONFIG_CHUNK(str, size, n, "", 1); -+ return(n); -+ } -+ -+ CONFIG_CHUNK(str, size, n, ",", 1); -+ n = one_chan_config_string(out, str, size, error_out); -+ str += n; -+ size -= n; -+ CONFIG_CHUNK(str, size, n, "", 1); -+ -+ return(n); -+} -+ -+int chan_config_string(struct list_head *chans, char *str, int size, -+ char **error_out) -+{ -+ struct list_head *ele; -+ struct chan *chan, *in = NULL, *out = NULL; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->primary) -+ continue; -+ if(chan->input) -+ in = chan; -+ if(chan->output) -+ out = chan; -+ } -+ -+ return(chan_pair_config_string(in, out, str, size, error_out)); -+} -+ -+struct chan_type { -+ char *key; -+ struct chan_ops *ops; -+}; -+ -+struct chan_type chan_table[] = { -+#ifdef CONFIG_FD_CHAN -+ { "fd", &fd_ops }, -+#else -+ { "fd", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_NULL_CHAN -+ { "null", &null_ops }, -+#else -+ { "null", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_PORT_CHAN -+ { "port", &port_ops }, -+#else -+ { "port", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_PTY_CHAN -+ { "pty", &pty_ops }, -+ { "pts", &pts_ops }, -+#else -+ { "pty", ¬_configged_ops }, -+ { "pts", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_TTY_CHAN -+ { "tty", &tty_ops }, -+#else -+ { "tty", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_XTERM_CHAN -+ { "xterm", &xterm_ops }, -+#else -+ { "xterm", ¬_configged_ops }, -+#endif -+}; -+ -+static struct chan *parse_chan(char *str, int pri, int device, -+ struct chan_opts *opts) -+{ -+ struct chan_type *entry; -+ struct chan_ops *ops; -+ struct chan *chan; -+ void *data; -+ int i; -+ -+ ops = NULL; -+ data = NULL; -+ for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){ -+ entry = &chan_table[i]; -+ if(!strncmp(str, entry->key, strlen(entry->key))){ -+ ops = entry->ops; -+ str += strlen(entry->key); -+ break; -+ } -+ } -+ if(ops == NULL){ -+ printk(KERN_ERR "parse_chan couldn't parse \"%s\"\n", -+ str); -+ return(NULL); -+ } -+ if(ops->init == NULL) return(NULL); -+ data = (*ops->init)(str, device, opts); -+ if(data == NULL) return(NULL); -+ -+ chan = kmalloc(sizeof(*chan), GFP_KERNEL); -+ if(chan == NULL) return(NULL); -+ *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), -+ .primary = 1, -+ .input = 0, -+ .output = 0, -+ .opened = 0, -+ .fd = -1, -+ .pri = pri, -+ .ops = ops, -+ .data = data }); -+ return(chan); -+} -+ -+int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, -+ struct chan_opts *opts) -+{ -+ struct chan *new, *chan; -+ char *in, *out; -+ -+ if(!list_empty(chans)){ -+ chan = list_entry(chans->next, struct chan, list); -+ if(chan->pri >= pri) return(0); -+ free_chan(chans); -+ INIT_LIST_HEAD(chans); -+ } -+ -+ if((out = strchr(str, ',')) != NULL){ -+ in = str; -+ *out = '\0'; -+ out++; -+ new = parse_chan(in, pri, device, opts); -+ if(new == NULL) return(-1); -+ new->input = 1; -+ list_add(&new->list, chans); -+ -+ new = parse_chan(out, pri, device, opts); -+ if(new == NULL) return(-1); -+ list_add(&new->list, chans); -+ new->output = 1; -+ } -+ else { -+ new = parse_chan(str, pri, device, opts); -+ if(new == NULL) return(-1); -+ list_add(&new->list, chans); -+ new->input = 1; -+ new->output = 1; -+ } -+ return(0); -+} -+ -+int chan_out_fd(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary && chan->output) -+ return(chan->fd); -+ } -+ return(-1); -+} -+ -+void chan_interrupt(struct list_head *chans, struct tq_struct *task, -+ struct tty_struct *tty, int irq, void *dev) -+{ -+ struct list_head *ele, *next; -+ struct chan *chan; -+ int err; -+ char c; -+ -+ list_for_each_safe(ele, next, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->input || (chan->ops->read == NULL)) continue; -+ do { -+ if((tty != NULL) && -+ (tty->flip.count >= TTY_FLIPBUF_SIZE)){ -+ queue_task(task, &tq_timer); -+ goto out; -+ } -+ err = chan->ops->read(chan->fd, &c, chan->data); -+ 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); -+ line_disable(dev, irq); -+ close_chan(chans); -+ free_chan(chans); -+ return; -+ } -+ else { -+ if(chan->ops->close != NULL) -+ chan->ops->close(chan->fd, chan->data); -+ free_one_chan(chan); -+ } -+ } -+ } -+ out: -+ if(tty) tty_flip_buffer_push(tty); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/chan_user.c um/arch/um/drivers/chan_user.c ---- orig/arch/um/drivers/chan_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/chan_user.c Wed Mar 26 13:23:48 2003 -@@ -0,0 +1,213 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "kern_util.h" -+#include "user_util.h" -+#include "chan_user.h" -+#include "user.h" -+#include "helper.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+void generic_close(int fd, void *unused) -+{ -+ close(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); -+} -+ -+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); -+} -+ -+int generic_console_write(int fd, const char *buf, int n, void *unused) -+{ -+ struct termios save, new; -+ int err; -+ -+ if(isatty(fd)){ -+ tcgetattr(fd, &save); -+ new = save; -+ new.c_oflag |= OPOST; -+ tcsetattr(fd, TCSAFLUSH, &new); -+ } -+ err = generic_write(fd, buf, n, NULL); -+ if(isatty(fd)) tcsetattr(fd, TCSAFLUSH, &save); -+ return(err); -+} -+ -+int generic_window_size(int fd, void *unused, unsigned short *rows_out, -+ unsigned short *cols_out) -+{ -+ struct winsize size; -+ int ret = 0; -+ -+ 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); -+} -+ -+void generic_free(void *data) -+{ -+ kfree(data); -+} -+ -+static void winch_handler(int sig) -+{ -+} -+ -+struct winch_data { -+ int pty_fd; -+ int pipe_fd; -+ int close_me; -+}; -+ -+static int winch_thread(void *arg) -+{ -+ struct winch_data *data = arg; -+ sigset_t sigs; -+ int pty_fd, pipe_fd; -+ char c = 1; -+ -+ close(data->close_me); -+ pty_fd = data->pty_fd; -+ pipe_fd = data->pipe_fd; -+ if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)) -+ printk("winch_thread : failed to write synchronization " -+ "byte, errno = %d\n", errno); -+ -+ signal(SIGWINCH, winch_handler); -+ sigfillset(&sigs); -+ sigdelset(&sigs, SIGWINCH); -+ if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){ -+ printk("winch_thread : sigprocmask failed, errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ if(setsid() < 0){ -+ printk("winch_thread : setsid failed, errno = %d\n", errno); -+ 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); -+ exit(1); -+ } -+ -+ if(read(pipe_fd, &c, sizeof(c)) != sizeof(c)) -+ printk("winch_thread : failed to read synchronization byte, " -+ "errno = %d\n", errno); -+ -+ while(1){ -+ pause(); -+ -+ if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)){ -+ printk("winch_thread : write failed, errno = %d\n", -+ errno); -+ } -+ } -+} -+ -+static int winch_tramp(int fd, void *device_data, int *fd_out) -+{ -+ struct winch_data data; -+ unsigned long stack; -+ int fds[2], pid, n, err; -+ char c; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err){ -+ printk("winch_tramp : os_pipe failed, errno = %d\n", -err); -+ return(err); -+ } -+ -+ data = ((struct winch_data) { .pty_fd = fd, -+ .pipe_fd = fds[1], -+ .close_me = fds[0] } ); -+ pid = run_helper_thread(winch_thread, &data, 0, &stack, 0); -+ if(pid < 0){ -+ printk("fork of winch_thread failed - errno = %d\n", errno); -+ return(pid); -+ } -+ -+ close(fds[1]); -+ *fd_out = fds[0]; -+ n = read(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("fd %d will not support SIGWINCH\n", fd); -+ *fd_out = -1; -+ } -+ return(pid); -+} -+ -+void register_winch(int fd, void *device_data) -+{ -+ int pid, thread, thread_fd; -+ char c = 1; -+ -+ if(!isatty(fd)) return; -+ -+ pid = tcgetpgrp(fd); -+ 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)) -+ printk("register_winch : failed to write " -+ "synchronization byte\n"); -+ } -+ } -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/daemon.h um/arch/um/drivers/daemon.h ---- orig/arch/um/drivers/daemon.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/daemon.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+#define SWITCH_VERSION 3 -+ -+struct daemon_data { -+ char *sock_type; -+ char *ctl_sock; -+ void *ctl_addr; -+ void *data_addr; -+ void *local_addr; -+ int fd; -+ int control; -+ void *dev; -+}; -+ -+extern struct net_user_info daemon_user_info; -+ -+extern int daemon_user_write(int fd, void *buf, int len, -+ struct daemon_data *pri); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/daemon_kern.c um/arch/um/drivers/daemon_kern.c ---- orig/arch/um/drivers/daemon_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/daemon_kern.c Sun Dec 15 21:19:17 2002 -@@ -0,0 +1,113 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "daemon.h" -+ -+struct daemon_init { -+ char *sock_type; -+ char *ctl_sock; -+}; -+ -+void daemon_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct daemon_data *dpri; -+ struct daemon_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ dpri = (struct daemon_data *) pri->user; -+ *dpri = ((struct daemon_data) -+ { .sock_type = init->sock_type, -+ .ctl_sock = init->ctl_sock, -+ .ctl_addr = NULL, -+ .data_addr = NULL, -+ .local_addr = NULL, -+ .fd = -1, -+ .control = -1, -+ .dev = dev }); -+ -+ printk("daemon backend (uml_switch version %d) - %s:%s", -+ SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); -+ printk("\n"); -+} -+ -+static int daemon_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int daemon_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(daemon_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct daemon_data *) &lp->user)); -+} -+ -+static struct net_kern_info daemon_kern_info = { -+ .init = daemon_init, -+ .protocol = eth_protocol, -+ .read = daemon_read, -+ .write = daemon_write, -+}; -+ -+int daemon_setup(char *str, char **mac_out, void *data) -+{ -+ struct daemon_init *init = data; -+ char *remain; -+ -+ *init = ((struct daemon_init) -+ { .sock_type = "unix", -+ .ctl_sock = "/tmp/uml.ctl" }); -+ -+ remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock, -+ NULL); -+ if(remain != NULL) -+ printk(KERN_WARNING "daemon_setup : Ignoring data socket " -+ "specification\n"); -+ -+ return(1); -+} -+ -+static struct transport daemon_transport = { -+ .list = LIST_HEAD_INIT(daemon_transport.list), -+ .name = "daemon", -+ .setup = daemon_setup, -+ .user = &daemon_user_info, -+ .kern = &daemon_kern_info, -+ .private_size = sizeof(struct daemon_data), -+ .setup_size = sizeof(struct daemon_init), -+}; -+ -+static int register_daemon(void) -+{ -+ register_transport(&daemon_transport); -+ return(1); -+} -+ -+__initcall(register_daemon); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/daemon_user.c um/arch/um/drivers/daemon_user.c ---- orig/arch/um/drivers/daemon_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/daemon_user.c Fri Jan 17 13:48:59 2003 -@@ -0,0 +1,195 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "net_user.h" -+#include "daemon.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+enum request_type { REQ_NEW_CONTROL }; -+ -+#define SWITCH_MAGIC 0xfeedface -+ -+struct request_v3 { -+ uint32_t magic; -+ uint32_t version; -+ enum request_type type; -+ struct sockaddr_un sock; -+}; -+ -+static struct sockaddr_un *new_addr(void *name, int len) -+{ -+ struct sockaddr_un *sun; -+ -+ sun = um_kmalloc(sizeof(struct sockaddr_un)); -+ if(sun == NULL){ -+ printk("new_addr: allocation of sockaddr_un failed\n"); -+ return(NULL); -+ } -+ sun->sun_family = AF_UNIX; -+ memcpy(sun->sun_path, name, len); -+ return(sun); -+} -+ -+static int connect_to_switch(struct daemon_data *pri) -+{ -+ struct sockaddr_un *ctl_addr = pri->ctl_addr; -+ struct sockaddr_un *local_addr = pri->local_addr; -+ struct sockaddr_un *sun; -+ struct request_v3 req; -+ int fd, n, err; -+ -+ if((pri->control = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){ -+ printk("daemon_open : control socket failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ if(connect(pri->control, (struct sockaddr *) ctl_addr, -+ sizeof(*ctl_addr)) < 0){ -+ printk("daemon_open : control connect failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out; -+ } -+ -+ if((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){ -+ printk("daemon_open : data socket failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out; -+ } -+ if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ -+ printk("daemon_open : data bind failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out_close; -+ } -+ -+ sun = um_kmalloc(sizeof(struct sockaddr_un)); -+ if(sun == NULL){ -+ printk("new_addr: allocation of sockaddr_un failed\n"); -+ err = -ENOMEM; -+ goto out_close; -+ } -+ -+ req.magic = SWITCH_MAGIC; -+ req.version = SWITCH_VERSION; -+ req.type = REQ_NEW_CONTROL; -+ req.sock = *local_addr; -+ n = write(pri->control, &req, sizeof(req)); -+ if(n != sizeof(req)){ -+ printk("daemon_open : control setup request returned %d, " -+ "errno = %d\n", n, errno); -+ err = -ENOTCONN; -+ goto out; -+ } -+ -+ n = read(pri->control, sun, sizeof(*sun)); -+ if(n != sizeof(*sun)){ -+ printk("daemon_open : read of data socket returned %d, " -+ "errno = %d\n", n, errno); -+ err = -ENOTCONN; -+ goto out_close; -+ } -+ -+ pri->data_addr = sun; -+ return(fd); -+ -+ out_close: -+ close(fd); -+ out: -+ close(pri->control); -+ return(err); -+} -+ -+static void daemon_user_init(void *data, void *dev) -+{ -+ struct daemon_data *pri = data; -+ struct timeval tv; -+ struct { -+ char zero; -+ int pid; -+ int usecs; -+ } name; -+ -+ if(!strcmp(pri->sock_type, "unix")) -+ pri->ctl_addr = new_addr(pri->ctl_sock, -+ strlen(pri->ctl_sock) + 1); -+ name.zero = 0; -+ name.pid = os_getpid(); -+ gettimeofday(&tv, NULL); -+ name.usecs = tv.tv_usec; -+ pri->local_addr = new_addr(&name, sizeof(name)); -+ pri->dev = dev; -+ pri->fd = connect_to_switch(pri); -+ if(pri->fd < 0){ -+ kfree(pri->local_addr); -+ pri->local_addr = NULL; -+ } -+} -+ -+static int daemon_open(void *data) -+{ -+ struct daemon_data *pri = data; -+ return(pri->fd); -+} -+ -+static void daemon_remove(void *data) -+{ -+ struct daemon_data *pri = data; -+ -+ close(pri->fd); -+ close(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); -+} -+ -+int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) -+{ -+ struct sockaddr_un *data_addr = pri->data_addr; -+ -+ return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); -+} -+ -+static int daemon_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info daemon_user_info = { -+ .init = daemon_user_init, -+ .open = daemon_open, -+ .close = NULL, -+ .remove = daemon_remove, -+ .set_mtu = daemon_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/fd.c um/arch/um/drivers/fd.c ---- orig/arch/um/drivers/fd.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/fd.c Sun Dec 15 20:57:25 2002 -@@ -0,0 +1,96 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include "user.h" -+#include "user_util.h" -+#include "chan_user.h" -+ -+struct fd_chan { -+ int fd; -+ int raw; -+ struct termios tt; -+ char str[sizeof("1234567890\0")]; -+}; -+ -+void *fd_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct fd_chan *data; -+ char *end; -+ int n; -+ -+ if(*str != ':'){ -+ printk("fd_init : channel type 'fd' must specify a file " -+ "descriptor\n"); -+ return(NULL); -+ } -+ str++; -+ n = strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk("fd_init : couldn't parse file descriptor '%s'\n", str); -+ return(NULL); -+ } -+ if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL); -+ *data = ((struct fd_chan) { .fd = n, -+ .raw = opts->raw }); -+ return(data); -+} -+ -+int fd_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct fd_chan *data = d; -+ -+ if(data->raw && isatty(data->fd)){ -+ tcgetattr(data->fd, &data->tt); -+ raw(data->fd, 0); -+ } -+ sprintf(data->str, "%d", data->fd); -+ *dev_out = data->str; -+ return(data->fd); -+} -+ -+void fd_close(int fd, void *d) -+{ -+ struct fd_chan *data = d; -+ -+ if(data->raw && isatty(fd)){ -+ tcsetattr(fd, TCSAFLUSH, &data->tt); -+ data->raw = 0; -+ } -+} -+ -+int fd_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct fd_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops fd_ops = { -+ .type = "fd", -+ .init = fd_init, -+ .open = fd_open, -+ .close = fd_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = fd_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 1, -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/harddog_kern.c um/arch/um/drivers/harddog_kern.c ---- orig/arch/um/drivers/harddog_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/harddog_kern.c Sun Dec 15 20:57:42 2002 -@@ -0,0 +1,194 @@ -+/* UML hardware watchdog, shamelessly stolen from: -+ * -+ * SoftDog 0.05: A Software Watchdog Device -+ * -+ * (c) Copyright 1996 Alan Cox , All Rights Reserved. -+ * http://www.redhat.com -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide -+ * warranty for any of this software. This material is provided -+ * "AS-IS" and at no charge. -+ * -+ * (c) Copyright 1995 Alan Cox -+ * -+ * Software only watchdog driver. Unlike its big brother the WDT501P -+ * driver this won't always recover a failed machine. -+ * -+ * 03/96: Angelo Haritsis : -+ * Modularised. -+ * Added soft_margin; use upon insmod to change the timer delay. -+ * NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate -+ * minors. -+ * -+ * 19980911 Alan Cox -+ * Made SMP safe for 2.3.x -+ * -+ * 20011127 Joel Becker (jlbec@evilplan.org> -+ * Added soft_noboot; Allows testing the softdog trigger without -+ * requiring a recompile. -+ * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "helper.h" -+#include "mconsole.h" -+ -+MODULE_LICENSE("GPL"); -+ -+/* Locked by the BKL in harddog_open and harddog_release */ -+static int timer_alive; -+static int harddog_in_fd = -1; -+static int harddog_out_fd = -1; -+ -+/* -+ * Allow only one person to hold it open -+ */ -+ -+extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); -+ -+static int harddog_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ char *sock = NULL; -+ -+ lock_kernel(); -+ if(timer_alive) -+ return -EBUSY; -+#ifdef CONFIG_HARDDOG_NOWAYOUT -+ MOD_INC_USE_COUNT; -+#endif -+ -+#ifdef CONFIG_MCONSOLE -+ sock = mconsole_notify_socket(); -+#endif -+ err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock); -+ if(err) return(err); -+ -+ timer_alive = 1; -+ unlock_kernel(); -+ return 0; -+} -+ -+extern void stop_watchdog(int in_fd, int out_fd); -+ -+static int harddog_release(struct inode *inode, struct file *file) -+{ -+ /* -+ * Shut off the timer. -+ */ -+ lock_kernel(); -+ -+ stop_watchdog(harddog_in_fd, harddog_out_fd); -+ harddog_in_fd = -1; -+ harddog_out_fd = -1; -+ -+ timer_alive=0; -+ unlock_kernel(); -+ return 0; -+} -+ -+extern int ping_watchdog(int fd); -+ -+static ssize_t harddog_write(struct file *file, const char *data, size_t len, -+ loff_t *ppos) -+{ -+ /* Can't seek (pwrite) on this device */ -+ if (ppos != &file->f_pos) -+ return -ESPIPE; -+ -+ /* -+ * Refresh the timer. -+ */ -+ if(len) -+ return(ping_watchdog(harddog_out_fd)); -+ return 0; -+} -+ -+static int harddog_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ static struct watchdog_info ident = { -+ WDIOF_SETTIMEOUT, -+ 0, -+ "UML Hardware Watchdog" -+ }; -+ switch (cmd) { -+ default: -+ return -ENOTTY; -+ case WDIOC_GETSUPPORT: -+ if(copy_to_user((struct harddog_info *)arg, &ident, -+ sizeof(ident))) -+ return -EFAULT; -+ return 0; -+ case WDIOC_GETSTATUS: -+ case WDIOC_GETBOOTSTATUS: -+ return put_user(0,(int *)arg); -+ case WDIOC_KEEPALIVE: -+ return(ping_watchdog(harddog_out_fd)); -+ } -+} -+ -+static struct file_operations harddog_fops = { -+ .owner = THIS_MODULE, -+ .write = harddog_write, -+ .ioctl = harddog_ioctl, -+ .open = harddog_open, -+ .release = harddog_release, -+}; -+ -+static struct miscdevice harddog_miscdev = { -+ .minor = WATCHDOG_MINOR, -+ .name = "watchdog", -+ .fops = &harddog_fops, -+}; -+ -+static char banner[] __initdata = KERN_INFO "UML Watchdog Timer\n"; -+ -+static int __init harddog_init(void) -+{ -+ int ret; -+ -+ ret = misc_register(&harddog_miscdev); -+ -+ if (ret) -+ return ret; -+ -+ printk(banner); -+ -+ return(0); -+} -+ -+static void __exit harddog_exit(void) -+{ -+ misc_deregister(&harddog_miscdev); -+} -+ -+module_init(harddog_init); -+module_exit(harddog_exit); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/harddog_user.c um/arch/um/drivers/harddog_user.c ---- orig/arch/um/drivers/harddog_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/harddog_user.c Wed Dec 4 16:38:05 2002 -@@ -0,0 +1,137 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include "user_util.h" -+#include "user.h" -+#include "helper.h" -+#include "mconsole.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+struct dog_data { -+ int stdin; -+ int stdout; -+ int close_me[2]; -+}; -+ -+static void pre_exec(void *d) -+{ -+ struct dog_data *data = 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]); -+} -+ -+int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) -+{ -+ struct dog_data data; -+ int in_fds[2], out_fds[2], pid, n, err; -+ char pid_buf[sizeof("nnnnn\0")], c; -+ char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; -+ char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, -+ NULL }; -+ char **args = NULL; -+ -+ err = os_pipe(in_fds, 1, 0); -+ if(err){ -+ printk("harddog_open - os_pipe failed, errno = %d\n", -err); -+ return(err); -+ } -+ -+ err = os_pipe(out_fds, 1, 0); -+ if(err){ -+ printk("harddog_open - os_pipe failed, errno = %d\n", -err); -+ return(err); -+ } -+ -+ data.stdin = out_fds[0]; -+ data.stdout = in_fds[1]; -+ data.close_me[0] = out_fds[1]; -+ data.close_me[1] = in_fds[0]; -+ -+ if(sock != NULL){ -+ mconsole_args[2] = sock; -+ args = mconsole_args; -+ } -+ else { -+ /* XXX The os_getpid() is not SMP correct */ -+ sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid())); -+ args = pid_args; -+ } -+ -+ pid = run_helper(pre_exec, &data, args, NULL); -+ -+ close(out_fds[0]); -+ close(in_fds[1]); -+ -+ if(pid < 0){ -+ err = -pid; -+ printk("harddog_open - run_helper failed, errno = %d\n", err); -+ goto out; -+ } -+ -+ n = read(in_fds[0], &c, sizeof(c)); -+ if(n == 0){ -+ printk("harddog_open - EOF on watchdog pipe\n"); -+ helper_wait(pid); -+ err = -EIO; -+ goto out; -+ } -+ else if(n < 0){ -+ printk("harddog_open - read of watchdog pipe failed, " -+ "errno = %d\n", errno); -+ helper_wait(pid); -+ err = -errno; -+ goto out; -+ } -+ *in_fd_ret = in_fds[0]; -+ *out_fd_ret = out_fds[1]; -+ return(0); -+ 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); -+} -+ -+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); -+ } -+ return 1; -+ -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/hostaudio_kern.c um/arch/um/drivers/hostaudio_kern.c ---- orig/arch/um/drivers/hostaudio_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/hostaudio_kern.c Sun Dec 15 20:58:02 2002 -@@ -0,0 +1,265 @@ -+/* -+ * Copyright (C) 2002 Steve Schmidtke -+ * Licensed under the GPL -+ */ -+ -+#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 "kern_util.h" -+#include "init.h" -+#include "hostaudio.h" -+ -+/* Only changed from linux_main at boot time */ -+char *dsp = HOSTAUDIO_DEV_DSP; -+char *mixer = HOSTAUDIO_DEV_MIXER; -+ -+#ifndef MODULE -+static int set_dsp(char *name, int *add) -+{ -+ dsp = uml_strdup(name); -+ return(0); -+} -+ -+__uml_setup("dsp=", set_dsp, -+"dsp=\n" -+" This is used to specify the host dsp device to the hostaudio driver.\n" -+" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n" -+); -+ -+static int set_mixer(char *name, int *add) -+{ -+ mixer = uml_strdup(name); -+ return(0); -+} -+ -+__uml_setup("mixer=", set_mixer, -+"mixer=\n" -+" This is used to specify the host mixer device to the hostaudio driver.\n" -+" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" -+); -+#endif -+ -+/* /dev/dsp file operations */ -+ -+static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count, -+ loff_t *ppos) -+{ -+ struct hostaudio_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostaudio: read called, count = %d\n", count); -+#endif -+ -+ return(hostaudio_read_user(state, buffer, count, ppos)); -+} -+ -+static ssize_t hostaudio_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct hostaudio_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostaudio: write called, count = %d\n", count); -+#endif -+ return(hostaudio_write_user(state, buffer, count, ppos)); -+} -+ -+static unsigned int hostaudio_poll(struct file *file, -+ struct poll_table_struct *wait) -+{ -+ unsigned int mask = 0; -+ -+#ifdef DEBUG -+ printk("hostaudio: poll called (unimplemented)\n"); -+#endif -+ -+ return(mask); -+} -+ -+static int hostaudio_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hostaudio_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostaudio: ioctl called, cmd = %u\n", cmd); -+#endif -+ -+ return(hostaudio_ioctl_user(state, cmd, arg)); -+} -+ -+static int hostaudio_open(struct inode *inode, struct file *file) -+{ -+ struct hostaudio_state *state; -+ int r = 0, w = 0; -+ int ret; -+ -+#ifdef DEBUG -+ printk("hostaudio: open called (host: %s)\n", dsp); -+#endif -+ -+ state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); -+ if(state == NULL) return(-ENOMEM); -+ -+ if(file->f_mode & FMODE_READ) r = 1; -+ if(file->f_mode & FMODE_WRITE) w = 1; -+ -+ ret = hostaudio_open_user(state, r, w, dsp); -+ if(ret < 0){ -+ kfree(state); -+ return(ret); -+ } -+ -+ file->private_data = state; -+ return(0); -+} -+ -+static int hostaudio_release(struct inode *inode, struct file *file) -+{ -+ struct hostaudio_state *state = file->private_data; -+ int ret; -+ -+#ifdef DEBUG -+ printk("hostaudio: release called\n"); -+#endif -+ -+ ret = hostaudio_release_user(state); -+ kfree(state); -+ -+ return(ret); -+} -+ -+/* /dev/mixer file operations */ -+ -+static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hostmixer_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostmixer: ioctl called\n"); -+#endif -+ -+ return(hostmixer_ioctl_mixdev_user(state, cmd, arg)); -+} -+ -+static int hostmixer_open_mixdev(struct inode *inode, struct file *file) -+{ -+ struct hostmixer_state *state; -+ int r = 0, w = 0; -+ int ret; -+ -+#ifdef DEBUG -+ printk("hostmixer: open called (host: %s)\n", mixer); -+#endif -+ -+ state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); -+ if(state == NULL) return(-ENOMEM); -+ -+ if(file->f_mode & FMODE_READ) r = 1; -+ if(file->f_mode & FMODE_WRITE) w = 1; -+ -+ ret = hostmixer_open_mixdev_user(state, r, w, mixer); -+ -+ if(ret < 0){ -+ kfree(state); -+ return(ret); -+ } -+ -+ file->private_data = state; -+ return(0); -+} -+ -+static int hostmixer_release(struct inode *inode, struct file *file) -+{ -+ struct hostmixer_state *state = file->private_data; -+ int ret; -+ -+#ifdef DEBUG -+ printk("hostmixer: release called\n"); -+#endif -+ -+ ret = hostmixer_release_mixdev_user(state); -+ kfree(state); -+ -+ return(ret); -+} -+ -+ -+/* kernel module operations */ -+ -+static struct file_operations hostaudio_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .read = hostaudio_read, -+ .write = hostaudio_write, -+ .poll = hostaudio_poll, -+ .ioctl = hostaudio_ioctl, -+ .mmap = NULL, -+ .open = hostaudio_open, -+ .release = hostaudio_release, -+}; -+ -+static struct file_operations hostmixer_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .ioctl = hostmixer_ioctl_mixdev, -+ .open = hostmixer_open_mixdev, -+ .release = hostmixer_release, -+}; -+ -+struct { -+ int dev_audio; -+ int dev_mixer; -+} module_data; -+ -+MODULE_AUTHOR("Steve Schmidtke"); -+MODULE_DESCRIPTION("UML Audio Relay"); -+MODULE_LICENSE("GPL"); -+ -+static int __init hostaudio_init_module(void) -+{ -+ printk(KERN_INFO "UML Audio Relay\n"); -+ -+ module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); -+ if(module_data.dev_audio < 0){ -+ printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); -+ return -ENODEV; -+ } -+ -+ module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); -+ if(module_data.dev_mixer < 0){ -+ printk(KERN_ERR "hostmixer: couldn't register mixer " -+ "device!\n"); -+ unregister_sound_dsp(module_data.dev_audio); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit hostaudio_cleanup_module (void) -+{ -+ unregister_sound_mixer(module_data.dev_mixer); -+ unregister_sound_dsp(module_data.dev_audio); -+} -+ -+module_init(hostaudio_init_module); -+module_exit(hostaudio_cleanup_module); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/hostaudio_user.c um/arch/um/drivers/hostaudio_user.c ---- orig/arch/um/drivers/hostaudio_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/hostaudio_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,149 @@ -+/* -+ * Copyright (C) 2002 Steve Schmidtke -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "hostaudio.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "os.h" -+ -+/* /dev/dsp file operations */ -+ -+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); -+} -+ -+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); -+} -+ -+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); -+} -+ -+int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp) -+{ -+#ifdef DEBUG -+ 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); -+ -+ printk("hostaudio_open_user failed to open '%s', errno = %d\n", -+ dsp, errno); -+ -+ return(-errno); -+} -+ -+int hostaudio_release_user(struct hostaudio_state *state) -+{ -+#ifdef DEBUG -+ printk("hostaudio: release called\n"); -+#endif -+ if(state->fd >= 0){ -+ close(state->fd); -+ state->fd=-1; -+ } -+ -+ return(0); -+} -+ -+/* /dev/mixer file operations */ -+ -+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); -+} -+ -+int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w, -+ char *mixer) -+{ -+#ifdef DEBUG -+ printk("hostmixer: open_user called\n"); -+#endif -+ -+ 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); -+ -+ return(-errno); -+} -+ -+int hostmixer_release_mixdev_user(struct hostmixer_state *state) -+{ -+#ifdef DEBUG -+ printk("hostmixer: release_user called\n"); -+#endif -+ -+ if(state->fd >= 0){ -+ close(state->fd); -+ state->fd = -1; -+ } -+ -+ 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 -Naur -X ../exclude-files orig/arch/um/drivers/line.c um/arch/um/drivers/line.c ---- orig/arch/um/drivers/line.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/line.c Wed Mar 26 15:09:44 2003 -@@ -0,0 +1,589 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "linux/list.h" -+#include "linux/devfs_fs_kernel.h" -+#include "asm/irq.h" -+#include "asm/uaccess.h" -+#include "chan_kern.h" -+#include "irq_user.h" -+#include "line.h" -+#include "kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "os.h" -+ -+#define LINE_BUFSIZE 4096 -+ -+void 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); -+} -+ -+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) -+{ -+ int end; -+ -+ if(line->buffer == NULL){ -+ line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); -+ if(line->buffer == NULL){ -+ printk("buffer_data - atomic allocation failed\n"); -+ return; -+ } -+ line->head = line->buffer; -+ line->tail = line->buffer; -+ } -+ end = line->buffer + LINE_BUFSIZE - line->tail; -+ if(len < end){ -+ memcpy(line->tail, buf, len); -+ line->tail += len; -+ } -+ else { -+ memcpy(line->tail, buf, end); -+ buf += end; -+ len -= end; -+ memcpy(line->buffer, buf, len); -+ line->tail = line->buffer + len; -+ } -+} -+ -+static int flush_buffer(struct line *line) -+{ -+ int n, count; -+ -+ if((line->buffer == NULL) || (line->head == line->tail)) return(1); -+ -+ if(line->tail < line->head){ -+ count = line->buffer + LINE_BUFSIZE - line->head; -+ n = write_chan(&line->chan_list, line->head, count, -+ line->driver->write_irq); -+ if(n < 0) return(n); -+ if(n == count) line->head = line->buffer; -+ else { -+ line->head += n; -+ return(0); -+ } -+ } -+ -+ count = line->tail - line->head; -+ n = write_chan(&line->chan_list, line->head, count, -+ line->driver->write_irq); -+ if(n < 0) return(n); -+ -+ line->head += n; -+ return(line->head == line->tail); -+} -+ -+int line_write(struct line *lines, struct tty_struct *tty, int from_user, -+ const char *buf, int len) -+{ -+ struct line *line; -+ char *new; -+ unsigned long flags; -+ int n, err, i; -+ -+ if(tty->stopped) return 0; -+ -+ if(from_user){ -+ new = kmalloc(len, GFP_KERNEL); -+ if(new == NULL) -+ return(0); -+ n = copy_from_user(new, buf, len); -+ if(n == len) -+ return(-EFAULT); -+ buf = new; -+ } -+ -+ i = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[i]; -+ -+ down(&line->sem); -+ if(line->head != line->tail){ -+ local_irq_save(flags); -+ buffer_data(line, buf, len); -+ err = flush_buffer(line); -+ local_irq_restore(flags); -+ if(err <= 0) -+ goto out; -+ } -+ else { -+ n = write_chan(&line->chan_list, buf, len, -+ line->driver->write_irq); -+ if(n < 0){ -+ len = n; -+ goto out; -+ } -+ if(n < len) -+ buffer_data(line, buf + n, len - n); -+ } -+ out: -+ up(&line->sem); -+ -+ if(from_user) -+ kfree(buf); -+ return(len); -+} -+ -+void 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; -+ else if(err < 0){ -+ dev->head = dev->buffer; -+ dev->tail = dev->buffer; -+ } -+ -+ if(tty == NULL) return; -+ -+ if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && -+ (tty->ldisc.write_wakeup != NULL)) -+ (tty->ldisc.write_wakeup)(tty); -+ -+ /* BLOCKING mode -+ * In blocking mode, everything sleeps on tty->write_wait. -+ * Sleeping in the console driver would break non-blocking -+ * writes. -+ */ -+ -+ 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); -+} -+ -+int line_setup_irq(int fd, int input, int output, void *data) -+{ -+ struct line *line = data; -+ struct line_driver *driver = line->driver; -+ int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; -+ -+ if(input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, -+ line_interrupt, flags, -+ driver->read_irq_name, line); -+ if(err) return(err); -+ if(output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, -+ line_write_interrupt, flags, -+ driver->write_irq_name, line); -+ line->have_irq = 1; -+ return(err); -+} -+ -+void line_disable(struct line *line, int current_irq) -+{ -+ if(!line->have_irq) return; -+ -+ if(line->driver->read_irq == current_irq) -+ free_irq_later(line->driver->read_irq, line); -+ else -+ free_irq(line->driver->read_irq, line); -+ -+ if(line->driver->write_irq == current_irq) -+ free_irq_later(line->driver->write_irq, line); -+ else -+ free_irq(line->driver->write_irq, line); -+ -+ line->have_irq = 0; -+} -+ -+int line_open(struct line *lines, struct tty_struct *tty, -+ struct chan_opts *opts) -+{ -+ struct line *line; -+ int n, err = 0; -+ -+ if(tty == NULL) n = 0; -+ else n = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[n]; -+ -+ down(&line->sem); -+ if(line->count == 0){ -+ if(!line->valid){ -+ err = -ENODEV; -+ goto out; -+ } -+ if(list_empty(&line->chan_list)){ -+ err = parse_chan_pair(line->init_str, &line->chan_list, -+ line->init_pri, n, opts); -+ if(err) goto out; -+ err = open_chan(&line->chan_list); -+ if(err) goto out; -+ } -+ enable_chan(&line->chan_list, line); -+ INIT_TQUEUE(&line->task, line_timer_cb, line); -+ } -+ -+ if(!line->sigio){ -+ chan_enable_winch(&line->chan_list, line); -+ line->sigio = 1; -+ } -+ -+ /* This is outside the if because the initial console is opened -+ * with tty == NULL -+ */ -+ line->tty = tty; -+ -+ if(tty != NULL){ -+ tty->driver_data = line; -+ chan_window_size(&line->chan_list, &tty->winsize.ws_row, -+ &tty->winsize.ws_col); -+ } -+ -+ line->count++; -+ out: -+ up(&line->sem); -+ return(err); -+} -+ -+void line_close(struct line *lines, struct tty_struct *tty) -+{ -+ struct line *line; -+ int n; -+ -+ if(tty == NULL) n = 0; -+ else n = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[n]; -+ -+ down(&line->sem); -+ line->count--; -+ -+ /* I don't like this, but I can't think of anything better. What's -+ * going on is that the tty is in the process of being closed for -+ * the last time. Its count hasn't been dropped yet, so it's still -+ * at 1. This may happen when line->count != 0 because of the initial -+ * console open (without a tty) bumping it up to 1. -+ */ -+ if((line->tty != NULL) && (line->tty->count == 1)) -+ line->tty = NULL; -+ if(line->count == 0) -+ line_disable(line, -1); -+ up(&line->sem); -+} -+ -+void close_lines(struct line *lines, int nlines) -+{ -+ int i; -+ -+ for(i = 0; i < nlines; i++) -+ close_chan(&lines[i].chan_list); -+} -+ -+int line_setup(struct line *lines, int num, char *init, int all_allowed) -+{ -+ int i, n; -+ char *end; -+ -+ if(*init == '=') n = -1; -+ else { -+ n = simple_strtoul(init, &end, 0); -+ if(*end != '='){ -+ printk(KERN_ERR "line_setup failed to parse \"%s\"\n", -+ init); -+ return(1); -+ } -+ init = end; -+ } -+ init++; -+ if((n >= 0) && (n >= num)){ -+ printk("line_setup - %d out of range ((0 ... %d) allowed)\n", -+ n, num); -+ return(1); -+ } -+ else if(n >= 0){ -+ if(lines[n].count > 0){ -+ printk("line_setup - device %d is open\n", n); -+ return(1); -+ } -+ if(lines[n].init_pri <= INIT_ONE){ -+ lines[n].init_pri = INIT_ONE; -+ if(!strcmp(init, "none")) lines[n].valid = 0; -+ else { -+ lines[n].init_str = init; -+ lines[n].valid = 1; -+ } -+ } -+ } -+ else if(!all_allowed){ -+ printk("line_setup - can't configure all devices from " -+ "mconsole\n"); -+ return(1); -+ } -+ else { -+ for(i = 0; i < num; i++){ -+ if(lines[i].init_pri <= INIT_ALL){ -+ lines[i].init_pri = INIT_ALL; -+ if(!strcmp(init, "none")) lines[i].valid = 0; -+ else { -+ lines[i].init_str = init; -+ lines[i].valid = 1; -+ } -+ } -+ } -+ } -+ return(0); -+} -+ -+int line_config(struct line *lines, int num, char *str) -+{ -+ char *new = uml_strdup(str); -+ -+ if(new == NULL){ -+ printk("line_config - uml_strdup failed\n"); -+ return(-ENOMEM); -+ } -+ return(line_setup(lines, num, new, 0)); -+} -+ -+int line_get_config(char *name, struct line *lines, int num, char *str, -+ int size, char **error_out) -+{ -+ struct line *line; -+ char *end; -+ int dev, n = 0; -+ -+ dev = simple_strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ *error_out = "line_get_config failed to parse device number"; -+ return(0); -+ } -+ -+ if((dev < 0) || (dev >= num)){ -+ *error_out = "device number of of range"; -+ return(0); -+ } -+ -+ 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); -+} -+ -+int line_remove(struct line *lines, int num, char *str) -+{ -+ char config[sizeof("conxxxx=none\0")]; -+ -+ sprintf(config, "%s=none", str); -+ return(line_setup(lines, num, config, 0)); -+} -+ -+void line_register_devfs(struct lines *set, struct line_driver *line_driver, -+ struct tty_driver *driver, struct line *lines, -+ int nlines) -+{ -+ int err, i, n; -+ char *from, *to; -+ -+ driver->driver_name = line_driver->name; -+ driver->name = line_driver->devfs_name; -+ driver->major = line_driver->major; -+ driver->minor_start = line_driver->minor_start; -+ driver->type = line_driver->type; -+ driver->subtype = line_driver->subtype; -+ driver->magic = TTY_DRIVER_MAGIC; -+ driver->flags = TTY_DRIVER_REAL_RAW; -+ -+ n = set->num; -+ driver->num = n; -+ driver->table = kmalloc(n * sizeof(driver->table[0]), GFP_KERNEL); -+ driver->termios = kmalloc(n * sizeof(driver->termios[0]), GFP_KERNEL); -+ driver->termios_locked = kmalloc(n * sizeof(driver->termios_locked[0]), -+ GFP_KERNEL); -+ if((driver->table == NULL) || (driver->termios == NULL) || -+ (driver->termios_locked == NULL)) -+ panic("Failed to allocate driver table"); -+ -+ memset(driver->table, 0, n * sizeof(driver->table[0])); -+ memset(driver->termios, 0, n * sizeof(driver->termios[0])); -+ memset(driver->termios_locked, 0, -+ n * sizeof(driver->termios_locked[0])); -+ -+ driver->write_room = line_write_room; -+ driver->init_termios = tty_std_termios; -+ -+ if (tty_register_driver(driver)) -+ panic("line_register_devfs : Couldn't register driver\n"); -+ -+ from = line_driver->symlink_from; -+ to = line_driver->symlink_to; -+ err = devfs_mk_symlink(NULL, from, 0, to, NULL, NULL); -+ if(err) printk("Symlink creation from /dev/%s to /dev/%s " -+ "returned %d\n", from, to, err); -+ -+ for(i = 0; i < nlines; i++){ -+ if(!lines[i].valid) -+ tty_unregister_devfs(driver, driver->minor_start + i); -+ } -+ -+ mconsole_register_dev(&line_driver->mc); -+} -+ -+void lines_init(struct line *lines, int nlines) -+{ -+ struct line *line; -+ int i; -+ -+ for(i = 0; i < nlines; i++){ -+ line = &lines[i]; -+ INIT_LIST_HEAD(&line->chan_list); -+ sema_init(&line->sem, 1); -+ if(line->init_str != NULL){ -+ line->init_str = uml_strdup(line->init_str); -+ if(line->init_str == NULL) -+ printk("lines_init - uml_strdup returned " -+ "NULL\n"); -+ } -+ } -+} -+ -+struct winch { -+ struct list_head list; -+ int fd; -+ int tty_fd; -+ int pid; -+ struct line *line; -+}; -+ -+void winch_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ struct winch *winch = data; -+ struct tty_struct *tty; -+ int err; -+ char c; -+ -+ 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; -+ } -+ goto out; -+ } -+ } -+ tty = winch->line->tty; -+ if(tty != NULL){ -+ chan_window_size(&winch->line->chan_list, -+ &tty->winsize.ws_row, -+ &tty->winsize.ws_col); -+ kill_pg(tty->pgrp, SIGWINCH, 1); -+ } -+ out: -+ if(winch->fd != -1) -+ reactivate_fd(winch->fd, WINCH_IRQ); -+} -+ -+DECLARE_MUTEX(winch_handler_sem); -+LIST_HEAD(winch_handlers); -+ -+void register_winch_irq(int fd, int tty_fd, int pid, void *line) -+{ -+ struct winch *winch; -+ -+ down(&winch_handler_sem); -+ winch = kmalloc(sizeof(*winch), GFP_KERNEL); -+ if(winch == NULL){ -+ printk("register_winch_irq - kmalloc failed\n"); -+ goto out; -+ } -+ *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), -+ .fd = fd, -+ .tty_fd = tty_fd, -+ .pid = pid, -+ .line = line }); -+ list_add(&winch->list, &winch_handlers); -+ if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "winch", winch) < 0) -+ printk("register_winch_irq - failed to register IRQ\n"); -+ out: -+ up(&winch_handler_sem); -+} -+ -+static void winch_cleanup(void) -+{ -+ struct list_head *ele; -+ struct winch *winch; -+ -+ list_for_each(ele, &winch_handlers){ -+ winch = list_entry(ele, struct winch, list); -+ if(winch->fd != -1){ -+ deactivate_fd(winch->fd, WINCH_IRQ); -+ close(winch->fd); -+ } -+ if(winch->pid != -1) -+ os_kill_process(winch->pid, 1); -+ } -+} -+ -+__uml_exitcall(winch_cleanup); -+ -+char *add_xterm_umid(char *base) -+{ -+ char *umid, *title; -+ int len; -+ -+ umid = get_umid(1); -+ if(umid == NULL) return(base); -+ -+ len = strlen(base) + strlen(" ()") + strlen(umid) + 1; -+ title = kmalloc(len, GFP_KERNEL); -+ if(title == NULL){ -+ printk("Failed to allocate buffer for xterm title\n"); -+ return(base); -+ } -+ -+ strncpy(title, base, len); -+ len -= strlen(title); -+ snprintf(&title[strlen(title)], len, " (%s)", umid); -+ return(title); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/mcast.h um/arch/um/drivers/mcast.h ---- orig/arch/um/drivers/mcast.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/mcast.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct mcast_data { -+ char *addr; -+ unsigned short port; -+ void *mcast_addr; -+ int ttl; -+ void *dev; -+}; -+ -+extern struct net_user_info mcast_user_info; -+ -+extern int mcast_user_write(int fd, void *buf, int len, -+ struct mcast_data *pri); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/mcast_kern.c um/arch/um/drivers/mcast_kern.c ---- orig/arch/um/drivers/mcast_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/mcast_kern.c Sun Dec 15 20:58:55 2002 -@@ -0,0 +1,145 @@ -+/* -+ * user-mode-linux networking multicast transport -+ * Copyright (C) 2001 by Harald Welte -+ * -+ * based on the existing uml-networking code, which is -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "linux/in.h" -+#include "linux/inet.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "mcast.h" -+ -+struct mcast_init { -+ char *addr; -+ int port; -+ int ttl; -+}; -+ -+void mcast_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct mcast_data *dpri; -+ struct mcast_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ dpri = (struct mcast_data *) pri->user; -+ *dpri = ((struct mcast_data) -+ { .addr = init->addr, -+ .port = init->port, -+ .ttl = init->ttl, -+ .mcast_addr = NULL, -+ .dev = dev }); -+ printk("mcast backend "); -+ printk("multicast adddress: %s:%u, TTL:%u ", -+ dpri->addr, dpri->port, dpri->ttl); -+ -+ printk("\n"); -+} -+ -+static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int mcast_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return mcast_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct mcast_data *) &lp->user); -+} -+ -+static struct net_kern_info mcast_kern_info = { -+ .init = mcast_init, -+ .protocol = eth_protocol, -+ .read = mcast_read, -+ .write = mcast_write, -+}; -+ -+int mcast_setup(char *str, char **mac_out, void *data) -+{ -+ struct mcast_init *init = data; -+ char *port_str = NULL, *ttl_str = NULL, *remain; -+ char *last; -+ int n; -+ -+ *init = ((struct mcast_init) -+ { .addr = "239.192.168.1", -+ .port = 1102, -+ .ttl = 1 }); -+ -+ remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, -+ NULL); -+ if(remain != NULL){ -+ printk(KERN_ERR "mcast_setup - Extra garbage on " -+ "specification : '%s'\n", remain); -+ return(0); -+ } -+ -+ if(port_str != NULL){ -+ n = simple_strtoul(port_str, &last, 10); -+ if((*last != '\0') || (last == port_str)){ -+ printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", -+ port_str); -+ return(0); -+ } -+ init->port = htons(n); -+ } -+ -+ if(ttl_str != NULL){ -+ init->ttl = simple_strtoul(ttl_str, &last, 10); -+ if((*last != '\0') || (last == ttl_str)){ -+ printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", -+ ttl_str); -+ return(0); -+ } -+ } -+ -+ printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, -+ init->port, init->ttl); -+ -+ return(1); -+} -+ -+static struct transport mcast_transport = { -+ .list = LIST_HEAD_INIT(mcast_transport.list), -+ .name = "mcast", -+ .setup = mcast_setup, -+ .user = &mcast_user_info, -+ .kern = &mcast_kern_info, -+ .private_size = sizeof(struct mcast_data), -+ .setup_size = sizeof(struct mcast_init), -+}; -+ -+static int register_mcast(void) -+{ -+ register_transport(&mcast_transport); -+ return(1); -+} -+ -+__initcall(register_mcast); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/mcast_user.c um/arch/um/drivers/mcast_user.c ---- orig/arch/um/drivers/mcast_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/mcast_user.c Sun Dec 15 21:19:16 2002 -@@ -0,0 +1,175 @@ -+/* -+ * user-mode-linux networking multicast transport -+ * Copyright (C) 2001 by Harald Welte -+ * -+ * based on the existing uml-networking code, which is -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * -+ * Licensed under the GPL. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "net_user.h" -+#include "mcast.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "user.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+static struct sockaddr_in *new_addr(char *addr, unsigned short port) -+{ -+ struct sockaddr_in *sin; -+ -+ sin = um_kmalloc(sizeof(struct sockaddr_in)); -+ if(sin == NULL){ -+ printk("new_addr: allocation of sockaddr_in failed\n"); -+ return(NULL); -+ } -+ sin->sin_family = AF_INET; -+ sin->sin_addr.s_addr = in_aton(addr); -+ sin->sin_port = port; -+ return(sin); -+} -+ -+static void mcast_user_init(void *data, void *dev) -+{ -+ struct mcast_data *pri = data; -+ -+ pri->mcast_addr = new_addr(pri->addr, pri->port); -+ pri->dev = dev; -+} -+ -+static int mcast_open(void *data) -+{ -+ struct mcast_data *pri = data; -+ struct sockaddr_in *sin = pri->mcast_addr; -+ struct ip_mreq mreq; -+ int fd, yes = 1; -+ -+ -+ if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) { -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ -+ printk("mcast_open : data socket failed, errno = %d\n", -+ errno); -+ fd = -ENOMEM; -+ goto out; -+ } -+ -+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { -+ printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", -+ errno); -+ close(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* set ttl according to config */ -+ if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, -+ sizeof(pri->ttl)) < 0) { -+ printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", -+ errno); -+ close(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* set LOOP, so data does get fed back to local sockets */ -+ 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); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* 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); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* subscribe to the multicast group */ -+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; -+ mreq.imr_interface.s_addr = 0; -+ if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, -+ &mreq, sizeof(mreq)) < 0) { -+ printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", -+ errno); -+ printk("There appears not to be a multicast-capable network " -+ "interface on the host.\n"); -+ printk("eth0 should be configured in order to use the " -+ "multicast transport.\n"); -+ close(fd); -+ fd = -EINVAL; -+ } -+ -+ out: -+ return(fd); -+} -+ -+static void mcast_close(int fd, void *data) -+{ -+ struct ip_mreq mreq; -+ struct mcast_data *pri = data; -+ struct sockaddr_in *sin = pri->mcast_addr; -+ -+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; -+ mreq.imr_interface.s_addr = 0; -+ if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, -+ &mreq, sizeof(mreq)) < 0) { -+ printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n", -+ errno); -+ } -+ -+ close(fd); -+} -+ -+int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) -+{ -+ struct sockaddr_in *data_addr = pri->mcast_addr; -+ -+ return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); -+} -+ -+static int mcast_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info mcast_user_info = { -+ .init = mcast_user_init, -+ .open = mcast_open, -+ .close = mcast_close, -+ .remove = NULL, -+ .set_mtu = mcast_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/mconsole_kern.c um/arch/um/drivers/mconsole_kern.c ---- orig/arch/um/drivers/mconsole_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/mconsole_kern.c Sun Dec 15 20:59:56 2002 -@@ -0,0 +1,453 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/slab.h" -+#include "linux/init.h" -+#include "linux/notifier.h" -+#include "linux/reboot.h" -+#include "linux/utsname.h" -+#include "linux/ctype.h" -+#include "linux/interrupt.h" -+#include "linux/sysrq.h" -+#include "linux/tqueue.h" -+#include "linux/module.h" -+#include "linux/proc_fs.h" -+#include "asm/irq.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mconsole.h" -+#include "mconsole_kern.h" -+#include "irq_user.h" -+#include "init.h" -+#include "os.h" -+#include "umid.h" -+ -+static int do_unlink_socket(struct notifier_block *notifier, -+ unsigned long what, void *data) -+{ -+ return(mconsole_unlink_socket()); -+} -+ -+ -+static struct notifier_block reboot_notifier = { -+ .notifier_call = do_unlink_socket, -+ .priority = 0, -+}; -+ -+/* Safe without explicit locking for now. Tasklets provide their own -+ * locking, and the interrupt handler is safe because it can't interrupt -+ * itself and it can only happen on CPU 0. -+ */ -+ -+LIST_HEAD(mc_requests); -+ -+void mc_task_proc(void *unused) -+{ -+ struct mconsole_entry *req; -+ unsigned long flags; -+ int done; -+ -+ do { -+ save_flags(flags); -+ req = list_entry(mc_requests.next, struct mconsole_entry, -+ list); -+ list_del(&req->list); -+ done = list_empty(&mc_requests); -+ restore_flags(flags); -+ req->request.cmd->handler(&req->request); -+ kfree(req); -+ } while(!done); -+} -+ -+struct tq_struct mconsole_task = { -+ .routine = mc_task_proc, -+ .data = NULL -+}; -+ -+void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ int fd; -+ struct mconsole_entry *new; -+ struct mc_request req; -+ -+ fd = (int) dev_id; -+ while (mconsole_get_request(fd, &req)){ -+ if(req.cmd->as_interrupt) (*req.cmd->handler)(&req); -+ else { -+ new = kmalloc(sizeof(req), GFP_ATOMIC); -+ if(new == NULL) -+ mconsole_reply(&req, "Out of memory", 1, 0); -+ else { -+ new->request = req; -+ list_add(&new->list, &mc_requests); -+ } -+ } -+ } -+ if(!list_empty(&mc_requests)) schedule_task(&mconsole_task); -+ reactivate_fd(fd, MCONSOLE_IRQ); -+} -+ -+void mconsole_version(struct mc_request *req) -+{ -+ char version[256]; -+ -+ sprintf(version, "%s %s %s %s %s", system_utsname.sysname, -+ system_utsname.nodename, system_utsname.release, -+ system_utsname.version, system_utsname.machine); -+ mconsole_reply(req, version, 0, 0); -+} -+ -+#define UML_MCONSOLE_HELPTEXT \ -+"Commands: -+ version - Get kernel version -+ help - Print this message -+ halt - Halt UML -+ reboot - Reboot UML -+ config = - Add a new device to UML; -+ same syntax as command line -+ config - Query the configuration of a device -+ remove - Remove a device from UML -+ sysrq - 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' -+" -+ -+void mconsole_help(struct mc_request *req) -+{ -+ mconsole_reply(req, UML_MCONSOLE_HELPTEXT, 0, 0); -+} -+ -+void mconsole_halt(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ machine_halt(); -+} -+ -+void mconsole_reboot(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ machine_restart(NULL); -+} -+ -+extern void ctrl_alt_del(void); -+ -+void mconsole_cad(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ ctrl_alt_del(); -+} -+ -+void mconsole_go(struct mc_request *req) -+{ -+ mconsole_reply(req, "Not stopped", 1, 0); -+} -+ -+void mconsole_stop(struct mc_request *req) -+{ -+ deactivate_fd(req->originating_fd, MCONSOLE_IRQ); -+ os_set_fd_block(req->originating_fd, 1); -+ mconsole_reply(req, "", 0, 0); -+ while(mconsole_get_request(req->originating_fd, req)){ -+ if(req->cmd->handler == mconsole_go) break; -+ (*req->cmd->handler)(req); -+ } -+ os_set_fd_block(req->originating_fd, 0); -+ reactivate_fd(req->originating_fd, MCONSOLE_IRQ); -+ mconsole_reply(req, "", 0, 0); -+} -+ -+/* This list is populated by __initcall routines. */ -+ -+LIST_HEAD(mconsole_devices); -+ -+void mconsole_register_dev(struct mc_device *new) -+{ -+ list_add(&new->list, &mconsole_devices); -+} -+ -+static struct mc_device *mconsole_find_dev(char *name) -+{ -+ struct list_head *ele; -+ struct mc_device *dev; -+ -+ list_for_each(ele, &mconsole_devices){ -+ dev = list_entry(ele, struct mc_device, list); -+ if(!strncmp(name, dev->name, strlen(dev->name))) -+ return(dev); -+ } -+ return(NULL); -+} -+ -+#define CONFIG_BUF_SIZE 64 -+ -+static void mconsole_get_config(int (*get_config)(char *, char *, int, -+ char **), -+ struct mc_request *req, char *name) -+{ -+ char default_buf[CONFIG_BUF_SIZE], *error, *buf; -+ int n, size; -+ -+ if(get_config == NULL){ -+ mconsole_reply(req, "No get_config routine defined", 1, 0); -+ return; -+ } -+ -+ error = NULL; -+ size = sizeof(default_buf)/sizeof(default_buf[0]); -+ buf = default_buf; -+ -+ while(1){ -+ n = (*get_config)(name, buf, size, &error); -+ if(error != NULL){ -+ mconsole_reply(req, error, 1, 0); -+ goto out; -+ } -+ -+ if(n <= size){ -+ mconsole_reply(req, buf, 0, 0); -+ goto out; -+ } -+ -+ if(buf != default_buf) -+ kfree(buf); -+ -+ size = n; -+ buf = kmalloc(size, GFP_KERNEL); -+ if(buf == NULL){ -+ mconsole_reply(req, "Failed to allocate buffer", 1, 0); -+ return; -+ } -+ } -+ out: -+ if(buf != default_buf) -+ kfree(buf); -+ -+} -+ -+void mconsole_config(struct mc_request *req) -+{ -+ struct mc_device *dev; -+ char *ptr = req->request.data, *name; -+ int err; -+ -+ ptr += strlen("config"); -+ while(isspace(*ptr)) ptr++; -+ dev = mconsole_find_dev(ptr); -+ if(dev == NULL){ -+ mconsole_reply(req, "Bad configuration option", 1, 0); -+ return; -+ } -+ -+ name = &ptr[strlen(dev->name)]; -+ ptr = name; -+ while((*ptr != '=') && (*ptr != '\0')) -+ ptr++; -+ -+ if(*ptr == '='){ -+ err = (*dev->config)(name); -+ mconsole_reply(req, "", err, 0); -+ } -+ else mconsole_get_config(dev->get_config, req, name); -+} -+ -+void mconsole_remove(struct mc_request *req) -+{ -+ struct mc_device *dev; -+ char *ptr = req->request.data; -+ int err; -+ -+ ptr += strlen("remove"); -+ while(isspace(*ptr)) ptr++; -+ dev = mconsole_find_dev(ptr); -+ if(dev == NULL){ -+ mconsole_reply(req, "Bad remove option", 1, 0); -+ return; -+ } -+ err = (*dev->remove)(&ptr[strlen(dev->name)]); -+ mconsole_reply(req, "", err, 0); -+} -+ -+#ifdef CONFIG_MAGIC_SYSRQ -+void mconsole_sysrq(struct mc_request *req) -+{ -+ char *ptr = req->request.data; -+ -+ ptr += strlen("sysrq"); -+ while(isspace(*ptr)) ptr++; -+ -+ handle_sysrq(*ptr, ¤t->thread.regs, NULL, NULL); -+ mconsole_reply(req, "", 0, 0); -+} -+#else -+void mconsole_sysrq(struct mc_request *req) -+{ -+ mconsole_reply(req, "Sysrq not compiled in", 1, 0); -+} -+#endif -+ -+/* Changed by mconsole_setup, which is __setup, and called before SMP is -+ * active. -+ */ -+static char *notify_socket = NULL; -+ -+int mconsole_init(void) -+{ -+ int err, sock; -+ char file[256]; -+ -+ 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)); -+ if (sock < 0){ -+ printk("Failed to initialize management console\n"); -+ return(1); -+ } -+ -+ register_reboot_notifier(&reboot_notifier); -+ -+ err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "mconsole", (void *)sock); -+ if (err){ -+ printk("Failed to get IRQ for management console\n"); -+ return(1); -+ } -+ -+ if(notify_socket != NULL){ -+ notify_socket = uml_strdup(notify_socket); -+ if(notify_socket != NULL) -+ mconsole_notify(notify_socket, MCONSOLE_SOCKET, -+ mconsole_socket_name, -+ strlen(mconsole_socket_name) + 1); -+ else printk(KERN_ERR "mconsole_setup failed to strdup " -+ "string\n"); -+ } -+ -+ printk("mconsole (version %d) initialized on %s\n", -+ MCONSOLE_VERSION, mconsole_socket_name); -+ return(0); -+} -+ -+__initcall(mconsole_init); -+ -+static int write_proc_mconsole(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ char *buf; -+ -+ buf = kmalloc(count + 1, GFP_KERNEL); -+ if(buf == NULL) -+ return(-ENOMEM); -+ -+ if(copy_from_user(buf, buffer, count)) -+ return(-EFAULT); -+ buf[count] = '\0'; -+ -+ mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); -+ return(count); -+} -+ -+static int create_proc_mconsole(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ if(notify_socket == NULL) return(0); -+ -+ ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); -+ if(ent == NULL){ -+ printk("create_proc_mconsole : create_proc_entry failed\n"); -+ return(0); -+ } -+ -+ ent->read_proc = NULL; -+ ent->write_proc = write_proc_mconsole; -+ return(0); -+} -+ -+static spinlock_t notify_spinlock = SPIN_LOCK_UNLOCKED; -+ -+void lock_notify(void) -+{ -+ spin_lock(¬ify_spinlock); -+} -+ -+void unlock_notify(void) -+{ -+ spin_unlock(¬ify_spinlock); -+} -+ -+__initcall(create_proc_mconsole); -+ -+#define NOTIFY "=notify:" -+ -+static int mconsole_setup(char *str) -+{ -+ if(!strncmp(str, NOTIFY, strlen(NOTIFY))){ -+ str += strlen(NOTIFY); -+ notify_socket = str; -+ } -+ else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str); -+ return(1); -+} -+ -+__setup("mconsole", mconsole_setup); -+ -+__uml_help(mconsole_setup, -+"mconsole=notify:\n" -+" Requests that the mconsole driver send a message to the named Unix\n" -+" socket containing the name of the mconsole socket. This also serves\n" -+" to notify outside processes when UML has booted far enough to respond\n" -+" to mconsole requests.\n\n" -+); -+ -+static int notify_panic(struct notifier_block *self, unsigned long unused1, -+ void *ptr) -+{ -+ char *message = ptr; -+ -+ if(notify_socket == NULL) return(0); -+ -+ mconsole_notify(notify_socket, MCONSOLE_PANIC, message, -+ strlen(message) + 1); -+ return(0); -+} -+ -+static struct notifier_block panic_exit_notifier = { -+ .notifier_call = notify_panic, -+ .next = NULL, -+ .priority = 1 -+}; -+ -+static int add_notifier(void) -+{ -+ notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); -+ return(0); -+} -+ -+__initcall(add_notifier); -+ -+char *mconsole_notify_socket(void) -+{ -+ return(notify_socket); -+} -+ -+EXPORT_SYMBOL(mconsole_notify_socket); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/mconsole_user.c um/arch/um/drivers/mconsole_user.c ---- orig/arch/um/drivers/mconsole_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/mconsole_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,212 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user.h" -+#include "mconsole.h" -+#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 }, -+}; -+ -+/* Initialized in mconsole_init, which is an initcall */ -+char mconsole_socket_name[256]; -+ -+int mconsole_reply_v0(struct mc_request *req, char *reply) -+{ -+ struct iovec iov; -+ struct msghdr msg; -+ -+ iov.iov_base = reply; -+ iov.iov_len = strlen(reply); -+ -+ msg.msg_name = &(req->origin); -+ msg.msg_namelen = req->originlen; -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ msg.msg_control = NULL; -+ msg.msg_controllen = 0; -+ msg.msg_flags = 0; -+ -+ return sendmsg(req->originating_fd, &msg, 0); -+} -+ -+static struct mconsole_command *mconsole_parse(struct mc_request *req) -+{ -+ struct mconsole_command *cmd; -+ int i; -+ -+ for(i=0;irequest.data, cmd->command, -+ strlen(cmd->command))){ -+ return(cmd); -+ } -+ } -+ return(NULL); -+} -+ -+#define MIN(a,b) ((a)<(b) ? (a):(b)) -+ -+#define STRINGX(x) #x -+#define STRING(x) STRINGX(x) -+ -+int mconsole_get_request(int fd, struct mc_request *req) -+{ -+ int len; -+ -+ req->originlen = sizeof(req->origin); -+ req->len = recvfrom(fd, &req->request, sizeof(req->request), 0, -+ (struct sockaddr *) req->origin, &req->originlen); -+ if (req->len < 0) -+ return 0; -+ -+ req->originating_fd = fd; -+ -+ if(req->request.magic != MCONSOLE_MAGIC){ -+ /* Unversioned request */ -+ len = MIN(sizeof(req->request.data) - 1, -+ strlen((char *) &req->request)); -+ memmove(req->request.data, &req->request, len); -+ req->request.data[len] = '\0'; -+ -+ req->request.magic = MCONSOLE_MAGIC; -+ req->request.version = 0; -+ req->request.len = len; -+ -+ mconsole_reply_v0(req, "ERR Version 0 mconsole clients are " -+ "not supported by this driver"); -+ return(0); -+ } -+ -+ if(req->request.len >= MCONSOLE_MAX_DATA){ -+ mconsole_reply(req, "Request too large", 1, 0); -+ return(0); -+ } -+ if(req->request.version != MCONSOLE_VERSION){ -+ mconsole_reply(req, "This driver only supports version " -+ STRING(MCONSOLE_VERSION) " clients", 1, 0); -+ } -+ -+ req->request.data[req->request.len] = '\0'; -+ req->cmd = mconsole_parse(req); -+ if(req->cmd == NULL){ -+ mconsole_reply(req, "Unknown command", 1, 0); -+ return(0); -+ } -+ -+ return(1); -+} -+ -+int mconsole_reply(struct mc_request *req, char *str, int err, int more) -+{ -+ struct mconsole_reply reply; -+ int total, len, n; -+ -+ total = strlen(str); -+ do { -+ reply.err = err; -+ -+ /* err can only be true on the first packet */ -+ err = 0; -+ -+ len = MIN(total, MCONSOLE_MAX_DATA - 1); -+ -+ if(len == total) reply.more = more; -+ else reply.more = 1; -+ -+ memcpy(reply.data, str, len); -+ reply.data[len] = '\0'; -+ total -= len; -+ reply.len = len + 1; -+ -+ len = sizeof(reply) + reply.len - sizeof(reply.data); -+ -+ n = sendto(req->originating_fd, &reply, len, 0, -+ (struct sockaddr *) req->origin, req->originlen); -+ -+ if(n < 0) return(-errno); -+ } while(total > 0); -+ return(0); -+} -+ -+int mconsole_unlink_socket(void) -+{ -+ unlink(mconsole_socket_name); -+ return 0; -+} -+ -+static int notify_sock = -1; -+ -+int mconsole_notify(char *sock_name, int type, const void *data, int len) -+{ -+ struct sockaddr_un target; -+ struct mconsole_notify packet; -+ int n, err = 0; -+ -+ lock_notify(); -+ if(notify_sock < 0){ -+ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); -+ if(notify_sock < 0){ -+ printk("mconsole_notify - socket failed, errno = %d\n", -+ errno); -+ err = -errno; -+ } -+ } -+ unlock_notify(); -+ -+ if(err) -+ return(err); -+ -+ target.sun_family = AF_UNIX; -+ strcpy(target.sun_path, sock_name); -+ -+ packet.magic = MCONSOLE_MAGIC; -+ packet.version = MCONSOLE_VERSION; -+ packet.type = type; -+ len = (len > sizeof(packet.data)) ? sizeof(packet.data) : len; -+ packet.len = len; -+ memcpy(packet.data, data, len); -+ -+ err = 0; -+ len = sizeof(packet) + packet.len - sizeof(packet.data); -+ n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, -+ sizeof(target)); -+ if(n < 0){ -+ printk("mconsole_notify - sendto failed, errno = %d\n", errno); -+ err = -errno; -+ } -+ 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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/mmapper_kern.c um/arch/um/drivers/mmapper_kern.c ---- orig/arch/um/drivers/mmapper_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/mmapper_kern.c Sun Dec 15 21:03:08 2002 -@@ -0,0 +1,148 @@ -+/* -+ * arch/um/drivers/mmapper_kern.c -+ * -+ * BRIEF MODULE DESCRIPTION -+ * -+ * Copyright (C) 2000 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mem_user.h" -+#include "user_util.h" -+ -+/* These are set in mmapper_init, which is called at boot time */ -+static unsigned long mmapper_size; -+static unsigned long p_buf = 0; -+static char *v_buf = NULL; -+ -+static ssize_t -+mmapper_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ if(*ppos > mmapper_size) -+ return -EINVAL; -+ -+ if(count + *ppos > mmapper_size) -+ count = count + *ppos - mmapper_size; -+ -+ if(count < 0) -+ return -EINVAL; -+ -+ copy_to_user(buf,&v_buf[*ppos],count); -+ -+ return count; -+} -+ -+static ssize_t -+mmapper_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -+{ -+ if(*ppos > mmapper_size) -+ return -EINVAL; -+ -+ if(count + *ppos > mmapper_size) -+ count = count + *ppos - mmapper_size; -+ -+ if(count < 0) -+ return -EINVAL; -+ -+ copy_from_user(&v_buf[*ppos],buf,count); -+ -+ return count; -+} -+ -+static int -+mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ return(-ENOIOCTLCMD); -+} -+ -+static int -+mmapper_mmap(struct file *file, struct vm_area_struct * vma) -+{ -+ int ret = -EINVAL; -+ int size; -+ -+ lock_kernel(); -+ if (vma->vm_pgoff != 0) -+ goto out; -+ -+ size = vma->vm_end - vma->vm_start; -+ if(size > mmapper_size) return(-EFAULT); -+ -+ /* XXX A comment above remap_page_range says it should only be -+ * called when the mm semaphore is held -+ */ -+ if (remap_page_range(vma->vm_start, p_buf, size, vma->vm_page_prot)) -+ goto out; -+ ret = 0; -+out: -+ unlock_kernel(); -+ return ret; -+} -+ -+static int -+mmapper_open(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static int -+mmapper_release(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static struct file_operations mmapper_fops = { -+ .owner = THIS_MODULE, -+ .read = mmapper_read, -+ .write = mmapper_write, -+ .ioctl = mmapper_ioctl, -+ .mmap = mmapper_mmap, -+ .open = mmapper_open, -+ .release = mmapper_release, -+}; -+ -+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); -+ -+ p_buf = __pa(v_buf); -+ -+ devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT, -+ 30, 0, S_IFCHR | S_IRUGO | S_IWUGO, -+ &mmapper_fops, NULL); -+ devfs_mk_symlink(NULL, "mmapper0", DEVFS_FL_DEFAULT, "mmapper", -+ NULL, NULL); -+ return(0); -+} -+ -+static void mmapper_exit(void) -+{ -+} -+ -+module_init(mmapper_init); -+module_exit(mmapper_exit); -+ -+MODULE_AUTHOR("Greg Lonnon "); -+MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/net_kern.c um/arch/um/drivers/net_kern.c ---- orig/arch/um/drivers/net_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/net_kern.c Sun Dec 15 21:19:16 2002 -@@ -0,0 +1,870 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/netdevice.h" -+#include "linux/rtnetlink.h" -+#include "linux/skbuff.h" -+#include "linux/socket.h" -+#include "linux/spinlock.h" -+#include "linux/module.h" -+#include "linux/init.h" -+#include "linux/etherdevice.h" -+#include "linux/list.h" -+#include "linux/inetdevice.h" -+#include "linux/ctype.h" -+#include "linux/bootmem.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "irq_user.h" -+ -+static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED; -+LIST_HEAD(opened); -+ -+static int uml_net_rx(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ int pkt_len; -+ struct sk_buff *skb; -+ -+ /* If we can't allocate memory, try again next round. */ -+ if ((skb = dev_alloc_skb(dev->mtu)) == NULL) { -+ lp->stats.rx_dropped++; -+ return 0; -+ } -+ -+ skb->dev = dev; -+ skb_put(skb, dev->mtu); -+ skb->mac.raw = skb->data; -+ pkt_len = (*lp->read)(lp->fd, &skb, lp); -+ -+ if (pkt_len > 0) { -+ skb_trim(skb, pkt_len); -+ skb->protocol = (*lp->protocol)(skb); -+ netif_rx(skb); -+ -+ lp->stats.rx_bytes += skb->len; -+ lp->stats.rx_packets++; -+ return pkt_len; -+ } -+ -+ kfree_skb(skb); -+ return pkt_len; -+} -+ -+void 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; -+ -+ spin_lock(&lp->lock); -+ while((err = uml_net_rx(dev)) > 0) ; -+ if(err < 0) { -+ printk(KERN_ERR -+ "Device '%s' read returned %d, shutting it down\n", -+ dev->name, err); -+ dev_close(dev); -+ goto out; -+ } -+ reactivate_fd(lp->fd, UM_ETH_IRQ); -+ -+ out: -+ spin_unlock(&lp->lock); -+} -+ -+static int uml_net_open(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ char addr[sizeof("255.255.255.255\0")]; -+ int err; -+ -+ spin_lock(&lp->lock); -+ -+ if(lp->fd >= 0){ -+ err = -ENXIO; -+ goto out; -+ } -+ -+ if(!lp->have_mac){ -+ dev_ip_addr(dev, addr, &lp->mac[2]); -+ set_ether_mac(dev, lp->mac); -+ } -+ -+ lp->fd = (*lp->open)(&lp->user); -+ if(lp->fd < 0){ -+ err = lp->fd; -+ goto out; -+ } -+ -+ err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, -+ SA_INTERRUPT | SA_SHIRQ, dev->name, dev); -+ if(err != 0){ -+ printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ lp->fd = -1; -+ err = -ENETUNREACH; -+ } -+ -+ lp->tl.data = (unsigned long) &lp->user; -+ netif_start_queue(dev); -+ -+ spin_lock(&opened_lock); -+ list_add(&lp->list, &opened); -+ spin_unlock(&opened_lock); -+ MOD_INC_USE_COUNT; -+ out: -+ spin_unlock(&lp->lock); -+ return(err); -+} -+ -+static int uml_net_close(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ -+ netif_stop_queue(dev); -+ spin_lock(&lp->lock); -+ -+ free_irq(dev->irq, dev); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ lp->fd = -1; -+ spin_lock(&opened_lock); -+ list_del(&lp->list); -+ spin_unlock(&opened_lock); -+ -+ MOD_DEC_USE_COUNT; -+ spin_unlock(&lp->lock); -+ return 0; -+} -+ -+static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ unsigned long flags; -+ int len; -+ -+ netif_stop_queue(dev); -+ -+ spin_lock_irqsave(&lp->lock, flags); -+ -+ len = (*lp->write)(lp->fd, &skb, lp); -+ -+ if(len == skb->len) { -+ lp->stats.tx_packets++; -+ lp->stats.tx_bytes += skb->len; -+ dev->trans_start = jiffies; -+ netif_start_queue(dev); -+ -+ /* this is normally done in the interrupt when tx finishes */ -+ netif_wake_queue(dev); -+ } -+ else if(len == 0){ -+ netif_start_queue(dev); -+ lp->stats.tx_dropped++; -+ } -+ else { -+ netif_start_queue(dev); -+ printk(KERN_ERR "uml_net_start_xmit: failed(%d)\n", len); -+ } -+ -+ spin_unlock_irqrestore(&lp->lock, flags); -+ -+ dev_kfree_skb(skb); -+ -+ return 0; -+} -+ -+static struct net_device_stats *uml_net_get_stats(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ return &lp->stats; -+} -+ -+static void uml_net_set_multicast_list(struct net_device *dev) -+{ -+ if (dev->flags & IFF_PROMISC) return; -+ else if (dev->mc_count) dev->flags |= IFF_ALLMULTI; -+ else dev->flags &= ~IFF_ALLMULTI; -+} -+ -+static void uml_net_tx_timeout(struct net_device *dev) -+{ -+ dev->trans_start = jiffies; -+ netif_wake_queue(dev); -+} -+ -+static int uml_net_set_mac(struct net_device *dev, void *addr) -+{ -+ struct uml_net_private *lp = dev->priv; -+ struct sockaddr *hwaddr = addr; -+ -+ spin_lock(&lp->lock); -+ memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); -+ spin_unlock(&lp->lock); -+ -+ return(0); -+} -+ -+static int uml_net_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ struct uml_net_private *lp = dev->priv; -+ int err = 0; -+ -+ spin_lock(&lp->lock); -+ -+ new_mtu = (*lp->set_mtu)(new_mtu, &lp->user); -+ if(new_mtu < 0){ -+ err = new_mtu; -+ goto out; -+ } -+ -+ dev->mtu = new_mtu; -+ -+ out: -+ spin_unlock(&lp->lock); -+ return err; -+} -+ -+static int uml_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -+{ -+ return(-EINVAL); -+} -+ -+void uml_net_user_timer_expire(unsigned long _conn) -+{ -+#ifdef undef -+ struct connection *conn = (struct connection *)_conn; -+ -+ dprintk(KERN_INFO "uml_net_user_timer_expire [%p]\n", conn); -+ do_connect(conn); -+#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); -+ -+static int eth_configure(int n, void *init, char *mac, -+ struct transport *transport) -+{ -+ struct uml_net *device; -+ struct net_device *dev; -+ struct uml_net_private *lp; -+ int save, err, size; -+ -+ size = transport->private_size + sizeof(struct uml_net_private) + -+ sizeof(((struct uml_net_private *) 0)->user); -+ -+ device = kmalloc(sizeof(*device), GFP_KERNEL); -+ if(device == NULL){ -+ printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); -+ return(1); -+ } -+ -+ *device = ((struct uml_net) { .list = LIST_HEAD_INIT(device->list), -+ .dev = NULL, -+ .index = n, -+ .mac = { [ 0 ... 5 ] = 0 }, -+ .have_mac = 0 }); -+ -+ spin_lock(&devices_lock); -+ list_add(&device->list, &devices); -+ spin_unlock(&devices_lock); -+ -+ if(setup_etheraddr(mac, device->mac)) -+ device->have_mac = 1; -+ -+ printk(KERN_INFO "Netdevice %d ", n); -+ if(device->have_mac) printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", -+ device->mac[0], device->mac[1], -+ device->mac[2], device->mac[3], -+ device->mac[4], device->mac[5]); -+ printk(": "); -+ dev = kmalloc(sizeof(*dev) + size, GFP_KERNEL); -+ if(dev == NULL){ -+ printk(KERN_ERR "eth_configure: failed to allocate device\n"); -+ return(1); -+ } -+ memset(dev, 0, sizeof(*dev) + size); -+ -+ snprintf(dev->name, sizeof(dev->name), "eth%d", n); -+ dev->priv = (void *) &dev[1]; -+ 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; -+ dev->open = uml_net_open; -+ dev->hard_start_xmit = uml_net_start_xmit; -+ dev->stop = uml_net_close; -+ dev->get_stats = uml_net_get_stats; -+ dev->set_multicast_list = uml_net_set_multicast_list; -+ dev->tx_timeout = uml_net_tx_timeout; -+ dev->set_mac_address = uml_net_set_mac; -+ dev->change_mtu = uml_net_change_mtu; -+ dev->do_ioctl = uml_net_ioctl; -+ dev->watchdog_timeo = (HZ >> 1); -+ dev->irq = UM_ETH_IRQ; -+ -+ rtnl_lock(); -+ err = register_netdevice(dev); -+ rtnl_unlock(); -+ if(err) -+ return(1); -+ lp = dev->priv; -+ -+ /* 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; -+ memset(&lp->stats, 0, sizeof(lp->stats)); -+ if(lp->have_mac) memcpy(lp->mac, device->mac, sizeof(lp->mac)); -+ -+ if(transport->user->init) -+ (*transport->user->init)(&lp->user, dev); -+ -+ if(device->have_mac) -+ set_ether_mac(dev, device->mac); -+ return(0); -+} -+ -+static struct uml_net *find_device(int n) -+{ -+ struct uml_net *device; -+ struct list_head *ele; -+ -+ spin_lock(&devices_lock); -+ list_for_each(ele, &devices){ -+ device = list_entry(ele, struct uml_net, list); -+ if(device->index == n) -+ goto out; -+ } -+ device = NULL; -+ out: -+ spin_unlock(&devices_lock); -+ return(device); -+} -+ -+static int eth_parse(char *str, int *index_out, char **str_out) -+{ -+ char *end; -+ int n; -+ -+ n = simple_strtoul(str, &end, 0); -+ if(end == str){ -+ printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str); -+ return(1); -+ } -+ if(n < 0){ -+ printk(KERN_ERR "eth_setup: device %d is negative\n", n); -+ return(1); -+ } -+ str = end; -+ if(*str != '='){ -+ printk(KERN_ERR -+ "eth_setup: expected '=' after device number\n"); -+ return(1); -+ } -+ str++; -+ if(find_device(n)){ -+ printk(KERN_ERR "eth_setup: Device %d already configured\n", -+ n); -+ return(1); -+ } -+ if(index_out) *index_out = n; -+ *str_out = str; -+ return(0); -+} -+ -+struct eth_init { -+ struct list_head list; -+ char *init; -+ int index; -+}; -+ -+/* Filled in at boot time. Will need locking if the transports become -+ * modular. -+ */ -+struct list_head transports = LIST_HEAD_INIT(transports); -+ -+/* Filled in during early boot */ -+struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line); -+ -+static int check_transport(struct transport *transport, char *eth, int n, -+ void **init_out, char **mac_out) -+{ -+ int len; -+ -+ len = strlen(transport->name); -+ if(strncmp(eth, transport->name, len)) -+ return(0); -+ -+ eth += len; -+ if(*eth == ',') -+ eth++; -+ else if(*eth != '\0') -+ return(0); -+ -+ *init_out = kmalloc(transport->setup_size, GFP_KERNEL); -+ if(*init_out == NULL) -+ return(1); -+ -+ if(!transport->setup(eth, mac_out, *init_out)){ -+ kfree(*init_out); -+ *init_out = NULL; -+ } -+ return(1); -+} -+ -+void register_transport(struct transport *new) -+{ -+ struct list_head *ele, *next; -+ struct eth_init *eth; -+ void *init; -+ char *mac = NULL; -+ int match; -+ -+ list_add(&new->list, &transports); -+ -+ list_for_each_safe(ele, next, ð_cmd_line){ -+ eth = list_entry(ele, struct eth_init, list); -+ match = check_transport(new, eth->init, eth->index, &init, -+ &mac); -+ if(!match) -+ continue; -+ else if(init != NULL){ -+ eth_configure(eth->index, init, mac, new); -+ kfree(init); -+ } -+ list_del(ð->list); -+ } -+} -+ -+static int eth_setup_common(char *str, int index) -+{ -+ struct list_head *ele; -+ struct transport *transport; -+ void *init; -+ char *mac = NULL; -+ -+ list_for_each(ele, &transports){ -+ transport = list_entry(ele, struct transport, list); -+ if(!check_transport(transport, str, index, &init, &mac)) -+ continue; -+ if(init != NULL){ -+ eth_configure(index, init, mac, transport); -+ kfree(init); -+ } -+ return(1); -+ } -+ return(0); -+} -+ -+static int eth_setup(char *str) -+{ -+ struct eth_init *new; -+ int n, err; -+ -+ err = eth_parse(str, &n, &str); -+ if(err) return(1); -+ -+ new = alloc_bootmem(sizeof(new)); -+ if(new == NULL){ -+ printk("eth_init : alloc_bootmem failed\n"); -+ return(1); -+ } -+ *new = ((struct eth_init) { .list = LIST_HEAD_INIT(new->list), -+ .index = n, -+ .init = str }); -+ list_add_tail(&new->list, ð_cmd_line); -+ return(1); -+} -+ -+__setup("eth", eth_setup); -+__uml_help(eth_setup, -+"eth[0-9]+=,\n" -+" Configure a network device.\n\n" -+); -+ -+static int eth_init(void) -+{ -+ struct list_head *ele, *next; -+ struct eth_init *eth; -+ -+ list_for_each_safe(ele, next, ð_cmd_line){ -+ eth = list_entry(ele, struct eth_init, list); -+ -+ if(eth_setup_common(eth->init, eth->index)) -+ list_del(ð->list); -+ } -+ -+ return(1); -+} -+ -+__initcall(eth_init); -+ -+static int net_config(char *str) -+{ -+ int n, err; -+ -+ err = eth_parse(str, &n, &str); -+ if(err) return(err); -+ -+ str = uml_strdup(str); -+ if(str == NULL){ -+ printk(KERN_ERR "net_config failed to strdup string\n"); -+ return(-1); -+ } -+ err = !eth_setup_common(str, n); -+ if(err) -+ kfree(str); -+ return(err); -+} -+ -+static int net_remove(char *str) -+{ -+ struct uml_net *device; -+ struct net_device *dev; -+ struct uml_net_private *lp; -+ char *end; -+ int n; -+ -+ n = simple_strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)) -+ return(-1); -+ -+ device = find_device(n); -+ if(device == NULL) -+ return(0); -+ -+ dev = device->dev; -+ lp = dev->priv; -+ if(lp->fd > 0) return(-1); -+ if(lp->remove != NULL) (*lp->remove)(&lp->user); -+ unregister_netdev(dev); -+ -+ list_del(&device->list); -+ kfree(device); -+ return(0); -+} -+ -+static struct mc_device net_mc = { -+ .name = "eth", -+ .config = net_config, -+ .get_config = NULL, -+ .remove = net_remove, -+}; -+ -+static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, -+ void *ptr) -+{ -+ struct in_ifaddr *ifa = ptr; -+ u32 addr = ifa->ifa_address; -+ u32 netmask = ifa->ifa_mask; -+ struct net_device *dev = ifa->ifa_dev->dev; -+ struct uml_net_private *lp; -+ void (*proc)(unsigned char *, unsigned char *, void *); -+ unsigned char addr_buf[4], netmask_buf[4]; -+ -+ if(dev->open != uml_net_open) return(NOTIFY_DONE); -+ -+ lp = dev->priv; -+ -+ proc = NULL; -+ switch (event){ -+ case NETDEV_UP: -+ proc = lp->add_address; -+ break; -+ case NETDEV_DOWN: -+ proc = lp->delete_address; -+ break; -+ } -+ if(proc != NULL){ -+ addr_buf[0] = addr & 0xff; -+ addr_buf[1] = (addr >> 8) & 0xff; -+ addr_buf[2] = (addr >> 16) & 0xff; -+ addr_buf[3] = addr >> 24; -+ netmask_buf[0] = netmask & 0xff; -+ netmask_buf[1] = (netmask >> 8) & 0xff; -+ netmask_buf[2] = (netmask >> 16) & 0xff; -+ netmask_buf[3] = netmask >> 24; -+ (*proc)(addr_buf, netmask_buf, &lp->user); -+ } -+ return(NOTIFY_DONE); -+} -+ -+struct notifier_block uml_inetaddr_notifier = { -+ .notifier_call = uml_inetaddr_event, -+}; -+ -+static int uml_net_init(void) -+{ -+ struct list_head *ele; -+ struct uml_net_private *lp; -+ struct in_device *ip; -+ struct in_ifaddr *in; -+ -+ mconsole_register_dev(&net_mc); -+ register_inetaddr_notifier(¨_inetaddr_notifier); -+ -+ /* Devices may have been opened already, so the uml_inetaddr_notifier -+ * didn't get a chance to run for them. This fakes it so that -+ * addresses which have already been set up get handled properly. -+ */ -+ list_for_each(ele, &opened){ -+ lp = list_entry(ele, struct uml_net_private, list); -+ ip = lp->dev->ip_ptr; -+ if(ip == NULL) continue; -+ in = ip->ifa_list; -+ while(in != NULL){ -+ uml_inetaddr_event(NULL, NETDEV_UP, in); -+ in = in->ifa_next; -+ } -+ } -+ -+ return(0); -+} -+ -+__initcall(uml_net_init); -+ -+static void close_devices(void) -+{ -+ struct list_head *ele; -+ struct uml_net_private *lp; -+ -+ list_for_each(ele, &opened){ -+ lp = list_entry(ele, struct uml_net_private, list); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ if(lp->remove != NULL) (*lp->remove)(&lp->user); -+ } -+} -+ -+__uml_exitcall(close_devices); -+ -+int setup_etheraddr(char *str, unsigned char *addr) -+{ -+ char *end; -+ int i; -+ -+ if(str == NULL) -+ return(0); -+ for(i=0;i<6;i++){ -+ addr[i] = simple_strtoul(str, &end, 16); -+ if((end == str) || -+ ((*end != ':') && (*end != ',') && (*end != '\0'))){ -+ printk(KERN_ERR -+ "setup_etheraddr: failed to parse '%s' " -+ "as an ethernet address\n", str); -+ return(0); -+ } -+ str = end + 1; -+ } -+ if(addr[0] & 1){ -+ printk(KERN_ERR -+ "Attempt to assign a broadcast ethernet address to a " -+ "device disallowed\n"); -+ return(0); -+ } -+ return(1); -+} -+ -+void dev_ip_addr(void *d, char *buf, char *bin_buf) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ u32 addr; -+ -+ if((ip == NULL) || ((in = ip->ifa_list) == NULL)){ -+ printk(KERN_WARNING "dev_ip_addr - device not assigned an " -+ "IP address\n"); -+ return; -+ } -+ addr = in->ifa_address; -+ sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff, -+ (addr >> 16) & 0xff, addr >> 24); -+ if(bin_buf){ -+ bin_buf[0] = addr & 0xff; -+ bin_buf[1] = (addr >> 8) & 0xff; -+ bin_buf[2] = (addr >> 16) & 0xff; -+ bin_buf[3] = addr >> 24; -+ } -+} -+ -+void set_ether_mac(void *d, unsigned char *addr) -+{ -+ struct net_device *dev = d; -+ -+ memcpy(dev->dev_addr, addr, ETH_ALEN); -+} -+ -+struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) -+{ -+ if((skb != NULL) && (skb_tailroom(skb) < extra)){ -+ struct sk_buff *skb2; -+ -+ skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC); -+ dev_kfree_skb(skb); -+ skb = skb2; -+ } -+ if(skb != NULL) skb_put(skb, extra); -+ return(skb); -+} -+ -+void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, -+ void *), -+ void *arg) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ unsigned char address[4], netmask[4]; -+ -+ if(ip == NULL) return; -+ in = ip->ifa_list; -+ while(in != NULL){ -+ address[0] = in->ifa_address & 0xff; -+ address[1] = (in->ifa_address >> 8) & 0xff; -+ address[2] = (in->ifa_address >> 16) & 0xff; -+ address[3] = in->ifa_address >> 24; -+ netmask[0] = in->ifa_mask & 0xff; -+ netmask[1] = (in->ifa_mask >> 8) & 0xff; -+ netmask[2] = (in->ifa_mask >> 16) & 0xff; -+ netmask[3] = in->ifa_mask >> 24; -+ (*cb)(address, netmask, arg); -+ in = in->ifa_next; -+ } -+} -+ -+int dev_netmask(void *d, void *m) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ __u32 *mask_out = m; -+ -+ if(ip == NULL) -+ return(1); -+ -+ in = ip->ifa_list; -+ if(in == NULL) -+ return(1); -+ -+ *mask_out = in->ifa_mask; -+ return(0); -+} -+ -+void *get_output_buffer(int *len_out) -+{ -+ void *ret; -+ -+ ret = (void *) __get_free_pages(GFP_KERNEL, 0); -+ if(ret) *len_out = PAGE_SIZE; -+ else *len_out = 0; -+ return(ret); -+} -+ -+void free_output_buffer(void *buffer) -+{ -+ free_pages((unsigned long) buffer, 0); -+} -+ -+int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, -+ char **gate_addr) -+{ -+ char *remain; -+ -+ remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL); -+ if(remain != NULL){ -+ printk("tap_setup_common - Extra garbage on specification : " -+ "'%s'\n", remain); -+ return(1); -+ } -+ -+ return(0); -+} -+ -+unsigned short eth_protocol(struct sk_buff *skb) -+{ -+ return(eth_type_trans(skb, skb->dev)); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/net_user.c um/arch/um/drivers/net_user.c ---- orig/arch/um/drivers/net_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/net_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,254 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "net_user.h" -+#include "helper.h" -+#include "os.h" -+ -+int tap_open_common(void *dev, char *gate_addr) -+{ -+ int tap_addr[4]; -+ -+ 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); -+ return(-EINVAL); -+ } -+ return(0); -+} -+ -+void tap_check_ips(char *gate_addr, char *eth_addr) -+{ -+ int tap_addr[4]; -+ -+ if((gate_addr != NULL) && -+ (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], -+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && -+ (eth_addr[0] == tap_addr[0]) && -+ (eth_addr[1] == tap_addr[1]) && -+ (eth_addr[2] == tap_addr[2]) && -+ (eth_addr[3] == tap_addr[3])){ -+ printk("The tap IP address and the UML eth IP address" -+ " must be different\n"); -+ } -+} -+ -+void read_output(int fd, char *output, int len) -+{ -+ int remain, n, actual; -+ char c; -+ -+ if(output == NULL){ -+ output = &c; -+ len = sizeof(c); -+ } -+ -+ *output = '\0'; -+ if(read(fd, &remain, sizeof(remain)) != sizeof(remain)){ -+ printk("read_output - read of length failed, errno = %d\n", -+ errno); -+ return; -+ } -+ -+ while(remain != 0){ -+ n = (remain < len) ? remain : len; -+ actual = read(fd, output, n); -+ if(actual != n){ -+ printk("read_output - read of data failed, " -+ "errno = %d\n", errno); -+ return; -+ } -+ remain -= actual; -+ } -+ return; -+} -+ -+int net_read(int fd, void *buf, int len) -+{ -+ int n; -+ -+ while(((n = read(fd, buf, len)) < 0) && (errno == EINTR)) ; -+ -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+int net_recvfrom(int fd, void *buf, int len) -+{ -+ int n; -+ -+ while(((n = recvfrom(fd, buf, len, 0, NULL, NULL)) < 0) && -+ (errno == EINTR)) ; -+ -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+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); -+} -+ -+int net_send(int fd, void *buf, int len) -+{ -+ int n; -+ -+ while(((n = send(fd, buf, len, 0)) < 0) && (errno == EINTR)) ; -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+int net_sendto(int fd, void *buf, int len, void *to, int sock_len) -+{ -+ int n; -+ -+ while(((n = sendto(fd, buf, len, 0, (struct sockaddr *) to, -+ sock_len)) < 0) && (errno == EINTR)) ; -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+struct change_pre_exec_data { -+ int close_me; -+ int stdout; -+}; -+ -+static void change_pre_exec(void *arg) -+{ -+ struct change_pre_exec_data *data = arg; -+ -+ close(data->close_me); -+ dup2(data->stdout, 1); -+} -+ -+static int change_tramp(char **argv, char *output, int output_len) -+{ -+ int pid, fds[2], err; -+ struct change_pre_exec_data pe_data; -+ -+ err = os_pipe(fds, 1, 0); -+ if(err){ -+ printk("change_tramp - pipe failed, errno = %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]); -+ read_output(fds[0], output, output_len); -+ waitpid(pid, NULL, 0); -+ return(pid); -+} -+ -+static void change(char *dev, char *what, unsigned char *addr, -+ unsigned char *netmask) -+{ -+ char addr_buf[sizeof("255.255.255.255\0")]; -+ char netmask_buf[sizeof("255.255.255.255\0")]; -+ char version[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version, what, dev, addr_buf, -+ netmask_buf, NULL }; -+ char *output; -+ int output_len, pid; -+ -+ sprintf(version, "%d", UML_NET_VERSION); -+ sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); -+ sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], -+ netmask[2], netmask[3]); -+ -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ if(output == NULL) -+ printk("change : failed to allocate output buffer\n"); -+ -+ pid = change_tramp(argv, output, output_len); -+ if(pid < 0) return; -+ -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+} -+ -+void open_addr(unsigned char *addr, unsigned char *netmask, void *arg) -+{ -+ change(arg, "add", addr, netmask); -+} -+ -+void close_addr(unsigned char *addr, unsigned char *netmask, void *arg) -+{ -+ change(arg, "del", addr, netmask); -+} -+ -+char *split_if_spec(char *str, ...) -+{ -+ char **arg, *end; -+ va_list ap; -+ -+ va_start(ap, str); -+ while((arg = va_arg(ap, char **)) != NULL){ -+ if(*str == '\0') -+ return(NULL); -+ end = strchr(str, ','); -+ if(end != str) -+ *arg = str; -+ if(end == NULL) -+ return(NULL); -+ *end++ = '\0'; -+ str = end; -+ } -+ va_end(ap); -+ return(str); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/null.c um/arch/um/drivers/null.c ---- orig/arch/um/drivers/null.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/null.c Sun Dec 15 21:04:00 2002 -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include "chan_user.h" -+#include "os.h" -+ -+static int null_chan; -+ -+void *null_init(char *str, int device, struct chan_opts *opts) -+{ -+ return(&null_chan); -+} -+ -+int null_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ *dev_out = NULL; -+ return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0)); -+} -+ -+int null_read(int fd, char *c_out, void *unused) -+{ -+ return(-ENODEV); -+} -+ -+void null_free(void *data) -+{ -+} -+ -+struct chan_ops null_ops = { -+ .type = "null", -+ .init = null_init, -+ .open = null_open, -+ .close = generic_close, -+ .read = null_read, -+ .write = generic_write, -+ .console_write = generic_console_write, -+ .window_size = generic_window_size, -+ .free = null_free, -+ .winch = 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 -Naur -X ../exclude-files orig/arch/um/drivers/pcap_kern.c um/arch/um/drivers/pcap_kern.c ---- orig/arch/um/drivers/pcap_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/pcap_kern.c Sun Dec 15 21:19:15 2002 -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "pcap_user.h" -+ -+struct pcap_init { -+ char *host_if; -+ int promisc; -+ int optimize; -+ char *filter; -+}; -+ -+void pcap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct pcap_data *ppri; -+ struct pcap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ ppri = (struct pcap_data *) pri->user; -+ *ppri = ((struct pcap_data) -+ { .host_if = init->host_if, -+ .promisc = init->promisc, -+ .optimize = init->optimize, -+ .filter = init->filter, -+ .compiled = NULL, -+ .pcap = NULL }); -+} -+ -+static int pcap_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(pcap_user_read(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER, -+ (struct pcap_data *) &lp->user)); -+} -+ -+static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ return(-EPERM); -+} -+ -+static struct net_kern_info pcap_kern_info = { -+ .init = pcap_init, -+ .protocol = eth_protocol, -+ .read = pcap_read, -+ .write = pcap_write, -+}; -+ -+int pcap_setup(char *str, char **mac_out, void *data) -+{ -+ struct pcap_init *init = data; -+ char *remain, *host_if = NULL, *options[2] = { NULL, NULL }; -+ int i; -+ -+ *init = ((struct pcap_init) -+ { .host_if = "eth0", -+ .promisc = 1, -+ .optimize = 0, -+ .filter = NULL }); -+ -+ remain = split_if_spec(str, &host_if, &init->filter, -+ &options[0], &options[1], NULL); -+ if(remain != NULL){ -+ printk(KERN_ERR "pcap_setup - Extra garbage on " -+ "specification : '%s'\n", remain); -+ return(0); -+ } -+ -+ if(host_if != NULL) -+ init->host_if = host_if; -+ -+ for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){ -+ if(options[i] == NULL) -+ continue; -+ if(!strcmp(options[i], "promisc")) -+ init->promisc = 1; -+ else if(!strcmp(options[i], "nopromisc")) -+ init->promisc = 0; -+ else if(!strcmp(options[i], "optimize")) -+ init->optimize = 1; -+ else if(!strcmp(options[i], "nooptimize")) -+ init->optimize = 0; -+ else printk("pcap_setup : bad option - '%s'\n", options[i]); -+ } -+ -+ return(1); -+} -+ -+static struct transport pcap_transport = { -+ .list = LIST_HEAD_INIT(pcap_transport.list), -+ .name = "pcap", -+ .setup = pcap_setup, -+ .user = &pcap_user_info, -+ .kern = &pcap_kern_info, -+ .private_size = sizeof(struct pcap_data), -+ .setup_size = sizeof(struct pcap_init), -+}; -+ -+static int register_pcap(void) -+{ -+ register_transport(&pcap_transport); -+ return(1); -+} -+ -+__initcall(register_pcap); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/pcap_user.c um/arch/um/drivers/pcap_user.c ---- orig/arch/um/drivers/pcap_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/pcap_user.c Sun Dec 15 21:04:39 2002 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike -+ * Licensed under the GPL. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "net_user.h" -+#include "pcap_user.h" -+#include "user.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+#define PCAP_FD(p) (*(int *)(p)) -+ -+static void pcap_user_init(void *data, void *dev) -+{ -+ struct pcap_data *pri = data; -+ pcap_t *p; -+ char errors[PCAP_ERRBUF_SIZE]; -+ -+ p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors); -+ if(p == NULL){ -+ printk("pcap_user_init : pcap_open_live failed - '%s'\n", -+ errors); -+ return; -+ } -+ -+ pri->dev = dev; -+ pri->pcap = p; -+} -+ -+static int pcap_open(void *data) -+{ -+ struct pcap_data *pri = data; -+ __u32 netmask; -+ int err; -+ -+ if(pri->pcap == NULL) -+ return(-ENODEV); -+ -+ if(pri->filter != NULL){ -+ err = dev_netmask(pri->dev, &netmask); -+ if(err < 0){ -+ printk("pcap_open : dev_netmask failed\n"); -+ return(-EIO); -+ } -+ -+ pri->compiled = um_kmalloc(sizeof(struct bpf_program)); -+ if(pri->compiled == NULL){ -+ printk("pcap_open : kmalloc failed\n"); -+ return(-ENOMEM); -+ } -+ -+ err = pcap_compile(pri->pcap, -+ (struct bpf_program *) pri->compiled, -+ pri->filter, pri->optimize, netmask); -+ if(err < 0){ -+ printk("pcap_open : pcap_compile failed - '%s'\n", -+ pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ -+ err = pcap_setfilter(pri->pcap, pri->compiled); -+ if(err < 0){ -+ printk("pcap_open : pcap_setfilter failed - '%s'\n", -+ pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ } -+ -+ return(PCAP_FD(pri->pcap)); -+} -+ -+static void pcap_remove(void *data) -+{ -+ struct pcap_data *pri = data; -+ -+ if(pri->compiled != NULL) -+ pcap_freecode(pri->compiled); -+ -+ pcap_close(pri->pcap); -+} -+ -+struct pcap_handler_data { -+ char *buffer; -+ int len; -+}; -+ -+static void handler(u_char *data, const struct pcap_pkthdr *header, -+ const u_char *packet) -+{ -+ int len; -+ -+ struct pcap_handler_data *hdata = (struct pcap_handler_data *) data; -+ -+ len = hdata->len < header->caplen ? hdata->len : header->caplen; -+ memcpy(hdata->buffer, packet, len); -+ hdata->len = len; -+} -+ -+int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri) -+{ -+ struct pcap_handler_data hdata = ((struct pcap_handler_data) -+ { .buffer = buffer, -+ .len = len }); -+ int n; -+ -+ n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); -+ if(n < 0){ -+ printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ else if(n == 0) -+ return(0); -+ return(hdata.len); -+} -+ -+struct net_user_info pcap_user_info = { -+ .init = pcap_user_init, -+ .open = pcap_open, -+ .close = NULL, -+ .remove = pcap_remove, -+ .set_mtu = NULL, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/pcap_user.h um/arch/um/drivers/pcap_user.h ---- orig/arch/um/drivers/pcap_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/pcap_user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct pcap_data { -+ char *host_if; -+ int promisc; -+ int optimize; -+ char *filter; -+ void *compiled; -+ void *pcap; -+ void *dev; -+}; -+ -+extern struct net_user_info pcap_user_info; -+ -+extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/port.h um/arch/um/drivers/port.h ---- orig/arch/um/drivers/port.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/port.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PORT_H__ -+#define __PORT_H__ -+ -+extern void *port_data(int port); -+extern int port_wait(void *data); -+extern void port_kern_close(void *d); -+extern int port_connection(int fd, int *socket_out, int *pid_out); -+extern int port_listen_fd(int port); -+extern void port_read(int fd, void *data); -+extern void port_kern_free(void *d); -+extern int port_rcv_fd(int fd); -+extern void port_remove_dev(void *d); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/drivers/port_kern.c um/arch/um/drivers/port_kern.c ---- orig/arch/um/drivers/port_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/port_kern.c Mon Dec 30 20:57:42 2002 -@@ -0,0 +1,302 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/list.h" -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "linux/irq.h" -+#include "linux/spinlock.h" -+#include "linux/errno.h" -+#include "asm/semaphore.h" -+#include "asm/errno.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "port.h" -+#include "init.h" -+#include "os.h" -+ -+struct port_list { -+ struct list_head list; -+ int has_connection; -+ struct semaphore sem; -+ int port; -+ int fd; -+ spinlock_t lock; -+ struct list_head pending; -+ struct list_head connections; -+}; -+ -+struct port_dev { -+ struct port_list *port; -+ int helper_pid; -+ int telnetd_pid; -+}; -+ -+struct connection { -+ struct list_head list; -+ int fd; -+ 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) -+{ -+ struct connection *conn = data; -+ int fd; -+ -+ fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); -+ if(fd < 0){ -+ if(fd == -EAGAIN) -+ return; -+ -+ printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", -+ -fd); -+ os_close_file(conn->fd); -+ } -+ -+ list_del(&conn->list); -+ -+ conn->fd = fd; -+ list_add(&conn->list, &conn->port->connections); -+ -+ up(&conn->port->sem); -+} -+ -+static int port_accept(struct port_list *port) -+{ -+ struct connection *conn; -+ int fd, socket[2], pid, ret = 0; -+ -+ fd = port_connection(port->fd, socket, &pid); -+ if(fd < 0){ -+ if(fd != -EAGAIN) -+ printk(KERN_ERR "port_accept : port_connection " -+ "returned %d\n", -fd); -+ goto out; -+ } -+ -+ conn = kmalloc(sizeof(*conn), GFP_ATOMIC); -+ if(conn == NULL){ -+ printk(KERN_ERR "port_accept : failed to allocate " -+ "connection\n"); -+ goto out_close; -+ } -+ *conn = ((struct connection) -+ { .list = LIST_HEAD_INIT(conn->list), -+ .fd = fd, -+ .socket = { socket[0], socket[1] }, -+ .telnetd_pid = pid, -+ .port = port }); -+ -+ if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "telnetd", conn)){ -+ printk(KERN_ERR "port_accept : failed to get IRQ for " -+ "telnetd\n"); -+ goto out_free; -+ } -+ -+ list_add(&conn->list, &port->pending); -+ return(1); -+ -+ out_free: -+ kfree(conn); -+ out_close: -+ os_close_file(fd); -+ if(pid != -1) -+ os_kill_process(pid, 1); -+ out: -+ return(ret); -+} -+ -+DECLARE_MUTEX(ports_sem); -+struct list_head ports = LIST_HEAD_INIT(ports); -+ -+void port_task_proc(void *unused) -+{ -+ struct port_list *port; -+ struct list_head *ele; -+ unsigned long flags; -+ -+ save_flags(flags); -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ if(!port->has_connection) -+ continue; -+ reactivate_fd(port->fd, ACCEPT_IRQ); -+ while(port_accept(port)) ; -+ port->has_connection = 0; -+ } -+ restore_flags(flags); -+} -+ -+struct tq_struct port_task = { -+ .routine = port_task_proc, -+ .data = NULL -+}; -+ -+static void port_interrupt(int irq, void *data, struct pt_regs *regs) -+{ -+ struct port_list *port = data; -+ -+ port->has_connection = 1; -+ schedule_task(&port_task); -+} -+ -+void *port_data(int port_num) -+{ -+ struct list_head *ele; -+ struct port_list *port; -+ struct port_dev *dev = NULL; -+ int fd; -+ -+ down(&ports_sem); -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ if(port->port == port_num) goto found; -+ } -+ port = kmalloc(sizeof(struct port_list), GFP_KERNEL); -+ if(port == NULL){ -+ printk(KERN_ERR "Allocation of port list failed\n"); -+ goto out; -+ } -+ -+ fd = port_listen_fd(port_num); -+ if(fd < 0){ -+ printk(KERN_ERR "binding to port %d failed, errno = %d\n", -+ port_num, -fd); -+ goto out_free; -+ } -+ if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "port", -+ port)){ -+ printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); -+ goto out_close; -+ } -+ -+ *port = ((struct port_list) -+ { .list = LIST_HEAD_INIT(port->list), -+ .has_connection = 0, -+ .sem = __SEMAPHORE_INITIALIZER(port->sem, -+ 0), -+ .lock = SPIN_LOCK_UNLOCKED, -+ .port = port_num, -+ .fd = fd, -+ .pending = LIST_HEAD_INIT(port->pending), -+ .connections = LIST_HEAD_INIT(port->connections) }); -+ list_add(&port->list, &ports); -+ -+ found: -+ dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); -+ if(dev == NULL){ -+ printk(KERN_ERR "Allocation of port device entry failed\n"); -+ goto out; -+ } -+ -+ *dev = ((struct port_dev) { .port = port, -+ .helper_pid = -1, -+ .telnetd_pid = -1 }); -+ goto out; -+ -+ out_free: -+ kfree(port); -+ out_close: -+ os_close_file(fd); -+ out: -+ up(&ports_sem); -+ return(dev); -+} -+ -+int port_wait(void *data) -+{ -+ struct port_dev *dev = data; -+ struct connection *conn; -+ struct port_list *port = dev->port; -+ int fd; -+ -+ while(1){ -+ if(down_interruptible(&port->sem)) -+ return(-ERESTARTSYS); -+ -+ spin_lock(&port->lock); -+ -+ conn = list_entry(port->connections.next, struct connection, -+ list); -+ list_del(&conn->list); -+ spin_unlock(&port->lock); -+ -+ os_shutdown_socket(conn->socket[0], 1, 1); -+ os_close_file(conn->socket[0]); -+ os_shutdown_socket(conn->socket[1], 1, 1); -+ os_close_file(conn->socket[1]); -+ -+ /* This is done here because freeing an IRQ can't be done -+ * within the IRQ handler. So, pipe_interrupt always ups -+ * the semaphore regardless of whether it got a successful -+ * connection. Then we loop here throwing out failed -+ * connections until a good one is found. -+ */ -+ free_irq(TELNETD_IRQ, conn); -+ -+ if(conn->fd >= 0) break; -+ os_close_file(conn->fd); -+ kfree(conn); -+ } -+ -+ fd = conn->fd; -+ dev->helper_pid = conn->helper_pid; -+ dev->telnetd_pid = conn->telnetd_pid; -+ kfree(conn); -+ -+ return(fd); -+} -+ -+void port_remove_dev(void *d) -+{ -+ struct port_dev *dev = d; -+ -+ if(dev->helper_pid != -1) -+ os_kill_process(dev->helper_pid, 0); -+ if(dev->telnetd_pid != -1) -+ os_kill_process(dev->telnetd_pid, 1); -+ dev->helper_pid = -1; -+ dev->telnetd_pid = -1; -+} -+ -+void port_kern_free(void *d) -+{ -+ struct port_dev *dev = d; -+ -+ port_remove_dev(dev); -+ kfree(dev); -+} -+ -+static void free_port(void) -+{ -+ struct list_head *ele; -+ struct port_list *port; -+ -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ free_irq_by_fd(port->fd); -+ os_close_file(port->fd); -+ } -+} -+ -+__uml_exitcall(free_port); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/port_user.c um/arch/um/drivers/port_user.c ---- orig/arch/um/drivers/port_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/port_user.c Mon Dec 16 22:46:20 2002 -@@ -0,0 +1,206 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "chan_user.h" -+#include "port.h" -+#include "helper.h" -+#include "os.h" -+ -+struct port_chan { -+ int raw; -+ struct termios tt; -+ void *kernel_data; -+ char dev[sizeof("32768\0")]; -+}; -+ -+void *port_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct port_chan *data; -+ void *kern_data; -+ char *end; -+ int port; -+ -+ if(*str != ':'){ -+ printk("port_init : channel type 'port' must specify a " -+ "port number\n"); -+ return(NULL); -+ } -+ str++; -+ port = strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk("port_init : couldn't parse port '%s'\n", str); -+ return(NULL); -+ } -+ -+ if((kern_data = port_data(port)) == NULL) -+ return(NULL); -+ -+ if((data = um_kmalloc(sizeof(*data))) == NULL) -+ goto err; -+ -+ *data = ((struct port_chan) { .raw = opts->raw, -+ .kernel_data = kern_data }); -+ sprintf(data->dev, "%d", port); -+ -+ return(data); -+ err: -+ port_kern_free(kern_data); -+ return(NULL); -+} -+ -+void port_free(void *d) -+{ -+ struct port_chan *data = d; -+ -+ port_kern_free(data->kernel_data); -+ kfree(data); -+} -+ -+int port_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct port_chan *data = d; -+ int fd; -+ -+ fd = port_wait(data->kernel_data); -+ if((fd >= 0) && data->raw){ -+ tcgetattr(fd, &data->tt); -+ raw(fd, 0); -+ } -+ *dev_out = data->dev; -+ return(fd); -+} -+ -+void port_close(int fd, void *d) -+{ -+ struct port_chan *data = d; -+ -+ port_remove_dev(data->kernel_data); -+ close(fd); -+} -+ -+int port_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct port_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops port_ops = { -+ .type = "port", -+ .init = port_init, -+ .open = port_open, -+ .close = port_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = port_console_write, -+ .window_size = generic_window_size, -+ .free = port_free, -+ .winch = 1, -+}; -+ -+int port_listen_fd(int port) -+{ -+ struct sockaddr_in addr; -+ int fd, err; -+ -+ fd = socket(PF_INET, SOCK_STREAM, 0); -+ if(fd == -1) -+ return(-errno); -+ -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = htonl(INADDR_ANY); -+ if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){ -+ err = -errno; -+ goto out; -+ } -+ -+ if((listen(fd, 1) < 0) || (os_set_fd_block(fd, 0))){ -+ err = -errno; -+ goto out; -+ } -+ -+ return(fd); -+ out: -+ os_close_file(fd); -+ return(err); -+} -+ -+struct port_pre_exec_data { -+ int sock_fd; -+ int pipe_fd; -+}; -+ -+void port_pre_exec(void *arg) -+{ -+ struct port_pre_exec_data *data = arg; -+ -+ dup2(data->sock_fd, 0); -+ dup2(data->sock_fd, 1); -+ dup2(data->sock_fd, 2); -+ close(data->sock_fd); -+ dup2(data->pipe_fd, 3); -+ os_shutdown_socket(3, 1, 0); -+ close(data->pipe_fd); -+} -+ -+int port_connection(int fd, int *socket, int *pid_out) -+{ -+ int new, err; -+ char *argv[] = { "/usr/sbin/in.telnetd", "-L", -+ "/usr/lib/uml/port-helper", NULL }; -+ struct port_pre_exec_data data; -+ -+ if((new = os_accept_connection(fd)) < 0) -+ return(-errno); -+ -+ err = os_pipe(socket, 0, 0); -+ if(err) -+ goto out_close; -+ -+ data = ((struct port_pre_exec_data) -+ { .sock_fd = new, -+ .pipe_fd = socket[1] }); -+ -+ err = run_helper(port_pre_exec, &data, argv, NULL); -+ if(err < 0) -+ goto out_shutdown; -+ -+ *pid_out = err; -+ return(new); -+ -+ out_shutdown: -+ os_shutdown_socket(socket[0], 1, 1); -+ close(socket[0]); -+ os_shutdown_socket(socket[1], 1, 1); -+ close(socket[1]); -+ out_close: -+ close(new); -+ 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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/pty.c um/arch/um/drivers/pty.c ---- orig/arch/um/drivers/pty.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/pty.c Sun Dec 15 21:06:01 2002 -@@ -0,0 +1,148 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "chan_user.h" -+#include "user.h" -+#include "user_util.h" -+#include "kern_util.h" -+ -+struct pty_chan { -+ void (*announce)(char *dev_name, int dev); -+ int dev; -+ int raw; -+ struct termios tt; -+ char dev_name[sizeof("/dev/pts/0123456\0")]; -+}; -+ -+void *pty_chan_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct pty_chan *data; -+ -+ if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL); -+ *data = ((struct pty_chan) { .announce = opts->announce, -+ .dev = device, -+ .raw = opts->raw }); -+ return(data); -+} -+ -+int pts_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct pty_chan *data = d; -+ char *dev; -+ int fd; -+ -+ if((fd = get_pty()) < 0){ -+ printk("open_pts : Failed to open pts\n"); -+ return(-errno); -+ } -+ if(data->raw){ -+ tcgetattr(fd, &data->tt); -+ raw(fd, 0); -+ } -+ -+ dev = ptsname(fd); -+ sprintf(data->dev_name, "%s", dev); -+ *dev_out = data->dev_name; -+ if(data->announce) (*data->announce)(dev, data->dev); -+ return(fd); -+} -+ -+int getmaster(char *line) -+{ -+ struct stat stb; -+ char *pty, *bank, *cp; -+ int master; -+ -+ pty = &line[strlen("/dev/ptyp")]; -+ for (bank = "pqrs"; *bank; bank++) { -+ line[strlen("/dev/pty")] = *bank; -+ *pty = '0'; -+ if (stat(line, &stb) < 0) -+ break; -+ for (cp = "0123456789abcdef"; *cp; cp++) { -+ *pty = *cp; -+ master = open(line, O_RDWR); -+ 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; -+ *tp = 'p'; -+ if (ok) return(master); -+ (void) close(master); -+ } -+ } -+ } -+ return(-1); -+} -+ -+int pty_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct pty_chan *data = d; -+ int fd; -+ char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx"; -+ -+ fd = getmaster(dev); -+ if(fd < 0) return(-errno); -+ -+ if(data->raw) raw(fd, 0); -+ if(data->announce) (*data->announce)(dev, data->dev); -+ -+ sprintf(data->dev_name, "%s", dev); -+ *dev_out = data->dev_name; -+ return(fd); -+} -+ -+int pty_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct pty_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops pty_ops = { -+ .type = "pty", -+ .init = pty_chan_init, -+ .open = pty_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = pty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 0, -+}; -+ -+struct chan_ops pts_ops = { -+ .type = "pts", -+ .init = pty_chan_init, -+ .open = pts_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = pty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 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 -Naur -X ../exclude-files orig/arch/um/drivers/slip.h um/arch/um/drivers/slip.h ---- orig/arch/um/drivers/slip.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/slip.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,39 @@ -+#ifndef __UM_SLIP_H -+#define __UM_SLIP_H -+ -+#define BUF_SIZE 1500 -+ /* two bytes each for a (pathological) max packet of escaped chars + * -+ * terminating END char + initial END char */ -+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2) -+ -+struct slip_data { -+ void *dev; -+ char name[sizeof("slnnnnn\0")]; -+ char *addr; -+ char *gate_addr; -+ int slave; -+ char ibuf[ENC_BUF_SIZE]; -+ char obuf[ENC_BUF_SIZE]; -+ int more; /* more data: do not read fd until ibuf has been drained */ -+ int pos; -+ int esc; -+}; -+ -+extern struct net_user_info slip_user_info; -+ -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri); -+extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/drivers/slip_kern.c um/arch/um/drivers/slip_kern.c ---- orig/arch/um/drivers/slip_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/slip_kern.c Sun Dec 15 21:06:24 2002 -@@ -0,0 +1,109 @@ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/stddef.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/if_arp.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "kern.h" -+#include "slip.h" -+ -+struct slip_init { -+ char *gate_addr; -+}; -+ -+void slip_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *private; -+ struct slip_data *spri; -+ struct slip_init *init = data; -+ -+ private = dev->priv; -+ spri = (struct slip_data *) private->user; -+ *spri = ((struct slip_data) -+ { .name = { '\0' }, -+ .addr = NULL, -+ .gate_addr = init->gate_addr, -+ .slave = -1, -+ .ibuf = { '\0' }, -+ .obuf = { '\0' }, -+ .pos = 0, -+ .esc = 0, -+ .dev = dev }); -+ -+ dev->init = NULL; -+ dev->hard_header_len = 0; -+ dev->addr_len = 4; -+ dev->type = ARPHRD_ETHER; -+ dev->tx_queue_len = 256; -+ dev->flags = IFF_NOARP; -+ printk("SLIP backend - SLIP IP = %s\n", spri->gate_addr); -+} -+ -+static unsigned short slip_protocol(struct sk_buff *skbuff) -+{ -+ return(htons(ETH_P_IP)); -+} -+ -+static int slip_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slip_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, -+ (struct slip_data *) &lp->user)); -+} -+ -+static int slip_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slip_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct slip_data *) &lp->user)); -+} -+ -+struct net_kern_info slip_kern_info = { -+ .init = slip_init, -+ .protocol = slip_protocol, -+ .read = slip_read, -+ .write = slip_write, -+}; -+ -+static int slip_setup(char *str, char **mac_out, void *data) -+{ -+ struct slip_init *init = data; -+ -+ *init = ((struct slip_init) -+ { .gate_addr = NULL }); -+ -+ if(str[0] != '\0') -+ init->gate_addr = str; -+ return(1); -+} -+ -+static struct transport slip_transport = { -+ .list = LIST_HEAD_INIT(slip_transport.list), -+ .name = "slip", -+ .setup = slip_setup, -+ .user = &slip_user_info, -+ .kern = &slip_kern_info, -+ .private_size = sizeof(struct slip_data), -+ .setup_size = sizeof(struct slip_init), -+}; -+ -+static int register_slip(void) -+{ -+ register_transport(&slip_transport); -+ return(1); -+} -+ -+__initcall(register_slip); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/slip_proto.h um/arch/um/drivers/slip_proto.h ---- orig/arch/um/drivers/slip_proto.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/slip_proto.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,93 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SLIP_PROTO_H__ -+#define __UM_SLIP_PROTO_H__ -+ -+/* SLIP protocol characters. */ -+#define SLIP_END 0300 /* indicates end of frame */ -+#define SLIP_ESC 0333 /* indicates byte stuffing */ -+#define SLIP_ESC_END 0334 /* ESC ESC_END means END 'data' */ -+#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */ -+ -+static inline int slip_unesc(unsigned char c,char *buf,int *pos, int *esc) -+{ -+ int ret; -+ -+ switch(c){ -+ case SLIP_END: -+ *esc = 0; -+ ret=*pos; -+ *pos=0; -+ return(ret); -+ case SLIP_ESC: -+ *esc = 1; -+ return(0); -+ case SLIP_ESC_ESC: -+ if(*esc){ -+ *esc = 0; -+ c = SLIP_ESC; -+ } -+ break; -+ case SLIP_ESC_END: -+ if(*esc){ -+ *esc = 0; -+ c = SLIP_END; -+ } -+ break; -+ } -+ buf[(*pos)++] = c; -+ return(0); -+} -+ -+static inline int slip_esc(unsigned char *s, unsigned char *d, int len) -+{ -+ unsigned char *ptr = d; -+ unsigned char c; -+ -+ /* -+ * Send an initial END character to flush out any -+ * data that may have accumulated in the receiver -+ * due to line noise. -+ */ -+ -+ *ptr++ = SLIP_END; -+ -+ /* -+ * For each byte in the packet, send the appropriate -+ * character sequence, according to the SLIP protocol. -+ */ -+ -+ while (len-- > 0) { -+ switch(c = *s++) { -+ case SLIP_END: -+ *ptr++ = SLIP_ESC; -+ *ptr++ = SLIP_ESC_END; -+ break; -+ case SLIP_ESC: -+ *ptr++ = SLIP_ESC; -+ *ptr++ = SLIP_ESC_ESC; -+ break; -+ default: -+ *ptr++ = c; -+ break; -+ } -+ } -+ *ptr++ = SLIP_END; -+ return (ptr - d); -+} -+ -+#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 -Naur -X ../exclude-files orig/arch/um/drivers/slip_user.c um/arch/um/drivers/slip_user.c ---- orig/arch/um/drivers/slip_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/slip_user.c Sun Dec 15 21:06:35 2002 -@@ -0,0 +1,279 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "net_user.h" -+#include "slip.h" -+#include "slip_proto.h" -+#include "helper.h" -+#include "os.h" -+ -+void slip_user_init(void *data, void *dev) -+{ -+ struct slip_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+static int set_up_tty(int fd) -+{ -+ int i; -+ struct termios tios; -+ -+ if (tcgetattr(fd, &tios) < 0) { -+ printk("could not get initial terminal attributes\n"); -+ return(-1); -+ } -+ -+ tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; -+ tios.c_iflag = IGNBRK | IGNPAR; -+ tios.c_oflag = 0; -+ tios.c_lflag = 0; -+ for (i = 0; i < NCCS; i++) -+ tios.c_cc[i] = 0; -+ tios.c_cc[VMIN] = 1; -+ tios.c_cc[VTIME] = 0; -+ -+ cfsetospeed(&tios, B38400); -+ cfsetispeed(&tios, B38400); -+ -+ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { -+ printk("failed to set terminal attributes\n"); -+ return(-1); -+ } -+ return(0); -+} -+ -+struct slip_pre_exec_data { -+ int stdin; -+ int stdout; -+ int close_me; -+}; -+ -+static void slip_pre_exec(void *arg) -+{ -+ struct slip_pre_exec_data *data = arg; -+ -+ if(data->stdin != -1) dup2(data->stdin, 0); -+ dup2(data->stdout, 1); -+ if(data->close_me != -1) close(data->close_me); -+} -+ -+static int slip_tramp(char **argv, int fd) -+{ -+ struct slip_pre_exec_data pe_data; -+ char *output; -+ 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); -+ return(err); -+ } -+ -+ err = 0; -+ pe_data.stdin = fd; -+ pe_data.stdout = fds[1]; -+ pe_data.close_me = fds[0]; -+ pid = run_helper(slip_pre_exec, &pe_data, argv, NULL); -+ -+ if(pid < 0) err = pid; -+ else { -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ if(output == NULL) -+ printk("slip_tramp : failed to allocate output " -+ "buffer\n"); -+ -+ close(fds[1]); -+ read_output(fds[0], output, output_len); -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+ 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; -+ } -+ } -+ return(err); -+} -+ -+static int slip_open(void *data) -+{ -+ struct slip_data *pri = data; -+ char version_buf[sizeof("nnnnn\0")]; -+ 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; -+ -+ if((mfd = get_pty()) < 0){ -+ printk("umn : Failed to open pty\n"); -+ return(-1); -+ } -+ if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){ -+ printk("Couldn't open tty for slip line\n"); -+ return(-1); -+ } -+ if(set_up_tty(sfd)) return(-1); -+ pri->slave = sfd; -+ pri->pos = 0; -+ pri->esc = 0; -+ if(pri->gate_addr != NULL){ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ strcpy(gate_buf, pri->gate_addr); -+ -+ err = slip_tramp(argv, sfd); -+ -+ if(err != 0){ -+ printk("slip_tramp failed - errno = %d\n", err); -+ return(-err); -+ } -+ if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){ -+ printk("SIOCGIFNAME failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ 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); -+ } -+ } -+ return(mfd); -+} -+ -+static void slip_close(int fd, void *data) -+{ -+ struct slip_data *pri = data; -+ char version_buf[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, -+ NULL }; -+ int err; -+ -+ if(pri->gate_addr != NULL) -+ iter_addresses(pri->dev, close_addr, pri->name); -+ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ -+ err = slip_tramp(argv, -1); -+ -+ if(err != 0) -+ printk("slip_tramp failed - errno = %d\n", err); -+ close(fd); -+ close(pri->slave); -+ pri->slave = -1; -+} -+ -+int slip_user_read(int fd, void *buf, int len, struct slip_data *pri) -+{ -+ int i, n, size, start; -+ -+ if(pri->more>0) { -+ i = 0; -+ while(i < pri->more) { -+ size = slip_unesc(pri->ibuf[i++], -+ pri->ibuf, &pri->pos, &pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i); -+ pri->more=pri->more-i; -+ return(size); -+ } -+ } -+ pri->more=0; -+ } -+ -+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos); -+ if(n <= 0) return(n); -+ -+ start = pri->pos; -+ for(i = 0; i < n; i++){ -+ size = slip_unesc(pri->ibuf[start + i], -+ pri->ibuf, &pri->pos, &pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1)); -+ pri->more=n-(i+1); -+ return(size); -+ } -+ } -+ return(0); -+} -+ -+int slip_user_write(int fd, void *buf, int len, struct slip_data *pri) -+{ -+ int actual, n; -+ -+ actual = slip_esc(buf, pri->obuf, len); -+ n = net_write(fd, pri->obuf, actual); -+ if(n < 0) return(n); -+ else return(len); -+} -+ -+static int slip_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+static void slip_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct slip_data *pri = data; -+ -+ if(pri->slave == -1) return; -+ open_addr(addr, netmask, pri->name); -+} -+ -+static void slip_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct slip_data *pri = data; -+ -+ if(pri->slave == -1) return; -+ close_addr(addr, netmask, pri->name); -+} -+ -+struct net_user_info slip_user_info = { -+ .init = slip_user_init, -+ .open = slip_open, -+ .close = slip_close, -+ .remove = NULL, -+ .set_mtu = slip_set_mtu, -+ .add_address = slip_add_addr, -+ .delete_address = slip_del_addr, -+ .max_packet = BUF_SIZE -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/slirp.h um/arch/um/drivers/slirp.h ---- orig/arch/um/drivers/slirp.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/slirp.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,51 @@ -+#ifndef __UM_SLIRP_H -+#define __UM_SLIRP_H -+ -+#define BUF_SIZE 1500 -+ /* two bytes each for a (pathological) max packet of escaped chars + * -+ * terminating END char + initial END char */ -+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2) -+ -+#define SLIRP_MAX_ARGS 100 -+/* -+ * XXX this next definition is here because I don't understand why this -+ * initializer doesn't work in slirp_kern.c: -+ * -+ * argv : { init->argv[ 0 ... SLIRP_MAX_ARGS-1 ] }, -+ * -+ * or why I can't typecast like this: -+ * -+ * argv : (char* [SLIRP_MAX_ARGS])(init->argv), -+ */ -+struct arg_list_dummy_wrapper { char *argv[SLIRP_MAX_ARGS]; }; -+ -+struct slirp_data { -+ void *dev; -+ struct arg_list_dummy_wrapper argw; -+ int pid; -+ int slave; -+ char ibuf[ENC_BUF_SIZE]; -+ char obuf[ENC_BUF_SIZE]; -+ int more; /* more data: do not read fd until ibuf has been drained */ -+ int pos; -+ int esc; -+}; -+ -+extern struct net_user_info slirp_user_info; -+ -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri); -+extern int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/drivers/slirp_kern.c um/arch/um/drivers/slirp_kern.c ---- orig/arch/um/drivers/slirp_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/slirp_kern.c Sun Dec 15 21:06:54 2002 -@@ -0,0 +1,132 @@ -+#include "linux/kernel.h" -+#include "linux/stddef.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/if_arp.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "kern.h" -+#include "slirp.h" -+ -+struct slirp_init { -+ struct arg_list_dummy_wrapper argw; /* XXX should be simpler... */ -+}; -+ -+void slirp_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *private; -+ struct slirp_data *spri; -+ struct slirp_init *init = data; -+ int i; -+ -+ private = dev->priv; -+ spri = (struct slirp_data *) private->user; -+ *spri = ((struct slirp_data) -+ { .argw = init->argw, -+ .pid = -1, -+ .slave = -1, -+ .ibuf = { '\0' }, -+ .obuf = { '\0' }, -+ .pos = 0, -+ .esc = 0, -+ .dev = dev }); -+ -+ dev->init = NULL; -+ dev->hard_header_len = 0; -+ dev->addr_len = 4; -+ dev->type = ARPHRD_ETHER; -+ dev->tx_queue_len = 256; -+ dev->flags = IFF_NOARP; -+ printk("SLIRP backend - command line:"); -+ for(i=0;spri->argw.argv[i]!=NULL;i++) { -+ printk(" '%s'",spri->argw.argv[i]); -+ } -+ printk("\n"); -+} -+ -+static unsigned short slirp_protocol(struct sk_buff *skbuff) -+{ -+ return(htons(ETH_P_IP)); -+} -+ -+static int slirp_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slirp_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, -+ (struct slirp_data *) &lp->user)); -+} -+ -+static int slirp_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slirp_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct slirp_data *) &lp->user)); -+} -+ -+struct net_kern_info slirp_kern_info = { -+ .init = slirp_init, -+ .protocol = slirp_protocol, -+ .read = slirp_read, -+ .write = slirp_write, -+}; -+ -+static int slirp_setup(char *str, char **mac_out, void *data) -+{ -+ struct slirp_init *init = data; -+ int i=0; -+ -+ *init = ((struct slirp_init) -+ { argw : { { "slirp", NULL } } }); -+ -+ str = split_if_spec(str, mac_out, NULL); -+ -+ if(str == NULL) { /* no command line given after MAC addr */ -+ return(1); -+ } -+ -+ do { -+ if(i>=SLIRP_MAX_ARGS-1) { -+ printk("slirp_setup: truncating slirp arguments\n"); -+ break; -+ } -+ init->argw.argv[i++] = str; -+ while(*str && *str!=',') { -+ if(*str=='_') *str=' '; -+ str++; -+ } -+ if(*str!=',') -+ break; -+ *str++='\0'; -+ } while(1); -+ init->argw.argv[i]=NULL; -+ return(1); -+} -+ -+static struct transport slirp_transport = { -+ .list = LIST_HEAD_INIT(slirp_transport.list), -+ .name = "slirp", -+ .setup = slirp_setup, -+ .user = &slirp_user_info, -+ .kern = &slirp_kern_info, -+ .private_size = sizeof(struct slirp_data), -+ .setup_size = sizeof(struct slirp_init), -+}; -+ -+static int register_slirp(void) -+{ -+ register_transport(&slirp_transport); -+ return(1); -+} -+ -+__initcall(register_slirp); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/slirp_user.c um/arch/um/drivers/slirp_user.c ---- orig/arch/um/drivers/slirp_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/slirp_user.c Sun Dec 15 21:07:08 2002 -@@ -0,0 +1,202 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "net_user.h" -+#include "slirp.h" -+#include "slip_proto.h" -+#include "helper.h" -+#include "os.h" -+ -+void slirp_user_init(void *data, void *dev) -+{ -+ struct slirp_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+struct slirp_pre_exec_data { -+ int stdin; -+ int stdout; -+}; -+ -+static void slirp_pre_exec(void *arg) -+{ -+ struct slirp_pre_exec_data *data = arg; -+ -+ if(data->stdin != -1) dup2(data->stdin, 0); -+ if(data->stdout != -1) dup2(data->stdout, 1); -+} -+ -+static int slirp_tramp(char **argv, int fd) -+{ -+ struct slirp_pre_exec_data pe_data; -+ int pid; -+ -+ pe_data.stdin = fd; -+ pe_data.stdout = fd; -+ pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL); -+ -+ return(pid); -+} -+ -+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); -+ return(err); -+ } -+ -+ *mfd = fds[0]; -+ *sfd = fds[1]; -+ return(0); -+} -+ -+static int slirp_open(void *data) -+{ -+ struct slirp_data *pri = data; -+ int sfd, mfd, pid, err; -+ -+ err = slirp_datachan(&mfd, &sfd); -+ if(err) -+ return(err); -+ -+ pid = slirp_tramp(pri->argw.argv, sfd); -+ -+ if(pid < 0){ -+ printk("slirp_tramp failed - errno = %d\n", pid); -+ os_close_file(sfd); -+ os_close_file(mfd); -+ return(pid); -+ } -+ -+ pri->slave = sfd; -+ pri->pos = 0; -+ pri->esc = 0; -+ -+ pri->pid = pid; -+ -+ return(mfd); -+} -+ -+static void slirp_close(int fd, void *data) -+{ -+ struct slirp_data *pri = data; -+ int status,err; -+ -+ close(fd); -+ close(pri->slave); -+ -+ pri->slave = -1; -+ -+ if(pri->pid<1) { -+ printk("slirp_close: no child process to shut down\n"); -+ return; -+ } -+ -+#if 0 -+ if(kill(pri->pid, SIGHUP)<0) { -+ printk("slirp_close: sending hangup to %d failed (%d)\n", -+ pri->pid, errno); -+ } -+#endif -+ -+ err = waitpid(pri->pid, &status, WNOHANG); -+ if(err<0) { -+ printk("slirp_close: waitpid returned %d\n", errno); -+ return; -+ } -+ -+ if(err==0) { -+ printk("slirp_close: process %d has not exited\n"); -+ return; -+ } -+ -+ pri->pid = -1; -+} -+ -+int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri) -+{ -+ int i, n, size, start; -+ -+ if(pri->more>0) { -+ i = 0; -+ while(i < pri->more) { -+ size = slip_unesc(pri->ibuf[i++], -+ pri->ibuf,&pri->pos,&pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i); -+ pri->more=pri->more-i; -+ return(size); -+ } -+ } -+ pri->more=0; -+ } -+ -+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos); -+ if(n <= 0) return(n); -+ -+ start = pri->pos; -+ for(i = 0; i < n; i++){ -+ size = slip_unesc(pri->ibuf[start + i], -+ pri->ibuf,&pri->pos,&pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1)); -+ pri->more=n-(i+1); -+ return(size); -+ } -+ } -+ return(0); -+} -+ -+int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) -+{ -+ int actual, n; -+ -+ actual = slip_esc(buf, pri->obuf, len); -+ n = net_write(fd, pri->obuf, actual); -+ if(n < 0) return(n); -+ else return(len); -+} -+ -+static int slirp_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info slirp_user_info = { -+ .init = slirp_user_init, -+ .open = slirp_open, -+ .close = slirp_close, -+ .remove = NULL, -+ .set_mtu = slirp_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = BUF_SIZE -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/ssl.c um/arch/um/drivers/ssl.c ---- orig/arch/um/drivers/ssl.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/ssl.c Thu Mar 6 18:55:01 2003 -@@ -0,0 +1,265 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/fs.h" -+#include "linux/tty.h" -+#include "linux/tty_driver.h" -+#include "linux/major.h" -+#include "linux/mm.h" -+#include "linux/init.h" -+#include "asm/termbits.h" -+#include "asm/irq.h" -+#include "line.h" -+#include "ssl.h" -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "init.h" -+#include "irq_user.h" -+#include "mconsole_kern.h" -+#include "2_5compat.h" -+ -+static int ssl_version = 1; -+ -+/* Referenced only by tty_driver below - presumably it's locked correctly -+ * by the tty driver. -+ */ -+static int ssl_refcount = 0; -+ -+static struct tty_driver ssl_driver; -+ -+#define NR_PORTS 64 -+ -+void ssl_announce(char *dev_name, int dev) -+{ -+ printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev, -+ dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = ssl_announce, -+ .xterm_title = "Serial Line #%d", -+ .raw = 1, -+ .tramp_stack = 0, -+ .in_kernel = 1, -+}; -+ -+static int ssl_config(char *str); -+static int ssl_get_config(char *dev, char *str, int size, char **error_out); -+static int ssl_remove(char *str); -+ -+static struct line_driver driver = { -+ .name = "UML serial line", -+ .devfs_name = "tts/%d", -+ .major = TTY_MAJOR, -+ .minor_start = 64, -+ .type = TTY_DRIVER_TYPE_SERIAL, -+ .subtype = 0, -+ .read_irq = SSL_IRQ, -+ .read_irq_name = "ssl", -+ .write_irq = SSL_WRITE_IRQ, -+ .write_irq_name = "ssl-write", -+ .symlink_from = "serial", -+ .symlink_to = "tts", -+ .mc = { -+ .name = "ssl", -+ .config = ssl_config, -+ .get_config = ssl_get_config, -+ .remove = ssl_remove, -+ }, -+}; -+ -+/* The array is initialized by line_init, which is an initcall. The -+ * individual elements are protected by individual semaphores. -+ */ -+static struct line serial_lines[NR_PORTS] = -+ { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; -+ -+static struct lines lines = LINES_INIT(NR_PORTS); -+ -+static int ssl_config(char *str) -+{ -+ return(line_config(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), str)); -+} -+ -+static int ssl_get_config(char *dev, char *str, int size, char **error_out) -+{ -+ return(line_get_config(dev, serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), -+ str, size, error_out)); -+} -+ -+static int ssl_remove(char *str) -+{ -+ return(line_remove(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), str)); -+} -+ -+int ssl_open(struct tty_struct *tty, struct file *filp) -+{ -+ return(line_open(serial_lines, tty, &opts)); -+} -+ -+static void ssl_close(struct tty_struct *tty, struct file * filp) -+{ -+ line_close(serial_lines, tty); -+} -+ -+static int ssl_write(struct tty_struct * tty, int from_user, -+ const unsigned char *buf, int count) -+{ -+ return(line_write(serial_lines, tty, from_user, buf, count)); -+} -+ -+static void ssl_put_char(struct tty_struct *tty, unsigned char ch) -+{ -+ line_write(serial_lines, tty, 0, &ch, sizeof(ch)); -+} -+ -+static void ssl_flush_chars(struct tty_struct *tty) -+{ -+ return; -+} -+ -+static int ssl_chars_in_buffer(struct tty_struct *tty) -+{ -+ return(0); -+} -+ -+static void ssl_flush_buffer(struct tty_struct *tty) -+{ -+ return; -+} -+ -+static int ssl_ioctl(struct tty_struct *tty, struct file * file, -+ unsigned int cmd, unsigned long arg) -+{ -+ int ret; -+ -+ ret = 0; -+ switch(cmd){ -+ case TCGETS: -+ case TCSETS: -+ case TCFLSH: -+ case TCSETSF: -+ case TCSETSW: -+ case TCGETA: -+ case TIOCMGET: -+ ret = -ENOIOCTLCMD; -+ break; -+ default: -+ printk(KERN_ERR -+ "Unimplemented ioctl in ssl_ioctl : 0x%x\n", cmd); -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return(ret); -+} -+ -+static void ssl_throttle(struct tty_struct * tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_throttle\n"); -+} -+ -+static void ssl_unthrottle(struct tty_struct * tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_unthrottle\n"); -+} -+ -+static void ssl_set_termios(struct tty_struct *tty, -+ struct termios *old_termios) -+{ -+} -+ -+static void ssl_stop(struct tty_struct *tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_stop\n"); -+} -+ -+static void ssl_start(struct tty_struct *tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_start\n"); -+} -+ -+void ssl_hangup(struct tty_struct *tty) -+{ -+} -+ -+static struct tty_driver ssl_driver = { -+ .refcount = &ssl_refcount, -+ .open = ssl_open, -+ .close = ssl_close, -+ .write = ssl_write, -+ .put_char = ssl_put_char, -+ .flush_chars = ssl_flush_chars, -+ .chars_in_buffer = ssl_chars_in_buffer, -+ .flush_buffer = ssl_flush_buffer, -+ .ioctl = ssl_ioctl, -+ .throttle = ssl_throttle, -+ .unthrottle = ssl_unthrottle, -+ .set_termios = ssl_set_termios, -+ .stop = ssl_stop, -+ .start = ssl_start, -+ .hangup = ssl_hangup -+}; -+ -+/* Changed by ssl_init and referenced by ssl_exit, which are both serialized -+ * by being an initcall and exitcall, respectively. -+ */ -+static int ssl_init_done = 0; -+ -+int ssl_init(void) -+{ -+ char *new_title; -+ -+ printk(KERN_INFO "Initializing software serial port version %d\n", -+ ssl_version); -+ -+ line_register_devfs(&lines, &driver, &ssl_driver, serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0])); -+ -+ lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); -+ -+ new_title = add_xterm_umid(opts.xterm_title); -+ if(new_title != NULL) opts.xterm_title = new_title; -+ -+ ssl_init_done = 1; -+ return(0); -+} -+ -+__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); -+} -+ -+__setup("ssl", ssl_chan_setup); -+__channel_help(ssl_chan_setup, "ssl"); -+ -+static void ssl_exit(void) -+{ -+ if(!ssl_init_done) return; -+ close_lines(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0])); -+} -+ -+__uml_exitcall(ssl_exit); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/ssl.h um/arch/um/drivers/ssl.h ---- orig/arch/um/drivers/ssl.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/ssl.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SSL_H__ -+#define __SSL_H__ -+ -+extern int ssl_read(int fd, int line); -+extern void ssl_receive_char(int line, char ch); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/drivers/stdio_console.c um/arch/um/drivers/stdio_console.c ---- orig/arch/um/drivers/stdio_console.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/stdio_console.c Sun Dec 15 21:08:20 2002 -@@ -0,0 +1,250 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/posix_types.h" -+#include "linux/tty.h" -+#include "linux/tty_flip.h" -+#include "linux/types.h" -+#include "linux/major.h" -+#include "linux/kdev_t.h" -+#include "linux/console.h" -+#include "linux/string.h" -+#include "linux/sched.h" -+#include "linux/list.h" -+#include "linux/init.h" -+#include "linux/interrupt.h" -+#include "linux/slab.h" -+#include "asm/current.h" -+#include "asm/softirq.h" -+#include "asm/hardirq.h" -+#include "asm/irq.h" -+#include "stdio_console.h" -+#include "line.h" -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "2_5compat.h" -+ -+#define MAX_TTYS (8) -+ -+/* Referenced only by tty_driver below - presumably it's locked correctly -+ * by the tty driver. -+ */ -+ -+static struct tty_driver console_driver; -+ -+static int console_refcount = 0; -+ -+static struct chan_ops init_console_ops = { -+ .type = "you shouldn't see this", -+ .init = NULL, -+ .open = NULL, -+ .close = NULL, -+ .read = NULL, -+ .write = NULL, -+ .console_write = generic_write, -+ .window_size = NULL, -+ .free = NULL, -+ .winch = 0, -+}; -+ -+static struct chan init_console_chan = { -+ .list = { }, -+ .primary = 1, -+ .input = 0, -+ .output = 1, -+ .opened = 1, -+ .fd = 1, -+ .pri = INIT_STATIC, -+ .ops = &init_console_ops, -+ .data = NULL -+}; -+ -+void stdio_announce(char *dev_name, int dev) -+{ -+ printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, -+ dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = stdio_announce, -+ .xterm_title = "Virtual Console #%d", -+ .raw = 1, -+ .tramp_stack = 0, -+ .in_kernel = 1, -+}; -+ -+static int con_config(char *str); -+static int con_get_config(char *dev, char *str, int size, char **error_out); -+static int con_remove(char *str); -+ -+static struct line_driver driver = { -+ .name = "UML console", -+ .devfs_name = "vc/%d", -+ .major = TTY_MAJOR, -+ .minor_start = 0, -+ .type = TTY_DRIVER_TYPE_CONSOLE, -+ .subtype = SYSTEM_TYPE_CONSOLE, -+ .read_irq = CONSOLE_IRQ, -+ .read_irq_name = "console", -+ .write_irq = CONSOLE_WRITE_IRQ, -+ .write_irq_name = "console-write", -+ .symlink_from = "ttys", -+ .symlink_to = "vc", -+ .mc = { -+ .name = "con", -+ .config = con_config, -+ .get_config = con_get_config, -+ .remove = con_remove, -+ }, -+}; -+ -+static struct lines console_lines = LINES_INIT(MAX_TTYS); -+ -+/* The array is initialized by line_init, which is an initcall. The -+ * individual elements are protected by individual semaphores. -+ */ -+struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), -+ [ 1 ... MAX_TTYS - 1 ] = -+ LINE_INIT(CONFIG_CON_CHAN, &driver) }; -+ -+static int con_config(char *str) -+{ -+ return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); -+} -+ -+static int con_get_config(char *dev, char *str, int size, char **error_out) -+{ -+ return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, -+ size, error_out)); -+} -+ -+static int con_remove(char *str) -+{ -+ return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str)); -+} -+ -+static int open_console(struct tty_struct *tty) -+{ -+ return(line_open(vts, tty, &opts)); -+} -+ -+static int con_open(struct tty_struct *tty, struct file *filp) -+{ -+ return(open_console(tty)); -+} -+ -+static void con_close(struct tty_struct *tty, struct file *filp) -+{ -+ line_close(vts, tty); -+} -+ -+static int con_write(struct tty_struct *tty, int from_user, -+ const unsigned char *buf, int count) -+{ -+ return(line_write(vts, tty, from_user, buf, count)); -+} -+ -+static void set_termios(struct tty_struct *tty, struct termios * old) -+{ -+} -+ -+static int chars_in_buffer(struct tty_struct *tty) -+{ -+ return(0); -+} -+ -+static int con_init_done = 0; -+ -+int stdio_init(void) -+{ -+ char *new_title; -+ -+ printk(KERN_INFO "Initializing stdio console driver\n"); -+ -+ line_register_devfs(&console_lines, &driver, &console_driver, vts, -+ sizeof(vts)/sizeof(vts[0])); -+ -+ lines_init(vts, sizeof(vts)/sizeof(vts[0])); -+ -+ new_title = add_xterm_umid(opts.xterm_title); -+ if(new_title != NULL) opts.xterm_title = new_title; -+ -+ open_console(NULL); -+ con_init_done = 1; -+ return(0); -+} -+ -+__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); -+} -+ -+static struct tty_driver console_driver = { -+ .refcount = &console_refcount, -+ .open = con_open, -+ .close = con_close, -+ .write = con_write, -+ .chars_in_buffer = chars_in_buffer, -+ .set_termios = set_termios -+}; -+ -+static kdev_t console_device(struct console *c) -+{ -+ return mk_kdev(TTY_MAJOR, c->index); -+} -+ -+static int console_setup(struct console *co, char *options) -+{ -+ return(0); -+} -+ -+static struct console stdiocons = INIT_CONSOLE("tty", console_write, -+ console_device, console_setup, -+ CON_PRINTBUFFER); -+ -+void stdio_console_init(void) -+{ -+ INIT_LIST_HEAD(&vts[0].chan_list); -+ list_add(&init_console_chan.list, &vts[0].chan_list); -+ register_console(&stdiocons); -+} -+ -+static int console_chan_setup(char *str) -+{ -+ line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1); -+ return(1); -+} -+ -+__setup("con", console_chan_setup); -+__channel_help(console_chan_setup, "con"); -+ -+static void console_exit(void) -+{ -+ if(!con_init_done) return; -+ close_lines(vts, sizeof(vts)/sizeof(vts[0])); -+} -+ -+__uml_exitcall(console_exit); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/stdio_console.h um/arch/um/drivers/stdio_console.h ---- orig/arch/um/drivers/stdio_console.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/stdio_console.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __STDIO_CONSOLE_H -+#define __STDIO_CONSOLE_H -+ -+extern void save_console_flags(void); -+#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 -Naur -X ../exclude-files orig/arch/um/drivers/tty.c um/arch/um/drivers/tty.c ---- orig/arch/um/drivers/tty.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/tty.c Sun Dec 15 21:08:41 2002 -@@ -0,0 +1,86 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "chan_user.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+ -+struct tty_chan { -+ char *dev; -+ int raw; -+ struct termios tt; -+}; -+ -+void *tty_chan_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct tty_chan *data; -+ -+ if(*str != ':'){ -+ printk("tty_init : channel type 'tty' must specify " -+ "a device\n"); -+ return(NULL); -+ } -+ str++; -+ -+ if((data = um_kmalloc(sizeof(*data))) == NULL) -+ return(NULL); -+ *data = ((struct tty_chan) { .dev = str, -+ .raw = opts->raw }); -+ -+ return(data); -+} -+ -+int tty_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct tty_chan *data = d; -+ int fd; -+ -+ fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0); -+ if(fd < 0) return(fd); -+ if(data->raw){ -+ tcgetattr(fd, &data->tt); -+ raw(fd, 0); -+ } -+ -+ *dev_out = data->dev; -+ return(fd); -+} -+ -+int tty_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct tty_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops tty_ops = { -+ .type = "tty", -+ .init = tty_chan_init, -+ .open = tty_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = tty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 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 -Naur -X ../exclude-files orig/arch/um/drivers/ubd_kern.c um/arch/um/drivers/ubd_kern.c ---- orig/arch/um/drivers/ubd_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/ubd_kern.c Tue Mar 11 15:46:36 2003 -@@ -0,0 +1,1067 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+/* 2001-09-28...2002-04-17 -+ * Partition stuff by James_McMechan@hotmail.com -+ * old style ubd by setting UBD_SHIFT to 0 -+ */ -+ -+#define MAJOR_NR UBD_MAJOR -+#define UBD_SHIFT 4 -+ -+#include "linux/config.h" -+#include "linux/blk.h" -+#include "linux/blkdev.h" -+#include "linux/hdreg.h" -+#include "linux/init.h" -+#include "linux/devfs_fs_kernel.h" -+#include "linux/cdrom.h" -+#include "linux/proc_fs.h" -+#include "linux/ctype.h" -+#include "linux/capability.h" -+#include "linux/mm.h" -+#include "linux/vmalloc.h" -+#include "linux/blkpg.h" -+#include "linux/genhd.h" -+#include "linux/spinlock.h" -+#include "asm/segment.h" -+#include "asm/uaccess.h" -+#include "asm/irq.h" -+#include "asm/types.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "irq_user.h" -+#include "ubd_user.h" -+#include "2_5compat.h" -+#include "os.h" -+ -+static int ubd_open(struct inode * inode, struct file * filp); -+static int ubd_release(struct inode * inode, struct file * file); -+static int ubd_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg); -+static int ubd_revalidate(kdev_t rdev); -+static int ubd_revalidate1(kdev_t rdev); -+ -+#define MAX_DEV (8) -+#define MAX_MINOR (MAX_DEV << UBD_SHIFT) -+ -+/* 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 ubd_lock */ -+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 }; -+ -+static struct block_device_operations ubd_blops = { -+ .open = ubd_open, -+ .release = ubd_release, -+ .ioctl = ubd_ioctl, -+ .revalidate = ubd_revalidate, -+}; -+ -+/* Protected by ubd_lock, except in prepare_request and ubd_ioctl because -+ * the block layer should ensure that the device is idle before closing it. -+ */ -+static struct hd_struct ubd_part[MAX_MINOR] = -+ { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } }; -+ -+/* Protected by io_request_lock */ -+static request_queue_t *ubd_queue; -+ -+/* Protected by ubd_lock */ -+static int fake_major = MAJOR_NR; -+ -+static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED; -+ -+#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 struct gendisk ubd_gendisk = INIT_GENDISK(MAJOR_NR, "ubd", ubd_part, -+ UBD_SHIFT, sizes, MAX_DEV, -+ &ubd_blops); -+static struct gendisk fake_gendisk = INIT_GENDISK(0, "ubd", ubd_part, -+ UBD_SHIFT, sizes, MAX_DEV, -+ &ubd_blops); -+ -+#ifdef CONFIG_BLK_DEV_UBD_SYNC -+#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \ -+ .cl = 1 }) -+#else -+#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \ -+ .cl = 1 }) -+#endif -+ -+/* Not protected - changed only in ubd_setup_common and then only to -+ * to enable O_SYNC. -+ */ -+static struct openflags global_openflags = OPEN_FLAGS; -+ -+struct cow { -+ char *file; -+ int fd; -+ unsigned long *bitmap; -+ unsigned long bitmap_len; -+ int bitmap_offset; -+ int data_offset; -+}; -+ -+struct ubd { -+ char *file; -+ int count; -+ int fd; -+ __u64 size; -+ struct openflags boot_openflags; -+ struct openflags openflags; -+ devfs_handle_t devfs; -+ struct cow cow; -+}; -+ -+#define DEFAULT_COW { \ -+ .file = NULL, \ -+ .fd = -1, \ -+ .bitmap = NULL, \ -+ .bitmap_offset = 0, \ -+ .data_offset = 0, \ -+} -+ -+#define DEFAULT_UBD { \ -+ .file = NULL, \ -+ .count = 0, \ -+ .fd = -1, \ -+ .size = -1, \ -+ .boot_openflags = OPEN_FLAGS, \ -+ .openflags = OPEN_FLAGS, \ -+ .devfs = NULL, \ -+ .cow = DEFAULT_COW, \ -+} -+ -+struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; -+ -+static int ubd0_init(void) -+{ -+ struct ubd *dev = &ubd_dev[0]; -+ -+ if(dev->file == NULL) -+ dev->file = "root_fs"; -+ return(0); -+} -+ -+__initcall(ubd0_init); -+ -+/* Only changed by fake_ide_setup which is a setup */ -+static int fake_ide = 0; -+static struct proc_dir_entry *proc_ide_root = NULL; -+static struct proc_dir_entry *proc_ide = NULL; -+ -+static void make_proc_ide(void) -+{ -+ proc_ide_root = proc_mkdir("ide", 0); -+ proc_ide = proc_mkdir("ide0", proc_ide_root); -+} -+ -+static int proc_ide_read_media(char *page, char **start, off_t off, int count, -+ int *eof, void *data) -+{ -+ int len; -+ -+ strcpy(page, "disk\n"); -+ len = strlen("disk\n"); -+ len -= off; -+ if (len < count){ -+ *eof = 1; -+ if (len <= 0) return 0; -+ } -+ else len = count; -+ *start = page + off; -+ return len; -+} -+ -+static void make_ide_entries(char *dev_name) -+{ -+ struct proc_dir_entry *dir, *ent; -+ char name[64]; -+ -+ if(!fake_ide) return; -+ -+ /* Without locking this could race if a UML was booted with no -+ * disks and then two mconsole requests which add disks came in -+ * at the same time. -+ */ -+ spin_lock(&ubd_lock); -+ if(proc_ide_root == NULL) make_proc_ide(); -+ spin_unlock(&ubd_lock); -+ -+ dir = proc_mkdir(dev_name, proc_ide); -+ if(!dir) return; -+ -+ ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir); -+ if(!ent) return; -+ ent->nlink = 1; -+ ent->data = NULL; -+ ent->read_proc = proc_ide_read_media; -+ ent->write_proc = NULL; -+ sprintf(name,"ide0/%s", dev_name); -+ proc_symlink(dev_name, proc_ide_root, name); -+} -+ -+static int fake_ide_setup(char *str) -+{ -+ fake_ide = 1; -+ return(1); -+} -+ -+__setup("fake_ide", fake_ide_setup); -+ -+__uml_help(fake_ide_setup, -+"fake_ide\n" -+" 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 openflags flags = global_openflags; -+ struct ubd *dev; -+ char *backing_file; -+ int n, err; -+ -+ if(index_out) *index_out = -1; -+ n = *str; -+ if(n == '='){ -+ char *end; -+ int major; -+ -+ str++; -+ if(!strcmp(str, "sync")){ -+ global_openflags.s = 1; -+ return(0); -+ } -+ major = simple_strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk(KERN_ERR -+ "ubd_setup : didn't parse major number\n"); -+ return(1); -+ } -+ -+ err = 1; -+ spin_lock(&ubd_lock); -+ if(fake_major != MAJOR_NR){ -+ printk(KERN_ERR "Can't assign a fake major twice\n"); -+ goto out1; -+ } -+ -+ fake_gendisk.major = major; -+ fake_major = major; -+ -+ printk(KERN_INFO "Setting extra ubd major number to %d\n", -+ major); -+ err = 0; -+ out1: -+ spin_unlock(&ubd_lock); -+ return(err); -+ } -+ -+ 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 %d out of range " -+ "(%d devices)\n", n, MAX_DEV); -+ return(1); -+ } -+ -+ err = 1; -+ spin_lock(&ubd_lock); -+ -+ dev = &ubd_dev[n]; -+ if(dev->file != NULL){ -+ printk(KERN_ERR "ubd_setup : device already configured\n"); -+ goto out2; -+ } -+ -+ if(index_out) *index_out = n; -+ -+ if (*str == 'r'){ -+ flags.w = 0; -+ str++; -+ } -+ if (*str == 's'){ -+ flags.s = 1; -+ str++; -+ } -+ if(*str++ != '='){ -+ printk(KERN_ERR "ubd_setup : Expected '='\n"); -+ goto out2; -+ } -+ -+ err = 0; -+ backing_file = strchr(str, ','); -+ if(backing_file){ -+ *backing_file = '\0'; -+ backing_file++; -+ } -+ dev->file = str; -+ dev->cow.file = backing_file; -+ dev->boot_openflags = flags; -+ out2: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static int ubd_setup(char *str) -+{ -+ ubd_setup_common(str, NULL); -+ return(1); -+} -+ -+__setup("ubd", ubd_setup); -+__uml_help(ubd_setup, -+"ubd=\n" -+" This is used to associate a device with a file in the underlying\n" -+" filesystem. Usually, there is a filesystem in the file, but \n" -+" that's not required. Swap devices containing swap files can be\n" -+" specified like this. Also, a file which doesn't contain a\n" -+" filesystem can have its contents read in the virtual \n" -+" machine by running dd on the device. n must be in the range\n" -+" 0 to 7. Appending an 'r' to the number will cause that device\n" -+" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n" -+" an 's' (has to be _after_ 'r', if there is one) will cause data\n" -+" to be written to disk on the host immediately.\n\n" -+); -+ -+static int fakehd(char *str) -+{ -+ printk(KERN_INFO -+ "fakehd : Changing ubd_gendisk.major_name to \"hd\".\n"); -+ ubd_gendisk.major_name = "hd"; -+ return(1); -+} -+ -+__setup("fakehd", fakehd); -+__uml_help(fakehd, -+"fakehd\n" -+" Change the ubd device name to \"hd\".\n\n" -+); -+ -+static void do_ubd_request(request_queue_t * q); -+ -+/* Only changed by ubd_init, which is an initcall. */ -+int thread_fd = -1; -+ -+/* Changed by ubd_handler, which is serialized because interrupts only -+ * happen on CPU 0. -+ */ -+int intr_count = 0; -+ -+static void ubd_finish(int error) -+{ -+ int nsect; -+ -+ if(error){ -+ end_request(0); -+ return; -+ } -+ nsect = CURRENT->current_nr_sectors; -+ CURRENT->sector += nsect; -+ CURRENT->buffer += nsect << 9; -+ CURRENT->errors = 0; -+ CURRENT->nr_sectors -= nsect; -+ CURRENT->current_nr_sectors = 0; -+ end_request(1); -+} -+ -+static void ubd_handler(void) -+{ -+ struct io_thread_req req; -+ int n; -+ -+ DEVICE_INTR = 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); -+ spin_lock(&io_request_lock); -+ end_request(0); -+ spin_unlock(&io_request_lock); -+ return; -+ } -+ -+ if((req.offset != ((__u64) (CURRENT->sector)) << 9) || -+ (req.length != (CURRENT->current_nr_sectors) << 9)) -+ panic("I/O op mismatch"); -+ -+ spin_lock(&io_request_lock); -+ ubd_finish(req.error); -+ reactivate_fd(thread_fd, UBD_IRQ); -+ do_ubd_request(ubd_queue); -+ spin_unlock(&io_request_lock); -+} -+ -+static void ubd_intr(int irq, void *dev, struct pt_regs *unused) -+{ -+ ubd_handler(); -+} -+ -+/* Only changed by ubd_init, which is an initcall. */ -+static int io_pid = -1; -+ -+void kill_io_thread(void) -+{ -+ if(io_pid != -1) -+ os_kill_process(io_pid, 1); -+} -+ -+__uml_exitcall(kill_io_thread); -+ -+/* Initialized in an initcall, and unchanged thereafter */ -+devfs_handle_t ubd_dir_handle; -+ -+static int ubd_add(int n) -+{ -+ struct ubd *dev = &ubd_dev[n]; -+ char name[sizeof("nnnnnn\0")], dev_name[sizeof("ubd0x")]; -+ int err = -EISDIR; -+ -+ if(dev->file == NULL) -+ goto out; -+ -+ err = ubd_revalidate1(MKDEV(MAJOR_NR, n << UBD_SHIFT)); -+ if(err) -+ goto out; -+ -+ sprintf(name, "%d", n); -+ dev->devfs = devfs_register(ubd_dir_handle, name, DEVFS_FL_REMOVABLE, -+ MAJOR_NR, n << UBD_SHIFT, S_IFBLK | -+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, -+ &ubd_blops, NULL); -+ -+ if(!strcmp(ubd_gendisk.major_name, "ubd")) -+ sprintf(dev_name, "%s%d", ubd_gendisk.major_name, n); -+ else sprintf(dev_name, "%s%c", ubd_gendisk.major_name, -+ n + 'a'); -+ -+ make_ide_entries(dev_name); -+ return(0); -+ -+ out: -+ return(err); -+} -+ -+static int ubd_config(char *str) -+{ -+ int n, err; -+ -+ str = uml_strdup(str); -+ if(str == NULL){ -+ printk(KERN_ERR "ubd_config failed to strdup string\n"); -+ return(1); -+ } -+ err = ubd_setup_common(str, &n); -+ if(err){ -+ kfree(str); -+ return(-1); -+ } -+ if(n == -1) return(0); -+ -+ spin_lock(&ubd_lock); -+ err = ubd_add(n); -+ if(err) -+ ubd_dev[n].file = NULL; -+ spin_unlock(&ubd_lock); -+ -+ return(err); -+} -+ -+static int ubd_get_config(char *name, char *str, int size, char **error_out) -+{ -+ struct ubd *dev; -+ char *end; -+ int n, len = 0; -+ -+ n = simple_strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ *error_out = "ubd_get_config : didn't parse device number"; -+ return(-1); -+ } -+ -+ if((n >= MAX_DEV) || (n < 0)){ -+ *error_out = "ubd_get_config : device number out of range"; -+ return(-1); -+ } -+ -+ dev = &ubd_dev[n]; -+ spin_lock(&ubd_lock); -+ -+ if(dev->file == NULL){ -+ CONFIG_CHUNK(str, size, len, "", 1); -+ goto out; -+ } -+ -+ CONFIG_CHUNK(str, size, len, dev->file, 0); -+ -+ 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, len, "", 1); -+ -+ out: -+ spin_unlock(&ubd_lock); -+ return(len); -+} -+ -+static int ubd_remove(char *str) -+{ -+ struct ubd *dev; -+ int n, err = -ENODEV; -+ -+ if(isdigit(*str)){ -+ char *end; -+ n = simple_strtoul(str, &end, 0); -+ if ((*end != '\0') || (end == str)) -+ return(err); -+ } -+ else if (('a' <= *str) && (*str <= 'h')) -+ n = *str - 'a'; -+ else -+ return(err); /* it should be a number 0-7/a-h */ -+ -+ if((n < 0) || (n >= MAX_DEV)) -+ return(err); -+ -+ dev = &ubd_dev[n]; -+ -+ spin_lock(&ubd_lock); -+ err = 0; -+ if(dev->file == NULL) -+ goto out; -+ err = -1; -+ if(dev->count > 0) -+ goto out; -+ if(dev->devfs != NULL) -+ devfs_unregister(dev->devfs); -+ -+ *dev = ((struct ubd) DEFAULT_UBD); -+ err = 0; -+ out: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static struct mc_device ubd_mc = { -+ .name = "ubd", -+ .config = ubd_config, -+ .get_config = ubd_get_config, -+ .remove = ubd_remove, -+}; -+ -+static int ubd_mc_init(void) -+{ -+ mconsole_register_dev(&ubd_mc); -+ return(0); -+} -+ -+__initcall(ubd_mc_init); -+ -+static request_queue_t *ubd_get_queue(kdev_t device) -+{ -+ return(ubd_queue); -+} -+ -+int ubd_init(void) -+{ -+ unsigned long stack; -+ int i, err; -+ -+ ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL); -+ if (devfs_register_blkdev(MAJOR_NR, "ubd", &ubd_blops)) { -+ printk(KERN_ERR "ubd: 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); -+ -+ ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR); -+ blk_init_queue(ubd_queue, DEVICE_REQUEST); -+ INIT_ELV(ubd_queue, &ubd_queue->elevator); -+ -+ add_gendisk(&ubd_gendisk); -+ if (fake_major != MAJOR_NR){ -+ /* major number 0 is used to auto select */ -+ err = devfs_register_blkdev(fake_major, "fake", &ubd_blops); -+ if(fake_major == 0){ -+ /* auto device number case */ -+ fake_major = err; -+ if(err == 0) -+ return(-ENODEV); -+ } -+ else if (err){ -+ /* not auto so normal error */ -+ printk(KERN_ERR "ubd: error %d getting major %d\n", -+ err, fake_major); -+ return(-ENODEV); -+ } -+ -+ blk_dev[fake_major].queue = ubd_get_queue; -+ read_ahead[fake_major] = 8; /* 8 sector (4kB) read-ahead */ -+ blksize_size[fake_major] = blk_sizes; -+ blk_size[fake_major] = sizes; -+ INIT_HARDSECT(hardsect_size, fake_major, hardsect_sizes); -+ add_gendisk(&fake_gendisk); -+ } -+ -+ for(i=0;ifd); -+ if(dev->cow.file != NULL) { -+ os_close_file(dev->cow.fd); -+ vfree(dev->cow.bitmap); -+ dev->cow.bitmap = NULL; -+ } -+} -+ -+static int ubd_open_dev(struct ubd *dev) -+{ -+ struct openflags flags; -+ 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, -+ &dev->cow.bitmap_offset, &dev->cow.bitmap_len, -+ &dev->cow.data_offset, create_ptr); -+ -+ if((dev->fd == -ENOENT) && create_cow){ -+ dev->fd = create_cow_file(dev->file, dev->cow.file, -+ dev->openflags, 1 << 9, -+ &dev->cow.bitmap_offset, -+ &dev->cow.bitmap_len, -+ &dev->cow.data_offset); -+ if(dev->fd >= 0){ -+ printk(KERN_INFO "Creating \"%s\" as COW file for " -+ "\"%s\"\n", dev->file, dev->cow.file); -+ } -+ } -+ -+ if(dev->fd < 0) return(dev->fd); -+ -+ if(dev->cow.file != NULL){ -+ err = -ENOMEM; -+ dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); -+ if(dev->cow.bitmap == NULL) 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; -+ -+ flags = dev->openflags; -+ flags.w = 0; -+ err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, -+ NULL, NULL); -+ if(err < 0) goto error; -+ dev->cow.fd = err; -+ } -+ return(0); -+ error: -+ os_close_file(dev->fd); -+ return(err); -+} -+ -+static int ubd_file_size(struct ubd *dev, __u64 *size_out) -+{ -+ char *file; -+ -+ file = dev->cow.file ? dev->cow.file : dev->file; -+ return(os_file_size(file, size_out)); -+} -+ -+static int ubd_open(struct inode *inode, struct file *filp) -+{ -+ struct ubd *dev; -+ int n, offset, err = 0; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ dev = &ubd_dev[n]; -+ if(n >= MAX_DEV) -+ return -ENODEV; -+ -+ spin_lock(&ubd_lock); -+ offset = n << UBD_SHIFT; -+ -+ if(dev->count == 0){ -+ err = ubd_open_dev(dev); -+ if(err){ -+ printk(KERN_ERR "ubd%d: Can't open \"%s\": " -+ "errno = %d\n", n, dev->file, -err); -+ goto out; -+ } -+ err = ubd_file_size(dev, &dev->size); -+ if(err) -+ goto out; -+ sizes[offset] = dev->size / BLOCK_SIZE; -+ ubd_part[offset].nr_sects = dev->size / hardsect_sizes[offset]; -+ } -+ dev->count++; -+ if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ -+ if(--dev->count == 0) ubd_close(dev); -+ err = -EROFS; -+ } -+ out: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static int ubd_release(struct inode * inode, struct file * file) -+{ -+ int n, offset; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ offset = n << UBD_SHIFT; -+ if(n >= MAX_DEV) -+ return -ENODEV; -+ -+ spin_lock(&ubd_lock); -+ if(--ubd_dev[n].count == 0) -+ ubd_close(&ubd_dev[n]); -+ spin_unlock(&ubd_lock); -+ -+ return(0); -+} -+ -+void cowify_req(struct io_thread_req *req, struct ubd *dev) -+{ -+ int i, update_bitmap, sector = req->offset >> 9; -+ -+ 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)){ -+ 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; -+ } -+ } -+} -+ -+static int prepare_request(struct request *req, struct io_thread_req *io_req) -+{ -+ struct ubd *dev; -+ __u64 block; -+ int nsect, minor, n; -+ -+ if(req->rq_status == RQ_INACTIVE) return(1); -+ -+ minor = MINOR(req->rq_dev); -+ n = minor >> UBD_SHIFT; -+ dev = &ubd_dev[n]; -+ if(IS_WRITE(req) && !dev->openflags.w){ -+ printk("Write attempted on readonly ubd device %d\n", n); -+ end_request(0); -+ return(1); -+ } -+ -+ req->sector += ubd_part[minor].start_sect; -+ block = req->sector; -+ nsect = req->current_nr_sectors; -+ -+ io_req->op = (req->cmd == 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->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); -+ return(0); -+} -+ -+static void do_ubd_request(request_queue_t *q) -+{ -+ struct io_thread_req io_req; -+ struct request *req; -+ int err, n; -+ -+ if(thread_fd == -1){ -+ while(!list_empty(&q->queue_head)){ -+ req = blkdev_entry_next_request(&q->queue_head); -+ err = prepare_request(req, &io_req); -+ if(!err){ -+ do_io(&io_req); -+ ubd_finish(io_req.error); -+ } -+ } -+ } -+ else { -+ if(DEVICE_INTR || list_empty(&q->queue_head)) return; -+ req = blkdev_entry_next_request(&q->queue_head); -+ err = prepare_request(req, &io_req); -+ if(!err){ -+ SET_INTR(ubd_handler); -+ n = write_ubd_fs(thread_fd, (char *) &io_req, -+ sizeof(io_req)); -+ if(n != sizeof(io_req)) -+ printk("write to io thread failed, " -+ "errno = %d\n", -n); -+ } -+ } -+} -+ -+static int ubd_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hd_geometry *loc = (struct hd_geometry *) arg; -+ struct ubd *dev; -+ int n, minor, err; -+ struct hd_driveid ubd_id = { -+ .cyls = 0, -+ .heads = 128, -+ .sectors = 32, -+ }; -+ -+ if(!inode) return(-EINVAL); -+ minor = MINOR(inode->i_rdev); -+ n = minor >> UBD_SHIFT; -+ if(n >= MAX_DEV) -+ return(-EINVAL); -+ dev = &ubd_dev[n]; -+ switch (cmd) { -+ struct hd_geometry g; -+ struct cdrom_volctrl volume; -+ case HDIO_GETGEO: -+ if(!loc) return(-EINVAL); -+ g.heads = 128; -+ g.sectors = 32; -+ g.cylinders = dev->size / (128 * 32 * hardsect_sizes[minor]); -+ g.start = 2; -+ return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0); -+ case BLKGETSIZE: /* Return device size */ -+ if(!arg) return(-EINVAL); -+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); -+ if(err) -+ return(err); -+ put_user(ubd_part[minor].nr_sects, (long *) arg); -+ return(0); -+ case BLKRRPART: /* Re-read partition tables */ -+ return(ubd_revalidate(inode->i_rdev)); -+ -+ case HDIO_SET_UNMASKINTR: -+ if(!capable(CAP_SYS_ADMIN)) return(-EACCES); -+ if((arg > 1) || (minor & 0x3F)) return(-EINVAL); -+ return(0); -+ -+ case HDIO_GET_UNMASKINTR: -+ if(!arg) return(-EINVAL); -+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); -+ if(err) -+ return(err); -+ return(0); -+ -+ case HDIO_GET_MULTCOUNT: -+ if(!arg) return(-EINVAL); -+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); -+ if(err) -+ return(err); -+ return(0); -+ -+ case HDIO_SET_MULTCOUNT: -+ if(!capable(CAP_SYS_ADMIN)) return(-EACCES); -+ if(MINOR(inode->i_rdev) & 0x3F) return(-EINVAL); -+ return(0); -+ -+ case HDIO_GET_IDENTITY: -+ ubd_id.cyls = dev->size / (128 * 32 * hardsect_sizes[minor]); -+ if(copy_to_user((char *) arg, (char *) &ubd_id, -+ sizeof(ubd_id))) -+ return(-EFAULT); -+ return(0); -+ -+ case CDROMVOLREAD: -+ if(copy_from_user(&volume, (char *) arg, sizeof(volume))) -+ return(-EFAULT); -+ volume.channel0 = 255; -+ volume.channel1 = 255; -+ volume.channel2 = 255; -+ volume.channel3 = 255; -+ if(copy_to_user((char *) arg, &volume, sizeof(volume))) -+ return(-EFAULT); -+ return(0); -+ -+ default: -+ return blk_ioctl(inode->i_rdev, cmd, arg); -+ } -+} -+ -+static int ubd_revalidate1(kdev_t rdev) -+{ -+ int i, n, offset, err = 0, pcount = 1 << UBD_SHIFT; -+ struct ubd *dev; -+ struct hd_struct *part; -+ -+ n = DEVICE_NR(rdev); -+ offset = n << UBD_SHIFT; -+ dev = &ubd_dev[n]; -+ -+ part = &ubd_part[offset]; -+ -+ /* clear all old partition counts */ -+ for(i = 1; i < pcount; i++) { -+ part[i].start_sect = 0; -+ part[i].nr_sects = 0; -+ } -+ -+ /* If it already has been opened we can check the partitions -+ * directly -+ */ -+ if(dev->count){ -+ part->start_sect = 0; -+ register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount, -+ &ubd_blops, part->nr_sects); -+ } -+ else if(dev->file){ -+ err = ubd_open_dev(dev); -+ if(err){ -+ printk(KERN_ERR "unable to open %s for validation\n", -+ dev->file); -+ goto out; -+ } -+ -+ /* have to recompute sizes since we opened it */ -+ err = ubd_file_size(dev, &dev->size); -+ if(err) { -+ ubd_close(dev); -+ goto out; -+ } -+ part->start_sect = 0; -+ part->nr_sects = dev->size / hardsect_sizes[offset]; -+ register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount, -+ &ubd_blops, part->nr_sects); -+ -+ /* we are done so close it */ -+ ubd_close(dev); -+ } -+ else err = -ENODEV; -+ out: -+ return(err); -+} -+ -+static int ubd_revalidate(kdev_t rdev) -+{ -+ int err; -+ -+ spin_lock(&ubd_lock); -+ err = ubd_revalidate1(rdev); -+ spin_unlock(&ubd_lock); -+ 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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/ubd_user.c um/arch/um/drivers/ubd_user.c ---- orig/arch/um/drivers/ubd_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/ubd_user.c Thu Mar 6 18:08:55 2003 -@@ -0,0 +1,626 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "asm/types.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "ubd_user.h" -+#include "os.h" -+ -+#include -+#include -+#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 stat64 buf1, buf2; -+ -+ if(from_cmdline == NULL) return(1); -+ if(!strcmp(from_cmdline, from_cow)) return(1); -+ -+ if(stat64(from_cmdline, &buf1) < 0){ -+ printk("Couldn't stat '%s', errno = %d\n", from_cmdline, -+ errno); -+ return(1); -+ } -+ if(stat64(from_cow, &buf2) < 0){ -+ printk("Couldn't stat '%s', errno = %d\n", from_cow, errno); -+ return(1); -+ } -+ if((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino)) -+ return(1); -+ -+ printk("Backing file mismatch - \"%s\" requested,\n" -+ "\"%s\" specified in COW header of \"%s\"\n", -+ from_cmdline, from_cow, cow); -+ return(0); -+} -+ -+static int backing_file_mismatch(char *file, __u64 size, time_t mtime) -+{ -+ struct stat64 buf; -+ 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_size(file, &actual); -+ if(err){ -+ printk("Failed to get size of backing file \"%s\", " -+ "errno = %d\n", file, -err); -+ return(err); -+ } -+ -+ if(actual != size){ -+ printk("Size mismatch (%ld vs %ld) of COW header vs backing " -+ "file\n", size, actual); -+ return(-EINVAL); -+ } -+ if(buf.st_mtime != mtime){ -+ printk("mtime mismatch (%ld vs %ld) of COW header vs backing " -+ "file\n", mtime, buf.st_mtime); -+ return(-EINVAL); -+ } -+ return(0); -+} -+ -+int read_cow_bitmap(int fd, void *buf, int offset, int len) -+{ -+ 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); -+} -+ -+static int absolutize(char *to, int size, char *from) -+{ -+ char save_cwd[256], *slash; -+ int remaining; -+ -+ 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, -+ int *create_cow_out) -+{ -+ time_t mtime; -+ __u64 size; -+ char *backing_file; -+ int fd, err, sectorsize, magic, same, mode = 0644; -+ -+ if((fd = os_open_file(file, *openflags, mode)) < 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) -+ return(fd); -+ } -+ -+ err = os_lock_file(fd, openflags->w); -+ if(err){ -+ printk("Failed to lock '%s', errno = %d\n", file, -err); -+ goto error; -+ } -+ -+ if(backing_file_out == NULL) return(fd); -+ -+ err = read_cow_header(fd, &magic, &backing_file, &mtime, &size, -+ §orsize, 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; -+ } -+ if(err) return(fd); -+ -+ if(backing_file_out == NULL) return(fd); -+ -+ same = same_backing_files(*backing_file_out, backing_file, file); -+ -+ 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); -+ if(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; -+ } -+ -+ sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, -+ data_offset_out); -+ -+ return(fd); -+ error: -+ 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, -+ unsigned long *bitmap_len_out, int *data_offset_out) -+{ -+ __u64 offset; -+ int err, fd; -+ long long size; -+ char zero = 0; -+ -+ flags.c = 1; -+ fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL); -+ if(fd < 0){ -+ err = fd; -+ printk("Open of COW file '%s' failed, errno = %d\n", cow_file, -+ -err); -+ goto out; -+ } -+ -+ err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size); -+ if(err) 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); -+ -+ offset = *data_offset_out + size - sizeof(zero); -+ err = os_seek_file(fd, offset); -+ if(err != 0){ -+ printk("cow bitmap lseek failed : errno = %d\n", errno); -+ goto out_close; -+ } -+ -+ /* 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 = os_write_file(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; -+ } -+ -+ return(fd); -+ -+ out_close: -+ close(fd); -+ out: -+ return(err); -+} -+ -+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); -+} -+ -+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); -+} -+ -+void do_io(struct io_thread_req *req) -+{ -+ char *buf; -+ unsigned long len; -+ int n, nsectors, start, end, bit; -+ __u64 off; -+ -+ nsectors = req->length / req->sectorsize; -+ start = 0; -+ do { -+ bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask); -+ end = start; -+ while((end < nsectors) && -+ (ubd_test_bit(end, (unsigned char *) -+ &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); -+ req->error = 1; -+ return; -+ } -+ if(req->op == UBD_READ){ -+ n = 0; -+ do { -+ buf = &buf[n]; -+ len -= n; -+ n = read(req->fds[bit], buf, len); -+ if (n < 0) { -+ printk("do_io - read returned %d : " -+ "errno = %d fd = %d\n", n, -+ errno, req->fds[bit]); -+ req->error = 1; -+ return; -+ } -+ } while((n < len) && (n != 0)); -+ if (n < len) memset(&buf[n], 0, len - n); -+ } -+ else { -+ n = write(req->fds[bit], buf, len); -+ if(n != len){ -+ printk("do_io - write returned %d : " -+ "errno = %d fd = %d\n", n, -+ errno, req->fds[bit]); -+ req->error = 1; -+ return; -+ } -+ } -+ -+ 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; -+} -+ -+/* Changed in start_io_thread, which is serialized by being called only -+ * from ubd_init, which is an initcall. -+ */ -+int kernel_fd = -1; -+ -+/* Only changed by the io thread */ -+int io_count = 0; -+ -+int io_thread(void *arg) -+{ -+ struct io_thread_req req; -+ int n; -+ -+ 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); -+ continue; -+ } -+ io_count++; -+ do_io(&req); -+ n = write(kernel_fd, &req, sizeof(req)); -+ if(n != sizeof(req)) -+ printk("io_thread - write failed, errno = %d\n", -+ errno); -+ } -+} -+ -+int start_io_thread(unsigned long sp, int *fd_out) -+{ -+ 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); -+ } -+ kernel_fd = fds[0]; -+ *fd_out = fds[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); -+} -+ -+#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); -+} -+#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 -Naur -X ../exclude-files orig/arch/um/drivers/xterm.c um/arch/um/drivers/xterm.c ---- orig/arch/um/drivers/xterm.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/xterm.c Mon Dec 30 20:49:22 2002 -@@ -0,0 +1,200 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "kern_util.h" -+#include "chan_user.h" -+#include "helper.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+#include "xterm.h" -+ -+struct xterm_chan { -+ int pid; -+ int helper_pid; -+ char *title; -+ int device; -+ int raw; -+ struct termios tt; -+ unsigned long stack; -+ int direct_rcv; -+}; -+ -+void *xterm_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct xterm_chan *data; -+ -+ if((data = malloc(sizeof(*data))) == NULL) return(NULL); -+ *data = ((struct xterm_chan) { .pid = -1, -+ .helper_pid = -1, -+ .device = device, -+ .title = opts->xterm_title, -+ .raw = opts->raw, -+ .stack = opts->tramp_stack, -+ .direct_rcv = !opts->in_kernel } ); -+ return(data); -+} -+ -+/* Only changed by xterm_setup, which is a setup */ -+static char *terminal_emulator = "xterm"; -+static char *title_switch = "-T"; -+static char *exec_switch = "-e"; -+ -+static int __init xterm_setup(char *line, int *add) -+{ -+ *add = 0; -+ terminal_emulator = line; -+ -+ line = strchr(line, ','); -+ if(line == NULL) return(0); -+ *line++ = '\0'; -+ if(*line) title_switch = line; -+ -+ line = strchr(line, ','); -+ if(line == NULL) return(0); -+ *line++ = '\0'; -+ if(*line) exec_switch = line; -+ -+ return(0); -+} -+ -+__uml_setup("xterm=", xterm_setup, -+"xterm=,,<exec switch>\n" -+" Specifies an alternate terminal emulator to use for the debugger,\n" -+" consoles, and serial lines when they are attached to the xterm channel.\n" -+" The values are the terminal emulator binary, the switch it uses to set\n" -+" its title, and the switch it uses to execute a subprocess,\n" -+" respectively. The title switch must have the form '<switch> title',\n" -+" not '<switch>=title'. Similarly, the exec switch must have the form\n" -+" '<switch> command arg1 arg2 ...'.\n" -+" The default values are 'xterm=xterm,-T,-e'. Values for gnome-terminal\n" -+" are 'xterm=gnome-terminal,-t,-x'.\n\n" -+); -+ -+int xterm_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct xterm_chan *data = d; -+ unsigned long stack; -+ int pid, fd, new, err; -+ char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; -+ char *argv[] = { terminal_emulator, title_switch, title, exec_switch, -+ "/usr/lib/uml/port-helper", "-uml-socket", -+ file, NULL }; -+ -+ if(access(argv[4], X_OK)) -+ argv[4] = "port-helper"; -+ -+ fd = mkstemp(file); -+ if(fd < 0){ -+ printk("xterm_open : mkstemp failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if(unlink(file)){ -+ printk("xterm_open : unlink failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ close(fd); -+ -+ fd = create_unix_socket(file, sizeof(file)); -+ if(fd < 0){ -+ printk("xterm_open : create_unix_socket failed, errno = %d\n", -+ -fd); -+ return(-fd); -+ } -+ -+ sprintf(title, data->title, data->device); -+ stack = data->stack; -+ pid = run_helper(NULL, NULL, argv, &stack); -+ if(pid < 0){ -+ printk("xterm_open : run_helper failed, errno = %d\n", -pid); -+ return(pid); -+ } -+ -+ if(data->stack == 0) free_stack(stack, 0); -+ -+ if(data->direct_rcv) -+ new = os_rcv_fd(fd, &data->helper_pid); -+ else { -+ if((err = os_set_fd_block(fd, 0)) != 0){ -+ printk("xterm_open : failed to set descriptor " -+ "non-blocking, errno = %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); -+ goto out; -+ } -+ -+ tcgetattr(new, &data->tt); -+ if(data->raw) raw(new, 0); -+ -+ data->pid = pid; -+ *dev_out = NULL; -+ out: -+ unlink(file); -+ return(new); -+} -+ -+void xterm_close(int fd, void *d) -+{ -+ struct xterm_chan *data = d; -+ -+ if(data->pid != -1) -+ os_kill_process(data->pid, 1); -+ data->pid = -1; -+ if(data->helper_pid != -1) -+ os_kill_process(data->helper_pid, 0); -+ data->helper_pid = -1; -+ close(fd); -+} -+ -+void xterm_free(void *d) -+{ -+ free(d); -+} -+ -+int xterm_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct xterm_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops xterm_ops = { -+ .type = "xterm", -+ .init = xterm_init, -+ .open = xterm_open, -+ .close = xterm_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = xterm_console_write, -+ .window_size = generic_window_size, -+ .free = xterm_free, -+ .winch = 1, -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/drivers/xterm.h um/arch/um/drivers/xterm.h ---- orig/arch/um/drivers/xterm.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/xterm.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __XTERM_H__ -+#define __XTERM_H__ -+ -+extern int xterm_fd(int socket, int *pid_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 -Naur -X ../exclude-files orig/arch/um/drivers/xterm_kern.c um/arch/um/drivers/xterm_kern.c ---- orig/arch/um/drivers/xterm_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/drivers/xterm_kern.c Tue Dec 17 17:31:20 2002 -@@ -0,0 +1,79 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/errno.h" -+#include "linux/slab.h" -+#include "asm/semaphore.h" -+#include "asm/irq.h" -+#include "irq_user.h" -+#include "kern_util.h" -+#include "os.h" -+#include "xterm.h" -+ -+struct xterm_wait { -+ struct semaphore sem; -+ int fd; -+ int pid; -+ int new_fd; -+}; -+ -+static void 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; -+ -+ xterm->new_fd = fd; -+ up(&xterm->sem); -+} -+ -+int xterm_fd(int socket, int *pid_out) -+{ -+ struct xterm_wait *data; -+ int err, ret; -+ -+ data = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(data == NULL){ -+ printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n"); -+ return(-ENOMEM); -+ } -+ *data = ((struct xterm_wait) -+ { .sem = __SEMAPHORE_INITIALIZER(data->sem, 0), -+ .fd = socket, -+ .pid = -1, -+ .new_fd = -1 }); -+ -+ err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "xterm", data); -+ if(err){ -+ printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " -+ "err = %d\n", err); -+ return(err); -+ } -+ down(&data->sem); -+ -+ free_irq(XTERM_IRQ, data); -+ -+ ret = data->new_fd; -+ *pid_out = data->pid; -+ kfree(data); -+ -+ return(ret); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/dyn_link.ld.in um/arch/um/dyn_link.ld.in ---- orig/arch/um/dyn_link.ld.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/dyn_link.ld.in Fri Jan 17 23:37:27 2003 -@@ -0,0 +1,172 @@ -+OUTPUT_FORMAT("ELF_FORMAT") -+OUTPUT_ARCH(ELF_ARCH) -+ENTRY(_start) -+SEARCH_DIR("/usr/local/i686-pc-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); -+/* Do we need any of these for elf? -+ __DYNAMIC = 0; */ -+SECTIONS -+{ -+ . = START() + SIZEOF_HEADERS; -+ .interp : { *(.interp) } -+ . = ALIGN(4096); -+ __binary_start = .; -+ . = ALIGN(4096); /* Init code and data */ -+ _stext = .; -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ -+ . = ALIGN(4096); -+ -+ /* Read-only sections, merged into text segment: */ -+ .hash : { *(.hash) } -+ .dynsym : { *(.dynsym) } -+ .dynstr : { *(.dynstr) } -+ .gnu.version : { *(.gnu.version) } -+ .gnu.version_d : { *(.gnu.version_d) } -+ .gnu.version_r : { *(.gnu.version_r) } -+ .rel.init : { *(.rel.init) } -+ .rela.init : { *(.rela.init) } -+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } -+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } -+ .rel.fini : { *(.rel.fini) } -+ .rela.fini : { *(.rela.fini) } -+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } -+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } -+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } -+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } -+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } -+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } -+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } -+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } -+ .rel.ctors : { *(.rel.ctors) } -+ .rela.ctors : { *(.rela.ctors) } -+ .rel.dtors : { *(.rel.dtors) } -+ .rela.dtors : { *(.rela.dtors) } -+ .rel.got : { *(.rel.got) } -+ .rela.got : { *(.rela.got) } -+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } -+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } -+ .rel.plt : { *(.rel.plt) } -+ .rela.plt : { *(.rela.plt) } -+ .init : { -+ KEEP (*(.init)) -+ } =0x90909090 -+ .plt : { *(.plt) } -+ .text : { -+ *(.text .stub .text.* .gnu.linkonce.t.*) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ } =0x90909090 -+ .fini : { -+ KEEP (*(.fini)) -+ } =0x90909090 -+ -+ PROVIDE (__etext = .); -+ PROVIDE (_etext = .); -+ PROVIDE (etext = .); -+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } -+ .rodata1 : { *(.rodata1) } -+ .eh_frame_hdr : { *(.eh_frame_hdr) } -+ -+ -+ . = ALIGN(4096); -+ PROVIDE (_sdata = .); -+ -+include(`arch/um/common.ld.in') -+ -+ /* Ensure the __preinit_array_start label is properly aligned. We -+ could instead move the label definition inside the section, but -+ the linker would then create the section even if it turns out to -+ be empty, which isn't pretty. */ -+ . = ALIGN(32 / 8); -+ .preinit_array : { *(.preinit_array) } -+ .init_array : { *(.init_array) } -+ .fini_array : { *(.fini_array) } -+ .data : { -+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ -+ *(.data.init_task) -+ *(.data .data.* .gnu.linkonce.d.*) -+ SORT(CONSTRUCTORS) -+ } -+ .data1 : { *(.data1) } -+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } -+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } -+ .eh_frame : { KEEP (*(.eh_frame)) } -+ .gcc_except_table : { *(.gcc_except_table) } -+ .dynamic : { *(.dynamic) } -+ .ctors : { -+ /* gcc uses crtbegin.o to find the start of -+ the constructors, so we make sure it is -+ first. Because this is a wildcard, it -+ doesn't matter if the user does not -+ actually link against crtbegin.o; the -+ linker won't look for a file to match a -+ wildcard. The wildcard also means that it -+ doesn't matter which directory crtbegin.o -+ is in. */ -+ KEEP (*crtbegin.o(.ctors)) -+ /* We don't want to include the .ctor section from -+ from the crtend.o file until after the sorted ctors. -+ The .ctor section from the crtend file contains the -+ end of ctors marker and it must be last */ -+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) -+ KEEP (*(SORT(.ctors.*))) -+ KEEP (*(.ctors)) -+ } -+ .dtors : { -+ KEEP (*crtbegin.o(.dtors)) -+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) -+ KEEP (*(SORT(.dtors.*))) -+ KEEP (*(.dtors)) -+ } -+ .jcr : { KEEP (*(.jcr)) } -+ .got : { *(.got.plt) *(.got) } -+ _edata = .; -+ PROVIDE (edata = .); -+ __bss_start = .; -+ .bss : { -+ *(.dynbss) -+ *(.bss .bss.* .gnu.linkonce.b.*) -+ *(COMMON) -+ /* Align here to ensure that the .bss section occupies space up to -+ _end. Align after .bss to ensure correct alignment even if the -+ .bss section disappears because there are no input sections. */ -+ . = ALIGN(32 / 8); -+ . = ALIGN(32 / 8); -+ } -+ _end = .; -+ PROVIDE (end = .); -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+ /* DWARF debug sections. -+ Symbols in the DWARF debugging sections are relative to the beginning -+ of the section so we begin them at 0. */ -+ /* DWARF 1 */ -+ .debug 0 : { *(.debug) } -+ .line 0 : { *(.line) } -+ /* GNU DWARF 1 extensions */ -+ .debug_srcinfo 0 : { *(.debug_srcinfo) } -+ .debug_sfnames 0 : { *(.debug_sfnames) } -+ /* DWARF 1.1 and DWARF 2 */ -+ .debug_aranges 0 : { *(.debug_aranges) } -+ .debug_pubnames 0 : { *(.debug_pubnames) } -+ /* DWARF 2 */ -+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } -+ .debug_abbrev 0 : { *(.debug_abbrev) } -+ .debug_line 0 : { *(.debug_line) } -+ .debug_frame 0 : { *(.debug_frame) } -+ .debug_str 0 : { *(.debug_str) } -+ .debug_loc 0 : { *(.debug_loc) } -+ .debug_macinfo 0 : { *(.debug_macinfo) } -+ /* SGI/MIPS DWARF 2 extensions */ -+ .debug_weaknames 0 : { *(.debug_weaknames) } -+ .debug_funcnames 0 : { *(.debug_funcnames) } -+ .debug_typenames 0 : { *(.debug_typenames) } -+ .debug_varnames 0 : { *(.debug_varnames) } -+} -diff -Naur -X ../exclude-files orig/arch/um/fs/Makefile um/arch/um/fs/Makefile ---- orig/arch/um/fs/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/fs/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,23 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := built-in.o -+ -+subdir-y = -+subdir-m = -+ -+subdir-$(CONFIG_HOSTFS) += hostfs -+subdir-$(CONFIG_HPPFS) += hppfs -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+obj-m += $(join $(subdir-m),$(subdir-m:%=/%.o)) -+ -+include $(TOPDIR)/Rules.make -+ -+dep: -+ -+clean: -+ -+archmrproper: -diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/Makefile um/arch/um/fs/hostfs/Makefile ---- orig/arch/um/fs/hostfs/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/fs/hostfs/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,24 @@ -+# -+# 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 -+ -+USER_CFLAGS := $(USER_CFLAGS) -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD) -+ -+O_TARGET := hostfs.o -+obj-y = hostfs_kern.o hostfs_user.o -+obj-m = $(O_TARGET) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs.h um/arch/um/fs/hostfs/hostfs.h ---- orig/arch/um/fs/hostfs/hostfs.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/fs/hostfs/hostfs.h Mon Feb 24 23:00:47 2003 -@@ -0,0 +1,69 @@ -+#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; -+ time_t ia_atime; -+ time_t ia_mtime; -+ time_t ia_ctime; -+ unsigned int ia_attr_flags; -+}; -+ -+extern int stat_file(const char *path, int *dev_out, -+ unsigned long long *inode_out, int *mode_out, -+ int *nlink_out, int *uid_out, int *gid_out, -+ unsigned long long *size_out, unsigned long *atime_out, -+ unsigned long *mtime_out, unsigned long *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); -+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 -diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs_kern.c um/arch/um/fs/hostfs/hostfs_kern.c ---- orig/arch/um/fs/hostfs/hostfs_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/fs/hostfs/hostfs_kern.c Thu Mar 6 16:32:38 2003 -@@ -0,0 +1,870 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#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 <asm/uaccess.h> -+#include "hostfs.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "user_util.h" -+#include "2_5compat.h" -+ -+#define file_hostfs_i(file) (&(file)->f_dentry->d_inode->u.hostfs_i) -+ -+int hostfs_d_delete(struct dentry *dentry) -+{ -+ return(1); -+} -+ -+struct dentry_operations hostfs_dentry_ops = { -+ .d_delete = hostfs_d_delete, -+}; -+ -+/* Not changed */ -+static char *root_ino = "/"; -+ -+#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 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 = parent->d_inode->u.hostfs_i.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_dev, 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_dev, &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_dev = i_dev; -+ 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(kdev_same(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; -+ -+ 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); -+} -+ -+void hostfs_delete_inode(struct inode *ino) -+{ -+ if(ino->u.hostfs_i.host_filename) -+ kfree(ino->u.hostfs_i.host_filename); -+ ino->u.hostfs_i.host_filename = NULL; -+ -+ if(ino->u.hostfs_i.fd != -1) -+ close_file(&ino->u.hostfs_i.fd); -+ -+ ino->u.hostfs_i.mode = 0; -+ clear_inode(ino); -+} -+ -+int hostfs_statfs(struct super_block *sb, struct statfs *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(sb->s_root->d_inode->u.hostfs_i.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 super_operations hostfs_sbops = { -+ .put_inode = force_delete, -+ .delete_inode = hostfs_delete_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 & ino->u.hostfs_i.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(ino->u.hostfs_i.fd != -1){ -+ close_file(&ino->u.hostfs_i.fd); -+ ino->u.hostfs_i.fd = -1; -+ } -+ -+ ino->u.hostfs_i.mode |= mode; -+ if(ino->u.hostfs_i.mode & FMODE_READ) -+ r = 1; -+ if(ino->u.hostfs_i.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); -+ kfree(name); -+ if(fd < 0) return(fd); -+ file_hostfs_i(file)->fd = fd; -+ -+ return(0); -+} -+ -+int hostfs_dir_open(struct inode *ino, struct file *file) -+{ -+ return(0); -+} -+ -+int hostfs_dir_release(struct inode *ino, struct file *file) -+{ -+ return(0); -+} -+ -+int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) -+{ -+ return(0); -+} -+ -+static struct file_operations hostfs_file_fops = { -+ .owner = NULL, -+ .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 = { -+ .owner = NULL, -+ .readdir = hostfs_readdir, -+ .open = hostfs_dir_open, -+ .release = hostfs_dir_release, -+ .fsync = hostfs_fsync, -+}; -+ -+int hostfs_writepage(struct page *page) -+{ -+ 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(inode->u.hostfs_i.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); -+ -+ UnlockPage(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; -+ -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ if (PageError(page)) ClearPageError(page); -+ err = 0; -+ out: -+ kunmap(page); -+ UnlockPage(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, -+ .prepare_write = hostfs_prepare_write, -+ .commit_write = hostfs_commit_write -+}; -+ -+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int *error) -+{ -+ struct inode *inode; -+ char *name; -+ int type, err = -ENOMEM, rdev; -+ -+ inode = new_inode(sb); -+ if(inode == NULL) -+ goto out; -+ -+ inode->u.hostfs_i.host_filename = NULL; -+ inode->u.hostfs_i.fd = -1; -+ inode->u.hostfs_i.mode = 0; -+ insert_inode_hash(inode); -+ if(dentry){ -+ name = dentry_name(dentry, 0); -+ if(name == NULL){ -+ err = -ENOMEM; -+ goto out_put; -+ } -+ type = file_type(name, &rdev); -+ kfree(name); -+ } -+ else type = OS_TYPE_DIR; -+ inode->i_sb = sb; -+ -+ 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; -+ } -+ -+ if(error) *error = err; -+ return(inode); -+ out_put: -+ iput(inode); -+ out: -+ if(error) *error = err; -+ return(NULL); -+} -+ -+int hostfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ struct inode *inode; -+ char *name; -+ int error; -+ -+ inode = get_inode(dir->i_sb, dentry, &error); -+ if(error) return(error); -+ name = dentry_name(dentry, 0); -+ if(name == NULL){ -+ iput(inode); -+ return(-ENOMEM); -+ } -+ error = 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(!error) error = read_name(inode, name); -+ kfree(name); -+ if(error){ -+ iput(inode); -+ return(error); -+ } -+ d_instantiate(dentry, inode); -+ return(0); -+} -+ -+struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry) -+{ -+ struct inode *inode; -+ char *name; -+ int error; -+ -+ inode = get_inode(ino->i_sb, dentry, &error); -+ if(error != 0) return(ERR_PTR(error)); -+ name = dentry_name(dentry, 0); -+ if(name == NULL) return(ERR_PTR(-ENOMEM)); -+ error = read_name(inode, name); -+ kfree(name); -+ if(error){ -+ iput(inode); -+ if(error == -ENOENT) inode = NULL; -+ else return(ERR_PTR(error)); -+ } -+ d_add(dentry, inode); -+ dentry->d_op = &hostfs_dentry_ops; -+ return(NULL); -+} -+ -+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); -+ 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, int dev) -+{ -+ struct inode *inode; -+ char *name; -+ int error; -+ -+ inode = get_inode(dir->i_sb, dentry, &error); -+ if(error) return(error); -+ name = dentry_name(dentry, 0); -+ if(name == NULL){ -+ iput(inode); -+ return(-ENOMEM); -+ } -+ init_special_inode(inode, mode, dev); -+ error = do_mknod(name, mode, dev); -+ if(!error) error = read_name(inode, name); -+ kfree(name); -+ if(error){ -+ iput(inode); -+ return(error); -+ } -+ d_instantiate(dentry, inode); -+ return(0); -+} -+ -+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) -+{ -+ 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; -+ -+ 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(kdev_same(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(kdev_same(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 dentry *dentry, struct iattr *attr) -+{ -+ not_implemented(); -+ return(-EINVAL); -+} -+ -+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); -+ UnlockPage(page); -+ return(err); -+} -+ -+static struct address_space_operations hostfs_link_aops = { -+ .readpage = hostfs_link_readpage, -+}; -+ -+static struct super_block *hostfs_read_super_common(struct super_block *sb, -+ char *data) -+{ -+ struct inode *root_inode; -+ char *name; -+ -+ sb->s_blocksize = 1024; -+ sb->s_blocksize_bits = 10; -+ sb->s_magic = HOSTFS_SUPER_MAGIC; -+ sb->s_op = &hostfs_sbops; -+ if((data == NULL) || (*((char *) data) == '\0')) data = root_ino; -+ name = kmalloc(strlen(data) + 1, GFP_KERNEL); -+ if(name == NULL) return(NULL); -+ strcpy(name, data); -+ root_inode = get_inode(sb, NULL, NULL); -+ if(root_inode == NULL) -+ goto out_free; -+ -+ root_inode->u.hostfs_i.host_filename = name; -+ sb->s_root = d_alloc_root(root_inode); -+ if(read_inode(root_inode)) -+ goto out_put; -+ return(sb); -+ -+ out_free: -+ kfree(name); -+ out_put: -+ iput(root_inode); -+ return(NULL); -+} -+ -+struct super_block *hostfs_read_super(struct super_block *sb, void *data, -+ int silent) -+{ -+ return(hostfs_read_super_common(sb, data)); -+} -+ -+DECLARE_FSTYPE(hostfs_type, "hostfs", hostfs_read_super, 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 -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs_user.c um/arch/um/fs/hostfs/hostfs_user.c ---- orig/arch/um/fs/hostfs/hostfs_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/fs/hostfs/hostfs_user.c Fri Jan 31 21:48:30 2003 -@@ -0,0 +1,341 @@ -+/* -+ * 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, int *dev_out, unsigned long long *inode_out, -+ int *mode_out, int *nlink_out, int *uid_out, int *gid_out, -+ unsigned long long *size_out, unsigned long *atime_out, -+ unsigned long *mtime_out, unsigned long *ctime_out, -+ int *blksize_out, unsigned long long *blocks_out) -+{ -+ struct stat64 buf; -+ -+ if(lstat64(path, &buf) < 0) -+ return(-errno); -+ if(dev_out != NULL) *dev_out = buf.st_dev; -+ -+ /* 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 = buf.st_atime; -+ if(mtime_out != NULL) *mtime_out = buf.st_mtime; -+ if(ctime_out != NULL) *ctime_out = buf.st_ctime; -+ 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 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"); -+ 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, mode); -+ if(fd < 0) return(-errno); -+ close(fd); -+ return(0); -+} -+ -+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; -+ buf.modtime = attrs->ia_mtime; -+ if(utime(file, &buf) != 0) return(-errno); -+ } -+ else { -+ if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){ -+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, &buf.modtime, NULL, -+ NULL, NULL); -+ if(err != 0) return(err); -+ buf.actime = attrs->ia_atime; -+ 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, NULL, &buf.actime, NULL, NULL, -+ NULL, NULL); -+ if(err != 0) return(err); -+ buf.modtime = attrs->ia_mtime; -+ 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, 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 -Naur -X ../exclude-files orig/arch/um/fs/hppfs/Makefile um/arch/um/fs/hppfs/Makefile ---- orig/arch/um/fs/hppfs/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/fs/hppfs/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,10 @@ -+O_TARGET := hppfs.o -+obj-y = hppfs_kern.o #hppfs_user.o -+obj-m = $(O_TARGET) -+ -+CFLAGS_hppfs_kern.o := $(CFLAGS) -+#CFLAGS_hppfs_user.o := $(USER_CFLAGS) -+ -+override CFLAGS = -+ -+include $(TOPDIR)/Rules.make -diff -Naur -X ../exclude-files orig/arch/um/fs/hppfs/hppfs_kern.c um/arch/um/fs/hppfs/hppfs_kern.c ---- orig/arch/um/fs/hppfs/hppfs_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/fs/hppfs/hppfs_kern.c Thu Feb 27 13:14:26 2003 -@@ -0,0 +1,725 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <linux/fs.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/list.h> -+#include <linux/kernel.h> -+#include <linux/ctype.h> -+#include <asm/uaccess.h> -+#include "os.h" -+ -+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; -+}; -+ -+#define HPPFS_SUPER_MAGIC 0xb00000ee -+ -+static struct super_operations hppfs_sbops; -+ -+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int *error); -+ -+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 struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry) -+{ -+ struct dentry *proc_dentry; -+ 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)); -+ -+ proc_dentry = lookup_hash(&dentry->d_name, ino->u.hppfs_i.proc_dentry); -+ if(IS_ERR(proc_dentry)) -+ return(proc_dentry); -+ -+ inode = get_inode(ino->i_sb, proc_dentry, &err); -+ if(err != 0) -+ return(ERR_PTR(err)); -+ -+ d_add(dentry, inode); -+ dentry->d_op = &hppfs_dentry_ops; -+ return(NULL); -+} -+ -+static struct inode_operations hppfs_file_iops = { -+}; -+ -+static struct inode_operations hppfs_dir_iops = { -+ .lookup = hppfs_lookup, -+}; -+ -+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 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 = inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&data->proc_file, proc_dentry, 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 = inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&data->proc_file, proc_dentry, 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)); -+} -+ -+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_file_fops = { -+ .owner = NULL, -+ .llseek = hppfs_llseek, -+ .read = hppfs_read, -+ .write = hppfs_write, -+ .open = hppfs_open, -+}; -+ -+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 statfs *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 super_operations hppfs_sbops = { -+ .put_inode = force_delete, -+ .delete_inode = NULL, -+ .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 = dentry->d_inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&proc_file, proc_dentry, FMODE_READ); -+ if(err) -+ return(err); -+ -+ readlink = proc_dentry->d_inode->i_op->readlink; -+ n = (*readlink)(proc_dentry, buffer, buflen); -+ -+ if(proc_file.f_op->release) -+ (*proc_file.f_op->release)(proc_dentry->d_inode, &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 = dentry->d_inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&proc_file, proc_dentry, FMODE_READ); -+ if(err) -+ return(err); -+ -+ follow_link = proc_dentry->d_inode->i_op->follow_link; -+ n = (*follow_link)(proc_dentry, nd); -+ -+ if(proc_file.f_op->release) -+ (*proc_file.f_op->release)(proc_dentry->d_inode, &proc_file); -+ -+ return(n); -+} -+ -+static struct inode_operations hppfs_link_iops = { -+ .readlink = hppfs_readlink, -+ .follow_link = hppfs_follow_link, -+}; -+ -+static void read_inode(struct inode *ino) -+{ -+ struct inode *proc_ino; -+ -+ proc_ino = ino->u.hppfs_i.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_dev = proc_ino->i_dev; -+ 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 inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int *error) -+{ -+ struct inode *inode; -+ int err = -ENOMEM; -+ -+ inode = new_inode(sb); -+ if(inode == NULL) -+ goto out; -+ -+ insert_inode_hash(inode); -+ 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; -+ } -+ -+ inode->i_sb = sb; -+ inode->u.hppfs_i.proc_dentry = dentry; -+ -+ read_inode(inode); -+ err = 0; -+ -+ if(error) *error = err; -+ return(inode); -+ out: -+ if(error) *error = err; -+ return(NULL); -+} -+ -+static struct super_block *hppfs_read_super(struct super_block *sb, void *d, -+ int silent) -+{ -+ struct inode *root_inode; -+ struct file_system_type *procfs; -+ struct super_block *proc_sb; -+ -+ 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; -+ -+ dget(proc_sb->s_root); -+ root_inode = get_inode(sb, proc_sb->s_root, NULL); -+ if(root_inode == NULL) -+ goto out_dput; -+ -+ sb->s_root = d_alloc_root(root_inode); -+ if(sb->s_root == NULL) -+ goto out_put; -+ -+ return(sb); -+ -+ out_put: -+ iput(root_inode); -+ out_dput: -+ dput(proc_sb->s_root); -+ out: -+ return(NULL); -+} -+ -+DECLARE_FSTYPE(hppfs_type, "hppfs", hppfs_read_super, 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 -Naur -X ../exclude-files orig/arch/um/include/2_5compat.h um/arch/um/include/2_5compat.h ---- orig/arch/um/include/2_5compat.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/2_5compat.h Thu Feb 27 20:15:19 2003 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#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, \ -+ unblank : NULL, \ -+ setup : setup_proc, \ -+ flags : f, \ -+ index : -1, \ -+ cflag : 0, \ -+ next : NULL \ -+} -+ -+#define INIT_ELV(queue, elv) elevator_init(elv, ELV_NOOP) -+ -+#define ELV_NOOP ELEVATOR_NOOP -+ -+#define INIT_HARDSECT(arr, maj, sizes) arr[maj] = sizes -+ -+#define IS_WRITE(req) ((req)->cmd == WRITE) -+ -+#define SET_PRI(task) \ -+ do { (task)->nice = 20; (task)->counter = -100; } while(0); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/Makefile um/arch/um/include/Makefile ---- orig/arch/um/include/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,7 @@ -+all : sc.h -+ -+sc.h : ../util/mk_sc -+ ../util/mk_sc > $@ -+ -+../util/mk_sc : -+ $(MAKE) -C ../util mk_sc -diff -Naur -X ../exclude-files orig/arch/um/include/chan_kern.h um/arch/um/include/chan_kern.h ---- orig/arch/um/include/chan_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/chan_kern.h Fri Nov 15 13:32:35 2002 -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHAN_KERN_H__ -+#define __CHAN_KERN_H__ -+ -+#include "linux/tty.h" -+#include "linux/list.h" -+#include "chan_user.h" -+ -+struct chan { -+ struct list_head list; -+ char *dev; -+ unsigned int primary:1; -+ unsigned int input:1; -+ unsigned int output:1; -+ unsigned int opened:1; -+ int fd; -+ enum chan_init_pri pri; -+ struct chan_ops *ops; -+ void *data; -+}; -+ -+extern void chan_interrupt(struct list_head *chans, struct tq_struct *task, -+ struct tty_struct *tty, int irq, void *dev); -+extern int parse_chan_pair(char *str, struct list_head *chans, int pri, -+ int device, struct chan_opts *opts); -+extern int open_chan(struct list_head *chans); -+extern int write_chan(struct list_head *chans, const char *buf, int len, -+ int write_irq); -+extern int console_write_chan(struct list_head *chans, const char *buf, -+ int len); -+extern void close_chan(struct list_head *chans); -+extern void chan_enable_winch(struct list_head *chans, void *line); -+extern void enable_chan(struct list_head *chans, void *data); -+extern int chan_window_size(struct list_head *chans, -+ unsigned short *rows_out, -+ unsigned short *cols_out); -+extern int chan_out_fd(struct list_head *chans); -+extern int chan_config_string(struct list_head *chans, char *str, int size, -+ char **error_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 -Naur -X ../exclude-files orig/arch/um/include/chan_user.h um/arch/um/include/chan_user.h ---- orig/arch/um/include/chan_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/chan_user.h Wed Nov 6 16:44:00 2002 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHAN_USER_H__ -+#define __CHAN_USER_H__ -+ -+#include "init.h" -+ -+struct chan_opts { -+ void (*announce)(char *dev_name, int dev); -+ char *xterm_title; -+ int raw; -+ unsigned long tramp_stack; -+ int in_kernel; -+}; -+ -+enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; -+ -+struct chan_ops { -+ char *type; -+ void *(*init)(char *, int, struct chan_opts *); -+ int (*open)(int, int, int, void *, char **); -+ void (*close)(int, void *); -+ int (*read)(int, char *, void *); -+ int (*write)(int, const char *, int, void *); -+ int (*console_write)(int, const char *, int, void *); -+ int (*window_size)(int, void *, unsigned short *, unsigned short *); -+ void (*free)(void *); -+ int winch; -+}; -+ -+extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, -+ xterm_ops; -+ -+extern void generic_close(int fd, void *unused); -+extern int generic_read(int fd, char *c_out, void *unused); -+extern int generic_write(int fd, const char *buf, int n, void *unused); -+extern int generic_console_write(int fd, const char *buf, int n, void *state); -+extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, -+ unsigned short *cols_out); -+extern void generic_free(void *data); -+ -+extern void register_winch(int fd, void *device_data); -+extern void register_winch_irq(int fd, int tty_fd, int pid, void *line); -+ -+#define __channel_help(fn, prefix) \ -+__uml_help(fn, prefix "[0-9]*=<channel description>\n" \ -+" Attach a console or serial line to a host channel. See\n" \ -+" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \ -+" description of this switch.\n\n" \ -+); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/choose-mode.h um/arch/um/include/choose-mode.h ---- orig/arch/um/include/choose-mode.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/choose-mode.h Fri Jan 17 13:23:32 2003 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHOOSE_MODE_H__ -+#define __CHOOSE_MODE_H__ -+ -+#include "uml-config.h" -+ -+#if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS) -+#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas)) -+ -+#elif defined(UML_CONFIG_MODE_SKAS) -+#define CHOOSE_MODE(tt, skas) (skas) -+ -+#elif defined(UML_CONFIG_MODE_TT) -+#define CHOOSE_MODE(tt, skas) (tt) -+#endif -+ -+#define CHOOSE_MODE_PROC(tt, skas, args...) \ -+ CHOOSE_MODE(tt(args), skas(args)) -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/frame.h um/arch/um/include/frame.h ---- orig/arch/um/include/frame.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/frame.h Mon Dec 2 21:43:03 2002 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_H_ -+#define __FRAME_H_ -+ -+#include "sysdep/frame.h" -+ -+struct frame_common { -+ void *data; -+ int len; -+ int sig_index; -+ int sr_index; -+ int sr_relative; -+ int sp_index; -+ struct arch_frame_data arch; -+}; -+ -+struct sc_frame { -+ struct frame_common common; -+ int sc_index; -+}; -+ -+extern struct sc_frame signal_frame_sc; -+ -+extern struct sc_frame signal_frame_sc_sr; -+ -+struct si_frame { -+ struct frame_common common; -+ int sip_index; -+ int si_index; -+ int ucp_index; -+ int uc_index; -+}; -+ -+extern struct si_frame signal_frame_si; -+ -+extern void capture_signal_stack(void); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/frame_kern.h um/arch/um/include/frame_kern.h ---- orig/arch/um/include/frame_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/frame_kern.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_KERN_H_ -+#define __FRAME_KERN_H_ -+ -+#include "frame.h" -+#include "sysdep/frame_kern.h" -+ -+extern int setup_signal_stack_sc(unsigned long stack_top, int sig, -+ unsigned long handler, -+ void (*restorer)(void), -+ struct pt_regs *regs, -+ sigset_t *mask); -+extern int setup_signal_stack_si(unsigned long stack_top, int sig, -+ unsigned long handler, -+ void (*restorer)(void), -+ struct pt_regs *regs, siginfo_t *info, -+ sigset_t *mask); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/frame_user.h um/arch/um/include/frame_user.h ---- orig/arch/um/include/frame_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/frame_user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_USER_H_ -+#define __FRAME_USER_H_ -+ -+#include "sysdep/frame_user.h" -+#include "frame.h" -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/helper.h um/arch/um/include/helper.h ---- orig/arch/um/include/helper.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/helper.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __HELPER_H__ -+#define __HELPER_H__ -+ -+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, -+ unsigned long *stack_out); -+extern int run_helper_thread(int (*proc)(void *), void *arg, -+ unsigned int flags, unsigned long *stack_out, -+ int stack_order); -+extern int helper_wait(int pid); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/hostaudio.h um/arch/um/include/hostaudio.h ---- orig/arch/um/include/hostaudio.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/hostaudio.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Steve Schmidtke -+ * Licensed under the GPL -+ */ -+ -+#ifndef HOSTAUDIO_H -+#define HOSTAUDIO_H -+ -+#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" -+#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" -+ -+struct hostaudio_state { -+ int fd; -+}; -+ -+struct hostmixer_state { -+ int fd; -+}; -+ -+/* UML user-side protoypes */ -+extern ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer, -+ size_t count, loff_t *ppos); -+extern ssize_t hostaudio_write_user(struct hostaudio_state *state, -+ const char *buffer, size_t count, -+ loff_t *ppos); -+extern int hostaudio_ioctl_user(struct hostaudio_state *state, -+ unsigned int cmd, unsigned long arg); -+extern int hostaudio_open_user(struct hostaudio_state *state, int r, int w, -+ char *dsp); -+extern int hostaudio_release_user(struct hostaudio_state *state); -+extern int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state, -+ unsigned int cmd, unsigned long arg); -+extern int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, -+ int w, char *mixer); -+extern int hostmixer_release_mixdev_user(struct hostmixer_state *state); -+ -+#endif /* HOSTAUDIO_H */ -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/include/init.h um/arch/um/include/init.h ---- orig/arch/um/include/init.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/init.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,114 @@ -+#ifndef _LINUX_UML_INIT_H -+#define _LINUX_UML_INIT_H -+ -+/* These macros are used to mark some functions or -+ * initialized data (doesn't apply to uninitialized data) -+ * as `initialization' functions. The kernel can take this -+ * as hint that the function is used only during the initialization -+ * phase and free up used memory resources after -+ * -+ * Usage: -+ * For functions: -+ * -+ * You should add __init immediately before the function name, like: -+ * -+ * static void __init initme(int x, int y) -+ * { -+ * extern int z; z = x * y; -+ * } -+ * -+ * If the function has a prototype somewhere, you can also add -+ * __init between closing brace of the prototype and semicolon: -+ * -+ * extern int initialize_foobar_device(int, int, int) __init; -+ * -+ * For initialized data: -+ * You should insert __initdata between the variable name and equal -+ * sign followed by value, e.g.: -+ * -+ * static int init_variable __initdata = 0; -+ * static char linux_logo[] __initdata = { 0x32, 0x36, ... }; -+ * -+ * Don't forget to initialize data not at file scope, i.e. within a function, -+ * as gcc otherwise puts the data into the bss section and not into the init -+ * section. -+ * -+ * Also note, that this data cannot be "const". -+ */ -+ -+#ifndef _LINUX_INIT_H -+typedef int (*initcall_t)(void); -+typedef void (*exitcall_t)(void); -+ -+#define __init __attribute__ ((__section__ (".text.init"))) -+#define __exit __attribute__ ((unused, __section__(".text.exit"))) -+#define __initdata __attribute__ ((__section__ (".data.init"))) -+ -+#endif -+ -+#ifndef MODULE -+struct uml_param { -+ const char *str; -+ int (*setup_func)(char *, int *); -+}; -+ -+extern initcall_t __uml_initcall_start, __uml_initcall_end; -+extern initcall_t __uml_postsetup_start, __uml_postsetup_end; -+extern const char *__uml_help_start, *__uml_help_end; -+#endif -+ -+#define __uml_initcall(fn) \ -+ static initcall_t __uml_initcall_##fn __uml_init_call = fn -+ -+#define __uml_exitcall(fn) \ -+ static exitcall_t __uml_exitcall_##fn __uml_exit_call = fn -+ -+extern struct uml_param __uml_setup_start, __uml_setup_end; -+ -+#define __uml_postsetup(fn) \ -+ static initcall_t __uml_postsetup_##fn __uml_postsetup_call = fn -+ -+#define __non_empty_string(dummyname,string) \ -+ struct __uml_non_empty_string_struct_##dummyname \ -+ { \ -+ char _string[sizeof(string)-2]; \ -+ } -+ -+#ifndef MODULE -+#define __uml_setup(str, fn, help...) \ -+ __non_empty_string(fn ##_setup, str); \ -+ __uml_help(fn, help); \ -+ static char __uml_setup_str_##fn[] __initdata = str; \ -+ static struct uml_param __uml_setup_##fn __uml_init_setup = { __uml_setup_str_##fn, fn } -+#else -+#define __uml_setup(str, fn, help...) \ -+ -+#endif -+ -+#define __uml_help(fn, help...) \ -+ __non_empty_string(fn ##__help, help); \ -+ static char __uml_help_str_##fn[] __initdata = help; \ -+ static const char *__uml_help_##fn __uml_setup_help = __uml_help_str_##fn -+ -+/* -+ * Mark functions and data as being only used at initialization -+ * or exit time. -+ */ -+#define __uml_init_setup __attribute__ ((unused,__section__ (".uml.setup.init"))) -+#define __uml_setup_help __attribute__ ((unused,__section__ (".uml.help.init"))) -+#define __uml_init_call __attribute__ ((unused,__section__ (".uml.initcall.init"))) -+#define __uml_postsetup_call __attribute__ ((unused,__section__ (".uml.postsetup.init"))) -+#define __uml_exit_call __attribute__ ((unused,__section__ (".uml.exitcall.exit"))) -+ -+#endif /* _LINUX_UML_INIT_H */ -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/include/initrd.h um/arch/um/include/initrd.h ---- orig/arch/um/include/initrd.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/initrd.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __INITRD_USER_H__ -+#define __INITRD_USER_H__ -+ -+extern int load_initrd(char *filename, void *buf, int size); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/irq_user.h um/arch/um/include/irq_user.h ---- orig/arch/um/include/irq_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/irq_user.h Sun Dec 8 20:38:42 2002 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __IRQ_USER_H__ -+#define __IRQ_USER_H__ -+ -+enum { IRQ_READ, IRQ_WRITE }; -+ -+extern void sigio_handler(int sig, union uml_pt_regs *regs); -+extern int activate_fd(int irq, int fd, int type, void *dev_id); -+extern void free_irq_by_irq_and_dev(int irq, void *dev_id); -+extern void free_irq_by_fd(int fd); -+extern void reactivate_fd(int fd, int irqnum); -+extern void deactivate_fd(int fd, int irqnum); -+extern void forward_interrupts(int pid); -+extern void init_irq_signals(int on_sigstack); -+extern void forward_ipi(int fd, int pid); -+extern void free_irq_later(int irq, void *dev_id); -+extern int activate_ipi(int fd, int pid); -+extern unsigned long irq_lock(void); -+extern void irq_unlock(unsigned long flags); -+#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 -Naur -X ../exclude-files orig/arch/um/include/kern.h um/arch/um/include/kern.h ---- orig/arch/um/include/kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/kern.h Sat Nov 2 21:38:02 2002 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __KERN_H__ -+#define __KERN_H__ -+ -+/* These are all user-mode things which are convenient to call directly -+ * from kernel code and for which writing a wrapper is too much of a pain. -+ * The regular include files can't be included because this file is included -+ * only into kernel code, and user-space includes conflict with kernel -+ * includes. -+ */ -+ -+extern int errno; -+ -+extern int clone(int (*proc)(void *), void *sp, int flags, void *data); -+extern int sleep(int); -+extern int printf(char *fmt, ...); -+extern char *strerror(int errnum); -+extern char *ptsname(int __fd); -+extern int munmap(void *, int); -+extern void *sbrk(int increment); -+extern void *malloc(int size); -+extern void perror(char *err); -+extern int kill(int pid, int sig); -+extern int getuid(void); -+extern int pause(void); -+extern int write(int, const void *, int); -+extern int exit(int); -+extern int close(int); -+extern int read(unsigned int, char *, int); -+extern int pipe(int *); -+extern int sched_yield(void); -+extern int ptrace(int op, int pid, long addr, long data); -+#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 -Naur -X ../exclude-files orig/arch/um/include/kern_util.h um/arch/um/include/kern_util.h ---- orig/arch/um/include/kern_util.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/kern_util.h Wed Mar 26 13:25:36 2003 -@@ -0,0 +1,122 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __KERN_UTIL_H__ -+#define __KERN_UTIL_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int ncpus; -+extern char *linux_prog; -+extern char *gdb_init; -+extern int kmalloc_ok; -+extern int timer_irq_inited; -+extern int jail; -+extern int nsyscalls; -+ -+#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK)) -+#define UML_ROUND_UP(addr) \ -+ UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) -+ -+extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); -+extern unsigned long stack_sp(unsigned long page); -+extern int kernel_thread_proc(void *data); -+extern void syscall_segv(int sig); -+extern int current_pid(void); -+extern unsigned long alloc_stack(int order, int atomic); -+extern int do_signal(int error); -+extern int is_stack_fault(unsigned long sp); -+extern unsigned long segv(unsigned long address, unsigned long ip, -+ int is_write, int is_user, void *sc); -+extern unsigned long handle_page_fault(unsigned long address, unsigned long ip, -+ int is_write, int is_user, -+ int *code_out); -+extern void syscall_ready(void); -+extern int segv_syscall(void); -+extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); -+extern int page_size(void); -+extern int page_mask(void); -+extern int need_finish_fork(void); -+extern void free_stack(unsigned long stack, int order); -+extern void add_input_request(int op, void (*proc)(int), void *arg); -+extern int sys_execve(char *file, char **argv, char **env); -+extern char *current_cmd(void); -+extern void timer_handler(int sig, union uml_pt_regs *regs); -+extern int set_signals(int enable); -+extern void force_sigbus(void); -+extern int pid_to_processor_id(int pid); -+extern void block_signals(void); -+extern void unblock_signals(void); -+extern void deliver_signals(void *t); -+extern int next_syscall_index(int max); -+extern int next_trap_index(int max); -+extern void cpu_idle(void); -+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 int hz(void); -+extern void 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); -+extern int debugger_signal(int status, int pid); -+extern void debugger_parent_signal(int status, int pid); -+extern void child_signal(int pid, int status); -+extern int init_ptrace_proxy(int idle_pid, int startup, int stop); -+extern int init_parent_proxy(int pid); -+extern void check_stack_overflow(void *ptr); -+extern void relay_signal(int sig, union uml_pt_regs *regs); -+extern void not_implemented(void); -+extern int user_context(unsigned long sp); -+extern void timer_irq(union uml_pt_regs *regs); -+extern void unprotect_stack(unsigned long stack); -+extern void do_uml_exitcalls(void); -+extern int attach_debugger(int idle_pid, int pid, int stop); -+extern void bad_segv(unsigned long address, unsigned long ip, int is_write); -+extern int config_gdb(char *str); -+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); -+extern int jail_setup(char *line, int *add); -+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 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); -+extern struct task_struct *get_task(int pid, int require); -+extern void machine_halt(void); -+extern int is_syscall(unsigned long addr); -+extern void arch_switch(void); -+extern void free_irq(unsigned int, void *); -+extern int um_in_interrupt(void); -+extern int cpu(void); -+#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 -Naur -X ../exclude-files orig/arch/um/include/line.h um/arch/um/include/line.h ---- orig/arch/um/include/line.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/line.h Fri Nov 15 13:44:44 2002 -@@ -0,0 +1,106 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __LINE_H__ -+#define __LINE_H__ -+ -+#include "linux/list.h" -+#include "linux/tqueue.h" -+#include "linux/tty.h" -+#include "asm/semaphore.h" -+#include "chan_user.h" -+#include "mconsole_kern.h" -+ -+struct line_driver { -+ char *name; -+ char *devfs_name; -+ short major; -+ short minor_start; -+ short type; -+ short subtype; -+ int read_irq; -+ char *read_irq_name; -+ int write_irq; -+ char *write_irq_name; -+ char *symlink_from; -+ char *symlink_to; -+ struct mc_device mc; -+}; -+ -+struct line { -+ char *init_str; -+ int init_pri; -+ struct list_head chan_list; -+ int valid; -+ int count; -+ struct tty_struct *tty; -+ struct semaphore sem; -+ char *buffer; -+ char *head; -+ char *tail; -+ int sigio; -+ struct tq_struct task; -+ struct line_driver *driver; -+ int have_irq; -+}; -+ -+#define LINE_INIT(str, d) \ -+ { init_str : str, \ -+ init_pri : INIT_STATIC, \ -+ chan_list : { }, \ -+ valid : 1, \ -+ count : 0, \ -+ tty : NULL, \ -+ sem : { }, \ -+ buffer : NULL, \ -+ head : NULL, \ -+ tail : NULL, \ -+ sigio : 0, \ -+ driver : d, \ -+ have_irq : 0 } -+ -+struct lines { -+ int num; -+}; -+ -+#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); -+extern int line_setup(struct line *lines, int num, char *init, -+ int all_allowed); -+extern int line_write(struct line *line, struct tty_struct *tty, int from_user, -+ const char *buf, int len); -+extern int line_write_room(struct tty_struct *tty); -+extern char *add_xterm_umid(char *base); -+extern int line_setup_irq(int fd, int input, int output, void *data); -+extern void line_close_chan(struct line *line); -+extern void line_disable(struct line *line, int current_irq); -+extern void line_register_devfs(struct lines *set, -+ struct line_driver *line_driver, -+ struct tty_driver *driver, struct line *lines, -+ int nlines); -+extern void lines_init(struct line *lines, int nlines); -+extern void close_lines(struct line *lines, int nlines); -+extern int line_config(struct line *lines, int num, char *str); -+extern int line_remove(struct line *lines, int num, char *str); -+extern int line_get_config(char *dev, struct line *lines, int num, char *str, -+ int size, char **error_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 -Naur -X ../exclude-files orig/arch/um/include/mconsole.h um/arch/um/include/mconsole.h ---- orig/arch/um/include/mconsole.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/mconsole.h Fri Jan 17 13:48:25 2003 -@@ -0,0 +1,99 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MCONSOLE_H__ -+#define __MCONSOLE_H__ -+ -+#ifndef __KERNEL__ -+#include <stdint.h> -+#define u32 uint32_t -+#endif -+ -+#define MCONSOLE_MAGIC (0xcafebabe) -+#define MCONSOLE_MAX_DATA (512) -+#define MCONSOLE_VERSION 2 -+ -+struct mconsole_request { -+ u32 magic; -+ u32 version; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mconsole_reply { -+ u32 err; -+ u32 more; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mconsole_notify { -+ u32 magic; -+ u32 version; -+ enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, -+ MCONSOLE_USER_NOTIFY } type; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mc_request; -+ -+struct mconsole_command -+{ -+ char *command; -+ void (*handler)(struct mc_request *req); -+ int as_interrupt; -+}; -+ -+struct mc_request -+{ -+ int len; -+ int as_interrupt; -+ -+ int originating_fd; -+ int originlen; -+ unsigned char origin[128]; /* sockaddr_un */ -+ -+ struct mconsole_request request; -+ struct mconsole_command *cmd; -+}; -+ -+extern char mconsole_socket_name[]; -+ -+extern int mconsole_unlink_socket(void); -+extern int mconsole_reply(struct mc_request *req, char *reply, int err, -+ int more); -+ -+extern void mconsole_version(struct mc_request *req); -+extern void mconsole_help(struct mc_request *req); -+extern void mconsole_halt(struct mc_request *req); -+extern void mconsole_reboot(struct mc_request *req); -+extern void mconsole_config(struct mc_request *req); -+extern void mconsole_remove(struct mc_request *req); -+extern void mconsole_sysrq(struct mc_request *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 int mconsole_get_request(int fd, struct mc_request *req); -+extern int mconsole_notify(char *sock_name, int type, const void *data, -+ int len); -+extern char *mconsole_notify_socket(void); -+extern void lock_notify(void); -+extern void unlock_notify(void); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/mconsole_kern.h um/arch/um/include/mconsole_kern.h ---- orig/arch/um/include/mconsole_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/mconsole_kern.h Fri Nov 15 15:21:58 2002 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MCONSOLE_KERN_H__ -+#define __MCONSOLE_KERN_H__ -+ -+#include "linux/config.h" -+#include "linux/list.h" -+#include "mconsole.h" -+ -+struct mconsole_entry { -+ struct list_head list; -+ struct mc_request request; -+}; -+ -+struct mc_device { -+ struct list_head list; -+ char *name; -+ int (*config)(char *); -+ int (*get_config)(char *, char *, int, char **); -+ int (*remove)(char *); -+}; -+ -+#define CONFIG_CHUNK(str, size, current, chunk, end) \ -+do { \ -+ current += strlen(chunk); \ -+ if(current >= size) \ -+ str = NULL; \ -+ if(str != NULL){ \ -+ strcpy(str, chunk); \ -+ str += strlen(chunk); \ -+ } \ -+ if(end) \ -+ current++; \ -+} while(0) -+ -+#ifdef CONFIG_MCONSOLE -+ -+extern void mconsole_register_dev(struct mc_device *new); -+ -+#else -+ -+static inline void mconsole_register_dev(struct mc_device *new) -+{ -+} -+ -+#endif -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/mem.h um/arch/um/include/mem.h ---- orig/arch/um/include/mem.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/mem.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MEM_H__ -+#define __MEM_H__ -+ -+struct vm_reserved { -+ struct list_head list; -+ unsigned long start; -+ unsigned long end; -+}; -+ -+extern void set_usable_vm(unsigned long start, unsigned long end); -+extern void set_kmem_end(unsigned long new); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/mem_user.h um/arch/um/include/mem_user.h ---- orig/arch/um/include/mem_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/mem_user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,87 @@ -+/* -+ * arch/um/include/mem_user.h -+ * -+ * BRIEF MODULE DESCRIPTION -+ * user side memory interface for support IO memory inside user mode linux -+ * -+ * Copyright (C) 2001 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef _MEM_USER_H -+#define _MEM_USER_H -+ -+struct mem_region { -+ char *driver; -+ unsigned long start_pfn; -+ unsigned long start; -+ unsigned long len; -+ void *mem_map; -+ int fd; -+}; -+ -+extern struct mem_region *regions[]; -+extern struct mem_region physmem_region; -+ -+#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) -+ -+extern unsigned long host_task_size; -+extern unsigned long task_size; -+ -+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 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); -+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 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); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/mode.h um/arch/um/include/mode.h ---- orig/arch/um/include/mode.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/mode.h Fri Jan 17 13:23:32 2003 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_H__ -+#define __MODE_H__ -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "../kernel/tt/include/mode.h" -+#endif -+ -+#ifdef UML_CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mode.h" -+#endif -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/mode_kern.h um/arch/um/include/mode_kern.h ---- orig/arch/um/include/mode_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/mode_kern.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_KERN_H__ -+#define __MODE_KERN_H__ -+ -+#include "linux/config.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/mode_kern.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mode_kern.h" -+#endif -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/net_kern.h um/arch/um/include/net_kern.h ---- orig/arch/um/include/net_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/net_kern.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,81 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_NET_KERN_H -+#define __UM_NET_KERN_H -+ -+#include "linux/netdevice.h" -+#include "linux/skbuff.h" -+#include "linux/socket.h" -+#include "linux/list.h" -+ -+struct uml_net { -+ struct list_head list; -+ struct net_device *dev; -+ int index; -+ unsigned char mac[ETH_ALEN]; -+ int have_mac; -+}; -+ -+struct uml_net_private { -+ struct list_head list; -+ spinlock_t lock; -+ struct net_device *dev; -+ struct timer_list tl; -+ struct net_device_stats stats; -+ int fd; -+ unsigned char mac[ETH_ALEN]; -+ int have_mac; -+ unsigned short (*protocol)(struct sk_buff *); -+ int (*open)(void *); -+ void (*close)(int, void *); -+ void (*remove)(void *); -+ int (*read)(int, struct sk_buff **skb, struct uml_net_private *); -+ int (*write)(int, struct sk_buff **skb, struct uml_net_private *); -+ -+ void (*add_address)(unsigned char *, unsigned char *, void *); -+ void (*delete_address)(unsigned char *, unsigned char *, void *); -+ int (*set_mtu)(int mtu, void *); -+ int user[1]; -+}; -+ -+struct net_kern_info { -+ void (*init)(struct net_device *, void *); -+ unsigned short (*protocol)(struct sk_buff *); -+ int (*read)(int, struct sk_buff **skb, struct uml_net_private *); -+ int (*write)(int, struct sk_buff **skb, struct uml_net_private *); -+}; -+ -+struct transport { -+ struct list_head list; -+ char *name; -+ int (*setup)(char *, char **, void *); -+ struct net_user_info *user; -+ struct net_kern_info *kern; -+ int private_size; -+ int setup_size; -+}; -+ -+extern struct net_device *ether_init(int); -+extern unsigned short ether_protocol(struct sk_buff *); -+extern int setup_etheraddr(char *str, unsigned char *addr); -+extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); -+extern int tap_setup_common(char *str, char *type, char **dev_name, -+ char **mac_out, char **gate_addr); -+extern void register_transport(struct transport *new); -+extern unsigned short eth_protocol(struct sk_buff *skb); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/net_user.h um/arch/um/include/net_user.h ---- orig/arch/um/include/net_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/net_user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_NET_USER_H__ -+#define __UM_NET_USER_H__ -+ -+#define ETH_ADDR_LEN (6) -+#define ETH_HEADER_ETHERTAP (16) -+#define ETH_HEADER_OTHER (14) -+#define ETH_MAX_PACKET (1500) -+ -+#define UML_NET_VERSION (4) -+ -+struct net_user_info { -+ void (*init)(void *, void *); -+ int (*open)(void *); -+ void (*close)(int, void *); -+ void (*remove)(void *); -+ int (*set_mtu)(int mtu, void *); -+ void (*add_address)(unsigned char *, unsigned char *, void *); -+ void (*delete_address)(unsigned char *, unsigned char *, void *); -+ int max_packet; -+}; -+ -+extern void ether_user_init(void *data, void *dev); -+extern void dev_ip_addr(void *d, char *buf, char *bin_buf); -+extern void set_ether_mac(void *d, unsigned char *addr); -+extern void iter_addresses(void *d, void (*cb)(unsigned char *, -+ unsigned char *, void *), -+ void *arg); -+ -+extern void *get_output_buffer(int *len_out); -+extern void free_output_buffer(void *buffer); -+ -+extern int tap_open_common(void *dev, char *gate_addr); -+extern void tap_check_ips(char *gate_addr, char *eth_addr); -+ -+extern void read_output(int fd, char *output_out, int len); -+ -+extern int net_read(int fd, void *buf, int len); -+extern int net_recvfrom(int fd, void *buf, int len); -+extern int net_write(int fd, void *buf, int len); -+extern int net_send(int fd, void *buf, int len); -+extern int net_sendto(int fd, void *buf, int len, void *to, int sock_len); -+ -+extern void open_addr(unsigned char *addr, unsigned char *netmask, void *arg); -+extern void close_addr(unsigned char *addr, unsigned char *netmask, void *arg); -+ -+extern char *split_if_spec(char *str, ...); -+ -+extern int dev_netmask(void *d, void *m); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/os.h um/arch/um/include/os.h ---- orig/arch/um/include/os.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/os.h Tue Feb 4 19:11:32 2003 -@@ -0,0 +1,137 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __OS_H__ -+#define __OS_H__ -+ -+#include "asm/types.h" -+#include "../os/include/file.h" -+ -+#define OS_TYPE_FILE 1 -+#define OS_TYPE_DIR 2 -+#define OS_TYPE_SYMLINK 3 -+#define OS_TYPE_CHARDEV 4 -+#define OS_TYPE_BLOCKDEV 5 -+#define OS_TYPE_FIFO 6 -+#define OS_TYPE_SOCK 7 -+ -+struct openflags { -+ unsigned int r : 1; -+ unsigned int w : 1; -+ unsigned int s : 1; /* O_SYNC */ -+ unsigned int c : 1; /* O_CREAT */ -+ unsigned int t : 1; /* O_TRUNC */ -+ unsigned int a : 1; /* O_APPEND */ -+ unsigned int e : 1; /* O_EXCL */ -+ unsigned int cl : 1; /* FD_CLOEXEC */ -+}; -+ -+#define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \ -+ .t = 0, .a = 0, .e = 0, .cl = 0 }) -+ -+static inline struct openflags of_read(struct openflags flags) -+{ -+ flags.r = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_write(struct openflags flags) -+{ -+ flags.w = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_rdwr(struct openflags flags) -+{ -+ return(of_read(of_write(flags))); -+} -+ -+static inline struct openflags of_set_rw(struct openflags flags, int r, int w) -+{ -+ flags.r = r; -+ flags.w = w; -+ return(flags); -+} -+ -+static inline struct openflags of_sync(struct openflags flags) -+{ -+ flags.s = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_create(struct openflags flags) -+{ -+ flags.c = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_trunc(struct openflags flags) -+{ -+ flags.t = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_append(struct openflags flags) -+{ -+ flags.a = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_excl(struct openflags flags) -+{ -+ flags.e = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_cloexec(struct openflags flags) -+{ -+ flags.cl = 1; -+ return(flags); -+} -+ -+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_file_size(char *file, long long *size_out); -+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_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 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); -+extern void os_stop_process(int pid); -+extern void os_kill_process(int pid, int reap_child); -+extern void os_usr1_process(int pid); -+extern int os_getpid(void); -+ -+extern int os_map_memory(void *virt, int fd, unsigned 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 -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/include/process.h um/arch/um/include/process.h ---- orig/arch/um/include/process.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/process.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PROCESS_H__ -+#define __PROCESS_H__ -+ -+#include <asm/sigcontext.h> -+ -+extern void sig_handler(int sig, struct sigcontext sc); -+extern void alarm_handler(int sig, struct sigcontext sc); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/ptrace_user.h um/arch/um/include/ptrace_user.h ---- orig/arch/um/include/ptrace_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/ptrace_user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,18 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_USER_H__ -+#define __PTRACE_USER_H__ -+ -+#include "sysdep/ptrace_user.h" -+ -+extern int ptrace_getregs(long pid, unsigned long *regs_out); -+extern int ptrace_setregs(long pid, unsigned long *regs_in); -+extern int ptrace_getfpregs(long pid, unsigned long *regs_out); -+extern void arch_enter_kernel(void *task, int pid); -+extern void arch_leave_kernel(void *task, int pid); -+extern void ptrace_pokeuser(unsigned long addr, unsigned long data); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/include/sigcontext.h um/arch/um/include/sigcontext.h ---- orig/arch/um/include/sigcontext.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sigcontext.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UML_SIGCONTEXT_H__ -+#define __UML_SIGCONTEXT_H__ -+ -+#include "sysdep/sigcontext.h" -+ -+extern int sc_size(void *data); -+extern void sc_to_sc(void *to_ptr, void *from_ptr); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sigio.h um/arch/um/include/sigio.h ---- orig/arch/um/include/sigio.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sigio.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGIO_H__ -+#define __SIGIO_H__ -+ -+extern int write_sigio_irq(int fd); -+extern int register_sigio_fd(int fd); -+extern int read_sigio_fd(int fd); -+extern int add_sigio_fd(int fd, int read); -+extern int ignore_sigio_fd(int fd); -+extern void sigio_lock(void); -+extern void sigio_unlock(void); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/signal_kern.h um/arch/um/include/signal_kern.h ---- orig/arch/um/include/signal_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/signal_kern.h Thu Dec 5 18:08:47 2002 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGNAL_KERN_H__ -+#define __SIGNAL_KERN_H__ -+ -+extern int have_signals(void *t); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/signal_user.h um/arch/um/include/signal_user.h ---- orig/arch/um/include/signal_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/signal_user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGNAL_USER_H__ -+#define __SIGNAL_USER_H__ -+ -+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, ...); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/skas_ptrace.h um/arch/um/include/skas_ptrace.h ---- orig/arch/um/include/skas_ptrace.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/skas_ptrace.h Mon Dec 16 11:54:52 2002 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_PTRACE_H -+#define __SKAS_PTRACE_H -+ -+struct ptrace_faultinfo { -+ int is_write; -+ unsigned long addr; -+}; -+ -+struct ptrace_ldt { -+ int func; -+ void *ptr; -+ unsigned long bytecount; -+}; -+ -+#define PTRACE_FAULTINFO 52 -+#define PTRACE_SIGPENDING 53 -+#define PTRACE_LDT 54 -+#define PTRACE_SWITCH_MM 55 -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/syscall_user.h um/arch/um/include/syscall_user.h ---- orig/arch/um/include/syscall_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/syscall_user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSCALL_USER_H -+#define __SYSCALL_USER_H -+ -+extern int record_syscall_start(int syscall); -+extern void record_syscall_end(int index, int result); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/checksum.h um/arch/um/include/sysdep-i386/checksum.h ---- orig/arch/um/include/sysdep-i386/checksum.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-i386/checksum.h Tue Oct 29 21:23:02 2002 -@@ -0,0 +1,217 @@ -+/* -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SYSDEP_CHECKSUM_H -+#define __UM_SYSDEP_CHECKSUM_H -+ -+#include "linux/string.h" -+ -+/* -+ * computes the checksum of a memory block at buff, length len, -+ * and adds in "sum" (32-bit) -+ * -+ * returns a 32-bit number suitable for feeding into itself -+ * or csum_tcpudp_magic -+ * -+ * this function must be called with even lengths, except -+ * for the last fragment, which may be odd -+ * -+ * it's best to have buff aligned on a 32-bit boundary -+ */ -+unsigned int csum_partial(const unsigned char * buff, int len, -+ unsigned int sum); -+ -+/* -+ * the same as csum_partial, but copies from src while it -+ * checksums, and handles user-space pointer exceptions correctly, when needed. -+ * -+ * here even more important to align src and dst on a 32-bit (or even -+ * better 64-bit) boundary -+ */ -+ -+unsigned int csum_partial_copy_to(const char *src, char *dst, int len, -+ int sum, int *err_ptr); -+unsigned int csum_partial_copy_from(const char *src, char *dst, int len, -+ int sum, int *err_ptr); -+ -+/* -+ * Note: when you get a NULL pointer exception here this means someone -+ * passed in an incorrect kernel address to one of these functions. -+ * -+ * If you use these functions directly please don't forget the -+ * verify_area(). -+ */ -+ -+static __inline__ -+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, -+ int len, int sum) -+{ -+ memcpy(dst, src, len); -+ return(csum_partial(dst, len, sum)); -+} -+ -+static __inline__ -+unsigned int csum_partial_copy_from_user(const char *src, char *dst, -+ int len, int sum, int *err_ptr) -+{ -+ return csum_partial_copy_from(src, dst, len, sum, err_ptr); -+} -+ -+/* -+ * These are the old (and unsafe) way of doing checksums, a warning message -+ * will be printed if they are used and an exeption occurs. -+ * -+ * these functions should go away after some time. -+ */ -+ -+#define csum_partial_copy_fromuser csum_partial_copy_from_user -+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum); -+ -+/* -+ * This is a version of ip_compute_csum() optimized for IP headers, -+ * which always checksum on 4 octet boundaries. -+ * -+ * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by -+ * Arnt Gulbrandsen. -+ */ -+static inline unsigned short ip_fast_csum(unsigned char * iph, -+ unsigned int ihl) -+{ -+ unsigned int sum; -+ -+ __asm__ __volatile__( -+ "movl (%1), %0 ;\n" -+ "subl $4, %2 ;\n" -+ "jbe 2f ;\n" -+ "addl 4(%1), %0 ;\n" -+ "adcl 8(%1), %0 ;\n" -+ "adcl 12(%1), %0 ;\n" -+"1: adcl 16(%1), %0 ;\n" -+ "lea 4(%1), %1 ;\n" -+ "decl %2 ;\n" -+ "jne 1b ;\n" -+ "adcl $0, %0 ;\n" -+ "movl %0, %2 ;\n" -+ "shrl $16, %0 ;\n" -+ "addw %w2, %w0 ;\n" -+ "adcl $0, %0 ;\n" -+ "notl %0 ;\n" -+"2: ;\n" -+ /* Since the input registers which are loaded with iph and ipl -+ are modified, we must also specify them as outputs, or gcc -+ will assume they contain their original values. */ -+ : "=r" (sum), "=r" (iph), "=r" (ihl) -+ : "1" (iph), "2" (ihl)); -+ return(sum); -+} -+ -+/* -+ * Fold a partial checksum -+ */ -+ -+static inline unsigned int csum_fold(unsigned int sum) -+{ -+ __asm__( -+ "addl %1, %0 ;\n" -+ "adcl $0xffff, %0 ;\n" -+ : "=r" (sum) -+ : "r" (sum << 16), "0" (sum & 0xffff0000) -+ ); -+ return (~sum) >> 16; -+} -+ -+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, -+ unsigned long daddr, -+ unsigned short len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ __asm__( -+ "addl %1, %0 ;\n" -+ "adcl %2, %0 ;\n" -+ "adcl %3, %0 ;\n" -+ "adcl $0, %0 ;\n" -+ : "=r" (sum) -+ : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum)); -+ return sum; -+} -+ -+/* -+ * computes the checksum of the TCP/UDP pseudo-header -+ * returns a 16-bit checksum, already complemented -+ */ -+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, -+ unsigned long daddr, -+ unsigned short len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); -+} -+ -+/* -+ * this routine is used for miscellaneous IP-like checksums, mainly -+ * in icmp.c -+ */ -+ -+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) -+{ -+ return csum_fold (csum_partial(buff, len, 0)); -+} -+ -+#define _HAVE_ARCH_IPV6_CSUM -+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr, -+ struct in6_addr *daddr, -+ __u32 len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ __asm__( -+ "addl 0(%1), %0 ;\n" -+ "adcl 4(%1), %0 ;\n" -+ "adcl 8(%1), %0 ;\n" -+ "adcl 12(%1), %0 ;\n" -+ "adcl 0(%2), %0 ;\n" -+ "adcl 4(%2), %0 ;\n" -+ "adcl 8(%2), %0 ;\n" -+ "adcl 12(%2), %0 ;\n" -+ "adcl %3, %0 ;\n" -+ "adcl %4, %0 ;\n" -+ "adcl $0, %0 ;\n" -+ : "=&r" (sum) -+ : "r" (saddr), "r" (daddr), -+ "r"(htonl(len)), "r"(htonl(proto)), "0"(sum)); -+ -+ return csum_fold(sum); -+} -+ -+/* -+ * Copy and checksum to user -+ */ -+#define HAVE_CSUM_COPY_USER -+static __inline__ unsigned int csum_and_copy_to_user(const char *src, -+ char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if (access_ok(VERIFY_WRITE, dst, len)) -+ return(csum_partial_copy_to(src, dst, len, sum, err_ptr)); -+ -+ if (len) -+ *err_ptr = -EFAULT; -+ -+ return -1; /* invalid checksum */ -+} -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame.h um/arch/um/include/sysdep-i386/frame.h ---- orig/arch/um/include/sysdep-i386/frame.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-i386/frame.h Fri Dec 6 14:07:54 2002 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_I386_H -+#define __FRAME_I386_H -+ -+struct arch_frame_data_raw { -+ unsigned long fp_start; -+ unsigned long sr; -+}; -+ -+struct arch_frame_data { -+ int fpstate_size; -+}; -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame_kern.h um/arch/um/include/sysdep-i386/frame_kern.h ---- orig/arch/um/include/sysdep-i386/frame_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-i386/frame_kern.h Mon Dec 2 21:45:04 2002 -@@ -0,0 +1,69 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_KERN_I386_H -+#define __FRAME_KERN_I386_H -+ -+/* This is called from sys_sigreturn. It takes the sp at the point of the -+ * sigreturn system call and returns the address of the sigcontext struct -+ * on the stack. -+ */ -+ -+static inline void *sp_to_sc(unsigned long sp) -+{ -+ return((void *) sp); -+} -+ -+static inline void *sp_to_uc(unsigned long sp) -+{ -+ unsigned long uc; -+ -+ uc = sp + signal_frame_si.uc_index - -+ signal_frame_si.common.sp_index - 4; -+ return((void *) uc); -+} -+ -+static inline void *sp_to_rt_sc(unsigned long sp) -+{ -+ unsigned long sc; -+ -+ sc = sp - signal_frame_si.common.sp_index + -+ signal_frame_si.common.len - 4; -+ return((void *) sc); -+} -+ -+static inline void *sp_to_mask(unsigned long sp) -+{ -+ unsigned long mask; -+ -+ mask = sp - signal_frame_sc.common.sp_index + -+ signal_frame_sc.common.len - 8; -+ return((void *) mask); -+} -+ -+extern int sc_size(void *data); -+ -+static inline void *sp_to_rt_mask(unsigned long sp) -+{ -+ unsigned long mask; -+ -+ mask = sp - signal_frame_si.common.sp_index + -+ signal_frame_si.common.len + -+ sc_size(&signal_frame_si.common.arch) - 4; -+ return((void *) mask); -+} -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame_user.h um/arch/um/include/sysdep-i386/frame_user.h ---- orig/arch/um/include/sysdep-i386/frame_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-i386/frame_user.h Fri Dec 6 14:13:59 2002 -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_USER_I386_H -+#define __FRAME_USER_I386_H -+ -+#include <asm/page.h> -+#include "sysdep/frame.h" -+ -+/* This stuff is to calculate the size of the fp state struct at runtime -+ * because it has changed between 2.2 and 2.4 and it would be good for a -+ * UML compiled on one to work on the other. -+ * So, setup_arch_frame_raw fills in the arch struct with the raw data, which -+ * just contains the address of the end of the sigcontext. This is invoked -+ * from the signal handler. -+ * setup_arch_frame uses that data to figure out what -+ * arch_frame_data.fpstate_size should be. It really has no idea, since it's -+ * not allowed to do sizeof(struct fpstate) but it's safe to consider that it's -+ * everything from the end of the sigcontext up to the top of the stack. So, -+ * it masks off the page number to get the offset within the page and subtracts -+ * that from the page size, and that's how big the fpstate struct will be -+ * considered to be. -+ */ -+ -+static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data, -+ void *end, unsigned long srp) -+{ -+ unsigned long sr = *((unsigned long *) srp); -+ -+ data->fp_start = (unsigned long) end; -+ if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK)) -+ data->sr = sr; -+ else data->sr = 0; -+} -+ -+static inline void setup_arch_frame(struct arch_frame_data_raw *in, -+ struct arch_frame_data *out) -+{ -+ unsigned long fpstate_start = in->fp_start; -+ -+ if(in->sr == 0){ -+ fpstate_start &= ~PAGE_MASK; -+ out->fpstate_size = PAGE_SIZE - fpstate_start; -+ } -+ else { -+ out->fpstate_size = in->sr - fpstate_start; -+ } -+} -+ -+/* This figures out where on the stack the SA_RESTORER function address -+ * is stored. For i386, it's the signal handler return address, so it's -+ * located next to the frame pointer. -+ * This is inlined, so __builtin_frame_address(0) is correct. Otherwise, -+ * 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)); -+} -+ -+/* 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)); -+} -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/ptrace.h um/arch/um/include/sysdep-i386/ptrace.h ---- orig/arch/um/include/sysdep-i386/ptrace.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-i386/ptrace.h Fri Jan 17 13:23:31 2003 -@@ -0,0 +1,193 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_I386_PTRACE_H -+#define __SYSDEP_I386_PTRACE_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "ptrace-tt.h" -+#endif -+ -+#ifdef UML_CONFIG_MODE_SKAS -+#include "ptrace-skas.h" -+#endif -+ -+#include "choose-mode.h" -+ -+union uml_pt_regs { -+#ifdef UML_CONFIG_MODE_TT -+ struct tt_regs { -+ long syscall; -+ void *sc; -+ } tt; -+#endif -+#ifdef UML_CONFIG_MODE_SKAS -+ struct skas_regs { -+ unsigned long regs[HOST_FRAME_SIZE]; -+ unsigned long fp[HOST_FP_SIZE]; -+ unsigned long xfp[HOST_XFP_SIZE]; -+ unsigned long fault_addr; -+ unsigned long fault_type; -+ unsigned long trap_type; -+ long syscall; -+ int is_user; -+ } skas; -+#endif -+}; -+ -+#define EMPTY_UML_PT_REGS { } -+ -+extern int mode_tt; -+ -+#define UPT_SC(r) ((r)->tt.sc) -+#define UPT_IP(r) \ -+ CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) -+#define UPT_SP(r) \ -+ CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) -+#define UPT_EFLAGS(r) \ -+ CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) -+#define UPT_EAX(r) \ -+ CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs)) -+#define UPT_EBX(r) \ -+ CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs)) -+#define UPT_ECX(r) \ -+ CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs)) -+#define UPT_EDX(r) \ -+ CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs)) -+#define UPT_ESI(r) \ -+ CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs)) -+#define UPT_EDI(r) \ -+ CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs)) -+#define UPT_EBP(r) \ -+ CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs)) -+#define UPT_ORIG_EAX(r) \ -+ CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) -+#define UPT_CS(r) \ -+ CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) -+#define UPT_SS(r) \ -+ CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) -+#define UPT_DS(r) \ -+ CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) -+#define UPT_ES(r) \ -+ CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) -+#define UPT_FS(r) \ -+ CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) -+#define UPT_GS(r) \ -+ CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) -+ -+#define UPT_SYSCALL_ARG1(r) UPT_EBX(r) -+#define UPT_SYSCALL_ARG2(r) UPT_ECX(r) -+#define UPT_SYSCALL_ARG3(r) UPT_EDX(r) -+#define UPT_SYSCALL_ARG4(r) UPT_ESI(r) -+#define UPT_SYSCALL_ARG5(r) UPT_EDI(r) -+#define UPT_SYSCALL_ARG6(r) UPT_EBP(r) -+ -+extern int user_context(unsigned long sp); -+ -+#define UPT_IS_USER(r) \ -+ CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) -+ -+struct syscall_args { -+ unsigned long args[6]; -+}; -+ -+#define SYSCALL_ARGS(r) ((struct syscall_args) \ -+ { .args = { UPT_SYSCALL_ARG1(r), \ -+ UPT_SYSCALL_ARG2(r), \ -+ UPT_SYSCALL_ARG3(r), \ -+ UPT_SYSCALL_ARG4(r), \ -+ UPT_SYSCALL_ARG5(r), \ -+ UPT_SYSCALL_ARG6(r) } } ) -+ -+#define UPT_REG(regs, reg) \ -+ ({ unsigned long val; \ -+ switch(reg){ \ -+ case EIP: val = UPT_IP(regs); break; \ -+ case UESP: val = UPT_SP(regs); break; \ -+ case EAX: val = UPT_EAX(regs); break; \ -+ case EBX: val = UPT_EBX(regs); break; \ -+ case ECX: val = UPT_ECX(regs); break; \ -+ case EDX: val = UPT_EDX(regs); break; \ -+ case ESI: val = UPT_ESI(regs); break; \ -+ case EDI: val = UPT_EDI(regs); break; \ -+ case EBP: val = UPT_EBP(regs); break; \ -+ case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \ -+ case CS: val = UPT_CS(regs); break; \ -+ case SS: val = UPT_SS(regs); break; \ -+ case DS: val = UPT_DS(regs); break; \ -+ case ES: val = UPT_ES(regs); break; \ -+ case FS: val = UPT_FS(regs); break; \ -+ case GS: val = UPT_GS(regs); break; \ -+ case EFL: val = UPT_EFLAGS(regs); break; \ -+ default : \ -+ panic("Bad register in UPT_REG : %d\n", reg); \ -+ val = -1; \ -+ } \ -+ val; \ -+ }) -+ -+ -+#define UPT_SET(regs, reg, val) \ -+ do { \ -+ switch(reg){ \ -+ case EIP: UPT_IP(regs) = val; break; \ -+ case UESP: UPT_SP(regs) = val; break; \ -+ case EAX: UPT_EAX(regs) = val; break; \ -+ case EBX: UPT_EBX(regs) = val; break; \ -+ case ECX: UPT_ECX(regs) = val; break; \ -+ case EDX: UPT_EDX(regs) = val; break; \ -+ case ESI: UPT_ESI(regs) = val; break; \ -+ case EDI: UPT_EDI(regs) = val; break; \ -+ case EBP: UPT_EBP(regs) = val; break; \ -+ case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \ -+ case CS: UPT_CS(regs) = val; break; \ -+ case SS: UPT_SS(regs) = val; break; \ -+ case DS: UPT_DS(regs) = val; break; \ -+ case ES: UPT_ES(regs) = val; break; \ -+ case FS: UPT_FS(regs) = val; break; \ -+ case GS: UPT_GS(regs) = val; break; \ -+ case EFL: UPT_EFLAGS(regs) = val; break; \ -+ default : \ -+ panic("Bad register in UPT_SET : %d\n", reg); \ -+ break; \ -+ } \ -+ } while (0) -+ -+#define UPT_SET_SYSCALL_RETURN(r, res) \ -+ CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ -+ REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) -+ -+#define UPT_RESTART_SYSCALL(r) \ -+ CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ -+ REGS_RESTART_SYSCALL((r)->skas.regs)) -+ -+#define UPT_ORIG_SYSCALL(r) UPT_EAX(r) -+#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) -+#define UPT_SYSCALL_RET(r) UPT_EAX(r) -+ -+#define UPT_SEGV_IS_FIXABLE(r) \ -+ CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ -+ REGS_SEGV_IS_FIXABLE(&r->skas)) -+ -+#define UPT_FAULT_ADDR(r) \ -+ CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas)) -+ -+#define UPT_FAULT_WRITE(r) \ -+ CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas)) -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/ptrace_user.h um/arch/um/include/sysdep-i386/ptrace_user.h ---- orig/arch/um/include/sysdep-i386/ptrace_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-i386/ptrace_user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_I386_PTRACE_USER_H__ -+#define __SYSDEP_I386_PTRACE_USER_H__ -+ -+#include <asm/ptrace.h> -+ -+#define PT_OFFSET(r) ((r) * sizeof(long)) -+ -+#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX]) -+#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX) -+ -+#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX) -+#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX) -+#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX) -+#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI) -+#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI) -+ -+#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX) -+ -+#define PT_IP_OFFSET PT_OFFSET(EIP) -+#define PT_IP(regs) ((regs)[EIP]) -+#define PT_SP(regs) ((regs)[UESP]) -+ -+#ifndef FRAME_SIZE -+#define FRAME_SIZE (17) -+#endif -+#define FRAME_SIZE_OFFSET (FRAME_SIZE * sizeof(unsigned long)) -+ -+#define FP_FRAME_SIZE (27) -+#define FPX_FRAME_SIZE (128) -+ -+#ifdef PTRACE_GETREGS -+#define UM_HAVE_GETREGS -+#endif -+ -+#ifdef PTRACE_SETREGS -+#define UM_HAVE_SETREGS -+#endif -+ -+#ifdef PTRACE_GETFPREGS -+#define UM_HAVE_GETFPREGS -+#endif -+ -+#ifdef PTRACE_SETFPREGS -+#define UM_HAVE_SETFPREGS -+#endif -+ -+#ifdef PTRACE_GETFPXREGS -+#define UM_HAVE_GETFPXREGS -+#endif -+ -+#ifdef PTRACE_SETFPXREGS -+#define UM_HAVE_SETFPXREGS -+#endif -+ -+extern void update_debugregs(int seq); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/sigcontext.h um/arch/um/include/sysdep-i386/sigcontext.h ---- orig/arch/um/include/sysdep-i386/sigcontext.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-i386/sigcontext.h Sun Dec 8 18:21:33 2002 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_SIGCONTEXT_I386_H -+#define __SYS_SIGCONTEXT_I386_H -+ -+#include "sc.h" -+ -+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2) -+ -+#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) -+#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result) -+ -+#define SC_FAULT_ADDR(sc) SC_CR2(sc) -+#define SC_FAULT_TYPE(sc) SC_ERR(sc) -+ -+#define FAULT_WRITE(err) (err & 2) -+#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0) -+ -+#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc))) -+ -+#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc) -+ -+/* ptrace expects that, at the start of a system call, %eax contains -+ * -ENOSYS, so this makes it so. -+ */ -+#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)) -+ -+#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc))) -+ -+extern unsigned long *sc_sigmask(void *sc_ptr); -+extern int sc_get_fpregs(unsigned long buf, void *sc_ptr); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/syscalls.h um/arch/um/include/sysdep-i386/syscalls.h ---- orig/arch/um/include/sysdep-i386/syscalls.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-i386/syscalls.h Sun Dec 8 18:04:15 2002 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "asm/unistd.h" -+#include "sysdep/ptrace.h" -+ -+typedef long syscall_handler_t(struct pt_regs); -+ -+#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, -+ -+/* 222 doesn't yet have a name in include/asm-i386/unistd.h */ -+ -+#define LAST_ARCH_SYSCALL 222 -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/ptrace.h um/arch/um/include/sysdep-ia64/ptrace.h ---- orig/arch/um/include/sysdep-ia64/ptrace.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-ia64/ptrace.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_PTRACE_H -+#define __SYSDEP_IA64_PTRACE_H -+ -+struct sys_pt_regs { -+ int foo; -+}; -+ -+#define EMPTY_REGS { 0 } -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/sigcontext.h um/arch/um/include/sysdep-ia64/sigcontext.h ---- orig/arch/um/include/sysdep-ia64/sigcontext.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-ia64/sigcontext.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_SIGCONTEXT_H -+#define __SYSDEP_IA64_SIGCONTEXT_H -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/syscalls.h um/arch/um/include/sysdep-ia64/syscalls.h ---- orig/arch/um/include/sysdep-ia64/syscalls.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-ia64/syscalls.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_SYSCALLS_H -+#define __SYSDEP_IA64_SYSCALLS_H -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/ptrace.h um/arch/um/include/sysdep-ppc/ptrace.h ---- orig/arch/um/include/sysdep-ppc/ptrace.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-ppc/ptrace.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,104 @@ -+/* -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_PTRACE_PPC_H -+#define __SYS_PTRACE_PPC_H -+ -+#include "linux/config.h" -+#include "linux/types.h" -+ -+/* the following taken from <asm-ppc/ptrace.h> */ -+ -+#ifdef CONFIG_PPC64 -+#define PPC_REG unsigned long /*long*/ -+#else -+#define PPC_REG unsigned long -+#endif -+struct sys_pt_regs_s { -+ PPC_REG gpr[32]; -+ PPC_REG nip; -+ PPC_REG msr; -+ PPC_REG orig_gpr3; /* Used for restarting system calls */ -+ PPC_REG ctr; -+ PPC_REG link; -+ PPC_REG xer; -+ PPC_REG ccr; -+ PPC_REG mq; /* 601 only (not used at present) */ -+ /* Used on APUS to hold IPL value. */ -+ PPC_REG trap; /* Reason for being here */ -+ PPC_REG dar; /* Fault registers */ -+ PPC_REG dsisr; -+ PPC_REG result; /* Result of a system call */ -+}; -+ -+#define NUM_REGS (sizeof(struct sys_pt_regs_s) / sizeof(PPC_REG)) -+ -+struct sys_pt_regs { -+ PPC_REG regs[sizeof(struct sys_pt_regs_s) / sizeof(PPC_REG)]; -+}; -+ -+#define UM_MAX_REG (PT_FPR0) -+#define UM_MAX_REG_OFFSET (UM_MAX_REG * sizeof(PPC_REG)) -+ -+#define EMPTY_REGS { { [ 0 ... NUM_REGS - 1] = 0 } } -+ -+#define UM_REG(r, n) ((r)->regs[n]) -+ -+#define UM_SYSCALL_RET(r) UM_REG(r, PT_R3) -+#define UM_SP(r) UM_REG(r, PT_R1) -+#define UM_IP(r) UM_REG(r, PT_NIP) -+#define UM_ELF_ZERO(r) UM_REG(r, PT_FPSCR) -+#define UM_SYSCALL_NR(r) UM_REG(r, PT_R0) -+#define UM_SYSCALL_ARG1(r) UM_REG(r, PT_ORIG_R3) -+#define UM_SYSCALL_ARG2(r) UM_REG(r, PT_R4) -+#define UM_SYSCALL_ARG3(r) UM_REG(r, PT_R5) -+#define UM_SYSCALL_ARG4(r) UM_REG(r, PT_R6) -+#define UM_SYSCALL_ARG5(r) UM_REG(r, PT_R7) -+#define UM_SYSCALL_ARG6(r) UM_REG(r, PT_R8) -+ -+#define UM_SYSCALL_NR_OFFSET (PT_R0 * sizeof(PPC_REG)) -+#define UM_SYSCALL_RET_OFFSET (PT_R3 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG1_OFFSET (PT_R3 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG2_OFFSET (PT_R4 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG3_OFFSET (PT_R5 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG4_OFFSET (PT_R6 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG5_OFFSET (PT_R7 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG6_OFFSET (PT_R8 * sizeof(PPC_REG)) -+#define UM_SP_OFFSET (PT_R1 * sizeof(PPC_REG)) -+#define UM_IP_OFFSET (PT_NIP * sizeof(PPC_REG)) -+#define UM_ELF_ZERO_OFFSET (PT_R3 * sizeof(PPC_REG)) -+ -+#define UM_SET_SYSCALL_RETURN(_regs, result) \ -+do { \ -+ if (result < 0) { \ -+ (_regs)->regs[PT_CCR] |= 0x10000000; \ -+ UM_SYSCALL_RET((_regs)) = -result; \ -+ } else { \ -+ UM_SYSCALL_RET((_regs)) = result; \ -+ } \ -+} while(0) -+ -+extern void shove_aux_table(unsigned long sp); -+#define UM_FIX_EXEC_STACK(sp) shove_aux_table(sp); -+ -+/* These aren't actually defined. The undefs are just to make sure -+ * everyone's clear on the concept. -+ */ -+#undef UML_HAVE_GETREGS -+#undef UML_HAVE_GETFPREGS -+#undef UML_HAVE_SETREGS -+#undef UML_HAVE_SETFPREGS -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/sigcontext.h um/arch/um/include/sysdep-ppc/sigcontext.h ---- orig/arch/um/include/sysdep-ppc/sigcontext.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-ppc/sigcontext.h Sat Nov 23 22:02:19 2002 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_SIGCONTEXT_PPC_H -+#define __SYS_SIGCONTEXT_PPC_H -+ -+#define DSISR_WRITE 0x02000000 -+ -+#define SC_FAULT_ADDR(sc) ({ \ -+ struct sigcontext *_sc = (sc); \ -+ long retval = -1; \ -+ switch (_sc->regs->trap) { \ -+ case 0x300: \ -+ /* data exception */ \ -+ retval = _sc->regs->dar; \ -+ break; \ -+ case 0x400: \ -+ /* instruction exception */ \ -+ retval = _sc->regs->nip; \ -+ break; \ -+ default: \ -+ panic("SC_FAULT_ADDR: unhandled trap type\n"); \ -+ } \ -+ retval; \ -+ }) -+ -+#define SC_FAULT_WRITE(sc) ({ \ -+ struct sigcontext *_sc = (sc); \ -+ long retval = -1; \ -+ switch (_sc->regs->trap) { \ -+ case 0x300: \ -+ /* data exception */ \ -+ retval = !!(_sc->regs->dsisr & DSISR_WRITE); \ -+ break; \ -+ case 0x400: \ -+ /* instruction exception: not a write */ \ -+ retval = 0; \ -+ break; \ -+ default: \ -+ panic("SC_FAULT_ADDR: unhandled trap type\n"); \ -+ } \ -+ retval; \ -+ }) -+ -+#define SC_IP(sc) ((sc)->regs->nip) -+#define SC_SP(sc) ((sc)->regs->gpr[1]) -+#define SEGV_IS_FIXABLE(sc) (1) -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/syscalls.h um/arch/um/include/sysdep-ppc/syscalls.h ---- orig/arch/um/include/sysdep-ppc/syscalls.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysdep-ppc/syscalls.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+typedef long syscall_handler_t(unsigned long arg1, unsigned long arg2, -+ unsigned long arg3, unsigned long arg4, -+ unsigned long arg5, unsigned long arg6); -+ -+#define EXECUTE_SYSCALL(syscall, regs) \ -+ (*sys_call_table[syscall])(UM_SYSCALL_ARG1(®s), \ -+ UM_SYSCALL_ARG2(®s), \ -+ UM_SYSCALL_ARG3(®s), \ -+ UM_SYSCALL_ARG4(®s), \ -+ UM_SYSCALL_ARG5(®s), \ -+ UM_SYSCALL_ARG6(®s)) -+ -+extern syscall_handler_t sys_mincore; -+extern syscall_handler_t sys_madvise; -+ -+/* old_mmap needs the correct prototype since syscall_kern.c includes -+ * this file. -+ */ -+int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset); -+ -+#define ARCH_SYSCALLS \ -+ [ __NR_modify_ldt ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_read ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_write ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_iobase ] = sys_ni_syscall, \ -+ [ __NR_pivot_root ] = sys_ni_syscall, \ -+ [ __NR_multiplexer ] = sys_ni_syscall, \ -+ [ __NR_mmap ] = old_mmap, \ -+ [ __NR_madvise ] = sys_madvise, \ -+ [ __NR_mincore ] = sys_mincore, -+ -+#define LAST_ARCH_SYSCALL __NR_mincore -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/include/sysrq.h um/arch/um/include/sysrq.h ---- orig/arch/um/include/sysrq.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/sysrq.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SYSRQ_H -+#define __UM_SYSRQ_H -+ -+extern void show_trace(unsigned long *stack); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/include/tempfile.h um/arch/um/include/tempfile.h ---- orig/arch/um/include/tempfile.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/tempfile.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TEMPFILE_H__ -+#define __TEMPFILE_H__ -+ -+extern int make_tempfile(const char *template, char **tempname, int do_unlink); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/time_user.h um/arch/um/include/time_user.h ---- orig/arch/um/include/time_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/time_user.h Wed Jan 8 12:55:47 2003 -@@ -0,0 +1,17 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TIME_USER_H__ -+#define __TIME_USER_H__ -+ -+extern void timer(void); -+extern void switch_timers(int to_real); -+extern void set_interval(int timer_type); -+extern void idle_sleep(int secs); -+extern void enable_timer(void); -+extern unsigned long time_lock(void); -+extern void time_unlock(unsigned long); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/include/tlb.h um/arch/um/include/tlb.h ---- orig/arch/um/include/tlb.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/tlb.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TLB_H__ -+#define __TLB_H__ -+ -+extern void mprotect_kernel_vm(int w); -+extern void force_flush_all(void); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/ubd_user.h um/arch/um/include/ubd_user.h ---- orig/arch/um/include/ubd_user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/ubd_user.h Thu Mar 6 18:09:14 2003 -@@ -0,0 +1,77 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_UBD_USER_H -+#define __UM_UBD_USER_H -+ -+#include "os.h" -+ -+enum ubd_req { UBD_READ, UBD_WRITE }; -+ -+struct io_thread_req { -+ enum ubd_req op; -+ int fds[2]; -+ unsigned long offsets[2]; -+ unsigned long long offset; -+ unsigned long length; -+ char *buffer; -+ int sectorsize; -+ unsigned long sector_mask; -+ unsigned long cow_offset; -+ unsigned long bitmap_words[2]; -+ int error; -+}; -+ -+extern 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, -+ int *create_cow_out); -+extern int create_cow_file(char *cow_file, char *backing_file, -+ struct openflags flags, int sectorsize, -+ 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); -+extern int read_ubd_fs(int fd, void *buffer, int len); -+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); -+ -+static inline int ubd_test_bit(__u64 bit, unsigned char *data) -+{ -+ __u64 n; -+ int bits, off; -+ -+ bits = sizeof(data[0]) * 8; -+ n = bit / bits; -+ off = bit % bits; -+ return((data[n] & (1 << off)) != 0); -+} -+ -+static inline void ubd_set_bit(__u64 bit, unsigned char *data) -+{ -+ __u64 n; -+ int bits, off; -+ -+ bits = sizeof(data[0]) * 8; -+ n = bit / bits; -+ off = bit % bits; -+ data[n] |= (1 << off); -+} -+ -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/um_mmu.h um/arch/um/include/um_mmu.h ---- orig/arch/um/include/um_mmu.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/um_mmu.h Sat Nov 9 12:51:43 2002 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __ARCH_UM_MMU_H -+#define __ARCH_UM_MMU_H -+ -+#include "linux/config.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/mmu.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mmu.h" -+#endif -+ -+typedef union { -+#ifdef CONFIG_MODE_TT -+ struct mmu_context_tt tt; -+#endif -+#ifdef CONFIG_MODE_SKAS -+ struct mmu_context_skas skas; -+#endif -+} mm_context_t; -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/um_uaccess.h um/arch/um/include/um_uaccess.h ---- orig/arch/um/include/um_uaccess.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/um_uaccess.h Sat Nov 23 22:03:02 2002 -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __ARCH_UM_UACCESS_H -+#define __ARCH_UM_UACCESS_H -+ -+#include "linux/config.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/uaccess.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/uaccess.h" -+#endif -+ -+#define access_ok(type, addr, size) \ -+ CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) -+ -+static inline int verify_area(int type, const void * addr, unsigned long size) -+{ -+ return(CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr, -+ size)); -+} -+ -+static inline int copy_from_user(void *to, const void *from, int n) -+{ -+ return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to, -+ from, n)); -+} -+ -+static inline int copy_to_user(void *to, const void *from, int n) -+{ -+ return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, -+ from, n)); -+} -+ -+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)); -+} -+ -+static inline int __clear_user(void *mem, int len) -+{ -+ return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len)); -+} -+ -+static inline int clear_user(void *mem, int len) -+{ -+ return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); -+} -+ -+static inline int strnlen_user(const void *str, int len) -+{ -+ return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); -+} -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/umid.h um/arch/um/include/umid.h ---- orig/arch/um/include/umid.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/umid.h Mon Dec 16 20:52:19 2002 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UMID_H__ -+#define __UMID_H__ -+ -+extern int umid_file_name(char *name, char *buf, int len); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/uml_uaccess.h um/arch/um/include/uml_uaccess.h ---- orig/arch/um/include/uml_uaccess.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/uml_uaccess.h Thu Dec 19 13:15:22 2002 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UML_UACCESS_H__ -+#define __UML_UACCESS_H__ -+ -+extern int __do_copy_to_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher); -+extern unsigned long __do_user_copy(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher, -+ void (*op)(void *to, const void *from, -+ int n), int *faulted_out); -+void __do_copy(void *to, const void *from, int n); -+ -+#endif -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/include/umn.h um/arch/um/include/umn.h ---- orig/arch/um/include/umn.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/umn.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UMN_H -+#define __UMN_H -+ -+extern int open_umn_tty(int *slave_out, int *slipno_out); -+extern void close_umn_tty(int master, int slave); -+extern int umn_send_packet(int fd, void *data, int len); -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern void slip_unesc(unsigned char s); -+extern void umn_read(int fd); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/user.h um/arch/um/include/user.h ---- orig/arch/um/include/user.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/user.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __USER_H__ -+#define __USER_H__ -+ -+extern void panic(const char *fmt, ...); -+extern int printk(const char *fmt, ...); -+extern void schedule(void); -+extern void *um_kmalloc(int size); -+extern void *um_kmalloc_atomic(int size); -+extern void kfree(void *ptr); -+extern int in_aton(char *str); -+extern int open_gdb_chan(void); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/include/user_util.h um/arch/um/include/user_util.h ---- orig/arch/um/include/user_util.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/include/user_util.h Fri Dec 20 23:28:42 2002 -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __USER_UTIL_H__ -+#define __USER_UTIL_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int mode_tt; -+ -+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; -+}; -+ -+extern struct cpu_task cpu_tasks[]; -+ -+struct signal_info { -+ void (*handler)(int, union uml_pt_regs *); -+ int is_irq; -+}; -+ -+extern struct signal_info sig_info[]; -+ -+extern unsigned long low_physmem; -+extern unsigned long high_physmem; -+extern unsigned long uml_physmem; -+extern unsigned long uml_reserved; -+extern unsigned long end_vm; -+extern unsigned long start_vm; -+extern unsigned long highmem; -+ -+extern char host_info[]; -+ -+extern char saved_command_line[]; -+extern char command_line[]; -+ -+extern char *tempdir; -+ -+extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; -+extern unsigned long _unprotected_end; -+extern unsigned long brk_start; -+ -+extern int pty_output_sigio; -+extern int pty_close_sigio; -+ -+extern void stop(void); -+extern void stack_protections(unsigned long address); -+extern void task_protections(unsigned long address); -+extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); -+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); -+extern int get_pty(void); -+extern void *um_kmalloc(int size); -+extern int raw(int fd, int complain); -+extern int switcheroo(int fd, int prot, void *from, void *to, int size); -+extern void setup_machinename(char *machine_out); -+extern void setup_hostinfo(void); -+extern void add_arg(char *cmd_line, char *arg); -+extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); -+extern void init_new_thread_signals(int altstack); -+extern void do_exec(int old_pid, int new_pid); -+extern void tracer_panic(char *msg, ...); -+extern char *get_umid(int only_if_set); -+extern void do_longjmp(void *p, int val); -+extern void suspend_new_thread(int fd); -+extern int detach(int pid, int sig); -+extern int attach(int pid); -+extern void kill_child_dead(int pid); -+extern int cont(int pid); -+extern void check_ptrace(void); -+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 arch_handle_signal(int sig, union uml_pt_regs *regs); -+extern int arch_fixup(unsigned long address, void *sc_ptr); -+extern int can_do_skas(void); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/Makefile um/arch/um/kernel/Makefile ---- orig/arch/um/kernel/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/Makefile Fri Dec 20 23:25:45 2002 -@@ -0,0 +1,73 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = config.o checksum.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 -+ -+obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o -+obj-$(CONFIG_GPROF) += gprof_syms.o -+obj-$(CONFIG_GCOV) += gmon_syms.o -+obj-$(CONFIG_TTY_LOG) += tty_log.o -+ -+subdir-$(CONFIG_MODE_TT) += tt -+subdir-$(CONFIG_MODE_SKAS) += skas -+ -+user-objs-$(CONFIG_TTY_LOG) += tty_log.o -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+# user_syms.o not included here because Rules.make has its own ideas about -+# building anything in export-objs -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \ -+ process.o tempfile.o time.o umid.o user_util.o -+ -+DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__ -+DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__ -+ -+export-objs-$(CONFIG_GPROF) += gprof_syms.o -+export-objs-$(CONFIG_GCOV) += gmon_syms.o -+ -+export-objs = ksyms.o process_kern.o signal_kern.o user_syms.o $(export-objs-y) -+ -+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)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(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. -+ -+frame.o: frame.c -+ $(CC) $(CFLAGS_$@) -c -o $@ $< -+ -+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }' -+ -+config.c : config.c.in $(TOPDIR)/.config -+ $(PERL) -e $(QUOTE) < config.c.in > $@ -+ -+clean: -+ $(RM) config.c -+ for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done -+ -+modules: -+ -+fastdep: -+ -+dep: -+ -+archmrproper: clean -diff -Naur -X ../exclude-files orig/arch/um/kernel/checksum.c um/arch/um/kernel/checksum.c ---- orig/arch/um/kernel/checksum.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/checksum.c Thu Oct 31 22:39:58 2002 -@@ -0,0 +1,42 @@ -+#include "asm/uaccess.h" -+#include "linux/errno.h" -+ -+extern unsigned int arch_csum_partial(const char *buff, int len, int sum); -+ -+extern unsigned int csum_partial(char *buff, int len, int sum) -+{ -+ return(arch_csum_partial(buff, len, sum)); -+} -+ -+unsigned int csum_partial_copy_to(const char *src, char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if(copy_to_user(dst, src, len)){ -+ *err_ptr = -EFAULT; -+ return(-1); -+ } -+ -+ return(arch_csum_partial(src, len, sum)); -+} -+ -+unsigned int csum_partial_copy_from(const char *src, char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if(copy_from_user(dst, src, len)){ -+ *err_ptr = -EFAULT; -+ return(-1); -+ } -+ -+ return(arch_csum_partial(dst, len, sum)); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/config.c.in um/arch/um/kernel/config.c.in ---- orig/arch/um/kernel/config.c.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/config.c.in Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include "init.h" -+ -+static __initdata char *config = " -+CONFIG -+"; -+ -+static int __init print_config(char *line, int *add) -+{ -+ printf("%s", config); -+ exit(0); -+} -+ -+__uml_setup("--showconfig", print_config, -+"--showconfig\n" -+" Prints the config file that this UML binary was generated from.\n\n" -+); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/exec_kern.c um/arch/um/kernel/exec_kern.c ---- orig/arch/um/kernel/exec_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/exec_kern.c Tue Nov 19 17:07:20 2002 -@@ -0,0 +1,81 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/slab.h" -+#include "linux/smp_lock.h" -+#include "asm/ptrace.h" -+#include "asm/pgtable.h" -+#include "asm/pgalloc.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "mem_user.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "tlb.h" -+#include "2_5compat.h" -+#include "os.h" -+#include "time_user.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+ -+void flush_thread(void) -+{ -+ CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); -+} -+ -+void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) -+{ -+ CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); -+} -+ -+static int execve1(char *file, char **argv, char **env) -+{ -+ int error; -+ -+ error = do_execve(file, argv, env, ¤t->thread.regs); -+ if (error == 0){ -+ current->ptrace &= ~PT_DTRACE; -+ set_cmdline(current_cmd()); -+ } -+ return(error); -+} -+ -+int um_execve(char *file, char **argv, char **env) -+{ -+ int err; -+ -+ err = execve1(file, argv, env); -+ if(!err) -+ do_longjmp(current->thread.exec_buf, 1); -+ return(err); -+} -+ -+int sys_execve(char *file, char **argv, char **env) -+{ -+ int error; -+ char *filename; -+ -+ lock_kernel(); -+ filename = getname((char *) file); -+ error = PTR_ERR(filename); -+ if (IS_ERR(filename)) goto out; -+ error = execve1(filename, argv, env); -+ putname(filename); -+ out: -+ unlock_kernel(); -+ return(error); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/exitcode.c um/arch/um/kernel/exitcode.c ---- orig/arch/um/kernel/exitcode.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/exitcode.c Thu Nov 7 18:22:04 2002 -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/ctype.h" -+#include "linux/proc_fs.h" -+#include "asm/uaccess.h" -+ -+/* If read and write race, the read will still atomically read a valid -+ * value. -+ */ -+int uml_exitcode = 0; -+ -+static int read_proc_exitcode(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len; -+ -+ len = sprintf(page, "%d\n", uml_exitcode); -+ len -= off; -+ if(len <= off+count) *eof = 1; -+ *start = page + off; -+ if(len > count) len = count; -+ if(len < 0) len = 0; -+ return(len); -+} -+ -+static int write_proc_exitcode(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ char *end, buf[sizeof("nnnnn\0")]; -+ int tmp; -+ -+ if(copy_from_user(buf, buffer, count)) -+ return(-EFAULT); -+ tmp = simple_strtol(buf, &end, 0); -+ if((*end != '\0') && !isspace(*end)) -+ return(-EINVAL); -+ uml_exitcode = tmp; -+ return(count); -+} -+ -+static int make_proc_exitcode(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ ent = create_proc_entry("exitcode", 0600, &proc_root); -+ if(ent == NULL){ -+ printk("make_proc_exitcode : Failed to register " -+ "/proc/exitcode\n"); -+ return(0); -+ } -+ -+ ent->read_proc = read_proc_exitcode; -+ ent->write_proc = write_proc_exitcode; -+ -+ return(0); -+} -+ -+__initcall(make_proc_exitcode); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/frame.c um/arch/um/kernel/frame.c ---- orig/arch/um/kernel/frame.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/frame.c Wed Dec 11 11:12:41 2002 -@@ -0,0 +1,342 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <string.h> -+#include <signal.h> -+#include <wait.h> -+#include <sched.h> -+#include <errno.h> -+#include <sys/ptrace.h> -+#include <sys/syscall.h> -+#include <sys/mman.h> -+#include <asm/page.h> -+#include <asm/ptrace.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+#include "frame_user.h" -+#include "kern_util.h" -+#include "ptrace_user.h" -+#include "os.h" -+ -+static int capture_stack(int (*child)(void *arg), void *arg, void *sp, -+ unsigned long top, void **data_out) -+{ -+ unsigned long regs[FRAME_SIZE]; -+ int pid, status, n, len; -+ -+ /* Start the child as a thread */ -+ pid = clone(child, sp, CLONE_VM | SIGCHLD, arg); -+ if(pid < 0){ -+ printf("capture_stack : clone failed - errno = %d\n", errno); -+ exit(1); -+ } -+ -+ /* Wait for it to stop itself and continue it with a SIGUSR1 to force -+ * it into the signal handler. -+ */ -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ fprintf(stderr, "capture_stack : Expected SIGSTOP, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ if(ptrace(PTRACE_CONT, pid, 0, SIGUSR1) < 0){ -+ printf("capture_stack : PTRACE_CONT failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ /* Wait for it to stop itself again and grab its registers again. -+ * At this point, the handler has stuffed the addresses of -+ * sig, sc, and SA_RESTORER in raw. -+ */ -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ fprintf(stderr, "capture_stack : Expected SIGSTOP, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0){ -+ printf("capture_stack : PTRACE_GETREGS failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ /* It has outlived its usefulness, so continue it so it can exit */ -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0){ -+ printf("capture_stack : PTRACE_CONT failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ if(waitpid(pid, &status, 0) < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != 9)){ -+ printf("capture_stack : Expected exit signal 9, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ -+ /* The frame that we want is the top of the signal stack */ -+ -+ len = top - PT_SP(regs); -+ *data_out = malloc(len); -+ if(*data_out == NULL){ -+ printf("capture_stack : malloc failed - errno = %d\n", errno); -+ exit(1); -+ } -+ memcpy(*data_out, (void *) PT_SP(regs), len); -+ -+ return(len); -+} -+ -+struct common_raw { -+ void *stack; -+ int size; -+ unsigned long sig; -+ unsigned long sr; -+ unsigned long sp; -+ struct arch_frame_data_raw arch; -+}; -+ -+#define SA_RESTORER (0x04000000) -+ -+typedef unsigned long old_sigset_t; -+ -+struct old_sigaction { -+ __sighandler_t handler; -+ old_sigset_t sa_mask; -+ unsigned long sa_flags; -+ void (*sa_restorer)(void); -+}; -+ -+static void child_common(struct common_raw *common, sighandler_t handler, -+ int restorer, int flags) -+{ -+ stack_t ss = ((stack_t) { .ss_sp = common->stack, -+ .ss_flags = 0, -+ .ss_size = common->size }); -+ int err; -+ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ printf("PTRACE_TRACEME failed, errno = %d\n", errno); -+ } -+ if(sigaltstack(&ss, NULL) < 0){ -+ printf("sigaltstack failed - errno = %d\n", errno); -+ kill(getpid(), SIGKILL); -+ } -+ -+ if(restorer){ -+ struct sigaction sa; -+ -+ sa.sa_handler = handler; -+ sigemptyset(&sa.sa_mask); -+ sa.sa_flags = SA_ONSTACK | flags; -+ err = sigaction(SIGUSR1, &sa, NULL); -+ } -+ else { -+ struct old_sigaction sa; -+ -+ sa.handler = handler; -+ sa.sa_mask = 0; -+ sa.sa_flags = (SA_ONSTACK | flags) & ~SA_RESTORER; -+ err = syscall(__NR_sigaction, SIGUSR1, &sa, NULL); -+ } -+ -+ if(err < 0){ -+ printf("sigaction failed - errno = %d\n", errno); -+ kill(getpid(), SIGKILL); -+ } -+ -+ os_stop_process(os_getpid()); -+} -+ -+/* Changed only during early boot */ -+struct sc_frame signal_frame_sc; -+ -+struct sc_frame signal_frame_sc_sr; -+ -+struct sc_frame_raw { -+ struct common_raw common; -+ unsigned long sc; -+ int restorer; -+}; -+ -+/* Changed only during early boot */ -+static struct sc_frame_raw *raw_sc = NULL; -+ -+static void sc_handler(int sig, struct sigcontext sc) -+{ -+ raw_sc->common.sig = (unsigned long) &sig; -+ raw_sc->common.sr = frame_restorer(); -+ raw_sc->common.sp = frame_sp(); -+ raw_sc->sc = (unsigned long) ≻ -+ setup_arch_frame_raw(&raw_sc->common.arch, &sc + 1, raw_sc->common.sr); -+ -+ os_stop_process(os_getpid()); -+ kill(getpid(), SIGKILL); -+} -+ -+static int sc_child(void *arg) -+{ -+ raw_sc = arg; -+ child_common(&raw_sc->common, (sighandler_t) sc_handler, -+ raw_sc->restorer, 0); -+ return(-1); -+} -+ -+/* Changed only during early boot */ -+struct si_frame signal_frame_si; -+ -+struct si_frame_raw { -+ struct common_raw common; -+ unsigned long sip; -+ unsigned long si; -+ unsigned long ucp; -+ unsigned long uc; -+}; -+ -+/* Changed only during early boot */ -+static struct si_frame_raw *raw_si = NULL; -+ -+static void si_handler(int sig, siginfo_t *si, struct ucontext *ucontext) -+{ -+ raw_si->common.sig = (unsigned long) &sig; -+ raw_si->common.sr = frame_restorer(); -+ raw_si->common.sp = frame_sp(); -+ raw_si->sip = (unsigned long) &si; -+ raw_si->si = (unsigned long) si; -+ raw_si->ucp = (unsigned long) &ucontext; -+ raw_si->uc = (unsigned long) ucontext; -+ setup_arch_frame_raw(&raw_si->common.arch, -+ ucontext->uc_mcontext.fpregs, raw_si->common.sr); -+ -+ os_stop_process(os_getpid()); -+ kill(getpid(), SIGKILL); -+} -+ -+static int si_child(void *arg) -+{ -+ raw_si = arg; -+ child_common(&raw_si->common, (sighandler_t) si_handler, 1, -+ SA_SIGINFO); -+ return(-1); -+} -+ -+static int relative_sr(unsigned long sr, int sr_index, void *stack, -+ void *framep) -+{ -+ unsigned long *srp = (unsigned long *) sr; -+ unsigned long frame = (unsigned long) framep; -+ -+ if((*srp & PAGE_MASK) == (unsigned long) stack){ -+ *srp -= sr; -+ *((unsigned long *) (frame + sr_index)) = *srp; -+ return(1); -+ } -+ else return(0); -+} -+ -+static unsigned long capture_stack_common(int (*proc)(void *), void *arg, -+ struct common_raw *common_in, -+ void *top, void *sigstack, -+ int stack_len, -+ struct frame_common *common_out) -+{ -+ unsigned long sig_top = (unsigned long) sigstack + stack_len, base; -+ -+ common_in->stack = (void *) sigstack; -+ common_in->size = stack_len; -+ common_out->len = capture_stack(proc, arg, top, sig_top, -+ &common_out->data); -+ base = sig_top - common_out->len; -+ common_out->sig_index = common_in->sig - base; -+ common_out->sp_index = common_in->sp - base; -+ common_out->sr_index = common_in->sr - base; -+ common_out->sr_relative = relative_sr(common_in->sr, -+ common_out->sr_index, sigstack, -+ common_out->data); -+ return(base); -+} -+ -+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; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ sigstack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if((stack == MAP_FAILED) || (sigstack == MAP_FAILED)){ -+ printf("capture_signal_stack : mmap failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ 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; -+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_sc.common); -+ -+ signal_frame_sc.sc_index = raw_sc.sc - base; -+ setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc.common.arch); -+ -+ /* Ditto for the sigcontext, sigrestorer layout */ -+ raw_sc.restorer = 1; -+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_sc_sr.common); -+ signal_frame_sc_sr.sc_index = raw_sc.sc - base; -+ setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc_sr.common.arch); -+ -+ /* And the siginfo layout */ -+ -+ base = capture_stack_common(si_child, &raw_si, &raw_si.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_si.common); -+ signal_frame_si.sip_index = raw_si.sip - base; -+ signal_frame_si.si_index = raw_si.si - base; -+ signal_frame_si.ucp_index = raw_si.ucp - base; -+ signal_frame_si.uc_index = raw_si.uc - base; -+ setup_arch_frame(&raw_si.common.arch, &signal_frame_si.common.arch); -+ -+ if((munmap(stack, PAGE_SIZE) < 0) || -+ (munmap(sigstack, PAGE_SIZE) < 0)){ -+ printf("capture_signal_stack : munmap failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/frame_kern.c um/arch/um/kernel/frame_kern.c ---- orig/arch/um/kernel/frame_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/frame_kern.c Sun Dec 8 19:44:13 2002 -@@ -0,0 +1,171 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#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" -+#include "sysdep/ptrace.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) -+{ -+ if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) -+ return -EFAULT; -+ if (from->si_code < 0) -+ return __copy_to_user(to, from, sizeof(siginfo_t)); -+ else { -+ int err; -+ -+ /* If you change siginfo_t structure, please be sure -+ this code is fixed accordingly. -+ It should never copy any pad contained in the structure -+ to avoid security leaks, but must copy the generic -+ 3 ints plus the relevant union member. */ -+ err = __put_user(from->si_signo, &to->si_signo); -+ err |= __put_user(from->si_errno, &to->si_errno); -+ err |= __put_user((short)from->si_code, &to->si_code); -+ /* First 32bits of unions are always present. */ -+ err |= __put_user(from->si_pid, &to->si_pid); -+ switch (from->si_code >> 16) { -+ case __SI_FAULT >> 16: -+ break; -+ case __SI_CHLD >> 16: -+ err |= __put_user(from->si_utime, &to->si_utime); -+ err |= __put_user(from->si_stime, &to->si_stime); -+ err |= __put_user(from->si_status, &to->si_status); -+ default: -+ err |= __put_user(from->si_uid, &to->si_uid); -+ break; -+ } -+ return err; -+ } -+} -+ -+static int copy_restorer(void (*restorer)(void), unsigned long start, -+ unsigned long sr_index, int sr_relative) -+{ -+ unsigned long sr; -+ -+ if(sr_relative){ -+ sr = (unsigned long) restorer; -+ sr += start + sr_index; -+ restorer = (void (*)(void)) sr; -+ } -+ -+ return(copy_to_user((void *) (start + sr_index), &restorer, -+ sizeof(restorer))); -+} -+ -+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, -+ current->thread.cr2, -+ current->thread.err))); -+} -+ -+static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set, -+ unsigned long sp) -+{ -+ int err = 0; -+ -+ err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); -+ err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); -+ err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); -+ err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, -+ &signal_frame_si.common.arch); -+ err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); -+ return(err); -+} -+ -+int setup_signal_stack_si(unsigned long stack_top, int sig, -+ unsigned long handler, void (*restorer)(void), -+ struct pt_regs *regs, siginfo_t *info, -+ sigset_t *mask) -+{ -+ unsigned long start; -+ void *sip, *ucp, *fp; -+ -+ start = stack_top - signal_frame_si.common.len; -+ sip = (void *) (start + signal_frame_si.si_index); -+ ucp = (void *) (start + signal_frame_si.uc_index); -+ fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext)); -+ -+ if(restorer == NULL) -+ panic("setup_signal_stack_si - no restorer"); -+ -+ if(copy_to_user((void *) start, signal_frame_si.common.data, -+ signal_frame_si.common.len) || -+ copy_to_user((void *) (start + signal_frame_si.common.sig_index), -+ &sig, sizeof(sig)) || -+ copy_siginfo_to_user(sip, info) || -+ copy_to_user((void *) (start + signal_frame_si.sip_index), &sip, -+ sizeof(sip)) || -+ copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) || -+ copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp, -+ sizeof(ucp)) || -+ copy_restorer(restorer, start, signal_frame_si.common.sr_index, -+ signal_frame_si.common.sr_relative)) -+ return(1); -+ -+ PT_REGS_IP(regs) = handler; -+ PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index; -+ return(0); -+} -+ -+int setup_signal_stack_sc(unsigned long stack_top, int sig, -+ unsigned long handler, void (*restorer)(void), -+ struct pt_regs *regs, sigset_t *mask) -+{ -+ struct frame_common *frame = &signal_frame_sc_sr.common; -+ void *user_sc; -+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); -+ unsigned long sigs, sr; -+ unsigned long start = stack_top - frame->len - sig_size; -+ -+ user_sc = (void *) (start + signal_frame_sc_sr.sc_index); -+ if(restorer == NULL){ -+ frame = &signal_frame_sc.common; -+ user_sc = (void *) (start + signal_frame_sc.sc_index); -+ sr = (unsigned long) frame->data; -+ sr += frame->sr_index; -+ sr = *((unsigned long *) sr); -+ restorer = ((void (*)(void)) sr); -+ } -+ -+ sigs = start + frame->len; -+ if(copy_to_user((void *) start, frame->data, frame->len) || -+ copy_to_user((void *) (start + frame->sig_index), &sig, -+ sizeof(sig)) || -+ copy_sc_to_user(user_sc, NULL, regs, -+ &signal_frame_sc.common.arch) || -+ copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) || -+ copy_to_user((void *) sigs, &mask->sig[1], sig_size) || -+ copy_restorer(restorer, start, frame->sr_index, frame->sr_relative)) -+ return(1); -+ -+ PT_REGS_IP(regs) = handler; -+ PT_REGS_SP(regs) = start + frame->sp_index; -+ -+ 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 -Naur -X ../exclude-files orig/arch/um/kernel/gmon_syms.c um/arch/um/kernel/gmon_syms.c ---- orig/arch/um/kernel/gmon_syms.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/gmon_syms.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+ -+extern void __bb_init_func(void *); -+EXPORT_SYMBOL(__bb_init_func); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/gprof_syms.c um/arch/um/kernel/gprof_syms.c ---- orig/arch/um/kernel/gprof_syms.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/gprof_syms.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+ -+extern void mcount(void); -+EXPORT_SYMBOL(mcount); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/helper.c um/arch/um/kernel/helper.c ---- orig/arch/um/kernel/helper.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/helper.c Thu Oct 31 10:34:23 2002 -@@ -0,0 +1,153 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <fcntl.h> -+#include <sched.h> -+#include <sys/signal.h> -+#include <sys/wait.h> -+#include "user.h" -+#include "kern_util.h" -+#include "os.h" -+ -+struct helper_data { -+ void (*pre_exec)(void*); -+ void *pre_data; -+ char **argv; -+ int fd; -+}; -+ -+/* Debugging aid, changed only from gdb */ -+int helper_pause = 0; -+ -+static void helper_hup(int sig) -+{ -+} -+ -+static int helper_child(void *arg) -+{ -+ struct helper_data *data = arg; -+ char **argv = data->argv; -+ -+ if(helper_pause){ -+ signal(SIGHUP, helper_hup); -+ pause(); -+ } -+ if(data->pre_exec != NULL) -+ (*data->pre_exec)(data->pre_data); -+ execvp(argv[0], argv); -+ printk("execvp of '%s' failed - errno = %d\n", argv[0], errno); -+ write(data->fd, &errno, sizeof(errno)); -+ os_kill_process(os_getpid(), 0); -+ return(0); -+} -+ -+/* XXX The alloc_stack here breaks if this is called in the tracing thread */ -+ -+int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, -+ unsigned long *stack_out) -+{ -+ struct helper_data data; -+ unsigned long stack, sp; -+ int pid, fds[2], err, n; -+ -+ if((stack_out != NULL) && (*stack_out != 0)) -+ stack = *stack_out; -+ else stack = alloc_stack(0, um_in_interrupt()); -+ 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(fcntl(fds[1], F_SETFD, 1) != 0){ -+ printk("run_helper : setting FD_CLOEXEC failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ sp = stack + page_size() - sizeof(void *); -+ data.pre_exec = pre_exec; -+ data.pre_data = pre_data; -+ data.argv = argv; -+ data.fd = fds[1]; -+ pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); -+ if(pid < 0){ -+ printk("run_helper : clone failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ close(fds[1]); -+ n = read(fds[0], &err, sizeof(err)); -+ if(n < 0){ -+ printk("run_helper : read on pipe failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ else if(n != 0){ -+ waitpid(pid, NULL, 0); -+ pid = -err; -+ } -+ -+ if(stack_out == NULL) free_stack(stack, 0); -+ else *stack_out = stack; -+ return(pid); -+} -+ -+int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, -+ unsigned long *stack_out, int stack_order) -+{ -+ unsigned long stack, sp; -+ int pid, status; -+ -+ stack = alloc_stack(stack_order, um_in_interrupt()); -+ if(stack == 0) return(-ENOMEM); -+ -+ sp = stack + (page_size() << stack_order) - sizeof(void *); -+ pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); -+ if(pid < 0){ -+ printk("run_helper_thread : clone failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ if(stack_out == NULL){ -+ pid = waitpid(pid, &status, 0); -+ if(pid < 0) -+ printk("run_helper_thread - wait failed, errno = %d\n", -+ pid); -+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) -+ printk("run_helper_thread - thread returned status " -+ "0x%x\n", status); -+ free_stack(stack, stack_order); -+ } -+ else *stack_out = stack; -+ return(pid); -+} -+ -+int helper_wait(int pid, int block) -+{ -+ int ret; -+ -+ ret = waitpid(pid, NULL, WNOHANG); -+ if(ret < 0){ -+ printk("helper_wait : waitpid failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ return(ret); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/init_task.c um/arch/um/kernel/init_task.c ---- orig/arch/um/kernel/init_task.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/init_task.c Sat Dec 28 19:58:44 2002 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "linux/sched.h" -+#include "linux/version.h" -+#include "asm/uaccess.h" -+#include "asm/pgtable.h" -+#include "user_util.h" -+#include "mem_user.h" -+ -+static struct fs_struct init_fs = INIT_FS; -+static struct files_struct init_files = INIT_FILES; -+static struct signal_struct init_signals = INIT_SIGNALS; -+struct mm_struct init_mm = INIT_MM(init_mm); -+ -+/* -+ * Initial task structure. -+ * -+ * We need to make sure that this is 16384-byte aligned due to the -+ * way process stacks are handled. This is done by having a special -+ * "init_task" linker map entry.. -+ */ -+ -+union task_union init_task_union -+__attribute__((__section__(".data.init_task"))) = -+{ INIT_TASK(init_task_union.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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/initrd_kern.c um/arch/um/kernel/initrd_kern.c ---- orig/arch/um/kernel/initrd_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/initrd_kern.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/bootmem.h" -+#include "linux/blk.h" -+#include "asm/types.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "initrd.h" -+#include "init.h" -+#include "os.h" -+ -+/* Changed by uml_initrd_setup, which is a setup */ -+static char *initrd __initdata = NULL; -+ -+static int __init read_initrd(void) -+{ -+ void *area; -+ long long size; -+ int err; -+ -+ if(initrd == NULL) return 0; -+ err = os_file_size(initrd, &size); -+ if(err) return 0; -+ area = alloc_bootmem(size); -+ if(area == NULL) return 0; -+ if(load_initrd(initrd, area, size) == -1) return 0; -+ initrd_start = (unsigned long) area; -+ initrd_end = initrd_start + size; -+ return 0; -+} -+ -+__uml_postsetup(read_initrd); -+ -+static int __init uml_initrd_setup(char *line, int *add) -+{ -+ initrd = line; -+ return 0; -+} -+ -+__uml_setup("initrd=", uml_initrd_setup, -+"initrd=<initrd image>\n" -+" This is used to boot UML from an initrd image. The argument is the\n" -+" name of the file containing the image.\n\n" -+); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/initrd_user.c um/arch/um/kernel/initrd_user.c ---- orig/arch/um/kernel/initrd_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/initrd_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <fcntl.h> -+#include <errno.h> -+ -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "initrd.h" -+#include "os.h" -+ -+int load_initrd(char *filename, void *buf, int size) -+{ -+ int fd, n; -+ -+ if((fd = os_open_file(filename, of_read(OPENFLAGS()), 0)) < 0){ -+ printk("Opening '%s' failed - errno = %d\n", filename, errno); -+ 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); -+ return(-1); -+ } -+ 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 -Naur -X ../exclude-files orig/arch/um/kernel/irq.c um/arch/um/kernel/irq.c ---- orig/arch/um/kernel/irq.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/irq.c Wed Mar 26 14:45:29 2003 -@@ -0,0 +1,842 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: -+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "linux/irq.h" -+#include "linux/kernel_stat.h" -+#include "linux/interrupt.h" -+#include "linux/random.h" -+#include "linux/slab.h" -+#include "linux/file.h" -+#include "linux/proc_fs.h" -+#include "linux/init.h" -+#include "linux/seq_file.h" -+#include "asm/irq.h" -+#include "asm/hw_irq.h" -+#include "asm/hardirq.h" -+#include "asm/atomic.h" -+#include "asm/signal.h" -+#include "asm/system.h" -+#include "asm/errno.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+ -+static void register_irq_proc (unsigned int irq); -+ -+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = -+ { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; -+ -+/* -+ * Generic no controller code -+ */ -+ -+static void enable_none(unsigned int irq) { } -+static unsigned int startup_none(unsigned int irq) { return 0; } -+static void disable_none(unsigned int irq) { } -+static void ack_none(unsigned int irq) -+{ -+/* -+ * 'what should we do if we get a hw irq event on an illegal vector'. -+ * each architecture has to answer this themselves, it doesnt deserve -+ * a generic callback i think. -+ */ -+#if CONFIG_X86 -+ printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq); -+#ifdef CONFIG_X86_LOCAL_APIC -+ /* -+ * Currently unexpected vectors happen only on SMP and APIC. -+ * We _must_ ack these because every local APIC has only N -+ * irq slots per priority level, and a 'hanging, unacked' IRQ -+ * holds up an irq slot - in excessive cases (when multiple -+ * unexpected vectors occur) that might lock up the APIC -+ * completely. -+ */ -+ ack_APIC_irq(); -+#endif -+#endif -+} -+ -+/* startup is the same as "enable", shutdown is same as "disable" */ -+#define shutdown_none disable_none -+#define end_none enable_none -+ -+struct hw_interrupt_type no_irq_type = { -+ "none", -+ startup_none, -+ shutdown_none, -+ enable_none, -+ disable_none, -+ ack_none, -+ end_none -+}; -+ -+/* Not changed */ -+volatile unsigned long irq_err_count; -+ -+/* -+ * Generic, controller-independent functions: -+ */ -+ -+int get_irq_list(char *buf) -+{ -+ int i, j; -+ unsigned long flags; -+ struct irqaction * action; -+ char *p = buf; -+ -+ p += sprintf(p, " "); -+ for (j=0; j<smp_num_cpus; j++) -+ p += sprintf(p, "CPU%d ",j); -+ *p++ = '\n'; -+ -+ for (i = 0 ; i < NR_IRQS ; i++) { -+ spin_lock_irqsave(&irq_desc[i].lock, flags); -+ action = irq_desc[i].action; -+ if (!action) -+ goto end; -+ p += sprintf(p, "%3d: ",i); -+#ifndef CONFIG_SMP -+ p += sprintf(p, "%10u ", kstat_irqs(i)); -+#else -+ for (j = 0; j < smp_num_cpus; j++) -+ p += sprintf(p, "%10u ", -+ kstat.irqs[cpu_logical_map(j)][i]); -+#endif -+ p += sprintf(p, " %14s", irq_desc[i].handler->typename); -+ p += sprintf(p, " %s", action->name); -+ -+ for (action=action->next; action; action = action->next) -+ p += sprintf(p, ", %s", action->name); -+ *p++ = '\n'; -+ end: -+ spin_unlock_irqrestore(&irq_desc[i].lock, flags); -+ } -+ p += sprintf(p, "\n"); -+#ifdef notdef -+#if CONFIG_SMP -+ p += sprintf(p, "LOC: "); -+ for (j = 0; j < smp_num_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; -+} -+ -+ -+/* -+ * This should really return information about whether -+ * we should do bottom half handling etc. Right now we -+ * end up _always_ checking the bottom half, which is a -+ * waste of time and is not what some drivers would -+ * prefer. -+ */ -+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, -+ struct irqaction * action) -+{ -+ int status; -+ int cpu = smp_processor_id(); -+ -+ irq_enter(cpu, irq); -+ -+ status = 1; /* Force the "do bottom halves" bit */ -+ -+ if (!(action->flags & SA_INTERRUPT)) -+ __sti(); -+ -+ do { -+ status |= action->flags; -+ action->handler(irq, action->dev_id, regs); -+ action = action->next; -+ } while (action); -+ if (status & SA_SAMPLE_RANDOM) -+ add_interrupt_randomness(irq); -+ __cli(); -+ -+ irq_exit(cpu, irq); -+ -+ return status; -+} -+ -+/* -+ * Generic enable/disable code: this just calls -+ * down into the PIC-specific version for the actual -+ * hardware disable after having gotten the irq -+ * controller lock. -+ */ -+ -+/** -+ * disable_irq_nosync - disable an irq without waiting -+ * @irq: Interrupt to disable -+ * -+ * Disable the selected interrupt line. Disables of an interrupt -+ * stack. Unlike disable_irq(), this function does not ensure existing -+ * instances of the IRQ handler have completed before returning. -+ * -+ * This function may be called from IRQ context. -+ */ -+ -+void inline disable_irq_nosync(unsigned int irq) -+{ -+ irq_desc_t *desc = irq_desc + irq; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&desc->lock, flags); -+ if (!desc->depth++) { -+ desc->status |= IRQ_DISABLED; -+ desc->handler->disable(irq); -+ } -+ spin_unlock_irqrestore(&desc->lock, flags); -+} -+ -+/** -+ * disable_irq - disable an irq and wait for completion -+ * @irq: Interrupt to disable -+ * -+ * Disable the selected interrupt line. Disables of an interrupt -+ * stack. That is for two disables you need two enables. This -+ * function waits for any pending IRQ handlers for this interrupt -+ * to complete before returning. If you use this function while -+ * holding a resource the IRQ handler may need you will deadlock. -+ * -+ * This function may be called - with care - from IRQ context. -+ */ -+ -+void disable_irq(unsigned int irq) -+{ -+ disable_irq_nosync(irq); -+ -+ if (!local_irq_count(smp_processor_id())) { -+ do { -+ barrier(); -+ } while (irq_desc[irq].status & IRQ_INPROGRESS); -+ } -+} -+ -+/** -+ * enable_irq - enable interrupt handling on an irq -+ * @irq: Interrupt to enable -+ * -+ * Re-enables the processing of interrupts on this IRQ line -+ * providing no disable_irq calls are now in effect. -+ * -+ * This function may be called from IRQ context. -+ */ -+ -+void enable_irq(unsigned int irq) -+{ -+ irq_desc_t *desc = irq_desc + irq; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&desc->lock, flags); -+ switch (desc->depth) { -+ case 1: { -+ unsigned int status = desc->status & ~IRQ_DISABLED; -+ desc->status = status; -+ if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { -+ desc->status = status | IRQ_REPLAY; -+ hw_resend_irq(desc->handler,irq); -+ } -+ desc->handler->enable(irq); -+ /* fall-through */ -+ } -+ default: -+ desc->depth--; -+ break; -+ case 0: -+ printk(KERN_ERR "enable_irq() unbalanced from %p\n", -+ __builtin_return_address(0)); -+ } -+ spin_unlock_irqrestore(&desc->lock, flags); -+} -+ -+/* -+ * do_IRQ handles all normal device IRQ's (the special -+ * SMP cross-CPU interrupts have their own specific -+ * handlers). -+ */ -+unsigned int do_IRQ(int irq, union uml_pt_regs *regs) -+{ -+ /* -+ * 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; -+ -+ kstat.irqs[cpu][irq]++; -+ spin_lock(&desc->lock); -+ desc->handler->ack(irq); -+ /* -+ REPLAY is when Linux resends an IRQ that was dropped earlier -+ WAITING is used by probe to mark irqs that are being tested -+ */ -+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); -+ status |= IRQ_PENDING; /* we _want_ to handle it */ -+ -+ /* -+ * If the IRQ is disabled for whatever reason, we cannot -+ * use the action we have. -+ */ -+ action = NULL; -+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { -+ action = desc->action; -+ status &= ~IRQ_PENDING; /* we commit to handling */ -+ status |= IRQ_INPROGRESS; /* we are handling it */ -+ } -+ desc->status = status; -+ -+ /* -+ * If there is no IRQ handler or it was disabled, exit early. -+ Since we set PENDING, if another processor is handling -+ a different instance of this same irq, the other processor -+ will take care of it. -+ */ -+ if (!action) -+ goto out; -+ -+ /* -+ * Edge triggered interrupts need to remember -+ * pending events. -+ * This applies to any hw interrupts that allow a second -+ * instance of the same irq to arrive while we are in do_IRQ -+ * or in the handler. But the code here only handles the _second_ -+ * instance of the irq, not the third or fourth. So it is mostly -+ * useful for irq hardware that does not mask cleanly in an -+ * SMP environment. -+ */ -+ for (;;) { -+ spin_unlock(&desc->lock); -+ handle_IRQ_event(irq, (struct pt_regs *) regs, action); -+ spin_lock(&desc->lock); -+ -+ if (!(desc->status & IRQ_PENDING)) -+ break; -+ desc->status &= ~IRQ_PENDING; -+ } -+ desc->status &= ~IRQ_INPROGRESS; -+out: -+ /* -+ * The ->end() handler has to deal with interrupts which got -+ * disabled while the handler was running. -+ */ -+ desc->handler->end(irq); -+ spin_unlock(&desc->lock); -+ -+ if (softirq_pending(cpu)) -+ do_softirq(); -+ return 1; -+} -+ -+/** -+ * request_irq - allocate an interrupt line -+ * @irq: Interrupt line to allocate -+ * @handler: Function to be called when the IRQ occurs -+ * @irqflags: Interrupt type flags -+ * @devname: An ascii name for the claiming device -+ * @dev_id: A cookie passed back to the handler function -+ * -+ * This call allocates interrupt resources and enables the -+ * interrupt line and IRQ handling. From the point this -+ * call is made your handler function may be invoked. Since -+ * your handler function must clear any interrupt the board -+ * raises, you must take care both to initialise your hardware -+ * and to set up the interrupt handler in the right order. -+ * -+ * Dev_id must be globally unique. Normally the address of the -+ * device data structure is used as the cookie. Since the handler -+ * receives this value it makes sense to use it. -+ * -+ * If your interrupt is shared you must pass a non NULL dev_id -+ * as this is required when freeing the interrupt. -+ * -+ * Flags: -+ * -+ * SA_SHIRQ Interrupt is shared -+ * -+ * SA_INTERRUPT Disable local interrupts while processing -+ * -+ * SA_SAMPLE_RANDOM The interrupt can be used for entropy -+ * -+ */ -+ -+int request_irq(unsigned int irq, -+ void (*handler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, -+ const char * devname, -+ void *dev_id) -+{ -+ int retval; -+ struct irqaction * action; -+ -+#if 1 -+ /* -+ * Sanity-check: shared interrupts should REALLY pass in -+ * a real dev-ID, otherwise we'll have trouble later trying -+ * to figure out which interrupt is which (messes up the -+ * interrupt freeing logic etc). -+ */ -+ if (irqflags & SA_SHIRQ) { -+ if (!dev_id) -+ printk(KERN_ERR "Bad boy: %s (at 0x%x) called us " -+ "without a dev_id!\n", devname, (&irq)[-1]); -+ } -+#endif -+ -+ if (irq >= NR_IRQS) -+ return -EINVAL; -+ if (!handler) -+ return -EINVAL; -+ -+ action = (struct irqaction *) -+ kmalloc(sizeof(struct irqaction), GFP_KERNEL); -+ if (!action) -+ return -ENOMEM; -+ -+ action->handler = handler; -+ action->flags = irqflags; -+ action->mask = 0; -+ action->name = devname; -+ action->next = NULL; -+ action->dev_id = dev_id; -+ -+ retval = setup_irq(irq, action); -+ if (retval) -+ kfree(action); -+ return retval; -+} -+ -+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) -+{ -+ int err; -+ -+ 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 */ -+int setup_irq(unsigned int irq, struct irqaction * new) -+{ -+ int shared = 0; -+ unsigned long flags; -+ struct irqaction *old, **p; -+ irq_desc_t *desc = irq_desc + irq; -+ -+ /* -+ * Some drivers like serial.c use request_irq() heavily, -+ * so we have to be careful not to interfere with a -+ * running system. -+ */ -+ if (new->flags & SA_SAMPLE_RANDOM) { -+ /* -+ * This function might sleep, we want to call it first, -+ * outside of the atomic block. -+ * Yes, this might clear the entropy pool if the wrong -+ * driver is attempted to be loaded, without actually -+ * installing a new handler, but is this really a problem, -+ * only the sysadmin is able to do this. -+ */ -+ rand_initialize_irq(irq); -+ } -+ -+ /* -+ * The following block of code has to be executed atomically -+ */ -+ spin_lock_irqsave(&desc->lock,flags); -+ p = &desc->action; -+ if ((old = *p) != NULL) { -+ /* Can't share interrupts unless both agree to */ -+ if (!(old->flags & new->flags & SA_SHIRQ)) { -+ spin_unlock_irqrestore(&desc->lock,flags); -+ return -EBUSY; -+ } -+ -+ /* add new interrupt at end of irq queue */ -+ do { -+ p = &old->next; -+ old = *p; -+ } while (old); -+ shared = 1; -+ } -+ -+ *p = new; -+ -+ if (!shared) { -+ desc->depth = 0; -+ desc->status &= ~IRQ_DISABLED; -+ desc->handler->startup(irq); -+ } -+ spin_unlock_irqrestore(&desc->lock,flags); -+ -+ register_irq_proc(irq); -+ return 0; -+} -+ -+/** -+ * free_irq - free an interrupt -+ * @irq: Interrupt line to free -+ * @dev_id: Device identity to free -+ * -+ * Remove an interrupt handler. The handler is removed and if the -+ * interrupt line is no longer in use by any driver it is disabled. -+ * On a shared IRQ the caller must ensure the interrupt is disabled -+ * on the card it drives before calling this function. The function -+ * does not return until any executing interrupts for this IRQ -+ * have completed. -+ * -+ * This function may be called from interrupt context. -+ * -+ * Bugs: Attempting to free an irq in a handler for the same irq hangs -+ * the machine. -+ */ -+ -+void free_irq(unsigned int irq, void *dev_id) -+{ -+ irq_desc_t *desc; -+ struct irqaction **p; -+ unsigned long flags; -+ -+ if (irq >= NR_IRQS) -+ return; -+ -+ desc = irq_desc + irq; -+ spin_lock_irqsave(&desc->lock,flags); -+ p = &desc->action; -+ for (;;) { -+ struct irqaction * action = *p; -+ if (action) { -+ struct irqaction **pp = p; -+ p = &action->next; -+ if (action->dev_id != dev_id) -+ continue; -+ -+ /* Found it - now remove it from the list of entries */ -+ *pp = action->next; -+ if (!desc->action) { -+ desc->status |= IRQ_DISABLED; -+ desc->handler->shutdown(irq); -+ } -+ free_irq_by_irq_and_dev(irq, dev_id); -+ spin_unlock_irqrestore(&desc->lock,flags); -+ -+#ifdef CONFIG_SMP -+ /* Wait to make sure it's not being used on another CPU */ -+ while (desc->status & IRQ_INPROGRESS) -+ barrier(); -+#endif -+ kfree(action); -+ return; -+ } -+ printk(KERN_ERR "Trying to free free IRQ%d\n",irq); -+ spin_unlock_irqrestore(&desc->lock,flags); -+ return; -+ } -+} -+ -+/* These are initialized by sysctl_init, which is called from init/main.c */ -+static struct proc_dir_entry * root_irq_dir; -+static struct proc_dir_entry * irq_dir [NR_IRQS]; -+static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; -+ -+/* These are read and written as longs, so a read won't see a partial write -+ * even during a race. -+ */ -+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; -+ -+#define HEX_DIGITS 8 -+ -+static int irq_affinity_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ if (count < HEX_DIGITS+1) -+ return -EINVAL; -+ return sprintf (page, "%08lx\n", irq_affinity[(long)data]); -+} -+ -+static unsigned int parse_hex_value (const char *buffer, -+ unsigned long count, unsigned long *ret) -+{ -+ unsigned char hexnum [HEX_DIGITS]; -+ unsigned long value; -+ int i; -+ -+ if (!count) -+ return -EINVAL; -+ if (count > HEX_DIGITS) -+ count = HEX_DIGITS; -+ if (copy_from_user(hexnum, buffer, count)) -+ return -EFAULT; -+ -+ /* -+ * Parse the first 8 characters as a hex string, any non-hex char -+ * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. -+ */ -+ value = 0; -+ -+ for (i = 0; i < count; i++) { -+ unsigned int c = hexnum[i]; -+ -+ switch (c) { -+ case '0' ... '9': c -= '0'; break; -+ case 'a' ... 'f': c -= 'a'-10; break; -+ case 'A' ... 'F': c -= 'A'-10; break; -+ default: -+ goto out; -+ } -+ value = (value << 4) | c; -+ } -+out: -+ *ret = value; -+ return 0; -+} -+ -+static int irq_affinity_write_proc (struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ int irq = (long) data, full_count = count, err; -+ unsigned long new_value; -+ -+ if (!irq_desc[irq].handler->set_affinity) -+ return -EIO; -+ -+ err = parse_hex_value(buffer, count, &new_value); -+ -+#if CONFIG_SMP -+ /* -+ * Do not allow disabling IRQs completely - it's a too easy -+ * way to make the system unusable accidentally :-) At least -+ * one online CPU still has to be targeted. -+ */ -+ if (!(new_value & cpu_online_map)) -+ return -EINVAL; -+#endif -+ -+ irq_affinity[irq] = new_value; -+ irq_desc[irq].handler->set_affinity(irq, new_value); -+ -+ return full_count; -+} -+ -+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ unsigned long *mask = (unsigned long *) data; -+ if (count < HEX_DIGITS+1) -+ return -EINVAL; -+ return sprintf (page, "%08lx\n", *mask); -+} -+ -+static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ unsigned long *mask = (unsigned long *) data, full_count = count, err; -+ unsigned long new_value; -+ -+ err = parse_hex_value(buffer, count, &new_value); -+ if (err) -+ return err; -+ -+ *mask = new_value; -+ return full_count; -+} -+ -+#define MAX_NAMELEN 10 -+ -+static void register_irq_proc (unsigned int irq) -+{ -+ struct proc_dir_entry *entry; -+ char name [MAX_NAMELEN]; -+ -+ if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || -+ irq_dir[irq]) -+ return; -+ -+ memset(name, 0, MAX_NAMELEN); -+ sprintf(name, "%d", irq); -+ -+ /* create /proc/irq/1234 */ -+ irq_dir[irq] = proc_mkdir(name, root_irq_dir); -+ -+ /* create /proc/irq/1234/smp_affinity */ -+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); -+ -+ entry->nlink = 1; -+ entry->data = (void *)(long)irq; -+ entry->read_proc = irq_affinity_read_proc; -+ entry->write_proc = irq_affinity_write_proc; -+ -+ smp_affinity_entry[irq] = entry; -+} -+ -+/* Read and written as a long */ -+unsigned long prof_cpu_mask = -1; -+ -+void __init init_irq_proc (void) -+{ -+ struct proc_dir_entry *entry; -+ int i; -+ -+ /* create /proc/irq */ -+ root_irq_dir = proc_mkdir("irq", 0); -+ -+ /* create /proc/irq/prof_cpu_mask */ -+ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); -+ -+ entry->nlink = 1; -+ entry->data = (void *)&prof_cpu_mask; -+ entry->read_proc = prof_cpu_mask_read_proc; -+ entry->write_proc = prof_cpu_mask_write_proc; -+ -+ /* -+ * Create entries for all existing IRQs. -+ */ -+ for (i = 0; i < NR_IRQS; i++) -+ register_irq_proc(i); -+} -+ -+static spinlock_t irq_spinlock = SPIN_LOCK_UNLOCKED; -+ -+unsigned long irq_lock(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&irq_spinlock, flags); -+ return(flags); -+} -+ -+void irq_unlock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&irq_spinlock, flags); -+} -+ -+unsigned long probe_irq_on(void) -+{ -+ return(0); -+} -+ -+int probe_irq_off(unsigned long val) -+{ -+ return(0); -+} -+ -+static unsigned int startup_SIGIO_irq(unsigned int irq) -+{ -+ return(0); -+} -+ -+static void shutdown_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void enable_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void disable_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void mask_and_ack_SIGIO(unsigned int irq) -+{ -+} -+ -+static void end_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static unsigned int startup_SIGVTALRM_irq(unsigned int irq) -+{ -+ return(0); -+} -+ -+static void shutdown_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void enable_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void disable_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void mask_and_ack_SIGVTALRM(unsigned int irq) -+{ -+} -+ -+static void end_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static struct hw_interrupt_type SIGIO_irq_type = { -+ "SIGIO", -+ startup_SIGIO_irq, -+ shutdown_SIGIO_irq, -+ enable_SIGIO_irq, -+ disable_SIGIO_irq, -+ mask_and_ack_SIGIO, -+ end_SIGIO_irq, -+ NULL -+}; -+ -+static struct hw_interrupt_type SIGVTALRM_irq_type = { -+ "SIGVTALRM", -+ startup_SIGVTALRM_irq, -+ shutdown_SIGVTALRM_irq, -+ enable_SIGVTALRM_irq, -+ disable_SIGVTALRM_irq, -+ mask_and_ack_SIGVTALRM, -+ end_SIGVTALRM_irq, -+ NULL -+}; -+ -+void __init init_IRQ(void) -+{ -+ int i; -+ -+ irq_desc[TIMER_IRQ].status = IRQ_DISABLED; -+ irq_desc[TIMER_IRQ].action = 0; -+ irq_desc[TIMER_IRQ].depth = 1; -+ irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type; -+ enable_irq(TIMER_IRQ); -+ for(i=1;i<NR_IRQS;i++){ -+ irq_desc[i].status = IRQ_DISABLED; -+ irq_desc[i].action = 0; -+ irq_desc[i].depth = 1; -+ irq_desc[i].handler = &SIGIO_irq_type; -+ enable_irq(i); -+ } -+ init_irq_signals(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 -Naur -X ../exclude-files orig/arch/um/kernel/irq_user.c um/arch/um/kernel/irq_user.c ---- orig/arch/um/kernel/irq_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/irq_user.c Sun Dec 22 15:49:46 2002 -@@ -0,0 +1,427 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <fcntl.h> -+#include <signal.h> -+#include <string.h> -+#include <sys/poll.h> -+#include <sys/types.h> -+#include <sys/time.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_user.h" -+#include "sigio.h" -+#include "irq_user.h" -+#include "os.h" -+ -+struct irq_fd { -+ struct irq_fd *next; -+ void *id; -+ int fd; -+ int type; -+ int irq; -+ int pid; -+ int events; -+ int current_events; -+ int freed; -+}; -+ -+static struct irq_fd *active_fds = NULL; -+static struct irq_fd **last_irq_ptr = &active_fds; -+ -+static struct pollfd *pollfds = NULL; -+static int pollfds_num = 0; -+static int pollfds_size = 0; -+ -+extern int io_count, intr_count; -+ -+void sigio_handler(int sig, union uml_pt_regs *regs) -+{ -+ struct irq_fd *irq_fd, *next; -+ int i, n; -+ -+ if(smp_sigio_handler()) return; -+ while(1){ -+ if((n = poll(pollfds, pollfds_num, 0)) < 0){ -+ if(errno == EINTR) continue; -+ printk("sigio_handler : poll returned %d, " -+ "errno = %d\n", n, errno); -+ break; -+ } -+ if(n == 0) break; -+ -+ irq_fd = active_fds; -+ for(i = 0; i < pollfds_num; i++){ -+ if(pollfds[i].revents != 0){ -+ irq_fd->current_events = pollfds[i].revents; -+ pollfds[i].fd = -1; -+ } -+ irq_fd = irq_fd->next; -+ } -+ -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ -+ next = irq_fd->next; -+ if(irq_fd->current_events != 0){ -+ irq_fd->current_events = 0; -+ do_IRQ(irq_fd->irq, regs); -+ -+ /* This is here because the next irq may be -+ * freed in the handler. If a console goes -+ * away, both the read and write irqs will be -+ * freed. After do_IRQ, ->next will point to -+ * a good IRQ. -+ * Irqs can't be freed inside their handlers, -+ * so the next best thing is to have them -+ * marked as needing freeing, so that they -+ * can be freed here. -+ */ -+ next = irq_fd->next; -+ if(irq_fd->freed) -+ free_irq(irq_fd->irq, irq_fd->id); -+ } -+ } -+ } -+} -+ -+int activate_ipi(int fd, int pid) -+{ -+ return(os_set_fd_async(fd, pid)); -+} -+ -+static void maybe_sigio_broken(int fd, int type) -+{ -+ if(isatty(fd)){ -+ if((type == IRQ_WRITE) && !pty_output_sigio){ -+ write_sigio_workaround(); -+ add_sigio_fd(fd, 0); -+ } -+ else if((type == IRQ_READ) && !pty_close_sigio){ -+ write_sigio_workaround(); -+ add_sigio_fd(fd, 1); -+ } -+ } -+} -+ -+int activate_fd(int irq, int fd, int type, void *dev_id) -+{ -+ struct pollfd *tmp_pfd; -+ struct irq_fd *new_fd, *irq_fd; -+ unsigned long flags; -+ int pid, events, err, n, size; -+ -+ pid = os_getpid(); -+ err = os_set_fd_async(fd, pid); -+ if(err < 0) -+ goto out; -+ -+ new_fd = um_kmalloc(sizeof(*new_fd)); -+ err = -ENOMEM; -+ if(new_fd == NULL) -+ goto out; -+ -+ if(type == IRQ_READ) events = POLLIN | POLLPRI; -+ else events = POLLOUT; -+ *new_fd = ((struct irq_fd) { .next = NULL, -+ .id = dev_id, -+ .fd = fd, -+ .type = type, -+ .irq = irq, -+ .pid = pid, -+ .events = events, -+ .current_events = 0, -+ .freed = 0 } ); -+ -+ /* Critical section - locked by a spinlock because this stuff can -+ * be changed from interrupt handlers. The stuff above is done -+ * outside the lock because it allocates memory. -+ */ -+ -+ /* Actually, it only looks like it can be called from interrupt -+ * context. The culprit is reactivate_fd, which calls -+ * maybe_sigio_broken, which calls write_sigio_workaround, -+ * which calls activate_fd. However, write_sigio_workaround should -+ * only be called once, at boot time. That would make it clear that -+ * this is called only from process context, and can be locked with -+ * a semaphore. -+ */ -+ flags = irq_lock(); -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ -+ if((irq_fd->fd == fd) && (irq_fd->type == type)){ -+ printk("Registering fd %d twice\n", fd); -+ printk("Irqs : %d, %d\n", irq_fd->irq, irq); -+ printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id); -+ goto out_unlock; -+ } -+ } -+ -+ n = pollfds_num; -+ if(n == pollfds_size){ -+ while(1){ -+ /* Here we have to drop the lock in order to call -+ * kmalloc, which might sleep. If something else -+ * came in and changed the pollfds array, we free -+ * the buffer and try again. -+ */ -+ irq_unlock(flags); -+ size = (pollfds_num + 1) * sizeof(pollfds[0]); -+ tmp_pfd = um_kmalloc(size); -+ flags = irq_lock(); -+ if(tmp_pfd == NULL) -+ goto out_unlock; -+ if(n == pollfds_size) -+ break; -+ kfree(tmp_pfd); -+ } -+ if(pollfds != NULL){ -+ memcpy(tmp_pfd, pollfds, -+ sizeof(pollfds[0]) * pollfds_size); -+ kfree(pollfds); -+ } -+ pollfds = tmp_pfd; -+ pollfds_size++; -+ } -+ -+ if(type == IRQ_WRITE) -+ fd = -1; -+ -+ pollfds[pollfds_num] = ((struct pollfd) { .fd = fd, -+ .events = events, -+ .revents = 0 }); -+ pollfds_num++; -+ -+ *last_irq_ptr = new_fd; -+ last_irq_ptr = &new_fd->next; -+ -+ irq_unlock(flags); -+ -+ /* This calls activate_fd, so it has to be outside the critical -+ * section. -+ */ -+ maybe_sigio_broken(fd, type); -+ -+ return(0); -+ -+ out_unlock: -+ irq_unlock(flags); -+ kfree(new_fd); -+ out: -+ return(err); -+} -+ -+static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) -+{ -+ struct irq_fd **prev; -+ unsigned long flags; -+ int i = 0; -+ -+ flags = irq_lock(); -+ prev = &active_fds; -+ while(*prev != NULL){ -+ if((*test)(*prev, arg)){ -+ struct irq_fd *old_fd = *prev; -+ if((pollfds[i].fd != -1) && -+ (pollfds[i].fd != (*prev)->fd)){ -+ printk("free_irq_by_cb - mismatch between " -+ "active_fds and pollfds, fd %d vs %d\n", -+ (*prev)->fd, pollfds[i].fd); -+ goto out; -+ } -+ memcpy(&pollfds[i], &pollfds[i + 1], -+ (pollfds_num - i - 1) * sizeof(pollfds[0])); -+ pollfds_num--; -+ if(last_irq_ptr == &old_fd->next) -+ last_irq_ptr = prev; -+ *prev = (*prev)->next; -+ if(old_fd->type == IRQ_WRITE) -+ ignore_sigio_fd(old_fd->fd); -+ kfree(old_fd); -+ continue; -+ } -+ prev = &(*prev)->next; -+ i++; -+ } -+ out: -+ irq_unlock(flags); -+} -+ -+struct irq_and_dev { -+ int irq; -+ void *dev; -+}; -+ -+static int same_irq_and_dev(struct irq_fd *irq, void *d) -+{ -+ struct irq_and_dev *data = d; -+ -+ return((irq->irq == data->irq) && (irq->id == data->dev)); -+} -+ -+void free_irq_by_irq_and_dev(int irq, void *dev) -+{ -+ struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq, -+ .dev = dev }); -+ -+ free_irq_by_cb(same_irq_and_dev, &data); -+} -+ -+static int same_fd(struct irq_fd *irq, void *fd) -+{ -+ return(irq->fd == *((int *) fd)); -+} -+ -+void free_irq_by_fd(int fd) -+{ -+ free_irq_by_cb(same_fd, &fd); -+} -+ -+static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) -+{ -+ struct irq_fd *irq; -+ int i = 0; -+ -+ for(irq=active_fds; irq != NULL; irq = irq->next){ -+ if((irq->fd == fd) && (irq->irq == irqnum)) break; -+ i++; -+ } -+ if(irq == NULL){ -+ printk("find_irq_by_fd doesn't have descriptor %d\n", fd); -+ goto out; -+ } -+ if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){ -+ printk("find_irq_by_fd - mismatch between active_fds and " -+ "pollfds, fd %d vs %d, need %d\n", irq->fd, -+ pollfds[i].fd, fd); -+ irq = NULL; -+ goto out; -+ } -+ *index_out = i; -+ out: -+ return(irq); -+} -+ -+void free_irq_later(int irq, void *dev_id) -+{ -+ struct irq_fd *irq_fd; -+ unsigned long flags; -+ -+ flags = irq_lock(); -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ -+ if((irq_fd->irq == irq) && (irq_fd->id == dev_id)) -+ break; -+ } -+ if(irq_fd == NULL){ -+ printk("free_irq_later found no irq, irq = %d, " -+ "dev_id = 0x%p\n", irq, dev_id); -+ goto out; -+ } -+ irq_fd->freed = 1; -+ out: -+ irq_unlock(flags); -+} -+ -+void reactivate_fd(int fd, int irqnum) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ int i; -+ -+ flags = irq_lock(); -+ irq = find_irq_by_fd(fd, irqnum, &i); -+ if(irq == NULL){ -+ irq_unlock(flags); -+ return; -+ } -+ -+ pollfds[i].fd = irq->fd; -+ -+ irq_unlock(flags); -+ -+ /* This calls activate_fd, so it has to be outside the critical -+ * section. -+ */ -+ maybe_sigio_broken(fd, irq->type); -+} -+ -+void deactivate_fd(int fd, int irqnum) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ int i; -+ -+ flags = irq_lock(); -+ irq = find_irq_by_fd(fd, irqnum, &i); -+ if(irq == NULL) -+ goto out; -+ pollfds[i].fd = -1; -+ out: -+ irq_unlock(flags); -+} -+ -+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); -+ } -+ } -+} -+ -+void forward_interrupts(int pid) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ -+ 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); -+ } -+ } -+ irq->pid = pid; -+ } -+ irq_unlock(flags); -+} -+ -+void init_irq_signals(int on_sigstack) -+{ -+ __sighandler_t h; -+ int flags; -+ -+ flags = on_sigstack ? SA_ONSTACK : 0; -+ if(timer_irq_inited) h = (__sighandler_t) alarm_handler; -+ else h = boot_timer_handler; -+ -+ set_handler(SIGVTALRM, h, flags | SA_RESTART, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); -+ set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ signal(SIGWINCH, SIG_IGN); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/ksyms.c um/arch/um/kernel/ksyms.c ---- orig/arch/um/kernel/ksyms.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/ksyms.c Tue Dec 17 13:29:43 2002 -@@ -0,0 +1,94 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/module.h" -+#include "linux/string.h" -+#include "linux/smp_lock.h" -+#include "linux/spinlock.h" -+#include "asm/current.h" -+#include "asm/delay.h" -+#include "asm/processor.h" -+#include "asm/unistd.h" -+#include "asm/pgalloc.h" -+#include "asm/pgtable.h" -+#include "asm/page.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+#include "helper.h" -+ -+EXPORT_SYMBOL(stop); -+EXPORT_SYMBOL(strtok); -+EXPORT_SYMBOL(uml_physmem); -+EXPORT_SYMBOL(set_signals); -+EXPORT_SYMBOL(get_signals); -+EXPORT_SYMBOL(kernel_thread); -+EXPORT_SYMBOL(__const_udelay); -+EXPORT_SYMBOL(__udelay); -+EXPORT_SYMBOL(sys_waitpid); -+EXPORT_SYMBOL(task_size); -+EXPORT_SYMBOL(flush_tlb_range); -+EXPORT_SYMBOL(host_task_size); -+EXPORT_SYMBOL(arch_validate); -+ -+EXPORT_SYMBOL(region_pa); -+EXPORT_SYMBOL(region_va); -+EXPORT_SYMBOL(phys_mem_map); -+EXPORT_SYMBOL(page_mem_map); -+EXPORT_SYMBOL(high_physmem); -+EXPORT_SYMBOL(empty_zero_page); -+EXPORT_SYMBOL(um_virt_to_phys); -+EXPORT_SYMBOL(mode_tt); -+EXPORT_SYMBOL(handle_page_fault); -+ -+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_pipe); -+EXPORT_SYMBOL(os_file_type); -+EXPORT_SYMBOL(os_close_file); -+EXPORT_SYMBOL(helper_wait); -+EXPORT_SYMBOL(os_shutdown_socket); -+EXPORT_SYMBOL(os_connect_socket); -+EXPORT_SYMBOL(run_helper); -+EXPORT_SYMBOL(start_thread); -+EXPORT_SYMBOL(dump_thread); -+ -+/* This is here because UML expands open to sys_open, not to a system -+ * call instruction. -+ */ -+EXPORT_SYMBOL(sys_open); -+EXPORT_SYMBOL(sys_lseek); -+EXPORT_SYMBOL(sys_read); -+EXPORT_SYMBOL(sys_wait4); -+ -+#ifdef CONFIG_SMP -+ -+/* required for SMP */ -+ -+extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); -+EXPORT_SYMBOL_NOVERS(__write_lock_failed); -+ -+extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); -+EXPORT_SYMBOL_NOVERS(__read_lock_failed); -+ -+EXPORT_SYMBOL(kernel_flag_cacheline); -+EXPORT_SYMBOL(smp_num_cpus); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/mem.c um/arch/um/kernel/mem.c ---- orig/arch/um/kernel/mem.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/mem.c Fri Jan 31 20:18:08 2003 -@@ -0,0 +1,850 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/types.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 "asm/page.h" -+#include "asm/pgtable.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 "uml_uaccess.h" -+ -+/* 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"; -+ -+/* Changed during early boot */ -+static unsigned long totalram_pages = 0; -+ -+extern char __init_begin, __init_end; -+extern long physmem_size; -+ -+#ifdef CONFIG_SMP -+/* Not changed by UML */ -+mmu_gather_t mmu_gathers[NR_CPUS]; -+#endif -+ -+/* Changed during early boot */ -+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; -+ -+static void map_cb(void *unused) -+{ -+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); -+} -+ -+void unmap_physmem(void) -+{ -+ os_unmap_memory((void *) brk_end, uml_reserved - brk_end); -+} -+ -+extern char __binary_start; -+ -+void mem_init(void) -+{ -+ unsigned long start; -+ -+#ifdef CONFIG_HIGHMEM -+ highmem_start_page = phys_page(__pa(high_physmem)); -+#endif -+ -+ /* clear the zero-page */ -+ memset((void *) empty_zero_page, 0, PAGE_SIZE); -+ -+ /* Map in the area just after the brk now that kmalloc is about -+ * to be turned on. -+ */ -+ brk_end = (unsigned long) UML_ROUND_UP(sbrk(0)); -+ map_cb(NULL); -+ initial_thread_cb(map_cb, NULL); -+ free_bootmem(__pa(brk_end), uml_reserved - brk_end); -+ uml_reserved = brk_end; -+ -+ /* Fill in any hole at the start of the binary */ -+ start = (unsigned long) &__binary_start; -+ if(uml_physmem != start){ -+ map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem, -+ 1, 1, 0); -+ } -+ -+ /* this will put all low memory onto the freelists */ -+ totalram_pages = free_all_bootmem(); -+ totalram_pages += highmem >> PAGE_SHIFT; -+ max_mapnr = totalram_pages; -+ num_physpages = 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; -+} -+ -+#if CONFIG_HIGHMEM -+/* Changed during early boot */ -+pte_t *kmap_pte; -+pgprot_t kmap_prot; -+ -+#define kmap_get_fixmap_pte(vaddr) \ -+ pte_offset(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; -+} -+#endif /* CONFIG_HIGHMEM */ -+ -+static void __init fixrange_init(unsigned long start, unsigned long end, -+ pgd_t *pgd_base) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ int i, j; -+ unsigned long vaddr; -+ -+ vaddr = start; -+ i = __pgd_offset(vaddr); -+ j = __pmd_offset(vaddr); -+ pgd = pgd_base + i; -+ -+ for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { -+ pmd = (pmd_t *)pgd; -+ for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { -+ if (pmd_none(*pmd)) { -+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); -+ set_pmd(pmd, __pmd(_KERNPG_TABLE + -+ (unsigned long) __pa(pte))); -+ if (pte != pte_offset(pmd, 0)) -+ BUG(); -+ } -+ vaddr += PMD_SIZE; -+ } -+ j = 0; -+ } -+} -+ -+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); -+} -+ -+DECLARE_MUTEX(regions_sem); -+ -+static int setup_one_range(int fd, char *driver, unsigned long start, -+ unsigned long pfn, int len, -+ struct mem_region *region) -+{ -+ int i; -+ -+ down(®ions_sem); -+ for(i = 0; i < NREGIONS; i++){ -+ if(regions[i] == NULL) break; -+ } -+ if(i == NREGIONS){ -+ printk("setup_one_range : no free regions\n"); -+ i = -1; -+ goto out; -+ } -+ -+ if(fd == -1) -+ fd = create_mem_file(len); -+ -+ if(region == NULL){ -+ region = alloc_bootmem_low_pages(sizeof(*region)); -+ if(region == NULL) -+ panic("Failed to allocating mem_region"); -+ } -+ -+ *region = ((struct mem_region) { .driver = driver, -+ .start_pfn = pfn, -+ .start = start, -+ .len = len, -+ .fd = fd } ); -+ regions[i] = region; -+ out: -+ up(®ions_sem); -+ return(i); -+} -+ -+#ifdef CONFIG_HIGHMEM -+static void init_highmem(void) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long vaddr; -+ -+ /* -+ * Permanent kmaps: -+ */ -+ vaddr = PKMAP_BASE; -+ fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir); -+ -+ pgd = swapper_pg_dir + __pgd_offset(vaddr); -+ pmd = pmd_offset(pgd, vaddr); -+ pte = pte_offset(pmd, vaddr); -+ pkmap_page_table = pte; -+ -+ 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); -+ atomic_set(&page->count, 1); -+ __free_page(page); -+ } -+ phys += cur; -+ len -= cur; -+ } while(len > 0); -+} -+#endif -+ -+void paging_init(void) -+{ -+ struct mem_region *region; -+ unsigned long zones_size[MAX_NR_ZONES], start, end, vaddr; -+ int i, index; -+ -+ 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[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 -+ * created - mappings will be set by set_fixmap(): -+ */ -+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; -+ fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir); -+ -+#if CONFIG_HIGHMEM -+ init_highmem(); -+ setup_highmem(highmem); -+#endif -+} -+ -+/* Changed by meminfo_compat, which is a setup */ -+static int meminfo_22 = 0; -+ -+static int meminfo_compat(char *str) -+{ -+ meminfo_22 = 1; -+ return(1); -+} -+ -+__setup("22_meminfo", meminfo_compat); -+ -+void si_meminfo(struct sysinfo *val) -+{ -+ val->totalram = totalram_pages; -+ val->sharedram = 0; -+ val->freeram = nr_free_pages(); -+ val->bufferram = atomic_read(&buffermem_pages); -+ val->totalhigh = highmem >> PAGE_SHIFT; -+ val->freehigh = nr_free_highpages(); -+ val->mem_unit = PAGE_SIZE; -+ if(meminfo_22){ -+ val->freeram <<= PAGE_SHIFT; -+ val->bufferram <<= PAGE_SHIFT; -+ val->totalram <<= PAGE_SHIFT; -+ val->sharedram <<= PAGE_SHIFT; -+ } -+} -+ -+pte_t __bad_page(void) -+{ -+ clear_page(empty_bad_page); -+ return pte_mkdirty(mk_pte((struct page *) empty_bad_page, -+ PAGE_SHARED)); -+} -+ -+/* This can't do anything because nothing in the kernel image can be freed -+ * since it's not in kernel physical memory. -+ */ -+ -+void free_initmem(void) -+{ -+} -+ -+#ifdef CONFIG_BLK_DEV_INITRD -+ -+void free_initrd_mem(unsigned long start, unsigned long end) -+{ -+ if (start < end) -+ printk ("Freeing initrd memory: %ldk freed\n", -+ (end - start) >> 10); -+ for (; start < end; start += PAGE_SIZE) { -+ ClearPageReserved(virt_to_page(start)); -+ set_page_count(virt_to_page(start), 1); -+ free_page(start); -+ totalram_pages++; -+ } -+} -+ -+#endif -+ -+int do_check_pgt_cache(int low, int high) -+{ -+ int freed = 0; -+ if(pgtable_cache_size > high) { -+ do { -+ if (pgd_quicklist) { -+ free_pgd_slow(get_pgd_fast()); -+ freed++; -+ } -+ if (pmd_quicklist) { -+ pmd_free_slow(pmd_alloc_one_fast(NULL, 0)); -+ freed++; -+ } -+ if (pte_quicklist) { -+ pte_free_slow(pte_alloc_one_fast(NULL, 0)); -+ freed++; -+ } -+ } while(pgtable_cache_size > low); -+ } -+ return freed; -+} -+ -+void show_mem(void) -+{ -+ int i, total = 0, reserved = 0; -+ int shared = 0, cached = 0; -+ int highmem = 0; -+ -+ printk("Mem-info:\n"); -+ show_free_areas(); -+ printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); -+ i = max_mapnr; -+ while(i-- > 0) { -+ total++; -+ if(PageHighMem(mem_map + i)) -+ highmem++; -+ if(PageReserved(mem_map + i)) -+ reserved++; -+ else if(PageSwapCache(mem_map + i)) -+ cached++; -+ else if(page_count(mem_map + i)) -+ shared += page_count(mem_map + i) - 1; -+ } -+ printk("%d pages of RAM\n", total); -+ printk("%d pages of HIGHMEM\n", highmem); -+ printk("%d reserved pages\n", reserved); -+ printk("%d pages shared\n", shared); -+ printk("%d pages swap cached\n", cached); -+ printk("%ld pages in page table cache\n", pgtable_cache_size); -+ show_buffers(); -+} -+ -+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); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/mem_user.c um/arch/um/kernel/mem_user.c ---- orig/arch/um/kernel/mem_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/mem_user.c Thu Mar 6 16:05:21 2003 -@@ -0,0 +1,232 @@ -+/* -+ * arch/um/kernel/mem_user.c -+ * -+ * BRIEF MODULE DESCRIPTION -+ * user side memory routines for supporting IO memory inside user mode linux -+ * -+ * Copyright (C) 2001 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stddef.h> -+#include <stdarg.h> -+#include <unistd.h> -+#include <fcntl.h> -+#include <errno.h> -+#include <string.h> -+#include <sys/stat.h> -+#include <sys/types.h> -+#include <sys/mman.h> -+#include "kern_util.h" -+#include "user.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "init.h" -+#include "os.h" -+#include "tempfile.h" -+ -+extern struct mem_region physmem_region; -+ -+#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" -+ -+int create_mem_file(unsigned long len) -+{ -+ int fd; -+ char zero; -+ -+ fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); -+ if (fchmod(fd, 0777) < 0){ -+ perror("fchmod"); -+ exit(1); -+ } -+ if(os_seek_file(fd, len) < 0){ -+ perror("lseek"); -+ exit(1); -+ } -+ zero = 0; -+ if(write(fd, &zero, 1) != 1){ -+ perror("write"); -+ 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) -+{ -+ 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"); -+ exit(1); -+ } -+ return(0); -+} -+ -+static int __init parse_iomem(char *str, int *add) -+{ -+ struct stat64 buf; -+ char *file, *driver; -+ int fd; -+ -+ driver = str; -+ file = strchr(str,','); -+ if(file == NULL){ -+ printf("parse_iomem : failed to parse iomem\n"); -+ return(1); -+ } -+ *file = '\0'; -+ file++; -+ fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printf("parse_iomem - Couldn't open io file, errno = %d\n", -+ errno); -+ return(1); -+ } -+ if(fstat64(fd, &buf) < 0) { -+ printf("parse_iomem - cannot fstat file, errno = %d\n", errno); -+ return(1); -+ } -+ add_iomem(driver, fd, buf.st_size); -+ return(0); -+} -+ -+__uml_setup("iomem=", parse_iomem, -+"iomem=<name>,<file>\n" -+" 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){ -+ if(must_succeed) -+ panic("protect failed, errno = %d", errno); -+ else return(-errno); -+ } -+ 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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/mprot.h um/arch/um/kernel/mprot.h ---- orig/arch/um/kernel/mprot.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/mprot.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,6 @@ -+#ifndef __MPROT_H__ -+#define __MPROT_H__ -+ -+extern void no_access(unsigned long addr, unsigned int len); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/kernel/process.c um/arch/um/kernel/process.c ---- orig/arch/um/kernel/process.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/process.c Fri Jan 17 22:05:48 2003 -@@ -0,0 +1,287 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <signal.h> -+#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> -+#include <asm/sigcontext.h> -+#include <asm/unistd.h> -+#include <asm/page.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+#include "irq_user.h" -+#include "ptrace_user.h" -+#include "time_user.h" -+#include "init.h" -+#include "os.h" -+#include "uml-config.h" -+#include "choose-mode.h" -+#include "mode.h" -+#ifdef UML_CONFIG_MODE_SKAS -+#include "skas.h" -+#include "skas_ptrace.h" -+#endif -+ -+void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) -+{ -+ int flags = 0, pages; -+ -+ if(sig_stack != NULL){ -+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; -+ set_sigstack(sig_stack, pages * page_size()); -+ flags = SA_ONSTACK; -+ } -+ if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1); -+} -+ -+void init_new_thread_signals(int altstack) -+{ -+ int flags = altstack ? SA_ONSTACK : 0; -+ -+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGFPE, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGILL, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, -+ 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); -+} -+ -+struct tramp { -+ int (*tramp)(void *); -+ void *tramp_data; -+ unsigned long temp_stack; -+ int flags; -+ int pid; -+}; -+ -+/* See above for why sigkill is here */ -+ -+int sigkill = SIGKILL; -+ -+int outer_tramp(void *arg) -+{ -+ struct tramp *t; -+ int sig = sigkill; -+ -+ t = arg; -+ t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2, -+ t->flags, t->tramp_data); -+ if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); -+ kill(os_getpid(), sig); -+ _exit(0); -+} -+ -+int start_fork_tramp(void *thread_arg, unsigned long temp_stack, -+ int clone_flags, int (*tramp)(void *)) -+{ -+ struct tramp arg; -+ unsigned long sp; -+ int new_pid, status, err; -+ -+ /* The trampoline will run on the temporary stack */ -+ sp = stack_sp(temp_stack); -+ -+ clone_flags |= CLONE_FILES | SIGCHLD; -+ -+ arg.tramp = tramp; -+ arg.tramp_data = thread_arg; -+ arg.temp_stack = temp_stack; -+ arg.flags = clone_flags; -+ -+ /* 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)) ; -+ 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"); -+ -+ return(arg.pid); -+} -+ -+void suspend_new_thread(int fd) -+{ -+ char c; -+ -+ os_stop_process(os_getpid()); -+ -+ if(read(fd, &c, sizeof(c)) != sizeof(c)) -+ panic("read failed in suspend_new_thread"); -+} -+ -+static int ptrace_child(void *arg) -+{ -+ int pid = os_getpid(); -+ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ perror("ptrace"); -+ os_kill_process(pid, 0); -+ } -+ os_stop_process(pid); -+ _exit(os_getpid() == pid); -+} -+ -+static int start_ptraced_child(void **stack_out) -+{ -+ void *stack; -+ unsigned long sp; -+ int pid, n, status; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if(stack == MAP_FAILED) -+ panic("check_ptrace : mmap failed, errno = %d", errno); -+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); -+ pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); -+ if(pid < 0) -+ panic("check_ptrace : clone failed, errno = %d", errno); -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0) -+ panic("check_ptrace : wait failed, errno = %d", errno); -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) -+ panic("check_ptrace : expected SIGSTOP, got status = %d", -+ status); -+ -+ *stack_out = stack; -+ return(pid); -+} -+ -+static void stop_ptraced_child(int pid, void *stack, int exitcode) -+{ -+ int status, n; -+ -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) -+ panic("check_ptrace : ptrace failed, errno = %d", errno); -+ n = waitpid(pid, &status, 0); -+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) -+ panic("check_ptrace : child exited with status 0x%x", status); -+ -+ if(munmap(stack, PAGE_SIZE) < 0) -+ panic("check_ptrace : munmap failed, errno = %d", errno); -+} -+ -+void __init check_ptrace(void) -+{ -+ void *stack; -+ int pid, syscall, n, status; -+ -+ printk("Checking that ptrace can change system call numbers..."); -+ pid = start_ptraced_child(&stack); -+ -+ while(1){ -+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) -+ panic("check_ptrace : ptrace failed, errno = %d", -+ errno); -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0) -+ panic("check_ptrace : wait failed, errno = %d", errno); -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) -+ panic("check_ptrace : expected SIGTRAP, " -+ "got status = %d", status); -+ -+ syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, -+ 0); -+ if(syscall == __NR_getpid){ -+ n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getppid); -+ if(n < 0) -+ panic("check_ptrace : failed to modify system " -+ "call, errno = %d", errno); -+ break; -+ } -+ } -+ stop_ptraced_child(pid, stack, 0); -+ printk("OK\n"); -+} -+ -+int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) -+{ -+ jmp_buf buf; -+ int n; -+ -+ *jmp_ptr = &buf; -+ n = setjmp(buf); -+ if(n != 0) -+ return(n); -+ (*fn)(arg); -+ return(0); -+} -+ -+int can_do_skas(void) -+{ -+#ifdef UML_CONFIG_MODE_SKAS -+ struct ptrace_faultinfo fi; -+ void *stack; -+ int pid, n, ret = 1; -+ -+ printf("Checking for the skas3 patch in the host..."); -+ pid = start_ptraced_child(&stack); -+ -+ n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); -+ if(n < 0){ -+ if(errno == EIO) -+ printf("not found\n"); -+ else printf("No (unexpected errno - %d)\n", errno); -+ ret = 0; -+ } -+ else printf("found\n"); -+ -+ init_registers(pid); -+ stop_ptraced_child(pid, stack, 1); -+ -+ printf("Checking for /proc/mm..."); -+ if(access("/proc/mm", W_OK)){ -+ printf("not found\n"); -+ ret = 0; -+ } -+ else printf("found\n"); -+ -+ return(ret); -+#else -+ return(0); -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/process_kern.c um/arch/um/kernel/process_kern.c ---- orig/arch/um/kernel/process_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/process_kern.c Thu Mar 6 20:19:55 2003 -@@ -0,0 +1,386 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/interrupt.h" -+#include "linux/mm.h" -+#include "linux/slab.h" -+#include "linux/utsname.h" -+#include "linux/fs.h" -+#include "linux/utime.h" -+#include "linux/smp_lock.h" -+#include "linux/module.h" -+#include "linux/init.h" -+#include "linux/capability.h" -+#include "asm/unistd.h" -+#include "asm/mman.h" -+#include "asm/segment.h" -+#include "asm/stat.h" -+#include "asm/pgtable.h" -+#include "asm/processor.h" -+#include "asm/pgalloc.h" -+#include "asm/spinlock.h" -+#include "asm/uaccess.h" -+#include "asm/user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "init.h" -+#include "irq_user.h" -+#include "mem_user.h" -+#include "time_user.h" -+#include "tlb.h" -+#include "frame_kern.h" -+#include "sigcontext.h" -+#include "2_5compat.h" -+#include "os.h" -+#include "mode.h" -+#include "mode_kern.h" -+#include "choose-mode.h" -+ -+/* This is a per-cpu array. A processor only modifies its entry and it only -+ * cares about its entry, so it's OK if another processor is modifying its -+ * entry. -+ */ -+struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; -+ -+struct task_struct *get_task(int pid, int require) -+{ -+ struct task_struct *ret; -+ -+ read_lock(&tasklist_lock); -+ 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); -+} -+ -+int external_pid(void *t) -+{ -+ struct task_struct *task = t ? t : current; -+ -+ return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task)); -+} -+ -+int pid_to_processor_id(int pid) -+{ -+ int i; -+ -+ for(i = 0; i < smp_num_cpus; i++){ -+ if(cpu_tasks[i].pid == pid) return(i); -+ } -+ return(-1); -+} -+ -+void free_stack(unsigned long stack, int order) -+{ -+ free_pages(stack, order); -+} -+ -+unsigned long alloc_stack(int order, int atomic) -+{ -+ unsigned long page; -+ int flags = GFP_KERNEL; -+ -+ if(atomic) flags |= GFP_ATOMIC; -+ if((page = __get_free_pages(flags, order)) == 0) -+ return(0); -+ stack_protections(page); -+ return(page); -+} -+ -+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -+{ -+ int pid; -+ -+ current->thread.request.u.thread.proc = fn; -+ current->thread.request.u.thread.arg = arg; -+ pid = do_fork(CLONE_VM | flags, 0, NULL, 0); -+ if(pid < 0) panic("do_fork failed in kernel_thread"); -+ return(pid); -+} -+ -+void switch_mm(struct mm_struct *prev, struct mm_struct *next, -+ struct task_struct *tsk, unsigned cpu) -+{ -+ if (prev != next) -+ clear_bit(cpu, &prev->cpu_vm_mask); -+ set_bit(cpu, &next->cpu_vm_mask); -+} -+ -+void set_current(void *t) -+{ -+ struct task_struct *task = t; -+ -+ cpu_tasks[task->processor] = ((struct cpu_task) -+ { external_pid(task), task }); -+} -+ -+void *_switch_to(void *prev, void *next) -+{ -+ return(CHOOSE_MODE(_switch_to_tt(prev, next), -+ _switch_to_skas(prev, next))); -+} -+ -+void interrupt_end(void) -+{ -+ if(current->need_resched) schedule(); -+ if(current->sigpending != 0) do_signal(0); -+} -+ -+void release_thread(struct task_struct *task) -+{ -+ CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); -+} -+ -+void exit_thread(void) -+{ -+ CHOOSE_MODE(exit_thread_tt(), exit_thread_skas()); -+ unprotect_stack((unsigned long) current); -+} -+ -+void *get_current(void) -+{ -+ return(current); -+} -+ -+int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ p->thread = (struct thread_struct) INIT_THREAD; -+ p->thread.kernel_stack = (unsigned long) p + 2 * PAGE_SIZE; -+ -+ return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, -+ clone_flags, sp, stack_top, p, regs)); -+} -+ -+void initial_thread_cb(void (*proc)(void *), void *arg) -+{ -+ int save_kmalloc_ok = kmalloc_ok; -+ -+ kmalloc_ok = 0; -+ CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, -+ arg); -+ kmalloc_ok = save_kmalloc_ok; -+} -+ -+unsigned long stack_sp(unsigned long page) -+{ -+ return(page + PAGE_SIZE - sizeof(void *)); -+} -+ -+int current_pid(void) -+{ -+ return(current->pid); -+} -+ -+void cpu_idle(void) -+{ -+ CHOOSE_MODE(init_idle_tt(), init_idle_skas()); -+ -+ atomic_inc(&init_mm.mm_count); -+ current->mm = &init_mm; -+ current->active_mm = &init_mm; -+ -+ while(1){ -+ /* endless idle loop with no priority at all */ -+ SET_PRI(current); -+ -+ /* -+ * although we are an idle CPU, we do not want to -+ * get into the scheduler unnecessarily. -+ */ -+ if (current->need_resched) { -+ schedule(); -+ check_pgt_cache(); -+ } -+ idle_sleep(10); -+ } -+} -+ -+int page_size(void) -+{ -+ return(PAGE_SIZE); -+} -+ -+int page_mask(void) -+{ -+ return(PAGE_MASK); -+} -+ -+void *um_virt_to_phys(struct task_struct *task, unsigned long addr, -+ pte_t *pte_out) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ -+ if(task->mm == NULL) -+ return(ERR_PTR(-EINVAL)); -+ pgd = pgd_offset(task->mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(!pmd_present(*pmd)) -+ return(ERR_PTR(-EINVAL)); -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte)) -+ return(ERR_PTR(-EINVAL)); -+ if(pte_out != NULL) -+ *pte_out = *pte; -+ return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK)); -+} -+ -+char *current_cmd(void) -+{ -+#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) -+ return("(Unknown)"); -+#else -+ void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); -+ return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); -+#endif -+} -+ -+void force_sigbus(void) -+{ -+ printk(KERN_ERR "Killing pid %d because of a lack of memory\n", -+ current->pid); -+ lock_kernel(); -+ sigaddset(¤t->pending.signal, SIGBUS); -+ recalc_sigpending(current); -+ current->flags |= PF_SIGNALED; -+ do_exit(SIGBUS | 0x80); -+} -+ -+void dump_thread(struct pt_regs *regs, struct user *u) -+{ -+} -+ -+void enable_hlt(void) -+{ -+ panic("enable_hlt"); -+} -+ -+void disable_hlt(void) -+{ -+ panic("disable_hlt"); -+} -+ -+extern int signal_frame_size; -+ -+void *um_kmalloc(int size) -+{ -+ return(kmalloc(size, GFP_KERNEL)); -+} -+ -+void *um_kmalloc_atomic(int size) -+{ -+ return(kmalloc(size, GFP_ATOMIC)); -+} -+ -+unsigned long get_fault_addr(void) -+{ -+ return((unsigned long) current->thread.fault_addr); -+} -+ -+EXPORT_SYMBOL(get_fault_addr); -+ -+void not_implemented(void) -+{ -+ printk(KERN_DEBUG "Something isn't implemented in here\n"); -+} -+ -+EXPORT_SYMBOL(not_implemented); -+ -+int user_context(unsigned long sp) -+{ -+ unsigned long stack; -+ -+ stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); -+ stack += 2 * PAGE_SIZE; -+ return(stack != current->thread.kernel_stack); -+} -+ -+extern void remove_umid_dir(void); -+ -+__uml_exitcall(remove_umid_dir); -+ -+extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; -+ -+void do_uml_exitcalls(void) -+{ -+ exitcall_t *call; -+ -+ call = &__uml_exitcall_end; -+ while (--call >= &__uml_exitcall_begin) -+ (*call)(); -+} -+ -+char *uml_strdup(char *string) -+{ -+ char *new; -+ -+ new = kmalloc(strlen(string) + 1, GFP_KERNEL); -+ if(new == NULL) return(NULL); -+ strcpy(new, string); -+ return(new); -+} -+ -+void *get_init_task(void) -+{ -+ return(&init_task_union.task); -+} -+ -+int copy_to_user_proc(void *to, void *from, int size) -+{ -+ return(copy_to_user(to, from, size)); -+} -+ -+int copy_from_user_proc(void *to, void *from, int size) -+{ -+ return(copy_from_user(to, from, size)); -+} -+ -+int clear_user_proc(void *buf, int size) -+{ -+ return(clear_user(buf, size)); -+} -+ -+int smp_sigio_handler(void) -+{ -+#ifdef CONFIG_SMP -+ int cpu = current->processor; -+ -+ IPI_handler(cpu); -+ if(cpu != 0) -+ return(1); -+#endif -+ return(0); -+} -+ -+int um_in_interrupt(void) -+{ -+ return(in_interrupt()); -+} -+ -+int cpu(void) -+{ -+ return(current->processor); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/ptrace.c um/arch/um/kernel/ptrace.c ---- orig/arch/um/kernel/ptrace.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/ptrace.c Sat Dec 28 22:50:21 2002 -@@ -0,0 +1,325 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/mm.h" -+#include "linux/errno.h" -+#include "linux/smp_lock.h" -+#ifdef CONFIG_PROC_MM -+#include "linux/proc_mm.h" -+#endif -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "kern_util.h" -+#include "ptrace_user.h" -+ -+/* -+ * Called by kernel/ptrace.c when detaching.. -+ */ -+void ptrace_disable(struct task_struct *child) -+{ -+} -+ -+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; -+ int i, ret; -+ -+ lock_kernel(); -+ ret = -EPERM; -+ if (request == PTRACE_TRACEME) { -+ /* are we already being traced? */ -+ if (current->ptrace & PT_PTRACED) -+ goto out; -+ /* set the ptrace bit in the process flags. */ -+ current->ptrace |= PT_PTRACED; -+ ret = 0; -+ goto out; -+ } -+ ret = -ESRCH; -+ read_lock(&tasklist_lock); -+ child = find_task_by_pid(pid); -+ if (child) -+ get_task_struct(child); -+ read_unlock(&tasklist_lock); -+ if (!child) -+ goto out; -+ -+ ret = -EPERM; -+ if (pid == 1) /* you may not mess with init */ -+ goto out_tsk; -+ -+ if (request == PTRACE_ATTACH) { -+ ret = ptrace_attach(child); -+ goto out_tsk; -+ } -+ -+ ret = ptrace_check_attach(child, request == PTRACE_KILL); -+ if (ret < 0) -+ goto out_tsk; -+ -+ switch (request) { -+ /* when I and D space are separate, these will need to be fixed. */ -+ case PTRACE_PEEKTEXT: /* read word at location addr. */ -+ case PTRACE_PEEKDATA: { -+ unsigned long tmp; -+ int copied; -+ -+ ret = -EIO; -+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); -+ if (copied != sizeof(tmp)) -+ break; -+ ret = put_user(tmp,(unsigned long *) data); -+ break; -+ } -+ -+ /* read the word at location addr in the USER area. */ -+ case PTRACE_PEEKUSR: { -+ unsigned long tmp; -+ -+ ret = -EIO; -+ if ((addr & 3) || addr < 0) -+ break; -+ -+ tmp = 0; /* Default return condition */ -+ if(addr < FRAME_SIZE_OFFSET){ -+ tmp = getreg(child, addr); -+ } -+ else if((addr >= offsetof(struct user, u_debugreg[0])) && -+ (addr <= offsetof(struct user, u_debugreg[7]))){ -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ tmp = child->thread.arch.debugregs[addr]; -+ } -+ ret = put_user(tmp, (unsigned long *) data); -+ break; -+ } -+ -+ /* when I and D space are separate, this will have to be fixed. */ -+ case PTRACE_POKETEXT: /* write the word at location addr. */ -+ case PTRACE_POKEDATA: -+ ret = -EIO; -+ if (access_process_vm(child, addr, &data, sizeof(data), -+ 1) != sizeof(data)) -+ break; -+ ret = 0; -+ break; -+ -+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ -+ ret = -EIO; -+ if ((addr & 3) || addr < 0) -+ break; -+ -+ if (addr < FRAME_SIZE_OFFSET) { -+ ret = putreg(child, addr, data); -+ break; -+ } -+ else if((addr >= offsetof(struct user, u_debugreg[0])) && -+ (addr <= offsetof(struct user, u_debugreg[7]))){ -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ if((addr == 4) || (addr == 5)) break; -+ child->thread.arch.debugregs[addr] = data; -+ ret = 0; -+ } -+ -+ break; -+ -+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ -+ case PTRACE_CONT: { /* restart after signal. */ -+ ret = -EIO; -+ if ((unsigned long) data > _NSIG) -+ break; -+ if (request == PTRACE_SYSCALL) -+ child->ptrace |= PT_TRACESYS; -+ else -+ child->ptrace &= ~PT_TRACESYS; -+ child->exit_code = data; -+ wake_up_process(child); -+ ret = 0; -+ break; -+ } -+ -+/* -+ * make the child exit. Best I can do is send it a sigkill. -+ * perhaps it should be put in the status that it wants to -+ * exit. -+ */ -+ case PTRACE_KILL: { -+ ret = 0; -+ if (child->state == TASK_ZOMBIE) /* already dead */ -+ break; -+ child->exit_code = SIGKILL; -+ wake_up_process(child); -+ break; -+ } -+ -+ case PTRACE_SINGLESTEP: { /* set the trap flag. */ -+ ret = -EIO; -+ if ((unsigned long) data > _NSIG) -+ break; -+ child->ptrace &= ~PT_TRACESYS; -+ child->ptrace |= PT_DTRACE; -+ child->exit_code = data; -+ /* give it a chance to run. */ -+ wake_up_process(child); -+ ret = 0; -+ break; -+ } -+ -+ case PTRACE_DETACH: -+ /* detach a process that was attached. */ -+ ret = ptrace_detach(child, data); -+ break; -+ -+#ifdef PTRACE_GETREGS -+ case PTRACE_GETREGS: { /* Get all gp regs from the child. */ -+ if (!access_ok(VERIFY_WRITE, (unsigned long *)data, -+ FRAME_SIZE_OFFSET)) { -+ ret = -EIO; -+ break; -+ } -+ for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { -+ __put_user(getreg(child, i), (unsigned long *) data); -+ data += sizeof(long); -+ } -+ ret = 0; -+ break; -+ } -+#endif -+#ifdef PTRACE_SETREGS -+ case PTRACE_SETREGS: { /* Set all gp regs in the child. */ -+ unsigned long tmp = 0; -+ if (!access_ok(VERIFY_READ, (unsigned *)data, -+ FRAME_SIZE_OFFSET)) { -+ ret = -EIO; -+ break; -+ } -+ for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { -+ __get_user(tmp, (unsigned long *) data); -+ putreg(child, i, tmp); -+ data += sizeof(long); -+ } -+ ret = 0; -+ break; -+ } -+#endif -+#ifdef PTRACE_GETFPREGS -+ case PTRACE_GETFPREGS: /* Get the child FPU state. */ -+ ret = get_fpregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_SETFPREGS -+ case PTRACE_SETFPREGS: /* Set the child FPU state. */ -+ ret = set_fpregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_GETFPXREGS -+ case PTRACE_GETFPXREGS: /* Get the child FPU state. */ -+ ret = get_fpxregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_SETFPXREGS -+ case PTRACE_SETFPXREGS: /* Set the child FPU state. */ -+ ret = set_fpxregs(data, child); -+ break; -+#endif -+ case PTRACE_FAULTINFO: { -+ struct ptrace_faultinfo fault; -+ -+ fault = ((struct ptrace_faultinfo) -+ { .is_write = child->thread.err, -+ .addr = child->thread.cr2 }); -+ ret = copy_to_user((unsigned long *) data, &fault, -+ sizeof(fault)); -+ if(ret) -+ break; -+ break; -+ } -+ case PTRACE_SIGPENDING: -+ ret = copy_to_user((unsigned long *) data, -+ &child->pending.signal, -+ sizeof(child->pending.signal)); -+ break; -+ -+ case PTRACE_LDT: { -+ struct ptrace_ldt ldt; -+ -+ if(copy_from_user(&ldt, (unsigned long *) data, -+ sizeof(ldt))){ -+ ret = -EIO; -+ break; -+ } -+ -+ /* This one is confusing, so just punt and return -EIO for -+ * now -+ */ -+ ret = -EIO; -+ break; -+ } -+#ifdef CONFIG_PROC_MM -+ case PTRACE_SWITCH_MM: { -+ struct mm_struct *old = child->mm; -+ struct mm_struct *new = proc_mm_get_mm(data); -+ -+ if(IS_ERR(new)){ -+ ret = PTR_ERR(new); -+ break; -+ } -+ -+ atomic_inc(&new->mm_users); -+ child->mm = new; -+ child->active_mm = new; -+ mmput(old); -+ ret = 0; -+ break; -+ } -+#endif -+ default: -+ ret = -EIO; -+ break; -+ } -+ out_tsk: -+ free_task_struct(child); -+ out: -+ unlock_kernel(); -+ return ret; -+} -+ -+void syscall_trace(void) -+{ -+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) -+ != (PT_PTRACED|PT_TRACESYS)) -+ return; -+ current->exit_code = SIGTRAP; -+ current->state = TASK_STOPPED; -+ notify_parent(current, SIGCHLD); -+ schedule(); -+ /* -+ * this isn't the same as continuing with a signal, but it will do -+ * for normal use. strace only continues with a signal if the -+ * stopping signal is not SIGTRAP. -brl -+ */ -+ if (current->exit_code) { -+ send_sig(current->exit_code, current, 1); -+ current->exit_code = 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 -Naur -X ../exclude-files orig/arch/um/kernel/reboot.c um/arch/um/kernel/reboot.c ---- orig/arch/um/kernel/reboot.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/reboot.c Mon Dec 30 20:57:42 2002 -@@ -0,0 +1,71 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "os.h" -+#include "mode.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_SMP -+static void kill_idlers(int me) -+{ -+ struct task_struct *p; -+ int i; -+ -+ for(i = 0; i < sizeof(init_tasks)/sizeof(init_tasks[0]); i++){ -+ p = init_tasks[i]; -+ if((p != NULL) && (p->thread.mode.tt.extern_pid != me) && -+ (p->thread.mode.tt.extern_pid != -1)) -+ os_kill_process(p->thread.mode.tt.extern_pid, 0); -+ } -+} -+#endif -+ -+static void kill_off_processes(void) -+{ -+ CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas()); -+#ifdef CONFIG_SMP -+ kill_idlers(os_getpid()); -+#endif -+} -+ -+void uml_cleanup(void) -+{ -+ kill_off_processes(); -+ do_uml_exitcalls(); -+} -+ -+void machine_restart(char * __unused) -+{ -+ do_uml_exitcalls(); -+ kill_off_processes(); -+ CHOOSE_MODE(reboot_tt(), reboot_skas()); -+} -+ -+void machine_power_off(void) -+{ -+ do_uml_exitcalls(); -+ kill_off_processes(); -+ CHOOSE_MODE(halt_tt(), halt_skas()); -+} -+ -+void machine_halt(void) -+{ -+ machine_power_off(); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/resource.c um/arch/um/kernel/resource.c ---- orig/arch/um/kernel/resource.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/resource.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/pci.h" -+ -+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, -+ unsigned long start, unsigned long size) -+{ -+ return start; -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/sigio_kern.c um/arch/um/kernel/sigio_kern.c ---- orig/arch/um/kernel/sigio_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/sigio_kern.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/list.h" -+#include "linux/slab.h" -+#include "asm/irq.h" -+#include "init.h" -+#include "sigio.h" -+#include "irq_user.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) -+{ -+ read_sigio_fd(sigio_irq_fd); -+ reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); -+} -+ -+int write_sigio_irq(int fd) -+{ -+ if(um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, -+ SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", -+ NULL)){ -+ printk("write_sigio_irq : um_request_irq failed\n"); -+ return(-1); -+ } -+ sigio_irq_fd = fd; -+ return(0); -+} -+ -+static spinlock_t sigio_spinlock = SPIN_LOCK_UNLOCKED; -+ -+void sigio_lock(void) -+{ -+ spin_lock(&sigio_spinlock); -+} -+ -+void sigio_unlock(void) -+{ -+ spin_unlock(&sigio_spinlock); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/sigio_user.c um/arch/um/kernel/sigio_user.c ---- orig/arch/um/kernel/sigio_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/sigio_user.c Sun Dec 29 23:36:35 2002 -@@ -0,0 +1,440 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdlib.h> -+#include <termios.h> -+#include <pty.h> -+#include <fcntl.h> -+#include <signal.h> -+#include <errno.h> -+#include <string.h> -+#include <sched.h> -+#include <sys/socket.h> -+#include <sys/poll.h> -+#include "init.h" -+#include "user.h" -+#include "kern_util.h" -+#include "sigio.h" -+#include "helper.h" -+#include "os.h" -+ -+/* Changed during early boot */ -+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; -+ -+void __init handler(int sig) -+{ -+ got_sigio = 1; -+} -+ -+struct openpty_arg { -+ int master; -+ int slave; -+ int err; -+}; -+ -+static void openpty_cb(void *arg) -+{ -+ struct openpty_arg *info = arg; -+ -+ info->err = 0; -+ if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) -+ info->err = errno; -+} -+ -+void __init check_one_sigio(void (*proc)(int, int)) -+{ -+ struct sigaction old, new; -+ struct termios tt; -+ struct openpty_arg pty = { .master = -1, .slave = -1 }; -+ int master, slave, flags; -+ -+ initial_thread_cb(openpty_cb, &pty); -+ if(pty.err){ -+ printk("openpty failed, errno = %d\n", pty.err); -+ return; -+ } -+ -+ master = pty.master; -+ slave = pty.slave; -+ -+ if((master == -1) || (slave == -1)){ -+ printk("openpty failed to allocate a pty\n"); -+ return; -+ } -+ -+ 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); -+ -+ if(sigaction(SIGIO, NULL, &old) < 0) -+ panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); -+ new = old; -+ new.sa_handler = handler; -+ if(sigaction(SIGIO, &new, NULL) < 0) -+ panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); -+ -+ got_sigio = 0; -+ (*proc)(master, slave); -+ -+ close(master); -+ close(slave); -+ -+ if(sigaction(SIGIO, &old, NULL) < 0) -+ panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); -+} -+ -+static void tty_output(int master, int slave) -+{ -+ int n; -+ char buf[512]; -+ -+ printk("Checking that host ptys support output SIGIO..."); -+ -+ memset(buf, 0, sizeof(buf)); -+ while(write(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) ; -+ -+ 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); -+} -+ -+static void tty_close(int master, int slave) -+{ -+ printk("Checking that host ptys support SIGIO on close..."); -+ -+ close(slave); -+ if(got_sigio){ -+ printk("Yes\n"); -+ pty_close_sigio = 1; -+ } -+ else printk("No, enabling workaround\n"); -+} -+ -+void __init check_sigio(void) -+{ -+ if(access("/dev/ptmx", R_OK) && access("/dev/ptyp0", R_OK)){ -+ printk("No pseudo-terminals available - skipping pty SIGIO " -+ "check\n"); -+ return; -+ } -+ check_one_sigio(tty_output); -+ check_one_sigio(tty_close); -+} -+ -+/* Protected by sigio_lock(), also used by sigio_cleanup, which is an -+ * exitcall. -+ */ -+static int write_sigio_pid = -1; -+ -+/* These arrays are initialized before the sigio thread is started, and -+ * the descriptors closed after it is killed. So, it can't see them change. -+ * On the UML side, they are changed under the sigio_lock. -+ */ -+static int write_sigio_fds[2] = { -1, -1 }; -+static int sigio_private[2] = { -1, -1 }; -+ -+struct pollfds { -+ struct pollfd *poll; -+ int size; -+ int used; -+}; -+ -+/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread -+ * synchronizes with it. -+ */ -+struct pollfds current_poll = { -+ .poll = NULL, -+ .size = 0, -+ .used = 0 -+}; -+ -+struct pollfds next_poll = { -+ .poll = NULL, -+ .size = 0, -+ .used = 0 -+}; -+ -+static int write_sigio_thread(void *unused) -+{ -+ struct pollfds *fds, tmp; -+ struct pollfd *p; -+ int i, n, respond_fd; -+ char c; -+ -+ fds = ¤t_poll; -+ while(1){ -+ n = poll(fds->poll, fds->used, -1); -+ if(n < 0){ -+ if(errno == EINTR) continue; -+ printk("write_sigio_thread : poll returned %d, " -+ "errno = %d\n", n, errno); -+ } -+ for(i = 0; i < fds->used; i++){ -+ p = &fds->poll[i]; -+ if(p->revents == 0) continue; -+ if(p->fd == sigio_private[1]){ -+ n = read(sigio_private[1], &c, sizeof(c)); -+ if(n != sizeof(c)) -+ printk("write_sigio_thread : " -+ "read failed, errno = %d\n", -+ errno); -+ tmp = current_poll; -+ current_poll = next_poll; -+ next_poll = tmp; -+ respond_fd = sigio_private[1]; -+ } -+ else { -+ respond_fd = write_sigio_fds[1]; -+ fds->used--; -+ memmove(&fds->poll[i], &fds->poll[i + 1], -+ (fds->used - i) * sizeof(*fds->poll)); -+ } -+ -+ n = write(respond_fd, &c, sizeof(c)); -+ if(n != sizeof(c)) -+ printk("write_sigio_thread : write failed, " -+ "errno = %d\n", errno); -+ } -+ } -+} -+ -+static int need_poll(int n) -+{ -+ if(n <= next_poll.size){ -+ next_poll.used = n; -+ return(0); -+ } -+ if(next_poll.poll != NULL) kfree(next_poll.poll); -+ next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); -+ if(next_poll.poll == NULL){ -+ printk("need_poll : failed to allocate new pollfds\n"); -+ next_poll.size = 0; -+ next_poll.used = 0; -+ return(-1); -+ } -+ next_poll.size = n; -+ next_poll.used = n; -+ return(0); -+} -+ -+static void update_thread(void) -+{ -+ unsigned long flags; -+ int n; -+ char c; -+ -+ flags = set_signals(0); -+ n = write(sigio_private[0], &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("update_thread : write failed, errno = %d\n", errno); -+ goto fail; -+ } -+ -+ n = read(sigio_private[0], &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("update_thread : read failed, errno = %d\n", errno); -+ goto fail; -+ } -+ -+ set_signals(flags); -+ return; -+ fail: -+ sigio_lock(); -+ 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]); -+ sigio_unlock(); -+ set_signals(flags); -+} -+ -+int add_sigio_fd(int fd, int read) -+{ -+ int err = 0, i, n, events; -+ -+ sigio_lock(); -+ for(i = 0; i < current_poll.used; i++){ -+ if(current_poll.poll[i].fd == fd) -+ goto out; -+ } -+ -+ n = current_poll.used + 1; -+ err = need_poll(n); -+ if(err) -+ goto out; -+ -+ for(i = 0; i < current_poll.used; i++) -+ next_poll.poll[i] = current_poll.poll[i]; -+ -+ if(read) events = POLLIN; -+ else events = POLLOUT; -+ -+ next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd, -+ .events = events, -+ .revents = 0 }); -+ update_thread(); -+ out: -+ sigio_unlock(); -+ return(err); -+} -+ -+int ignore_sigio_fd(int fd) -+{ -+ struct pollfd *p; -+ int err = 0, i, n = 0; -+ -+ sigio_lock(); -+ for(i = 0; i < current_poll.used; i++){ -+ if(current_poll.poll[i].fd == fd) break; -+ } -+ if(i == current_poll.used) -+ goto out; -+ -+ err = need_poll(current_poll.used - 1); -+ if(err) -+ goto out; -+ -+ for(i = 0; i < current_poll.used; i++){ -+ p = ¤t_poll.poll[i]; -+ if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i]; -+ } -+ if(n == i){ -+ printk("ignore_sigio_fd : fd %d not found\n", fd); -+ err = -1; -+ goto out; -+ } -+ -+ update_thread(); -+ out: -+ sigio_unlock(); -+ return(err); -+} -+ -+static int setup_initial_poll(int fd) -+{ -+ struct pollfd *p; -+ -+ p = um_kmalloc(sizeof(struct pollfd)); -+ if(p == NULL){ -+ printk("setup_initial_poll : failed to allocate poll\n"); -+ return(-1); -+ } -+ *p = ((struct pollfd) { .fd = fd, -+ .events = POLLIN, -+ .revents = 0 }); -+ current_poll = ((struct pollfds) { .poll = p, -+ .used = 1, -+ .size = 1 }); -+ return(0); -+} -+ -+void write_sigio_workaround(void) -+{ -+ unsigned long stack; -+ int err; -+ -+ sigio_lock(); -+ if(write_sigio_pid != -1) -+ goto out; -+ -+ err = os_pipe(write_sigio_fds, 1, 1); -+ if(err){ -+ printk("write_sigio_workaround - os_pipe 1 failed, " -+ "errno = %d\n", -err); -+ goto out; -+ } -+ err = os_pipe(sigio_private, 1, 1); -+ if(err){ -+ printk("write_sigio_workaround - os_pipe 2 failed, " -+ "errno = %d\n", -err); -+ goto out_close1; -+ } -+ if(setup_initial_poll(sigio_private[1])) -+ goto out_close2; -+ -+ write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, -+ CLONE_FILES | CLONE_VM, &stack, 0); -+ -+ if(write_sigio_pid < 0) goto out_close2; -+ -+ if(write_sigio_irq(write_sigio_fds[0])) -+ goto out_kill; -+ -+ out: -+ sigio_unlock(); -+ return; -+ -+ out_kill: -+ os_kill_process(write_sigio_pid, 1); -+ write_sigio_pid = -1; -+ out_close2: -+ close(sigio_private[0]); -+ close(sigio_private[1]); -+ out_close1: -+ close(write_sigio_fds[0]); -+ close(write_sigio_fds[1]); -+ sigio_unlock(); -+} -+ -+int read_sigio_fd(int fd) -+{ -+ int n; -+ char c; -+ -+ n = read(fd, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("read_sigio_fd - read failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ return(n); -+} -+ -+static void sigio_cleanup(void) -+{ -+ if(write_sigio_pid != -1) -+ os_kill_process(write_sigio_pid, 1); -+} -+ -+__uml_exitcall(sigio_cleanup); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/signal_kern.c um/arch/um/kernel/signal_kern.c ---- orig/arch/um/kernel/signal_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/signal_kern.c Sun Dec 8 19:44:13 2002 -@@ -0,0 +1,367 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/stddef.h" -+#include "linux/sys.h" -+#include "linux/sched.h" -+#include "linux/wait.h" -+#include "linux/kernel.h" -+#include "linux/smp_lock.h" -+#include "linux/module.h" -+#include "linux/slab.h" -+#include "asm/signal.h" -+#include "asm/uaccess.h" -+#include "asm/ucontext.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "kern.h" -+#include "frame_kern.h" -+#include "sigcontext.h" -+#include "mode.h" -+ -+EXPORT_SYMBOL(block_signals); -+EXPORT_SYMBOL(unblock_signals); -+ -+static void force_segv(int sig) -+{ -+ if(sig == SIGSEGV){ -+ struct k_sigaction *ka; -+ -+ ka = ¤t->sig->action[SIGSEGV - 1]; -+ ka->sa.sa_handler = SIG_DFL; -+ } -+ force_sig(SIGSEGV, current); -+} -+ -+#define _S(nr) (1<<((nr)-1)) -+ -+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) -+ -+/* -+ * OK, we're invoking a handler -+ */ -+static int handle_signal(struct pt_regs *regs, unsigned long signr, -+ struct k_sigaction *ka, siginfo_t *info, -+ sigset_t *oldset, int error) -+{ -+ __sighandler_t handler; -+ void (*restorer)(void); -+ unsigned long sp; -+ sigset_t save; -+ int err, ret; -+ -+ ret = 0; -+ switch(error){ -+ case -ERESTARTNOHAND: -+ ret = -EINTR; -+ break; -+ -+ case -ERESTARTSYS: -+ if (!(ka->sa.sa_flags & SA_RESTART)) { -+ ret = -EINTR; -+ break; -+ } -+ /* fallthrough */ -+ case -ERESTARTNOINTR: -+ PT_REGS_RESTART_SYSCALL(regs); -+ PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); -+ -+ /* This is because of the UM_SET_SYSCALL_RETURN and the fact -+ * that on i386 the system call number and return value are -+ * in the same register. When the system call restarts, %eax -+ * had better have the system call number in it. Since the -+ * return value doesn't matter (except that it shouldn't be -+ * -ERESTART*), we'll stick the system call number there. -+ */ -+ ret = PT_REGS_SYSCALL_NR(regs); -+ break; -+ } -+ -+ handler = ka->sa.sa_handler; -+ save = *oldset; -+ -+ if (ka->sa.sa_flags & SA_ONESHOT) -+ ka->sa.sa_handler = SIG_DFL; -+ -+ if (!(ka->sa.sa_flags & SA_NODEFER)) { -+ spin_lock_irq(¤t->sigmask_lock); -+ sigorsets(¤t->blocked, ¤t->blocked, -+ &ka->sa.sa_mask); -+ sigaddset(¤t->blocked, signr); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ } -+ -+ sp = PT_REGS_SP(regs); -+ -+ if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) -+ sp = current->sas_ss_sp + current->sas_ss_size; -+ -+ if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret); -+ -+ if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; -+ else restorer = NULL; -+ -+ if(ka->sa.sa_flags & SA_SIGINFO) -+ err = setup_signal_stack_si(sp, signr, (unsigned long) handler, -+ restorer, regs, info, &save); -+ else -+ err = setup_signal_stack_sc(sp, signr, (unsigned long) handler, -+ restorer, regs, &save); -+ if(err) goto segv; -+ -+ return(0); -+ segv: -+ force_segv(signr); -+ return(1); -+} -+ -+/* -+ * Note that 'init' is a special process: it doesn't get signals it doesn't -+ * want to handle. Thus you cannot kill init even with a SIGKILL even by -+ * mistake. -+ */ -+ -+static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error) -+{ -+ siginfo_t info; -+ struct k_sigaction *ka; -+ int err; -+ -+ if (!oldset) -+ oldset = ¤t->blocked; -+ -+ for (;;) { -+ unsigned long signr; -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ signr = dequeue_signal(¤t->blocked, &info); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ if (!signr) -+ break; -+ -+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { -+ /* Let the debugger run. */ -+ current->exit_code = signr; -+ current->state = TASK_STOPPED; -+ notify_parent(current, SIGCHLD); -+ schedule(); -+ -+ /* We're back. Did the debugger cancel the sig? */ -+ if (!(signr = current->exit_code)) -+ continue; -+ current->exit_code = 0; -+ -+ /* The debugger continued. Ignore SIGSTOP. */ -+ if (signr == SIGSTOP) -+ continue; -+ -+ /* Update the siginfo structure. Is this good? */ -+ if (signr != info.si_signo) { -+ info.si_signo = signr; -+ info.si_errno = 0; -+ info.si_code = SI_USER; -+ info.si_pid = current->p_pptr->pid; -+ info.si_uid = current->p_pptr->uid; -+ } -+ -+ /* If the (new) signal is now blocked, requeue it. */ -+ if (sigismember(¤t->blocked, signr)) { -+ send_sig_info(signr, &info, current); -+ continue; -+ } -+ } -+ -+ ka = ¤t->sig->action[signr-1]; -+ if (ka->sa.sa_handler == SIG_IGN) { -+ if (signr != SIGCHLD) -+ continue; -+ /* Check for SIGCHLD: it's special. */ -+ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) -+ /* nothing */; -+ continue; -+ } -+ -+ if (ka->sa.sa_handler == SIG_DFL) { -+ int exit_code = signr; -+ -+ /* Init gets no signals it doesn't want. */ -+ if (current->pid == 1) -+ continue; -+ -+ switch (signr) { -+ case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: -+ continue; -+ -+ case SIGTSTP: case SIGTTIN: case SIGTTOU: -+ if (is_orphaned_pgrp(current->pgrp)) -+ continue; -+ /* FALLTHRU */ -+ -+ case SIGSTOP: { -+ struct signal_struct *sig; -+ current->state = TASK_STOPPED; -+ current->exit_code = signr; -+ sig = current->p_pptr->sig; -+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) -+ notify_parent(current, SIGCHLD); -+ schedule(); -+ continue; -+ } -+ case SIGQUIT: case SIGILL: case SIGTRAP: -+ case SIGABRT: case SIGFPE: case SIGSEGV: -+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: -+ if (do_coredump(signr, ¤t->thread.regs)) -+ exit_code |= 0x80; -+ /* FALLTHRU */ -+ -+ default: -+ sig_exit(signr, exit_code, &info); -+ /* NOTREACHED */ -+ } -+ } -+ -+ /* Whee! Actually deliver the signal. */ -+ err = handle_signal(regs, signr, ka, &info, oldset, error); -+ if(!err) return(1); -+ } -+ -+ /* Did we come from a system call? */ -+ if(PT_REGS_SYSCALL_NR(regs) >= 0){ -+ /* Restart the system call - no handlers present */ -+ if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || -+ PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || -+ PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ -+ PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); -+ PT_REGS_RESTART_SYSCALL(regs); -+ } -+ } -+ -+ /* This closes a way to execute a system call on the host. If -+ * you set a breakpoint on a system call instruction and singlestep -+ * from it, the tracing thread used to PTRACE_SINGLESTEP the process -+ * rather than PTRACE_SYSCALL it, allowing the system call to execute -+ * on the host. The tracing thread will check this flag and -+ * PTRACE_SYSCALL if necessary. -+ */ -+ if((current->ptrace & PT_DTRACE) && -+ is_syscall(PT_REGS_IP(¤t->thread.regs))) -+ (void) CHOOSE_MODE(current->thread.mode.tt.singlestep_syscall = 1, 0); -+ -+ return(0); -+} -+ -+int do_signal(int error) -+{ -+ return(kern_do_signal(¤t->thread.regs, NULL, error)); -+} -+ -+/* -+ * Atomically swap in the new signal mask, and wait for a signal. -+ */ -+int sys_sigsuspend(int history0, int history1, old_sigset_t mask) -+{ -+ sigset_t saveset; -+ -+ mask &= _BLOCKABLE; -+ spin_lock_irq(¤t->sigmask_lock); -+ saveset = current->blocked; -+ siginitset(¤t->blocked, mask); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ while (1) { -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ if(kern_do_signal(¤t->thread.regs, &saveset, -EINTR)) -+ return(-EINTR); -+ } -+} -+ -+int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) -+{ -+ sigset_t saveset, newset; -+ -+ /* XXX: Don't preclude handling different sized sigset_t's. */ -+ if (sigsetsize != sizeof(sigset_t)) -+ return -EINVAL; -+ -+ if (copy_from_user(&newset, unewset, sizeof(newset))) -+ return -EFAULT; -+ sigdelsetmask(&newset, ~_BLOCKABLE); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ saveset = current->blocked; -+ current->blocked = newset; -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ while (1) { -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ if (kern_do_signal(¤t->thread.regs, &saveset, -EINTR)) -+ return(-EINTR); -+ } -+} -+ -+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)); -+ 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)); -+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ copy_from_user(¤t->blocked.sig[0], sc_sigmask(sc), -+ sizeof(current->blocked.sig[0])); -+ copy_from_user(¤t->blocked.sig[1], mask, sig_size); -+ sigdelsetmask(¤t->blocked, ~_BLOCKABLE); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ copy_sc_from_user(¤t->thread.regs, sc, -+ &signal_frame_sc.common.arch); -+ return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); -+} -+ -+int sys_rt_sigreturn(struct pt_regs regs) -+{ -+ struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs)); -+ void *fp; -+ int sig_size = _NSIG_WORDS * sizeof(unsigned long); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ copy_from_user(¤t->blocked, &uc->uc_sigmask, sig_size); -+ sigdelsetmask(¤t->blocked, ~_BLOCKABLE); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ 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)); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/signal_user.c um/arch/um/kernel/signal_user.c ---- orig/arch/um/kernel/signal_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/signal_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stdlib.h> -+#include <signal.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <string.h> -+#include <sys/mman.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "signal_user.h" -+#include "signal_kern.h" -+#include "sysdep/sigcontext.h" -+#include "sigcontext.h" -+ -+void set_sigstack(void *sig_stack, int size) -+{ -+ stack_t stack = ((stack_t) { .ss_flags = 0, -+ .ss_sp = (__ptr_t) sig_stack, -+ .ss_size = size - sizeof(void *) }); -+ -+ if(sigaltstack(&stack, NULL) != 0) -+ panic("enabling signal stack failed, errno = %d\n", errno); -+} -+ -+void set_handler(int sig, void (*handler)(int), int flags, ...) -+{ -+ struct sigaction action; -+ va_list ap; -+ int mask; -+ -+ va_start(ap, flags); -+ action.sa_handler = handler; -+ sigemptyset(&action.sa_mask); -+ while((mask = va_arg(ap, int)) != -1){ -+ sigaddset(&action.sa_mask, mask); -+ } -+ action.sa_flags = flags; -+ action.sa_restorer = NULL; -+ if(sigaction(sig, &action, NULL) < 0) -+ panic("sigaction failed"); -+} -+ -+int change_sig(int signal, int on) -+{ -+ sigset_t sigset, old; -+ -+ sigemptyset(&sigset); -+ sigaddset(&sigset, signal); -+ sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); -+ return(!sigismember(&old, signal)); -+} -+ -+static void change_signals(int type) -+{ -+ sigset_t mask; -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ sigaddset(&mask, SIGIO); -+ sigaddset(&mask, SIGPROF); -+ if(sigprocmask(type, &mask, NULL) < 0) -+ panic("Failed to change signal mask - errno = %d", errno); -+} -+ -+void block_signals(void) -+{ -+ change_signals(SIG_BLOCK); -+} -+ -+void unblock_signals(void) -+{ -+ change_signals(SIG_UNBLOCK); -+} -+ -+#define SIGIO_BIT 0 -+#define SIGVTALRM_BIT 1 -+ -+static int enable_mask(sigset_t *mask) -+{ -+ int sigs; -+ -+ sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; -+ sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; -+ sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; -+ return(sigs); -+} -+ -+int get_signals(void) -+{ -+ sigset_t mask; -+ -+ if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) -+ panic("Failed to get signal mask"); -+ return(enable_mask(&mask)); -+} -+ -+int set_signals(int enable) -+{ -+ sigset_t mask; -+ int ret; -+ -+ sigemptyset(&mask); -+ if(enable & (1 << SIGIO_BIT)) -+ sigaddset(&mask, SIGIO); -+ if(enable & (1 << SIGVTALRM_BIT)){ -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ } -+ if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) -+ panic("Failed to enable signals"); -+ ret = enable_mask(&mask); -+ sigemptyset(&mask); -+ if((enable & (1 << SIGIO_BIT)) == 0) -+ sigaddset(&mask, SIGIO); -+ if((enable & (1 << SIGVTALRM_BIT)) == 0){ -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ } -+ if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) -+ panic("Failed to block signals"); -+ -+ return(ret); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/Makefile um/arch/um/kernel/skas/Makefile ---- orig/arch/um/kernel/skas/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/Makefile Fri Nov 1 16:05:44 2002 -@@ -0,0 +1,30 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = skas.o -+ -+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 -+ -+subdir-y = sys-$(SUBARCH) -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o -+ -+include $(TOPDIR)/Rules.make -+ -+include/skas_ptregs.h : util/mk_ptregs -+ util/mk_ptregs > $@ -+ -+util/mk_ptregs : -+ $(MAKE) -C util -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -+ $(MAKE) -C util clean -+ $(RM) -f include/skas_ptregs.h -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/exec_kern.c um/arch/um/kernel/skas/exec_kern.c ---- orig/arch/um/kernel/skas/exec_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/exec_kern.c Mon Nov 11 18:57:19 2002 -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "asm/current.h" -+#include "asm/page.h" -+#include "asm/signal.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/mmu_context.h" -+#include "tlb.h" -+#include "skas.h" -+#include "mmu.h" -+#include "os.h" -+ -+void flush_thread_skas(void) -+{ -+ force_flush_all(); -+ switch_mm_skas(current->mm->context.skas.mm_fd); -+} -+ -+void start_thread_skas(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp) -+{ -+ set_fs(USER_DS); -+ PT_REGS_IP(regs) = eip; -+ PT_REGS_SP(regs) = esp; -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/exec_user.c um/arch/um/kernel/skas/exec_user.c ---- orig/arch/um/kernel/skas/exec_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/exec_user.c Sun Nov 3 19:23:01 2002 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include <signal.h> -+#include <sched.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include "user.h" -+#include "kern_util.h" -+#include "os.h" -+#include "time_user.h" -+ -+static int user_thread_tramp(void *arg) -+{ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) -+ panic("user_thread_tramp - PTRACE_TRACEME failed, " -+ "errno = %d\n", errno); -+ enable_timer(); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+int user_thread(unsigned long stack, int flags) -+{ -+ int pid, status; -+ -+ pid = clone(user_thread_tramp, (void *) stack_sp(stack), -+ flags | CLONE_FILES | SIGCHLD, NULL); -+ if(pid < 0){ -+ printk("user_thread - clone failed, errno = %d\n", errno); -+ return(pid); -+ } -+ -+ if(waitpid(pid, &status, WUNTRACED) < 0){ -+ printk("user_thread - waitpid failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ printk("user_thread - trampoline didn't stop, status = %d\n", -+ status); -+ return(-EINVAL); -+ } -+ -+ return(pid); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mmu.h um/arch/um/kernel/skas/include/mmu.h ---- orig/arch/um/kernel/skas/include/mmu.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/include/mmu.h Sun Nov 10 21:21:50 2002 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_MMU_H -+#define __SKAS_MMU_H -+ -+#include "linux/list.h" -+#include "linux/spinlock.h" -+ -+struct mmu_context_skas { -+ int mm_fd; -+}; -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mode.h um/arch/um/kernel/skas/include/mode.h ---- orig/arch/um/kernel/skas/include/mode.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/include/mode.h Wed Mar 26 13:27:46 2003 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_SKAS_H__ -+#define __MODE_SKAS_H__ -+ -+extern unsigned long exec_regs[]; -+extern unsigned long exec_fp_regs[]; -+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, -+ 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 -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mode_kern.h um/arch/um/kernel/skas/include/mode_kern.h ---- orig/arch/um/kernel/skas/include/mode_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/include/mode_kern.h Mon Dec 16 21:49:11 2002 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_MODE_KERN_H__ -+#define __SKAS_MODE_KERN_H__ -+ -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/ptrace.h" -+ -+extern void flush_thread_skas(void); -+extern void *_switch_to_skas(void *prev, void *next); -+extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp); -+extern int copy_thread_skas(int nr, unsigned long clone_flags, -+ unsigned long sp, unsigned long stack_top, -+ struct task_struct *p, struct pt_regs *regs); -+extern void release_thread_skas(struct task_struct *task); -+extern void exit_thread_skas(void); -+extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); -+extern void init_idle_skas(void); -+extern void flush_tlb_kernel_vm_skas(void); -+extern void __flush_tlb_one_skas(unsigned long addr); -+extern void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_mm_skas(struct mm_struct *mm); -+extern void force_flush_all_skas(void); -+extern long execute_syscall_skas(void *r); -+extern void before_mem_skas(unsigned long unused); -+extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out); -+extern int start_uml_skas(void); -+extern int external_pid_skas(struct task_struct *task); -+extern int thread_pid_skas(struct thread_struct *thread); -+ -+#define kmem_end_skas (host_task_size - 1024 * 1024) -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/proc_mm.h um/arch/um/kernel/skas/include/proc_mm.h ---- orig/arch/um/kernel/skas/include/proc_mm.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/include/proc_mm.h Wed Nov 13 11:57:23 2002 -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_PROC_MM_H -+#define __SKAS_PROC_MM_H -+ -+#define MM_MMAP 54 -+#define MM_MUNMAP 55 -+#define MM_MPROTECT 56 -+#define MM_COPY_SEGMENTS 57 -+ -+struct mm_mmap { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+struct mm_munmap { -+ unsigned long addr; -+ unsigned long len; -+}; -+ -+struct mm_mprotect { -+ unsigned long addr; -+ unsigned long len; -+ unsigned int prot; -+}; -+ -+struct proc_mm_op { -+ int op; -+ union { -+ struct mm_mmap mmap; -+ struct mm_munmap munmap; -+ struct mm_mprotect mprotect; -+ int copy_segments; -+ } u; -+}; -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/ptrace-skas.h um/arch/um/kernel/skas/include/ptrace-skas.h ---- orig/arch/um/kernel/skas/include/ptrace-skas.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/include/ptrace-skas.h Fri Jan 17 13:22:09 2003 -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_SKAS_H -+#define __PTRACE_SKAS_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_SKAS -+ -+#include "skas_ptregs.h" -+ -+#define HOST_FRAME_SIZE 17 -+ -+#define REGS_IP(r) ((r)[HOST_IP]) -+#define REGS_SP(r) ((r)[HOST_SP]) -+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) -+#define REGS_EAX(r) ((r)[HOST_EAX]) -+#define REGS_EBX(r) ((r)[HOST_EBX]) -+#define REGS_ECX(r) ((r)[HOST_ECX]) -+#define REGS_EDX(r) ((r)[HOST_EDX]) -+#define REGS_ESI(r) ((r)[HOST_ESI]) -+#define REGS_EDI(r) ((r)[HOST_EDI]) -+#define REGS_EBP(r) ((r)[HOST_EBP]) -+#define REGS_CS(r) ((r)[HOST_CS]) -+#define REGS_SS(r) ((r)[HOST_SS]) -+#define REGS_DS(r) ((r)[HOST_DS]) -+#define REGS_ES(r) ((r)[HOST_ES]) -+#define REGS_FS(r) ((r)[HOST_FS]) -+#define REGS_GS(r) ((r)[HOST_GS]) -+ -+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res) -+ -+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) -+ -+#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) -+ -+#define REGS_FAULT_ADDR(r) ((r)->fault_addr) -+ -+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) -+ -+#endif -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/skas.h um/arch/um/kernel/skas/include/skas.h ---- orig/arch/um/kernel/skas/include/skas.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/include/skas.h Sun Dec 8 21:00:12 2002 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_H -+#define __SKAS_H -+ -+#include "sysdep/ptrace.h" -+ -+extern int userspace_pid; -+ -+extern void switch_threads(void *me, void *next); -+extern void thread_wait(void *sw, void *fb); -+extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, -+ void (*handler)(int)); -+extern int start_idle_thread(void *stack, void *switch_buf_ptr, -+ void **fork_buf_ptr); -+extern int user_thread(unsigned long stack, int flags); -+extern void userspace(union uml_pt_regs *regs); -+extern void new_thread_proc(void *stack, void (*handler)(int sig)); -+extern void remove_sigstack(void); -+extern void new_thread_handler(int sig); -+extern void handle_syscall(union uml_pt_regs *regs); -+extern void map(int fd, unsigned long virt, unsigned long phys, -+ unsigned long len, int r, int w, int x); -+extern int unmap(int fd, void *addr, int len); -+extern int protect(int fd, unsigned long addr, unsigned long len, -+ int r, int w, int x, int must_succeed); -+extern void user_signal(int sig, union uml_pt_regs *regs); -+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 init_registers(int pid); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/uaccess.h um/arch/um/kernel/skas/include/uaccess.h ---- orig/arch/um/kernel/skas/include/uaccess.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/include/uaccess.h Fri Jan 31 23:05:56 2003 -@@ -0,0 +1,232 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_UACCESS_H -+#define __SKAS_UACCESS_H -+ -+#include "linux/string.h" -+#include "linux/sched.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))) -+ -+static inline int verify_area_skas(int type, const void * addr, -+ unsigned long size) -+{ -+ 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); -+} -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/mem.c um/arch/um/kernel/skas/mem.c ---- orig/arch/um/kernel/skas/mem.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/mem.c Mon Dec 16 21:49:39 2002 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "mem_user.h" -+ -+unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out) -+{ -+ /* Round up to the nearest 4M */ -+ unsigned long top = ROUND_4M((unsigned long) &arg); -+ -+ *host_size_out = top; -+ *task_size_out = top; -+ return(((unsigned long) set_task_sizes_skas) & ~0xffffff); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/mem_user.c um/arch/um/kernel/skas/mem_user.c ---- orig/arch/um/kernel/skas/mem_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/mem_user.c Tue Dec 31 00:13:18 2002 -@@ -0,0 +1,95 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <sys/mman.h> -+#include <sys/ptrace.h> -+#include "mem_user.h" -+#include "user.h" -+#include "os.h" -+#include "proc_mm.h" -+ -+void map(int fd, unsigned long virt, unsigned long phys, unsigned long len, -+ int r, int w, int x) -+{ -+ struct proc_mm_op map; -+ struct mem_region *region; -+ int prot, n; -+ -+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0); -+ region = phys_region(phys); -+ -+ map = ((struct proc_mm_op) { .op = MM_MMAP, -+ .u = -+ { .mmap = -+ { .addr = virt, -+ .len = len, -+ .prot = prot, -+ .flags = MAP_SHARED | -+ MAP_FIXED, -+ .fd = region->fd, -+ .offset = phys_offset(phys) -+ } } } ); -+ n = os_write_file(fd, &map, sizeof(map)); -+ if(n != sizeof(map)) -+ printk("map : /proc/mm map failed, errno = %d\n", errno); -+} -+ -+int unmap(int fd, void *addr, int len) -+{ -+ struct proc_mm_op unmap; -+ int n; -+ -+ unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, -+ .u = -+ { .munmap = -+ { .addr = (unsigned long) addr, -+ .len = len } } } ); -+ n = os_write_file(fd, &unmap, sizeof(unmap)); -+ if((n != 0) && (n != sizeof(unmap))) -+ return(-errno); -+ return(0); -+} -+ -+int protect(int fd, unsigned long addr, unsigned long len, int r, int w, -+ int x, int must_succeed) -+{ -+ struct proc_mm_op protect; -+ int prot, n; -+ -+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0); -+ -+ protect = ((struct proc_mm_op) { .op = MM_MPROTECT, -+ .u = -+ { .mprotect = -+ { .addr = (unsigned long) addr, -+ .len = len, -+ .prot = prot } } } ); -+ -+ n = os_write_file(fd, &protect, sizeof(protect)); -+ if((n != 0) && (n != sizeof(protect))){ -+ if(must_succeed) -+ panic("protect failed, errno = %d", errno); -+ return(-errno); -+ } -+ return(0); -+} -+ -+void before_mem_skas(unsigned long unused) -+{ -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/mmu.c um/arch/um/kernel/skas/mmu.c ---- orig/arch/um/kernel/skas/mmu.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/mmu.c Wed Nov 13 13:09:57 2002 -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/list.h" -+#include "linux/spinlock.h" -+#include "linux/slab.h" -+#include "asm/segment.h" -+#include "asm/mmu.h" -+#include "os.h" -+#include "skas.h" -+ -+int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) -+{ -+ int from; -+ -+ if((current->mm != NULL) && (current->mm != &init_mm)) -+ from = current->mm->context.skas.mm_fd; -+ 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); -+ -+ return(0); -+} -+ -+void destroy_context_skas(struct mm_struct *mm) -+{ -+ os_close_file(mm->context.skas.mm_fd); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/process.c um/arch/um/kernel/skas/process.c ---- orig/arch/um/kernel/skas/process.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/process.c Wed Mar 26 14:43:19 2003 -@@ -0,0 +1,407 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <signal.h> -+#include <setjmp.h> -+#include <sched.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <sys/mman.h> -+#include <sys/user.h> -+#include <asm/unistd.h> -+#include "user.h" -+#include "ptrace_user.h" -+#include "time_user.h" -+#include "sysdep/ptrace.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "skas.h" -+#include "sysdep/sigcontext.h" -+#include "os.h" -+#include "proc_mm.h" -+#include "skas_ptrace.h" -+#include "chan_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); -+} -+ -+unsigned long exec_regs[FRAME_SIZE]; -+unsigned long exec_fp_regs[HOST_FP_SIZE]; -+unsigned long exec_fpx_regs[HOST_XFP_SIZE]; -+int have_fpx_regs = 1; -+ -+static void handle_segv(int pid) -+{ -+ struct ptrace_faultinfo fault; -+ int err; -+ -+ err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault); -+ if(err) -+ panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n", -+ errno); -+ -+ segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL); -+} -+ -+static void handle_trap(int pid, union uml_pt_regs *regs) -+{ -+ int err, syscall_nr, status; -+ -+ syscall_nr = PT_SYSCALL_NR(regs->skas.regs); -+ 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) -+ panic("handle_trap - nullifying syscall failed errno = %d\n", -+ errno); -+ -+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0); -+ if(err < 0) -+ panic("handle_trap - continuing to end of syscall failed, " -+ "errno = %d\n", errno); -+ -+ err = waitpid(pid, &status, WUNTRACED); -+ if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) -+ panic("handle_trap - failed to wait at end of syscall, " -+ "errno = %d, status = %d\n", errno, status); -+ -+ handle_syscall(regs); -+} -+ -+static int userspace_tramp(void *arg) -+{ -+ init_new_thread_signals(0); -+ enable_timer(); -+ ptrace(PTRACE_TRACEME, 0, 0, 0); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+int userspace_pid; -+ -+void start_userspace(void) -+{ -+ void *stack; -+ unsigned long sp; -+ int pid, status, n; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if(stack == MAP_FAILED) -+ panic("start_userspace : mmap failed, errno = %d", errno); -+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); -+ -+ pid = clone(userspace_tramp, (void *) sp, -+ CLONE_FILES | CLONE_VM | SIGCHLD, NULL); -+ if(pid < 0) -+ panic("start_userspace : clone failed, errno = %d", errno); -+ -+ do { -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0) -+ panic("start_userspace : wait failed, errno = %d", -+ errno); -+ } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); -+ -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) -+ panic("start_userspace : expected SIGSTOP, got status = %d", -+ status); -+ -+ if(munmap(stack, PAGE_SIZE) < 0) -+ panic("start_userspace : munmap failed, errno = %d\n", errno); -+ -+ userspace_pid = pid; -+} -+ -+void userspace(union uml_pt_regs *regs) -+{ -+ int err, status, op; -+ -+ restore_registers(regs); -+ -+ err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0); -+ if(err) -+ panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", -+ errno); -+ while(1){ -+ err = waitpid(userspace_pid, &status, WUNTRACED); -+ if(err < 0) -+ panic("userspace - waitpid failed, errno = %d\n", -+ errno); -+ -+ regs->skas.is_user = 1; -+ save_registers(regs); -+ -+ if(WIFSTOPPED(status)){ -+ switch(WSTOPSIG(status)){ -+ case SIGSEGV: -+ handle_segv(userspace_pid); -+ break; -+ case SIGTRAP: -+ handle_trap(userspace_pid, regs); -+ break; -+ case SIGIO: -+ case SIGVTALRM: -+ case SIGILL: -+ case SIGBUS: -+ case SIGFPE: -+ case SIGWINCH: -+ user_signal(WSTOPSIG(status), regs); -+ break; -+ default: -+ printk("userspace - child stopped with signal " -+ "%d\n", WSTOPSIG(status)); -+ } -+ interrupt_end(); -+ } -+ -+ restore_registers(regs); -+ -+ op = singlestepping_skas() ? PTRACE_SINGLESTEP : -+ PTRACE_SYSCALL; -+ err = ptrace(op, userspace_pid, 0, 0); -+ if(err) -+ panic("userspace - PTRACE_SYSCALL failed, " -+ "errno = %d\n", errno); -+ } -+} -+ -+void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, -+ void (*handler)(int)) -+{ -+ jmp_buf switch_buf, fork_buf; -+ -+ *switch_buf_ptr = &switch_buf; -+ *fork_buf_ptr = &fork_buf; -+ -+ if(setjmp(fork_buf) == 0) -+ new_thread_proc(stack, handler); -+ -+ remove_sigstack(); -+} -+ -+void thread_wait(void *sw, void *fb) -+{ -+ jmp_buf buf, **switch_buf = sw, *fork_buf; -+ -+ *switch_buf = &buf; -+ fork_buf = fb; -+ if(setjmp(buf) == 0) -+ longjmp(*fork_buf, 1); -+} -+ -+static int move_registers(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) -+ return(-errno); -+ if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0) -+ return(-errno); -+ return(0); -+} -+ -+void save_registers(union uml_pt_regs *regs) -+{ -+ unsigned long *fp_regs; -+ int err, fp_op; -+ -+ if(have_fpx_regs){ -+ fp_op = PTRACE_GETFPXREGS; -+ fp_regs = regs->skas.xfp; -+ } -+ else { -+ fp_op = PTRACE_GETFPREGS; -+ fp_regs = regs->skas.fp; -+ } -+ -+ err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs); -+ if(err) -+ panic("save_registers - saving registers failed, errno = %d\n", -+ err); -+} -+ -+void restore_registers(union uml_pt_regs *regs) -+{ -+ unsigned long *fp_regs; -+ int err, fp_op; -+ -+ if(have_fpx_regs){ -+ fp_op = PTRACE_SETFPXREGS; -+ fp_regs = regs->skas.xfp; -+ } -+ else { -+ fp_op = PTRACE_SETFPREGS; -+ fp_regs = regs->skas.fp; -+ } -+ -+ err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs); -+ if(err) -+ panic("restore_registers - saving registers failed, " -+ "errno = %d\n", err); -+} -+ -+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); -+} -+ -+static jmp_buf initial_jmpbuf; -+ -+/* XXX Make these percpu */ -+static void (*cb_proc)(void *arg); -+static void *cb_arg; -+static jmp_buf *cb_back; -+ -+int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) -+{ -+ jmp_buf **switch_buf = switch_buf_ptr; -+ int n; -+ -+ *fork_buf_ptr = &initial_jmpbuf; -+ n = setjmp(initial_jmpbuf); -+ 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); -+ } -+ else if(n == 3){ -+ kmalloc_ok = 0; -+ return(0); -+ } -+ else if(n == 4){ -+ kmalloc_ok = 0; -+ return(1); -+ } -+ longjmp(**switch_buf, 1); -+} -+ -+void remove_sigstack(void) -+{ -+ stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, -+ .ss_sp = NULL, -+ .ss_size = 0 }); -+ -+ if(sigaltstack(&stack, NULL) != 0) -+ panic("disabling signal stack failed, errno = %d\n", errno); -+} -+ -+void initial_thread_cb_skas(void (*proc)(void *), void *arg) -+{ -+ jmp_buf here; -+ -+ cb_proc = proc; -+ cb_arg = arg; -+ cb_back = &here; -+ -+ block_signals(); -+ if(setjmp(here) == 0) -+ longjmp(initial_jmpbuf, 2); -+ unblock_signals(); -+ -+ cb_proc = NULL; -+ cb_arg = NULL; -+ cb_back = NULL; -+} -+ -+void halt_skas(void) -+{ -+ block_signals(); -+ longjmp(initial_jmpbuf, 3); -+} -+ -+void reboot_skas(void) -+{ -+ block_signals(); -+ longjmp(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); -+ -+ if(fd < 0) -+ return(-errno); -+ -+ if(from != -1){ -+ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, -+ .u = -+ { .copy_segments = from } } ); -+ n = os_write_file(fd, ©, sizeof(copy)); -+ if(n != sizeof(copy)) -+ printk("new_mm : /proc/mm copy_segments failed, " -+ "errno = %d\n", errno); -+ } -+ return(fd); -+} -+ -+void switch_mm_skas(int mm_fd) -+{ -+ int err; -+ -+ err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd); -+ if(err) -+ panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", -+ errno); -+} -+ -+void kill_off_processes_skas(void) -+{ -+ os_kill_process(userspace_pid, 1); -+} -+ -+void init_registers(int pid) -+{ -+ int err; -+ -+ if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0) -+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", -+ errno); -+ -+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); -+ if(!err) -+ return; -+ -+ have_fpx_regs = 0; -+ if(errno != EIO) -+ panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", -+ errno); -+ -+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); -+ if(err) -+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", -+ errno); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/process_kern.c um/arch/um/kernel/skas/process_kern.c ---- orig/arch/um/kernel/skas/process_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/process_kern.c Sun Dec 22 20:37:39 2002 -@@ -0,0 +1,191 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "kern_util.h" -+#include "time_user.h" -+#include "signal_user.h" -+#include "skas.h" -+#include "os.h" -+#include "user_util.h" -+#include "tlb.h" -+#include "frame.h" -+#include "kern.h" -+#include "mode.h" -+ -+int singlestepping_skas(void) -+{ -+ int ret = current->ptrace & PT_DTRACE; -+ -+ current->ptrace &= ~PT_DTRACE; -+ return(ret); -+} -+ -+void *_switch_to_skas(void *prev, void *next) -+{ -+ struct task_struct *from, *to; -+ -+ from = prev; -+ to = next; -+ -+ /* XXX need to check runqueues[cpu].idle */ -+ if(current->pid == 0) -+ switch_timers(0); -+ -+ to->thread.prev_sched = from; -+ set_current(to); -+ -+ switch_threads(&from->thread.mode.skas.switch_buf, -+ to->thread.mode.skas.switch_buf); -+ -+ if(current->pid == 0) -+ switch_timers(1); -+ -+ return(current->thread.prev_sched); -+} -+ -+extern void schedule_tail(struct task_struct *prev); -+ -+void new_thread_handler(int sig) -+{ -+ int (*fn)(void *), n; -+ void *arg; -+ -+ fn = current->thread.request.u.thread.proc; -+ arg = current->thread.request.u.thread.arg; -+ change_sig(SIGUSR1, 1); -+ thread_wait(¤t->thread.mode.skas.switch_buf, -+ current->thread.mode.skas.fork_buf); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); -+ if(n == 1) -+ userspace(¤t->thread.regs.regs); -+ else do_exit(0); -+} -+ -+void new_thread_proc(void *stack, void (*handler)(int sig)) -+{ -+ init_new_thread_stack(stack, handler); -+ os_usr1_process(os_getpid()); -+} -+ -+void release_thread_skas(struct task_struct *task) -+{ -+} -+ -+void exit_thread_skas(void) -+{ -+} -+ -+void fork_handler(int sig) -+{ -+ change_sig(SIGUSR1, 1); -+ thread_wait(¤t->thread.mode.skas.switch_buf, -+ current->thread.mode.skas.fork_buf); -+ -+ force_flush_all(); -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ unblock_signals(); -+ -+ userspace(¤t->thread.regs.regs); -+} -+ -+int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ void (*handler)(int); -+ -+ if(current->thread.forking){ -+ memcpy(&p->thread.regs.regs.skas, -+ ¤t->thread.regs.regs.skas, -+ sizeof(p->thread.regs.regs.skas)); -+ REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); -+ if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; -+ -+ handler = fork_handler; -+ } -+ else { -+ memcpy(p->thread.regs.regs.skas.regs, exec_regs, -+ sizeof(p->thread.regs.regs.skas.regs)); -+ memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs, -+ sizeof(p->thread.regs.regs.skas.fp)); -+ memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs, -+ sizeof(p->thread.regs.regs.skas.xfp)); -+ p->thread.request.u.thread = current->thread.request.u.thread; -+ handler = new_thread_handler; -+ } -+ -+ new_thread((void *) p->thread.kernel_stack, -+ &p->thread.mode.skas.switch_buf, -+ &p->thread.mode.skas.fork_buf, handler); -+ return(0); -+} -+ -+void init_idle_skas(void) -+{ -+ cpu_tasks[current->processor].pid = os_getpid(); -+} -+ -+extern void start_kernel(void); -+ -+static int start_kernel_proc(void *unused) -+{ -+ int pid; -+ -+ block_signals(); -+ pid = os_getpid(); -+ -+ cpu_tasks[0].pid = pid; -+ cpu_tasks[0].task = current; -+#ifdef CONFIG_SMP -+ cpu_online_map = 1; -+#endif -+ start_kernel(); -+ return(0); -+} -+ -+int start_uml_skas(void) -+{ -+ start_userspace(); -+ capture_signal_stack(); -+ -+ 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; -+ return(start_idle_thread((void *) init_task.thread.kernel_stack, -+ &init_task.thread.mode.skas.switch_buf, -+ &init_task.thread.mode.skas.fork_buf)); -+} -+ -+int external_pid_skas(struct task_struct *task) -+{ -+ return(userspace_pid); -+} -+ -+int thread_pid_skas(struct thread_struct *thread) -+{ -+ return(userspace_pid); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/sys-i386/Makefile um/arch/um/kernel/skas/sys-i386/Makefile ---- orig/arch/um/kernel/skas/sys-i386/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/sys-i386/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = sys-i386.o -+ -+obj-y = sigcontext.o -+ -+USER_OBJS = sigcontext.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/sys-i386/sigcontext.c um/arch/um/kernel/skas/sys-i386/sigcontext.c ---- orig/arch/um/kernel/skas/sys-i386/sigcontext.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/sys-i386/sigcontext.c Sun Dec 8 20:38:46 2002 -@@ -0,0 +1,115 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <asm/sigcontext.h> -+#include <sys/ptrace.h> -+#include <linux/ptrace.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/ptrace_user.h" -+#include "kern_util.h" -+#include "user.h" -+#include "sigcontext.h" -+ -+extern int userspace_pid; -+ -+int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr) -+{ -+ struct sigcontext sc, *from = from_ptr; -+ unsigned long fpregs[FP_FRAME_SIZE]; -+ int err; -+ -+ err = copy_from_user_proc(&sc, from, sizeof(sc)); -+ err |= copy_from_user_proc(fpregs, sc.fpstate, sizeof(fpregs)); -+ if(err) -+ return(err); -+ -+ regs->skas.regs[GS] = sc.gs; -+ regs->skas.regs[FS] = sc.fs; -+ regs->skas.regs[ES] = sc.es; -+ regs->skas.regs[DS] = sc.ds; -+ regs->skas.regs[EDI] = sc.edi; -+ regs->skas.regs[ESI] = sc.esi; -+ regs->skas.regs[EBP] = sc.ebp; -+ regs->skas.regs[UESP] = sc.esp; -+ regs->skas.regs[EBX] = sc.ebx; -+ regs->skas.regs[EDX] = sc.edx; -+ regs->skas.regs[ECX] = sc.ecx; -+ regs->skas.regs[EAX] = sc.eax; -+ 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); -+ if(err < 0){ -+ printk("copy_sc_to_user - PTRACE_SETFPREGS failed, " -+ "errno = %d\n", errno); -+ return(1); -+ } -+ -+ 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) -+{ -+ struct sigcontext sc, *to = to_ptr; -+ struct _fpstate *to_fp; -+ unsigned long fpregs[FP_FRAME_SIZE]; -+ int err; -+ -+ sc.gs = regs->skas.regs[GS]; -+ sc.fs = regs->skas.regs[FS]; -+ sc.es = regs->skas.regs[ES]; -+ sc.ds = regs->skas.regs[DS]; -+ sc.edi = regs->skas.regs[EDI]; -+ sc.esi = regs->skas.regs[ESI]; -+ sc.ebp = regs->skas.regs[EBP]; -+ sc.esp = regs->skas.regs[UESP]; -+ sc.ebx = regs->skas.regs[EBX]; -+ sc.edx = regs->skas.regs[EDX]; -+ sc.ecx = regs->skas.regs[ECX]; -+ sc.eax = regs->skas.regs[EAX]; -+ sc.eip = regs->skas.regs[EIP]; -+ sc.cs = regs->skas.regs[CS]; -+ sc.eflags = regs->skas.regs[EFL]; -+ sc.esp_at_signal = regs->skas.regs[UESP]; -+ sc.ss = regs->skas.regs[SS]; -+ sc.cr2 = fault_addr; -+ sc.err = TO_SC_ERR(fault_type); -+ sc.trapno = regs->skas.trap_type; -+ -+ err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs); -+ if(err < 0){ -+ printk("copy_sc_to_user - PTRACE_GETFPREGS failed, " -+ "errno = %d\n", errno); -+ return(1); -+ } -+ to_fp = (struct _fpstate *) -+ (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to))); -+ sc.fpstate = to_fp; -+ -+ if(err) -+ return(err); -+ -+ return(copy_to_user_proc(to, &sc, sizeof(sc)) || -+ copy_to_user_proc(to_fp, fpregs, sizeof(fpregs))); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/syscall_kern.c um/arch/um/kernel/skas/syscall_kern.c ---- orig/arch/um/kernel/skas/syscall_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/syscall_kern.c Sun Dec 8 21:01:44 2002 -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sys.h" -+#include "asm/errno.h" -+#include "asm/unistd.h" -+#include "asm/ptrace.h" -+#include "asm/current.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+extern syscall_handler_t *sys_call_table[]; -+ -+long execute_syscall_skas(void *r) -+{ -+ struct pt_regs *regs = r; -+ long res; -+ int syscall; -+ -+ current->thread.nsyscalls++; -+ nsyscalls++; -+ syscall = UPT_SYSCALL_NR(®s->regs); -+ -+ if((syscall >= NR_syscalls) || (syscall < 0)) -+ res = -ENOSYS; -+ else res = EXECUTE_SYSCALL(syscall, regs); -+ -+ return(res); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/syscall_user.c um/arch/um/kernel/skas/syscall_user.c ---- orig/arch/um/kernel/skas/syscall_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/syscall_user.c Sun Dec 8 21:00:12 2002 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <signal.h> -+#include "kern_util.h" -+#include "syscall_user.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+ -+/* XXX Bogus */ -+#define ERESTARTSYS 512 -+#define ERESTARTNOINTR 513 -+#define ERESTARTNOHAND 514 -+ -+void handle_syscall(union uml_pt_regs *regs) -+{ -+ long result; -+ int index; -+ -+ index = record_syscall_start(UPT_SYSCALL_NR(regs)); -+ -+ syscall_trace(); -+ result = execute_syscall(regs); -+ -+ REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); -+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || -+ (result == -ERESTARTNOINTR)) -+ do_signal(result); -+ -+ syscall_trace(); -+ record_syscall_end(index, result); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/time.c um/arch/um/kernel/skas/time.c ---- orig/arch/um/kernel/skas/time.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/time.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <sys/signal.h> -+#include <sys/time.h> -+#include "time_user.h" -+#include "process.h" -+#include "user.h" -+ -+void user_time_init_skas(void) -+{ -+ if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGALRM handler"); -+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/tlb.c um/arch/um/kernel/skas/tlb.c ---- orig/arch/um/kernel/skas/tlb.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/tlb.c Sun Dec 22 18:30:35 2002 -@@ -0,0 +1,153 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/mmu.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "skas.h" -+#include "os.h" -+ -+static void fix_range(struct mm_struct *mm, unsigned long start_addr, -+ unsigned long end_addr, int force) -+{ -+ pgd_t *npgd; -+ pmd_t *npmd; -+ pte_t *npte; -+ unsigned long addr; -+ int r, w, x, err, fd; -+ -+ if(mm == NULL) return; -+ fd = mm->context.skas.mm_fd; -+ for(addr = start_addr; addr < end_addr;){ -+ npgd = pgd_offset(mm, addr); -+ npmd = pmd_offset(npgd, addr); -+ if(pmd_present(*npmd)){ -+ npte = pte_offset(npmd, addr); -+ r = pte_read(*npte); -+ w = pte_write(*npte); -+ x = pte_exec(*npte); -+ if(!pte_dirty(*npte)) w = 0; -+ if(!pte_young(*npte)){ -+ r = 0; -+ w = 0; -+ } -+ if(force || pte_newpage(*npte)){ -+ err = unmap(fd, (void *) addr, PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*npte)) -+ map(fd, addr, -+ pte_val(*npte) & PAGE_MASK, -+ PAGE_SIZE, r, w, x); -+ } -+ else if(pte_newprot(*npte)){ -+ protect(fd, addr, PAGE_SIZE, r, w, x, 1); -+ } -+ *npte = pte_mkuptodate(*npte); -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(force || pmd_newpage(*npmd)){ -+ err = unmap(fd, (void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ pmd_mkuptodate(*npmd); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+static void flush_kernel_vm_range(unsigned long start, unsigned long end) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ int updated = 0, err; -+ -+ mm = &init_mm; -+ for(addr = start_vm; addr < end_vm;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte) || pte_newpage(*pte)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*pte)) -+ map_memory(addr, -+ pte_val(*pte) & PAGE_MASK, -+ PAGE_SIZE, 1, 1, 1); -+ } -+ else if(pte_newprot(*pte)){ -+ updated = 1; -+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); -+ } -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(pmd_newpage(*pmd)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+void flush_tlb_kernel_vm_skas(void) -+{ -+ flush_kernel_vm_range(start_vm, end_vm); -+} -+ -+void __flush_tlb_one_skas(unsigned long addr) -+{ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE); -+} -+ -+void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ if(mm == NULL) -+ flush_kernel_vm_range(start, end); -+ else fix_range(mm, start, end, 0); -+} -+ -+void flush_tlb_mm_skas(struct mm_struct *mm) -+{ -+ flush_tlb_kernel_vm_skas(); -+ fix_range(mm, 0, host_task_size, 0); -+} -+ -+void force_flush_all_skas(void) -+{ -+ fix_range(current->mm, 0, host_task_size, 1); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/trap_user.c um/arch/um/kernel/skas/trap_user.c ---- orig/arch/um/kernel/skas/trap_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/trap_user.c Sun Dec 15 13:28:41 2002 -@@ -0,0 +1,65 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include <errno.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "task.h" -+#include "sigcontext.h" -+ -+void sig_handler_common_skas(int sig, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct skas_regs *r; -+ struct signal_info *info; -+ int save_errno = errno; -+ -+ r = &TASK_REGS(get_current())->skas; -+ r->is_user = 0; -+ r->fault_addr = SC_FAULT_ADDR(sc); -+ r->fault_type = SC_FAULT_TYPE(sc); -+ r->trap_type = SC_TRAP_TYPE(sc); -+ -+ change_sig(SIGUSR1, 1); -+ info = &sig_info[sig]; -+ if(!info->is_irq) unblock_signals(); -+ -+ (*info->handler)(sig, (union uml_pt_regs *) r); -+ -+ 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; -+ regs->skas.trap_type = 0; -+ info = &sig_info[sig]; -+ (*info->handler)(sig, regs); -+ -+ unblock_signals(); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/skas/util/Makefile um/arch/um/kernel/skas/util/Makefile ---- orig/arch/um/kernel/skas/util/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/util/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,10 @@ -+all: mk_ptregs -+ -+mk_ptregs : mk_ptregs.o -+ $(CC) -o mk_ptregs mk_ptregs.o -+ -+mk_ptregs.o : mk_ptregs.c -+ $(CC) -c $< -+ -+clean : -+ $(RM) -f mk_ptregs *.o *~ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/util/mk_ptregs.c um/arch/um/kernel/skas/util/mk_ptregs.c ---- orig/arch/um/kernel/skas/util/mk_ptregs.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/skas/util/mk_ptregs.c Mon Nov 11 12:10:06 2002 -@@ -0,0 +1,50 @@ -+#include <asm/ptrace.h> -+#include <asm/user.h> -+ -+#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val)) -+ -+int main(int argc, char **argv) -+{ -+ printf("/* Automatically generated by " -+ "arch/um/kernel/skas/util/mk_ptregs */\n"); -+ printf("\n"); -+ printf("#ifndef __SKAS_PT_REGS_\n"); -+ printf("#define __SKAS_PT_REGS_\n"); -+ printf("\n"); -+ printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE); -+ printf("#define HOST_FP_SIZE %d\n", -+ sizeof(struct user_i387_struct) / sizeof(unsigned long)); -+ printf("#define HOST_XFP_SIZE %d\n", -+ sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); -+ -+ PRINT_REG("IP", EIP); -+ PRINT_REG("SP", UESP); -+ PRINT_REG("EFLAGS", EFL); -+ PRINT_REG("EAX", EAX); -+ PRINT_REG("EBX", EBX); -+ PRINT_REG("ECX", ECX); -+ PRINT_REG("EDX", EDX); -+ PRINT_REG("ESI", ESI); -+ PRINT_REG("EDI", EDI); -+ PRINT_REG("EBP", EBP); -+ PRINT_REG("CS", CS); -+ PRINT_REG("SS", SS); -+ PRINT_REG("DS", DS); -+ PRINT_REG("FS", FS); -+ PRINT_REG("ES", ES); -+ PRINT_REG("GS", GS); -+ printf("\n"); -+ printf("#endif\n"); -+ 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 -Naur -X ../exclude-files orig/arch/um/kernel/smp.c um/arch/um/kernel/smp.c ---- orig/arch/um/kernel/smp.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/smp.c Sat Feb 22 14:28:45 2003 -@@ -0,0 +1,324 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+ -+ -+#ifdef CONFIG_SMP -+ -+#include "linux/sched.h" -+#include "linux/threads.h" -+#include "linux/interrupt.h" -+#include "asm/smp.h" -+#include "asm/processor.h" -+#include "asm/spinlock.h" -+#include "asm/softirq.h" -+#include "asm/hardirq.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "kern.h" -+#include "os.h" -+ -+/* Total count of live CPUs, set by smp_boot_cpus */ -+int smp_num_cpus = 1; -+ -+/* The 'big kernel lock' */ -+spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED}; -+ -+/* Per CPU bogomips and other parameters */ -+ -+/* The only piece used here is the ipi pipe, which is set before SMP is -+ * started and never changed. -+ */ -+struct cpuinfo_um cpu_data[NR_CPUS]; -+ -+/* CPU online map, set by smp_boot_cpus */ -+unsigned long cpu_online_map; -+ -+atomic_t global_bh_count; -+ -+/* Set when the idlers are all forked */ -+int smp_threads_ready = 0; -+ -+/* Not used by UML */ -+unsigned char global_irq_holder = 0; -+unsigned volatile long global_irq_lock; -+ -+/* A statistic, can be a little off */ -+static int num_reschedules_sent = 0; -+ -+void smp_send_reschedule(int cpu) -+{ -+ write(cpu_data[cpu].ipi_pipe[1], "R", 1); -+ num_reschedules_sent++; -+} -+ -+static void show(char * str) -+{ -+ int cpu = smp_processor_id(); -+ -+ printk(KERN_INFO "\n%s, CPU %d:\n", str, cpu); -+} -+ -+#define MAXCOUNT 100000000 -+ -+static inline void wait_on_bh(void) -+{ -+ int count = MAXCOUNT; -+ do { -+ if (!--count) { -+ show("wait_on_bh"); -+ count = ~0; -+ } -+ /* nothing .. wait for the other bh's to go away */ -+ } while (atomic_read(&global_bh_count) != 0); -+} -+ -+/* -+ * This is called when we want to synchronize with -+ * bottom half handlers. We need to wait until -+ * no other CPU is executing any bottom half handler. -+ * -+ * Don't wait if we're already running in an interrupt -+ * context or are inside a bh handler. -+ */ -+void synchronize_bh(void) -+{ -+ if (atomic_read(&global_bh_count) && !in_interrupt()) -+ wait_on_bh(); -+} -+ -+void smp_send_stop(void) -+{ -+ int i; -+ -+ printk(KERN_INFO "Stopping all CPUs..."); -+ for(i = 0; i < ncpus; i++){ -+ if(i == current->processor) -+ continue; -+ write(cpu_data[i].ipi_pipe[1], "S", 1); -+ } -+ printk("done\n"); -+} -+ -+ -+static atomic_t smp_commenced = ATOMIC_INIT(0); -+static volatile unsigned long smp_callin_map = 0; -+ -+void smp_commence(void) -+{ -+ printk("All CPUs are go!\n"); -+ -+ wmb(); -+ atomic_set(&smp_commenced, 1); -+} -+ -+static int idle_proc(void *unused) -+{ -+ int cpu, err; -+ -+ set_current(current); -+ del_from_runqueue(current); -+ unhash_process(current); -+ -+ cpu = current->processor; -+ err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); -+ if(err) -+ panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, -+ -err); -+ -+ activate_ipi(cpu_data[cpu].ipi_pipe[0], -+ current->thread.mode.tt.extern_pid); -+ -+ wmb(); -+ if (test_and_set_bit(current->processor, &smp_callin_map)) { -+ printk("huh, CPU#%d already present??\n", current->processor); -+ BUG(); -+ } -+ -+ while (!atomic_read(&smp_commenced)) -+ cpu_relax(); -+ -+ init_idle(); -+ cpu_idle(); -+ return(0); -+} -+ -+static int idle_thread(int (*fn)(void *), int cpu) -+{ -+ struct task_struct *new_task; -+ int pid; -+ unsigned char c; -+ -+ current->thread.request.u.thread.proc = fn; -+ current->thread.request.u.thread.arg = NULL; -+ pid = do_fork(CLONE_VM | CLONE_PID, 0, NULL, 0); -+ if(pid < 0) panic("do_fork failed in idle_thread"); -+ new_task = get_task(pid, 1); -+ -+ cpu_tasks[cpu].pid = new_task->thread.mode.tt.extern_pid; -+ cpu_tasks[cpu].task = new_task; -+ init_tasks[cpu] = new_task; -+ new_task->processor = cpu; -+ new_task->cpus_allowed = 1 << cpu; -+ new_task->cpus_runnable = new_task->cpus_allowed; -+ CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c, -+ sizeof(c)), -+ ({ panic("skas mode doesn't support SMP"); })); -+ return(new_task->thread.mode.tt.extern_pid); -+} -+ -+void smp_boot_cpus(void) -+{ -+ int err; -+ -+ set_bit(0, &cpu_online_map); -+ set_bit(0, &smp_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); -+ -+ activate_ipi(cpu_data[0].ipi_pipe[0], -+ current->thread.mode.tt.extern_pid); -+ -+ if(ncpus < 1){ -+ printk(KERN_INFO "ncpus set to 1\n"); -+ ncpus = 1; -+ } -+ else if(ncpus > NR_CPUS){ -+ printk(KERN_INFO -+ "ncpus can't be greater than NR_CPUS, set to %d\n", -+ NR_CPUS); -+ ncpus = NR_CPUS; -+ } -+ -+ if(ncpus > 1){ -+ int i, pid; -+ -+ printk(KERN_INFO "Starting up other processors:\n"); -+ for(i=1;i<ncpus;i++){ -+ int waittime; -+ -+ /* Do this early, for hard_smp_processor_id() */ -+ cpu_tasks[i].pid = -1; -+ set_bit(i, &cpu_online_map); -+ smp_num_cpus++; -+ -+ pid = idle_thread(idle_proc, i); -+ printk(KERN_INFO "\t#%d - idle thread pid = %d.. ", -+ i, pid); -+ -+ waittime = 200000000; -+ while (waittime-- && !test_bit(i, &smp_callin_map)) -+ cpu_relax(); -+ -+ if (test_bit(i, &smp_callin_map)) -+ printk("online\n"); -+ else { -+ printk("failed\n"); -+ clear_bit(i, &cpu_online_map); -+ } -+ } -+ } -+} -+ -+int setup_profiling_timer(unsigned int multiplier) -+{ -+ printk(KERN_INFO "setup_profiling_timer\n"); -+ return(0); -+} -+ -+void smp_call_function_slave(int cpu); -+ -+void IPI_handler(int cpu) -+{ -+ unsigned char c; -+ int fd; -+ -+ fd = cpu_data[cpu].ipi_pipe[0]; -+ while (read(fd, &c, 1) == 1) { -+ switch (c) { -+ case 'C': -+ smp_call_function_slave(cpu); -+ break; -+ -+ case 'R': -+ current->need_resched = 1; -+ break; -+ -+ case 'S': -+ printk("CPU#%d stopping\n", cpu); -+ while(1) -+ pause(); -+ break; -+ -+ default: -+ printk("CPU#%d received unknown IPI [%c]!\n", cpu, c); -+ break; -+ } -+ } -+} -+ -+int hard_smp_processor_id(void) -+{ -+ return(pid_to_processor_id(os_getpid())); -+} -+ -+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED; -+static atomic_t scf_started; -+static atomic_t scf_finished; -+static void (*func)(void *info); -+static void *info; -+ -+void smp_call_function_slave(int cpu) -+{ -+ atomic_inc(&scf_started); -+ (*func)(info); -+ atomic_inc(&scf_finished); -+} -+ -+int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, -+ int wait) -+{ -+ int cpus = smp_num_cpus - 1; -+ int i; -+ -+ if (!cpus) -+ return 0; -+ -+ spin_lock_bh(&call_lock); -+ atomic_set(&scf_started, 0); -+ atomic_set(&scf_finished, 0); -+ func = _func; -+ info = _info; -+ -+ for (i=0;i<NR_CPUS;i++) -+ if (i != current->processor && test_bit(i, &cpu_online_map)) -+ write(cpu_data[i].ipi_pipe[1], "C", 1); -+ -+ while (atomic_read(&scf_started) != cpus) -+ barrier(); -+ -+ if (wait) -+ while (atomic_read(&scf_finished) != cpus) -+ barrier(); -+ -+ spin_unlock_bh(&call_lock); -+ return 0; -+} -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/sys_call_table.c um/arch/um/kernel/sys_call_table.c ---- orig/arch/um/kernel/sys_call_table.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/sys_call_table.c Thu Feb 27 13:33:23 2003 -@@ -0,0 +1,485 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/unistd.h" -+#include "linux/version.h" -+#include "linux/sys.h" -+#include "asm/signal.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_exit; -+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_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_uselib; -+extern syscall_handler_t sys_swapon; -+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_create_module; -+extern syscall_handler_t sys_init_module; -+extern syscall_handler_t sys_delete_module; -+extern syscall_handler_t sys_get_kernel_syms; -+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_sysctl; -+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_query_module; -+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_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_pread; -+extern syscall_handler_t sys_pwrite; -+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_setxattr; -+extern syscall_handler_t sys_lsetxattr; -+extern syscall_handler_t sys_fsetxattr; -+extern syscall_handler_t sys_getxattr; -+extern syscall_handler_t sys_lgetxattr; -+extern syscall_handler_t sys_fgetxattr; -+extern syscall_handler_t sys_listxattr; -+extern syscall_handler_t sys_llistxattr; -+extern syscall_handler_t sys_flistxattr; -+extern syscall_handler_t sys_removexattr; -+extern syscall_handler_t sys_lremovexattr; -+extern syscall_handler_t sys_fremovexattr; -+ -+extern syscall_handler_t um_mount; -+extern syscall_handler_t um_time; -+extern syscall_handler_t um_stime; -+ -+#define LAST_GENERIC_SYSCALL __NR_sched_getaffinity -+ -+#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL -+#define LAST_SYSCALL LAST_GENERIC_SYSCALL -+#else -+#define LAST_SYSCALL LAST_ARCH_SYSCALL -+#endif -+ -+syscall_handler_t *sys_call_table[] = { -+ [ 0 ] = sys_ni_syscall, -+ [ __NR_exit ] = sys_exit, -+ [ __NR_fork ] = sys_fork, -+ [ __NR_read ] = (syscall_handler_t *) sys_read, -+ [ __NR_write ] = (syscall_handler_t *) sys_write, -+ -+ /* These three are declared differently in asm/unistd.h */ -+ [ __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, -+ -+ /* declared differently in kern_util.h */ -+ [ __NR_execve ] = (syscall_handler_t *) sys_execve, -+ [ __NR_chdir ] = 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_lseek ] = (syscall_handler_t *) sys_lseek, -+ [ __NR_getpid ] = sys_getpid, -+ [ __NR_mount ] = um_mount, -+ [ __NR_umount ] = sys_oldumount, -+ [ __NR_setuid ] = sys_setuid16, -+ [ __NR_getuid ] = 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, -+ -+ /* 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_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_swapon ] = sys_swapon, -+ [ __NR_reboot ] = 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_wait4 ] = (syscall_handler_t *) sys_wait4, -+ [ __NR_swapoff ] = 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_create_module, -+ [ __NR_init_module ] = sys_init_module, -+ [ __NR_delete_module ] = sys_delete_module, -+ [ __NR_get_kernel_syms ] = sys_get_kernel_syms, -+ [ __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__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__sysctl ] = 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_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_query_module, -+ [ __NR_poll ] = sys_poll, -+ [ __NR_nfsservctl ] = sys_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_pread ] = sys_pread, -+ [ __NR_pwrite ] = sys_pwrite, -+ [ __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_security ] = sys_ni_syscall, -+ [ __NR_gettid ] = sys_gettid, -+ [ __NR_readahead ] = sys_readahead, -+ [ __NR_setxattr ] = sys_setxattr, -+ [ __NR_lsetxattr ] = sys_lsetxattr, -+ [ __NR_fsetxattr ] = sys_fsetxattr, -+ [ __NR_getxattr ] = sys_getxattr, -+ [ __NR_lgetxattr ] = sys_lgetxattr, -+ [ __NR_fgetxattr ] = sys_fgetxattr, -+ [ __NR_listxattr ] = sys_listxattr, -+ [ __NR_llistxattr ] = sys_llistxattr, -+ [ __NR_flistxattr ] = sys_flistxattr, -+ [ __NR_removexattr ] = sys_removexattr, -+ [ __NR_lremovexattr ] = sys_lremovexattr, -+ [ __NR_fremovexattr ] = sys_fremovexattr, -+ [ __NR_tkill ] = sys_tkill, -+ [ __NR_sendfile64 ] = sys_ni_syscall, -+ [ __NR_futex ] = sys_ni_syscall, -+ [ __NR_sched_setaffinity ] = sys_ni_syscall, -+ [ __NR_sched_getaffinity ] = sys_ni_syscall, -+ -+ ARCH_SYSCALLS -+ [ LAST_SYSCALL + 1 ... NR_syscalls ] = -+ (syscall_handler_t *) sys_ni_syscall -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/syscall_kern.c um/arch/um/kernel/syscall_kern.c ---- orig/arch/um/kernel/syscall_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/syscall_kern.c Fri Nov 8 14:04:10 2002 -@@ -0,0 +1,343 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/file.h" -+#include "linux/smp_lock.h" -+#include "linux/mm.h" -+#include "linux/utsname.h" -+#include "linux/msg.h" -+#include "linux/shm.h" -+#include "linux/sys.h" -+#include "linux/unistd.h" -+#include "linux/slab.h" -+#include "linux/utime.h" -+#include "asm/mman.h" -+#include "asm/uaccess.h" -+#include "asm/ipc.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "sysdep/syscalls.h" -+#include "mode_kern.h" -+#include "choose-mode.h" -+ -+/* Unlocked, I don't care if this is a bit off */ -+int nsyscalls = 0; -+ -+long um_mount(char * dev_name, char * dir_name, char * type, -+ unsigned long new_flags, void * data) -+{ -+ if(type == NULL) type = ""; -+ return(sys_mount(dev_name, dir_name, type, new_flags, data)); -+} -+ -+long sys_fork(void) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(SIGCHLD, 0, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+long sys_clone(unsigned long clone_flags, unsigned long newsp) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(clone_flags, newsp, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+long sys_vfork(void) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+/* common code for old and new mmaps */ -+long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, unsigned long fd, -+ unsigned long pgoff) -+{ -+ int error = -EBADF; -+ struct file * file = NULL; -+ -+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); -+ if (!(flags & MAP_ANONYMOUS)) { -+ file = fget(fd); -+ if (!file) -+ goto out; -+ } -+ -+ down_write(&mm->mmap_sem); -+ error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff); -+ up_write(&mm->mmap_sem); -+ -+ if (file) -+ fput(file); -+ out: -+ return error; -+} -+ -+long sys_mmap2(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long pgoff) -+{ -+ return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff); -+} -+ -+/* -+ * Perform the select(nd, in, out, ex, tv) and mmap() system -+ * calls. Linux/i386 didn't use to be able to handle more than -+ * 4 system call parameters, so these system calls used a memory -+ * block for parameter passing.. -+ */ -+ -+struct mmap_arg_struct { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset) -+{ -+ int err = -EINVAL; -+ if (offset & ~PAGE_MASK) -+ goto out; -+ -+ err = do_mmap2(current->mm, addr, len, prot, flags, fd, -+ offset >> PAGE_SHIFT); -+ out: -+ return err; -+} -+/* -+ * sys_pipe() is the normal C calling standard for creating -+ * a pipe. It's not the way unix traditionally does this, though. -+ */ -+int sys_pipe(unsigned long * fildes) -+{ -+ int fd[2]; -+ int error; -+ -+ error = do_pipe(fd); -+ if (!error) { -+ if (copy_to_user(fildes, fd, 2*sizeof(int))) -+ error = -EFAULT; -+ } -+ return error; -+} -+ -+int sys_pause(void) -+{ -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ return -ERESTARTNOHAND; -+} -+ -+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.. -+ * -+ * This is really horribly ugly. -+ */ -+int sys_ipc (uint call, int first, int second, -+ int third, void *ptr, long fifth) -+{ -+ int version, ret; -+ -+ version = call >> 16; /* hack for backward compatibility */ -+ call &= 0xffff; -+ -+ switch (call) { -+ case SEMOP: -+ return sys_semop (first, (struct sembuf *)ptr, second); -+ case SEMGET: -+ return sys_semget (first, second, third); -+ case SEMCTL: { -+ union semun fourth; -+ if (!ptr) -+ return -EINVAL; -+ if (get_user(fourth.__pad, (void **) ptr)) -+ return -EFAULT; -+ return sys_semctl (first, second, third, fourth); -+ } -+ -+ case MSGSND: -+ return sys_msgsnd (first, (struct msgbuf *) ptr, -+ second, third); -+ case MSGRCV: -+ switch (version) { -+ case 0: { -+ struct ipc_kludge tmp; -+ if (!ptr) -+ return -EINVAL; -+ -+ if (copy_from_user(&tmp, -+ (struct ipc_kludge *) ptr, -+ sizeof (tmp))) -+ return -EFAULT; -+ return sys_msgrcv (first, tmp.msgp, second, -+ tmp.msgtyp, third); -+ } -+ default: -+ panic("msgrcv with version != 0"); -+ return sys_msgrcv (first, -+ (struct msgbuf *) ptr, -+ second, fifth, third); -+ } -+ case MSGGET: -+ return sys_msgget ((key_t) first, second); -+ case MSGCTL: -+ return sys_msgctl (first, second, (struct msqid_ds *) ptr); -+ -+ case SHMAT: -+ switch (version) { -+ default: { -+ ulong raddr; -+ ret = sys_shmat (first, (char *) ptr, second, &raddr); -+ if (ret) -+ return ret; -+ return put_user (raddr, (ulong *) third); -+ } -+ case 1: /* iBCS2 emulator entry point */ -+ if (!segment_eq(get_fs(), get_ds())) -+ return -EINVAL; -+ return sys_shmat (first, (char *) ptr, second, (ulong *) third); -+ } -+ case SHMDT: -+ return sys_shmdt ((char *)ptr); -+ case SHMGET: -+ return sys_shmget (first, second, third); -+ case SHMCTL: -+ return sys_shmctl (first, second, -+ (struct shmid_ds *) ptr); -+ default: -+ return -EINVAL; -+ } -+} -+ -+int sys_uname(struct old_utsname * name) -+{ -+ int err; -+ if (!name) -+ return -EFAULT; -+ down_read(&uts_sem); -+ err=copy_to_user(name, &system_utsname, sizeof (*name)); -+ up_read(&uts_sem); -+ return err?-EFAULT:0; -+} -+ -+int sys_olduname(struct oldold_utsname * name) -+{ -+ int error; -+ -+ if (!name) -+ return -EFAULT; -+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) -+ return -EFAULT; -+ -+ down_read(&uts_sem); -+ -+ error = __copy_to_user(&name->sysname,&system_utsname.sysname, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->sysname+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->nodename+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->release,&system_utsname.release, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->release+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->version,&system_utsname.version, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->version+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->machine,&system_utsname.machine, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->machine+__OLD_UTS_LEN); -+ -+ up_read(&uts_sem); -+ -+ error = error ? -EFAULT : 0; -+ -+ 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)); -+} -+ -+spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED; -+ -+static int syscall_index = 0; -+ -+int next_syscall_index(int limit) -+{ -+ int ret; -+ -+ spin_lock(&syscall_lock); -+ ret = syscall_index; -+ if(++syscall_index == limit) -+ syscall_index = 0; -+ spin_unlock(&syscall_lock); -+ return(ret); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/syscall_user.c um/arch/um/kernel/syscall_user.c ---- orig/arch/um/kernel/syscall_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/syscall_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <sys/time.h> -+#include "kern_util.h" -+#include "syscall_user.h" -+ -+struct { -+ int syscall; -+ int pid; -+ int result; -+ struct timeval start; -+ struct timeval end; -+} syscall_record[1024]; -+ -+int record_syscall_start(int syscall) -+{ -+ int max, index; -+ -+ max = sizeof(syscall_record)/sizeof(syscall_record[0]); -+ index = next_syscall_index(max); -+ -+ syscall_record[index].syscall = syscall; -+ syscall_record[index].pid = current_pid(); -+ syscall_record[index].result = 0xdeadbeef; -+ gettimeofday(&syscall_record[index].start, NULL); -+ return(index); -+} -+ -+void record_syscall_end(int index, int result) -+{ -+ syscall_record[index].result = result; -+ gettimeofday(&syscall_record[index].end, NULL); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/sysrq.c um/arch/um/kernel/sysrq.c ---- orig/arch/um/kernel/sysrq.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/sysrq.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/kernel.h" -+#include "linux/module.h" -+#include "asm/page.h" -+#include "asm/processor.h" -+#include "sysrq.h" -+#include "user_util.h" -+ -+ /* -+ * If the address is either in the .text section of the -+ * kernel, or in the vmalloc'ed module regions, it *may* -+ * be the address of a calling routine -+ */ -+ -+#ifdef CONFIG_MODULES -+ -+extern struct module *module_list; -+extern struct module kernel_module; -+ -+static inline int kernel_text_address(unsigned long addr) -+{ -+ int retval = 0; -+ struct module *mod; -+ -+ if (addr >= (unsigned long) &_stext && -+ addr <= (unsigned long) &_etext) -+ return 1; -+ -+ for (mod = module_list; mod != &kernel_module; mod = mod->next) { -+ /* mod_bound tests for addr being inside the vmalloc'ed -+ * module area. Of course it'd be better to test only -+ * for the .text subset... */ -+ if (mod_bound(addr, 0, mod)) { -+ retval = 1; -+ break; -+ } -+ } -+ -+ return retval; -+} -+ -+#else -+ -+static inline int kernel_text_address(unsigned long addr) -+{ -+ return (addr >= (unsigned long) &_stext && -+ addr <= (unsigned long) &_etext); -+} -+ -+#endif -+ -+void show_trace(unsigned long * stack) -+{ -+ int i; -+ unsigned long addr; -+ -+ if (!stack) -+ stack = (unsigned long*) &stack; -+ -+ printk("Call Trace: "); -+ i = 1; -+ while (((long) stack & (THREAD_SIZE-1)) != 0) { -+ addr = *stack++; -+ if (kernel_text_address(addr)) { -+ if (i && ((i % 6) == 0)) -+ printk("\n "); -+ printk("[<%08lx>] ", addr); -+ i++; -+ } -+ } -+ printk("\n"); -+} -+ -+void show_trace_task(struct task_struct *tsk) -+{ -+ unsigned long esp = PT_REGS_SP(&tsk->thread.regs); -+ -+ /* User space on another CPU? */ -+ if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ return; -+ show_trace((unsigned long *)esp); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tempfile.c um/arch/um/kernel/tempfile.c ---- orig/arch/um/kernel/tempfile.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tempfile.c Fri Jan 17 23:16:19 2003 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <string.h> -+#include <errno.h> -+#include <sys/param.h> -+#include "init.h" -+ -+/* Modified from create_mem_file and start_debugger */ -+static char *tempdir = NULL; -+ -+static void __init find_tempdir(void) -+{ -+ char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; -+ int i; -+ char *dir = NULL; -+ -+ if(tempdir != NULL) return; /* We've already been called */ -+ for(i = 0; dirs[i]; i++){ -+ dir = getenv(dirs[i]); -+ if((dir != NULL) && (*dir != '\0')) -+ break; -+ } -+ if((dir == NULL) || (*dir == '\0')) -+ dir = "/tmp"; -+ -+ tempdir = malloc(strlen(dir) + 2); -+ if(tempdir == NULL){ -+ fprintf(stderr, "Failed to malloc tempdir, " -+ "errno = %d\n", errno); -+ return; -+ } -+ strcpy(tempdir, dir); -+ strcat(tempdir, "/"); -+} -+ -+int make_tempfile(const char *template, char **out_tempname, int do_unlink) -+{ -+ char tempname[MAXPATHLEN]; -+ int fd; -+ -+ find_tempdir(); -+ if (*template != '/') -+ strcpy(tempname, tempdir); -+ else -+ *tempname = 0; -+ strcat(tempname, template); -+ if((fd = mkstemp(tempname)) < 0){ -+ fprintf(stderr, "open - cannot create %s: %s\n", tempname, -+ strerror(errno)); -+ return -1; -+ } -+ if(do_unlink && (unlink(tempname) < 0)){ -+ perror("unlink"); -+ return -1; -+ } -+ if(out_tempname){ -+ if((*out_tempname = strdup(tempname)) == NULL){ -+ perror("strdup"); -+ return -1; -+ } -+ } -+ return(fd); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/time.c um/arch/um/kernel/time.c ---- orig/arch/um/kernel/time.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/time.c Wed Jan 8 13:02:53 2003 -@@ -0,0 +1,126 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <time.h> -+#include <sys/time.h> -+#include <signal.h> -+#include <errno.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_user.h" -+#include "time_user.h" -+ -+extern struct timeval xtime; -+ -+void timer(void) -+{ -+ gettimeofday(&xtime, NULL); -+} -+ -+void set_interval(int timer_type) -+{ -+ int usec = 1000000/hz(); -+ struct itimerval interval = ((struct itimerval) { { 0, usec }, -+ { 0, usec } }); -+ -+ if(setitimer(timer_type, &interval, NULL) == -1) -+ panic("setitimer failed - errno = %d\n", errno); -+} -+ -+void enable_timer(void) -+{ -+ int usec = 1000000/hz(); -+ struct itimerval enable = ((struct itimerval) { { 0, usec }, -+ { 0, usec }}); -+ if(setitimer(ITIMER_VIRTUAL, &enable, NULL)) -+ printk("enable_timer - setitimer failed, errno = %d\n", -+ errno); -+} -+ -+void switch_timers(int to_real) -+{ -+ struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); -+ struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, -+ { 0, 1000000/hz() }}); -+ int old, new; -+ -+ if(to_real){ -+ old = ITIMER_VIRTUAL; -+ new = ITIMER_REAL; -+ } -+ else { -+ old = ITIMER_REAL; -+ new = ITIMER_VIRTUAL; -+ } -+ -+ if((setitimer(old, &disable, NULL) < 0) || -+ (setitimer(new, &enable, NULL))) -+ printk("switch_timers - setitimer failed, errno = %d\n", -+ errno); -+} -+ -+void idle_timer(void) -+{ -+ if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) -+ panic("Couldn't unset SIGVTALRM handler"); -+ -+ set_handler(SIGALRM, (__sighandler_t) alarm_handler, -+ SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); -+ set_interval(ITIMER_REAL); -+} -+ -+void time_init(void) -+{ -+ if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+struct timeval local_offset = { 0, 0 }; -+ -+void do_gettimeofday(struct timeval *tv) -+{ -+ unsigned long flags; -+ -+ flags = time_lock(); -+ gettimeofday(tv, NULL); -+ timeradd(tv, &local_offset, tv); -+ time_unlock(flags); -+} -+ -+void do_settimeofday(struct timeval *tv) -+{ -+ struct timeval now; -+ unsigned long flags; -+ -+ flags = time_lock(); -+ gettimeofday(&now, NULL); -+ timersub(tv, &now, &local_offset); -+ time_unlock(flags); -+} -+ -+void idle_sleep(int secs) -+{ -+ struct timespec ts; -+ -+ ts.tv_sec = secs; -+ ts.tv_nsec = 0; -+ nanosleep(&ts, NULL); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/time_kern.c um/arch/um/kernel/time_kern.c ---- orig/arch/um/kernel/time_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/time_kern.c Wed Jan 8 13:04:50 2003 -@@ -0,0 +1,170 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/unistd.h" -+#include "linux/stddef.h" -+#include "linux/spinlock.h" -+#include "linux/sched.h" -+#include "linux/interrupt.h" -+#include "linux/init.h" -+#include "linux/delay.h" -+#include "asm/irq.h" -+#include "asm/param.h" -+#include "asm/current.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "time_user.h" -+#include "mode.h" -+ -+extern rwlock_t xtime_lock; -+ -+int hz(void) -+{ -+ return(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]; -+ -+void timer_irq(union uml_pt_regs *regs) -+{ -+ int cpu = current->processor, ticks = missed_ticks[cpu]; -+ -+ if(!timer_irq_inited) return; -+ missed_ticks[cpu] = 0; -+ while(ticks--) do_IRQ(TIMER_IRQ, regs); -+} -+ -+void boot_timer_handler(int sig) -+{ -+ struct pt_regs regs; -+ -+ CHOOSE_MODE((void) -+ (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)), -+ (void) (regs.regs.skas.is_user = 0)); -+ do_timer(®s); -+} -+ -+void um_timer(int irq, void *dev, struct pt_regs *regs) -+{ -+ do_timer(regs); -+ write_lock(&xtime_lock); -+ timer(); -+ write_unlock(&xtime_lock); -+} -+ -+long um_time(int * tloc) -+{ -+ struct timeval now; -+ -+ do_gettimeofday(&now); -+ if (tloc) { -+ if (put_user(now.tv_sec,tloc)) -+ now.tv_sec = -EFAULT; -+ } -+ return now.tv_sec; -+} -+ -+long um_stime(int * tptr) -+{ -+ int value; -+ struct timeval new; -+ -+ if (get_user(value, tptr)) -+ return -EFAULT; -+ new.tv_sec = value; -+ new.tv_usec = 0; -+ do_settimeofday(&new); -+ return 0; -+} -+ -+/* XXX Needs to be moved under sys-i386 */ -+void __delay(um_udelay_t time) -+{ -+ /* Stolen from the i386 __loop_delay */ -+ int d0; -+ __asm__ __volatile__( -+ "\tjmp 1f\n" -+ ".align 16\n" -+ "1:\tjmp 2f\n" -+ ".align 16\n" -+ "2:\tdecl %0\n\tjns 2b" -+ :"=&a" (d0) -+ :"0" (time)); -+} -+ -+void __udelay(um_udelay_t usecs) -+{ -+ int i, n; -+ -+ n = (loops_per_jiffy * HZ * usecs) / 1000000; -+ for(i=0;i<n;i++) ; -+} -+ -+void __const_udelay(um_udelay_t usecs) -+{ -+ int i, n; -+ -+ n = (loops_per_jiffy * HZ * usecs) / 1000000; -+ for(i=0;i<n;i++) ; -+} -+ -+void timer_handler(int sig, union uml_pt_regs *regs) -+{ -+#ifdef CONFIG_SMP -+ update_process_times(user_context(UPT_SP(regs))); -+#endif -+ if(current->processor == 0) -+ timer_irq(regs); -+} -+ -+static spinlock_t timer_spinlock = SPIN_LOCK_UNLOCKED; -+ -+unsigned long time_lock(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&timer_spinlock, flags); -+ return(flags); -+} -+ -+void time_unlock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&timer_spinlock, flags); -+} -+ -+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) -+ printk(KERN_ERR "timer_init : request_irq failed - " -+ "errno = %d\n", -err); -+ timer_irq_inited = 1; -+ return(0); -+} -+ -+__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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tlb.c um/arch/um/kernel/tlb.c ---- orig/arch/um/kernel/tlb.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tlb.c Wed Oct 23 22:15:51 2002 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/mm.h" -+#include "asm/page.h" -+#include "asm/pgalloc.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+ -+void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) -+{ -+ address &= PAGE_MASK; -+ flush_tlb_range(vma->vm_mm, address, address + PAGE_SIZE); -+} -+ -+void flush_tlb_all(void) -+{ -+ flush_tlb_mm(current->mm); -+} -+ -+void flush_tlb_kernel_vm(void) -+{ -+ CHOOSE_MODE(flush_tlb_kernel_vm_tt(), flush_tlb_kernel_vm_skas()); -+} -+ -+void __flush_tlb_one(unsigned long addr) -+{ -+ CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); -+} -+ -+void flush_tlb_range(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, mm, start, -+ end); -+} -+ -+void flush_tlb_mm(struct mm_struct *mm) -+{ -+ CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); -+} -+ -+void force_flush_all(void) -+{ -+ CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); -+} -+ -+ -+pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) -+{ -+ return(pgd_offset(mm, address)); -+} -+ -+pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address) -+{ -+ return(pmd_offset(pgd, address)); -+} -+ -+pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) -+{ -+ return(pte_offset(pmd, address)); -+} -+ -+pte_t *addr_pte(struct task_struct *task, unsigned long addr) -+{ -+ return(pte_offset(pmd_offset(pgd_offset(task->mm, addr), addr), addr)); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/trap_kern.c um/arch/um/kernel/trap_kern.c ---- orig/arch/um/kernel/trap_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/trap_kern.c Wed Mar 26 13:26:00 2003 -@@ -0,0 +1,192 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/mm.h" -+#include "linux/spinlock.h" -+#include "linux/config.h" -+#include "linux/init.h" -+#include "asm/semaphore.h" -+#include "asm/pgtable.h" -+#include "asm/pgalloc.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" -+ -+unsigned long handle_page_fault(unsigned long address, unsigned long ip, -+ int is_write, int is_user, int *code_out) -+{ -+ struct mm_struct *mm = current->mm; -+ struct vm_area_struct *vma; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long page; -+ int handled = 0; -+ -+ *code_out = SEGV_MAPERR; -+ down_read(&mm->mmap_sem); -+ vma = find_vma(mm, address); -+ if(!vma) -+ goto out; -+ else if(vma->vm_start <= address) -+ goto good_area; -+ else if(!(vma->vm_flags & VM_GROWSDOWN)) -+ goto out; -+ else if(expand_stack(vma, address)) -+ goto out; -+ -+ good_area: -+ *code_out = SEGV_ACCERR; -+ if(is_write && !(vma->vm_flags & VM_WRITE)) -+ goto out; -+ page = address & PAGE_MASK; -+ if(page == (unsigned long) current + PAGE_SIZE) -+ panic("Kernel stack overflow"); -+ pgd = pgd_offset(mm, page); -+ pmd = pmd_offset(pgd, page); -+ do { -+ survive: -+ switch (handle_mm_fault(mm, vma, address, is_write)) { -+ case 1: -+ current->min_flt++; -+ break; -+ case 2: -+ current->maj_flt++; -+ break; -+ default: -+ if (current->pid == 1) { -+ up_read(&mm->mmap_sem); -+ yield(); -+ down_read(&mm->mmap_sem); -+ goto survive; -+ } -+ /* Fall through to bad area case */ -+ case 0: -+ goto out; -+ } -+ pte = pte_offset(pmd, page); -+ } while(!pte_present(*pte)); -+ handled = 1; -+ *pte = pte_mkyoung(*pte); -+ if(pte_write(*pte)) *pte = pte_mkdirty(*pte); -+ flush_tlb_page(vma, page); -+ out: -+ up_read(&mm->mmap_sem); -+ return(handled); -+} -+ -+unsigned long segv(unsigned long address, unsigned long ip, int is_write, -+ int is_user, void *sc) -+{ -+ struct siginfo si; -+ void *catcher; -+ int handled; -+ -+ if(!is_user && (address >= start_vm) && (address < end_vm)){ -+ flush_tlb_kernel_vm(); -+ return(0); -+ } -+ if(current->mm == NULL) -+ panic("Segfault with no mm"); -+ -+ handled = handle_page_fault(address, ip, is_write, is_user, -+ &si.si_code); -+ -+ catcher = current->thread.fault_catcher; -+ if(handled) -+ return(0); -+ else if(catcher != NULL){ -+ current->thread.fault_addr = (void *) address; -+ do_longjmp(catcher, 1); -+ } -+ else if(current->thread.fault_addr != NULL){ -+ panic("fault_addr set but no fault catcher"); -+ } -+ else if(arch_fixup(ip, sc)) -+ return(0); -+ -+ if(!is_user) -+ panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", -+ address, ip); -+ si.si_signo = SIGSEGV; -+ si.si_addr = (void *) address; -+ current->thread.cr2 = address; -+ current->thread.err = is_write; -+ force_sig_info(SIGSEGV, &si, current); -+ return(0); -+} -+ -+void bad_segv(unsigned long address, unsigned long ip, int is_write) -+{ -+ 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; -+ current->thread.cr2 = address; -+ current->thread.err = is_write; -+ force_sig_info(SIGSEGV, &si, current); -+} -+ -+void relay_signal(int sig, union uml_pt_regs *regs) -+{ -+ if(arch_handle_signal(sig, regs)) return; -+ if(!UPT_IS_USER(regs)) -+ panic("Kernel mode signal %d", sig); -+ force_sig(sig, current); -+} -+ -+void bus_handler(int sig, union uml_pt_regs *regs) -+{ -+ if(current->thread.fault_catcher != NULL) -+ do_longjmp(current->thread.fault_catcher, 1); -+ else relay_signal(sig, regs); -+} -+ -+void winch(int sig, union uml_pt_regs *regs) -+{ -+ do_IRQ(WINCH_IRQ, regs); -+} -+ -+void trap_init(void) -+{ -+} -+ -+spinlock_t trap_lock = SPIN_LOCK_UNLOCKED; -+ -+static int trap_index = 0; -+ -+int next_trap_index(int limit) -+{ -+ int ret; -+ -+ spin_lock(&trap_lock); -+ ret = trap_index; -+ if(++trap_index == limit) -+ trap_index = 0; -+ spin_unlock(&trap_lock); -+ return(ret); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/trap_user.c um/arch/um/kernel/trap_user.c ---- orig/arch/um/kernel/trap_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/trap_user.c Wed Mar 26 13:25:50 2003 -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#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> -+#include <asm/unistd.h> -+#include <asm/ptrace.h> -+#include "init.h" -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "sysdep/sigcontext.h" -+#include "irq_user.h" -+#include "frame_user.h" -+#include "signal_user.h" -+#include "time_user.h" -+#include "task.h" -+#include "mode.h" -+#include "choose-mode.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+ -+void kill_child_dead(int pid) -+{ -+ kill(pid, SIGKILL); -+ kill(pid, SIGCONT); -+ while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT); -+} -+ -+/* Unlocked - don't care if this is a bit off */ -+int nsegfaults = 0; -+ -+struct { -+ unsigned long address; -+ int is_write; -+ int pid; -+ unsigned long sp; -+ int is_user; -+} segfault_record[1024]; -+ -+void segv_handler(int sig, union uml_pt_regs *regs) -+{ -+ int index, max; -+ -+ if(UPT_IS_USER(regs) && !UPT_SEGV_IS_FIXABLE(regs)){ -+ bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), -+ UPT_FAULT_WRITE(regs)); -+ return; -+ } -+ max = sizeof(segfault_record)/sizeof(segfault_record[0]); -+ index = next_trap_index(max); -+ -+ nsegfaults++; -+ segfault_record[index].address = UPT_FAULT_ADDR(regs); -+ segfault_record[index].pid = os_getpid(); -+ segfault_record[index].is_write = UPT_FAULT_WRITE(regs); -+ segfault_record[index].sp = UPT_SP(regs); -+ segfault_record[index].is_user = UPT_IS_USER(regs); -+ segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs), -+ UPT_IS_USER(regs), regs); -+} -+ -+void usr2_handler(int sig, union uml_pt_regs *regs) -+{ -+ CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); -+} -+ -+struct signal_info sig_info[] = { -+ [ SIGTRAP ] { .handler = relay_signal, -+ .is_irq = 0 }, -+ [ SIGFPE ] { .handler = relay_signal, -+ .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, -+ .is_irq = 0 }, -+ [ SIGIO ] { .handler = sigio_handler, -+ .is_irq = 1 }, -+ [ SIGVTALRM ] { .handler = timer_handler, -+ .is_irq = 1 }, -+ [ SIGALRM ] { .handler = timer_handler, -+ .is_irq = 1 }, -+ [ SIGUSR2 ] { .handler = usr2_handler, -+ .is_irq = 0 }, -+}; -+ -+void sig_handler(int sig, struct sigcontext sc) -+{ -+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, -+ sig, &sc); -+} -+ -+extern int timer_irq_inited, missed_ticks[]; -+ -+void alarm_handler(int sig, struct sigcontext sc) -+{ -+ if(!timer_irq_inited) return; -+ missed_ticks[cpu()]++; -+ -+ if(sig == SIGALRM) -+ switch_timers(0); -+ -+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, -+ sig, &sc); -+ -+ if(sig == SIGALRM) -+ switch_timers(1); -+} -+ -+void do_longjmp(void *b, int val) -+{ -+ jmp_buf *buf = b; -+ -+ longjmp(*buf, val); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/Makefile um/arch/um/kernel/tt/Makefile ---- orig/arch/um/kernel/tt/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/Makefile Fri Dec 20 23:29:42 2002 -@@ -0,0 +1,39 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = tt.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 -+ -+obj-$(CONFIG_PT_PROXY) += gdb_kern.o -+ -+subdir-y = sys-$(SUBARCH) -+subdir-$(CONFIG_PT_PROXY) += ptproxy -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+export-objs = ksyms.o -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) gdb.o time.o tracer.o -+ -+UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS)) -+UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+$(O_TARGET) : unmap_fin.o -+ -+unmap.o: unmap.c -+ $(CC) $(UNMAP_CFLAGS) -c -o $@ $< -+ -+unmap_fin.o : unmap.o -+ ld -r -o $@ $< -lc -L/usr/lib -+ -+clean : -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/exec_kern.c um/arch/um/kernel/tt/exec_kern.c ---- orig/arch/um/kernel/tt/exec_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/exec_kern.c Thu Oct 24 19:22:17 2002 -@@ -0,0 +1,83 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/mm.h" -+#include "asm/signal.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/pgalloc.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "time_user.h" -+#include "mem_user.h" -+#include "os.h" -+#include "tlb.h" -+ -+static int exec_tramp(void *sig_stack) -+{ -+ init_new_thread_stack(sig_stack, NULL); -+ init_new_thread_signals(1); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+void flush_thread_tt(void) -+{ -+ unsigned long stack; -+ int new_pid; -+ -+ stack = alloc_stack(0, 0); -+ if(stack == 0){ -+ printk(KERN_ERR -+ "flush_thread : failed to allocate temporary stack\n"); -+ do_exit(SIGKILL); -+ } -+ -+ new_pid = start_fork_tramp((void *) current->thread.kernel_stack, -+ stack, 0, exec_tramp); -+ if(new_pid < 0){ -+ printk(KERN_ERR -+ "flush_thread : new thread failed, errno = %d\n", -+ -new_pid); -+ do_exit(SIGKILL); -+ } -+ -+ if(current->processor == 0) -+ forward_interrupts(new_pid); -+ current->thread.request.op = OP_EXEC; -+ current->thread.request.u.exec.pid = new_pid; -+ unprotect_stack((unsigned long) current); -+ 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); -+ force_flush_all(); -+ unblock_signals(); -+} -+ -+void start_thread_tt(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp) -+{ -+ set_fs(USER_DS); -+ flush_tlb_mm(current->mm); -+ PT_REGS_IP(regs) = eip; -+ PT_REGS_SP(regs) = esp; -+ PT_FIX_EXEC_STACK(esp); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/exec_user.c um/arch/um/kernel/tt/exec_user.c ---- orig/arch/um/kernel/tt/exec_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/exec_user.c Thu Dec 5 19:36:57 2002 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stdlib.h> -+#include <sched.h> -+#include <errno.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <signal.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "ptrace_user.h" -+ -+void do_exec(int old_pid, int new_pid) -+{ -+ unsigned long regs[FRAME_SIZE]; -+ -+ if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || -+ (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0) || -+ (waitpid(new_pid, 0, WUNTRACED) < 0)) -+ tracer_panic("do_exec failed to attach proc - errno = %d", -+ errno); -+ -+ if(ptrace_getregs(old_pid, regs) < 0) -+ tracer_panic("do_exec failed to get registers - errno = %d", -+ errno); -+ -+ kill(old_pid, SIGKILL); -+ -+ if(ptrace_setregs(new_pid, regs) < 0) -+ tracer_panic("do_exec failed to start new proc - errno = %d", -+ errno); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/gdb.c um/arch/um/kernel/tt/gdb.c ---- orig/arch/um/kernel/tt/gdb.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/gdb.c Fri Jan 17 13:23:31 2003 -@@ -0,0 +1,278 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <errno.h> -+#include <string.h> -+#include <signal.h> -+#include <sys/ptrace.h> -+#include <sys/types.h> -+#include "uml-config.h" -+#include "kern_constants.h" -+#include "chan_user.h" -+#include "init.h" -+#include "user.h" -+#include "debug.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "tt.h" -+#include "sysdep/thread.h" -+ -+extern int debugger_pid; -+extern int debugger_fd; -+extern int debugger_parent; -+ -+int detach(int pid, int sig) -+{ -+ return(ptrace(PTRACE_DETACH, pid, 0, sig)); -+} -+ -+int attach(int pid) -+{ -+ int err; -+ -+ err = ptrace(PTRACE_ATTACH, pid, 0, 0); -+ if(err < 0) return(-errno); -+ else return(err); -+} -+ -+int cont(int pid) -+{ -+ return(ptrace(PTRACE_CONT, pid, 0, 0)); -+} -+ -+#ifdef UML_CONFIG_PT_PROXY -+ -+int debugger_signal(int status, pid_t pid) -+{ -+ return(debugger_proxy(status, pid)); -+} -+ -+void child_signal(pid_t pid, int status) -+{ -+ child_proxy(pid, status); -+} -+ -+static void gdb_announce(char *dev_name, int dev) -+{ -+ printf("gdb assigned device '%s'\n", dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = gdb_announce, -+ .xterm_title = "UML kernel debugger", -+ .raw = 0, -+ .tramp_stack = 0, -+ .in_kernel = 0, -+}; -+ -+/* Accessed by the tracing thread, which automatically serializes access */ -+static void *xterm_data; -+static int xterm_fd; -+ -+extern void *xterm_init(char *, int, struct chan_opts *); -+extern int xterm_open(int, int, int, void *, char **); -+extern void xterm_close(int, void *); -+ -+int open_gdb_chan(void) -+{ -+ char stack[UM_KERN_PAGE_SIZE], *dummy; -+ -+ opts.tramp_stack = (unsigned long) stack; -+ xterm_data = xterm_init("", 0, &opts); -+ xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy); -+ return(xterm_fd); -+} -+ -+static void exit_debugger_cb(void *unused) -+{ -+ if(debugger_pid != -1){ -+ if(gdb_pid != -1){ -+ fake_child_exit(); -+ gdb_pid = -1; -+ } -+ else kill_child_dead(debugger_pid); -+ debugger_pid = -1; -+ if(debugger_parent != -1) -+ detach(debugger_parent, SIGINT); -+ } -+ if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data); -+} -+ -+static void exit_debugger(void) -+{ -+ initial_thread_cb(exit_debugger_cb, NULL); -+} -+ -+__uml_exitcall(exit_debugger); -+ -+struct gdb_data { -+ char *str; -+ int err; -+}; -+ -+static void config_gdb_cb(void *arg) -+{ -+ struct gdb_data *data = arg; -+ void *task; -+ int pid; -+ -+ data->err = -1; -+ if(debugger_pid != -1) exit_debugger_cb(NULL); -+ if(!strncmp(data->str, "pid,", strlen("pid,"))){ -+ data->str += strlen("pid,"); -+ pid = strtoul(data->str, NULL, 0); -+ task = cpu_tasks[0].task; -+ debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0); -+ if(debugger_pid != -1){ -+ data->err = 0; -+ gdb_pid = pid; -+ } -+ return; -+ } -+ data->err = 0; -+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); -+ init_proxy(debugger_pid, 0, 0); -+} -+ -+int gdb_config(char *str) -+{ -+ struct gdb_data data; -+ -+ if(*str++ != '=') return(-1); -+ data.str = str; -+ initial_thread_cb(config_gdb_cb, &data); -+ return(data.err); -+} -+ -+void remove_gdb_cb(void *unused) -+{ -+ exit_debugger_cb(NULL); -+} -+ -+int gdb_remove(char *unused) -+{ -+ initial_thread_cb(remove_gdb_cb, NULL); -+ return(0); -+} -+ -+void signal_usr1(int sig) -+{ -+ if(debugger_pid != -1){ -+ printk(UM_KERN_ERR "The debugger is already running\n"); -+ return; -+ } -+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); -+ init_proxy(debugger_pid, 0, 0); -+} -+ -+int init_ptrace_proxy(int idle_pid, int startup, int stop) -+{ -+ int pid, status; -+ -+ pid = start_debugger(linux_prog, startup, stop, &debugger_fd); -+ status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); -+ if(pid < 0){ -+ cont(idle_pid); -+ return(-1); -+ } -+ init_proxy(pid, 1, status); -+ return(pid); -+} -+ -+int attach_debugger(int idle_pid, int pid, int stop) -+{ -+ int status = 0, err; -+ -+ err = attach(pid); -+ if(err < 0){ -+ printf("Failed to attach pid %d, errno = %d\n", pid, -err); -+ return(-1); -+ } -+ if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); -+ init_proxy(pid, 1, status); -+ return(pid); -+} -+ -+#ifdef notdef /* Put this back in when it does something useful */ -+static int __init uml_gdb_init_setup(char *line, int *add) -+{ -+ gdb_init = uml_strdup(line); -+ return 0; -+} -+ -+__uml_setup("gdb=", uml_gdb_init_setup, -+"gdb=<channel description>\n\n" -+); -+#endif -+ -+static int __init uml_gdb_pid_setup(char *line, int *add) -+{ -+ gdb_pid = strtoul(line, NULL, 0); -+ *add = 0; -+ return 0; -+} -+ -+__uml_setup("gdb-pid=", uml_gdb_pid_setup, -+"gdb-pid=<pid>\n" -+" gdb-pid is used to attach an external debugger to UML. This may be\n" -+" an already-running gdb or a debugger-like process like strace.\n\n" -+); -+ -+#else -+ -+int debugger_signal(int status, pid_t pid){ return(0); } -+void child_signal(pid_t pid, int status){ } -+int init_ptrace_proxy(int idle_pid, int startup, int stop) -+{ -+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n"); -+ kill_child_dead(idle_pid); -+ exit(1); -+} -+ -+void signal_usr1(int sig) -+{ -+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n"); -+} -+ -+int attach_debugger(int idle_pid, int pid, int stop) -+{ -+ printk(UM_KERN_ERR "attach_debugger called when CONFIG_PT_PROXY " -+ "is off\n"); -+ return(-1); -+} -+ -+int config_gdb(char *str) -+{ -+ return(-1); -+} -+ -+int remove_gdb(void) -+{ -+ return(-1); -+} -+ -+int init_parent_proxy(int pid) -+{ -+ return(-1); -+} -+ -+void debugger_parent_signal(int status, int pid) -+{ -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/gdb_kern.c um/arch/um/kernel/tt/gdb_kern.c ---- orig/arch/um/kernel/tt/gdb_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/gdb_kern.c Sun Dec 15 21:16:17 2002 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/config.h" -+#include "mconsole_kern.h" -+ -+#ifdef CONFIG_MCONSOLE -+ -+extern int gdb_config(char *str); -+extern int gdb_remove(char *unused); -+ -+static struct mc_device gdb_mc = { -+ .name = "gdb", -+ .config = gdb_config, -+ .remove = gdb_remove, -+}; -+ -+int gdb_mc_init(void) -+{ -+ mconsole_register_dev(&gdb_mc); -+ return(0); -+} -+ -+__initcall(gdb_mc_init); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/debug.h um/arch/um/kernel/tt/include/debug.h ---- orig/arch/um/kernel/tt/include/debug.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/include/debug.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and -+ * Lars Brinkhoff. -+ * Licensed under the GPL -+ */ -+ -+#ifndef __DEBUG_H -+#define __DEBUG_H -+ -+extern int debugger_proxy(int status, pid_t pid); -+extern void child_proxy(pid_t pid, int status); -+extern void init_proxy (pid_t pid, int waiting, int status); -+extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd); -+extern void fake_child_exit(void); -+extern int gdb_config(char *str); -+extern int gdb_remove(char *unused); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mmu.h um/arch/um/kernel/tt/include/mmu.h ---- orig/arch/um/kernel/tt/include/mmu.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/include/mmu.h Sat Nov 9 12:51:32 2002 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_MMU_H -+#define __TT_MMU_H -+ -+struct mmu_context_tt { -+}; -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mode.h um/arch/um/kernel/tt/include/mode.h ---- orig/arch/um/kernel/tt/include/mode.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/include/mode.h Mon Dec 9 00:34:40 2002 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_TT_H__ -+#define __MODE_TT_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int tracing_pid; -+ -+extern int tracer(int (*init_proc)(void *), void *sp); -+extern void user_time_init_tt(void); -+extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data); -+extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, -+ void *data); -+extern void sig_handler_common_tt(int sig, void *sc); -+extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); -+extern void reboot_tt(void); -+extern void halt_tt(void); -+extern int is_tracer_winch(int pid, int fd, void *data); -+extern void kill_off_processes_tt(void); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mode_kern.h um/arch/um/kernel/tt/include/mode_kern.h ---- orig/arch/um/kernel/tt/include/mode_kern.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/include/mode_kern.h Mon Dec 16 21:49:18 2002 -@@ -0,0 +1,52 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_MODE_KERN_H__ -+#define __TT_MODE_KERN_H__ -+ -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+ -+extern void *_switch_to_tt(void *prev, void *next); -+extern void flush_thread_tt(void); -+extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp); -+extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct *p, -+ struct pt_regs *regs); -+extern void release_thread_tt(struct task_struct *task); -+extern void exit_thread_tt(void); -+extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); -+extern void init_idle_tt(void); -+extern void flush_tlb_kernel_vm_tt(void); -+extern void __flush_tlb_one_tt(unsigned long addr); -+extern void flush_tlb_range_tt(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_mm_tt(struct mm_struct *mm); -+extern void force_flush_all_tt(void); -+extern long execute_syscall_tt(void *r); -+extern void before_mem_tt(unsigned long brk_start); -+extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out); -+extern int start_uml_tt(void); -+extern int external_pid_tt(struct task_struct *task); -+extern int thread_pid_tt(struct thread_struct *thread); -+ -+#define kmem_end_tt (host_task_size - ABOVE_KMEM) -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/ptrace-tt.h um/arch/um/kernel/tt/include/ptrace-tt.h ---- orig/arch/um/kernel/tt/include/ptrace-tt.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/include/ptrace-tt.h Fri Jan 17 13:23:30 2003 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_TT_H -+#define __PTRACE_TT_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "sysdep/sc.h" -+#endif -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/tt.h um/arch/um/kernel/tt/include/tt.h ---- orig/arch/um/kernel/tt/include/tt.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/include/tt.h Fri Dec 20 23:29:11 2002 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_H__ -+#define __TT_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int gdb_pid; -+extern int debug; -+extern int debug_stop; -+extern int debug_trace; -+ -+extern int honeypot; -+ -+extern int fork_tramp(void *sig_stack); -+extern int do_proc_op(void *t, int proc_id); -+extern int tracer(int (*init_proc)(void *), void *sp); -+extern void attach_process(int pid); -+extern void tracer_panic(char *format, ...); -+extern void set_init_pid(int pid); -+extern int set_user_mode(void *task); -+extern void set_tracing(void *t, int tracing); -+extern int is_tracing(void *task); -+extern int singlestepping_tt(void *t); -+extern void clear_singlestep(void *t); -+extern void syscall_handler(int sig, union uml_pt_regs *regs); -+extern void exit_kernel(int pid, void *task); -+extern int do_syscall(void *task, int pid); -+extern int is_valid_pid(int pid); -+extern void remap_data(void *segment_start, void *segment_end, int w); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/uaccess.h um/arch/um/kernel/tt/include/uaccess.h ---- orig/arch/um/kernel/tt/include/uaccess.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/include/uaccess.h Tue Mar 25 16:58:42 2003 -@@ -0,0 +1,122 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_UACCESS_H -+#define __TT_UACCESS_H -+ -+#include "linux/string.h" -+#include "linux/sched.h" -+#include "asm/processor.h" -+#include "asm/errno.h" -+#include "asm/current.h" -+#include "asm/a.out.h" -+#include "uml_uaccess.h" -+ -+#define ABOVE_KMEM (16 * 1024 * 1024) -+ -+extern unsigned long end_vm; -+extern unsigned long uml_physmem; -+ -+#define under_task_size(addr, size) \ -+ (((unsigned long) (addr) < TASK_SIZE) && \ -+ (((unsigned long) (addr) + (size)) < TASK_SIZE)) -+ -+#define is_stack(addr, size) \ -+ (((unsigned long) (addr) < STACK_TOP) && \ -+ ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ -+ (((unsigned long) (addr) + (size)) <= STACK_TOP)) -+ -+#define access_ok_tt(type, addr, size) \ -+ ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ -+ (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ -+ (under_task_size(addr, size) || is_stack(addr, size)))) -+ -+static inline int verify_area_tt(int type, const void * addr, -+ unsigned long size) -+{ -+ return(access_ok_tt(type, addr, size) ? 0 : -EFAULT); -+} -+ -+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) -+{ -+ 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)); -+} -+ -+static inline 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)); -+} -+ -+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) -+{ -+ if(!access_ok_tt(VERIFY_WRITE, mem, len)) -+ return(len); -+ -+ return(__do_clear_user(mem, len, ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+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)); -+} -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/ksyms.c um/arch/um/kernel/tt/ksyms.c ---- orig/arch/um/kernel/tt/ksyms.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ksyms.c Sun Oct 27 17:01:56 2002 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+#include "asm/uaccess.h" -+#include "mode.h" -+ -+EXPORT_SYMBOL(__do_copy_from_user); -+EXPORT_SYMBOL(__do_copy_to_user); -+EXPORT_SYMBOL(__do_strncpy_from_user); -+EXPORT_SYMBOL(__do_strnlen_user); -+EXPORT_SYMBOL(__do_clear_user); -+ -+EXPORT_SYMBOL(tracing_pid); -+EXPORT_SYMBOL(honeypot); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/mem.c um/arch/um/kernel/tt/mem.c ---- orig/arch/um/kernel/tt/mem.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/mem.c Mon Dec 16 21:49:51 2002 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "asm/uaccess.h" -+#include "mem_user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "kern.h" -+#include "tt.h" -+ -+void before_mem_tt(unsigned long brk_start) -+{ -+ if(!jail || debug) -+ remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); -+ remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); -+ remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(brk_start), 1); -+} -+ -+#ifdef CONFIG_HOST_2G_2G -+#define TOP 0x80000000 -+#else -+#define TOP 0xc0000000 -+#endif -+ -+#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) -+#define START (TOP - SIZE) -+ -+unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out) -+{ -+ /* Round up to the nearest 4M */ -+ *host_size_out = ROUND_4M((unsigned long) &arg); -+ *task_size_out = START; -+ return(START); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/mem_user.c um/arch/um/kernel/tt/mem_user.c ---- orig/arch/um/kernel/tt/mem_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/mem_user.c Fri Jan 17 22:07:31 2003 -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <stdio.h> -+#include <unistd.h> -+#include <string.h> -+#include <errno.h> -+#include <sys/mman.h> -+#include "tt.h" -+#include "mem_user.h" -+#include "user_util.h" -+ -+void remap_data(void *segment_start, void *segment_end, int w) -+{ -+ void *addr; -+ unsigned long size; -+ int data, prot; -+ -+ if(w) prot = PROT_WRITE; -+ else prot = 0; -+ prot |= PROT_READ | PROT_EXEC; -+ 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){ -+ perror("mapping new data segment"); -+ exit(1); -+ } -+ memcpy(addr, segment_start, size); -+ if(switcheroo(data, prot, addr, segment_start, -+ size) < 0){ -+ printf("switcheroo failed\n"); -+ exit(1); -+ } -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/process_kern.c um/arch/um/kernel/tt/process_kern.c ---- orig/arch/um/kernel/tt/process_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/process_kern.c Sun Feb 16 21:34:23 2003 -@@ -0,0 +1,516 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/signal.h" -+#include "linux/kernel.h" -+#include "asm/system.h" -+#include "asm/pgalloc.h" -+#include "asm/ptrace.h" -+#include "irq_user.h" -+#include "signal_user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+#include "kern.h" -+#include "sigcontext.h" -+#include "time_user.h" -+#include "mem_user.h" -+#include "tlb.h" -+#include "mode.h" -+#include "init.h" -+#include "tt.h" -+ -+void *_switch_to_tt(void *prev, void *next) -+{ -+ struct task_struct *from, *to; -+ unsigned long flags; -+ int err, vtalrm, alrm, prof, cpu; -+ char c; -+ /* jailing and SMP are incompatible, so this doesn't need to be -+ * made per-cpu -+ */ -+ static int reading; -+ -+ from = prev; -+ to = next; -+ -+ to->thread.prev_sched = from; -+ -+ cpu = from->processor; -+ if(cpu == 0) -+ forward_interrupts(to->thread.mode.tt.extern_pid); -+#ifdef CONFIG_SMP -+ forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); -+#endif -+ local_irq_save(flags); -+ -+ vtalrm = change_sig(SIGVTALRM, 0); -+ alrm = change_sig(SIGALRM, 0); -+ prof = change_sig(SIGPROF, 0); -+ -+ c = 0; -+ set_current(to); -+ -+ 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); -+ -+ reading = 1; -+ if(from->state == TASK_ZOMBIE) -+ os_kill_process(os_getpid(), 0); -+ -+ err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); -+ if(err != sizeof(c)) -+ panic("read of switch_pipe failed, errno = %d", -err); -+ -+ /* This works around a nasty race with 'jail'. If we are switching -+ * between two threads of a threaded app and the incoming process -+ * runs before the outgoing process reaches the read, and it makes -+ * it all the way out to userspace, then it will have write-protected -+ * the outgoing process stack. Then, when the outgoing process -+ * returns from the write, it will segfault because it can no longer -+ * write its own stack. So, in order to avoid that, the incoming -+ * thread sits in a loop yielding until 'reading' is set. This -+ * isn't entirely safe, since there may be a reschedule from a timer -+ * happening between setting 'reading' and sleeping in read. But, -+ * it should get a whole quantum in which to reach the read and sleep, -+ * which should be enough. -+ */ -+ -+ if(jail){ -+ while(!reading) sched_yield(); -+ } -+ -+ change_sig(SIGVTALRM, vtalrm); -+ change_sig(SIGALRM, alrm); -+ change_sig(SIGPROF, prof); -+ -+ arch_switch(); -+ -+ flush_tlb_all(); -+ local_irq_restore(flags); -+ -+ return(current->thread.prev_sched); -+} -+ -+void release_thread_tt(struct task_struct *task) -+{ -+ os_kill_process(task->thread.mode.tt.extern_pid, 0); -+} -+ -+void exit_thread_tt(void) -+{ -+ close(current->thread.mode.tt.switch_pipe[0]); -+ close(current->thread.mode.tt.switch_pipe[1]); -+} -+ -+extern void schedule_tail(struct task_struct *prev); -+ -+static void new_thread_handler(int sig) -+{ -+ 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); -+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); -+ -+ init_new_thread_signals(1); -+ enable_timer(); -+ free_page(current->thread.temp_stack); -+ set_cmdline("(kernel thread)"); -+ force_flush_all(); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ change_sig(SIGUSR1, 1); -+ change_sig(SIGVTALRM, 1); -+ change_sig(SIGPROF, 1); -+ sti(); -+ if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) -+ do_exit(0); -+} -+ -+static int new_thread_proc(void *stack) -+{ -+ cli(); -+ init_new_thread_stack(stack, new_thread_handler); -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+/* Signal masking - signals are blocked at the start of fork_tramp. They -+ * are re-enabled when finish_fork_handler is entered by fork_tramp hitting -+ * 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 -+ * onto the signal frame. -+ */ -+ -+static 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]); -+ -+ init_new_thread_signals(1); -+ enable_timer(); -+ sti(); -+ force_flush_all(); -+ if(current->mm != current->p_pptr->mm) -+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1, -+ 1, 0, 1); -+ task_protections((unsigned long) current); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ free_page(current->thread.temp_stack); -+ cli(); -+ change_sig(SIGUSR1, 0); -+ set_user_mode(current); -+} -+ -+int fork_tramp(void *stack) -+{ -+ cli(); -+ init_new_thread_stack(stack, finish_fork_handler); -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ int (*tramp)(void *); -+ int new_pid, err; -+ unsigned long stack; -+ -+ if(current->thread.forking) -+ tramp = fork_tramp; -+ else { -+ tramp = new_thread_proc; -+ p->thread.request.u.thread = current->thread.request.u.thread; -+ } -+ -+ err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); -+ if(err){ -+ printk("copy_thread : pipe failed, errno = %d\n", -err); -+ return(err); -+ } -+ -+ stack = alloc_stack(0, 0); -+ if(stack == 0){ -+ printk(KERN_ERR "copy_thread : failed to allocate " -+ "temporary stack\n"); -+ return(-ENOMEM); -+ } -+ -+ clone_flags &= CLONE_VM; -+ p->thread.temp_stack = stack; -+ new_pid = start_fork_tramp((void *) p->thread.kernel_stack, stack, -+ clone_flags, tramp); -+ if(new_pid < 0){ -+ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", -+ -new_pid); -+ return(new_pid); -+ } -+ -+ if(current->thread.forking){ -+ sc_to_sc(UPT_SC(&p->thread.regs.regs), -+ UPT_SC(¤t->thread.regs.regs)); -+ SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); -+ if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; -+ } -+ p->thread.mode.tt.extern_pid = new_pid; -+ -+ current->thread.request.op = OP_FORK; -+ current->thread.request.u.fork.pid = new_pid; -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+void reboot_tt(void) -+{ -+ current->thread.request.op = OP_REBOOT; -+ os_usr1_process(os_getpid()); -+ os_kill_process(os_getpid(), 0); -+} -+ -+void halt_tt(void) -+{ -+ current->thread.request.op = OP_HALT; -+ os_usr1_process(os_getpid()); -+ os_kill_process(os_getpid(), 0); -+} -+ -+void kill_off_processes_tt(void) -+{ -+ struct task_struct *p; -+ int me; -+ -+ me = os_getpid(); -+ for_each_task(p){ -+ int pid = p->thread.mode.tt.extern_pid; -+ if((pid != me) && (pid != -1)) -+ os_kill_process(p->thread.mode.tt.extern_pid, 0); -+ } -+ if((init_task.thread.mode.tt.extern_pid != me) && -+ (init_task.thread.mode.tt.extern_pid != -1)) -+ os_kill_process(init_task.thread.mode.tt.extern_pid, 0); -+} -+ -+void initial_thread_cb_tt(void (*proc)(void *), void *arg) -+{ -+ if(os_getpid() == tracing_pid){ -+ (*proc)(arg); -+ } -+ else { -+ current->thread.request.op = OP_CB; -+ current->thread.request.u.cb.proc = proc; -+ current->thread.request.u.cb.arg = arg; -+ os_usr1_process(os_getpid()); -+ } -+} -+ -+int do_proc_op(void *t, int proc_id) -+{ -+ struct task_struct *task; -+ struct thread_struct *thread; -+ int op, pid; -+ -+ task = t; -+ thread = &task->thread; -+ op = thread->request.op; -+ switch(op){ -+ case OP_NONE: -+ case OP_TRACE_ON: -+ break; -+ case OP_EXEC: -+ pid = thread->request.u.exec.pid; -+ do_exec(thread->mode.tt.extern_pid, pid); -+ thread->mode.tt.extern_pid = pid; -+ cpu_tasks[task->processor].pid = pid; -+ break; -+ case OP_FORK: -+ attach_process(thread->request.u.fork.pid); -+ break; -+ case OP_CB: -+ (*thread->request.u.cb.proc)(thread->request.u.cb.arg); -+ break; -+ case OP_REBOOT: -+ case OP_HALT: -+ break; -+ default: -+ tracer_panic("Bad op in do_proc_op"); -+ break; -+ } -+ thread->request.op = OP_NONE; -+ return(op); -+} -+ -+void init_idle_tt(void) -+{ -+ idle_timer(); -+} -+ -+/* Changed by jail_setup, which is a setup */ -+int jail = 0; -+ -+int __init jail_setup(char *line, int *add) -+{ -+ int ok = 1; -+ -+ if(jail) return(0); -+#ifdef CONFIG_SMP -+ printf("'jail' may not used used in a kernel with CONFIG_SMP " -+ "enabled\n"); -+ ok = 0; -+#endif -+#ifdef CONFIG_HOSTFS -+ printf("'jail' may not used used in a kernel with CONFIG_HOSTFS " -+ "enabled\n"); -+ ok = 0; -+#endif -+#ifdef CONFIG_MODULES -+ printf("'jail' may not used used in a kernel with CONFIG_MODULES " -+ "enabled\n"); -+ ok = 0; -+#endif -+ if(!ok) exit(1); -+ -+ /* CAP_SYS_RAWIO controls the ability to open /dev/mem and /dev/kmem. -+ * Removing it from the bounding set eliminates the ability of anything -+ * to acquire it, and thus read or write kernel memory. -+ */ -+ cap_lower(cap_bset, CAP_SYS_RAWIO); -+ jail = 1; -+ return(0); -+} -+ -+__uml_setup("jail", jail_setup, -+"jail\n" -+" Enables the protection of kernel memory from processes.\n\n" -+); -+ -+static void mprotect_kernel_mem(int w) -+{ -+ unsigned long start, end; -+ int pages; -+ -+ if(!jail || (current == &init_task)) return; -+ -+ pages = (1 << CONFIG_KERNEL_STACK_ORDER); -+ -+ start = (unsigned long) current + PAGE_SIZE; -+ end = (unsigned long) current + PAGE_SIZE * pages; -+ protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1); -+ protect_memory(end, high_physmem - end, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&_stext); -+ end = (unsigned long) UML_ROUND_UP(&_etext); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&_unprotected_end); -+ end = (unsigned long) UML_ROUND_UP(&_edata); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&__bss_start); -+ end = (unsigned long) UML_ROUND_UP(brk_start); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ mprotect_kernel_vm(w); -+} -+ -+void unprotect_kernel_mem(void) -+{ -+ mprotect_kernel_mem(1); -+} -+ -+void protect_kernel_mem(void) -+{ -+ mprotect_kernel_mem(0); -+} -+ -+extern void start_kernel(void); -+ -+static int start_kernel_proc(void *unused) -+{ -+ int pid; -+ -+ block_signals(); -+ pid = os_getpid(); -+ -+ cpu_tasks[0].pid = pid; -+ cpu_tasks[0].task = current; -+#ifdef CONFIG_SMP -+ cpu_online_map = 1; -+#endif -+ if(debug) os_stop_process(pid); -+ start_kernel(); -+ return(0); -+} -+ -+void set_tracing(void *task, int tracing) -+{ -+ ((struct task_struct *) task)->thread.mode.tt.tracing = tracing; -+} -+ -+int is_tracing(void *t) -+{ -+ return (((struct task_struct *) t)->thread.mode.tt.tracing); -+} -+ -+int set_user_mode(void *t) -+{ -+ struct task_struct *task; -+ -+ task = t ? t : current; -+ if(task->thread.mode.tt.tracing) -+ return(1); -+ task->thread.request.op = OP_TRACE_ON; -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+void set_init_pid(int pid) -+{ -+ int err; -+ -+ 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); -+} -+ -+int singlestepping_tt(void *t) -+{ -+ struct task_struct *task = t; -+ -+ if(task->thread.mode.tt.singlestep_syscall) -+ return(0); -+ return(task->ptrace & PT_DTRACE); -+} -+ -+void clear_singlestep(void *t) -+{ -+ struct task_struct *task = t; -+ -+ task->ptrace &= ~PT_DTRACE; -+} -+ -+int start_uml_tt(void) -+{ -+ void *sp; -+ int pages; -+ -+ pages = (1 << CONFIG_KERNEL_STACK_ORDER) - 2; -+ sp = (void *) init_task.thread.kernel_stack + pages * PAGE_SIZE - -+ sizeof(unsigned long); -+ return(tracer(start_kernel_proc, sp)); -+} -+ -+int external_pid_tt(struct task_struct *task) -+{ -+ return(task->thread.mode.tt.extern_pid); -+} -+ -+int thread_pid_tt(struct thread_struct *thread) -+{ -+ return(thread->mode.tt.extern_pid); -+} -+ -+int is_valid_pid(int pid) -+{ -+ struct task_struct *task; -+ -+ read_lock(&tasklist_lock); -+ for_each_task(task){ -+ if(task->thread.mode.tt.extern_pid == pid){ -+ read_unlock(&tasklist_lock); -+ return(1); -+ } -+ } -+ read_unlock(&tasklist_lock); -+ 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/Makefile um/arch/um/kernel/tt/ptproxy/Makefile ---- orig/arch/um/kernel/tt/ptproxy/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ptproxy/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,12 @@ -+O_TARGET = ptproxy.o -+ -+obj-y = proxy.o ptrace.o sysdep.o wait.o -+ -+USER_OBJS = $(obj-y) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean: -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/proxy.c um/arch/um/kernel/tt/ptproxy/proxy.c ---- orig/arch/um/kernel/tt/ptproxy/proxy.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ptproxy/proxy.c Sun Dec 15 21:19:15 2002 -@@ -0,0 +1,370 @@ -+/********************************************************************** -+proxy.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+Jeff Dike (jdike@karaya.com) : Modified for integration into uml -+**********************************************************************/ -+ -+/* XXX This file shouldn't refer to CONFIG_* */ -+ -+#include <errno.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <signal.h> -+#include <string.h> -+#include <fcntl.h> -+#include <termios.h> -+#include <sys/wait.h> -+#include <sys/types.h> -+#include <sys/ptrace.h> -+#include <sys/ioctl.h> -+#include <asm/unistd.h> -+ -+#include "ptproxy.h" -+#include "sysdep.h" -+#include "wait.h" -+ -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+#include "tempfile.h" -+ -+static int debugger_wait(debugger_state *debugger, int *status, int options, -+ int (*syscall)(debugger_state *debugger, pid_t child), -+ int (*normal_return)(debugger_state *debugger, -+ pid_t unused), -+ int (*wait_return)(debugger_state *debugger, -+ pid_t unused)) -+{ -+ if(debugger->real_wait){ -+ debugger->handle_trace = normal_return; -+ syscall_continue(debugger->pid); -+ debugger->real_wait = 0; -+ return(1); -+ } -+ debugger->wait_status_ptr = status; -+ debugger->wait_options = options; -+ if((debugger->debugee != NULL) && debugger->debugee->event){ -+ syscall_continue(debugger->pid); -+ wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL, -+ NULL); -+ (*wait_return)(debugger, -1); -+ return(0); -+ } -+ else if(debugger->wait_options & WNOHANG){ -+ syscall_cancel(debugger->pid, 0); -+ debugger->handle_trace = syscall; -+ return(0); -+ } -+ else { -+ syscall_pause(debugger->pid); -+ debugger->handle_trace = wait_return; -+ debugger->waiting = 1; -+ } -+ return(1); -+} -+ -+/* -+ * Handle debugger trap, i.e. syscall. -+ */ -+ -+int debugger_syscall(debugger_state *debugger, pid_t child) -+{ -+ long arg1, arg2, arg3, arg4, arg5, result; -+ int syscall, ret = 0; -+ -+ syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, -+ &arg5); -+ -+ switch(syscall){ -+ case __NR_execve: -+ /* execve never returns */ -+ debugger->handle_trace = debugger_syscall; -+ break; -+ -+ case __NR_ptrace: -+ if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid; -+ if(!debugger->debugee->in_context) -+ child = debugger->debugee->pid; -+ result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child, -+ &ret); -+ syscall_cancel(debugger->pid, result); -+ debugger->handle_trace = debugger_syscall; -+ return(ret); -+ -+ case __NR_waitpid: -+ case __NR_wait4: -+ if(!debugger_wait(debugger, (int *) arg2, arg3, -+ debugger_syscall, debugger_normal_return, -+ proxy_wait_return)) -+ return(0); -+ break; -+ -+ case __NR_kill: -+ if(!debugger->debugee->in_context) -+ child = debugger->debugee->pid; -+ if(arg1 == debugger->debugee->pid){ -+ result = kill(child, arg2); -+ syscall_cancel(debugger->pid, result); -+ debugger->handle_trace = debugger_syscall; -+ return(0); -+ } -+ else debugger->handle_trace = debugger_normal_return; -+ break; -+ -+ default: -+ debugger->handle_trace = debugger_normal_return; -+ } -+ -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+/* Used by the tracing thread */ -+static debugger_state parent; -+static int parent_syscall(debugger_state *debugger, int pid); -+ -+int init_parent_proxy(int pid) -+{ -+ parent = ((debugger_state) { .pid = pid, -+ .wait_options = 0, -+ .wait_status_ptr = NULL, -+ .waiting = 0, -+ .real_wait = 0, -+ .expecting_child = 0, -+ .handle_trace = parent_syscall, -+ .debugee = NULL } ); -+ return(0); -+} -+ -+int parent_normal_return(debugger_state *debugger, pid_t unused) -+{ -+ debugger->handle_trace = parent_syscall; -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+static int parent_syscall(debugger_state *debugger, int pid) -+{ -+ long arg1, arg2, arg3, arg4, arg5; -+ int syscall; -+ -+ syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5); -+ -+ if((syscall == __NR_waitpid) || (syscall == __NR_wait4)){ -+ debugger_wait(&parent, (int *) arg2, arg3, parent_syscall, -+ parent_normal_return, parent_wait_return); -+ } -+ else ptrace(PTRACE_SYSCALL, pid, 0, 0); -+ return(0); -+} -+ -+int debugger_normal_return(debugger_state *debugger, pid_t unused) -+{ -+ debugger->handle_trace = debugger_syscall; -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+void debugger_cancelled_return(debugger_state *debugger, int result) -+{ -+ debugger->handle_trace = debugger_syscall; -+ syscall_set_result(debugger->pid, result); -+ syscall_continue(debugger->pid); -+} -+ -+/* Used by the tracing thread */ -+static debugger_state debugger; -+static debugee_state debugee; -+ -+void init_proxy (pid_t debugger_pid, int stopped, int status) -+{ -+ debugger.pid = debugger_pid; -+ debugger.handle_trace = debugger_syscall; -+ debugger.debugee = &debugee; -+ debugger.waiting = 0; -+ debugger.real_wait = 0; -+ debugger.expecting_child = 0; -+ -+ debugee.pid = 0; -+ debugee.traced = 0; -+ debugee.stopped = stopped; -+ debugee.event = 0; -+ debugee.zombie = 0; -+ debugee.died = 0; -+ debugee.wait_status = status; -+ debugee.in_context = 1; -+} -+ -+int debugger_proxy(int status, int pid) -+{ -+ int ret = 0, sig; -+ -+ if(WIFSTOPPED(status)){ -+ sig = WSTOPSIG(status); -+ if (sig == SIGTRAP) -+ ret = (*debugger.handle_trace)(&debugger, pid); -+ -+ else if(sig == SIGCHLD){ -+ if(debugger.expecting_child){ -+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ debugger.expecting_child = 0; -+ } -+ else if(debugger.waiting) -+ real_wait_return(&debugger); -+ else { -+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ debugger.real_wait = 1; -+ } -+ } -+ else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ } -+ else if(WIFEXITED(status)){ -+ tracer_panic("debugger (pid %d) exited with status %d", -+ debugger.pid, WEXITSTATUS(status)); -+ } -+ else if(WIFSIGNALED(status)){ -+ tracer_panic("debugger (pid %d) exited with signal %d", -+ debugger.pid, WTERMSIG(status)); -+ } -+ else { -+ tracer_panic("proxy got unknown status (0x%x) on debugger " -+ "(pid %d)", status, debugger.pid); -+ } -+ return(ret); -+} -+ -+void child_proxy(pid_t pid, int status) -+{ -+ debugee.event = 1; -+ debugee.wait_status = status; -+ -+ if(WIFSTOPPED(status)){ -+ debugee.stopped = 1; -+ debugger.expecting_child = 1; -+ kill(debugger.pid, SIGCHLD); -+ } -+ else if(WIFEXITED(status) || WIFSIGNALED(status)){ -+ debugee.zombie = 1; -+ debugger.expecting_child = 1; -+ kill(debugger.pid, SIGCHLD); -+ } -+ else panic("proxy got unknown status (0x%x) on child (pid %d)", -+ status, pid); -+} -+ -+void debugger_parent_signal(int status, int pid) -+{ -+ int sig; -+ -+ if(WIFSTOPPED(status)){ -+ sig = WSTOPSIG(status); -+ if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid); -+ else ptrace(PTRACE_SYSCALL, pid, 0, sig); -+ } -+} -+ -+void fake_child_exit(void) -+{ -+ int status, pid; -+ -+ child_proxy(1, W_EXITCODE(0, 0)); -+ while(debugger.waiting == 1){ -+ pid = waitpid(debugger.pid, &status, WUNTRACED); -+ if(pid != debugger.pid){ -+ printk("fake_child_exit - waitpid failed, " -+ "errno = %d\n", errno); -+ return; -+ } -+ debugger_proxy(status, debugger.pid); -+ } -+ pid = waitpid(debugger.pid, &status, WUNTRACED); -+ if(pid != debugger.pid){ -+ printk("fake_child_exit - waitpid failed, " -+ "errno = %d\n", errno); -+ return; -+ } -+ if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0) -+ printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n", -+ errno); -+} -+ -+char gdb_init_string[] = -+"att 1 -+b panic -+b stop -+handle SIGWINCH nostop noprint pass -+"; -+ -+int start_debugger(char *prog, int startup, int stop, int *fd_out) -+{ -+ int slave, child; -+ -+ slave = open_gdb_chan(); -+ if((child = fork()) == 0){ -+ char *tempname = NULL; -+ int fd; -+ -+ if(setsid() < 0) perror("setsid"); -+ if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || -+ (dup2(slave, 2) < 0)){ -+ printk("start_debugger : dup2 failed, errno = %d\n", -+ errno); -+ exit(1); -+ } -+ if(ioctl(0, TIOCSCTTY, 0) < 0){ -+ printk("start_debugger : TIOCSCTTY failed, " -+ "errno = %d\n", errno); -+ exit(1); -+ } -+ if(tcsetpgrp (1, os_getpid()) < 0){ -+ printk("start_debugger : tcsetpgrp failed, " -+ "errno = %d\n", errno); -+#ifdef notdef -+ exit(1); -+#endif -+ } -+ if((fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0)) < 0){ -+ printk("start_debugger : make_tempfile failed, errno = %d\n", -+ errno); -+ exit(1); -+ } -+ write(fd, gdb_init_string, sizeof(gdb_init_string) - 1); -+ if(startup){ -+ if(stop){ -+ write(fd, "b start_kernel\n", -+ strlen("b start_kernel\n")); -+ } -+ write(fd, "c\n", strlen("c\n")); -+ } -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ printk("start_debugger : PTRACE_TRACEME failed, " -+ "errno = %d\n", errno); -+ exit(1); -+ } -+ execlp("gdb", "gdb", "--command", tempname, prog, NULL); -+ printk("start_debugger : exec of gdb failed, errno = %d\n", -+ errno); -+ } -+ if(child < 0){ -+ printk("start_debugger : fork for gdb failed, errno = %d\n", -+ errno); -+ return(-1); -+ } -+ *fd_out = slave; -+ return(child); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/ptproxy.h um/arch/um/kernel/tt/ptproxy/ptproxy.h ---- orig/arch/um/kernel/tt/ptproxy/ptproxy.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ptproxy/ptproxy.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,61 @@ -+/********************************************************************** -+ptproxy.h -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#ifndef __PTPROXY_H -+#define __PTPROXY_H -+ -+#include <sys/types.h> -+ -+typedef struct debugger debugger_state; -+typedef struct debugee debugee_state; -+ -+struct debugger -+{ -+ pid_t pid; -+ int wait_options; -+ int *wait_status_ptr; -+ unsigned int waiting : 1; -+ unsigned int real_wait : 1; -+ unsigned int expecting_child : 1; -+ int (*handle_trace) (debugger_state *, pid_t); -+ -+ debugee_state *debugee; -+}; -+ -+struct debugee -+{ -+ pid_t pid; -+ int wait_status; -+ unsigned int died : 1; -+ unsigned int event : 1; -+ unsigned int stopped : 1; -+ unsigned int trace_singlestep : 1; -+ unsigned int trace_syscall : 1; -+ unsigned int traced : 1; -+ unsigned int zombie : 1; -+ unsigned int in_context : 1; -+}; -+ -+extern int debugger_syscall(debugger_state *debugger, pid_t pid); -+extern int debugger_normal_return (debugger_state *debugger, pid_t unused); -+ -+extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t, -+ int *strace_out); -+extern void debugger_cancelled_return(debugger_state *debugger, int result); -+ -+#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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/ptrace.c um/arch/um/kernel/tt/ptproxy/ptrace.c ---- orig/arch/um/kernel/tt/ptproxy/ptrace.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ptproxy/ptrace.c Mon Nov 11 13:06:03 2002 -@@ -0,0 +1,239 @@ -+/********************************************************************** -+ptrace.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+Jeff Dike (jdike@karaya.com) : Modified for integration into uml -+**********************************************************************/ -+ -+#include <errno.h> -+#include <unistd.h> -+#include <signal.h> -+#include <sys/types.h> -+#include <sys/time.h> -+#include <sys/ptrace.h> -+#include <sys/wait.h> -+#include <asm/ptrace.h> -+ -+#include "ptproxy.h" -+#include "debug.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "ptrace_user.h" -+#include "tt.h" -+ -+long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, -+ long arg3, long arg4, pid_t child, int *ret) -+{ -+ sigset_t relay; -+ long result; -+ int status; -+ -+ *ret = 0; -+ if(debugger->debugee->died) return(-ESRCH); -+ -+ switch(arg1){ -+ case PTRACE_ATTACH: -+ if(debugger->debugee->traced) return(-EPERM); -+ -+ debugger->debugee->pid = arg2; -+ debugger->debugee->traced = 1; -+ -+ if(is_valid_pid(arg2) && (arg2 != child)){ -+ debugger->debugee->in_context = 0; -+ kill(arg2, SIGSTOP); -+ debugger->debugee->event = 1; -+ debugger->debugee->wait_status = W_STOPCODE(SIGSTOP); -+ } -+ else { -+ debugger->debugee->in_context = 1; -+ if(debugger->debugee->stopped) -+ child_proxy(child, W_STOPCODE(SIGSTOP)); -+ else kill(child, SIGSTOP); -+ } -+ -+ return(0); -+ -+ case PTRACE_DETACH: -+ if(!debugger->debugee->traced) return(-EPERM); -+ -+ debugger->debugee->traced = 0; -+ debugger->debugee->pid = 0; -+ if(!debugger->debugee->in_context) -+ kill(child, SIGCONT); -+ -+ return(0); -+ -+ case PTRACE_CONT: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ *ret = PTRACE_CONT; -+ return(ptrace(PTRACE_CONT, child, arg3, arg4)); -+ -+#ifdef UM_HAVE_GETFPREGS -+ case PTRACE_GETFPREGS: -+ { -+ long regs[FP_FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETFPREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, -+ regs[i]); -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_GETFPXREGS -+ case PTRACE_GETFPXREGS: -+ { -+ long regs[FPX_FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETFPXREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, -+ regs[i]); -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_GETREGS -+ case PTRACE_GETREGS: -+ { -+ long regs[FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace (PTRACE_POKEDATA, debugger->pid, -+ arg4 + 4 * i, regs[i]); -+ return(result); -+ } -+ break; -+#endif -+ -+ case PTRACE_KILL: -+ result = ptrace(PTRACE_KILL, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ -+ case PTRACE_PEEKDATA: -+ case PTRACE_PEEKTEXT: -+ case PTRACE_PEEKUSER: -+ /* The value being read out could be -1, so we have to -+ * check errno to see if there's an error, and zero it -+ * beforehand so we're not faked out by an old error -+ */ -+ -+ errno = 0; -+ result = ptrace(arg1, child, arg3, 0); -+ if((result == -1) && (errno != 0)) return(-errno); -+ -+ result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ -+ case PTRACE_POKEDATA: -+ case PTRACE_POKETEXT: -+ case PTRACE_POKEUSER: -+ result = ptrace(arg1, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ if(arg1 == PTRACE_POKEUSER) ptrace_pokeuser(arg3, arg4); -+ return(result); -+ -+#ifdef UM_HAVE_SETFPREGS -+ case PTRACE_SETFPREGS: -+ { -+ long regs[FP_FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETFPREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_SETFPXREGS -+ case PTRACE_SETFPXREGS: -+ { -+ long regs[FPX_FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETFPXREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_SETREGS -+ case PTRACE_SETREGS: -+ { -+ long regs[FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+ case PTRACE_SINGLESTEP: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ sigemptyset(&relay); -+ sigaddset(&relay, SIGSEGV); -+ sigaddset(&relay, SIGILL); -+ sigaddset(&relay, SIGBUS); -+ result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP, -+ &relay); -+ child_proxy(child, status); -+ return(result); -+ -+ case PTRACE_SYSCALL: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ result = ptrace(PTRACE_SYSCALL, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ *ret = PTRACE_SYSCALL; -+ return(result); -+ -+ case PTRACE_TRACEME: -+ default: -+ return(-EINVAL); -+ } -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/sysdep.c um/arch/um/kernel/tt/ptproxy/sysdep.c ---- orig/arch/um/kernel/tt/ptproxy/sysdep.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ptproxy/sysdep.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,71 @@ -+/********************************************************************** -+sysdep.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#include <stdio.h> -+#include <string.h> -+#include <stdlib.h> -+#include <signal.h> -+#include <sys/types.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+#include <linux/unistd.h> -+#include "ptrace_user.h" -+#include "user_util.h" -+#include "user.h" -+ -+int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, -+ long *arg5) -+{ -+ *arg1 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG1_OFFSET, 0); -+ *arg2 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG2_OFFSET, 0); -+ *arg3 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG3_OFFSET, 0); -+ *arg4 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG4_OFFSET, 0); -+ *arg5 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG5_OFFSET, 0); -+ return(ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, 0)); -+} -+ -+void syscall_cancel(pid_t pid, int result) -+{ -+ if((ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getpid) < 0) || -+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) || -+ (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) || -+ (ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result) < 0) || -+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)) -+ printk("ptproxy: couldn't cancel syscall: errno = %d\n", -+ errno); -+} -+ -+void syscall_set_result(pid_t pid, long result) -+{ -+ ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result); -+} -+ -+void syscall_continue(pid_t pid) -+{ -+ ptrace(PTRACE_SYSCALL, pid, 0, 0); -+} -+ -+int syscall_pause(pid_t pid) -+{ -+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){ -+ printk("syscall_change - ptrace failed, errno = %d\n", errno); -+ return(-1); -+ } -+ 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/sysdep.h um/arch/um/kernel/tt/ptproxy/sysdep.h ---- orig/arch/um/kernel/tt/ptproxy/sysdep.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ptproxy/sysdep.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,25 @@ -+/********************************************************************** -+sysdep.h -+ -+Copyright (C) 1999 Lars Brinkhoff. -+Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+See the file COPYING for licensing terms and conditions. -+**********************************************************************/ -+ -+extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, -+ long *arg4, long *arg5); -+extern void syscall_cancel (pid_t pid, long result); -+extern void syscall_set_result (pid_t pid, long result); -+extern void syscall_continue (pid_t pid); -+extern int syscall_pause(pid_t pid); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/wait.c um/arch/um/kernel/tt/ptproxy/wait.c ---- orig/arch/um/kernel/tt/ptproxy/wait.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ptproxy/wait.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,86 @@ -+/********************************************************************** -+wait.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+**********************************************************************/ -+ -+#include <errno.h> -+#include <signal.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+ -+#include "ptproxy.h" -+#include "sysdep.h" -+#include "wait.h" -+#include "user_util.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/ptrace_user.h" -+#include "sysdep/sigcontext.h" -+ -+int proxy_wait_return(struct debugger *debugger, pid_t unused) -+{ -+ debugger->waiting = 0; -+ -+ if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){ -+ debugger_cancelled_return(debugger, -ECHILD); -+ return(0); -+ } -+ -+ if(debugger->debugee->zombie && debugger->debugee->event) -+ debugger->debugee->died = 1; -+ -+ if(debugger->debugee->event){ -+ debugger->debugee->event = 0; -+ ptrace(PTRACE_POKEDATA, debugger->pid, -+ debugger->wait_status_ptr, -+ debugger->debugee->wait_status); -+ /* if (wait4) -+ ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */ -+ debugger_cancelled_return(debugger, debugger->debugee->pid); -+ return(0); -+ } -+ -+ /* pause will return -EINTR, which happens to be right for wait */ -+ debugger_normal_return(debugger, -1); -+ return(0); -+} -+ -+int parent_wait_return(struct debugger *debugger, pid_t unused) -+{ -+ return(debugger_normal_return(debugger, -1)); -+} -+ -+int real_wait_return(struct debugger *debugger) -+{ -+ unsigned long ip; -+ int err, 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); -+ if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0) -+ tracer_panic("real_wait_return : Failed to restart system " -+ "call, errno = %d\n"); -+ 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"); -+ 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/wait.h um/arch/um/kernel/tt/ptproxy/wait.h ---- orig/arch/um/kernel/tt/ptproxy/wait.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/ptproxy/wait.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,15 @@ -+/********************************************************************** -+wait.h -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#ifndef __PTPROXY_WAIT_H -+#define __PTPROXY_WAIT_H -+ -+extern int proxy_wait_return(struct debugger *debugger, pid_t unused); -+extern int real_wait_return(struct debugger *debugger); -+extern int parent_wait_return(struct debugger *debugger, pid_t unused); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/sys-i386/Makefile um/arch/um/kernel/tt/sys-i386/Makefile ---- orig/arch/um/kernel/tt/sys-i386/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/sys-i386/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = sys-i386.o -+ -+obj-y = sigcontext.o -+ -+USER_OBJS = sigcontext.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/sys-i386/sigcontext.c um/arch/um/kernel/tt/sys-i386/sigcontext.c ---- orig/arch/um/kernel/tt/sys-i386/sigcontext.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/sys-i386/sigcontext.c Sun Dec 1 23:33:52 2002 -@@ -0,0 +1,60 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <asm/sigcontext.h> -+#include "kern_util.h" -+#include "sysdep/frame.h" -+ -+int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data) -+{ -+ struct arch_frame_data *arch = data; -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ struct _fpstate *to_fp, *from_fp; -+ unsigned long sigs; -+ int err; -+ -+ to_fp = to->fpstate; -+ from_fp = from->fpstate; -+ sigs = to->oldmask; -+ err = copy_from_user_proc(to, from, sizeof(*to)); -+ to->oldmask = sigs; -+ if(to_fp != NULL){ -+ err |= copy_from_user_proc(&to->fpstate, &to_fp, -+ sizeof(to->fpstate)); -+ err |= copy_from_user_proc(to_fp, from_fp, arch->fpstate_size); -+ } -+ return(err); -+} -+ -+int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, void *data) -+{ -+ struct arch_frame_data *arch = data; -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ struct _fpstate *to_fp, *from_fp; -+ int err; -+ -+ to_fp = (struct _fpstate *) -+ (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to))); -+ from_fp = from->fpstate; -+ err = copy_to_user_proc(to, from, sizeof(*to)); -+ if(from_fp != NULL){ -+ err |= copy_to_user_proc(&to->fpstate, &to_fp, -+ sizeof(to->fpstate)); -+ err |= copy_to_user_proc(to_fp, from_fp, arch->fpstate_size); -+ } -+ 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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/syscall_kern.c um/arch/um/kernel/tt/syscall_kern.c ---- orig/arch/um/kernel/tt/syscall_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/syscall_kern.c Sun Dec 8 19:32:53 2002 -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/types.h" -+#include "linux/utime.h" -+#include "linux/sys.h" -+#include "asm/unistd.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+static inline int check_area(void *ptr, int size) -+{ -+ return(verify_area(VERIFY_WRITE, ptr, size)); -+} -+ -+static int check_readlink(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ UPT_SYSCALL_ARG2(®s->regs))); -+} -+ -+static int check_utime(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct utimbuf))); -+} -+ -+static int check_oldstat(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct __old_kernel_stat))); -+} -+ -+static int check_stat(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct stat))); -+} -+ -+static int check_stat64(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct stat64))); -+} -+ -+struct bogus { -+ int kernel_ds; -+ int (*check_params)(struct pt_regs *); -+}; -+ -+struct bogus this_is_bogus[256] = { -+ [ __NR_mknod ] = { 1, NULL }, -+ [ __NR_mkdir ] = { 1, NULL }, -+ [ __NR_rmdir ] = { 1, NULL }, -+ [ __NR_unlink ] = { 1, NULL }, -+ [ __NR_symlink ] = { 1, NULL }, -+ [ __NR_link ] = { 1, NULL }, -+ [ __NR_rename ] = { 1, NULL }, -+ [ __NR_umount ] = { 1, NULL }, -+ [ __NR_mount ] = { 1, NULL }, -+ [ __NR_pivot_root ] = { 1, NULL }, -+ [ __NR_chdir ] = { 1, NULL }, -+ [ __NR_chroot ] = { 1, NULL }, -+ [ __NR_open ] = { 1, NULL }, -+ [ __NR_quotactl ] = { 1, NULL }, -+ [ __NR_sysfs ] = { 1, NULL }, -+ [ __NR_readlink ] = { 1, check_readlink }, -+ [ __NR_acct ] = { 1, NULL }, -+ [ __NR_execve ] = { 1, NULL }, -+ [ __NR_uselib ] = { 1, NULL }, -+ [ __NR_statfs ] = { 1, NULL }, -+ [ __NR_truncate ] = { 1, NULL }, -+ [ __NR_access ] = { 1, NULL }, -+ [ __NR_chmod ] = { 1, NULL }, -+ [ __NR_chown ] = { 1, NULL }, -+ [ __NR_lchown ] = { 1, NULL }, -+ [ __NR_utime ] = { 1, check_utime }, -+ [ __NR_oldlstat ] = { 1, check_oldstat }, -+ [ __NR_oldstat ] = { 1, check_oldstat }, -+ [ __NR_stat ] = { 1, check_stat }, -+ [ __NR_lstat ] = { 1, check_stat }, -+ [ __NR_stat64 ] = { 1, check_stat64 }, -+ [ __NR_lstat64 ] = { 1, check_stat64 }, -+ [ __NR_chown32 ] = { 1, NULL }, -+}; -+ -+/* sys_utimes */ -+ -+static int check_bogosity(struct pt_regs *regs) -+{ -+ struct bogus *bogon = &this_is_bogus[UPT_SYSCALL_NR(®s->regs)]; -+ -+ if(!bogon->kernel_ds) return(0); -+ if(bogon->check_params && (*bogon->check_params)(regs)) -+ return(-EFAULT); -+ set_fs(KERNEL_DS); -+ return(0); -+} -+ -+extern syscall_handler_t *sys_call_table[]; -+ -+long execute_syscall_tt(void *r) -+{ -+ struct pt_regs *regs = r; -+ long res; -+ int syscall; -+ -+ current->thread.nsyscalls++; -+ nsyscalls++; -+ syscall = UPT_SYSCALL_NR(®s->regs); -+ -+ if((syscall >= NR_syscalls) || (syscall < 0)) -+ res = -ENOSYS; -+ else if(honeypot && check_bogosity(regs)) -+ res = -EFAULT; -+ else res = EXECUTE_SYSCALL(syscall, regs); -+ -+ set_fs(USER_DS); -+ -+ if(current->thread.mode.tt.singlestep_syscall){ -+ current->thread.mode.tt.singlestep_syscall = 0; -+ current->ptrace &= ~PT_DTRACE; -+ force_sig(SIGTRAP, current); -+ } -+ -+ return(res); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/syscall_user.c um/arch/um/kernel/tt/syscall_user.c ---- orig/arch/um/kernel/tt/syscall_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/syscall_user.c Sun Dec 8 21:00:11 2002 -@@ -0,0 +1,89 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <signal.h> -+#include <errno.h> -+#include <sys/ptrace.h> -+#include <asm/unistd.h> -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "ptrace_user.h" -+#include "task.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "syscall_user.h" -+#include "tt.h" -+ -+/* XXX Bogus */ -+#define ERESTARTSYS 512 -+#define ERESTARTNOINTR 513 -+#define ERESTARTNOHAND 514 -+ -+void syscall_handler_tt(int sig, union uml_pt_regs *regs) -+{ -+ void *sc; -+ long result; -+ int index, syscall; -+ -+ syscall = UPT_SYSCALL_NR(regs); -+ sc = UPT_SC(regs); -+ SC_START_SYSCALL(sc); -+ -+ index = record_syscall_start(syscall); -+ syscall_trace(); -+ result = execute_syscall(regs); -+ -+ /* regs->sc may have changed while the system call ran (there may -+ * have been an interrupt or segfault), so it needs to be refreshed. -+ */ -+ UPT_SC(regs) = sc; -+ -+ SC_SET_SYSCALL_RETURN(sc, result); -+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || -+ (result == -ERESTARTNOINTR)) -+ do_signal(result); -+ -+ syscall_trace(); -+ record_syscall_end(index, result); -+} -+ -+int do_syscall(void *task, int pid) -+{ -+ unsigned long proc_regs[FRAME_SIZE]; -+ union uml_pt_regs *regs; -+ int syscall; -+ -+ if(ptrace_getregs(pid, proc_regs) < 0) -+ tracer_panic("Couldn't read registers"); -+ syscall = PT_SYSCALL_NR(proc_regs); -+ -+ regs = TASK_REGS(task); -+ UPT_SYSCALL_NR(regs) = syscall; -+ -+ if(syscall < 1) return(0); -+ -+ if((syscall != __NR_sigreturn) && -+ ((unsigned long *) PT_IP(proc_regs) >= &_stext) && -+ ((unsigned long *) PT_IP(proc_regs) <= &_etext)) -+ tracer_panic("I'm tracing myself and I can't get out"); -+ -+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getpid) < 0) -+ tracer_panic("do_syscall : Nullifying syscall failed, " -+ "errno = %d", errno); -+ return(1); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/time.c um/arch/um/kernel/tt/time.c ---- orig/arch/um/kernel/tt/time.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/time.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include <sys/time.h> -+#include <time_user.h> -+#include "process.h" -+#include "user.h" -+ -+void user_time_init_tt(void) -+{ -+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/tlb.c um/arch/um/kernel/tt/tlb.c ---- orig/arch/um/kernel/tt/tlb.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/tlb.c Thu Dec 19 13:03:11 2002 -@@ -0,0 +1,220 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "os.h" -+ -+static void fix_range(struct mm_struct *mm, unsigned long start_addr, -+ unsigned long end_addr, int force) -+{ -+ pgd_t *npgd; -+ pmd_t *npmd; -+ pte_t *npte; -+ unsigned long addr; -+ int r, w, x, err; -+ -+ if((current->thread.mode.tt.extern_pid != -1) && -+ (current->thread.mode.tt.extern_pid != os_getpid())) -+ panic("fix_range fixing wrong address space, current = 0x%p", -+ current); -+ if(mm == NULL) return; -+ for(addr=start_addr;addr<end_addr;){ -+ if(addr == TASK_SIZE){ -+ /* Skip over kernel text, kernel data, and physical -+ * memory, which don't have ptes, plus kernel virtual -+ * memory, which is flushed separately, and remap -+ * the process stack. The only way to get here is -+ * if (end_addr == STACK_TOP) > TASK_SIZE, which is -+ * only true in the honeypot case. -+ */ -+ addr = STACK_TOP - ABOVE_KMEM; -+ continue; -+ } -+ npgd = pgd_offset(mm, addr); -+ npmd = pmd_offset(npgd, addr); -+ if(pmd_present(*npmd)){ -+ npte = pte_offset(npmd, addr); -+ r = pte_read(*npte); -+ w = pte_write(*npte); -+ x = pte_exec(*npte); -+ if(!pte_dirty(*npte)) w = 0; -+ if(!pte_young(*npte)){ -+ r = 0; -+ w = 0; -+ } -+ if(force || pte_newpage(*npte)){ -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*npte)) -+ map_memory(addr, -+ pte_val(*npte) & PAGE_MASK, -+ PAGE_SIZE, r, w, x); -+ } -+ else if(pte_newprot(*npte)){ -+ protect_memory(addr, PAGE_SIZE, r, w, x, 1); -+ } -+ *npte = pte_mkuptodate(*npte); -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(force || pmd_newpage(*npmd)){ -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ pmd_mkuptodate(*npmd); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+atomic_t vmchange_seq = ATOMIC_INIT(1); -+ -+static void flush_kernel_vm_range(unsigned long start, unsigned long end, -+ int update_seq) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ int updated = 0, err; -+ -+ mm = &init_mm; -+ for(addr = start; addr < end;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte) || pte_newpage(*pte)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*pte)) -+ map_memory(addr, -+ pte_val(*pte) & PAGE_MASK, -+ PAGE_SIZE, 1, 1, 1); -+ } -+ else if(pte_newprot(*pte)){ -+ updated = 1; -+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); -+ } -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(pmd_newpage(*pmd)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+ if(updated && update_seq) atomic_inc(&vmchange_seq); -+} -+ -+static void protect_vm_page(unsigned long addr, int w, int must_succeed) -+{ -+ int err; -+ -+ err = protect_memory(addr, PAGE_SIZE, 1, w, 1, must_succeed); -+ if(err == 0) return; -+ else if((err == -EFAULT) || (err == -ENOMEM)){ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE, 1); -+ protect_vm_page(addr, w, 1); -+ } -+ else panic("protect_vm_page : protect failed, errno = %d\n", err); -+} -+ -+void mprotect_kernel_vm(int w) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ -+ mm = &init_mm; -+ for(addr = start_vm; addr < end_vm;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(pte_present(*pte)) protect_vm_page(addr, w, 0); -+ addr += PAGE_SIZE; -+ } -+ else addr += PMD_SIZE; -+ } -+} -+ -+void flush_tlb_kernel_vm_tt(void) -+{ -+ flush_kernel_vm_range(start_vm, end_vm, 1); -+} -+ -+void __flush_tlb_one_tt(unsigned long addr) -+{ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE, 1); -+} -+ -+void flush_tlb_range_tt(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ if(mm != current->mm) return; -+ -+ /* Assumes that the range start ... end is entirely within -+ * either process memory or kernel vm -+ */ -+ if((start >= start_vm) && (start < end_vm)) -+ flush_kernel_vm_range(start, end, 1); -+ else fix_range(mm, start, end, 0); -+} -+ -+void flush_tlb_mm_tt(struct mm_struct *mm) -+{ -+ unsigned long seq; -+ -+ if(mm != current->mm) return; -+ -+ fix_range(mm, 0, STACK_TOP, 0); -+ -+ seq = atomic_read(&vmchange_seq); -+ if(current->thread.mode.tt.vm_seq == seq) return; -+ current->thread.mode.tt.vm_seq = seq; -+ flush_kernel_vm_range(start_vm, end_vm, 0); -+} -+ -+void force_flush_all_tt(void) -+{ -+ fix_range(current->mm, 0, STACK_TOP, 1); -+ flush_kernel_vm_range(start_vm, end_vm, 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/tracer.c um/arch/um/kernel/tt/tracer.c ---- orig/arch/um/kernel/tt/tracer.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/tracer.c Wed Mar 26 10:01:33 2003 -@@ -0,0 +1,453 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stdarg.h> -+#include <unistd.h> -+#include <signal.h> -+#include <errno.h> -+#include <sched.h> -+#include <string.h> -+#include <sys/mman.h> -+#include <sys/ptrace.h> -+#include <sys/time.h> -+#include <sys/wait.h> -+#include "user.h" -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "sysdep/sigcontext.h" -+#include "os.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "process.h" -+#include "kern_util.h" -+#include "frame.h" -+#include "chan_user.h" -+#include "ptrace_user.h" -+#include "mode.h" -+#include "tt.h" -+ -+static int tracer_winch[2]; -+ -+int is_tracer_winch(int pid, int fd, void *data) -+{ -+ if(pid != tracing_pid) -+ return(0); -+ -+ register_winch_irq(tracer_winch[0], fd, -1, data); -+ return(1); -+} -+ -+static void tracer_winch_handler(int sig) -+{ -+ char c = 1; -+ -+ if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c)) -+ printk("tracer_winch_handler - write failed, errno = %d\n", -+ errno); -+} -+ -+/* Called only by the tracing thread during initialization */ -+ -+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); -+ return; -+ } -+ signal(SIGWINCH, tracer_winch_handler); -+} -+ -+void attach_process(int pid) -+{ -+ if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) || -+ (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) -+ tracer_panic("OP_FORK failed to attach pid"); -+ wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) -+ tracer_panic("OP_FORK failed to continue process"); -+} -+ -+void tracer_panic(char *format, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, format); -+ vprintf(format, ap); -+ printf("\n"); -+ while(1) pause(); -+} -+ -+static void tracer_segv(int sig, struct sigcontext sc) -+{ -+ printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n", -+ SC_FAULT_ADDR(&sc), SC_IP(&sc)); -+ while(1) -+ pause(); -+} -+ -+/* Changed early in boot, and then only read */ -+int debug = 0; -+int debug_stop = 1; -+int debug_parent = 0; -+int honeypot = 0; -+ -+static int signal_tramp(void *arg) -+{ -+ int (*proc)(void *); -+ -+ if(honeypot && munmap((void *) (host_task_size - 0x10000000), -+ 0x10000000)) -+ panic("Unmapping stack failed"); -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) -+ panic("ptrace PTRACE_TRACEME failed"); -+ os_stop_process(os_getpid()); -+ change_sig(SIGWINCH, 0); -+ signal(SIGUSR1, SIG_IGN); -+ change_sig(SIGCHLD, 0); -+ signal(SIGSEGV, (__sighandler_t) sig_handler); -+ set_cmdline("(idle thread)"); -+ set_init_pid(os_getpid()); -+ proc = arg; -+ return((*proc)(NULL)); -+} -+ -+static void sleeping_process_signal(int pid, int sig) -+{ -+ switch(sig){ -+ /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is -+ * right because the process must be in the kernel already. -+ */ -+ case SIGCONT: -+ 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); -+ break; -+ -+ /* This happens when the debugger (e.g. strace) is doing system call -+ * tracing on the kernel. During a context switch, the current task -+ * will be set to the incoming process and the outgoing process will -+ * hop into write and then read. Since it's not the current process -+ * any more, the trace of those will land here. So, we need to just -+ * PTRACE_SYSCALL it. -+ */ -+ case SIGTRAP: -+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) -+ tracer_panic("sleeping_process_signal : Failed to " -+ "PTRACE_SYSCALL pid %d, errno = %d\n", -+ pid, sig); -+ break; -+ case SIGSTOP: -+ break; -+ default: -+ tracer_panic("sleeping process %d got unexpected " -+ "signal : %d\n", pid, sig); -+ break; -+ } -+} -+ -+/* Accessed only by the tracing thread */ -+int debugger_pid = -1; -+int debugger_parent = -1; -+int debugger_fd = -1; -+int gdb_pid = -1; -+ -+struct { -+ int pid; -+ int signal; -+ unsigned long addr; -+ struct timeval time; -+} signal_record[1024][32]; -+ -+int signal_index[32]; -+int nsignals = 0; -+int debug_trace = 0; -+extern int io_nsignals, io_count, intr_count; -+ -+extern void signal_usr1(int sig); -+ -+int tracing_pid = -1; -+ -+int tracer(int (*init_proc)(void *), void *sp) -+{ -+ void *task = NULL; -+ unsigned long eip = 0; -+ int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; -+ int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0; -+ -+ capture_signal_stack(); -+ signal(SIGPIPE, SIG_IGN); -+ setup_tracer_winch(); -+ tracing_pid = os_getpid(); -+ printf("tracing thread pid = %d\n", tracing_pid); -+ -+ pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0){ -+ printf("waitpid on idle thread failed, errno = %d\n", errno); -+ exit(1); -+ } -+ if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ -+ printf("Failed to continue idle thread, errno = %d\n", errno); -+ exit(1); -+ } -+ -+ signal(SIGSEGV, (sighandler_t) tracer_segv); -+ signal(SIGUSR1, signal_usr1); -+ if(debug_trace){ -+ printf("Tracing thread pausing to be attached\n"); -+ stop(); -+ } -+ if(debug){ -+ if(gdb_pid != -1) -+ debugger_pid = attach_debugger(pid, gdb_pid, 1); -+ else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop); -+ if(debug_parent){ -+ debugger_parent = os_process_parent(debugger_pid); -+ init_parent_proxy(debugger_parent); -+ err = attach(debugger_parent); -+ if(err){ -+ printf("Failed to attach debugger parent %d, " -+ "errno = %d\n", debugger_parent, err); -+ debugger_parent = -1; -+ } -+ else { -+ if(ptrace(PTRACE_SYSCALL, debugger_parent, -+ 0, 0) < 0){ -+ printf("Failed to continue debugger " -+ "parent, errno = %d\n", errno); -+ debugger_parent = -1; -+ } -+ } -+ } -+ } -+ set_cmdline("(tracing thread)"); -+ while(1){ -+ if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){ -+ if(errno != ECHILD){ -+ printf("wait failed - errno = %d\n", errno); -+ } -+ continue; -+ } -+ if(pid == debugger_pid){ -+ int cont = 0; -+ -+ if(WIFEXITED(status) || WIFSIGNALED(status)) -+ debugger_pid = -1; -+ /* XXX Figure out how to deal with gdb and SMP */ -+ else cont = debugger_signal(status, cpu_tasks[0].pid); -+ if(cont == PTRACE_SYSCALL) strace = 1; -+ continue; -+ } -+ else if(pid == debugger_parent){ -+ debugger_parent_signal(status, pid); -+ continue; -+ } -+ nsignals++; -+ if(WIFEXITED(status)) ; -+#ifdef notdef -+ { -+ printf("Child %d exited with status %d\n", pid, -+ WEXITSTATUS(status)); -+ } -+#endif -+ else if(WIFSIGNALED(status)){ -+ sig = WTERMSIG(status); -+ if(sig != 9){ -+ printf("Child %d exited with signal %d\n", pid, -+ sig); -+ } -+ } -+ else if(WIFSTOPPED(status)){ -+ proc_id = pid_to_processor_id(pid); -+ sig = WSTOPSIG(status); -+ if(signal_index[proc_id] == 1024){ -+ signal_index[proc_id] = 0; -+ last_index = 1023; -+ } -+ else last_index = signal_index[proc_id] - 1; -+ if(((sig == SIGPROF) || (sig == SIGVTALRM) || -+ (sig == SIGALRM)) && -+ (signal_record[proc_id][last_index].signal == sig)&& -+ (signal_record[proc_id][last_index].pid == pid)) -+ signal_index[proc_id] = last_index; -+ signal_record[proc_id][signal_index[proc_id]].pid = pid; -+ gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL); -+ eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); -+ signal_record[proc_id][signal_index[proc_id]].addr = eip; -+ signal_record[proc_id][signal_index[proc_id]++].signal = sig; -+ -+ if(proc_id == -1){ -+ sleeping_process_signal(pid, sig); -+ continue; -+ } -+ -+ task = cpu_tasks[proc_id].task; -+ tracing = is_tracing(task); -+ old_tracing = tracing; -+ -+ switch(sig){ -+ case SIGUSR1: -+ sig = 0; -+ op = do_proc_op(task, proc_id); -+ switch(op){ -+ case OP_TRACE_ON: -+ arch_leave_kernel(task, pid); -+ tracing = 1; -+ break; -+ case OP_REBOOT: -+ case OP_HALT: -+ unmap_physmem(); -+ kmalloc_ok = 0; -+ ptrace(PTRACE_KILL, pid, 0, 0); -+ return(op == OP_REBOOT); -+ case OP_NONE: -+ printf("Detaching pid %d\n", pid); -+ detach(pid, SIGSTOP); -+ continue; -+ default: -+ break; -+ } -+ /* OP_EXEC switches host processes on us, -+ * we want to continue the new one. -+ */ -+ pid = cpu_tasks[proc_id].pid; -+ break; -+ case SIGTRAP: -+ if(!tracing && (debugger_pid != -1)){ -+ child_signal(pid, status); -+ continue; -+ } -+ tracing = 0; -+ if(do_syscall(task, pid)) sig = SIGUSR2; -+ else clear_singlestep(task); -+ break; -+ case SIGPROF: -+ if(tracing) sig = 0; -+ break; -+ case SIGCHLD: -+ case SIGHUP: -+ sig = 0; -+ break; -+ case SIGSEGV: -+ case SIGIO: -+ case SIGALRM: -+ case SIGVTALRM: -+ case SIGFPE: -+ case SIGBUS: -+ case SIGILL: -+ case SIGWINCH: -+ default: -+ tracing = 0; -+ break; -+ } -+ set_tracing(task, tracing); -+ -+ if(!tracing && old_tracing) -+ arch_enter_kernel(task, pid); -+ -+ if(!tracing && (debugger_pid != -1) && (sig != 0) && -+ (sig != SIGALRM) && (sig != SIGVTALRM) && -+ (sig != SIGSEGV) && (sig != SIGTRAP) && -+ (sig != SIGUSR2) && (sig != SIGIO) && -+ (sig != SIGFPE)){ -+ child_signal(pid, status); -+ continue; -+ } -+ -+ if(tracing){ -+ if(singlestepping_tt(task)) -+ cont_type = PTRACE_SINGLESTEP; -+ else cont_type = PTRACE_SYSCALL; -+ } -+ else cont_type = PTRACE_CONT; -+ -+ if((cont_type == PTRACE_CONT) && -+ (debugger_pid != -1) && strace) -+ cont_type = PTRACE_SYSCALL; -+ -+ if(ptrace(cont_type, pid, 0, sig) != 0){ -+ tracer_panic("ptrace failed to continue " -+ "process - errno = %d\n", -+ errno); -+ } -+ } -+ } -+ return(0); -+} -+ -+static int __init uml_debug_setup(char *line, int *add) -+{ -+ char *next; -+ -+ debug = 1; -+ *add = 0; -+ if(*line != '=') return(0); -+ line++; -+ -+ while(line != NULL){ -+ next = strchr(line, ','); -+ if(next) *next++ = '\0'; -+ -+ if(!strcmp(line, "go")) debug_stop = 0; -+ else if(!strcmp(line, "parent")) debug_parent = 1; -+ else printf("Unknown debug option : '%s'\n", line); -+ -+ line = next; -+ } -+ return(0); -+} -+ -+__uml_setup("debug", uml_debug_setup, -+"debug\n" -+" Starts up the kernel under the control of gdb. See the \n" -+" kernel debugging tutorial and the debugging session pages\n" -+" at http://user-mode-linux.sourceforge.net/ for more information.\n\n" -+); -+ -+static int __init uml_debugtrace_setup(char *line, int *add) -+{ -+ debug_trace = 1; -+ return 0; -+} -+__uml_setup("debugtrace", uml_debugtrace_setup, -+"debugtrace\n" -+" Causes the tracing thread to pause until it is attached by a\n" -+" debugger and continued. This is mostly for debugging crashes\n" -+" early during boot, and should be pretty much obsoleted by\n" -+" the debug switch.\n\n" -+); -+ -+static int __init uml_honeypot_setup(char *line, int *add) -+{ -+ jail_setup("", add); -+ honeypot = 1; -+ return 0; -+} -+__uml_setup("honeypot", uml_honeypot_setup, -+"honeypot\n" -+" This makes UML put process stacks in the same location as they are\n" -+" on the host, allowing expoits such as stack smashes to work against\n" -+" UML. This implies 'jail'.\n\n" -+); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/trap_user.c um/arch/um/kernel/tt/trap_user.c ---- orig/arch/um/kernel/tt/trap_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/trap_user.c Mon Dec 9 13:14:42 2002 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include <signal.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "task.h" -+#include "tt.h" -+ -+void sig_handler_common_tt(int sig, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct tt_regs save_regs, *r; -+ struct signal_info *info; -+ int save_errno = errno, is_user; -+ -+ unprotect_kernel_mem(); -+ -+ r = &TASK_REGS(get_current())->tt; -+ save_regs = *r; -+ is_user = user_context(SC_SP(sc)); -+ r->sc = sc; -+ if(sig != SIGUSR2) -+ r->syscall = -1; -+ -+ change_sig(SIGUSR1, 1); -+ info = &sig_info[sig]; -+ if(!info->is_irq) unblock_signals(); -+ -+ (*info->handler)(sig, (union uml_pt_regs *) r); -+ -+ if(is_user){ -+ interrupt_end(); -+ block_signals(); -+ change_sig(SIGUSR1, 0); -+ set_user_mode(NULL); -+ } -+ *r = save_regs; -+ errno = save_errno; -+ if(is_user) protect_kernel_mem(); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/uaccess_user.c um/arch/um/kernel/tt/uaccess_user.c ---- orig/arch/um/kernel/tt/uaccess_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/uaccess_user.c Tue Mar 25 17:10:54 2003 -@@ -0,0 +1,100 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <setjmp.h> -+#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)); -+} -+ -+static void __do_strncpy(void *dst, const void *src, int count) -+{ -+ strncpy(dst, src, count); -+} -+ -+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); -+} -+ -+static void __do_clear(void *to, const void *from, int n) -+{ -+ memset(to, 0, n); -+} -+ -+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)); -+} -+ -+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){ -+ ret = strlen(str) + 1; -+ } -+ else { -+ ret = *faddrp - (unsigned long) str; -+ } -+ *fault_addr = NULL; -+ *fault_catcher = NULL; -+ -+ TASK_REGS(get_current())->tt = save; -+ return ret; -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/tt/unmap.c um/arch/um/kernel/tt/unmap.c ---- orig/arch/um/kernel/tt/unmap.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tt/unmap.c Wed Dec 11 10:42:21 2002 -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <sys/mman.h> -+ -+int switcheroo(int fd, int prot, void *from, void *to, int size) -+{ -+ if(munmap(to, size) < 0){ -+ return(-1); -+ } -+ if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){ -+ return(-1); -+ } -+ if(munmap(from, size) < 0){ -+ return(-1); -+ } -+ 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 -Naur -X ../exclude-files orig/arch/um/kernel/tty_log.c um/arch/um/kernel/tty_log.c ---- orig/arch/um/kernel/tty_log.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/tty_log.c Mon Feb 24 23:11:22 2003 -@@ -0,0 +1,168 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and -+ * geoffrey hing <ghing@net.ohio-state.edu> -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <string.h> -+#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 "./" -+ -+/* Set early in boot and then unchanged */ -+static char *tty_log_dir = TTY_LOG_DIR; -+static int tty_log_fd = -1; -+ -+#define TTY_LOG_OPEN 1 -+#define TTY_LOG_CLOSE 2 -+#define TTY_LOG_WRITE 3 -+ -+#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, 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 = sizeof(current_tty), -+ .direction = 0, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ write(tty_log_fd, &data, sizeof(data)); -+ write(tty_log_fd, ¤t_tty, data.len); -+ return(tty_log_fd); -+ } -+ -+ sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, -+ (unsigned int) tv.tv_usec); -+ -+ fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))), -+ 0644); -+ if(fd < 0){ -+ printk("open_tty_log : couldn't open '%s', errno = %d\n", -+ buf, -fd); -+ } -+ return(fd); -+} -+ -+void close_tty_log(int fd, void *tty) -+{ -+ struct tty_log_buf data; -+ struct timeval tv; -+ -+ if(tty_log_fd != -1){ -+ 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 } ); -+ write(tty_log_fd, &data, sizeof(data)); -+ return; -+ } -+ close(fd); -+} -+ -+int write_tty_log(int fd, char *buf, int len, void *tty, int is_read) -+{ -+ struct timeval tv; -+ struct tty_log_buf data; -+ int total = 0, try, missed, n, direction; -+ char chunk[64]; -+ -+ if(fd == tty_log_fd){ -+ 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 } ); -+ write(tty_log_fd, &data, sizeof(data)); -+ } -+ while(len > 0){ -+ try = (len > sizeof(chunk)) ? sizeof(chunk) : len; -+ missed = copy_from_user_proc(chunk, buf, try); -+ try -= missed; -+ n = write(fd, chunk, try); -+ if(n != try) -+ return(-errno); -+ if(missed != 0) -+ return(-EFAULT); -+ -+ len -= try; -+ total += try; -+ buf += try; -+ } -+ return(total); -+} -+ -+static int __init set_tty_log_dir(char *name, int *add) -+{ -+ tty_log_dir = name; -+ return 0; -+} -+ -+__uml_setup("tty_log_dir=", set_tty_log_dir, -+"tty_log_dir=<directory>\n" -+" This is used to specify the directory where the logs of all pty\n" -+" data from this UML machine will be written.\n\n" -+); -+ -+static int __init set_tty_log_fd(char *name, int *add) -+{ -+ char *end; -+ -+ tty_log_fd = strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ printf("set_tty_log_fd - strtoul failed on '%s'\n", name); -+ tty_log_fd = -1; -+ } -+ return 0; -+} -+ -+__uml_setup("tty_log_fd=", set_tty_log_fd, -+"tty_log_fd=<fd>\n" -+" This is used to specify a preconfigured file descriptor to which all\n" -+" tty data will be written. Preconfigure the descriptor with something\n" -+" like '10>tty_log tty_log_fd=10'.\n\n" -+); -+ -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/uaccess_user.c um/arch/um/kernel/uaccess_user.c ---- orig/arch/um/kernel/uaccess_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/uaccess_user.c Tue Mar 25 17:06:05 2003 -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <setjmp.h> -+#include <string.h> -+ -+/* These are here rather than tt/uaccess.c because skas mode needs them in -+ * order to do SIGBUS recovery when a tmpfs mount runs out of room. -+ */ -+ -+unsigned long __do_user_copy(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher, -+ void (*op)(void *to, const void *from, -+ int n), int *faulted_out) -+{ -+ unsigned long *faddrp = (unsigned long *) fault_addr, ret; -+ -+ jmp_buf jbuf; -+ *fault_catcher = &jbuf; -+ if(setjmp(jbuf) == 0){ -+ (*op)(to, from, n); -+ ret = 0; -+ *faulted_out = 0; -+ } -+ else { -+ ret = *faddrp; -+ *faulted_out = 1; -+ } -+ *fault_addr = NULL; -+ *fault_catcher = NULL; -+ return ret; -+} -+ -+void __do_copy(void *to, const void *from, int n) -+{ -+ memcpy(to, from, n); -+} -+ -+ -+int __do_copy_to_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher) -+{ -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, -+ __do_copy, &faulted); -+ if(!faulted) return(0); -+ else return(n - (fault - (unsigned long) to)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/um_arch.c um/arch/um/kernel/um_arch.c ---- orig/arch/um/kernel/um_arch.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/um_arch.c Thu Mar 6 19:06:09 2003 -@@ -0,0 +1,425 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/notifier.h" -+#include "linux/mm.h" -+#include "linux/types.h" -+#include "linux/tty.h" -+#include "linux/init.h" -+#include "linux/bootmem.h" -+#include "linux/spinlock.h" -+#include "linux/utsname.h" -+#include "linux/sysrq.h" -+#include "linux/seq_file.h" -+#include "linux/delay.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/ptrace.h" -+#include "asm/elf.h" -+#include "asm/user.h" -+#include "ubd_user.h" -+#include "asm/current.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mprot.h" -+#include "mem_user.h" -+#include "mem.h" -+#include "umid.h" -+#include "initrd.h" -+#include "init.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+#include "mode.h" -+ -+#define DEFAULT_COMMAND_LINE "root=/dev/ubd0" -+ -+struct cpuinfo_um boot_cpu_data = { -+ .loops_per_jiffy = 0, -+ .pgd_quick = NULL, -+ .pmd_quick = NULL, -+ .pte_quick = NULL, -+ .pgtable_cache_sz = 0, -+ .ipi_pipe = { -1, -1 } -+}; -+ -+unsigned long thread_saved_pc(struct thread_struct *thread) -+{ -+ return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, -+ thread))); -+} -+ -+static int show_cpuinfo(struct seq_file *m, void *v) -+{ -+ int index; -+ -+ index = (struct cpuinfo_um *)v - cpu_data; -+#ifdef CONFIG_SMP -+ if (!(cpu_online_map & (1 << index))) -+ return 0; -+#endif -+ -+ 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); -+ -+ return(0); -+} -+ -+static void *c_start(struct seq_file *m, loff_t *pos) -+{ -+ return *pos < NR_CPUS ? cpu_data + *pos : NULL; -+} -+ -+static void *c_next(struct seq_file *m, void *v, loff_t *pos) -+{ -+ ++*pos; -+ return c_start(m, pos); -+} -+ -+static void c_stop(struct seq_file *m, void *v) -+{ -+} -+ -+struct seq_operations cpuinfo_op = { -+ .start = c_start, -+ .next = c_next, -+ .stop = c_stop, -+ .show = show_cpuinfo, -+}; -+ -+pte_t * __bad_pagetable(void) -+{ -+ panic("Someone should implement __bad_pagetable"); -+ return(NULL); -+} -+ -+/* Set in linux_main */ -+unsigned long host_task_size; -+unsigned long task_size; -+unsigned long uml_start; -+ -+/* Set in early boot */ -+unsigned long uml_physmem; -+unsigned long uml_reserved; -+unsigned long start_vm; -+unsigned long end_vm; -+int ncpus = 1; -+ -+#ifdef CONFIG_MODE_TT -+/* Pointer set in linux_main, the array itself is private to each thread, -+ * and changed at address space creation time so this poses no concurrency -+ * problems. -+ */ -+static char *argv1_begin = NULL; -+static char *argv1_end = NULL; -+#endif -+ -+/* Set in early boot */ -+static int have_root __initdata = 0; -+long physmem_size = 32 * 1024 * 1024; -+ -+void set_cmdline(char *cmd) -+{ -+#ifdef CONFIG_MODE_TT -+ char *umid, *ptr; -+ -+ if(CHOOSE_MODE(honeypot, 0)) return; -+ -+ umid = get_umid(1); -+ if(umid != NULL){ -+ snprintf(argv1_begin, -+ (argv1_end - argv1_begin) * sizeof(*ptr), -+ "(%s) ", umid); -+ ptr = &argv1_begin[strlen(argv1_begin)]; -+ } -+ else ptr = argv1_begin; -+ -+ snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); -+ memset(argv1_begin + strlen(argv1_begin), '\0', -+ argv1_end - argv1_begin - strlen(argv1_begin)); -+#endif -+} -+ -+static char *usage_string = -+"User Mode Linux v%s\n" -+" available at http://user-mode-linux.sourceforge.net/\n\n"; -+ -+static int __init uml_version_setup(char *line, int *add) -+{ -+ printf("%s\n", system_utsname.release); -+ exit(0); -+} -+ -+__uml_setup("--version", uml_version_setup, -+"--version\n" -+" Prints the version number of the kernel.\n\n" -+); -+ -+static int __init uml_root_setup(char *line, int *add) -+{ -+ have_root = 1; -+ return 0; -+} -+ -+__uml_setup("root=", uml_root_setup, -+"root=<file containing the root fs>\n" -+" This is actually used by the generic kernel in exactly the same\n" -+" way as in any other kernel. If you configure a number of block\n" -+" devices and want to boot off something other than ubd0, you \n" -+" would use something like:\n" -+" root=/dev/ubd5\n\n" -+); -+ -+#ifdef CONFIG_SMP -+static int __init uml_ncpus_setup(char *line, int *add) -+{ -+ if (!sscanf(line, "%d", &ncpus)) { -+ printf("Couldn't parse [%s]\n", line); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+__uml_setup("ncpus=", uml_ncpus_setup, -+"ncpus=<# of desired CPUs>\n" -+" This tells an SMP kernel how many virtual processors to start.\n\n" -+); -+#endif -+ -+int force_tt = 0; -+ -+#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) -+#define DEFAULT_TT 0 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ force_tt = 1; -+ return(0); -+} -+ -+#else -+#ifdef CONFIG_MODE_SKAS -+ -+#define DEFAULT_TT 0 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); -+ return(0); -+} -+ -+#else -+#ifdef CONFIG_MODE_TT -+ -+#define DEFAULT_TT 1 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); -+ return(0); -+} -+ -+#else -+ -+#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled -+ -+#endif -+#endif -+#endif -+ -+__uml_setup("mode=tt", mode_tt_setup, -+"mode=tt\n" -+" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" -+" forces UML to run in tt (tracing thread) mode. It is not the default\n" -+" because it's slower and less secure than skas mode.\n\n" -+); -+ -+int mode_tt = DEFAULT_TT; -+ -+static int __init Usage(char *line, int *add) -+{ -+ const char **p; -+ -+ printf(usage_string, system_utsname.release); -+ p = &__uml_help_start; -+ while (p < &__uml_help_end) { -+ printf("%s", *p); -+ p++; -+ } -+ exit(0); -+} -+ -+__uml_setup("--help", Usage, -+"--help\n" -+" Prints this message.\n\n" -+); -+ -+static int __init uml_checksetup(char *line, int *add) -+{ -+ struct uml_param *p; -+ -+ p = &__uml_setup_start; -+ while(p < &__uml_setup_end) { -+ int n; -+ -+ n = strlen(p->str); -+ if(!strncmp(line, p->str, n)){ -+ if (p->setup_func(line + n, add)) return 1; -+ } -+ p++; -+ } -+ return 0; -+} -+ -+static void __init uml_postsetup(void) -+{ -+ initcall_t *p; -+ -+ p = &__uml_postsetup_start; -+ while(p < &__uml_postsetup_end){ -+ (*p)(); -+ p++; -+ } -+ return; -+} -+ -+/* Set during early boot */ -+unsigned long brk_start; -+static struct vm_reserved kernel_vm_reserved; -+ -+#define MIN_VMALLOC (32 * 1024 * 1024) -+ -+int linux_main(int argc, char **argv) -+{ -+ unsigned long avail; -+ unsigned long virtmem_size, max_physmem; -+ unsigned int i, add, err; -+ -+ for (i = 1; i < argc; i++){ -+ if((i == 1) && (argv[i][0] == ' ')) continue; -+ add = 1; -+ uml_checksetup(argv[i], &add); -+ if(add) add_arg(saved_command_line, argv[i]); -+ } -+ if(have_root == 0) add_arg(saved_command_line, DEFAULT_COMMAND_LINE); -+ -+ mode_tt = force_tt ? 1 : !can_do_skas(); -+ uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, -+ &host_task_size, &task_size); -+ -+ brk_start = (unsigned long) sbrk(0); -+ CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); -+ -+ uml_physmem = uml_start; -+ -+ /* Reserve up to 4M after the current brk */ -+ uml_reserved = ROUND_4M(brk_start) + (1 << 22); -+ -+ setup_machinename(system_utsname.machine); -+ -+#ifdef CONFIG_MODE_TT -+ argv1_begin = argv[1]; -+ 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; -+ physmem_size -= highmem; -+#ifndef CONFIG_HIGHMEM -+ highmem = 0; -+ printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " -+ "to %ld bytes\n", physmem_size); -+#endif -+ } -+ -+ high_physmem = uml_physmem + physmem_size; -+ high_memory = (void *) high_physmem; -+ -+ start_vm = VMALLOC_START; -+ -+ setup_physmem(uml_physmem, uml_reserved, physmem_size); -+ virtmem_size = physmem_size; -+ avail = get_kmem_end() - start_vm; -+ if(physmem_size > avail) virtmem_size = avail; -+ end_vm = start_vm + virtmem_size; -+ -+ if(virtmem_size < physmem_size) -+ 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_task + -+ 2 * PAGE_SIZE; -+ -+ task_protections((unsigned long) &init_task); -+ os_flush_stdout(); -+ -+ return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); -+} -+ -+static int panic_exit(struct notifier_block *self, unsigned long unused1, -+ void *unused2) -+{ -+#ifdef CONFIG_SYSRQ -+ handle_sysrq('p', ¤t->thread.regs, NULL, NULL); -+#endif -+ machine_halt(); -+ return(0); -+} -+ -+static struct notifier_block panic_exit_notifier = { -+ .notifier_call = panic_exit, -+ .next = NULL, -+ .priority = 0 -+}; -+ -+void __init setup_arch(char **cmdline_p) -+{ -+ notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); -+ paging_init(); -+ strcpy(command_line, saved_command_line); -+ *cmdline_p = command_line; -+ setup_hostinfo(); -+} -+ -+void __init check_bugs(void) -+{ -+ arch_check_bugs(); -+ check_ptrace(); -+ check_sigio(); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/umid.c um/arch/um/kernel/umid.c ---- orig/arch/um/kernel/umid.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/umid.c Mon Feb 24 23:11:23 2003 -@@ -0,0 +1,319 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <fcntl.h> -+#include <errno.h> -+#include <string.h> -+#include <stdlib.h> -+#include <dirent.h> -+#include <signal.h> -+#include <sys/stat.h> -+#include <sys/param.h> -+#include "user.h" -+#include "umid.h" -+#include "init.h" -+#include "os.h" -+#include "user_util.h" -+#include "choose-mode.h" -+ -+#define UMID_LEN 64 -+#define UML_DIR "~/.uml/" -+ -+/* Changed by set_umid and make_umid, which are run early in boot */ -+static char umid[UMID_LEN] = { 0 }; -+ -+/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ -+static char *uml_dir = UML_DIR; -+ -+/* Changed by set_umid */ -+static int umid_is_random = 1; -+static int umid_inited = 0; -+ -+static int make_umid(int (*printer)(const char *fmt, ...)); -+ -+static int __init set_umid(char *name, int is_random, -+ int (*printer)(const char *fmt, ...)) -+{ -+ if(umid_inited){ -+ (*printer)("Unique machine name can't be set twice\n"); -+ return(-1); -+ } -+ -+ if(strlen(name) > UMID_LEN - 1) -+ (*printer)("Unique machine name is being truncated to %s " -+ "characters\n", UMID_LEN); -+ strncpy(umid, name, UMID_LEN - 1); -+ umid[UMID_LEN - 1] = '\0'; -+ -+ umid_is_random = is_random; -+ umid_inited = 1; -+ return 0; -+} -+ -+static int __init set_umid_arg(char *name, int *add) -+{ -+ return(set_umid(name, 0, printf)); -+} -+ -+__uml_setup("umid=", set_umid_arg, -+"umid=<name>\n" -+" This is used to assign a unique identity to this UML machine and\n" -+" is used for naming the pid file and management console socket.\n\n" -+); -+ -+int __init umid_file_name(char *name, char *buf, int len) -+{ -+ int n; -+ -+ if(!umid_inited && make_umid(printk)) return(-1); -+ -+ n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; -+ if(n > len){ -+ printk("umid_file_name : buffer too short\n"); -+ return(-1); -+ } -+ -+ sprintf(buf, "%s%s/%s", uml_dir, umid, name); -+ return(0); -+} -+ -+extern int tracing_pid; -+ -+static int __init create_pid_file(void) -+{ -+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; -+ char pid[sizeof("nnnnn\0")]; -+ int fd; -+ -+ 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){ -+ printf("Open of machine pid file \"%s\" failed - " -+ "errno = %d\n", file, -fd); -+ return 0; -+ } -+ -+ sprintf(pid, "%d\n", os_getpid()); -+ if(write(fd, pid, strlen(pid)) != strlen(pid)) -+ printf("Write of pid file failed - errno = %d\n", errno); -+ close(fd); -+ return 0; -+} -+ -+static int actually_do_remove(char *dir) -+{ -+ DIR *directory; -+ struct dirent *ent; -+ int len; -+ char file[256]; -+ -+ if((directory = opendir(dir)) == NULL){ -+ printk("actually_do_remove : couldn't open directory '%s', " -+ "errno = %d\n", dir, errno); -+ return(1); -+ } -+ while((ent = readdir(directory)) != NULL){ -+ if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) -+ continue; -+ len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; -+ if(len > sizeof(file)){ -+ printk("Not deleting '%s' from '%s' - name too long\n", -+ ent->d_name, dir); -+ continue; -+ } -+ sprintf(file, "%s/%s", dir, ent->d_name); -+ if(unlink(file) < 0){ -+ printk("actually_do_remove : couldn't remove '%s' " -+ "from '%s', errno = %d\n", ent->d_name, dir, -+ errno); -+ return(1); -+ } -+ } -+ if(rmdir(dir) < 0){ -+ printk("actually_do_remove : couldn't rmdir '%s', " -+ "errno = %d\n", dir, errno); -+ return(1); -+ } -+ return(0); -+} -+ -+void remove_umid_dir(void) -+{ -+ char dir[strlen(uml_dir) + UMID_LEN + 1]; -+ if(!umid_inited) return; -+ -+ sprintf(dir, "%s%s", uml_dir, umid); -+ actually_do_remove(dir); -+} -+ -+char *get_umid(int only_if_set) -+{ -+ if(only_if_set && umid_is_random) return(NULL); -+ return(umid); -+} -+ -+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; -+ -+ sprintf(file, "%s/pid", dir); -+ dead = 0; -+ if((fd = os_open_file(file, of_read(OPENFLAGS()), 0)) < 0){ -+ if(fd != -ENOENT){ -+ printk("not_dead_yet : couldn't open pid file '%s', " -+ "errno = %d\n", file, -fd); -+ return(1); -+ } -+ dead = 1; -+ } -+ if(fd > 0){ -+ if(read(fd, pid, sizeof(pid)) < 0){ -+ printk("not_dead_yet : couldn't read pid file '%s', " -+ "errno = %d\n", file, errno); -+ return(1); -+ } -+ p = strtoul(pid, &end, 0); -+ if(end == pid){ -+ printk("not_dead_yet : couldn't parse pid file '%s', " -+ "errno = %d\n", file, errno); -+ dead = 1; -+ } -+ if(((kill(p, 0) < 0) && (errno == ESRCH)) || -+ (p == CHOOSE_MODE(tracing_pid, os_getpid()))) -+ dead = 1; -+ } -+ if(!dead) return(1); -+ return(actually_do_remove(dir)); -+} -+ -+static int __init set_uml_dir(char *name, int *add) -+{ -+ if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ -+ uml_dir = malloc(strlen(name) + 1); -+ if(uml_dir == NULL){ -+ printf("Failed to malloc uml_dir - error = %d\n", -+ errno); -+ uml_dir = name; -+ return(0); -+ } -+ sprintf(uml_dir, "%s/", name); -+ } -+ else uml_dir = name; -+ return 0; -+} -+ -+static int __init make_uml_dir(void) -+{ -+ char dir[MAXPATHLEN + 1] = { '\0' }; -+ int len; -+ -+ if(*uml_dir == '~'){ -+ char *home = getenv("HOME"); -+ -+ if(home == NULL){ -+ printf("make_uml_dir : no value in environment for " -+ "$HOME\n"); -+ exit(1); -+ } -+ strncpy(dir, home, sizeof(dir)); -+ uml_dir++; -+ } -+ len = strlen(dir); -+ strncat(dir, uml_dir, sizeof(dir) - len); -+ len = strlen(dir); -+ if((len > 0) && (len < sizeof(dir) - 1) && (dir[len - 1] != '/')){ -+ dir[len] = '/'; -+ dir[len + 1] = '\0'; -+ } -+ -+ if((uml_dir = malloc(strlen(dir) + 1)) == 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)){ -+ printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno); -+ return(-1); -+ } -+ return 0; -+} -+ -+static int __init make_umid(int (*printer)(const char *fmt, ...)) -+{ -+ int fd, err; -+ char tmp[strlen(uml_dir) + UMID_LEN + 1]; -+ -+ strncpy(tmp, uml_dir, sizeof(tmp) - 1); -+ tmp[sizeof(tmp) - 1] = '\0'; -+ -+ if(!umid_inited){ -+ strcat(tmp, "XXXXXX"); -+ fd = mkstemp(tmp); -+ if(fd < 0){ -+ (*printer)("make_umid - mkstemp failed, errno = %d\n", -+ errno); -+ return(1); -+ } -+ -+ close(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, printer); -+ } -+ -+ sprintf(tmp, "%s%s", uml_dir, umid); -+ -+ if((err = mkdir(tmp, 0777)) < 0){ -+ if(errno == EEXIST){ -+ if(not_dead_yet(tmp)){ -+ (*printer)("umid '%s' is in use\n", umid); -+ return(-1); -+ } -+ err = mkdir(tmp, 0777); -+ } -+ } -+ if(err < 0){ -+ (*printer)("Failed to create %s - errno = %d\n", umid, errno); -+ return(-1); -+ } -+ -+ return(0); -+} -+ -+__uml_setup("uml_dir=", set_uml_dir, -+"uml_dir=<directory>\n" -+" The location to place the pid and umid files.\n\n" -+); -+ -+__uml_postsetup(make_uml_dir); -+ -+static int __init make_umid_setup(void) -+{ -+ return(make_umid(printf)); -+} -+ -+__uml_postsetup(make_umid_setup); -+__uml_postsetup(create_pid_file); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/kernel/user_syms.c um/arch/um/kernel/user_syms.c ---- orig/arch/um/kernel/user_syms.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/user_syms.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,116 @@ -+#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" -+ -+/* XXX All the __CONFIG_* stuff is broken because this file can't include -+ * 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(__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(__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 -Naur -X ../exclude-files orig/arch/um/kernel/user_util.c um/arch/um/kernel/user_util.c ---- orig/arch/um/kernel/user_util.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/kernel/user_util.c Fri Jan 17 13:23:19 2003 -@@ -0,0 +1,175 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <fcntl.h> -+#include <unistd.h> -+#include <limits.h> -+#include <sys/mman.h> -+#include <sys/stat.h> -+#include <sys/ptrace.h> -+#include <sys/utsname.h> -+#include <sys/param.h> -+#include <sys/time.h> -+#include "asm/types.h" -+#include <ctype.h> -+#include <signal.h> -+#include <wait.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <sched.h> -+#include <termios.h> -+#include <string.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "mem_user.h" -+#include "init.h" -+#include "helper.h" -+#include "uml-config.h" -+ -+#define COMMAND_LINE_SIZE _POSIX_ARG_MAX -+ -+/* Changed in linux_main and setup_arch, which run before SMP is started */ -+char saved_command_line[COMMAND_LINE_SIZE] = { 0 }; -+char command_line[COMMAND_LINE_SIZE] = { 0 }; -+ -+void add_arg(char *cmd_line, char *arg) -+{ -+ if (strlen(cmd_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { -+ printf("add_arg: Too much command line!\n"); -+ exit(1); -+ } -+ if(strlen(cmd_line) > 0) strcat(cmd_line, " "); -+ strcat(cmd_line, arg); -+} -+ -+void stop(void) -+{ -+ while(1) sleep(1000000); -+} -+ -+void stack_protections(unsigned long address) -+{ -+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC; -+ -+ if(mprotect((void *) address, page_size(), prot) < 0) -+ panic("protecting stack failed, errno = %d", errno); -+} -+ -+void task_protections(unsigned long address) -+{ -+ unsigned long guard = address + page_size(); -+ unsigned long stack = guard + page_size(); -+ int prot = 0, pages; -+#ifdef notdef -+ if(mprotect((void *) guard, page_size(), prot) < 0) -+ panic("protecting guard page failed, errno = %d", errno); -+#endif -+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; -+ prot = PROT_READ | PROT_WRITE | PROT_EXEC; -+ if(mprotect((void *) stack, pages * page_size(), prot) < 0) -+ panic("protecting stack failed, errno = %d", errno); -+} -+ -+int wait_for_stop(int pid, int sig, int cont_type, void *relay) -+{ -+ sigset_t *relay_signals = relay; -+ int status, ret; -+ -+ while(1){ -+ if(((ret = waitpid(pid, &status, WUNTRACED)) < 0) || -+ !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ -+ if(ret < 0){ -+ if(errno == EINTR) continue; -+ printk("wait failed, errno = %d\n", -+ errno); -+ } -+ else if(WIFEXITED(status)) -+ printk("process exited with status %d\n", -+ WEXITSTATUS(status)); -+ else if(WIFSIGNALED(status)) -+ printk("process exited with signal %d\n", -+ WTERMSIG(status)); -+ else if((WSTOPSIG(status) == SIGVTALRM) || -+ (WSTOPSIG(status) == SIGALRM) || -+ (WSTOPSIG(status) == SIGIO) || -+ (WSTOPSIG(status) == SIGPROF) || -+ (WSTOPSIG(status) == SIGCHLD) || -+ (WSTOPSIG(status) == SIGWINCH) || -+ (WSTOPSIG(status) == SIGINT)){ -+ ptrace(cont_type, pid, 0, WSTOPSIG(status)); -+ continue; -+ } -+ else if((relay_signals != NULL) && -+ sigismember(relay_signals, WSTOPSIG(status))){ -+ ptrace(cont_type, pid, 0, WSTOPSIG(status)); -+ continue; -+ } -+ else printk("process stopped with signal %d\n", -+ WSTOPSIG(status)); -+ panic("wait_for_stop failed to wait for %d to stop " -+ "with %d\n", pid, sig); -+ } -+ return(status); -+ } -+} -+ -+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; -+ int err; -+ -+ tcgetattr(fd, &tt); -+ cfmakeraw(&tt); -+ err = tcsetattr(fd, TCSANOW, &tt); -+ if((err < 0) && complain){ -+ printk("tcsetattr failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ return(0); -+} -+ -+void setup_machinename(char *machine_out) -+{ -+ struct utsname host; -+ -+ uname(&host); -+ strcpy(machine_out, host.machine); -+} -+ -+char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1]; -+ -+void setup_hostinfo(void) -+{ -+ struct utsname host; -+ -+ uname(&host); -+ sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename, -+ host.release, host.version, host.machine); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/link.ld.in um/arch/um/link.ld.in ---- orig/arch/um/link.ld.in Wed Dec 31 19:00:00 1969 -+++ um/arch/um/link.ld.in Fri Jan 17 23:11:30 2003 -@@ -0,0 +1,95 @@ -+OUTPUT_FORMAT("ELF_FORMAT") -+OUTPUT_ARCH(ELF_ARCH) -+ENTRY(_start) -+ -+SECTIONS -+{ -+ . = START() + SIZEOF_HEADERS; -+ -+ . = ALIGN(4096); -+ __binary_start = .; -+ifdef(`MODE_TT', ` -+ .thread_private : { -+ __start_thread_private = .; -+ errno = .; -+ . += 4; -+ arch/um/kernel/tt/unmap_fin.o (.data) -+ __end_thread_private = .; -+ } -+ . = ALIGN(4096); -+ .remap : { arch/um/kernel/tt/unmap_fin.o (.text) } -+') -+ . = ALIGN(4096); /* Init code and data */ -+ _stext = .; -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ . = ALIGN(4096); -+ .text : -+ { -+ *(.text) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ *(.gnu.linkonce.t*) -+ } -+ .fini : { *(.fini) } =0x9090 -+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) } -+ .rodata1 : { *(.rodata1) } -+ _etext = .; -+ PROVIDE (etext = .); -+ -+ . = ALIGN(4096); -+ PROVIDE (_sdata = .); -+ -+include(`arch/um/common.ld.in') -+ -+ .data : -+ { -+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ -+ *(.data.init_task) -+ *(.data) -+ *(.gnu.linkonce.d*) -+ CONSTRUCTORS -+ } -+ .data1 : { *(.data1) } -+ .ctors : -+ { -+ *(.ctors) -+ } -+ .dtors : -+ { -+ *(.dtors) -+ } -+ -+ .got : { *(.got.plt) *(.got) } -+ .dynamic : { *(.dynamic) } -+ /* We want the small data sections together, so single-instruction offsets -+ can access them all, and initialized data all before uninitialized, so -+ we can shorten the on-disk segment size. */ -+ .sdata : { *(.sdata) } -+ _edata = .; -+ PROVIDE (edata = .); -+ . = ALIGN(0x1000); -+ .sbss : -+ { -+ __bss_start = .; -+ PROVIDE(_bss_start = .); -+ *(.sbss) -+ *(.scommon) -+ } -+ .bss : -+ { -+ *(.dynbss) -+ *(.bss) -+ *(COMMON) -+ } -+ _end = . ; -+ PROVIDE (end = .); -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+} -diff -Naur -X ../exclude-files orig/arch/um/main.c um/arch/um/main.c ---- orig/arch/um/main.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/main.c Fri Jan 17 13:22:40 2003 -@@ -0,0 +1,195 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+#include <signal.h> -+#include <sys/resource.h> -+#include <sys/mman.h> -+#include <sys/user.h> -+#include <asm/page.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "mem_user.h" -+#include "signal_user.h" -+#include "user.h" -+#include "init.h" -+#include "mode.h" -+#include "choose-mode.h" -+#include "uml-config.h" -+ -+/* Set in set_stklim, which is called from main and __wrap_malloc. -+ * __wrap_malloc only calls it if main hasn't started. -+ */ -+unsigned long stacksizelim; -+ -+/* Set in main */ -+char *linux_prog; -+ -+#define PGD_BOUND (4 * 1024 * 1024) -+#define STACKSIZE (8 * 1024 * 1024) -+#define THREAD_NAME_LEN (256) -+ -+static void set_stklim(void) -+{ -+ struct rlimit lim; -+ -+ if(getrlimit(RLIMIT_STACK, &lim) < 0){ -+ perror("getrlimit"); -+ exit(1); -+ } -+ if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ -+ lim.rlim_cur = STACKSIZE; -+ if(setrlimit(RLIMIT_STACK, &lim) < 0){ -+ perror("setrlimit"); -+ exit(1); -+ } -+ } -+ stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); -+} -+ -+static __init void do_uml_initcalls(void) -+{ -+ initcall_t *call; -+ -+ call = &__uml_initcall_start; -+ while (call < &__uml_initcall_end){; -+ (*call)(); -+ call++; -+ } -+} -+ -+static void last_ditch_exit(int sig) -+{ -+ CHOOSE_MODE(kmalloc_ok = 0, (void) 0); -+ signal(SIGINT, SIG_DFL); -+ signal(SIGTERM, SIG_DFL); -+ signal(SIGHUP, SIG_DFL); -+ uml_cleanup(); -+ exit(1); -+} -+ -+extern int uml_exitcode; -+ -+int main(int argc, char **argv, char **envp) -+{ -+ char **new_argv; -+ sigset_t mask; -+ int ret, i; -+ -+ /* Enable all signals except SIGIO - in some environments, we can -+ * enter with some signals blocked -+ */ -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, SIGIO); -+ if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ -+ perror("sigprocmask"); -+ exit(1); -+ } -+ -+#ifdef UML_CONFIG_MODE_TT -+ /* Allocate memory for thread command lines */ -+ if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ -+ -+ char padding[THREAD_NAME_LEN] = { -+ [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' -+ }; -+ -+ new_argv = malloc((argc + 2) * sizeof(char*)); -+ if(!new_argv) { -+ perror("Allocating extended argv"); -+ exit(1); -+ } -+ -+ new_argv[0] = argv[0]; -+ new_argv[1] = padding; -+ -+ for(i = 2; i <= argc; i++) -+ new_argv[i] = argv[i - 1]; -+ new_argv[argc + 1] = NULL; -+ -+ execvp(new_argv[0], new_argv); -+ perror("execing with extended args"); -+ exit(1); -+ } -+#endif -+ -+ linux_prog = argv[0]; -+ -+ set_stklim(); -+ -+ if((new_argv = malloc((argc + 1) * sizeof(char *))) == NULL){ -+ perror("Mallocing argv"); -+ exit(1); -+ } -+ for(i=0;i<argc;i++){ -+ if((new_argv[i] = strdup(argv[i])) == NULL){ -+ perror("Mallocing an arg"); -+ exit(1); -+ } -+ } -+ new_argv[argc] = NULL; -+ -+ set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ -+ do_uml_initcalls(); -+ ret = linux_main(argc, argv); -+ -+ /* Reboot */ -+ if(ret){ -+ printf("\n"); -+ execvp(new_argv[0], new_argv); -+ perror("Failed to exec kernel"); -+ ret = 1; -+ } -+ printf("\n"); -+ return(uml_exitcode); -+} -+ -+#define CAN_KMALLOC() \ -+ (kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1)) -+ -+extern void *__real_malloc(int); -+ -+void *__wrap_malloc(int size) -+{ -+ if(CAN_KMALLOC()) -+ return(um_kmalloc(size)); -+ else -+ return(__real_malloc(size)); -+} -+ -+void *__wrap_calloc(int n, int size) -+{ -+ void *ptr = __wrap_malloc(n * size); -+ -+ if(ptr == NULL) return(NULL); -+ memset(ptr, 0, n * size); -+ return(ptr); -+} -+ -+extern void __real_free(void *); -+ -+void __wrap_free(void *ptr) -+{ -+ if(CAN_KMALLOC()) kfree(ptr); -+ else __real_free(ptr); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/Makefile um/arch/um/os-Linux/Makefile ---- orig/arch/um/os-Linux/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = file.o process.o tty.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(obj-y) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -+ -+archmrproper: -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/Makefile um/arch/um/os-Linux/drivers/Makefile ---- orig/arch/um/os-Linux/drivers/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/drivers/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,31 @@ -+# -+# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := drivers.o -+ -+list-multi := tuntap.o ethertap.o -+ -+ethertap-objs := ethertap_kern.o ethertap_user.o -+tuntap-objs := tuntap_kern.o tuntap_user.o -+ -+obj-y = -+obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o -+obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o -+ -+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y)),$($(f)-objs)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y) $(USER_SINGLE_OBJS)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+ethertap.o : $(ethertap-objs) -+ -+tuntap.o : $(tuntap-objs) -+ -+$(list-multi) : # This doesn't work, but should : '%.o : $(%-objs)' -+ $(LD) $(LD_RFLAG) -r -o $@ $($(patsubst %.o,%,$@)-objs) -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/etap.h um/arch/um/os-Linux/drivers/etap.h ---- orig/arch/um/os-Linux/drivers/etap.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/drivers/etap.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct ethertap_data { -+ char *dev_name; -+ char *gate_addr; -+ int data_fd; -+ int control_fd; -+ void *dev; -+}; -+ -+extern struct net_user_info ethertap_user_info; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/ethertap_kern.c um/arch/um/os-Linux/drivers/ethertap_kern.c ---- orig/arch/um/os-Linux/drivers/ethertap_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/drivers/ethertap_kern.c Sun Dec 15 21:17:37 2002 -@@ -0,0 +1,122 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#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" -+ -+struct ethertap_init { -+ char *dev_name; -+ char *gate_addr; -+}; -+ -+static void etap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct ethertap_data *epri; -+ struct ethertap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ epri = (struct ethertap_data *) pri->user; -+ *epri = ((struct ethertap_data) -+ { .dev_name = init->dev_name, -+ .gate_addr = init->gate_addr, -+ .data_fd = -1, -+ .control_fd = -1, -+ .dev = dev }); -+ -+ printk("ethertap backend - %s", epri->dev_name); -+ if(epri->gate_addr != NULL) -+ printk(", IP = %s", epri->gate_addr); -+ printk("\n"); -+} -+ -+static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ int len; -+ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); -+ if(*skb == NULL) return(-ENOMEM); -+ len = net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); -+ if(len <= 0) return(len); -+ skb_pull(*skb, 2); -+ len -= 2; -+ return(len); -+} -+ -+static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ if(skb_headroom(*skb) < 2){ -+ struct sk_buff *skb2; -+ -+ skb2 = skb_realloc_headroom(*skb, 2); -+ dev_kfree_skb(*skb); -+ if (skb2 == NULL) return(-ENOMEM); -+ *skb = skb2; -+ } -+ skb_push(*skb, 2); -+ return(net_send(fd, (*skb)->data, (*skb)->len)); -+} -+ -+struct net_kern_info ethertap_kern_info = { -+ .init = etap_init, -+ .protocol = eth_protocol, -+ .read = etap_read, -+ .write = etap_write, -+}; -+ -+int ethertap_setup(char *str, char **mac_out, void *data) -+{ -+ struct ethertap_init *init = data; -+ -+ *init = ((struct ethertap_init) -+ { .dev_name = NULL, -+ .gate_addr = NULL }); -+ if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, -+ &init->gate_addr)) -+ return(0); -+ if(init->dev_name == NULL){ -+ printk("ethertap_setup : Missing tap device name\n"); -+ return(0); -+ } -+ -+ return(1); -+} -+ -+static struct transport ethertap_transport = { -+ .list = LIST_HEAD_INIT(ethertap_transport.list), -+ .name = "ethertap", -+ .setup = ethertap_setup, -+ .user = ðertap_user_info, -+ .kern = ðertap_kern_info, -+ .private_size = sizeof(struct ethertap_data), -+}; -+ -+static int register_ethertap(void) -+{ -+ register_transport(ðertap_transport); -+ return(1); -+} -+ -+__initcall(register_ethertap); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/ethertap_user.c um/arch/um/os-Linux/drivers/ethertap_user.c ---- orig/arch/um/os-Linux/drivers/ethertap_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/drivers/ethertap_user.c Sun Dec 15 21:17:52 2002 -@@ -0,0 +1,238 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stddef.h> -+#include <fcntl.h> -+#include <stdlib.h> -+#include <sys/errno.h> -+#include <sys/socket.h> -+#include <sys/wait.h> -+#include <sys/un.h> -+#include <net/if.h> -+#include "user.h" -+#include "kern_util.h" -+#include "net_user.h" -+#include "etap.h" -+#include "helper.h" -+#include "os.h" -+ -+#define MAX_PACKET ETH_MAX_PACKET -+ -+void etap_user_init(void *data, void *dev) -+{ -+ struct ethertap_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+struct addr_change { -+ enum { ADD_ADDR, DEL_ADDR } what; -+ unsigned char addr[4]; -+ unsigned char netmask[4]; -+}; -+ -+static void etap_change(int op, unsigned char *addr, unsigned char *netmask, -+ int fd) -+{ -+ struct addr_change change; -+ void *output; -+ -+ 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); -+ output = um_kmalloc(page_size()); -+ if(output == NULL) -+ printk("etap_change : Failed to allocate output buffer\n"); -+ read_output(fd, output, page_size()); -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+} -+ -+static void etap_open_addr(unsigned char *addr, unsigned char *netmask, -+ void *arg) -+{ -+ etap_change(ADD_ADDR, addr, netmask, *((int *) arg)); -+} -+ -+static void etap_close_addr(unsigned char *addr, unsigned char *netmask, -+ void *arg) -+{ -+ etap_change(DEL_ADDR, addr, netmask, *((int *) arg)); -+} -+ -+struct etap_pre_exec_data { -+ int control_remote; -+ int control_me; -+ int data_me; -+}; -+ -+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); -+} -+ -+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; -+ char version_buf[sizeof("nnnnn\0")]; -+ char data_fd_buf[sizeof("nnnnnn\0")]; -+ char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; -+ char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, -+ data_fd_buf, gate_buf, NULL }; -+ char *nosetup_args[] = { "uml_net", version_buf, "ethertap", -+ dev, data_fd_buf, NULL }; -+ char **args, c; -+ -+ sprintf(data_fd_buf, "%d", data_remote); -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ if(gate != NULL){ -+ strcpy(gate_buf, gate); -+ args = setup_args; -+ } -+ else args = nosetup_args; -+ -+ err = 0; -+ pe_data.control_remote = control_remote; -+ pe_data.control_me = control_me; -+ 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(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)){ -+ printk("uml_net didn't exit with status 1\n"); -+ } -+ } -+ return(err); -+} -+ -+static int etap_open(void *data) -+{ -+ struct ethertap_data *pri = data; -+ char *output; -+ int data_fds[2], control_fds[2], err, output_len; -+ -+ err = tap_open_common(pri->dev, pri->gate_addr); -+ if(err) return(err); -+ -+ err = os_pipe(data_fds, 0, 0); -+ if(err){ -+ printk("data os_pipe failed - errno = %d\n", -err); -+ return(err); -+ } -+ -+ err = os_pipe(control_fds, 1, 0); -+ if(err){ -+ printk("control os_pipe failed - errno = %d\n", -err); -+ return(err); -+ } -+ -+ err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], -+ control_fds[1], data_fds[0], data_fds[1]); -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ read_output(control_fds[0], output, output_len); -+ -+ if(output == NULL) -+ printk("etap_open : failed to allocate output buffer\n"); -+ else { -+ printk("%s", output); -+ kfree(output); -+ } -+ -+ if(err != 0){ -+ printk("etap_tramp failed - errno = %d\n", err); -+ return(-err); -+ } -+ -+ pri->data_fd = data_fds[0]; -+ pri->control_fd = control_fds[0]; -+ iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); -+ return(data_fds[0]); -+} -+ -+static void etap_close(int fd, void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); -+ close(fd); -+ os_shutdown_socket(pri->data_fd, 1, 1); -+ close(pri->data_fd); -+ pri->data_fd = -1; -+ close(pri->control_fd); -+ pri->control_fd = -1; -+} -+ -+static int etap_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+static void etap_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ tap_check_ips(pri->gate_addr, addr); -+ if(pri->control_fd == -1) return; -+ etap_open_addr(addr, netmask, &pri->control_fd); -+} -+ -+static void etap_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ if(pri->control_fd == -1) return; -+ etap_close_addr(addr, netmask, &pri->control_fd); -+} -+ -+struct net_user_info ethertap_user_info = { -+ .init = etap_user_init, -+ .open = etap_open, -+ .close = etap_close, -+ .remove = NULL, -+ .set_mtu = etap_set_mtu, -+ .add_address = etap_add_addr, -+ .delete_address = etap_del_addr, -+ .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap.h um/arch/um/os-Linux/drivers/tuntap.h ---- orig/arch/um/os-Linux/drivers/tuntap.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/drivers/tuntap.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_TUNTAP_H -+#define __UM_TUNTAP_H -+ -+#include "net_user.h" -+ -+struct tuntap_data { -+ char *dev_name; -+ int fixed_config; -+ char *gate_addr; -+ int fd; -+ void *dev; -+}; -+ -+extern struct net_user_info tuntap_user_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 -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap_kern.c um/arch/um/os-Linux/drivers/tuntap_kern.c ---- orig/arch/um/os-Linux/drivers/tuntap_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/drivers/tuntap_kern.c Sun Dec 15 21:18:16 2002 -@@ -0,0 +1,105 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "linux/skbuff.h" -+#include "linux/init.h" -+#include "asm/errno.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "tuntap.h" -+ -+struct tuntap_init { -+ char *dev_name; -+ char *gate_addr; -+}; -+ -+static void tuntap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct tuntap_data *tpri; -+ struct tuntap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ tpri = (struct tuntap_data *) pri->user; -+ *tpri = ((struct tuntap_data) -+ { .dev_name = init->dev_name, -+ .fixed_config = (init->dev_name != NULL), -+ .gate_addr = init->gate_addr, -+ .fd = -1, -+ .dev = dev }); -+ printk("TUN/TAP backend - "); -+ if(tpri->gate_addr != NULL) -+ printk("IP = %s", tpri->gate_addr); -+ printk("\n"); -+} -+ -+static int tuntap_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_read(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int tuntap_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(net_write(fd, (*skb)->data, (*skb)->len)); -+} -+ -+struct net_kern_info tuntap_kern_info = { -+ .init = tuntap_init, -+ .protocol = eth_protocol, -+ .read = tuntap_read, -+ .write = tuntap_write, -+}; -+ -+int tuntap_setup(char *str, char **mac_out, void *data) -+{ -+ struct tuntap_init *init = data; -+ -+ *init = ((struct tuntap_init) -+ { .dev_name = NULL, -+ .gate_addr = NULL }); -+ if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, -+ &init->gate_addr)) -+ return(0); -+ -+ return(1); -+} -+ -+static struct transport tuntap_transport = { -+ .list = LIST_HEAD_INIT(tuntap_transport.list), -+ .name = "tuntap", -+ .setup = tuntap_setup, -+ .user = &tuntap_user_info, -+ .kern = &tuntap_kern_info, -+ .private_size = sizeof(struct tuntap_data), -+ .setup_size = sizeof(struct tuntap_init), -+}; -+ -+static int register_tuntap(void) -+{ -+ register_transport(&tuntap_transport); -+ return(1); -+} -+ -+__initcall(register_tuntap); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap_user.c um/arch/um/os-Linux/drivers/tuntap_user.c ---- orig/arch/um/os-Linux/drivers/tuntap_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/drivers/tuntap_user.c Sun Dec 15 21:18:25 2002 -@@ -0,0 +1,223 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stddef.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <fcntl.h> -+#include <sys/wait.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <sys/uio.h> -+#include <sys/ioctl.h> -+#include <net/if.h> -+#include <linux/if_tun.h> -+#include "net_user.h" -+#include "tuntap.h" -+#include "kern_util.h" -+#include "user.h" -+#include "helper.h" -+#include "os.h" -+ -+#define MAX_PACKET ETH_MAX_PACKET -+ -+void tuntap_user_init(void *data, void *dev) -+{ -+ struct tuntap_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ tap_check_ips(pri->gate_addr, addr); -+ if((pri->fd == -1) || pri->fixed_config) return; -+ open_addr(addr, netmask, pri->dev_name); -+} -+ -+static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ if((pri->fd == -1) || pri->fixed_config) return; -+ close_addr(addr, netmask, pri->dev_name); -+} -+ -+struct tuntap_pre_exec_data { -+ int stdout; -+ int close_me; -+}; -+ -+static void tuntap_pre_exec(void *arg) -+{ -+ struct tuntap_pre_exec_data *data = arg; -+ -+ dup2(data->stdout, 1); -+ close(data->close_me); -+} -+ -+static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, -+ char *buffer, int buffer_len, int *used_out) -+{ -+ struct tuntap_pre_exec_data data; -+ char version_buf[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate, -+ NULL }; -+ char buf[CMSG_SPACE(sizeof(*fd_out))]; -+ struct msghdr msg; -+ struct cmsghdr *cmsg; -+ struct iovec iov; -+ int pid, n; -+ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ -+ data.stdout = remote; -+ data.close_me = me; -+ -+ pid = run_helper(tuntap_pre_exec, &data, argv, NULL); -+ -+ if(pid < 0) return(-pid); -+ -+ close(remote); -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ if(buffer != NULL){ -+ iov = ((struct iovec) { buffer, buffer_len }); -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ } -+ else { -+ msg.msg_iov = NULL; -+ msg.msg_iovlen = 0; -+ } -+ msg.msg_control = buf; -+ msg.msg_controllen = sizeof(buf); -+ msg.msg_flags = 0; -+ n = recvmsg(me, &msg, 0); -+ *used_out = n; -+ if(n < 0){ -+ printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", -+ 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); -+ } -+ if((cmsg->cmsg_level != SOL_SOCKET) || -+ (cmsg->cmsg_type != SCM_RIGHTS)){ -+ printk("tuntap_open_tramp : didn't receive a descriptor\n"); -+ return(EINVAL); -+ } -+ *fd_out = ((int *) CMSG_DATA(cmsg))[0]; -+ return(0); -+} -+ -+static int tuntap_open(void *data) -+{ -+ struct ifreq ifr; -+ struct tuntap_data *pri = data; -+ char *output, *buffer; -+ int err, fds[2], len, used; -+ -+ err = tap_open_common(pri->dev, pri->gate_addr); -+ if(err) 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); -+ } -+ memset(&ifr, 0, sizeof(ifr)); -+ ifr.ifr_flags = IFF_TAP; -+ strncpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name) - 1); -+ if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ -+ printk("TUNSETIFF failed, errno = %d", errno); -+ close(pri->fd); -+ return(-errno); -+ } -+ } -+ else { -+ err = os_pipe(fds, 0, 0); -+ if(err){ -+ printk("tuntap_open : os_pipe failed - errno = %d\n", -+ -err); -+ return(err); -+ } -+ -+ buffer = get_output_buffer(&len); -+ if(buffer != NULL) len--; -+ used = 0; -+ -+ err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], -+ 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); -+ free_output_buffer(buffer); -+ printk("tuntap_open_tramp failed - errno = %d\n", err); -+ return(-err); -+ } -+ close(fds[0]); -+ iter_addresses(pri->dev, open_addr, pri->dev_name); -+ } -+ -+ return(pri->fd); -+} -+ -+static void tuntap_close(int fd, void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ if(!pri->fixed_config) -+ iter_addresses(pri->dev, close_addr, pri->dev_name); -+ close(fd); -+ pri->fd = -1; -+} -+ -+static int tuntap_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info tuntap_user_info = { -+ .init = tuntap_user_init, -+ .open = tuntap_open, -+ .close = tuntap_close, -+ .remove = NULL, -+ .set_mtu = tuntap_set_mtu, -+ .add_address = tuntap_add_addr, -+ .delete_address = tuntap_del_addr, -+ .max_packet = MAX_PACKET -+}; -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/os-Linux/file.c um/arch/um/os-Linux/file.c ---- orig/arch/um/os-Linux/file.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/file.c Tue Feb 4 19:32:10 2003 -@@ -0,0 +1,384 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <errno.h> -+#include <fcntl.h> -+#include <signal.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <sys/ioctl.h> -+#include <sys/mount.h> -+#include <sys/uio.h> -+#include "os.h" -+#include "user.h" -+#include "kern_util.h" -+ -+int os_file_type(char *file) -+{ -+ struct stat64 buf; -+ -+ if(stat64(file, &buf) == -1) -+ 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); -+ else return(OS_TYPE_FILE); -+} -+ -+int os_file_mode(char *file, struct openflags *mode_out) -+{ -+ *mode_out = OPENFLAGS(); -+ -+ if(!access(file, W_OK)) *mode_out = of_write(*mode_out); -+ else if(errno != EACCES) -+ return(-errno); -+ -+ if(!access(file, R_OK)) *mode_out = of_read(*mode_out); -+ else if(errno != EACCES) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_open_file(char *file, struct openflags flags, int mode) -+{ -+ int fd, f = 0; -+ -+ if(flags.r && flags.w) f = O_RDWR; -+ else if(flags.r) f = O_RDONLY; -+ else if(flags.w) f = O_WRONLY; -+ else f = 0; -+ -+ if(flags.s) f |= O_SYNC; -+ if(flags.c) f |= O_CREAT; -+ if(flags.t) f |= O_TRUNC; -+ 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); -+ } -+ } -+ -+ return(fd); -+} -+ -+int os_connect_socket(char *name) -+{ -+ struct sockaddr_un sock; -+ int fd, err; -+ -+ sock.sun_family = AF_UNIX; -+ snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); -+ -+ fd = socket(AF_UNIX, SOCK_STREAM, 0); -+ if(fd < 0) -+ return(fd); -+ -+ err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); -+ if(err) -+ return(err); -+ -+ return(fd); -+} -+ -+void os_close_file(int fd) -+{ -+ close(fd); -+} -+ -+int os_seek_file(int fd, __u64 offset) -+{ -+ __u64 actual; -+ -+ actual = lseek64(fd, offset, SEEK_SET); -+ if(actual != offset) return(-errno); -+ return(0); -+} -+ -+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, &c, sizeof(c))) -+ return(-EFAULT); -+#endif -+ -+ n = read(fd, buf, len); -+ if(n < 0) -+ return(-errno); -+ return(n); -+} -+ -+int os_write_file(int fd, void *buf, int count) -+{ -+ 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 -+ -+ n = write(fd, buf, count); -+ if(n < 0) -+ return(-errno); -+ return(n); -+} -+ -+int os_file_size(char *file, long long *size_out) -+{ -+ struct stat64 buf; -+ -+ if(stat64(file, &buf) == -1){ -+ printk("Couldn't stat \"%s\" : errno = %d\n", file, errno); -+ return(-errno); -+ } -+ if(S_ISBLK(buf.st_mode)){ -+ int fd, blocks; -+ -+ if((fd = open64(file, O_RDONLY)) < 0){ -+ printk("Couldn't open \"%s\", errno = %d\n", file, -+ errno); -+ return(-errno); -+ } -+ if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ -+ printk("Couldn't get the block size of \"%s\", " -+ "errno = %d\n", file, errno); -+ close(fd); -+ return(-errno); -+ } -+ *size_out = ((long long) blocks) * 512; -+ close(fd); -+ return(0); -+ } -+ *size_out = buf.st_size; -+ return(0); -+} -+ -+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) -+ 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); -+ -+ return(0); -+} -+ -+int os_set_fd_async(int fd, int owner) -+{ -+ /* XXX This should do F_GETFL first */ -+ if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ -+ printk("os_set_fd_async : failed to set O_ASYNC and " -+ "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); -+ return(-errno); -+ } -+#ifdef notdef -+ if(fcntl(fd, F_SETFD, 1) < 0){ -+ printk("os_set_fd_async : Setting FD_CLOEXEC failed, " -+ "errno = %d\n", errno); -+ } -+#endif -+ -+ if((fcntl(fd, F_SETSIG, SIGIO) < 0) || -+ (fcntl(fd, F_SETOWN, owner) < 0)){ -+ printk("os_set_fd_async : Failed to fcntl F_SETOWN " -+ "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, -+ owner, errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+int os_set_fd_block(int fd, int blocking) -+{ -+ int flags; -+ -+ flags = fcntl(fd, F_GETFL); -+ -+ if(blocking) flags &= ~O_NONBLOCK; -+ else flags |= O_NONBLOCK; -+ -+ if(fcntl(fd, F_SETFL, flags) < 0){ -+ printk("Failed to change blocking on fd # %d, errno = %d\n", -+ fd, errno); -+ return(-errno); -+ } -+ return(0); -+} -+ -+int os_accept_connection(int fd) -+{ -+ int new; -+ -+ new = accept(fd, NULL, 0); -+ if(new < 0) -+ return(-errno); -+ return(new); -+} -+ -+#ifndef SHUT_RD -+#define SHUT_RD 0 -+#endif -+ -+#ifndef SHUT_WR -+#define SHUT_WR 1 -+#endif -+ -+#ifndef SHUT_RDWR -+#define SHUT_RDWR 2 -+#endif -+ -+int os_shutdown_socket(int fd, int r, int w) -+{ -+ int what, err; -+ -+ if(r && w) what = SHUT_RDWR; -+ else if(r) what = SHUT_RD; -+ else if(w) what = SHUT_WR; -+ else { -+ printk("os_shutdown_socket : neither r or w was set\n"); -+ return(-EINVAL); -+ } -+ err = shutdown(fd, what); -+ if(err) -+ return(-errno); -+ return(0); -+} -+ -+int os_rcv_fd(int fd, int *helper_pid_out) -+{ -+ int new, n; -+ char buf[CMSG_SPACE(sizeof(new))]; -+ struct msghdr msg; -+ struct cmsghdr *cmsg; -+ struct iovec iov; -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ iov = ((struct iovec) { .iov_base = helper_pid_out, -+ .iov_len = sizeof(*helper_pid_out) }); -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ msg.msg_control = buf; -+ msg.msg_controllen = sizeof(buf); -+ msg.msg_flags = 0; -+ -+ n = recvmsg(fd, &msg, 0); -+ if(n < 0) -+ return(-errno); -+ -+ else if(n != sizeof(iov.iov_len)) -+ *helper_pid_out = -1; -+ -+ cmsg = CMSG_FIRSTHDR(&msg); -+ if(cmsg == NULL){ -+ printk("rcv_fd didn't receive anything, error = %d\n", errno); -+ return(-1); -+ } -+ if((cmsg->cmsg_level != SOL_SOCKET) || -+ (cmsg->cmsg_type != SCM_RIGHTS)){ -+ printk("rcv_fd didn't receive a descriptor\n"); -+ return(-1); -+ } -+ -+ new = ((int *) CMSG_DATA(cmsg))[0]; -+ return(new); -+} -+ -+int create_unix_socket(char *file, int len) -+{ -+ struct sockaddr_un addr; -+ int sock, err; -+ -+ sock = socket(PF_UNIX, SOCK_DGRAM, 0); -+ if (sock < 0){ -+ printk("create_unix_socket - socket failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ addr.sun_family = AF_UNIX; -+ -+ /* XXX Be more careful about overflow */ -+ snprintf(addr.sun_path, len, "%s", file); -+ -+ err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); -+ if (err < 0){ -+ printk("create_listening_socket - bind failed, errno = %d\n", -+ 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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/include/file.h um/arch/um/os-Linux/include/file.h ---- orig/arch/um/os-Linux/include/file.h Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/include/file.h Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __OS_FILE_H__ -+#define __OS_FILE_H__ -+ -+#define DEV_NULL "/dev/null" -+ -+#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 -Naur -X ../exclude-files orig/arch/um/os-Linux/process.c um/arch/um/os-Linux/process.c ---- orig/arch/um/os-Linux/process.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/process.c Wed Jan 8 14:19:00 2003 -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdio.h> -+#include <errno.h> -+#include <signal.h> -+#include <sys/mman.h> -+#include <sys/wait.h> -+#include "os.h" -+#include "user.h" -+ -+unsigned long os_process_pc(int pid) -+{ -+ char proc_stat[sizeof("/proc/#####/stat\0")], buf[256]; -+ unsigned long pc; -+ int fd; -+ -+ 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); -+ } -+ 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); -+ } -+ close(fd); -+ pc = -1; -+ 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){ -+ printk("os_process_pc - couldn't find pc in '%s'\n", buf); -+ } -+ return(pc); -+} -+ -+int os_process_parent(int pid) -+{ -+ char stat[sizeof("/proc/nnnnn/stat\0")]; -+ char data[256]; -+ int parent, n, fd; -+ -+ if(pid == -1) return(-1); -+ -+ 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); -+ } -+ -+ n = read(fd, data, sizeof(data)); -+ close(fd); -+ -+ if(n < 0){ -+ printk("Couldn't read '%s', errno = %d\n", stat); -+ return(-1); -+ } -+ -+ parent = -1; -+ /* 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); -+ -+ return(parent); -+} -+ -+void os_stop_process(int pid) -+{ -+ kill(pid, SIGSTOP); -+} -+ -+void os_kill_process(int pid, int reap_child) -+{ -+ kill(pid, SIGKILL); -+ if(reap_child) -+ waitpid(pid, NULL, 0); -+ -+} -+ -+void os_usr1_process(int pid) -+{ -+ kill(pid, SIGUSR1); -+} -+ -+int os_getpid(void) -+{ -+ return(getpid()); -+} -+ -+int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len, -+ int r, int w, int x) -+{ -+ void *loc; -+ int prot; -+ -+ 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); -+ if(loc == MAP_FAILED) -+ return(-errno); -+ return(0); -+} -+ -+int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) -+{ -+ int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0)); -+ -+ if(mprotect(addr, len, prot) < 0) -+ return(-errno); -+ return(0); -+} -+ -+int os_unmap_memory(void *addr, int len) -+{ -+ int err; -+ -+ err = munmap(addr, len); -+ if(err < 0) return(-errno); -+ 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 -Naur -X ../exclude-files orig/arch/um/os-Linux/tty.c um/arch/um/os-Linux/tty.c ---- orig/arch/um/os-Linux/tty.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/os-Linux/tty.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include "os.h" -+#include "user.h" -+#include "kern_util.h" -+ -+struct grantpt_info { -+ int fd; -+ int res; -+ int err; -+}; -+ -+static void grantpt_cb(void *arg) -+{ -+ struct grantpt_info *info = arg; -+ -+ info->res = grantpt(info->fd); -+ info->err = errno; -+} -+ -+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); -+ } -+ -+ info.fd = fd; -+ initial_thread_cb(grantpt_cb, &info); -+ -+ if(info.res < 0){ -+ printk("get_pty : Couldn't grant pty - errno = %d\n", -+ info.err); -+ return(-1); -+ } -+ if(unlockpt(fd) < 0){ -+ printk("get_pty : Couldn't unlock pty - errno = %d\n", errno); -+ return(-1); -+ } -+ return(fd); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/sys-i386/Makefile um/arch/um/sys-i386/Makefile ---- orig/arch/um/sys-i386/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/Makefile Sat Nov 23 23:34:24 2002 -@@ -0,0 +1,46 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o ptrace.o \ -+ ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o -+export-objs = ksyms.o -+ -+USER_OBJS = bugs.o ptrace_user.o sigcontext.o fault.o -+ -+SYMLINKS = semaphore.c extable.c -+ -+semaphore.c-dir = kernel -+extable.c-dir = mm -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+define make_link -+ -rm -f $1 -+ ln -sf $(TOPDIR)/arch/i386/$($1-dir)/$1 $1 -+endef -+ -+$(SYMLINKS): -+ $(call make_link,$@) -+ -+clean: -+ $(MAKE) -C util clean -+ rm -f $(SYMLINKS) -+ -+fastdep: -+ -+dep: -+ -+archmrproper: -+ -+archclean: -+ -+archdep: -+ -+modules: -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/bugs.c um/arch/um/sys-i386/bugs.c ---- orig/arch/um/sys-i386/bugs.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/bugs.c Sun Dec 8 20:38:45 2002 -@@ -0,0 +1,157 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <fcntl.h> -+#include <errno.h> -+#include <string.h> -+#include <sys/signal.h> -+#include "kern_util.h" -+#include "user.h" -+#include "sysdep/ptrace.h" -+#include "task.h" -+ -+#define MAXTOKEN 64 -+ -+/* Set during early boot */ -+int cpu_has_cmov = 1; -+int cpu_has_xmm = 0; -+ -+static char token(int fd, char *buf, int len, char stop) -+{ -+ int n; -+ char *ptr, *end, c; -+ -+ ptr = buf; -+ end = &buf[len]; -+ do { -+ n = read(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); -+ } -+ } while((c != '\n') && (c != stop) && (ptr < end)); -+ -+ if(ptr == end){ -+ printk("Failed to find '%c' in /proc/cpuinfo\n", stop); -+ return(-1); -+ } -+ *(ptr - 1) = '\0'; -+ return(c); -+} -+ -+static int check_cpu_feature(char *feature, int *have_it) -+{ -+ 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); -+ } -+ -+ *have_it = 0; -+ buf[len - 1] = '\0'; -+ while(1){ -+ c = token(fd, buf, len - 1, ':'); -+ if(c <= 0) goto out; -+ else if(c != ':'){ -+ printk("Failed to find ':' in /proc/cpuinfo\n"); -+ goto out; -+ } -+ -+ if(!strncmp(buf, "flags", strlen("flags"))) break; -+ -+ do { -+ n = read(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; -+ } -+ } while(c != '\n'); -+ } -+ -+ c = token(fd, buf, len - 1, ' '); -+ if(c < 0) goto out; -+ else if(c != ' '){ -+ printk("Failed to find ':' in /proc/cpuinfo\n"); -+ goto out; -+ } -+ -+ while(1){ -+ c = token(fd, buf, len - 1, ' '); -+ if(c < 0) goto out; -+ else if(c == '\n') break; -+ -+ if(!strcmp(buf, feature)){ -+ *have_it = 1; -+ goto out; -+ } -+ } -+ out: -+ if(*have_it == 0) printk("No\n"); -+ else if(*have_it == 1) printk("Yes\n"); -+ close(fd); -+ return(1); -+} -+ -+void arch_check_bugs(void) -+{ -+ int have_it; -+ -+ if(access("/proc/cpuinfo", R_OK)){ -+ 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; -+} -+ -+int arch_handle_signal(int sig, union uml_pt_regs *regs) -+{ -+ unsigned long ip; -+ -+ /* This is testing for a cmov (0x0f 0x4x) instruction causing a -+ * SIGILL in init. -+ */ -+ if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0); -+ -+ ip = UPT_IP(regs); -+ if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40)) -+ return(0); -+ -+ if(cpu_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) -+ panic("SIGILL caused by cmov, which this processor claims to " -+ "implement"); -+ else if(cpu_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); -+ 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 -Naur -X ../exclude-files orig/arch/um/sys-i386/checksum.S um/arch/um/sys-i386/checksum.S ---- orig/arch/um/sys-i386/checksum.S Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/checksum.S Thu Oct 31 20:17:50 2002 -@@ -0,0 +1,460 @@ -+/* -+ * INET An implementation of the TCP/IP protocol suite for the LINUX -+ * operating system. INET is implemented using the BSD Socket -+ * interface as the means of communication with the user level. -+ * -+ * IP/TCP/UDP checksumming routines -+ * -+ * Authors: Jorge Cwik, <jorge@laser.satlink.net> -+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no> -+ * Tom May, <ftom@netcom.com> -+ * Pentium Pro/II routines: -+ * Alexander Kjeldaas <astor@guardian.no> -+ * Finn Arne Gangstad <finnag@guardian.no> -+ * Lots of code moved from tcp.c and ip.c; see those files -+ * for more names. -+ * -+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception -+ * handling. -+ * Andi Kleen, add zeroing on error -+ * converted to pure assembler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#include <linux/config.h> -+#include <asm/errno.h> -+ -+/* -+ * computes a partial checksum, e.g. for TCP/UDP fragments -+ */ -+ -+/* -+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) -+ */ -+ -+.text -+.align 4 -+.globl arch_csum_partial -+ -+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM -+ -+ /* -+ * Experiments with Ethernet and SLIP connections show that buff -+ * is aligned on either a 2-byte or 4-byte boundary. We get at -+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned. -+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte -+ * alignment for the unrolled loop. -+ */ -+arch_csum_partial: -+ pushl %esi -+ pushl %ebx -+ movl 20(%esp),%eax # Function arg: unsigned int sum -+ movl 16(%esp),%ecx # Function arg: int len -+ movl 12(%esp),%esi # Function arg: unsigned char *buff -+ testl $2, %esi # Check alignment. -+ jz 2f # Jump if alignment is ok. -+ subl $2, %ecx # Alignment uses up two bytes. -+ jae 1f # Jump if we had at least two bytes. -+ addl $2, %ecx # ecx was < 2. Deal with it. -+ jmp 4f -+1: movw (%esi), %bx -+ addl $2, %esi -+ addw %bx, %ax -+ adcl $0, %eax -+2: -+ movl %ecx, %edx -+ shrl $5, %ecx -+ jz 2f -+ testl %esi, %esi -+1: movl (%esi), %ebx -+ adcl %ebx, %eax -+ movl 4(%esi), %ebx -+ adcl %ebx, %eax -+ movl 8(%esi), %ebx -+ adcl %ebx, %eax -+ movl 12(%esi), %ebx -+ adcl %ebx, %eax -+ movl 16(%esi), %ebx -+ adcl %ebx, %eax -+ movl 20(%esi), %ebx -+ adcl %ebx, %eax -+ movl 24(%esi), %ebx -+ adcl %ebx, %eax -+ movl 28(%esi), %ebx -+ adcl %ebx, %eax -+ lea 32(%esi), %esi -+ dec %ecx -+ jne 1b -+ adcl $0, %eax -+2: movl %edx, %ecx -+ andl $0x1c, %edx -+ je 4f -+ shrl $2, %edx # This clears CF -+3: adcl (%esi), %eax -+ lea 4(%esi), %esi -+ dec %edx -+ jne 3b -+ adcl $0, %eax -+4: andl $3, %ecx -+ jz 7f -+ cmpl $2, %ecx -+ jb 5f -+ movw (%esi),%cx -+ leal 2(%esi),%esi -+ je 6f -+ shll $16,%ecx -+5: movb (%esi),%cl -+6: addl %ecx,%eax -+ adcl $0, %eax -+7: -+ popl %ebx -+ popl %esi -+ ret -+ -+#else -+ -+/* Version for PentiumII/PPro */ -+ -+arch_csum_partial: -+ pushl %esi -+ pushl %ebx -+ movl 20(%esp),%eax # Function arg: unsigned int sum -+ movl 16(%esp),%ecx # Function arg: int len -+ movl 12(%esp),%esi # Function arg: const unsigned char *buf -+ -+ testl $2, %esi -+ jnz 30f -+10: -+ movl %ecx, %edx -+ movl %ecx, %ebx -+ andl $0x7c, %ebx -+ shrl $7, %ecx -+ addl %ebx,%esi -+ shrl $2, %ebx -+ negl %ebx -+ lea 45f(%ebx,%ebx,2), %ebx -+ testl %esi, %esi -+ jmp *%ebx -+ -+ # Handle 2-byte-aligned regions -+20: addw (%esi), %ax -+ lea 2(%esi), %esi -+ adcl $0, %eax -+ jmp 10b -+ -+30: subl $2, %ecx -+ ja 20b -+ je 32f -+ movzbl (%esi),%ebx # csumming 1 byte, 2-aligned -+ addl %ebx, %eax -+ adcl $0, %eax -+ jmp 80f -+32: -+ addw (%esi), %ax # csumming 2 bytes, 2-aligned -+ adcl $0, %eax -+ jmp 80f -+ -+40: -+ addl -128(%esi), %eax -+ adcl -124(%esi), %eax -+ adcl -120(%esi), %eax -+ adcl -116(%esi), %eax -+ adcl -112(%esi), %eax -+ adcl -108(%esi), %eax -+ adcl -104(%esi), %eax -+ adcl -100(%esi), %eax -+ adcl -96(%esi), %eax -+ adcl -92(%esi), %eax -+ adcl -88(%esi), %eax -+ adcl -84(%esi), %eax -+ adcl -80(%esi), %eax -+ adcl -76(%esi), %eax -+ adcl -72(%esi), %eax -+ adcl -68(%esi), %eax -+ adcl -64(%esi), %eax -+ adcl -60(%esi), %eax -+ adcl -56(%esi), %eax -+ adcl -52(%esi), %eax -+ adcl -48(%esi), %eax -+ adcl -44(%esi), %eax -+ adcl -40(%esi), %eax -+ adcl -36(%esi), %eax -+ adcl -32(%esi), %eax -+ adcl -28(%esi), %eax -+ adcl -24(%esi), %eax -+ adcl -20(%esi), %eax -+ adcl -16(%esi), %eax -+ adcl -12(%esi), %eax -+ adcl -8(%esi), %eax -+ adcl -4(%esi), %eax -+45: -+ lea 128(%esi), %esi -+ adcl $0, %eax -+ dec %ecx -+ jge 40b -+ movl %edx, %ecx -+50: andl $3, %ecx -+ jz 80f -+ -+ # Handle the last 1-3 bytes without jumping -+ notl %ecx # 1->2, 2->1, 3->0, higher bits are masked -+ movl $0xffffff,%ebx # by the shll and shrl instructions -+ shll $3,%ecx -+ shrl %cl,%ebx -+ andl -128(%esi),%ebx # esi is 4-aligned so should be ok -+ addl %ebx,%eax -+ adcl $0,%eax -+80: -+ popl %ebx -+ popl %esi -+ ret -+ -+#endif -+ -+/* -+unsigned int csum_partial_copy_generic (const char *src, char *dst, -+ int len, int sum, int *src_err_ptr, int *dst_err_ptr) -+ */ -+ -+/* -+ * Copy from ds while checksumming, otherwise like csum_partial -+ * -+ * The macros SRC and DST specify the type of access for the instruction. -+ * thus we can call a custom exception handler for all access types. -+ * -+ * FIXME: could someone double-check whether I haven't mixed up some SRC and -+ * DST definitions? It's damn hard to trigger all cases. I hope I got -+ * them all but there's no guarantee. -+ */ -+ -+#define SRC(y...) \ -+ 9999: y; \ -+ .section __ex_table, "a"; \ -+ .long 9999b, 6001f ; \ -+ .previous -+ -+#define DST(y...) \ -+ 9999: y; \ -+ .section __ex_table, "a"; \ -+ .long 9999b, 6002f ; \ -+ .previous -+ -+.align 4 -+.globl csum_partial_copy_generic_i386 -+ -+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM -+ -+#define ARGBASE 16 -+#define FP 12 -+ -+csum_partial_copy_generic_i386: -+ subl $4,%esp -+ pushl %edi -+ pushl %esi -+ pushl %ebx -+ movl ARGBASE+16(%esp),%eax # sum -+ movl ARGBASE+12(%esp),%ecx # len -+ movl ARGBASE+4(%esp),%esi # src -+ movl ARGBASE+8(%esp),%edi # dst -+ -+ testl $2, %edi # Check alignment. -+ jz 2f # Jump if alignment is ok. -+ subl $2, %ecx # Alignment uses up two bytes. -+ jae 1f # Jump if we had at least two bytes. -+ addl $2, %ecx # ecx was < 2. Deal with it. -+ jmp 4f -+SRC(1: movw (%esi), %bx ) -+ addl $2, %esi -+DST( movw %bx, (%edi) ) -+ addl $2, %edi -+ addw %bx, %ax -+ adcl $0, %eax -+2: -+ movl %ecx, FP(%esp) -+ shrl $5, %ecx -+ jz 2f -+ testl %esi, %esi -+SRC(1: movl (%esi), %ebx ) -+SRC( movl 4(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, (%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 4(%edi) ) -+ -+SRC( movl 8(%esi), %ebx ) -+SRC( movl 12(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 8(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 12(%edi) ) -+ -+SRC( movl 16(%esi), %ebx ) -+SRC( movl 20(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 16(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 20(%edi) ) -+ -+SRC( movl 24(%esi), %ebx ) -+SRC( movl 28(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 24(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 28(%edi) ) -+ -+ lea 32(%esi), %esi -+ lea 32(%edi), %edi -+ dec %ecx -+ jne 1b -+ adcl $0, %eax -+2: movl FP(%esp), %edx -+ movl %edx, %ecx -+ andl $0x1c, %edx -+ je 4f -+ shrl $2, %edx # This clears CF -+SRC(3: movl (%esi), %ebx ) -+ adcl %ebx, %eax -+DST( movl %ebx, (%edi) ) -+ lea 4(%esi), %esi -+ lea 4(%edi), %edi -+ dec %edx -+ jne 3b -+ adcl $0, %eax -+4: andl $3, %ecx -+ jz 7f -+ cmpl $2, %ecx -+ jb 5f -+SRC( movw (%esi), %cx ) -+ leal 2(%esi), %esi -+DST( movw %cx, (%edi) ) -+ leal 2(%edi), %edi -+ je 6f -+ shll $16,%ecx -+SRC(5: movb (%esi), %cl ) -+DST( movb %cl, (%edi) ) -+6: addl %ecx, %eax -+ adcl $0, %eax -+7: -+5000: -+ -+# Exception handler: -+.section .fixup, "ax" -+ -+6001: -+ movl ARGBASE+20(%esp), %ebx # src_err_ptr -+ movl $-EFAULT, (%ebx) -+ -+ # zero the complete destination - computing the rest -+ # is too much work -+ movl ARGBASE+8(%esp), %edi # dst -+ movl ARGBASE+12(%esp), %ecx # len -+ xorl %eax,%eax -+ rep ; stosb -+ -+ jmp 5000b -+ -+6002: -+ movl ARGBASE+24(%esp), %ebx # dst_err_ptr -+ movl $-EFAULT,(%ebx) -+ jmp 5000b -+ -+.previous -+ -+ popl %ebx -+ popl %esi -+ popl %edi -+ popl %ecx # equivalent to addl $4,%esp -+ ret -+ -+#else -+ -+/* Version for PentiumII/PPro */ -+ -+#define ROUND1(x) \ -+ SRC(movl x(%esi), %ebx ) ; \ -+ addl %ebx, %eax ; \ -+ DST(movl %ebx, x(%edi) ) ; -+ -+#define ROUND(x) \ -+ SRC(movl x(%esi), %ebx ) ; \ -+ adcl %ebx, %eax ; \ -+ DST(movl %ebx, x(%edi) ) ; -+ -+#define ARGBASE 12 -+ -+csum_partial_copy_generic_i386: -+ pushl %ebx -+ pushl %edi -+ pushl %esi -+ movl ARGBASE+4(%esp),%esi #src -+ movl ARGBASE+8(%esp),%edi #dst -+ movl ARGBASE+12(%esp),%ecx #len -+ movl ARGBASE+16(%esp),%eax #sum -+# movl %ecx, %edx -+ movl %ecx, %ebx -+ movl %esi, %edx -+ shrl $6, %ecx -+ andl $0x3c, %ebx -+ negl %ebx -+ subl %ebx, %esi -+ subl %ebx, %edi -+ lea -1(%esi),%edx -+ andl $-32,%edx -+ lea 3f(%ebx,%ebx), %ebx -+ testl %esi, %esi -+ jmp *%ebx -+1: addl $64,%esi -+ addl $64,%edi -+ SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl) -+ ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52) -+ ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36) -+ ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20) -+ ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4) -+3: adcl $0,%eax -+ addl $64, %edx -+ dec %ecx -+ jge 1b -+4: movl ARGBASE+12(%esp),%edx #len -+ andl $3, %edx -+ jz 7f -+ cmpl $2, %edx -+ jb 5f -+SRC( movw (%esi), %dx ) -+ leal 2(%esi), %esi -+DST( movw %dx, (%edi) ) -+ leal 2(%edi), %edi -+ je 6f -+ shll $16,%edx -+5: -+SRC( movb (%esi), %dl ) -+DST( movb %dl, (%edi) ) -+6: addl %edx, %eax -+ adcl $0, %eax -+7: -+.section .fixup, "ax" -+6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr -+ movl $-EFAULT, (%ebx) -+ # zero the complete destination (computing the rest is too much work) -+ movl ARGBASE+8(%esp),%edi # dst -+ movl ARGBASE+12(%esp),%ecx # len -+ xorl %eax,%eax -+ rep; stosb -+ jmp 7b -+6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr -+ movl $-EFAULT, (%ebx) -+ jmp 7b -+.previous -+ -+ popl %esi -+ popl %edi -+ popl %ebx -+ ret -+ -+#undef ROUND -+#undef ROUND1 -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/fault.c um/arch/um/sys-i386/fault.c ---- orig/arch/um/sys-i386/fault.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/fault.c Sun Oct 27 16:49:35 2002 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+ -+extern unsigned long search_exception_table(unsigned long addr); -+ -+int arch_fixup(unsigned long address, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ unsigned long fixup; -+ -+ fixup = search_exception_table(address); -+ if(fixup != 0){ -+ sc->eip = fixup; -+ return(1); -+ } -+ 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 -Naur -X ../exclude-files orig/arch/um/sys-i386/ksyms.c um/arch/um/sys-i386/ksyms.c ---- orig/arch/um/sys-i386/ksyms.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/ksyms.c Tue Oct 29 21:01:45 2002 -@@ -0,0 +1,17 @@ -+#include "linux/module.h" -+#include "linux/in6.h" -+#include "linux/rwsem.h" -+#include "asm/byteorder.h" -+#include "asm/semaphore.h" -+#include "asm/uaccess.h" -+#include "asm/checksum.h" -+#include "asm/errno.h" -+ -+EXPORT_SYMBOL(__down_failed); -+EXPORT_SYMBOL(__down_failed_interruptible); -+EXPORT_SYMBOL(__down_failed_trylock); -+EXPORT_SYMBOL(__up_wakeup); -+ -+/* Networking helper routines. */ -+EXPORT_SYMBOL(csum_partial_copy_from); -+EXPORT_SYMBOL(csum_partial_copy_to); -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ldt.c um/arch/um/sys-i386/ldt.c ---- orig/arch/um/sys-i386/ldt.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/ldt.c Wed Nov 13 12:43:04 2002 -@@ -0,0 +1,92 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/slab.h" -+#include "asm/uaccess.h" -+#include "asm/ptrace.h" -+#include "choose-mode.h" -+#include "kern.h" -+ -+#ifdef CONFIG_MODE_TT -+extern int modify_ldt(int func, void *ptr, unsigned long bytecount); -+ -+int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) -+{ -+ if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT); -+ return(modify_ldt(func, ptr, bytecount)); -+} -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+extern int userspace_pid; -+ -+int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) -+{ -+ struct ptrace_ldt ldt; -+ void *buf; -+ int res, n; -+ -+ buf = kmalloc(bytecount, GFP_KERNEL); -+ if(buf == NULL) -+ return(-ENOMEM); -+ -+ res = 0; -+ -+ switch(func){ -+ case 1: -+ case 0x11: -+ res = copy_from_user(buf, ptr, bytecount); -+ break; -+ } -+ -+ if(res != 0){ -+ res = -EFAULT; -+ goto out; -+ } -+ -+ ldt = ((struct ptrace_ldt) { .func = func, -+ .ptr = buf, -+ .bytecount = bytecount }); -+ res = ptrace(PTRACE_LDT, userspace_pid, 0, (unsigned long) &ldt); -+ if(res < 0) -+ goto out; -+ -+ switch(func){ -+ case 0: -+ case 2: -+ n = res; -+ res = copy_to_user(ptr, buf, n); -+ if(res != 0) -+ res = -EFAULT; -+ else -+ res = n; -+ break; -+ } -+ -+ out: -+ kfree(buf); -+ return(res); -+} -+#endif -+ -+int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) -+{ -+ return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, -+ ptr, bytecount)); -+} -+ -+ -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/sys-i386/ptrace.c um/arch/um/sys-i386/ptrace.c ---- orig/arch/um/sys-i386/ptrace.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/ptrace.c Sun Oct 27 16:49:35 2002 -@@ -0,0 +1,365 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "asm/elf.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "ptrace_user.h" -+#include "sysdep/sigcontext.h" -+#include "sysdep/sc.h" -+ -+void arch_switch(void) -+{ -+ update_debugregs(current->thread.arch.debugregs_seq); -+} -+ -+int is_syscall(unsigned long addr) -+{ -+ unsigned short instr; -+ int n; -+ -+ n = copy_from_user(&instr, (void *) addr, sizeof(instr)); -+ if(n){ -+ printk("is_syscall : failed to read instruction from 0x%lu\n", -+ addr); -+ return(0); -+ } -+ return(instr == 0x80cd); -+} -+ -+/* determines which flags the user has access to. */ -+/* 1 = access 0 = no access */ -+#define FLAG_MASK 0x00044dd5 -+ -+int putreg(struct task_struct *child, int regno, unsigned long value) -+{ -+ regno >>= 2; -+ switch (regno) { -+ case FS: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ PT_REGS_FS(&child->thread.regs) = value; -+ return 0; -+ case GS: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ PT_REGS_GS(&child->thread.regs) = value; -+ return 0; -+ case DS: -+ case ES: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ value &= 0xffff; -+ break; -+ case SS: -+ case CS: -+ if ((value & 3) != 3) -+ return -EIO; -+ value &= 0xffff; -+ break; -+ case EFL: -+ value &= FLAG_MASK; -+ value |= PT_REGS_EFLAGS(&child->thread.regs); -+ break; -+ } -+ PT_REGS_SET(&child->thread.regs, regno, value); -+ return 0; -+} -+ -+unsigned long getreg(struct task_struct *child, int regno) -+{ -+ unsigned long retval = ~0UL; -+ -+ regno >>= 2; -+ switch (regno) { -+ case FS: -+ case GS: -+ case DS: -+ case ES: -+ case SS: -+ case CS: -+ retval = 0xffff; -+ /* fall through */ -+ default: -+ retval &= PT_REG(&child->thread.regs, regno); -+ } -+ return retval; -+} -+ -+struct i387_fxsave_struct { -+ unsigned short cwd; -+ unsigned short swd; -+ unsigned short twd; -+ unsigned short fop; -+ long fip; -+ long fcs; -+ long foo; -+ long fos; -+ long mxcsr; -+ long reserved; -+ long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ -+ long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ -+ long padding[56]; -+}; -+ -+/* -+ * FPU tag word conversions. -+ */ -+ -+static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) -+{ -+ unsigned int tmp; /* to avoid 16 bit prefixes in the code */ -+ -+ /* Transform each pair of bits into 01 (valid) or 00 (empty) */ -+ tmp = ~twd; -+ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ -+ /* and move the valid bits to the lower byte. */ -+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ -+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ -+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ -+ return tmp; -+} -+ -+static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave ) -+{ -+ struct _fpxreg *st = NULL; -+ unsigned long twd = (unsigned long) fxsave->twd; -+ unsigned long tag; -+ unsigned long ret = 0xffff0000; -+ int i; -+ -+#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); -+ -+ for ( i = 0 ; i < 8 ; i++ ) { -+ if ( twd & 0x1 ) { -+ st = (struct _fpxreg *) FPREG_ADDR( fxsave, i ); -+ -+ switch ( st->exponent & 0x7fff ) { -+ case 0x7fff: -+ tag = 2; /* Special */ -+ break; -+ case 0x0000: -+ if ( !st->significand[0] && -+ !st->significand[1] && -+ !st->significand[2] && -+ !st->significand[3] ) { -+ tag = 1; /* Zero */ -+ } else { -+ tag = 2; /* Special */ -+ } -+ break; -+ default: -+ if ( st->significand[3] & 0x8000 ) { -+ tag = 0; /* Valid */ -+ } else { -+ tag = 2; /* Special */ -+ } -+ break; -+ } -+ } else { -+ tag = 3; /* Empty */ -+ } -+ ret |= (tag << (2 * i)); -+ twd = twd >> 1; -+ } -+ return ret; -+} -+ -+/* -+ * FXSR floating point environment conversions. -+ */ -+ -+#ifdef CONFIG_MODE_TT -+static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, -+ struct pt_regs *regs) -+{ -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned long env[7]; -+ struct _fpreg *to; -+ struct _fpxreg *from; -+ int i; -+ -+ env[0] = (unsigned long)fxsave->cwd | 0xffff0000; -+ env[1] = (unsigned long)fxsave->swd | 0xffff0000; -+ env[2] = twd_fxsr_to_i387(fxsave); -+ env[3] = fxsave->fip; -+ env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); -+ env[5] = fxsave->foo; -+ env[6] = fxsave->fos; -+ -+ if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) ) -+ return 1; -+ -+ to = &buf->_st[0]; -+ from = (struct _fpxreg *) &fxsave->st_space[0]; -+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) { -+ if ( __copy_to_user( to, from, sizeof(*to) ) ) -+ return 1; -+ } -+ return 0; -+} -+#endif -+ -+static inline int convert_fxsr_to_user(struct _fpstate *buf, -+ struct pt_regs *regs) -+{ -+ return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); -+} -+ -+#ifdef CONFIG_MODE_TT -+static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, -+ struct _fpstate *buf) -+{ -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned long env[7]; -+ struct _fpxreg *to; -+ struct _fpreg *from; -+ int i; -+ -+ if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) -+ return 1; -+ -+ fxsave->cwd = (unsigned short)(env[0] & 0xffff); -+ fxsave->swd = (unsigned short)(env[1] & 0xffff); -+ fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); -+ fxsave->fip = env[3]; -+ fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16); -+ fxsave->fcs = (env[4] & 0xffff); -+ fxsave->foo = env[5]; -+ fxsave->fos = env[6]; -+ -+ to = (struct _fpxreg *) &fxsave->st_space[0]; -+ from = &buf->_st[0]; -+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) { -+ if ( __copy_from_user( to, from, sizeof(*from) ) ) -+ return 1; -+ } -+ return 0; -+} -+#endif -+ -+static inline int convert_fxsr_from_user(struct pt_regs *regs, -+ struct _fpstate *buf) -+{ -+ return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); -+} -+ -+int get_fpregs(unsigned long buf, struct task_struct *child) -+{ -+ int err; -+ -+ err = convert_fxsr_to_user((struct _fpstate *) buf, -+ &child->thread.regs); -+ if(err) return(-EFAULT); -+ else return(0); -+} -+ -+int set_fpregs(unsigned long buf, struct task_struct *child) -+{ -+ int err; -+ -+ err = convert_fxsr_from_user(&child->thread.regs, -+ (struct _fpstate *) buf); -+ if(err) return(-EFAULT); -+ else return(0); -+} -+ -+#ifdef CONFIG_MODE_TT -+int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) -+{ -+ struct pt_regs *regs = &tsk->thread.regs; -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ int err; -+ -+ err = __copy_to_user((void *) buf, fxsave, -+ sizeof(struct user_fxsr_struct)); -+ if(err) return -EFAULT; -+ else return 0; -+} -+#endif -+ -+int get_fpxregs(unsigned long buf, struct task_struct *tsk) -+{ -+ return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0)); -+} -+ -+#ifdef CONFIG_MODE_TT -+int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) -+{ -+ struct pt_regs *regs = &tsk->thread.regs; -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ int err; -+ -+ err = __copy_from_user(fxsave, (void *) buf, -+ sizeof(struct user_fxsr_struct) ); -+ if(err) return -EFAULT; -+ else return 0; -+} -+#endif -+ -+int set_fpxregs(unsigned long buf, struct task_struct *tsk) -+{ -+ return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0)); -+} -+ -+#ifdef notdef -+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) -+{ -+ fpu->cwd = (((SC_FP_CW(PT_REGS_SC(regs)) & 0xffff) << 16) | -+ (SC_FP_SW(PT_REGS_SC(regs)) & 0xffff)); -+ fpu->swd = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; -+ fpu->twd = SC_FP_IPOFF(PT_REGS_SC(regs)); -+ fpu->fip = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; -+ fpu->fcs = SC_FP_DATAOFF(PT_REGS_SC(regs)); -+ fpu->foo = SC_FP_DATASEL(PT_REGS_SC(regs)); -+ fpu->fos = 0; -+ memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)), -+ sizeof(fpu->st_space)); -+ return(1); -+} -+#endif -+ -+#ifdef CONFIG_MODE_TT -+static inline void copy_fpu_fxsave_tt(struct pt_regs *regs, -+ struct user_i387_struct *buf) -+{ -+ struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned short *to; -+ unsigned short *from; -+ int i; -+ -+ memcpy( buf, fpu, 7 * sizeof(long) ); -+ -+ to = (unsigned short *) &buf->st_space[0]; -+ from = (unsigned short *) &fpu->st_space[0]; -+ for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) { -+ memcpy( to, from, 5 * sizeof(unsigned short) ); -+ } -+} -+#endif -+ -+static inline void copy_fpu_fxsave(struct pt_regs *regs, -+ struct user_i387_struct *buf) -+{ -+ (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0); -+} -+ -+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) -+{ -+ copy_fpu_fxsave(regs, (struct user_i387_struct *) fpu); -+ return(1); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/sys-i386/ptrace_user.c um/arch/um/sys-i386/ptrace_user.c ---- orig/arch/um/sys-i386/ptrace_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/ptrace_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,117 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <errno.h> -+#include <unistd.h> -+#include <linux/stddef.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+#include <asm/user.h> -+#include "kern_util.h" -+#include "sysdep/thread.h" -+#include "user.h" -+#include "os.h" -+ -+int ptrace_getregs(long pid, unsigned long *regs_out) -+{ -+ return(ptrace(PTRACE_GETREGS, pid, 0, regs_out)); -+} -+ -+int ptrace_setregs(long pid, unsigned long *regs) -+{ -+ return(ptrace(PTRACE_SETREGS, pid, 0, regs)); -+} -+ -+int ptrace_getfpregs(long pid, unsigned long *regs) -+{ -+ return(ptrace(PTRACE_GETFPREGS, pid, 0, regs)); -+} -+ -+static void write_debugregs(int pid, unsigned long *regs) -+{ -+ struct user *dummy; -+ int nregs, i; -+ -+ dummy = NULL; -+ 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], -+ regs[i]) < 0) -+ printk("write_debugregs - ptrace failed, " -+ "errno = %d\n", errno); -+ } -+} -+ -+static void read_debugregs(int pid, unsigned long *regs) -+{ -+ struct user *dummy; -+ int nregs, i; -+ -+ dummy = NULL; -+ nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); -+ for(i = 0; i < nregs; i++){ -+ regs[i] = ptrace(PTRACE_PEEKUSR, pid, -+ &dummy->u_debugreg[i], 0); -+ } -+} -+ -+/* Accessed only by the tracing thread */ -+static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 }; -+static int debugregs_seq = 0; -+ -+void arch_enter_kernel(void *task, int pid) -+{ -+ read_debugregs(pid, TASK_DEBUGREGS(task)); -+ write_debugregs(pid, kernel_debugregs); -+} -+ -+void arch_leave_kernel(void *task, int pid) -+{ -+ read_debugregs(pid, kernel_debugregs); -+ write_debugregs(pid, TASK_DEBUGREGS(task)); -+} -+ -+void ptrace_pokeuser(unsigned long addr, unsigned long data) -+{ -+ if((addr < offsetof(struct user, u_debugreg[0])) || -+ (addr > offsetof(struct user, u_debugreg[7]))) -+ return; -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ if(kernel_debugregs[addr] == data) return; -+ -+ kernel_debugregs[addr] = data; -+ debugregs_seq++; -+} -+ -+static void update_debugregs_cb(void *arg) -+{ -+ int pid = *((int *) arg); -+ -+ write_debugregs(pid, kernel_debugregs); -+} -+ -+void update_debugregs(int seq) -+{ -+ int me; -+ -+ if(seq == debugregs_seq) return; -+ -+ me = os_getpid(); -+ initial_thread_cb(update_debugregs_cb, &me); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/sys-i386/sigcontext.c um/arch/um/sys-i386/sigcontext.c ---- orig/arch/um/sys-i386/sigcontext.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/sigcontext.c Mon Dec 2 23:20:13 2002 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stddef.h> -+#include <string.h> -+#include <asm/ptrace.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "kern_util.h" -+#include "frame_user.h" -+ -+int sc_size(void *data) -+{ -+ struct arch_frame_data *arch = data; -+ -+ return(sizeof(struct sigcontext) + arch->fpstate_size); -+} -+ -+void sc_to_sc(void *to_ptr, void *from_ptr) -+{ -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ int size = sizeof(*to) + signal_frame_sc.common.arch.fpstate_size; -+ -+ memcpy(to, from, size); -+ if(from->fpstate != NULL) to->fpstate = (struct _fpstate *) (to + 1); -+} -+ -+unsigned long *sc_sigmask(void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ -+ return(&sc->oldmask); -+} -+ -+int sc_get_fpregs(unsigned long buf, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct _fpstate *from = sc->fpstate, *to = (struct _fpstate *) buf; -+ int err = 0; -+ -+ if(from == NULL){ -+ err |= clear_user_proc(&to->cw, sizeof(to->cw)); -+ err |= clear_user_proc(&to->sw, sizeof(to->sw)); -+ err |= clear_user_proc(&to->tag, sizeof(to->tag)); -+ err |= clear_user_proc(&to->ipoff, sizeof(to->ipoff)); -+ err |= clear_user_proc(&to->cssel, sizeof(to->cssel)); -+ err |= clear_user_proc(&to->dataoff, sizeof(to->dataoff)); -+ err |= clear_user_proc(&to->datasel, sizeof(to->datasel)); -+ err |= clear_user_proc(&to->_st, sizeof(to->_st)); -+ } -+ else { -+ err |= copy_to_user_proc(&to->cw, &from->cw, sizeof(to->cw)); -+ err |= copy_to_user_proc(&to->sw, &from->sw, sizeof(to->sw)); -+ err |= copy_to_user_proc(&to->tag, &from->tag, -+ sizeof(to->tag)); -+ err |= copy_to_user_proc(&to->ipoff, &from->ipoff, -+ sizeof(to->ipoff)); -+ err |= copy_to_user_proc(&to->cssel,& from->cssel, -+ sizeof(to->cssel)); -+ err |= copy_to_user_proc(&to->dataoff, &from->dataoff, -+ sizeof(to->dataoff)); -+ err |= copy_to_user_proc(&to->datasel, &from->datasel, -+ sizeof(to->datasel)); -+ err |= copy_to_user_proc(to->_st, from->_st, sizeof(to->_st)); -+ } -+ 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 -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/syscalls.c um/arch/um/sys-i386/syscalls.c ---- orig/arch/um/sys-i386/syscalls.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/syscalls.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "asm/mman.h" -+#include "asm/uaccess.h" -+#include "asm/unistd.h" -+ -+/* -+ * Perform the select(nd, in, out, ex, tv) and mmap() system -+ * calls. Linux/i386 didn't use to be able to handle more than -+ * 4 system call parameters, so these system calls used a memory -+ * block for parameter passing.. -+ */ -+ -+struct mmap_arg_struct { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+extern int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset); -+ -+int old_mmap_i386(struct mmap_arg_struct *arg) -+{ -+ struct mmap_arg_struct a; -+ int err = -EFAULT; -+ -+ if (copy_from_user(&a, arg, sizeof(a))) -+ goto out; -+ -+ err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); -+ out: -+ return err; -+} -+ -+struct sel_arg_struct { -+ unsigned long n; -+ fd_set *inp, *outp, *exp; -+ struct timeval *tvp; -+}; -+ -+int old_select(struct sel_arg_struct *arg) -+{ -+ struct sel_arg_struct a; -+ -+ if (copy_from_user(&a, arg, sizeof(a))) -+ return -EFAULT; -+ /* sys_select() does the appropriate kernel locking */ -+ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/sys-i386/sysrq.c um/arch/um/sys-i386/sysrq.c ---- orig/arch/um/sys-i386/sysrq.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/sysrq.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,30 @@ -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "linux/sched.h" -+#include "asm/ptrace.h" -+#include "sysrq.h" -+ -+void show_regs(struct pt_regs *regs) -+{ -+ printk("\n"); -+ printk("EIP: %04lx:[<%08lx>] CPU: %d %s", -+ 0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs), -+ smp_processor_id(), print_tainted()); -+ if (PT_REGS_CS(regs) & 3) -+ printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs), -+ PT_REGS_SP(regs)); -+ printk(" EFLAGS: %08lx\n %s\n", PT_REGS_EFLAGS(regs), -+ print_tainted()); -+ printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", -+ PT_REGS_EAX(regs), PT_REGS_EBX(regs), -+ PT_REGS_ECX(regs), -+ PT_REGS_EDX(regs)); -+ printk("ESI: %08lx EDI: %08lx EBP: %08lx", -+ PT_REGS_ESI(regs), PT_REGS_EDI(regs), -+ PT_REGS_EBP(regs)); -+ printk(" DS: %04lx ES: %04lx\n", -+ 0xffff & PT_REGS_DS(regs), -+ 0xffff & PT_REGS_ES(regs)); -+ -+ show_trace((unsigned long *) ®s); -+} -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/Makefile um/arch/um/sys-i386/util/Makefile ---- orig/arch/um/sys-i386/util/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/util/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,28 @@ -+EXE = mk_sc mk_thread -+ -+include $(TOPDIR)/Rules.make -+ -+all : $(EXE) -+ -+mk_sc : mk_sc.o -+ $(CC) -o mk_sc mk_sc.o -+ -+mk_sc.o : mk_sc.c -+ $(CC) -c $< -+ -+mk_thread : mk_thread_user.o mk_thread_kern.o -+ $(CC) -o mk_thread mk_thread_user.o mk_thread_kern.o -+ -+mk_thread_user.o : mk_thread_user.c -+ $(CC) -c $< -+ -+mk_thread_kern.o : mk_thread_kern.c -+ $(CC) $(CFLAGS) -c $< -+ -+clean : -+ $(RM) $(EXE) *.o -+ -+archmrproper : clean -+ -+fastdep : -+ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_sc.c um/arch/um/sys-i386/util/mk_sc.c ---- orig/arch/um/sys-i386/util/mk_sc.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/util/mk_sc.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,51 @@ -+#include <stdio.h> -+#include <signal.h> -+#include <linux/stddef.h> -+ -+#define SC_OFFSET(name, field) \ -+ printf("#define " name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\ -+ offsetof(struct sigcontext, field)) -+ -+#define SC_FP_OFFSET(name, field) \ -+ printf("#define " name \ -+ "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ -+ offsetof(struct _fpstate, field)) -+ -+#define SC_FP_OFFSET_PTR(name, field, type) \ -+ printf("#define " name \ -+ "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ -+ offsetof(struct _fpstate, field)) -+ -+int main(int argc, char **argv) -+{ -+ SC_OFFSET("SC_IP", eip); -+ SC_OFFSET("SC_SP", esp); -+ SC_OFFSET("SC_FS", fs); -+ SC_OFFSET("SC_GS", gs); -+ SC_OFFSET("SC_DS", ds); -+ SC_OFFSET("SC_ES", es); -+ SC_OFFSET("SC_SS", ss); -+ SC_OFFSET("SC_CS", cs); -+ SC_OFFSET("SC_EFLAGS", eflags); -+ SC_OFFSET("SC_EAX", eax); -+ SC_OFFSET("SC_EBX", ebx); -+ SC_OFFSET("SC_ECX", ecx); -+ SC_OFFSET("SC_EDX", edx); -+ SC_OFFSET("SC_EDI", edi); -+ SC_OFFSET("SC_ESI", esi); -+ SC_OFFSET("SC_EBP", ebp); -+ SC_OFFSET("SC_TRAPNO", trapno); -+ SC_OFFSET("SC_ERR", err); -+ SC_OFFSET("SC_CR2", cr2); -+ SC_OFFSET("SC_FPSTATE", fpstate); -+ SC_FP_OFFSET("SC_FP_CW", cw); -+ SC_FP_OFFSET("SC_FP_SW", sw); -+ SC_FP_OFFSET("SC_FP_TAG", tag); -+ SC_FP_OFFSET("SC_FP_IPOFF", ipoff); -+ SC_FP_OFFSET("SC_FP_CSSEL", cssel); -+ SC_FP_OFFSET("SC_FP_DATAOFF", dataoff); -+ SC_FP_OFFSET("SC_FP_DATASEL", datasel); -+ SC_FP_OFFSET_PTR("SC_FP_ST", _st, "struct _fpstate"); -+ SC_FP_OFFSET_PTR("SC_FXSR_ENV", _fxsr_env, "void"); -+ return(0); -+} -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_thread_kern.c um/arch/um/sys-i386/util/mk_thread_kern.c ---- orig/arch/um/sys-i386/util/mk_thread_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/util/mk_thread_kern.c Mon Dec 9 23:24:38 2002 -@@ -0,0 +1,22 @@ -+#include "linux/config.h" -+#include "linux/stddef.h" -+#include "linux/sched.h" -+ -+extern void print_head(void); -+extern void print_constant_ptr(char *name, int value); -+extern void print_constant(char *name, char *type, int value); -+extern void print_tail(void); -+ -+#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field) -+ -+int main(int argc, char **argv) -+{ -+ print_head(); -+ print_constant_ptr("TASK_DEBUGREGS", THREAD_OFFSET(arch.debugregs)); -+#ifdef CONFIG_MODE_TT -+ print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid)); -+#endif -+ print_tail(); -+ return(0); -+} -+ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_thread_user.c um/arch/um/sys-i386/util/mk_thread_user.c ---- orig/arch/um/sys-i386/util/mk_thread_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-i386/util/mk_thread_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,30 @@ -+#include <stdio.h> -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_thread\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __UM_THREAD_H\n"); -+ printf("#define __UM_THREAD_H\n"); -+ printf("\n"); -+} -+ -+void print_constant_ptr(char *name, int value) -+{ -+ printf("#define %s(task) ((unsigned long *) " -+ "&(((char *) (task))[%d]))\n", name, value); -+} -+ -+void print_constant(char *name, char *type, int value) -+{ -+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, -+ value); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -diff -Naur -X ../exclude-files orig/arch/um/sys-ia64/Makefile um/arch/um/sys-ia64/Makefile ---- orig/arch/um/sys-ia64/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-ia64/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,26 @@ -+OBJ = sys.o -+ -+OBJS = -+ -+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: -+ -+include $(TOPDIR)/Rules.make -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/Makefile um/arch/um/sys-ppc/Makefile ---- orig/arch/um/sys-ppc/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-ppc/Makefile Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,80 @@ -+OBJ = sys.o -+ -+.S.o: -+ $(CC) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o -+ -+OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \ -+ ptrace_user.o sysrq.o -+ -+EXTRA_AFLAGS := -DCONFIG_ALL_PPC -I. -I$(TOPDIR)/arch/ppc/kernel -+ -+all: $(OBJ) -+ -+$(OBJ): $(OBJS) -+ rm -f $@ -+ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ -+ -+ptrace_user.o: ptrace_user.c -+ $(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< -+ -+sigcontext.o: sigcontext.c -+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< -+ -+semaphore.c: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+checksum.S: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/lib/$@ $@ -+ -+mk_defs.c: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+ppc_defs.head: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+ppc_defs.h: mk_defs.c ppc_defs.head \ -+ $(TOPDIR)/include/asm-ppc/mmu.h \ -+ $(TOPDIR)/include/asm-ppc/processor.h \ -+ $(TOPDIR)/include/asm-ppc/pgtable.h \ -+ $(TOPDIR)/include/asm-ppc/ptrace.h -+# $(CC) $(CFLAGS) -S mk_defs.c -+ cp ppc_defs.head ppc_defs.h -+# for bk, this way we can write to the file even if it's not checked out -+ echo '#define THREAD 608' >> ppc_defs.h -+ echo '#define PT_REGS 8' >> ppc_defs.h -+ echo '#define CLONE_VM 256' >> ppc_defs.h -+# chmod u+w ppc_defs.h -+# grep '^#define' mk_defs.s >> ppc_defs.h -+# rm mk_defs.s -+ -+# the asm link is horrible, and breaks the other targets. This is also -+# not going to work with parallel makes. -+ -+checksum.o: checksum.S -+ rm -f asm -+ ln -s $(TOPDIR)/include/asm-ppc asm -+ $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o -+ rm -f asm -+ -+misc.o: misc.S ppc_defs.h -+ rm -f asm -+ ln -s $(TOPDIR)/include/asm-ppc asm -+ $(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: -+ -+include $(TOPDIR)/Rules.make -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/misc.S um/arch/um/sys-ppc/misc.S ---- orig/arch/um/sys-ppc/misc.S Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-ppc/misc.S Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,116 @@ -+/* -+ * This file contains miscellaneous low-level functions. -+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) -+ * -+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) -+ * and Paul Mackerras. -+ * -+ * A couple of functions stolen from arch/ppc/kernel/misc.S for UML -+ * by Chris Emerson. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <asm/processor.h> -+#include "ppc_asm.h" -+ -+#if defined(CONFIG_4xx) || defined(CONFIG_8xx) -+#define CACHE_LINE_SIZE 16 -+#define LG_CACHE_LINE_SIZE 4 -+#define MAX_COPY_PREFETCH 1 -+#elif !defined(CONFIG_PPC64BRIDGE) -+#define CACHE_LINE_SIZE 32 -+#define LG_CACHE_LINE_SIZE 5 -+#define MAX_COPY_PREFETCH 4 -+#else -+#define CACHE_LINE_SIZE 128 -+#define LG_CACHE_LINE_SIZE 7 -+#define MAX_COPY_PREFETCH 1 -+#endif /* CONFIG_4xx || CONFIG_8xx */ -+ -+ .text -+ -+/* -+ * Clear a page using the dcbz instruction, which doesn't cause any -+ * memory traffic (except to write out any cache lines which get -+ * displaced). This only works on cacheable memory. -+ */ -+_GLOBAL(clear_page) -+ li r0,4096/CACHE_LINE_SIZE -+ mtctr r0 -+#ifdef CONFIG_8xx -+ li r4, 0 -+1: stw r4, 0(r3) -+ stw r4, 4(r3) -+ stw r4, 8(r3) -+ stw r4, 12(r3) -+#else -+1: dcbz 0,r3 -+#endif -+ addi r3,r3,CACHE_LINE_SIZE -+ bdnz 1b -+ blr -+ -+/* -+ * Copy a whole page. We use the dcbz instruction on the destination -+ * to reduce memory traffic (it eliminates the unnecessary reads of -+ * the destination into cache). This requires that the destination -+ * is cacheable. -+ */ -+#define COPY_16_BYTES \ -+ lwz r6,4(r4); \ -+ lwz r7,8(r4); \ -+ lwz r8,12(r4); \ -+ lwzu r9,16(r4); \ -+ stw r6,4(r3); \ -+ stw r7,8(r3); \ -+ stw r8,12(r3); \ -+ stwu r9,16(r3) -+ -+_GLOBAL(copy_page) -+ addi r3,r3,-4 -+ addi r4,r4,-4 -+ li r5,4 -+ -+#ifndef CONFIG_8xx -+#if MAX_COPY_PREFETCH > 1 -+ li r0,MAX_COPY_PREFETCH -+ li r11,4 -+ mtctr r0 -+11: dcbt r11,r4 -+ addi r11,r11,CACHE_LINE_SIZE -+ bdnz 11b -+#else /* MAX_COPY_PREFETCH == 1 */ -+ dcbt r5,r4 -+ li r11,CACHE_LINE_SIZE+4 -+#endif /* MAX_COPY_PREFETCH */ -+#endif /* CONFIG_8xx */ -+ -+ li r0,4096/CACHE_LINE_SIZE -+ mtctr r0 -+1: -+#ifndef CONFIG_8xx -+ dcbt r11,r4 -+ dcbz r5,r3 -+#endif -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 32 -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 64 -+ COPY_16_BYTES -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 128 -+ COPY_16_BYTES -+ COPY_16_BYTES -+ COPY_16_BYTES -+ COPY_16_BYTES -+#endif -+#endif -+#endif -+ bdnz 1b -+ blr -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/miscthings.c um/arch/um/sys-ppc/miscthings.c ---- orig/arch/um/sys-ppc/miscthings.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-ppc/miscthings.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,53 @@ -+#include "linux/threads.h" -+#include "linux/stddef.h" // for NULL -+#include "linux/elf.h" // for AT_NULL -+ -+/* The following function nicked from arch/ppc/kernel/process.c and -+ * adapted slightly */ -+/* -+ * XXX ld.so expects the auxiliary table to start on -+ * a 16-byte boundary, so we have to find it and -+ * move it up. :-( -+ */ -+void shove_aux_table(unsigned long sp) -+{ -+ int argc; -+ char *p; -+ unsigned long e; -+ unsigned long aux_start, offset; -+ -+ argc = *(int *)sp; -+ sp += sizeof(int) + (argc + 1) * sizeof(char *); -+ /* skip over the environment pointers */ -+ do { -+ p = *(char **)sp; -+ sp += sizeof(char *); -+ } while (p != NULL); -+ aux_start = sp; -+ /* skip to the end of the auxiliary table */ -+ do { -+ e = *(unsigned long *)sp; -+ sp += 2 * sizeof(unsigned long); -+ } while (e != AT_NULL); -+ offset = ((aux_start + 15) & ~15) - aux_start; -+ if (offset != 0) { -+ do { -+ sp -= sizeof(unsigned long); -+ e = *(unsigned long *)sp; -+ *(unsigned long *)(sp + offset) = e; -+ } while (sp > aux_start); -+ } -+} -+/* END stuff taken from arch/ppc/kernel/process.c */ -+ -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/sys-ppc/ptrace.c um/arch/um/sys-ppc/ptrace.c ---- orig/arch/um/sys-ppc/ptrace.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-ppc/ptrace.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,28 @@ -+#include "linux/sched.h" -+#include "asm/ptrace.h" -+ -+int putreg(struct task_struct *child, unsigned long regno, -+ unsigned long value) -+{ -+ child->thread.process_regs.regs[regno >> 2] = value; -+ return 0; -+} -+ -+unsigned long getreg(struct task_struct *child, unsigned long regno) -+{ -+ unsigned long retval = ~0UL; -+ -+ retval &= child->thread.process_regs.regs[regno >> 2]; -+ return retval; -+} -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/sys-ppc/ptrace_user.c um/arch/um/sys-ppc/ptrace_user.c ---- orig/arch/um/sys-ppc/ptrace_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-ppc/ptrace_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,40 @@ -+#include <sys/ptrace.h> -+#include <errno.h> -+#include <asm/ptrace.h> -+#include "sysdep/ptrace.h" -+ -+int ptrace_getregs(long pid, unsigned long *regs_out) -+{ -+ int i; -+ for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) { -+ errno = 0; -+ regs_out->regs[i] = ptrace(PTRACE_PEEKUSER, pid, i*4, 0); -+ if (errno) { -+ return -errno; -+ } -+ } -+ return 0; -+} -+ -+int ptrace_setregs(long pid, unsigned long *regs_in) -+{ -+ int i; -+ for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) { -+ if (i != 34 /* FIXME: PT_ORIG_R3 */ && i <= PT_MQ) { -+ if (ptrace(PTRACE_POKEUSER, pid, i*4, regs_in->regs[i]) < 0) { -+ return -errno; -+ } -+ } -+ } -+ 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 -Naur -X ../exclude-files orig/arch/um/sys-ppc/sigcontext.c um/arch/um/sys-ppc/sigcontext.c ---- orig/arch/um/sys-ppc/sigcontext.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-ppc/sigcontext.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,15 @@ -+#include "asm/ptrace.h" -+#include "asm/sigcontext.h" -+#include "sysdep/ptrace.h" -+#include "user_util.h" -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/sys-ppc/sysrq.c um/arch/um/sys-ppc/sysrq.c ---- orig/arch/um/sys-ppc/sysrq.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/sys-ppc/sysrq.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "asm/ptrace.h" -+#include "sysrq.h" -+ -+void show_regs(struct pt_regs_subarch *regs) -+{ -+ printk("\n"); -+ printk("show_regs(): insert regs here.\n"); -+#if 0 -+ printk("\n"); -+ printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs, regs->eip, -+ smp_processor_id()); -+ if (regs->xcs & 3) -+ printk(" ESP: %04x:%08lx",0xffff & regs->xss, regs->esp); -+ printk(" EFLAGS: %08lx\n", regs->eflags); -+ printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", -+ regs->eax, regs->ebx, regs->ecx, regs->edx); -+ printk("ESI: %08lx EDI: %08lx EBP: %08lx", -+ regs->esi, regs->edi, regs->ebp); -+ printk(" DS: %04x ES: %04x\n", -+ 0xffff & regs->xds, 0xffff & regs->xes); -+#endif -+ -+ show_trace(®s->gpr[1]); -+} -+ -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/arch/um/util/Makefile um/arch/um/util/Makefile ---- orig/arch/um/util/Makefile Wed Dec 31 19:00:00 1969 -+++ um/arch/um/util/Makefile Wed Oct 23 21:09:14 2002 -@@ -0,0 +1,26 @@ -+ALL = mk_task mk_constants -+ -+all : $(ALL) -+ -+mk_task : mk_task_user.o mk_task_kern.o -+ $(CC) -o mk_task mk_task_user.o mk_task_kern.o -+ -+mk_task_user.o : mk_task_user.c -+ $(CC) -c $< -+ -+mk_task_kern.o : mk_task_kern.c -+ $(CC) $(CFLAGS) -c $< -+ -+mk_constants : mk_constants_user.o mk_constants_kern.o -+ $(CC) -o mk_constants mk_constants_user.o mk_constants_kern.o -+ -+mk_constants_user.o : mk_constants_user.c -+ $(CC) -c $< -+ -+mk_constants_kern.o : mk_constants_kern.c -+ $(CC) $(CFLAGS) -c $< -+ -+clean : -+ $(RM) $(ALL) *.o *~ -+ -+archmrproper : clean -diff -Naur -X ../exclude-files orig/arch/um/util/mk_constants_kern.c um/arch/um/util/mk_constants_kern.c ---- orig/arch/um/util/mk_constants_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/util/mk_constants_kern.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,24 @@ -+#include "linux/kernel.h" -+#include "linux/stringify.h" -+#include "asm/page.h" -+ -+extern void print_head(void); -+extern void print_constant_str(char *name, char *value); -+extern void print_constant_int(char *name, int value); -+extern void print_tail(void); -+ -+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); -+ print_constant_str("UM_KERN_ERR", KERN_ERR); -+ print_constant_str("UM_KERN_WARNING", KERN_WARNING); -+ 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_tail(); -+ return(0); -+} -diff -Naur -X ../exclude-files orig/arch/um/util/mk_constants_user.c um/arch/um/util/mk_constants_user.c ---- orig/arch/um/util/mk_constants_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/util/mk_constants_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,28 @@ -+#include <stdio.h> -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_constants\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __UM_CONSTANTS_H\n"); -+ printf("#define __UM_CONSTANTS_H\n"); -+ printf("\n"); -+} -+ -+void print_constant_str(char *name, char *value) -+{ -+ printf("#define %s \"%s\"\n", name, value); -+} -+ -+void print_constant_int(char *name, int value) -+{ -+ printf("#define %s %d\n", name, value); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -diff -Naur -X ../exclude-files orig/arch/um/util/mk_task_kern.c um/arch/um/util/mk_task_kern.c ---- orig/arch/um/util/mk_task_kern.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/util/mk_task_kern.c Sun Dec 8 21:03:34 2002 -@@ -0,0 +1,17 @@ -+#include "linux/sched.h" -+#include "linux/stddef.h" -+ -+extern void print(char *name, char *type, int offset); -+extern void print_ptr(char *name, char *type, int offset); -+extern void print_head(void); -+extern void print_tail(void); -+ -+int main(int argc, char **argv) -+{ -+ print_head(); -+ print_ptr("TASK_REGS", "union uml_pt_regs", -+ offsetof(struct task_struct, thread.regs)); -+ print("TASK_PID", "int", offsetof(struct task_struct, pid)); -+ print_tail(); -+ return(0); -+} -diff -Naur -X ../exclude-files orig/arch/um/util/mk_task_user.c um/arch/um/util/mk_task_user.c ---- orig/arch/um/util/mk_task_user.c Wed Dec 31 19:00:00 1969 -+++ um/arch/um/util/mk_task_user.c Wed Oct 23 21:08:04 2002 -@@ -0,0 +1,30 @@ -+#include <stdio.h> -+ -+void print(char *name, char *type, int offset) -+{ -+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, -+ offset); -+} -+ -+void print_ptr(char *name, char *type, int offset) -+{ -+ printf("#define %s(task) ((%s *) &(((char *) (task))[%d]))\n", name, type, -+ offset); -+} -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_task\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __TASK_H\n"); -+ printf("#define __TASK_H\n"); -+ printf("\n"); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -diff -Naur -X ../exclude-files orig/drivers/char/Makefile um/drivers/char/Makefile ---- orig/drivers/char/Makefile Thu Feb 27 13:04:15 2003 -+++ um/drivers/char/Makefile Thu Feb 27 13:05:21 2003 -@@ -95,6 +95,12 @@ - endif - endif - -+ifeq ($(ARCH),um) -+ KEYMAP = -+ KEYBD = -+ CONSOLE = -+endif -+ - ifeq ($(ARCH),sh) - KEYMAP = - KEYBD = -diff -Naur -X ../exclude-files orig/drivers/char/tty_io.c um/drivers/char/tty_io.c ---- orig/drivers/char/tty_io.c Thu Feb 27 13:04:15 2003 -+++ um/drivers/char/tty_io.c Thu Feb 27 13:05:21 2003 -@@ -637,6 +637,9 @@ - wake_up_interruptible(&tty->write_wait); - } - -+extern int write_tty_log(int fd, const unsigned char *buf, int len, void *tty, -+ int direction); -+ - static ssize_t tty_read(struct file * file, char * buf, size_t count, - loff_t *ppos) - { -@@ -677,8 +680,13 @@ - else - i = -EIO; - unlock_kernel(); -- if (i > 0) -+ if (i > 0){ - inode->i_atime = CURRENT_TIME; -+#ifdef CONFIG_TTY_LOG -+ if(tty->log_fd >= 0) -+ write_tty_log(tty->log_fd, buf, i, tty, 1); -+#endif -+ } - return i; - } - -@@ -732,6 +740,10 @@ - if (written) { - file->f_dentry->d_inode->i_mtime = CURRENT_TIME; - ret = written; -+#ifdef CONFIG_TTY_LOG -+ if(tty->log_fd >= 0) -+ write_tty_log(tty->log_fd, buf - ret, ret, tty, 0); -+#endif - } - up(&tty->atomic_write); - return ret; -@@ -945,6 +957,9 @@ - goto release_mem_out; - } - } -+#ifdef CONFIG_TTY_LOG -+ tty->log_fd = -1; -+#endif - goto success; - - /* -@@ -1039,6 +1054,8 @@ - free_tty_struct(tty); - } - -+extern int close_tty_log(int fd, void *tty); -+ - /* - * Even releasing the tty structures is a tricky business.. We have - * to be very careful that the structures are all released at the -@@ -1267,6 +1284,10 @@ - run_task_queue(&tq_timer); - flush_scheduled_tasks(); - -+#ifdef CONFIG_TTY_LOG -+ if(tty->log_fd >= 0) close_tty_log(tty->log_fd, tty); -+#endif -+ - /* - * The release_mem function takes care of the details of clearing - * the slots and preserving the termios structure. -@@ -1274,6 +1295,8 @@ - release_mem(tty, idx); - } - -+extern int open_tty_log(void *tty, void *current_tty); -+ - /* - * tty_open and tty_release keep up the tty count that contains the - * number of opens done on a tty. We cannot use the inode-count, as -@@ -1425,6 +1448,11 @@ - nr_warns++; - } - } -+ -+#ifdef CONFIG_TTY_LOG -+ if(tty->log_fd < 0) -+ tty->log_fd = open_tty_log(tty, current->tty); -+#endif - return 0; - } - -diff -Naur -X ../exclude-files orig/drivers/net/setup.c um/drivers/net/setup.c ---- orig/drivers/net/setup.c Sun Sep 15 12:13:19 2002 -+++ um/drivers/net/setup.c Wed Oct 23 21:08:05 2002 -@@ -28,7 +28,6 @@ - extern int lmc_setup(void); - - extern int madgemc_probe(void); --extern int uml_net_probe(void); - - /* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */ - #define __PAD6 "\0\0\0\0\0\0\0\0\0" -@@ -102,9 +101,6 @@ - */ - #ifdef CONFIG_MADGEMC - {madgemc_probe, 0}, --#endif --#ifdef CONFIG_UML_NET -- {uml_net_probe, 0}, - #endif - - {NULL, 0}, -diff -Naur -X ../exclude-files orig/include/asm-i386/hardirq.h um/include/asm-i386/hardirq.h ---- orig/include/asm-i386/hardirq.h Sun Sep 15 12:13:19 2002 -+++ um/include/asm-i386/hardirq.h Tue Mar 25 14:23:19 2003 -@@ -4,6 +4,7 @@ - #include <linux/config.h> - #include <linux/threads.h> - #include <linux/irq.h> -+#include <asm/processor.h> /* for cpu_relax */ - - /* assembly code in softirq.h is sensitive to the offsets of these fields */ - typedef struct { -diff -Naur -X ../exclude-files orig/include/asm-um/a.out.h um/include/asm-um/a.out.h ---- orig/include/asm-um/a.out.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/a.out.h Sun Oct 27 11:54:50 2002 -@@ -0,0 +1,20 @@ -+#ifndef __UM_A_OUT_H -+#define __UM_A_OUT_H -+ -+#include "linux/config.h" -+#include "asm/arch/a.out.h" -+#include "choose-mode.h" -+ -+#undef STACK_TOP -+ -+extern unsigned long stacksizelim; -+ -+extern unsigned long host_task_size; -+ -+#define STACK_ROOM (stacksizelim) -+ -+extern int honeypot; -+#define STACK_TOP \ -+ CHOOSE_MODE((honeypot ? host_task_size : task_size), task_size) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/arch-signal-i386.h um/include/asm-um/arch-signal-i386.h ---- orig/include/asm-um/arch-signal-i386.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/arch-signal-i386.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,24 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_ARCH_SIGNAL_I386_H -+#define __UM_ARCH_SIGNAL_I386_H -+ -+struct arch_signal_context { -+ unsigned long extrasigs[_NSIG_WORDS]; -+}; -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/archparam-i386.h um/include/asm-um/archparam-i386.h ---- orig/include/asm-um/archparam-i386.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/archparam-i386.h Sun Dec 8 20:09:11 2002 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_ARCHPARAM_I386_H -+#define __UM_ARCHPARAM_I386_H -+ -+/********* Bits for asm-um/elf.h ************/ -+ -+#include "user.h" -+ -+#define ELF_PLATFORM "i586" -+ -+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) -+ -+typedef struct user_i387_struct elf_fpregset_t; -+typedef unsigned long elf_greg_t; -+ -+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) -+typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -+ -+#define ELF_DATA ELFDATA2LSB -+#define ELF_ARCH EM_386 -+ -+#define ELF_PLAT_INIT(regs) do { \ -+ PT_REGS_EBX(regs) = 0; \ -+ PT_REGS_ECX(regs) = 0; \ -+ PT_REGS_EDX(regs) = 0; \ -+ PT_REGS_ESI(regs) = 0; \ -+ PT_REGS_EDI(regs) = 0; \ -+ PT_REGS_EBP(regs) = 0; \ -+ PT_REGS_EAX(regs) = 0; \ -+} while(0) -+ -+/* Shamelessly stolen from include/asm-i386/elf.h */ -+ -+#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \ -+ pr_reg[0] = PT_REGS_EBX(regs); \ -+ pr_reg[1] = PT_REGS_ECX(regs); \ -+ pr_reg[2] = PT_REGS_EDX(regs); \ -+ pr_reg[3] = PT_REGS_ESI(regs); \ -+ pr_reg[4] = PT_REGS_EDI(regs); \ -+ pr_reg[5] = PT_REGS_EBP(regs); \ -+ pr_reg[6] = PT_REGS_EAX(regs); \ -+ pr_reg[7] = PT_REGS_DS(regs); \ -+ pr_reg[8] = PT_REGS_ES(regs); \ -+ /* fake once used fs and gs selectors? */ \ -+ pr_reg[9] = PT_REGS_DS(regs); \ -+ pr_reg[10] = PT_REGS_DS(regs); \ -+ pr_reg[11] = PT_REGS_SYSCALL_NR(regs); \ -+ pr_reg[12] = PT_REGS_IP(regs); \ -+ pr_reg[13] = PT_REGS_CS(regs); \ -+ pr_reg[14] = PT_REGS_EFLAGS(regs); \ -+ pr_reg[15] = PT_REGS_SP(regs); \ -+ pr_reg[16] = PT_REGS_SS(regs); \ -+} while(0); -+ -+/********* Bits for asm-um/delay.h **********/ -+ -+typedef unsigned long um_udelay_t; -+ -+/********* Nothing for asm-um/hardirq.h **********/ -+ -+/********* Nothing for asm-um/hw_irq.h **********/ -+ -+/********* Nothing for asm-um/string.h **********/ -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/archparam-ppc.h um/include/asm-um/archparam-ppc.h ---- orig/include/asm-um/archparam-ppc.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/archparam-ppc.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,41 @@ -+#ifndef __UM_ARCHPARAM_PPC_H -+#define __UM_ARCHPARAM_PPC_H -+ -+/********* Bits for asm-um/elf.h ************/ -+ -+#define ELF_PLATFORM (0) -+ -+#define ELF_ET_DYN_BASE (0x08000000) -+ -+/* the following stolen from asm-ppc/elf.h */ -+#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ -+#define ELF_NFPREG 33 /* includes fpscr */ -+/* General registers */ -+typedef unsigned long elf_greg_t; -+typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -+ -+/* Floating point registers */ -+typedef double elf_fpreg_t; -+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; -+ -+#define ELF_DATA ELFDATA2MSB -+#define ELF_ARCH EM_PPC -+ -+/********* Bits for asm-um/delay.h **********/ -+ -+typedef unsigned int um_udelay_t; -+ -+/********* Bits for asm-um/hw_irq.h **********/ -+ -+struct hw_interrupt_type; -+ -+/********* Bits for asm-um/hardirq.h **********/ -+ -+#define irq_enter(cpu, irq) hardirq_enter(cpu) -+#define irq_exit(cpu, irq) hardirq_exit(cpu) -+ -+/********* Bits for asm-um/string.h **********/ -+ -+#define __HAVE_ARCH_STRRCHR -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/atomic.h um/include/asm-um/atomic.h ---- orig/include/asm-um/atomic.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/atomic.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_ATOMIC_H -+#define __UM_ATOMIC_H -+ -+#include "asm/arch/atomic.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/bitops.h um/include/asm-um/bitops.h ---- orig/include/asm-um/bitops.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/bitops.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BITOPS_H -+#define __UM_BITOPS_H -+ -+#include "asm/arch/bitops.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/boot.h um/include/asm-um/boot.h ---- orig/include/asm-um/boot.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/boot.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BOOT_H -+#define __UM_BOOT_H -+ -+#include "asm/arch/boot.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/bugs.h um/include/asm-um/bugs.h ---- orig/include/asm-um/bugs.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/bugs.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BUGS_H -+#define __UM_BUGS_H -+ -+void check_bugs(void); -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/byteorder.h um/include/asm-um/byteorder.h ---- orig/include/asm-um/byteorder.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/byteorder.h Thu Feb 27 13:20:12 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BYTEORDER_H -+#define __UM_BYTEORDER_H -+ -+#include "asm/arch/byteorder.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/cache.h um/include/asm-um/cache.h ---- orig/include/asm-um/cache.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/cache.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_CACHE_H -+#define __UM_CACHE_H -+ -+#define L1_CACHE_BYTES 32 -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/checksum.h um/include/asm-um/checksum.h ---- orig/include/asm-um/checksum.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/checksum.h Tue Oct 29 17:25:12 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_CHECKSUM_H -+#define __UM_CHECKSUM_H -+ -+#include "sysdep/checksum.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/cobalt.h um/include/asm-um/cobalt.h ---- orig/include/asm-um/cobalt.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/cobalt.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_COBALT_H -+#define __UM_COBALT_H -+ -+#include "asm/arch/cobalt.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/current.h um/include/asm-um/current.h ---- orig/include/asm-um/current.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/current.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_CURRENT_H -+#define __UM_CURRENT_H -+ -+#ifndef __ASSEMBLY__ -+ -+#include "linux/config.h" -+#include "asm/page.h" -+ -+struct task_struct; -+ -+#define CURRENT_TASK(dummy) (((unsigned long) &dummy) & \ -+ (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER)) -+ -+#define current ({ int dummy; (struct task_struct *) CURRENT_TASK(dummy); }) -+ -+#endif /* __ASSEMBLY__ */ -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/delay.h um/include/asm-um/delay.h ---- orig/include/asm-um/delay.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/delay.h Sun Dec 8 20:09:15 2002 -@@ -0,0 +1,7 @@ -+#ifndef __UM_DELAY_H -+#define __UM_DELAY_H -+ -+#include "asm/arch/delay.h" -+#include "asm/archparam.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/desc.h um/include/asm-um/desc.h ---- orig/include/asm-um/desc.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/desc.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_DESC_H -+#define __UM_DESC_H -+ -+#include "asm/arch/desc.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/div64.h um/include/asm-um/div64.h ---- orig/include/asm-um/div64.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/div64.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef _UM_DIV64_H -+#define _UM_DIV64_H -+ -+#include "asm/arch/div64.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/dma.h um/include/asm-um/dma.h ---- orig/include/asm-um/dma.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/dma.h Sun Oct 27 16:53:42 2002 -@@ -0,0 +1,10 @@ -+#ifndef __UM_DMA_H -+#define __UM_DMA_H -+ -+#include "asm/io.h" -+ -+extern unsigned long uml_physmem; -+ -+#define MAX_DMA_ADDRESS (uml_physmem) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/elf.h um/include/asm-um/elf.h ---- orig/include/asm-um/elf.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/elf.h Sun Dec 8 20:13:07 2002 -@@ -0,0 +1,18 @@ -+#ifndef __UM_ELF_H -+#define __UM_ELF_H -+ -+#include "asm/archparam.h" -+ -+#define ELF_HWCAP (0) -+ -+#define SET_PERSONALITY(ex, ibcs2) do ; while(0) -+ -+#define ELF_EXEC_PAGESIZE 4096 -+ -+#define elf_check_arch(x) (1) -+ -+#define ELF_CLASS ELFCLASS32 -+ -+#define USE_ELF_CORE_DUMP -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/errno.h um/include/asm-um/errno.h ---- orig/include/asm-um/errno.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/errno.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_ERRNO_H -+#define __UM_ERRNO_H -+ -+#include "asm/arch/errno.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/fcntl.h um/include/asm-um/fcntl.h ---- orig/include/asm-um/fcntl.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/fcntl.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_FCNTL_H -+#define __UM_FCNTL_H -+ -+#include "asm/arch/fcntl.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/fixmap.h um/include/asm-um/fixmap.h ---- orig/include/asm-um/fixmap.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/fixmap.h Mon Mar 24 16:53:25 2003 -@@ -0,0 +1,89 @@ -+#ifndef __UM_FIXMAP_H -+#define __UM_FIXMAP_H -+ -+#include <linux/config.h> -+#include <asm/kmap_types.h> -+ -+/* -+ * Here we define all the compile-time 'special' virtual -+ * addresses. The point is to have a constant address at -+ * compile time, but to set the physical address only -+ * in the boot process. We allocate these special addresses -+ * from the end of virtual memory (0xfffff000) backwards. -+ * Also this lets us do fail-safe vmalloc(), we -+ * can guarantee that these special addresses and -+ * vmalloc()-ed addresses never overlap. -+ * -+ * these 'compile-time allocated' memory buffers are -+ * fixed-size 4k pages. (or larger if used with an increment -+ * highger than 1) use fixmap_set(idx,phys) to associate -+ * physical memory with fixmap indices. -+ * -+ * TLB entries of such buffers will not be flushed across -+ * task switches. -+ */ -+ -+/* -+ * on UP currently we will have no trace of the fixmap mechanizm, -+ * no page table allocations, etc. This might change in the -+ * future, say framebuffers for the console driver(s) could be -+ * fix-mapped? -+ */ -+enum fixed_addresses { -+#ifdef CONFIG_HIGHMEM -+ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ -+ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, -+#endif -+ __end_of_fixed_addresses -+}; -+ -+extern void __set_fixmap (enum fixed_addresses idx, -+ unsigned long phys, pgprot_t flags); -+ -+#define set_fixmap(idx, phys) \ -+ __set_fixmap(idx, phys, PAGE_KERNEL) -+/* -+ * Some hardware wants to get fixmapped without caching. -+ */ -+#define set_fixmap_nocache(idx, phys) \ -+ __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE) -+/* -+ * used by vmalloc.c. -+ * -+ * Leave one empty page between vmalloc'ed areas and -+ * the start of the fixmap, and leave one page empty -+ * at the top of mem.. -+ */ -+extern unsigned long get_kmem_end(void); -+ -+#define FIXADDR_TOP (get_kmem_end() - 0x2000) -+#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) -+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) -+ -+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) -+ -+extern void __this_fixmap_does_not_exist(void); -+ -+/* -+ * 'index to address' translation. If anyone tries to use the idx -+ * directly without tranlation, we catch the bug with a NULL-deference -+ * kernel oops. Illegal ranges of incoming indices are caught too. -+ */ -+static inline unsigned long fix_to_virt(const unsigned int idx) -+{ -+ /* -+ * this branch gets completely eliminated after inlining, -+ * except when someone tries to use fixaddr indices in an -+ * illegal way. (such as mixing up address types or using -+ * out-of-range indices). -+ * -+ * If it doesn't get removed, the linker will complain -+ * loudly with a reasonably clear error message.. -+ */ -+ if (idx >= __end_of_fixed_addresses) -+ __this_fixmap_does_not_exist(); -+ -+ return __fix_to_virt(idx); -+} -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/floppy.h um/include/asm-um/floppy.h ---- orig/include/asm-um/floppy.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/floppy.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_FLOPPY_H -+#define __UM_FLOPPY_H -+ -+#include "asm/arch/floppy.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/hardirq.h um/include/asm-um/hardirq.h ---- orig/include/asm-um/hardirq.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/hardirq.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_HARDIRQ_H -+#define __UM_HARDIRQ_H -+ -+#include "asm/arch/hardirq.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/hdreg.h um/include/asm-um/hdreg.h ---- orig/include/asm-um/hdreg.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/hdreg.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_HDREG_H -+#define __UM_HDREG_H -+ -+#include "asm/arch/hdreg.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/highmem.h um/include/asm-um/highmem.h ---- orig/include/asm-um/highmem.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/highmem.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,12 @@ -+#ifndef __UM_HIGHMEM_H -+#define __UM_HIGHMEM_H -+ -+#include "asm/page.h" -+#include "asm/fixmap.h" -+#include "asm/arch/highmem.h" -+ -+#undef PKMAP_BASE -+ -+#define PKMAP_BASE ((FIXADDR_START - LAST_PKMAP * PAGE_SIZE) & PMD_MASK) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/hw_irq.h um/include/asm-um/hw_irq.h ---- orig/include/asm-um/hw_irq.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/hw_irq.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,10 @@ -+#ifndef _ASM_UM_HW_IRQ_H -+#define _ASM_UM_HW_IRQ_H -+ -+#include "asm/irq.h" -+#include "asm/archparam.h" -+ -+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) -+{} -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ide.h um/include/asm-um/ide.h ---- orig/include/asm-um/ide.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/ide.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IDE_H -+#define __UM_IDE_H -+ -+#include "asm/arch/ide.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/init.h um/include/asm-um/init.h ---- orig/include/asm-um/init.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/init.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,11 @@ -+#ifndef _UM_INIT_H -+#define _UM_INIT_H -+ -+#ifdef notdef -+#define __init -+#define __initdata -+#define __initfunc(__arginit) __arginit -+#define __cacheline_aligned -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/io.h um/include/asm-um/io.h ---- orig/include/asm-um/io.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/io.h Sun Oct 27 16:53:42 2002 -@@ -0,0 +1,25 @@ -+#ifndef __UM_IO_H -+#define __UM_IO_H -+ -+#include "asm/page.h" -+ -+#define IO_SPACE_LIMIT 0xdeadbeef /* Sure hope nothing uses this */ -+ -+static inline int inb(unsigned long i) { return(0); } -+static inline void outb(char c, unsigned long i) { } -+ -+/* -+ * Change virtual addresses to physical addresses and vv. -+ * These are pretty trivial -+ */ -+static inline unsigned long virt_to_phys(volatile void * address) -+{ -+ return __pa((void *) address); -+} -+ -+static inline void * phys_to_virt(unsigned long address) -+{ -+ return __va(address); -+} -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ioctl.h um/include/asm-um/ioctl.h ---- orig/include/asm-um/ioctl.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/ioctl.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IOCTL_H -+#define __UM_IOCTL_H -+ -+#include "asm/arch/ioctl.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ioctls.h um/include/asm-um/ioctls.h ---- orig/include/asm-um/ioctls.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/ioctls.h Wed Oct 23 21:11:14 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IOCTLS_H -+#define __UM_IOCTLS_H -+ -+#include "asm/arch/ioctls.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ipc.h um/include/asm-um/ipc.h ---- orig/include/asm-um/ipc.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/ipc.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IPC_H -+#define __UM_IPC_H -+ -+#include "asm/arch/ipc.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ipcbuf.h um/include/asm-um/ipcbuf.h ---- orig/include/asm-um/ipcbuf.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/ipcbuf.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IPCBUF_H -+#define __UM_IPCBUF_H -+ -+#include "asm/arch/ipcbuf.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/irq.h um/include/asm-um/irq.h ---- orig/include/asm-um/irq.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/irq.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,36 @@ -+#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/arch/irq.h" -+#include "asm/ptrace.h" -+ -+#undef NR_IRQS -+ -+#define TIMER_IRQ 0 -+#define UMN_IRQ 1 -+#define CONSOLE_IRQ 2 -+#define CONSOLE_WRITE_IRQ 3 -+#define UBD_IRQ 4 -+#define UM_ETH_IRQ 5 -+#define SSL_IRQ 6 -+#define SSL_WRITE_IRQ 7 -+#define ACCEPT_IRQ 8 -+#define MCONSOLE_IRQ 9 -+#define WINCH_IRQ 10 -+#define SIGIO_WRITE_IRQ 11 -+#define TELNETD_IRQ 12 -+#define XTERM_IRQ 13 -+ -+#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); -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/keyboard.h um/include/asm-um/keyboard.h ---- orig/include/asm-um/keyboard.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/keyboard.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_KEYBOARD_H -+#define __UM_KEYBOARD_H -+ -+#include "asm/arch/keyboard.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/kmap_types.h um/include/asm-um/kmap_types.h ---- orig/include/asm-um/kmap_types.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/kmap_types.h Thu Feb 27 13:20:14 2003 -@@ -0,0 +1,11 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_KMAP_TYPES_H -+#define __UM_KMAP_TYPES_H -+ -+#include "asm/arch/kmap_types.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/linux_logo.h um/include/asm-um/linux_logo.h ---- orig/include/asm-um/linux_logo.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/linux_logo.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_LINUX_LOGO_H -+#define __UM_LINUX_LOGO_H -+ -+#include "asm/arch/linux_logo.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/locks.h um/include/asm-um/locks.h ---- orig/include/asm-um/locks.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/locks.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_LOCKS_H -+#define __UM_LOCKS_H -+ -+#include "asm/arch/locks.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/mca_dma.h um/include/asm-um/mca_dma.h ---- orig/include/asm-um/mca_dma.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/mca_dma.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef mca___UM_DMA_H -+#define mca___UM_DMA_H -+ -+#include "asm/arch/mca_dma.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/mman.h um/include/asm-um/mman.h ---- orig/include/asm-um/mman.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/mman.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MMAN_H -+#define __UM_MMAN_H -+ -+#include "asm/arch/mman.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/mmu.h um/include/asm-um/mmu.h ---- orig/include/asm-um/mmu.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/mmu.h Sat Nov 9 12:51:11 2002 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MMU_H -+#define __MMU_H -+ -+#include "um_mmu.h" -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/mmu_context.h um/include/asm-um/mmu_context.h ---- orig/include/asm-um/mmu_context.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/mmu_context.h Tue Mar 25 14:23:24 2003 -@@ -0,0 +1,72 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_MMU_CONTEXT_H -+#define __UM_MMU_CONTEXT_H -+ -+#include "linux/sched.h" -+#include "choose-mode.h" -+ -+#define get_mmu_context(task) do ; while(0) -+#define activate_context(tsk) do ; while(0) -+ -+static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) -+{ -+} -+ -+extern void switch_mm_skas(int mm_fd); -+ -+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, -+ struct task_struct *tsk, unsigned cpu) -+{ -+ if(prev != next){ -+ clear_bit(cpu, &prev->cpu_vm_mask); -+ set_bit(cpu, &next->cpu_vm_mask); -+ if(next != &init_mm) -+ CHOOSE_MODE((void) 0, -+ switch_mm_skas(next->context.skas.mm_fd)); -+ } -+} -+ -+static inline void enter_lazy_tlb(struct mm_struct *mm, -+ struct task_struct *tsk, unsigned cpu) -+{ -+} -+ -+extern int init_new_context_skas(struct task_struct *task, -+ struct mm_struct *mm); -+ -+static inline int init_new_context_tt(struct task_struct *task, -+ struct mm_struct *mm) -+{ -+ return(0); -+} -+ -+static inline int init_new_context(struct task_struct *task, -+ struct mm_struct *mm) -+{ -+ return(CHOOSE_MODE_PROC(init_new_context_tt, init_new_context_skas, -+ task, mm)); -+} -+ -+extern void destroy_context_skas(struct mm_struct *mm); -+ -+static inline void destroy_context(struct mm_struct *mm) -+{ -+ CHOOSE_MODE((void) 0, destroy_context_skas(mm)); -+} -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/module.h um/include/asm-um/module.h ---- orig/include/asm-um/module.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/module.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MODULE_H -+#define __UM_MODULE_H -+ -+#include "asm/arch/module.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/msgbuf.h um/include/asm-um/msgbuf.h ---- orig/include/asm-um/msgbuf.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/msgbuf.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MSGBUF_H -+#define __UM_MSGBUF_H -+ -+#include "asm/arch/msgbuf.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/mtrr.h um/include/asm-um/mtrr.h ---- orig/include/asm-um/mtrr.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/mtrr.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MTRR_H -+#define __UM_MTRR_H -+ -+#include "asm/arch/mtrr.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/namei.h um/include/asm-um/namei.h ---- orig/include/asm-um/namei.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/namei.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_NAMEI_H -+#define __UM_NAMEI_H -+ -+#include "asm/arch/namei.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/page.h um/include/asm-um/page.h ---- orig/include/asm-um/page.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/page.h Sun Oct 27 16:49:35 2002 -@@ -0,0 +1,53 @@ -+#ifndef __UM_PAGE_H -+#define __UM_PAGE_H -+ -+struct page; -+ -+#include "asm/arch/page.h" -+ -+#undef BUG -+#undef PAGE_BUG -+#undef __pa -+#undef __va -+#undef virt_to_page -+#undef VALID_PAGE -+#undef PAGE_OFFSET -+#undef KERNELBASE -+ -+extern unsigned long uml_physmem; -+ -+#define PAGE_OFFSET (uml_physmem) -+#define KERNELBASE PAGE_OFFSET -+ -+#ifndef __ASSEMBLY__ -+ -+extern void stop(void); -+ -+#define BUG() do { \ -+ panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ -+} while (0) -+ -+#define PAGE_BUG(page) do { \ -+ BUG(); \ -+} while (0) -+ -+#endif /* __ASSEMBLY__ */ -+ -+#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 struct page *page_mem_map(struct page *page); -+ -+extern struct page *pfn_to_page(unsigned long pfn); -+ -+#define VALID_PAGE(page) (page_mem_map(page) != NULL) -+ -+extern struct page *arch_validate(struct page *page, int mask, int order); -+#define HAVE_ARCH_VALIDATE -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/page_offset.h um/include/asm-um/page_offset.h ---- orig/include/asm-um/page_offset.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/page_offset.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1 @@ -+#define PAGE_OFFSET_RAW (uml_physmem) -diff -Naur -X ../exclude-files orig/include/asm-um/param.h um/include/asm-um/param.h ---- orig/include/asm-um/param.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/param.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,24 @@ -+#ifndef _UM_PARAM_H -+#define _UM_PARAM_H -+ -+#ifndef HZ -+#define HZ 52 -+#endif -+ -+#define EXEC_PAGESIZE 4096 -+ -+#ifndef NGROUPS -+#define NGROUPS 32 -+#endif -+ -+#ifndef NOGROUP -+#define NOGROUP (-1) -+#endif -+ -+#define MAXHOSTNAMELEN 64 /* max length of hostname */ -+ -+#ifdef __KERNEL__ -+# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */ -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/pci.h um/include/asm-um/pci.h ---- orig/include/asm-um/pci.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/pci.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_PCI_H -+#define __UM_PCI_H -+ -+#define PCI_DMA_BUS_IS_PHYS (1) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/pgalloc.h um/include/asm-um/pgalloc.h ---- orig/include/asm-um/pgalloc.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/pgalloc.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,162 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Derived from include/asm-i386/pgalloc.h and include/asm-i386/pgtable.h -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PGALLOC_H -+#define __UM_PGALLOC_H -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "asm/fixmap.h" -+#include "choose-mode.h" -+ -+#define pgd_quicklist (current_cpu_data.pgd_quick) -+#define pmd_quicklist (current_cpu_data.pmd_quick) -+#define pte_quicklist (current_cpu_data.pte_quick) -+#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz) -+ -+#define pmd_populate(mm, pmd, pte) set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) -+ -+/* -+ * Allocate and free page tables. -+ */ -+ -+static inline pgd_t *get_pgd_slow_tt(void) -+{ -+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL); -+ -+ if (pgd) { -+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); -+ memcpy(pgd + USER_PTRS_PER_PGD, -+ swapper_pg_dir + USER_PTRS_PER_PGD, -+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); -+ } -+ return pgd; -+} -+ -+static inline pgd_t *get_pgd_slow_skas(void) -+{ -+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL); -+ -+ if (pgd) -+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); -+ return pgd; -+} -+ -+static inline pgd_t *get_pgd_slow(void) -+{ -+ return(CHOOSE_MODE(get_pgd_slow_tt(), get_pgd_slow_skas())); -+} -+ -+static inline pgd_t *get_pgd_fast(void) -+{ -+ unsigned long *ret; -+ -+ if ((ret = pgd_quicklist) != NULL) { -+ pgd_quicklist = (unsigned long *)(*ret); -+ ret[0] = 0; -+ pgtable_cache_size--; -+ } else -+ ret = (unsigned long *)get_pgd_slow(); -+ return (pgd_t *)ret; -+} -+ -+static inline void free_pgd_fast(pgd_t *pgd) -+{ -+ *(unsigned long *)pgd = (unsigned long) pgd_quicklist; -+ pgd_quicklist = (unsigned long *) pgd; -+ pgtable_cache_size++; -+} -+ -+static inline void free_pgd_slow(pgd_t *pgd) -+{ -+ free_page((unsigned long)pgd); -+} -+ -+static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) -+{ -+ pte_t *pte; -+ -+ pte = (pte_t *) __get_free_page(GFP_KERNEL); -+ if (pte) -+ clear_page(pte); -+ return pte; -+} -+ -+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address) -+{ -+ unsigned long *ret; -+ -+ if ((ret = (unsigned long *)pte_quicklist) != NULL) { -+ pte_quicklist = (unsigned long *)(*ret); -+ ret[0] = ret[1]; -+ pgtable_cache_size--; -+ } -+ return (pte_t *)ret; -+} -+ -+static inline void pte_free_fast(pte_t *pte) -+{ -+ *(unsigned long *)pte = (unsigned long) pte_quicklist; -+ pte_quicklist = (unsigned long *) pte; -+ pgtable_cache_size++; -+} -+ -+static inline void pte_free_slow(pte_t *pte) -+{ -+ free_page((unsigned long)pte); -+} -+ -+#define pte_free(pte) pte_free_fast(pte) -+#define pgd_free(pgd) free_pgd_slow(pgd) -+#define pgd_alloc(mm) get_pgd_fast() -+ -+/* -+ * allocating and freeing a pmd is trivial: the 1-entry pmd is -+ * inside the pgd, so has no extra memory associated with it. -+ */ -+ -+#define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); }) -+#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) -+#define pmd_free_slow(x) do { } while (0) -+#define pmd_free_fast(x) do { } while (0) -+#define pmd_free(x) do { } while (0) -+#define pgd_populate(mm, pmd, pte) BUG() -+ -+/* -+ * TLB flushing: -+ * -+ * - flush_tlb() flushes the current mm struct TLBs -+ * - flush_tlb_all() flushes all processes TLBs -+ * - flush_tlb_mm(mm) flushes the specified mm context TLB's -+ * - flush_tlb_page(vma, vmaddr) flushes one page -+ * - flush_tlb_kernel_vm() flushes the kernel vm area -+ * - flush_tlb_range(mm, start, end) flushes a range of pages -+ * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables -+ */ -+ -+extern void flush_tlb_all(void); -+extern void flush_tlb_mm(struct mm_struct *mm); -+extern void flush_tlb_range(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); -+extern void flush_tlb_kernel_vm(void); -+ -+static inline void flush_tlb_pgtables(struct mm_struct *mm, -+ unsigned long start, unsigned long end) -+{ -+} -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/pgtable.h um/include/asm-um/pgtable.h ---- orig/include/asm-um/pgtable.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/pgtable.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,428 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Derived from include/asm-i386/pgtable.h -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PGTABLE_H -+#define __UM_PGTABLE_H -+ -+#include "linux/sched.h" -+#include "asm/processor.h" -+#include "asm/page.h" -+ -+extern pgd_t swapper_pg_dir[1024]; -+ -+#define flush_cache_all() do ; while (0) -+#define flush_cache_mm(mm) do ; while (0) -+#define flush_cache_range(vma, start, end) do ; while (0) -+#define flush_cache_page(vma, vmaddr) do ; while (0) -+#define flush_page_to_ram(page) do ; while (0) -+#define flush_dcache_page(page) do ; while (0) -+#define flush_icache_range(from, to) do ; while (0) -+#define flush_icache_page(vma,pg) do ; while (0) -+#define flush_icache_user_range(vma,pg,adr,len) do ; while (0) -+ -+extern void __flush_tlb_one(unsigned long addr); -+ -+extern void pte_free(pte_t *pte); -+ -+extern void pgd_free(pgd_t *pgd); -+ -+extern int do_check_pgt_cache(int, int); -+ -+extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt, -+ pte_t *pte_out); -+ -+/* zero page used for uninitialized stuff */ -+extern unsigned long *empty_zero_page; -+ -+#define pgtable_cache_init() do ; while (0) -+ -+/* PMD_SHIFT determines the size of the area a second-level page table can map */ -+#define PMD_SHIFT 22 -+#define PMD_SIZE (1UL << PMD_SHIFT) -+#define PMD_MASK (~(PMD_SIZE-1)) -+ -+/* PGDIR_SHIFT determines what a third-level page table entry can map */ -+#define PGDIR_SHIFT 22 -+#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -+#define PGDIR_MASK (~(PGDIR_SIZE-1)) -+ -+/* -+ * entries per page directory level: the i386 is two-level, so -+ * we don't really have any PMD directory physically. -+ */ -+#define PTRS_PER_PTE 1024 -+#define PTRS_PER_PMD 1 -+#define PTRS_PER_PGD 1024 -+#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) -+#define FIRST_USER_PGD_NR 0 -+ -+#define pte_ERROR(e) \ -+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) -+#define pmd_ERROR(e) \ -+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) -+#define pgd_ERROR(e) \ -+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) -+ -+/* -+ * pgd entries used up by user/kernel: -+ */ -+ -+#define USER_PGD_PTRS (TASK_SIZE >> PGDIR_SHIFT) -+#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS) -+ -+#ifndef __ASSEMBLY__ -+/* Just any arbitrary offset to the start of the vmalloc VM area: the -+ * current 8MB value just means that there will be a 8MB "hole" after the -+ * physical memory until the kernel virtual memory starts. That means that -+ * any out-of-bounds memory accesses will hopefully be caught. -+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced -+ * area for the same reason. ;) -+ */ -+ -+extern unsigned long high_physmem; -+ -+#define VMALLOC_OFFSET (__va_space) -+#define VMALLOC_START (((unsigned long) high_physmem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -+#define VMALLOC_VMADDR(x) ((unsigned long)(x)) -+ -+#if CONFIG_HIGHMEM -+# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) -+#else -+# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) -+#endif -+ -+#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 REGION_MASK 0xf0000000 -+#define REGION_SHIFT 28 -+ -+#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) -+#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) -+ -+#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) -+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) -+#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED) -+ -+/* -+ * The i386 can't do page protection for execute, and considers that the same are read. -+ * Also, write permissions imply read permissions. This is the closest we can get.. -+ */ -+#define __P000 PAGE_NONE -+#define __P001 PAGE_READONLY -+#define __P010 PAGE_COPY -+#define __P011 PAGE_COPY -+#define __P100 PAGE_READONLY -+#define __P101 PAGE_READONLY -+#define __P110 PAGE_COPY -+#define __P111 PAGE_COPY -+ -+#define __S000 PAGE_NONE -+#define __S001 PAGE_READONLY -+#define __S010 PAGE_SHARED -+#define __S011 PAGE_SHARED -+#define __S100 PAGE_READONLY -+#define __S101 PAGE_READONLY -+#define __S110 PAGE_SHARED -+#define __S111 PAGE_SHARED -+ -+/* -+ * Define this if things work differently on an i386 and an i486: -+ * it will (on an i486) warn about kernel memory accesses that are -+ * done without a 'verify_area(VERIFY_WRITE,..)' -+ */ -+#undef TEST_VERIFY_AREA -+ -+/* page table for 0-4MB for everybody */ -+extern unsigned long pg0[1024]; -+ -+/* -+ * BAD_PAGETABLE is used when we need a bogus page-table, while -+ * BAD_PAGE is used for a bogus page. -+ * -+ * ZERO_PAGE is a global shared page that is always zero: used -+ * for zero-mapped memory areas etc.. -+ */ -+extern pte_t __bad_page(void); -+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)) -+ -+/* number of bits that fit into a memory pointer */ -+#define BITS_PER_PTR (8*sizeof(unsigned long)) -+ -+/* to align the pointer to a pointer address */ -+#define PTR_MASK (~(sizeof(void*)-1)) -+ -+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */ -+/* 64-bit machines, beware! SRB. */ -+#define SIZEOF_PTR_LOG2 2 -+ -+/* to find an entry in a page-table */ -+#define PAGE_PTR(address) \ -+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) -+ -+#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE) -+#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) -+ -+#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) -+#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0) -+ -+#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE) -+#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE) -+ -+/* -+ * The "pgd_xxx()" functions here are trivial for a folded two-level -+ * setup: the pgd is never bad, and a pmd always exists (as it's folded -+ * into the pgd entry) -+ */ -+static inline int pgd_none(pgd_t pgd) { return 0; } -+static inline int pgd_bad(pgd_t pgd) { return 0; } -+static inline int pgd_present(pgd_t pgd) { return 1; } -+static inline void pgd_clear(pgd_t * pgdp) { } -+ -+#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); -+ -+#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 virt_to_page(kaddr) \ -+ (phys_mem_map(__pa(kaddr)) + (phys_addr(__pa(kaddr)) >> PAGE_SHIFT)) -+#define pte_pfn(x) phys_to_pfn(pte_val(x)) -+ -+static inline pte_t pte_mknewprot(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_NEWPROT; -+ return(pte); -+} -+ -+static inline pte_t pte_mknewpage(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_NEWPAGE; -+ return(pte); -+} -+ -+static inline void set_pte(pte_t *pteptr, pte_t pteval) -+{ -+ /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so -+ * fix_range knows to unmap it. _PAGE_NEWPROT is specific to -+ * mapped pages. -+ */ -+ *pteptr = pte_mknewpage(pteval); -+ if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr); -+} -+ -+/* -+ * (pmds are folded into pgds so this doesnt get actually called, -+ * but the define is needed for a generic inline function.) -+ */ -+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) -+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval) -+ -+/* -+ * The following only work if pte_present() is true. -+ * Undefined behaviour if not.. -+ */ -+static inline int pte_read(pte_t pte) -+{ -+ return((pte_val(pte) & _PAGE_USER) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+static inline int pte_exec(pte_t pte){ -+ return((pte_val(pte) & _PAGE_USER) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+static inline int pte_write(pte_t pte) -+{ -+ return((pte_val(pte) & _PAGE_RW) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+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; } -+static inline int pte_newprot(pte_t pte) -+{ -+ return(pte_present(pte) && (pte_val(pte) & _PAGE_NEWPROT)); -+} -+ -+static inline pte_t pte_rdprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_exprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkclean(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_DIRTY; -+ return(pte); -+} -+ -+static inline pte_t pte_mkold(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_ACCESSED; -+ return(pte); -+} -+ -+static inline pte_t pte_wrprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_RW; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkread(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkexec(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkdirty(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_DIRTY; -+ return(pte); -+} -+ -+static inline pte_t pte_mkyoung(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_ACCESSED; -+ return(pte); -+} -+ -+static inline pte_t pte_mkwrite(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_RW; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkuptodate(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_NEWPAGE; -+ if(pte_present(pte)) pte_val(pte) &= ~_PAGE_NEWPROT; -+ return(pte); -+} -+ -+extern unsigned long page_to_phys(struct page *page); -+ -+/* -+ * Conversion functions: convert a page and protection to a page entry, -+ * 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; \ -+}) -+ -+/* This takes a physical page address that is used by the remapping functions */ -+#define mk_pte_phys(physpage, pgprot) \ -+ pte_mknewpage(mk_pte(phys_page(physpage), pgprot)) -+ -+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -+{ -+ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); -+ if(pte_present(pte)) pte = pte_mknewpage(pte_mknewprot(pte)); -+ return pte; -+} -+ -+#define pmd_page(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) -+ -+/* to find an entry in a page-table-directory. */ -+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -+#define __pgd_offset(address) pgd_index(address) -+ -+/* to find an entry in a page-table-directory */ -+#define pgd_offset(mm, address) \ -+((mm)->pgd + ((address) >> PGDIR_SHIFT)) -+ -+/* to find an entry in a kernel page-table-directory */ -+#define pgd_offset_k(address) pgd_offset(&init_mm, address) -+ -+#define __pmd_offset(address) \ -+ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -+ -+/* Find an entry in the second-level page table.. */ -+static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -+{ -+ return (pmd_t *) dir; -+} -+ -+/* Find an entry in the third-level page table.. */ -+#define pte_offset(pmd, address) \ -+((pte_t *) (pmd_page(*pmd) + ((address>>10) & ((PTRS_PER_PTE-1)<<2)))) -+ -+#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_ENTRY(type, offset) \ -+ ((swp_entry_t) { ((type) << 3) | ((offset) << 10) }) -+#define pte_to_swp_entry(pte) \ -+ ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) }) -+#define swp_entry_to_pte(x) ((pte_t) { (x).val }) -+ -+#define PageSkip(x) (0) -+#define kern_addr_valid(addr) (1) -+ -+#include <asm-generic/pgtable.h> -+ -+#endif -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/poll.h um/include/asm-um/poll.h ---- orig/include/asm-um/poll.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/poll.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_POLL_H -+#define __UM_POLL_H -+ -+#include "asm/arch/poll.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/posix_types.h um/include/asm-um/posix_types.h ---- orig/include/asm-um/posix_types.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/posix_types.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_POSIX_TYPES_H -+#define __UM_POSIX_TYPES_H -+ -+#include "asm/arch/posix_types.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/processor-generic.h um/include/asm-um/processor-generic.h ---- orig/include/asm-um/processor-generic.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/processor-generic.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,182 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PROCESSOR_GENERIC_H -+#define __UM_PROCESSOR_GENERIC_H -+ -+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 -+ -+struct thread_struct { -+ int forking; -+ unsigned long kernel_stack; -+ int nsyscalls; -+ struct pt_regs regs; -+ unsigned long cr2; -+ int err; -+ void *fault_addr; -+ void *fault_catcher; -+ struct task_struct *prev_sched; -+ unsigned long temp_stack; -+ void *exec_buf; -+ struct arch_thread arch; -+ union { -+#ifdef CONFIG_MODE_TT -+ struct proc_tt_mode tt; -+#endif -+#ifdef CONFIG_MODE_SKAS -+ struct proc_skas_mode skas; -+#endif -+ } mode; -+ struct { -+ int op; -+ union { -+ struct { -+ int pid; -+ } fork, exec; -+ struct { -+ int (*proc)(void *); -+ void *arg; -+ } thread; -+ struct { -+ void (*proc)(void *); -+ void *arg; -+ } cb; -+ } u; -+ } request; -+}; -+ -+#define INIT_THREAD \ -+{ \ -+ .forking = 0, \ -+ .kernel_stack = 0, \ -+ .nsyscalls = 0, \ -+ .regs = EMPTY_REGS, \ -+ .cr2 = 0, \ -+ .err = 0, \ -+ .fault_addr = NULL, \ -+ .prev_sched = NULL, \ -+ .temp_stack = 0, \ -+ .exec_buf = NULL, \ -+ .arch = INIT_ARCH_THREAD, \ -+ .request = { 0 } \ -+} -+ -+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) -+ -+typedef struct { -+ unsigned long seg; -+} mm_segment_t; -+ -+extern struct task_struct *alloc_task_struct(void); -+extern void free_task_struct(struct task_struct *task); -+ -+#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) -+ -+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 unsigned long thread_saved_pc(struct thread_struct *t); -+ -+static inline void mm_copy_segments(struct mm_struct *from_mm, -+ struct mm_struct *new_mm) -+{ -+} -+ -+static inline void copy_segments(struct task_struct *p, -+ struct mm_struct *new_mm) -+{ -+} -+ -+static inline void release_segments(struct mm_struct *mm) -+{ -+} -+ -+#define init_task (init_task_union.task) -+#define init_stack (init_task_union.stack) -+ -+/* -+ * User space process size: 3GB (default). -+ */ -+extern unsigned long task_size; -+ -+#define TASK_SIZE (task_size) -+ -+/* This decides where the kernel will search for a free chunk of vm -+ * space during mmap's. -+ */ -+#define TASK_UNMAPPED_BASE (0x40000000) -+ -+extern void start_thread(struct pt_regs *regs, unsigned long entry, -+ unsigned long stack); -+ -+struct cpuinfo_um { -+ unsigned long loops_per_jiffy; -+ unsigned long *pgd_quick; -+ unsigned long *pmd_quick; -+ unsigned long *pte_quick; -+ unsigned long pgtable_cache_sz; -+ int ipi_pipe[2]; -+}; -+ -+extern struct cpuinfo_um boot_cpu_data; -+ -+#define my_cpu_data cpu_data[smp_processor_id()] -+ -+#ifdef CONFIG_SMP -+extern struct cpuinfo_um cpu_data[]; -+#define current_cpu_data cpu_data[smp_processor_id()] -+#else -+#define cpu_data (&boot_cpu_data) -+#define current_cpu_data boot_cpu_data -+#endif -+ -+#define KSTK_EIP(tsk) (PT_REGS_IP(&tsk->thread.regs)) -+#define KSTK_ESP(tsk) (PT_REGS_SP(&tsk->thread.regs)) -+#define get_wchan(p) (0) -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/processor-i386.h um/include/asm-um/processor-i386.h ---- orig/include/asm-um/processor-i386.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/processor-i386.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PROCESSOR_I386_H -+#define __UM_PROCESSOR_I386_H -+ -+extern int cpu_has_xmm; -+extern int cpu_has_cmov; -+ -+struct arch_thread { -+ unsigned long debugregs[8]; -+ int debugregs_seq; -+}; -+ -+#define INIT_ARCH_THREAD { .debugregs = { [ 0 ... 7 ] = 0 }, \ -+ .debugregs_seq = 0 } -+ -+#include "asm/arch/user.h" -+ -+#include "asm/processor-generic.h" -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/processor-ppc.h um/include/asm-um/processor-ppc.h ---- orig/include/asm-um/processor-ppc.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/processor-ppc.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,15 @@ -+#ifndef __UM_PROCESSOR_PPC_H -+#define __UM_PROCESSOR_PPC_H -+ -+#if defined(__ASSEMBLY__) -+ -+#define CONFIG_ALL_PPC -+#include "arch/processor.h" -+ -+#else -+ -+#include "asm/processor-generic.h" -+ -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ptrace-generic.h um/include/asm-um/ptrace-generic.h ---- orig/include/asm-um/ptrace-generic.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/ptrace-generic.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,74 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PTRACE_GENERIC_H -+#define __UM_PTRACE_GENERIC_H -+ -+#ifndef __ASSEMBLY__ -+ -+#include "linux/config.h" -+ -+#include "asm/current.h" -+ -+#define pt_regs pt_regs_subarch -+#define show_regs show_regs_subarch -+ -+#include "asm/arch/ptrace.h" -+ -+#undef pt_regs -+#undef show_regs -+#undef user_mode -+#undef instruction_pointer -+ -+#include "sysdep/ptrace.h" -+#include "skas_ptrace.h" -+ -+struct pt_regs { -+ union uml_pt_regs regs; -+}; -+ -+#define EMPTY_REGS { regs : EMPTY_UML_PT_REGS } -+ -+#define PT_REGS_IP(r) UPT_IP(&(r)->regs) -+#define PT_REGS_SP(r) UPT_SP(&(r)->regs) -+ -+#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg) -+#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val) -+ -+#define PT_REGS_SET_SYSCALL_RETURN(r, res) \ -+ UPT_SET_SYSCALL_RETURN(&(r)->regs, res) -+#define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs) -+ -+#define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs) -+ -+#define PT_REGS_SC(r) UPT_SC(&(r)->regs) -+ -+struct task_struct; -+ -+extern unsigned long getreg(struct task_struct *child, int regno); -+extern int putreg(struct task_struct *child, int regno, unsigned long value); -+extern int get_fpregs(unsigned long buf, struct task_struct *child); -+extern int set_fpregs(unsigned long buf, struct task_struct *child); -+extern int get_fpxregs(unsigned long buf, struct task_struct *child); -+extern int set_fpxregs(unsigned long buf, struct task_struct *tsk); -+ -+extern void show_regs(struct pt_regs *regs); -+ -+#define INIT_TASK_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) -+ -+#endif -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/ptrace-i386.h um/include/asm-um/ptrace-i386.h ---- orig/include/asm-um/ptrace-i386.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/ptrace-i386.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PTRACE_I386_H -+#define __UM_PTRACE_I386_H -+ -+#include "sysdep/ptrace.h" -+#include "asm/ptrace-generic.h" -+ -+#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs) -+#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs) -+#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs) -+#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs) -+#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs) -+#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs) -+#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs) -+ -+#define PT_REGS_CS(r) UPT_CS(&(r)->regs) -+#define PT_REGS_SS(r) UPT_SS(&(r)->regs) -+#define PT_REGS_DS(r) UPT_DS(&(r)->regs) -+#define PT_REGS_ES(r) UPT_ES(&(r)->regs) -+#define PT_REGS_FS(r) UPT_FS(&(r)->regs) -+#define PT_REGS_GS(r) UPT_GS(&(r)->regs) -+ -+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs) -+ -+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r) -+#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r) -+#define PT_FIX_EXEC_STACK(sp) do ; while(0) -+ -+#define user_mode(r) UPT_IS_USER(&(r)->regs) -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/resource.h um/include/asm-um/resource.h ---- orig/include/asm-um/resource.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/resource.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_RESOURCE_H -+#define __UM_RESOURCE_H -+ -+#include "asm/arch/resource.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/rwlock.h um/include/asm-um/rwlock.h ---- orig/include/asm-um/rwlock.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/rwlock.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_RWLOCK_H -+#define __UM_RWLOCK_H -+ -+#include "asm/arch/rwlock.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/rwsem.h um/include/asm-um/rwsem.h ---- orig/include/asm-um/rwsem.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/rwsem.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,10 @@ -+#ifndef __UM_RWSEM_H__ -+#define __UM_RWSEM_H__ -+ -+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) -+#define __builtin_expect(exp,c) (exp) -+#endif -+ -+#include "asm/arch/rwsem.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/scatterlist.h um/include/asm-um/scatterlist.h ---- orig/include/asm-um/scatterlist.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/scatterlist.h Thu Feb 27 13:21:49 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SCATTERLIST_H -+#define __UM_SCATTERLIST_H -+ -+#include "asm/arch/scatterlist.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/segment.h um/include/asm-um/segment.h ---- orig/include/asm-um/segment.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/segment.h Fri Nov 1 19:45:34 2002 -@@ -0,0 +1,4 @@ -+#ifndef __UM_SEGMENT_H -+#define __UM_SEGMENT_H -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/semaphore.h um/include/asm-um/semaphore.h ---- orig/include/asm-um/semaphore.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/semaphore.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SEMAPHORE_H -+#define __UM_SEMAPHORE_H -+ -+#include "asm/arch/semaphore.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sembuf.h um/include/asm-um/sembuf.h ---- orig/include/asm-um/sembuf.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/sembuf.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SEMBUF_H -+#define __UM_SEMBUF_H -+ -+#include "asm/arch/sembuf.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/serial.h um/include/asm-um/serial.h ---- orig/include/asm-um/serial.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/serial.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SERIAL_H -+#define __UM_SERIAL_H -+ -+#include "asm/arch/serial.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/shmbuf.h um/include/asm-um/shmbuf.h ---- orig/include/asm-um/shmbuf.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/shmbuf.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SHMBUF_H -+#define __UM_SHMBUF_H -+ -+#include "asm/arch/shmbuf.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/shmparam.h um/include/asm-um/shmparam.h ---- orig/include/asm-um/shmparam.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/shmparam.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SHMPARAM_H -+#define __UM_SHMPARAM_H -+ -+#include "asm/arch/shmparam.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-generic.h um/include/asm-um/sigcontext-generic.h ---- orig/include/asm-um/sigcontext-generic.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/sigcontext-generic.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGCONTEXT_GENERIC_H -+#define __UM_SIGCONTEXT_GENERIC_H -+ -+#include "asm/arch/sigcontext.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-i386.h um/include/asm-um/sigcontext-i386.h ---- orig/include/asm-um/sigcontext-i386.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/sigcontext-i386.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGCONTEXT_I386_H -+#define __UM_SIGCONTEXT_I386_H -+ -+#include "asm/sigcontext-generic.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-ppc.h um/include/asm-um/sigcontext-ppc.h ---- orig/include/asm-um/sigcontext-ppc.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/sigcontext-ppc.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,10 @@ -+#ifndef __UM_SIGCONTEXT_PPC_H -+#define __UM_SIGCONTEXT_PPC_H -+ -+#define pt_regs sys_pt_regs -+ -+#include "asm/sigcontext-generic.h" -+ -+#undef pt_regs -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/siginfo.h um/include/asm-um/siginfo.h ---- orig/include/asm-um/siginfo.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/siginfo.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGINFO_H -+#define __UM_SIGINFO_H -+ -+#include "asm/arch/siginfo.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/signal.h um/include/asm-um/signal.h ---- orig/include/asm-um/signal.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/signal.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SIGNAL_H -+#define __UM_SIGNAL_H -+ -+#include "asm/arch/signal.h" -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/smp.h um/include/asm-um/smp.h ---- orig/include/asm-um/smp.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/smp.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,19 @@ -+#ifndef __UM_SMP_H -+#define __UM_SMP_H -+ -+#ifdef CONFIG_SMP -+ -+#include "linux/config.h" -+#include "asm/current.h" -+ -+#define smp_processor_id() (current->processor) -+#define cpu_logical_map(n) (n) -+#define cpu_number_map(n) (n) -+#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */ -+extern int hard_smp_processor_id(void); -+extern unsigned long cpu_online_map; -+#define NO_PROC_ID -1 -+ -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/smplock.h um/include/asm-um/smplock.h ---- orig/include/asm-um/smplock.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/smplock.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SMPLOCK_H -+#define __UM_SMPLOCK_H -+ -+#include "asm/arch/smplock.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/socket.h um/include/asm-um/socket.h ---- orig/include/asm-um/socket.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/socket.h Thu Feb 27 13:20:13 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SOCKET_H -+#define __UM_SOCKET_H -+ -+#include "asm/arch/socket.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sockios.h um/include/asm-um/sockios.h ---- orig/include/asm-um/sockios.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/sockios.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SOCKIOS_H -+#define __UM_SOCKIOS_H -+ -+#include "asm/arch/sockios.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/softirq.h um/include/asm-um/softirq.h ---- orig/include/asm-um/softirq.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/softirq.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,13 @@ -+#ifndef __UM_SOFTIRQ_H -+#define __UM_SOFTIRQ_H -+ -+#include "linux/smp.h" -+#include "asm/system.h" -+#include "asm/processor.h" -+ -+/* A gratuitous name change */ -+#define i386_bh_lock um_bh_lock -+#include "asm/arch/softirq.h" -+#undef i386_bh_lock -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/spinlock.h um/include/asm-um/spinlock.h ---- orig/include/asm-um/spinlock.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/spinlock.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,10 @@ -+#ifndef __UM_SPINLOCK_H -+#define __UM_SPINLOCK_H -+ -+#include "linux/config.h" -+ -+#ifdef CONFIG_SMP -+#include "asm/arch/spinlock.h" -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/stat.h um/include/asm-um/stat.h ---- orig/include/asm-um/stat.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/stat.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_STAT_H -+#define __UM_STAT_H -+ -+#include "asm/arch/stat.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/statfs.h um/include/asm-um/statfs.h ---- orig/include/asm-um/statfs.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/statfs.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,6 @@ -+#ifndef _UM_STATFS_H -+#define _UM_STATFS_H -+ -+#include "asm/arch/statfs.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/string.h um/include/asm-um/string.h ---- orig/include/asm-um/string.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/string.h Mon Feb 24 22:52:09 2003 -@@ -0,0 +1,7 @@ -+#ifndef __UM_STRING_H -+#define __UM_STRING_H -+ -+#include "asm/arch/string.h" -+#include "asm/archparam.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/system-generic.h um/include/asm-um/system-generic.h ---- orig/include/asm-um/system-generic.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/system-generic.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,50 @@ -+#ifndef __UM_SYSTEM_GENERIC_H -+#define __UM_SYSTEM_GENERIC_H -+ -+#include "asm/arch/system.h" -+ -+#undef prepare_to_switch -+#undef switch_to -+#undef __save_flags -+#undef save_flags -+#undef __restore_flags -+#undef restore_flags -+#undef __cli -+#undef __sti -+#undef cli -+#undef sti -+#undef local_irq_save -+#undef local_irq_restore -+#undef local_irq_disable -+#undef local_irq_enable -+ -+#define prepare_to_switch() do ; while(0) -+ -+void *_switch_to(void *prev, void *next); -+ -+#define switch_to(prev, next, last) prev = _switch_to(prev, next) -+ -+extern int get_signals(void); -+extern int set_signals(int enable); -+extern void block_signals(void); -+extern void unblock_signals(void); -+ -+#define local_irq_save(flags) do { (flags) = set_signals(0); } while(0) -+ -+#define local_irq_restore(flags) do { set_signals(flags); } while(0) -+ -+#define local_irq_enable() unblock_signals() -+#define local_irq_disable() block_signals() -+ -+#define __sti() unblock_signals() -+#define sti() unblock_signals() -+#define __cli() block_signals() -+#define cli() block_signals() -+ -+#define __save_flags(x) do { (flags) = get_signals(); } while(0) -+#define save_flags(x) __save_flags(x) -+ -+#define __restore_flags(x) local_irq_restore(x) -+#define restore_flags(x) __restore_flags(x) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/system-i386.h um/include/asm-um/system-i386.h ---- orig/include/asm-um/system-i386.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/system-i386.h Tue Mar 25 14:23:19 2003 -@@ -0,0 +1,39 @@ -+#ifndef __UM_SYSTEM_I386_H -+#define __UM_SYSTEM_I386_H -+ -+#include "asm/system-generic.h" -+ -+#define __HAVE_ARCH_CMPXCHG 1 -+ -+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 -Naur -X ../exclude-files orig/include/asm-um/system-ppc.h um/include/asm-um/system-ppc.h ---- orig/include/asm-um/system-ppc.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/system-ppc.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,12 @@ -+#ifndef __UM_SYSTEM_PPC_H -+#define __UM_SYSTEM_PPC_H -+ -+#define _switch_to _ppc_switch_to -+ -+#include "asm/arch/system.h" -+ -+#undef _switch_to -+ -+#include "asm/system-generic.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/termbits.h um/include/asm-um/termbits.h ---- orig/include/asm-um/termbits.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/termbits.h Wed Oct 23 21:11:14 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TERMBITS_H -+#define __UM_TERMBITS_H -+ -+#include "asm/arch/termbits.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/termios.h um/include/asm-um/termios.h ---- orig/include/asm-um/termios.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/termios.h Thu Feb 27 13:20:13 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TERMIOS_H -+#define __UM_TERMIOS_H -+ -+#include "asm/arch/termios.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/timex.h um/include/asm-um/timex.h ---- orig/include/asm-um/timex.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/timex.h Mon Mar 24 16:53:23 2003 -@@ -0,0 +1,18 @@ -+#ifndef __UM_TIMEX_H -+#define __UM_TIMEX_H -+ -+#include "linux/time.h" -+ -+typedef unsigned long cycles_t; -+ -+#define cacheflush_time (0) -+ -+static inline cycles_t get_cycles (void) -+{ -+ return 0; -+} -+ -+#define vxtime_lock() do ; while (0) -+#define vxtime_unlock() do ; while (0) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/tlb.h um/include/asm-um/tlb.h ---- orig/include/asm-um/tlb.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/tlb.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1 @@ -+#include <asm-generic/tlb.h> -diff -Naur -X ../exclude-files orig/include/asm-um/types.h um/include/asm-um/types.h ---- orig/include/asm-um/types.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/types.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TYPES_H -+#define __UM_TYPES_H -+ -+#include "asm/arch/types.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/uaccess.h um/include/asm-um/uaccess.h ---- orig/include/asm-um/uaccess.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/uaccess.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,97 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_UACCESS_H -+#define __UM_UACCESS_H -+ -+#define VERIFY_READ 0 -+#define VERIFY_WRITE 1 -+ -+/* -+ * The fs value determines whether argument validity checking should be -+ * performed or not. If get_fs() == USER_DS, checking is performed, with -+ * get_fs() == KERNEL_DS, checking is bypassed. -+ * -+ * For historical reasons, these macros are grossly misnamed. -+ */ -+ -+#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) -+ -+#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) -+#define USER_DS MAKE_MM_SEG(TASK_SIZE) -+ -+#define get_ds() (KERNEL_DS) -+#define get_fs() (current->addr_limit) -+#define set_fs(x) (current->addr_limit = (x)) -+ -+#define segment_eq(a, b) ((a).seg == (b).seg) -+ -+#include "um_uaccess.h" -+ -+#define __copy_from_user(to, from, n) copy_from_user(to, from, n) -+ -+#define __copy_to_user(to, from, n) copy_to_user(to, from, n) -+ -+#define __get_user(x, ptr) \ -+({ \ -+ const __typeof__(ptr) __private_ptr = ptr; \ -+ __typeof__(*(__private_ptr)) __private_val; \ -+ int __private_ret = -EFAULT; \ -+ (x) = 0; \ -+ if (__copy_from_user(&__private_val, (__private_ptr), \ -+ sizeof(*(__private_ptr))) == 0) {\ -+ (x) = (__typeof__(*(__private_ptr))) __private_val; \ -+ __private_ret = 0; \ -+ } \ -+ __private_ret; \ -+}) -+ -+#define get_user(x, ptr) \ -+({ \ -+ const __typeof__((*ptr)) *private_ptr = (ptr); \ -+ (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \ -+ __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \ -+}) -+ -+#define __put_user(x, ptr) \ -+({ \ -+ __typeof__(ptr) __private_ptr = ptr; \ -+ __typeof__(*(__private_ptr)) __private_val; \ -+ int __private_ret = -EFAULT; \ -+ __private_val = (__typeof__(*(__private_ptr))) (x); \ -+ if (__copy_to_user((__private_ptr), &__private_val, \ -+ sizeof(*(__private_ptr))) == 0) { \ -+ __private_ret = 0; \ -+ } \ -+ __private_ret; \ -+}) -+ -+#define put_user(x, ptr) \ -+({ \ -+ __typeof__(*(ptr)) *private_ptr = (ptr); \ -+ (access_ok(VERIFY_WRITE, private_ptr, sizeof(*private_ptr)) ? \ -+ __put_user(x, private_ptr) : -EFAULT); \ -+}) -+ -+#define strlen_user(str) strnlen_user(str, ~0UL >> 1) -+ -+struct exception_table_entry -+{ -+ unsigned long insn; -+ unsigned long fixup; -+}; -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/ucontext.h um/include/asm-um/ucontext.h ---- orig/include/asm-um/ucontext.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/ucontext.h Sun Dec 1 13:20:58 2002 -@@ -0,0 +1,6 @@ -+#ifndef _ASM_UM_UCONTEXT_H -+#define _ASM_UM_UCONTEXT_H -+ -+#include "asm/arch/ucontext.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/unaligned.h um/include/asm-um/unaligned.h ---- orig/include/asm-um/unaligned.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/unaligned.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_UNALIGNED_H -+#define __UM_UNALIGNED_H -+ -+#include "asm/arch/unaligned.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/unistd.h um/include/asm-um/unistd.h ---- orig/include/asm-um/unistd.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/unistd.h Mon Mar 24 16:53:25 2003 -@@ -0,0 +1,118 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef _UM_UNISTD_H_ -+#define _UM_UNISTD_H_ -+ -+#include "linux/resource.h" -+#include "asm/uaccess.h" -+ -+extern long sys_open(const char *filename, int flags, int mode); -+extern long sys_dup(unsigned int fildes); -+extern long sys_close(unsigned int fd); -+extern int um_execve(const char *file, char *const argv[], char *const env[]); -+extern long sys_setsid(void); -+extern long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options); -+extern long sys_wait4(pid_t pid,unsigned int *stat_addr, int options, -+ struct rusage *ru); -+extern long sys_mount(char *dev_name, char *dir_name, char *type, -+ unsigned long flags, void *data); -+extern long sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, -+ struct timeval *tvp); -+extern long sys_lseek(unsigned int fildes, unsigned long offset, int whence); -+extern long sys_read(unsigned int fildes, char *buf, int len); -+extern long sys_write(unsigned int fildes, char *buf, int len); -+ -+#ifdef __KERNEL_SYSCALLS__ -+ -+#define KERNEL_CALL(ret_t, sys, args...) \ -+ mm_segment_t fs = get_fs(); \ -+ ret_t ret; \ -+ set_fs(KERNEL_DS); \ -+ ret = sys(args); \ -+ set_fs(fs); \ -+ return ret; -+ -+static inline long open(const char *pathname, int flags, int mode) -+{ -+ KERNEL_CALL(int, sys_open, pathname, flags, mode) -+} -+ -+static inline long dup(unsigned int fd) -+{ -+ KERNEL_CALL(int, sys_dup, fd); -+} -+ -+static inline long close(unsigned int fd) -+{ -+ KERNEL_CALL(int, sys_close, fd); -+} -+ -+static inline int execve(const char *filename, char *const argv[], -+ char *const envp[]) -+{ -+ KERNEL_CALL(int, um_execve, filename, argv, envp); -+} -+ -+static inline long waitpid(pid_t pid, unsigned int *status, int options) -+{ -+ KERNEL_CALL(pid_t, sys_wait4, pid, status, options, NULL) -+} -+ -+static inline pid_t wait(int *status) -+{ -+ KERNEL_CALL(pid_t, sys_wait4, -1, status, 0, NULL) -+} -+ -+static inline pid_t setsid(void) -+{ -+ KERNEL_CALL(pid_t, sys_setsid) -+} -+ -+static inline long lseek(unsigned int fd, off_t offset, unsigned int whence) -+{ -+ KERNEL_CALL(long, sys_lseek, fd, offset, whence) -+} -+ -+static inline int read(unsigned int fd, char * buf, int len) -+{ -+ KERNEL_CALL(int, sys_read, fd, buf, len) -+} -+ -+static inline int write(unsigned int fd, char * buf, int len) -+{ -+ KERNEL_CALL(int, sys_write, fd, buf, len) -+} -+ -+#endif -+ -+/* Save the value of __KERNEL_SYSCALLS__, undefine it, include the underlying -+ * arch's unistd.h for the system call numbers, and restore the old -+ * __KERNEL_SYSCALLS__. -+ */ -+ -+#ifdef __KERNEL_SYSCALLS__ -+#define __SAVE_KERNEL_SYSCALLS__ __KERNEL_SYSCALLS__ -+#endif -+ -+#undef __KERNEL_SYSCALLS__ -+#include "asm/arch/unistd.h" -+ -+#ifdef __KERNEL_SYSCALLS__ -+#define __KERNEL_SYSCALLS__ __SAVE_KERNEL_SYSCALLS__ -+#endif -+ -+#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 -Naur -X ../exclude-files orig/include/asm-um/user.h um/include/asm-um/user.h ---- orig/include/asm-um/user.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/user.h Mon Mar 24 16:57:21 2003 -@@ -0,0 +1,6 @@ -+#ifndef __UM_USER_H -+#define __UM_USER_H -+ -+#include "asm/arch/user.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/vga.h um/include/asm-um/vga.h ---- orig/include/asm-um/vga.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/vga.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_VGA_H -+#define __UM_VGA_H -+ -+#include "asm/arch/vga.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/xor.h um/include/asm-um/xor.h ---- orig/include/asm-um/xor.h Wed Dec 31 19:00:00 1969 -+++ um/include/asm-um/xor.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,6 @@ -+#ifndef __UM_XOR_H -+#define __UM_XOR_H -+ -+#include "asm-generic/xor.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/linux/blk.h um/include/linux/blk.h ---- orig/include/linux/blk.h Sun Sep 15 12:13:19 2002 -+++ um/include/linux/blk.h Tue Mar 25 14:23:19 2003 -@@ -320,6 +320,15 @@ - #define DEVICE_REQUEST do_ida_request - #define DEVICE_NR(device) (MINOR(device) >> 4) - -+#elif (MAJOR_NR == UBD_MAJOR) -+ -+#define DEVICE_NAME "User-mode block device" -+#define DEVICE_INTR do_ubd -+#define DEVICE_REQUEST do_ubd_request -+#define DEVICE_NR(device) (MINOR(device) >> UBD_SHIFT) -+#define DEVICE_ON(device) -+#define DEVICE_OFF(device) -+ - #endif /* MAJOR_NR == whatever */ - - /* provide DEVICE_xxx defaults, if not explicitly defined -diff -Naur -X ../exclude-files orig/include/linux/fs.h um/include/linux/fs.h ---- orig/include/linux/fs.h Thu Feb 27 13:04:27 2003 -+++ um/include/linux/fs.h Tue Mar 25 14:23:19 2003 -@@ -318,6 +318,8 @@ - #include <linux/ncp_fs_i.h> - #include <linux/proc_fs_i.h> - #include <linux/usbdev_fs_i.h> -+#include <linux/hostfs_fs_i.h> -+#include <linux/hppfs_fs_i.h> - #include <linux/jffs2_fs_i.h> - #include <linux/cramfs_fs_sb.h> - -@@ -509,7 +511,9 @@ - struct proc_inode_info proc_i; - struct socket socket_i; - struct usbdev_inode_info usbdev_i; -- struct jffs2_inode_info jffs2_i; -+ struct hostfs_inode_info hostfs_i; -+ struct hppfs_inode_info hppfs_i; -+ struct jffs2_inode_info jffs2_i; - void *generic_ip; - } u; - }; -diff -Naur -X ../exclude-files orig/include/linux/hostfs_fs_i.h um/include/linux/hostfs_fs_i.h ---- orig/include/linux/hostfs_fs_i.h Wed Dec 31 19:00:00 1969 -+++ um/include/linux/hostfs_fs_i.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,21 @@ -+#ifndef _HOSTFS_FS_I -+#define _HOSTFS_FS_I -+ -+struct hostfs_inode_info { -+ char *host_filename; -+ int fd; -+ int mode; -+}; -+ -+#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 -Naur -X ../exclude-files orig/include/linux/hppfs_fs_i.h um/include/linux/hppfs_fs_i.h ---- orig/include/linux/hppfs_fs_i.h Wed Dec 31 19:00:00 1969 -+++ um/include/linux/hppfs_fs_i.h Wed Oct 23 21:08:05 2002 -@@ -0,0 +1,19 @@ -+#ifndef _HPPFS_FS_I -+#define _HPPFS_FS_I -+ -+struct hppfs_inode_info { -+ struct dentry *proc_dentry; -+}; -+ -+#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 -Naur -X ../exclude-files orig/include/linux/kernel.h um/include/linux/kernel.h ---- orig/include/linux/kernel.h Thu Feb 27 13:04:27 2003 -+++ um/include/linux/kernel.h Mon Mar 24 16:53:23 2003 -@@ -49,7 +49,7 @@ - # define ATTRIB_NORET __attribute__((noreturn)) - # define NORET_AND noreturn, - --#ifdef __i386__ -+#if defined(__i386__) || defined(UM_FASTCALL) - #define FASTCALL(x) x __attribute__((regparm(3))) - #else - #define FASTCALL(x) x -diff -Naur -X ../exclude-files orig/include/linux/kernel_stat.h um/include/linux/kernel_stat.h ---- orig/include/linux/kernel_stat.h Thu Feb 27 13:04:27 2003 -+++ um/include/linux/kernel_stat.h Tue Mar 25 14:23:24 2003 -@@ -12,7 +12,7 @@ - * used by rstatd/perfmeter - */ - --#define DK_MAX_MAJOR 16 -+#define DK_MAX_MAJOR 99 - #define DK_MAX_DISK 16 - - struct kernel_stat { -diff -Naur -X ../exclude-files orig/include/linux/mm.h um/include/linux/mm.h ---- orig/include/linux/mm.h Sun Sep 15 12:13:19 2002 -+++ um/include/linux/mm.h Tue Mar 25 14:23:19 2003 -@@ -425,6 +425,14 @@ - extern struct page * FASTCALL(__alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist)); - extern struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order); - -+#ifndef HAVE_ARCH_VALIDATE -+static inline struct page *arch_validate(struct page *page, -+ unsigned int gfp_mask, int order) -+{ -+ return(page); -+} -+#endif -+ - static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order) - { - /* -@@ -432,7 +440,7 @@ - */ - if (order >= MAX_ORDER) - return NULL; -- return _alloc_pages(gfp_mask, order); -+ return arch_validate(_alloc_pages(gfp_mask, order), gfp_mask, order); - } - - #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) -@@ -492,6 +500,9 @@ - int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, - int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); - -+extern long do_mprotect(struct mm_struct *mm, unsigned long start, -+ size_t len, unsigned long prot); -+ - /* - * On a two-level page table, this ends up being trivial. Thus the - * inlining and the symmetry break with pte_alloc() that does all -@@ -539,9 +550,10 @@ - - extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - --extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, -- unsigned long len, unsigned long prot, -- unsigned long flag, unsigned long pgoff); -+extern unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file *file, -+ unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flag, -+ unsigned long pgoff); - - static inline unsigned long do_mmap(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, -@@ -551,7 +563,8 @@ - if ((offset + PAGE_ALIGN(len)) < offset) - goto out; - if (!(offset & ~PAGE_MASK)) -- ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); -+ ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag, -+ offset >> PAGE_SHIFT); - out: - return ret; - } -diff -Naur -X ../exclude-files orig/include/linux/proc_mm.h um/include/linux/proc_mm.h ---- orig/include/linux/proc_mm.h Wed Dec 31 19:00:00 1969 -+++ um/include/linux/proc_mm.h Tue Mar 25 14:25:47 2003 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PROC_MM_H -+#define __PROC_MM_H -+ -+#include "linux/sched.h" -+ -+#define MM_MMAP 54 -+#define MM_MUNMAP 55 -+#define MM_MPROTECT 56 -+#define MM_COPY_SEGMENTS 57 -+ -+struct mm_mmap { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+struct mm_munmap { -+ unsigned long addr; -+ unsigned long len; -+}; -+ -+struct mm_mprotect { -+ unsigned long addr; -+ unsigned long len; -+ unsigned int prot; -+}; -+ -+struct proc_mm_op { -+ int op; -+ union { -+ struct mm_mmap mmap; -+ struct mm_munmap munmap; -+ struct mm_mprotect mprotect; -+ int copy_segments; -+ } u; -+}; -+ -+extern struct mm_struct *proc_mm_get_mm(int fd); -+ -+#endif -diff -Naur -X ../exclude-files orig/include/linux/tty.h um/include/linux/tty.h ---- orig/include/linux/tty.h Thu Feb 27 13:04:28 2003 -+++ um/include/linux/tty.h Tue Mar 25 14:23:19 2003 -@@ -309,6 +309,9 @@ - spinlock_t read_lock; - /* If the tty has a pending do_SAK, queue it here - akpm */ - struct tq_struct SAK_tq; -+#ifdef CONFIG_TTY_LOG -+ int log_fd; -+#endif - }; - - /* tty magic number */ -@@ -366,6 +369,7 @@ - extern int specialix_init(void); - extern int espserial_init(void); - extern int macserial_init(void); -+extern int stdio_init(void); - extern int a2232board_init(void); - - extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device, -@@ -420,6 +424,8 @@ - - extern int vt_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg); -+ -+extern void stdio_console_init(void); - - #endif /* __KERNEL__ */ - #endif -diff -Naur -X ../exclude-files orig/init/do_mounts.c um/init/do_mounts.c ---- orig/init/do_mounts.c Thu Feb 27 13:04:28 2003 -+++ um/init/do_mounts.c Thu Feb 27 13:05:27 2003 -@@ -153,6 +153,22 @@ - { "pf", 0x2f00 }, - { "apblock", APBLOCK_MAJOR << 8}, - { "ddv", DDV_MAJOR << 8}, -+ { "ubd0", UBD_MAJOR << 8 | 0 << 4}, -+ { "ubda", UBD_MAJOR << 8 | 0 << 4}, -+ { "ubd1", UBD_MAJOR << 8 | 1 << 4}, -+ { "ubdb", UBD_MAJOR << 8 | 1 << 4}, -+ { "ubd2", UBD_MAJOR << 8 | 2 << 4}, -+ { "ubdc", UBD_MAJOR << 8 | 2 << 4}, -+ { "ubd3", UBD_MAJOR << 8 | 3 << 4}, -+ { "ubdd", UBD_MAJOR << 8 | 3 << 4}, -+ { "ubd4", UBD_MAJOR << 8 | 4 << 4}, -+ { "ubde", UBD_MAJOR << 8 | 4 << 4}, -+ { "ubd5", UBD_MAJOR << 8 | 5 << 4}, -+ { "ubdf", UBD_MAJOR << 8 | 5 << 4}, -+ { "ubd6", UBD_MAJOR << 8 | 6 << 4}, -+ { "ubdg", UBD_MAJOR << 8 | 6 << 4}, -+ { "ubd7", UBD_MAJOR << 8 | 7 << 4}, -+ { "ubdh", UBD_MAJOR << 8 | 7 << 4}, - { "jsfd", JSFD_MAJOR << 8}, - #if defined(CONFIG_ARCH_S390) - { "dasda", (DASD_MAJOR << MINORBITS) }, -diff -Naur -X ../exclude-files orig/kernel/panic.c um/kernel/panic.c ---- orig/kernel/panic.c Thu Feb 27 13:04:29 2003 -+++ um/kernel/panic.c Thu Feb 27 13:05:27 2003 -@@ -66,7 +66,7 @@ - smp_send_stop(); - #endif - -- notifier_call_chain(&panic_notifier_list, 0, NULL); -+ notifier_call_chain(&panic_notifier_list, 0, buf); - - if (panic_timeout > 0) - { -diff -Naur -X ../exclude-files orig/mm/Makefile um/mm/Makefile ---- orig/mm/Makefile Wed Aug 21 11:47:43 2002 -+++ um/mm/Makefile Fri Nov 8 14:21:36 2002 -@@ -17,5 +17,6 @@ - shmem.o - - obj-$(CONFIG_HIGHMEM) += highmem.o -+obj-$(CONFIG_PROC_MM) += proc_mm.o - - include $(TOPDIR)/Rules.make -diff -Naur -X ../exclude-files orig/mm/mmap.c um/mm/mmap.c ---- orig/mm/mmap.c Thu Feb 27 13:04:29 2003 -+++ um/mm/mmap.c Thu Feb 27 13:05:27 2003 -@@ -390,10 +390,11 @@ - return 0; - } - --unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len, -- unsigned long prot, unsigned long flags, unsigned long pgoff) -+unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file, -+ unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long pgoff) - { -- struct mm_struct * mm = current->mm; - struct vm_area_struct * vma, * prev; - unsigned int vm_flags; - int correct_wcount = 0; -diff -Naur -X ../exclude-files orig/mm/mprotect.c um/mm/mprotect.c ---- orig/mm/mprotect.c Wed Aug 21 11:47:43 2002 -+++ um/mm/mprotect.c Sun Nov 10 20:24:32 2002 -@@ -264,7 +264,8 @@ - return 0; - } - --asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) -+long do_mprotect(struct mm_struct *mm, unsigned long start, size_t len, -+ unsigned long prot) - { - unsigned long nstart, end, tmp; - struct vm_area_struct * vma, * next, * prev; -@@ -281,9 +282,9 @@ - if (end == start) - return 0; - -- down_write(¤t->mm->mmap_sem); -+ down_write(&mm->mmap_sem); - -- vma = find_vma_prev(current->mm, start, &prev); -+ vma = find_vma_prev(mm, start, &prev); - error = -ENOMEM; - if (!vma || vma->vm_start > start) - goto out; -@@ -332,6 +333,11 @@ - prev->vm_mm->map_count--; - } - out: -- up_write(¤t->mm->mmap_sem); -+ up_write(&mm->mmap_sem); - return error; -+} -+ -+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) -+{ -+ return(do_mprotect(current->mm, start, len, prot)); - } -diff -Naur -X ../exclude-files orig/mm/proc_mm.c um/mm/proc_mm.c ---- orig/mm/proc_mm.c Wed Dec 31 19:00:00 1969 -+++ um/mm/proc_mm.c Tue Nov 19 14:20:26 2002 -@@ -0,0 +1,173 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/proc_fs.h" -+#include "linux/proc_mm.h" -+#include "linux/file.h" -+#include "asm/uaccess.h" -+#include "asm/mmu_context.h" -+ -+static struct file_operations proc_mm_fops; -+ -+struct mm_struct *proc_mm_get_mm(int fd) -+{ -+ struct mm_struct *ret = ERR_PTR(-EBADF); -+ struct file *file; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ ret = ERR_PTR(-EINVAL); -+ if(file->f_op != &proc_mm_fops) -+ goto out_fput; -+ -+ ret = file->private_data; -+ out_fput: -+ fput(file); -+ out: -+ return(ret); -+} -+ -+extern long do_mmap2(struct mm_struct *mm, unsigned long addr, -+ unsigned long len, unsigned long prot, -+ unsigned long flags, unsigned long fd, -+ unsigned long pgoff); -+ -+static ssize_t write_proc_mm(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct mm_struct *mm = file->private_data; -+ struct proc_mm_op req; -+ int n, ret; -+ -+ if(count > sizeof(req)) -+ return(-EINVAL); -+ -+ n = copy_from_user(&req, buffer, count); -+ if(n != 0) -+ return(-EFAULT); -+ -+ ret = count; -+ switch(req.op){ -+ case MM_MMAP: { -+ struct mm_mmap *map = &req.u.mmap; -+ -+ ret = do_mmap2(mm, map->addr, map->len, map->prot, -+ map->flags, map->fd, map->offset >> PAGE_SHIFT); -+ if((ret & ~PAGE_MASK) == 0) -+ ret = count; -+ -+ break; -+ } -+ case MM_MUNMAP: { -+ struct mm_munmap *unmap = &req.u.munmap; -+ -+ down_write(&mm->mmap_sem); -+ ret = do_munmap(mm, unmap->addr, unmap->len); -+ up_write(&mm->mmap_sem); -+ -+ if(ret == 0) -+ ret = count; -+ break; -+ } -+ case MM_MPROTECT: { -+ struct mm_mprotect *protect = &req.u.mprotect; -+ -+ ret = do_mprotect(mm, protect->addr, protect->len, -+ protect->prot); -+ if(ret == 0) -+ ret = count; -+ break; -+ } -+ -+ case MM_COPY_SEGMENTS: { -+ struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments); -+ -+ if(IS_ERR(from)){ -+ ret = PTR_ERR(from); -+ break; -+ } -+ -+ mm_copy_segments(from, mm); -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return(ret); -+} -+ -+static int open_proc_mm(struct inode *inode, struct file *file) -+{ -+ struct mm_struct *mm = mm_alloc(); -+ int ret; -+ -+ ret = -ENOMEM; -+ if(mm == NULL) -+ goto out_mem; -+ -+ ret = init_new_context(current, mm); -+ if(ret) -+ goto out_free; -+ -+ spin_lock(&mmlist_lock); -+ list_add(&mm->mmlist, ¤t->mm->mmlist); -+ mmlist_nr++; -+ spin_unlock(&mmlist_lock); -+ -+ file->private_data = mm; -+ -+ return(0); -+ -+ out_free: -+ mmput(mm); -+ out_mem: -+ return(ret); -+} -+ -+static int release_proc_mm(struct inode *inode, struct file *file) -+{ -+ struct mm_struct *mm = file->private_data; -+ -+ mmput(mm); -+ return(0); -+} -+ -+static struct file_operations proc_mm_fops = { -+ .open = open_proc_mm, -+ .release = release_proc_mm, -+ .write = write_proc_mm, -+}; -+ -+static int make_proc_mm(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ ent = create_proc_entry("mm", 0222, &proc_root); -+ if(ent == NULL){ -+ printk("make_proc_mm : Failed to register /proc/mm\n"); -+ return(0); -+ } -+ ent->proc_fops = &proc_mm_fops; -+ -+ return(0); -+} -+ -+__initcall(make_proc_mm); -+ -+/* -+ * 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 -Naur -X ../exclude-files orig/mm/slab.c um/mm/slab.c ---- orig/mm/slab.c Thu Feb 27 13:04:29 2003 -+++ um/mm/slab.c Thu Feb 27 13:05:27 2003 -@@ -1946,10 +1946,14 @@ - - name = cachep->name; - { -+ mm_segment_t fs; - char tmp; -+ fs = get_fs(); -+ set_fs(KERNEL_DS); - if (__get_user(tmp, name)) - name = "broken"; -- } -+ set_fs(fs); -+ } - - seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u", - name, active_objs, num_objs, cachep->objsize, diff --git a/lustre/kernel_patches/patches/uml-patch-2.4.20-tmp.patch b/lustre/kernel_patches/patches/uml-patch-2.4.20-tmp.patch deleted file mode 100644 index e6245ef..0000000 --- a/lustre/kernel_patches/patches/uml-patch-2.4.20-tmp.patch +++ /dev/null @@ -1,16 +0,0 @@ - arch/um/kernel/process.c | 2 +- - 1 files changed, 1 insertion(+), 1 deletion(-) - ---- linux-2.4.20/arch/um/kernel/process.c~uml-patch-2.4.20-tmp 2003-04-15 11:13:26.000000000 +0800 -+++ linux-2.4.20-root/arch/um/kernel/process.c 2003-04-15 11:24:21.000000000 +0800 -@@ -72,7 +72,7 @@ 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); -+// (void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0); - signal(SIGHUP, SIG_IGN); - - init_irq_signals(altstack); - -_ diff --git a/lustre/kernel_patches/series/vanilla-2.4.20 b/lustre/kernel_patches/series/vanilla-2.4.20 index 5cc7604..ca0f7d0 100644 --- a/lustre/kernel_patches/series/vanilla-2.4.20 +++ b/lustre/kernel_patches/series/vanilla-2.4.20 @@ -1,4 +1,4 @@ -uml-patch-2.4.20-3.patch +uml-patch-2.4.20-4.patch dev_read_only_hp.patch exports_hp.patch kmem_cache_validate_hp.patch @@ -22,4 +22,3 @@ ext3-unmount_sync.patch ext3-use-after-free.patch extN-wantedi.patch extN-san.patch -uml-patch-2.4.20-tmp -- 1.8.3.1