aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig16
-rw-r--r--arch/um/Kconfig_i38612
-rw-r--r--arch/um/Kconfig_net2
-rw-r--r--arch/um/Kconfig_x86_6412
-rw-r--r--arch/um/Makefile35
-rw-r--r--arch/um/Makefile-i38632
-rw-r--r--arch/um/Makefile-x86_648
-rw-r--r--arch/um/defconfig58
-rw-r--r--arch/um/drivers/Makefile17
-rw-r--r--arch/um/drivers/cow.h4
-rw-r--r--arch/um/drivers/daemon_user.c6
-rw-r--r--arch/um/drivers/hostaudio_kern.c4
-rw-r--r--arch/um/drivers/line.c59
-rw-r--r--arch/um/drivers/mconsole_kern.c36
-rw-r--r--arch/um/drivers/net_kern.c32
-rw-r--r--arch/um/drivers/port_kern.c1
-rw-r--r--arch/um/drivers/ssl.c9
-rw-r--r--arch/um/drivers/stdio_console.c7
-rw-r--r--arch/um/drivers/ubd_kern.c37
-rw-r--r--arch/um/drivers/xterm_kern.c1
-rw-r--r--arch/um/include/line.h3
-rw-r--r--arch/um/include/mconsole_kern.h3
-rw-r--r--arch/um/include/mem.h1
-rw-r--r--arch/um/include/registers.h1
-rw-r--r--arch/um/include/sysdep-i386/ptrace_user.h13
-rw-r--r--arch/um/include/sysdep-i386/stub.h65
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace_user.h14
-rw-r--r--arch/um/include/sysdep-x86_64/stub.h58
-rw-r--r--arch/um/include/time_user.h3
-rw-r--r--arch/um/include/tlb.h30
-rw-r--r--arch/um/kernel/dyn.lds.S6
-rw-r--r--arch/um/kernel/helper.c14
-rw-r--r--arch/um/kernel/irq.c11
-rw-r--r--arch/um/kernel/irq_user.c2
-rw-r--r--arch/um/kernel/main.c1
-rw-r--r--arch/um/kernel/mem.c1
-rw-r--r--arch/um/kernel/physmem.c8
-rw-r--r--arch/um/kernel/process.c49
-rw-r--r--arch/um/kernel/process_kern.c14
-rw-r--r--arch/um/kernel/reboot.c15
-rw-r--r--arch/um/kernel/skas/Makefile9
-rw-r--r--arch/um/kernel/skas/clone.c44
-rw-r--r--arch/um/kernel/skas/exec_kern.c2
-rw-r--r--arch/um/kernel/skas/include/mm_id.h17
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h7
-rw-r--r--arch/um/kernel/skas/include/mode-skas.h1
-rw-r--r--arch/um/kernel/skas/include/skas.h16
-rw-r--r--arch/um/kernel/skas/include/stub-data.h18
-rw-r--r--arch/um/kernel/skas/mem.c6
-rw-r--r--arch/um/kernel/skas/mem_user.c225
-rw-r--r--arch/um/kernel/skas/mmu.c141
-rw-r--r--arch/um/kernel/skas/process.c216
-rw-r--r--arch/um/kernel/skas/process_kern.c46
-rw-r--r--arch/um/kernel/skas/syscall_user.c4
-rw-r--r--arch/um/kernel/skas/time.c30
-rw-r--r--arch/um/kernel/skas/tlb.c29
-rw-r--r--arch/um/kernel/syscall_kern.c19
-rw-r--r--arch/um/kernel/time.c36
-rw-r--r--arch/um/kernel/time_kern.c2
-rw-r--r--arch/um/kernel/tlb.c132
-rw-r--r--arch/um/kernel/tt/Makefile19
-rw-r--r--arch/um/kernel/tt/gdb.c4
-rw-r--r--arch/um/kernel/tt/gdb_kern.c2
-rw-r--r--arch/um/kernel/tt/include/debug.h17
-rw-r--r--arch/um/kernel/tt/include/mode-tt.h1
-rw-r--r--arch/um/kernel/tt/process_kern.c17
-rw-r--r--arch/um/kernel/tt/time.c28
-rw-r--r--arch/um/kernel/tt/tlb.c4
-rw-r--r--arch/um/kernel/tt/unmap.c31
-rw-r--r--arch/um/kernel/um_arch.c19
-rw-r--r--arch/um/kernel/uml.lds.S22
-rw-r--r--arch/um/os-Linux/elf_aux.c1
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c5
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c5
-rw-r--r--arch/um/scripts/Makefile.rules11
-rw-r--r--arch/um/scripts/Makefile.unmap22
-rw-r--r--arch/um/sys-i386/Makefile14
-rw-r--r--arch/um/sys-i386/ldt.c114
-rw-r--r--arch/um/sys-i386/signal.c2
-rw-r--r--arch/um/sys-i386/stub.S8
-rw-r--r--arch/um/sys-i386/stub_segv.c30
-rw-r--r--arch/um/sys-i386/syscalls.c23
-rw-r--r--arch/um/sys-i386/unmap.c25
-rw-r--r--arch/um/sys-x86_64/Makefile14
-rw-r--r--arch/um/sys-x86_64/signal.c2
-rw-r--r--arch/um/sys-x86_64/stub.S15
-rw-r--r--arch/um/sys-x86_64/stub_segv.c31
-rw-r--r--arch/um/sys-x86_64/syscalls.c23
-rw-r--r--arch/um/sys-x86_64/unmap.c25
89 files changed, 1536 insertions, 698 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c5292181a664..f945444df49c 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -35,6 +35,11 @@ config GENERIC_CALIBRATE_DELAY
35 bool 35 bool
36 default y 36 default y
37 37
38# Used in kernel/irq/manage.c and include/linux/irq.h
39config IRQ_RELEASE_METHOD
40 bool
41 default y
42
38menu "UML-specific options" 43menu "UML-specific options"
39 44
40config MODE_TT 45config MODE_TT
@@ -69,6 +74,7 @@ config MODE_SKAS
69 option will shrink the UML binary slightly. 74 option will shrink the UML binary slightly.
70 75
71source "arch/um/Kconfig_arch" 76source "arch/um/Kconfig_arch"
77source "mm/Kconfig"
72 78
73config LD_SCRIPT_STATIC 79config LD_SCRIPT_STATIC
74 bool 80 bool
@@ -122,7 +128,6 @@ config HOSTFS
122 128
123config HPPFS 129config HPPFS
124 tristate "HoneyPot ProcFS (EXPERIMENTAL)" 130 tristate "HoneyPot ProcFS (EXPERIMENTAL)"
125 depends on BROKEN
126 help 131 help
127 hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc 132 hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
128 entries to be overridden, removed, or fabricated from the host. 133 entries to be overridden, removed, or fabricated from the host.
@@ -135,8 +140,9 @@ config HPPFS
135 You only need this if you are setting up a UML honeypot. Otherwise, 140 You only need this if you are setting up a UML honeypot. Otherwise,
136 it is safe to say 'N' here. 141 it is safe to say 'N' here.
137 142
138 If you are actively using it, please ask for it to be fixed. In this 143 If you are actively using it, please report any problems, since it's
139 moment, it does not work on 2.6 (it works somehow on 2.4). 144 getting fixed. In this moment, it is experimental on 2.6 (it works on
145 2.4).
140 146
141config MCONSOLE 147config MCONSOLE
142 bool "Management console" 148 bool "Management console"
@@ -269,6 +275,8 @@ endmenu
269 275
270source "init/Kconfig" 276source "init/Kconfig"
271 277
278source "net/Kconfig"
279
272source "drivers/base/Kconfig" 280source "drivers/base/Kconfig"
273 281
274source "arch/um/Kconfig_char" 282source "arch/um/Kconfig_char"
@@ -281,7 +289,7 @@ config NETDEVICES
281 289
282source "arch/um/Kconfig_net" 290source "arch/um/Kconfig_net"
283 291
284source "net/Kconfig" 292source "drivers/net/Kconfig"
285 293
286source "fs/Kconfig" 294source "fs/Kconfig"
287 295
diff --git a/arch/um/Kconfig_i386 b/arch/um/Kconfig_i386
index e41f3748d30f..27c18a8d9d17 100644
--- a/arch/um/Kconfig_i386
+++ b/arch/um/Kconfig_i386
@@ -19,6 +19,18 @@ config 3_LEVEL_PGTABLES
19 memory. All the memory that can't be mapped directly will be treated 19 memory. All the memory that can't be mapped directly will be treated
20 as high memory. 20 as high memory.
21 21
22config STUB_CODE
23 hex
24 default 0xbfffe000
25
26config STUB_DATA
27 hex
28 default 0xbffff000
29
30config STUB_START
31 hex
32 default STUB_CODE
33
22config ARCH_HAS_SC_SIGNALS 34config ARCH_HAS_SC_SIGNALS
23 bool 35 bool
24 default y 36 default y
diff --git a/arch/um/Kconfig_net b/arch/um/Kconfig_net
index 1c2f9a70d91d..fa2ab2dd78b7 100644
--- a/arch/um/Kconfig_net
+++ b/arch/um/Kconfig_net
@@ -135,7 +135,7 @@ config UML_NET_MCAST
135 135
136config UML_NET_PCAP 136config UML_NET_PCAP
137 bool "pcap transport" 137 bool "pcap transport"
138 depends on UML_NET && BROKEN 138 depends on UML_NET && EXPERIMENTAL
139 help 139 help
140 The pcap transport makes a pcap packet stream on the host look 140 The pcap transport makes a pcap packet stream on the host look
141 like an ethernet device inside UML. This is useful for making 141 like an ethernet device inside UML. This is useful for making
diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64
index f162f50f0b17..735a047c890c 100644
--- a/arch/um/Kconfig_x86_64
+++ b/arch/um/Kconfig_x86_64
@@ -14,6 +14,18 @@ config 3_LEVEL_PGTABLES
14 bool 14 bool
15 default y 15 default y
16 16
17config STUB_CODE
18 hex
19 default 0x7fbfffe000
20
21config STUB_DATA
22 hex
23 default 0x7fbffff000
24
25config STUB_START
26 hex
27 default STUB_CODE
28
17config ARCH_HAS_SC_SIGNALS 29config ARCH_HAS_SC_SIGNALS
18 bool 30 bool
19 default n 31 default n
diff --git a/arch/um/Makefile b/arch/um/Makefile
index f2a0c40a9204..f5a83a72aa75 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -51,25 +51,26 @@ MRPROPER_DIRS += $(ARCH_DIR)/include2
51endif 51endif
52SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) 52SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
53 53
54include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) 54# -Dvmap=kernel_vmap affects everything, and prevents anything from
55# referencing the libpcap.o symbol so named.
56
57CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
58 $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap
55 59
56core-y += $(SUBARCH_CORE) 60USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
57libs-y += $(SUBARCH_LIBS) 61USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
62 $(MODE_INCLUDE)
58 63
59# -Derrno=kernel_errno - This turns all kernel references to errno into 64# -Derrno=kernel_errno - This turns all kernel references to errno into
60# kernel_errno to separate them from the libc errno. This allows -fno-common 65# kernel_errno to separate them from the libc errno. This allows -fno-common
61# in CFLAGS. Otherwise, it would cause ld to complain about the two different 66# in CFLAGS. Otherwise, it would cause ld to complain about the two different
62# errnos. 67# errnos.
63 68
64CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
65 $(ARCH_INCLUDE) $(MODE_INCLUDE)
66
67USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
68USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
69 $(MODE_INCLUDE) $(ARCH_USER_CFLAGS)
70CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask 69CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask
71CFLAGS += $(call cc-option,-fno-unit-at-a-time,) 70CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
72 71
72include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
73
73#This will adjust *FLAGS accordingly to the platform. 74#This will adjust *FLAGS accordingly to the platform.
74include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) 75include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
75 76
@@ -116,18 +117,19 @@ CONFIG_KERNEL_STACK_ORDER ?= 2
116STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) 117STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
117 118
118ifndef START 119ifndef START
119 START = $$(($(TOP_ADDR) - $(SIZE))) 120 START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] )
120endif 121endif
121 122
122CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \ 123CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \
123 -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ 124 -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
124 -DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE-y) \ 125 -DELF_FORMAT="$(ELF_FORMAT)" $(CPP_MODE-y) \
125 -DKERNEL_STACK_SIZE=$(STACK_SIZE)) 126 -DKERNEL_STACK_SIZE=$(STACK_SIZE) \
127 -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap_fin.o
126 128
127#The wrappers will select whether using "malloc" or the kernel allocator. 129#The wrappers will select whether using "malloc" or the kernel allocator.
128LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc 130LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
129 131
130CFLAGS_vmlinux = $(LINK-y) $(LINK_WRAPS) 132CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS)
131define cmd_vmlinux__ 133define cmd_vmlinux__
132 $(CC) $(CFLAGS_vmlinux) -o $@ \ 134 $(CC) $(CFLAGS_vmlinux) -o $@ \
133 -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \ 135 -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
@@ -140,7 +142,8 @@ endef
140#When cleaning we don't include .config, so we don't include 142#When cleaning we don't include .config, so we don't include
141#TT or skas makefiles and don't clean skas_ptregs.h. 143#TT or skas makefiles and don't clean skas_ptregs.h.
142CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ 144CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
143 $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h 145 $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h \
146 $(ARCH_DIR)/include/user_constants.h
144 147
145MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \ 148MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
146 $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os \ 149 $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os \
@@ -242,7 +245,7 @@ $(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h $(ARCH_DIR)/kernel-offsets.h FOR
242$(ARCH_DIR)/kernel/skas/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE 245$(ARCH_DIR)/kernel/skas/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
243 $(Q)$(MAKE) $(build)=$@ 246 $(Q)$(MAKE) $(build)=$@
244 247
245$(ARCH_DIR)/os-$(OS)/util: scripts_basic FORCE 248$(ARCH_DIR)/os-$(OS)/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
246 $(Q)$(MAKE) $(build)=$@ 249 $(Q)$(MAKE) $(build)=$@
247 250
248export SUBARCH USER_CFLAGS OS 251export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index 29e182d5a83a..a777e57dbf89 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -1,4 +1,4 @@
1SUBARCH_CORE := arch/um/sys-i386/ arch/i386/crypto/ 1core-y += arch/um/sys-i386/ arch/i386/crypto/
2 2
3TOP_ADDR := $(CONFIG_TOP_ADDR) 3TOP_ADDR := $(CONFIG_TOP_ADDR)
4 4
@@ -8,21 +8,33 @@ ifeq ($(CONFIG_MODE_SKAS),y)
8 endif 8 endif
9endif 9endif
10 10
11CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) 11LDFLAGS += -m elf_i386
12ARCH_USER_CFLAGS := 12ELF_ARCH := $(SUBARCH)
13ELF_FORMAT := elf32-$(SUBARCH)
14OBJCOPYFLAGS := -O binary -R .note -R .comment -S
15
16ifeq ("$(origin SUBARCH)", "command line")
17ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
18CFLAGS += $(call cc-option,-m32)
19USER_CFLAGS += $(call cc-option,-m32)
20HOSTCFLAGS += $(call cc-option,-m32)
21HOSTLDFLAGS += $(call cc-option,-m32)
22AFLAGS += $(call cc-option,-m32)
23LINK-y += $(call cc-option,-m32)
24UML_OBJCOPYFLAGS += -F $(ELF_FORMAT)
25
26export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
27endif
28endif
29
30CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) $(STUB_CFLAGS)
13 31
14ifneq ($(CONFIG_GPROF),y) 32ifneq ($(CONFIG_GPROF),y)
15ARCH_CFLAGS += -DUM_FASTCALL 33ARCH_CFLAGS += -DUM_FASTCALL
16endif 34endif
17 35
18ELF_ARCH := $(SUBARCH)
19ELF_FORMAT := elf32-$(SUBARCH)
20
21OBJCOPYFLAGS := -O binary -R .note -R .comment -S
22
23SYS_UTIL_DIR := $(ARCH_DIR)/sys-i386/util 36SYS_UTIL_DIR := $(ARCH_DIR)/sys-i386/util
24 37SYS_HEADERS := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
25SYS_HEADERS := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
26 38
27prepare: $(SYS_HEADERS) 39prepare: $(SYS_HEADERS)
28 40
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 32144562c279..aa2f7174ebca 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -1,11 +1,13 @@
1# Copyright 2003 - 2004 Pathscale, Inc 1# Copyright 2003 - 2004 Pathscale, Inc
2# Released under the GPL 2# Released under the GPL
3 3
4SUBARCH_LIBS := arch/um/sys-x86_64/ 4libs-y += arch/um/sys-x86_64/
5START := 0x60000000 5START := 0x60000000
6 6
7CFLAGS += -U__$(SUBARCH)__ -fno-builtin 7#We #undef __x86_64__ for kernelspace, not for userspace where
8ARCH_USER_CFLAGS := -D__x86_64__ 8#it's needed for headers to work!
9CFLAGS += -U__$(SUBARCH)__ -fno-builtin $(STUB_CFLAGS)
10USER_CFLAGS += -fno-builtin
9 11
10ELF_ARCH := i386:x86-64 12ELF_ARCH := i386:x86-64
11ELF_FORMAT := elf64-x86-64 13ELF_FORMAT := elf64-x86-64
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 4067c3aa5b60..80d30d19d750 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.12-rc3-skas3-v9-pre2 3# Linux kernel version: 2.6.12-rc6-mm1
4# Sun Apr 24 19:46:10 2005 4# Tue Jun 14 18:22:21 2005
5# 5#
6CONFIG_GENERIC_HARDIRQS=y 6CONFIG_GENERIC_HARDIRQS=y
7CONFIG_UML=y 7CONFIG_UML=y
@@ -13,23 +13,32 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
13# 13#
14# UML-specific options 14# UML-specific options
15# 15#
16CONFIG_MODE_TT=y 16# CONFIG_MODE_TT is not set
17# CONFIG_STATIC_LINK is not set
17CONFIG_MODE_SKAS=y 18CONFIG_MODE_SKAS=y
18CONFIG_UML_X86=y 19CONFIG_UML_X86=y
19# CONFIG_64BIT is not set 20# CONFIG_64BIT is not set
20CONFIG_TOP_ADDR=0xc0000000 21CONFIG_TOP_ADDR=0xc0000000
21# CONFIG_3_LEVEL_PGTABLES is not set 22# CONFIG_3_LEVEL_PGTABLES is not set
23CONFIG_STUB_CODE=0xbfffe000
24CONFIG_STUB_DATA=0xbffff000
25CONFIG_STUB_START=0xbfffe000
22CONFIG_ARCH_HAS_SC_SIGNALS=y 26CONFIG_ARCH_HAS_SC_SIGNALS=y
23CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y 27CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
24CONFIG_LD_SCRIPT_STATIC=y 28CONFIG_SELECT_MEMORY_MODEL=y
29CONFIG_FLATMEM_MANUAL=y
30# CONFIG_DISCONTIGMEM_MANUAL is not set
31# CONFIG_SPARSEMEM_MANUAL is not set
32CONFIG_FLATMEM=y
33CONFIG_FLAT_NODE_MEM_MAP=y
34CONFIG_LD_SCRIPT_DYN=y
25CONFIG_NET=y 35CONFIG_NET=y
26CONFIG_BINFMT_ELF=y 36CONFIG_BINFMT_ELF=y
27CONFIG_BINFMT_MISC=m 37CONFIG_BINFMT_MISC=m
28CONFIG_HOSTFS=y 38# CONFIG_HOSTFS is not set
29CONFIG_MCONSOLE=y 39CONFIG_MCONSOLE=y
30# CONFIG_MAGIC_SYSRQ is not set 40# CONFIG_MAGIC_SYSRQ is not set
31# CONFIG_HOST_2G_2G is not set 41# CONFIG_HOST_2G_2G is not set
32# CONFIG_SMP is not set
33CONFIG_NEST_LEVEL=0 42CONFIG_NEST_LEVEL=0
34CONFIG_KERNEL_HALF_GIGS=1 43CONFIG_KERNEL_HALF_GIGS=1
35# CONFIG_HIGHMEM is not set 44# CONFIG_HIGHMEM is not set
@@ -63,6 +72,8 @@ CONFIG_IKCONFIG_PROC=y
63CONFIG_KALLSYMS=y 72CONFIG_KALLSYMS=y
64# CONFIG_KALLSYMS_ALL is not set 73# CONFIG_KALLSYMS_ALL is not set
65CONFIG_KALLSYMS_EXTRA_PASS=y 74CONFIG_KALLSYMS_EXTRA_PASS=y
75CONFIG_PRINTK=y
76CONFIG_BUG=y
66CONFIG_BASE_FULL=y 77CONFIG_BASE_FULL=y
67CONFIG_FUTEX=y 78CONFIG_FUTEX=y
68CONFIG_EPOLL=y 79CONFIG_EPOLL=y
@@ -81,6 +92,7 @@ CONFIG_MODULES=y
81CONFIG_MODULE_UNLOAD=y 92CONFIG_MODULE_UNLOAD=y
82# CONFIG_MODULE_FORCE_UNLOAD is not set 93# CONFIG_MODULE_FORCE_UNLOAD is not set
83CONFIG_OBSOLETE_MODPARM=y 94CONFIG_OBSOLETE_MODPARM=y
95# CONFIG_MODVERSIONS is not set
84# CONFIG_MODULE_SRCVERSION_ALL is not set 96# CONFIG_MODULE_SRCVERSION_ALL is not set
85CONFIG_KMOD=y 97CONFIG_KMOD=y
86 98
@@ -115,6 +127,7 @@ CONFIG_UML_SOUND=m
115CONFIG_SOUND=m 127CONFIG_SOUND=m
116CONFIG_HOSTAUDIO=m 128CONFIG_HOSTAUDIO=m
117CONFIG_UML_RANDOM=y 129CONFIG_UML_RANDOM=y
130# CONFIG_MMAPPER is not set
118 131
119# 132#
120# Block devices 133# Block devices
@@ -176,6 +189,17 @@ CONFIG_INET=y
176# CONFIG_INET_TUNNEL is not set 189# CONFIG_INET_TUNNEL is not set
177CONFIG_IP_TCPDIAG=y 190CONFIG_IP_TCPDIAG=y
178# CONFIG_IP_TCPDIAG_IPV6 is not set 191# CONFIG_IP_TCPDIAG_IPV6 is not set
192
193#
194# TCP congestion control
195#
196CONFIG_TCP_CONG_BIC=y
197CONFIG_TCP_CONG_WESTWOOD=y
198CONFIG_TCP_CONG_HTCP=y
199# CONFIG_TCP_CONG_HSTCP is not set
200# CONFIG_TCP_CONG_HYBLA is not set
201# CONFIG_TCP_CONG_VEGAS is not set
202# CONFIG_TCP_CONG_SCALABLE is not set
179# CONFIG_IPV6 is not set 203# CONFIG_IPV6 is not set
180# CONFIG_NETFILTER is not set 204# CONFIG_NETFILTER is not set
181 205
@@ -206,11 +230,15 @@ CONFIG_IP_TCPDIAG=y
206# Network testing 230# Network testing
207# 231#
208# CONFIG_NET_PKTGEN is not set 232# CONFIG_NET_PKTGEN is not set
233# CONFIG_KGDBOE is not set
209# CONFIG_NETPOLL is not set 234# CONFIG_NETPOLL is not set
235# CONFIG_NETPOLL_RX is not set
236# CONFIG_NETPOLL_TRAP is not set
210# CONFIG_NET_POLL_CONTROLLER is not set 237# CONFIG_NET_POLL_CONTROLLER is not set
211# CONFIG_HAMRADIO is not set 238# CONFIG_HAMRADIO is not set
212# CONFIG_IRDA is not set 239# CONFIG_IRDA is not set
213# CONFIG_BT is not set 240# CONFIG_BT is not set
241# CONFIG_IEEE80211 is not set
214CONFIG_DUMMY=m 242CONFIG_DUMMY=m
215# CONFIG_BONDING is not set 243# CONFIG_BONDING is not set
216# CONFIG_EQUALIZER is not set 244# CONFIG_EQUALIZER is not set
@@ -227,6 +255,7 @@ CONFIG_PPP=m
227# CONFIG_PPP_SYNC_TTY is not set 255# CONFIG_PPP_SYNC_TTY is not set
228# CONFIG_PPP_DEFLATE is not set 256# CONFIG_PPP_DEFLATE is not set
229# CONFIG_PPP_BSDCOMP is not set 257# CONFIG_PPP_BSDCOMP is not set
258# CONFIG_PPP_MPPE is not set
230# CONFIG_PPPOE is not set 259# CONFIG_PPPOE is not set
231CONFIG_SLIP=m 260CONFIG_SLIP=m
232# CONFIG_SLIP_COMPRESSED is not set 261# CONFIG_SLIP_COMPRESSED is not set
@@ -240,10 +269,12 @@ CONFIG_SLIP=m
240# 269#
241CONFIG_EXT2_FS=y 270CONFIG_EXT2_FS=y
242# CONFIG_EXT2_FS_XATTR is not set 271# CONFIG_EXT2_FS_XATTR is not set
272# CONFIG_EXT2_FS_XIP is not set
243CONFIG_EXT3_FS=y 273CONFIG_EXT3_FS=y
244# CONFIG_EXT3_FS_XATTR is not set 274# CONFIG_EXT3_FS_XATTR is not set
245CONFIG_JBD=y 275CONFIG_JBD=y
246# CONFIG_JBD_DEBUG is not set 276# CONFIG_JBD_DEBUG is not set
277# CONFIG_REISER4_FS is not set
247CONFIG_REISERFS_FS=y 278CONFIG_REISERFS_FS=y
248# CONFIG_REISERFS_CHECK is not set 279# CONFIG_REISERFS_CHECK is not set
249# CONFIG_REISERFS_PROC_INFO is not set 280# CONFIG_REISERFS_PROC_INFO is not set
@@ -256,6 +287,7 @@ CONFIG_REISERFS_FS=y
256# CONFIG_XFS_FS is not set 287# CONFIG_XFS_FS is not set
257# CONFIG_MINIX_FS is not set 288# CONFIG_MINIX_FS is not set
258# CONFIG_ROMFS_FS is not set 289# CONFIG_ROMFS_FS is not set
290CONFIG_INOTIFY=y
259CONFIG_QUOTA=y 291CONFIG_QUOTA=y
260# CONFIG_QFMT_V1 is not set 292# CONFIG_QFMT_V1 is not set
261# CONFIG_QFMT_V2 is not set 293# CONFIG_QFMT_V2 is not set
@@ -265,6 +297,12 @@ CONFIG_AUTOFS_FS=m
265CONFIG_AUTOFS4_FS=m 297CONFIG_AUTOFS4_FS=m
266 298
267# 299#
300# Caches
301#
302# CONFIG_FSCACHE is not set
303# CONFIG_FUSE_FS is not set
304
305#
268# CD-ROM/DVD Filesystems 306# CD-ROM/DVD Filesystems
269# 307#
270CONFIG_ISO9660_FS=m 308CONFIG_ISO9660_FS=m
@@ -291,6 +329,8 @@ CONFIG_TMPFS=y
291# CONFIG_TMPFS_XATTR is not set 329# CONFIG_TMPFS_XATTR is not set
292# CONFIG_HUGETLB_PAGE is not set 330# CONFIG_HUGETLB_PAGE is not set
293CONFIG_RAMFS=y 331CONFIG_RAMFS=y
332# CONFIG_CONFIGFS_FS is not set
333# CONFIG_RELAYFS_FS is not set
294 334
295# 335#
296# Miscellaneous filesystems 336# Miscellaneous filesystems
@@ -319,6 +359,7 @@ CONFIG_RAMFS=y
319# CONFIG_NCP_FS is not set 359# CONFIG_NCP_FS is not set
320# CONFIG_CODA_FS is not set 360# CONFIG_CODA_FS is not set
321# CONFIG_AFS_FS is not set 361# CONFIG_AFS_FS is not set
362# CONFIG_9P_FS is not set
322 363
323# 364#
324# Partition Types 365# Partition Types
@@ -404,14 +445,15 @@ CONFIG_CRC32=m
404# CONFIG_PRINTK_TIME is not set 445# CONFIG_PRINTK_TIME is not set
405CONFIG_DEBUG_KERNEL=y 446CONFIG_DEBUG_KERNEL=y
406CONFIG_LOG_BUF_SHIFT=14 447CONFIG_LOG_BUF_SHIFT=14
448CONFIG_DETECT_SOFTLOCKUP=y
407# CONFIG_SCHEDSTATS is not set 449# CONFIG_SCHEDSTATS is not set
408# CONFIG_DEBUG_SLAB is not set 450CONFIG_DEBUG_SLAB=y
409# CONFIG_DEBUG_SPINLOCK is not set 451# CONFIG_DEBUG_SPINLOCK is not set
410# CONFIG_DEBUG_SPINLOCK_SLEEP is not set 452# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
411# CONFIG_DEBUG_KOBJECT is not set 453# CONFIG_DEBUG_KOBJECT is not set
412CONFIG_DEBUG_INFO=y 454CONFIG_DEBUG_INFO=y
413# CONFIG_DEBUG_FS is not set 455# CONFIG_DEBUG_FS is not set
414CONFIG_FRAME_POINTER=y 456CONFIG_FRAME_POINTER=y
415CONFIG_PT_PROXY=y 457# CONFIG_GPROF is not set
416# CONFIG_GCOV is not set 458# CONFIG_GCOV is not set
417# CONFIG_SYSCALL_DEBUG is not set 459# CONFIG_SYSCALL_DEBUG is not set
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index b2de9916c32c..d6c31a95b887 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -10,7 +10,6 @@ slip-objs := slip_kern.o slip_user.o
10slirp-objs := slirp_kern.o slirp_user.o 10slirp-objs := slirp_kern.o slirp_user.o
11daemon-objs := daemon_kern.o daemon_user.o 11daemon-objs := daemon_kern.o daemon_user.o
12mcast-objs := mcast_kern.o mcast_user.o 12mcast-objs := mcast_kern.o mcast_user.o
13#pcap-objs := pcap_kern.o pcap_user.o $(PCAP)
14net-objs := net_kern.o net_user.o 13net-objs := net_kern.o net_user.o
15mconsole-objs := mconsole_kern.o mconsole_user.o 14mconsole-objs := mconsole_kern.o mconsole_user.o
16hostaudio-objs := hostaudio_kern.o 15hostaudio-objs := hostaudio_kern.o
@@ -18,6 +17,17 @@ ubd-objs := ubd_kern.o ubd_user.o
18port-objs := port_kern.o port_user.o 17port-objs := port_kern.o port_user.o
19harddog-objs := harddog_kern.o harddog_user.o 18harddog-objs := harddog_kern.o harddog_user.o
20 19
20LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a)
21
22$(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o
23 $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o)
24#XXX: The call below does not work because the flags are added before the
25# object name, so nothing from the library gets linked.
26#$(call if_changed,ld)
27
28# When the above is fixed, don't forget to add this too!
29#targets := $(obj)/pcap.o
30
21obj-y := stdio_console.o fd.o chan_kern.o chan_user.o line.o 31obj-y := stdio_console.o fd.o chan_kern.o chan_user.o line.o
22obj-$(CONFIG_SSL) += ssl.o 32obj-$(CONFIG_SSL) += ssl.o
23obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o 33obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o
@@ -26,7 +36,7 @@ obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o
26obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o 36obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o
27obj-$(CONFIG_UML_NET_DAEMON) += daemon.o 37obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
28obj-$(CONFIG_UML_NET_MCAST) += mcast.o 38obj-$(CONFIG_UML_NET_MCAST) += mcast.o
29#obj-$(CONFIG_UML_NET_PCAP) += pcap.o $(PCAP) 39obj-$(CONFIG_UML_NET_PCAP) += pcap.o
30obj-$(CONFIG_UML_NET) += net.o 40obj-$(CONFIG_UML_NET) += net.o
31obj-$(CONFIG_MCONSOLE) += mconsole.o 41obj-$(CONFIG_MCONSOLE) += mconsole.o
32obj-$(CONFIG_MMAPPER) += mmapper_kern.o 42obj-$(CONFIG_MMAPPER) += mmapper_kern.o
@@ -41,6 +51,7 @@ obj-$(CONFIG_UML_WATCHDOG) += harddog.o
41obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o 51obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
42obj-$(CONFIG_UML_RANDOM) += random.o 52obj-$(CONFIG_UML_RANDOM) += random.o
43 53
44USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o 54# pcap_user.o must be added explicitly.
55USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o
45 56
46include arch/um/scripts/Makefile.rules 57include arch/um/scripts/Makefile.rules
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
index 4fcbe8b1b77e..4fcf3a8d13f4 100644
--- a/arch/um/drivers/cow.h
+++ b/arch/um/drivers/cow.h
@@ -3,10 +3,10 @@
3 3
4#include <asm/types.h> 4#include <asm/types.h>
5 5
6#if __BYTE_ORDER == __BIG_ENDIAN 6#if defined(__BIG_ENDIAN)
7# define ntohll(x) (x) 7# define ntohll(x) (x)
8# define htonll(x) (x) 8# define htonll(x) (x)
9#elif __BYTE_ORDER == __LITTLE_ENDIAN 9#elif defined(__LITTLE_ENDIAN)
10# define ntohll(x) bswap_64(x) 10# define ntohll(x) bswap_64(x)
11# define htonll(x) bswap_64(x) 11# define htonll(x) bswap_64(x)
12#else 12#else
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index cf15b4a8b517..c1b03f7c1daa 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -157,9 +157,9 @@ static void daemon_remove(void *data)
157 157
158 os_close_file(pri->fd); 158 os_close_file(pri->fd);
159 os_close_file(pri->control); 159 os_close_file(pri->control);
160 if(pri->data_addr != NULL) kfree(pri->data_addr); 160 kfree(pri->data_addr);
161 if(pri->ctl_addr != NULL) kfree(pri->ctl_addr); 161 kfree(pri->ctl_addr);
162 if(pri->local_addr != NULL) kfree(pri->local_addr); 162 kfree(pri->local_addr);
163} 163}
164 164
165int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) 165int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index d5742783e19d..59602b81b240 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -57,10 +57,10 @@ __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
57 57
58#else /*MODULE*/ 58#else /*MODULE*/
59 59
60MODULE_PARM(dsp, "s"); 60module_param(dsp, charp, 0644);
61MODULE_PARM_DESC(dsp, DSP_HELP); 61MODULE_PARM_DESC(dsp, DSP_HELP);
62 62
63MODULE_PARM(mixer, "s"); 63module_param(mixer, charp, 0644);
64MODULE_PARM_DESC(mixer, MIXER_HELP); 64MODULE_PARM_DESC(mixer, MIXER_HELP);
65 65
66#endif 66#endif
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 025d3be8aca4..e0fdffa2d542 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -406,14 +406,12 @@ void line_disable(struct tty_struct *tty, int current_irq)
406 if(line->driver->read_irq == current_irq) 406 if(line->driver->read_irq == current_irq)
407 free_irq_later(line->driver->read_irq, tty); 407 free_irq_later(line->driver->read_irq, tty);
408 else { 408 else {
409 free_irq_by_irq_and_dev(line->driver->read_irq, tty);
410 free_irq(line->driver->read_irq, tty); 409 free_irq(line->driver->read_irq, tty);
411 } 410 }
412 411
413 if(line->driver->write_irq == current_irq) 412 if(line->driver->write_irq == current_irq)
414 free_irq_later(line->driver->write_irq, tty); 413 free_irq_later(line->driver->write_irq, tty);
415 else { 414 else {
416 free_irq_by_irq_and_dev(line->driver->write_irq, tty);
417 free_irq(line->driver->write_irq, tty); 415 free_irq(line->driver->write_irq, tty);
418 } 416 }
419 417
@@ -604,11 +602,26 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
604 return n; 602 return n;
605} 603}
606 604
607int line_remove(struct line *lines, unsigned int num, char *str) 605int line_id(char **str, int *start_out, int *end_out)
606{
607 char *end;
608 int n;
609
610 n = simple_strtoul(*str, &end, 0);
611 if((*end != '\0') || (end == *str))
612 return -1;
613
614 *str = end;
615 *start_out = n;
616 *end_out = n;
617 return n;
618}
619
620int line_remove(struct line *lines, unsigned int num, int n)
608{ 621{
609 char config[sizeof("conxxxx=none\0")]; 622 char config[sizeof("conxxxx=none\0")];
610 623
611 sprintf(config, "%s=none", str); 624 sprintf(config, "%d=none", n);
612 return !line_setup(lines, num, config, 0); 625 return !line_setup(lines, num, config, 0);
613} 626}
614 627
@@ -650,11 +663,15 @@ struct tty_driver *line_register_devfs(struct lines *set,
650 return driver; 663 return driver;
651} 664}
652 665
666static spinlock_t winch_handler_lock;
667LIST_HEAD(winch_handlers);
668
653void lines_init(struct line *lines, int nlines) 669void lines_init(struct line *lines, int nlines)
654{ 670{
655 struct line *line; 671 struct line *line;
656 int i; 672 int i;
657 673
674 spin_lock_init(&winch_handler_lock);
658 for(i = 0; i < nlines; i++){ 675 for(i = 0; i < nlines; i++){
659 line = &lines[i]; 676 line = &lines[i];
660 INIT_LIST_HEAD(&line->chan_list); 677 INIT_LIST_HEAD(&line->chan_list);
@@ -711,31 +728,30 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
711 return IRQ_HANDLED; 728 return IRQ_HANDLED;
712} 729}
713 730
714DECLARE_MUTEX(winch_handler_sem);
715LIST_HEAD(winch_handlers);
716
717void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) 731void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
718{ 732{
719 struct winch *winch; 733 struct winch *winch;
720 734
721 down(&winch_handler_sem);
722 winch = kmalloc(sizeof(*winch), GFP_KERNEL); 735 winch = kmalloc(sizeof(*winch), GFP_KERNEL);
723 if (winch == NULL) { 736 if (winch == NULL) {
724 printk("register_winch_irq - kmalloc failed\n"); 737 printk("register_winch_irq - kmalloc failed\n");
725 goto out; 738 return;
726 } 739 }
740
727 *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), 741 *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list),
728 .fd = fd, 742 .fd = fd,
729 .tty_fd = tty_fd, 743 .tty_fd = tty_fd,
730 .pid = pid, 744 .pid = pid,
731 .tty = tty }); 745 .tty = tty });
746
747 spin_lock(&winch_handler_lock);
732 list_add(&winch->list, &winch_handlers); 748 list_add(&winch->list, &winch_handlers);
749 spin_unlock(&winch_handler_lock);
750
733 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 751 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
734 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 752 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
735 "winch", winch) < 0) 753 "winch", winch) < 0)
736 printk("register_winch_irq - failed to register IRQ\n"); 754 printk("register_winch_irq - failed to register IRQ\n");
737 out:
738 up(&winch_handler_sem);
739} 755}
740 756
741static void unregister_winch(struct tty_struct *tty) 757static void unregister_winch(struct tty_struct *tty)
@@ -743,7 +759,7 @@ static void unregister_winch(struct tty_struct *tty)
743 struct list_head *ele; 759 struct list_head *ele;
744 struct winch *winch, *found = NULL; 760 struct winch *winch, *found = NULL;
745 761
746 down(&winch_handler_sem); 762 spin_lock(&winch_handler_lock);
747 list_for_each(ele, &winch_handlers){ 763 list_for_each(ele, &winch_handlers){
748 winch = list_entry(ele, struct winch, list); 764 winch = list_entry(ele, struct winch, list);
749 if(winch->tty == tty){ 765 if(winch->tty == tty){
@@ -751,21 +767,25 @@ static void unregister_winch(struct tty_struct *tty)
751 break; 767 break;
752 } 768 }
753 } 769 }
754
755 if(found == NULL) 770 if(found == NULL)
756 goto out; 771 goto err;
772
773 list_del(&winch->list);
774 spin_unlock(&winch_handler_lock);
757 775
758 if(winch->pid != -1) 776 if(winch->pid != -1)
759 os_kill_process(winch->pid, 1); 777 os_kill_process(winch->pid, 1);
760 778
761 free_irq_by_irq_and_dev(WINCH_IRQ, winch);
762 free_irq(WINCH_IRQ, winch); 779 free_irq(WINCH_IRQ, winch);
763 list_del(&winch->list);
764 kfree(winch); 780 kfree(winch);
765 out: 781
766 up(&winch_handler_sem); 782 return;
783err:
784 spin_unlock(&winch_handler_lock);
767} 785}
768 786
787/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup
788 * order... are we sure that nothing else is done on the list? */
769static void winch_cleanup(void) 789static void winch_cleanup(void)
770{ 790{
771 struct list_head *ele; 791 struct list_head *ele;
@@ -774,6 +794,9 @@ static void winch_cleanup(void)
774 list_for_each(ele, &winch_handlers){ 794 list_for_each(ele, &winch_handlers){
775 winch = list_entry(ele, struct winch, list); 795 winch = list_entry(ele, struct winch, list);
776 if(winch->fd != -1){ 796 if(winch->fd != -1){
797 /* Why is this different from the above free_irq(),
798 * which deactivates SIGIO? This searches the FD
799 * somewhere else and removes it from the list... */
777 deactivate_fd(winch->fd, WINCH_IRQ); 800 deactivate_fd(winch->fd, WINCH_IRQ);
778 os_close_file(winch->fd); 801 os_close_file(winch->fd);
779 } 802 }
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index d7c7adcc0a67..404de41a4f67 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -419,8 +419,9 @@ void mconsole_config(struct mc_request *req)
419void mconsole_remove(struct mc_request *req) 419void mconsole_remove(struct mc_request *req)
420{ 420{
421 struct mc_device *dev; 421 struct mc_device *dev;
422 char *ptr = req->request.data; 422 char *ptr = req->request.data, *err_msg = "";
423 int err; 423 char error[256];
424 int err, start, end, n;
424 425
425 ptr += strlen("remove"); 426 ptr += strlen("remove");
426 while(isspace(*ptr)) ptr++; 427 while(isspace(*ptr)) ptr++;
@@ -429,8 +430,35 @@ void mconsole_remove(struct mc_request *req)
429 mconsole_reply(req, "Bad remove option", 1, 0); 430 mconsole_reply(req, "Bad remove option", 1, 0);
430 return; 431 return;
431 } 432 }
432 err = (*dev->remove)(&ptr[strlen(dev->name)]); 433
433 mconsole_reply(req, "", err, 0); 434 ptr = &ptr[strlen(dev->name)];
435
436 err = 1;
437 n = (*dev->id)(&ptr, &start, &end);
438 if(n < 0){
439 err_msg = "Couldn't parse device number";
440 goto out;
441 }
442 else if((n < start) || (n > end)){
443 sprintf(error, "Invalid device number - must be between "
444 "%d and %d", start, end);
445 err_msg = error;
446 goto out;
447 }
448
449 err = (*dev->remove)(n);
450 switch(err){
451 case -ENODEV:
452 err_msg = "Device doesn't exist";
453 break;
454 case -EBUSY:
455 err_msg = "Device is currently open";
456 break;
457 default:
458 break;
459 }
460 out:
461 mconsole_reply(req, err_msg, err, 0);
434} 462}
435 463
436#ifdef CONFIG_MAGIC_SYSRQ 464#ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 4eeaf88c1e97..1495007bf6c0 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -146,7 +146,6 @@ static int uml_net_close(struct net_device *dev)
146 netif_stop_queue(dev); 146 netif_stop_queue(dev);
147 spin_lock(&lp->lock); 147 spin_lock(&lp->lock);
148 148
149 free_irq_by_irq_and_dev(dev->irq, dev);
150 free_irq(dev->irq, dev); 149 free_irq(dev->irq, dev);
151 if(lp->close != NULL) 150 if(lp->close != NULL)
152 (*lp->close)(lp->fd, &lp->user); 151 (*lp->close)(lp->fd, &lp->user);
@@ -613,25 +612,35 @@ static int net_config(char *str)
613 return(err); 612 return(err);
614} 613}
615 614
616static int net_remove(char *str) 615static int net_id(char **str, int *start_out, int *end_out)
616{
617 char *end;
618 int n;
619
620 n = simple_strtoul(*str, &end, 0);
621 if((*end != '\0') || (end == *str))
622 return -1;
623
624 *start_out = n;
625 *end_out = n;
626 *str = end;
627 return n;
628}
629
630static int net_remove(int n)
617{ 631{
618 struct uml_net *device; 632 struct uml_net *device;
619 struct net_device *dev; 633 struct net_device *dev;
620 struct uml_net_private *lp; 634 struct uml_net_private *lp;
621 char *end;
622 int n;
623
624 n = simple_strtoul(str, &end, 0);
625 if((*end != '\0') || (end == str))
626 return(-1);
627 635
628 device = find_device(n); 636 device = find_device(n);
629 if(device == NULL) 637 if(device == NULL)
630 return(0); 638 return -ENODEV;
631 639
632 dev = device->dev; 640 dev = device->dev;
633 lp = dev->priv; 641 lp = dev->priv;
634 if(lp->fd > 0) return(-1); 642 if(lp->fd > 0)
643 return -EBUSY;
635 if(lp->remove != NULL) (*lp->remove)(&lp->user); 644 if(lp->remove != NULL) (*lp->remove)(&lp->user);
636 unregister_netdev(dev); 645 unregister_netdev(dev);
637 platform_device_unregister(&device->pdev); 646 platform_device_unregister(&device->pdev);
@@ -639,13 +648,14 @@ static int net_remove(char *str)
639 list_del(&device->list); 648 list_del(&device->list);
640 kfree(device); 649 kfree(device);
641 free_netdev(dev); 650 free_netdev(dev);
642 return(0); 651 return 0;
643} 652}
644 653
645static struct mc_device net_mc = { 654static struct mc_device net_mc = {
646 .name = "eth", 655 .name = "eth",
647 .config = net_config, 656 .config = net_config,
648 .get_config = NULL, 657 .get_config = NULL,
658 .id = net_id,
649 .remove = net_remove, 659 .remove = net_remove,
650}; 660};
651 661
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index b5ee07472f79..c41efd207fcc 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -257,7 +257,6 @@ int port_wait(void *data)
257 * connection. Then we loop here throwing out failed 257 * connection. Then we loop here throwing out failed
258 * connections until a good one is found. 258 * connections until a good one is found.
259 */ 259 */
260 free_irq_by_irq_and_dev(TELNETD_IRQ, conn);
261 free_irq(TELNETD_IRQ, conn); 260 free_irq(TELNETD_IRQ, conn);
262 261
263 if(conn->fd >= 0) break; 262 if(conn->fd >= 0) break;
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index b32a77010fbe..62e04ecfada8 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -49,7 +49,7 @@ static struct chan_opts opts = {
49 49
50static int ssl_config(char *str); 50static int ssl_config(char *str);
51static int ssl_get_config(char *dev, char *str, int size, char **error_out); 51static int ssl_get_config(char *dev, char *str, int size, char **error_out);
52static int ssl_remove(char *str); 52static int ssl_remove(int n);
53 53
54static struct line_driver driver = { 54static struct line_driver driver = {
55 .name = "UML serial line", 55 .name = "UML serial line",
@@ -69,6 +69,7 @@ static struct line_driver driver = {
69 .name = "ssl", 69 .name = "ssl",
70 .config = ssl_config, 70 .config = ssl_config,
71 .get_config = ssl_get_config, 71 .get_config = ssl_get_config,
72 .id = line_id,
72 .remove = ssl_remove, 73 .remove = ssl_remove,
73 }, 74 },
74}; 75};
@@ -94,10 +95,10 @@ static int ssl_get_config(char *dev, char *str, int size, char **error_out)
94 str, size, error_out)); 95 str, size, error_out));
95} 96}
96 97
97static int ssl_remove(char *str) 98static int ssl_remove(int n)
98{ 99{
99 return(line_remove(serial_lines, 100 return line_remove(serial_lines,
100 sizeof(serial_lines)/sizeof(serial_lines[0]), str)); 101 sizeof(serial_lines)/sizeof(serial_lines[0]), n);
101} 102}
102 103
103int ssl_open(struct tty_struct *tty, struct file *filp) 104int ssl_open(struct tty_struct *tty, struct file *filp)
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index afbe1e71ed83..005aa6333b6e 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -55,7 +55,7 @@ static struct chan_opts opts = {
55 55
56static int con_config(char *str); 56static int con_config(char *str);
57static int con_get_config(char *dev, char *str, int size, char **error_out); 57static int con_get_config(char *dev, char *str, int size, char **error_out);
58static int con_remove(char *str); 58static int con_remove(int n);
59 59
60static struct line_driver driver = { 60static struct line_driver driver = {
61 .name = "UML console", 61 .name = "UML console",
@@ -75,6 +75,7 @@ static struct line_driver driver = {
75 .name = "con", 75 .name = "con",
76 .config = con_config, 76 .config = con_config,
77 .get_config = con_get_config, 77 .get_config = con_get_config,
78 .id = line_id,
78 .remove = con_remove, 79 .remove = con_remove,
79 }, 80 },
80}; 81};
@@ -99,9 +100,9 @@ static int con_get_config(char *dev, char *str, int size, char **error_out)
99 size, error_out)); 100 size, error_out));
100} 101}
101 102
102static int con_remove(char *str) 103static int con_remove(int n)
103{ 104{
104 return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str)); 105 return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n);
105} 106}
106 107
107static int con_open(struct tty_struct *tty, struct file *filp) 108static int con_open(struct tty_struct *tty, struct file *filp)
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 2a7f6892c55c..344b24d09a7c 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -754,24 +754,34 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
754 return(len); 754 return(len);
755} 755}
756 756
757static int ubd_remove(char *str) 757static int ubd_id(char **str, int *start_out, int *end_out)
758{
759 int n;
760
761 n = parse_unit(str);
762 *start_out = 0;
763 *end_out = MAX_DEV - 1;
764 return n;
765}
766
767static int ubd_remove(int n)
758{ 768{
759 struct ubd *dev; 769 struct ubd *dev;
760 int n, err = -ENODEV; 770 int err = -ENODEV;
761 771
762 n = parse_unit(&str); 772 spin_lock(&ubd_lock);
763 773
764 if((n < 0) || (n >= MAX_DEV)) 774 if(ubd_gendisk[n] == NULL)
765 return(err); 775 goto out;
766 776
767 dev = &ubd_dev[n]; 777 dev = &ubd_dev[n];
768 if(dev->count > 0)
769 return(-EBUSY); /* you cannot remove a open disk */
770 778
771 err = 0; 779 if(dev->file == NULL)
772 spin_lock(&ubd_lock); 780 goto out;
773 781
774 if(ubd_gendisk[n] == NULL) 782 /* you cannot remove a open disk */
783 err = -EBUSY;
784 if(dev->count > 0)
775 goto out; 785 goto out;
776 786
777 del_gendisk(ubd_gendisk[n]); 787 del_gendisk(ubd_gendisk[n]);
@@ -787,15 +797,16 @@ static int ubd_remove(char *str)
787 platform_device_unregister(&dev->pdev); 797 platform_device_unregister(&dev->pdev);
788 *dev = ((struct ubd) DEFAULT_UBD); 798 *dev = ((struct ubd) DEFAULT_UBD);
789 err = 0; 799 err = 0;
790 out: 800out:
791 spin_unlock(&ubd_lock); 801 spin_unlock(&ubd_lock);
792 return(err); 802 return err;
793} 803}
794 804
795static struct mc_device ubd_mc = { 805static struct mc_device ubd_mc = {
796 .name = "ubd", 806 .name = "ubd",
797 .config = ubd_config, 807 .config = ubd_config,
798 .get_config = ubd_get_config, 808 .get_config = ubd_get_config,
809 .id = ubd_id,
799 .remove = ubd_remove, 810 .remove = ubd_remove,
800}; 811};
801 812
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index a4fdf3584ad2..d269a80f4b0c 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -69,7 +69,6 @@ int xterm_fd(int socket, int *pid_out)
69 * isn't set) this will hang... */ 69 * isn't set) this will hang... */
70 wait_for_completion(&data->ready); 70 wait_for_completion(&data->ready);
71 71
72 free_irq_by_irq_and_dev(XTERM_IRQ, data);
73 free_irq(XTERM_IRQ, data); 72 free_irq(XTERM_IRQ, data);
74 73
75 ret = data->new_fd; 74 ret = data->new_fd;
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 4c5e92c04ccb..5323d22a6ca7 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -101,7 +101,8 @@ extern void lines_init(struct line *lines, int nlines);
101extern void close_lines(struct line *lines, int nlines); 101extern void close_lines(struct line *lines, int nlines);
102 102
103extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str); 103extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str);
104extern int line_remove(struct line *lines, unsigned int sizeof_lines, char *str); 104extern int line_id(char **str, int *start_out, int *end_out);
105extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
105extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str, 106extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
106 int size, char **error_out); 107 int size, char **error_out);
107 108
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index 61c274fcee5d..d86ee14260ce 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -20,7 +20,8 @@ struct mc_device {
20 char *name; 20 char *name;
21 int (*config)(char *); 21 int (*config)(char *);
22 int (*get_config)(char *, char *, int, char **); 22 int (*get_config)(char *, char *, int, char **);
23 int (*remove)(char *); 23 int (*id)(char **, int *, int *);
24 int (*remove)(int);
24}; 25};
25 26
26#define CONFIG_CHUNK(str, size, current, chunk, end) \ 27#define CONFIG_CHUNK(str, size, current, chunk, end) \
diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h
index 10c46c38949a..99d3ad4a03e5 100644
--- a/arch/um/include/mem.h
+++ b/arch/um/include/mem.h
@@ -13,6 +13,7 @@ extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
13extern int is_remapped(void *virt); 13extern int is_remapped(void *virt);
14extern int physmem_remove_mapping(void *virt); 14extern int physmem_remove_mapping(void *virt);
15extern void physmem_forget_descriptor(int fd); 15extern void physmem_forget_descriptor(int fd);
16extern unsigned long to_phys(void *virt);
16 17
17#endif 18#endif
18 19
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 8744abb5224f..0a35e6d0baa0 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -14,6 +14,7 @@ extern int restore_fp_registers(int pid, unsigned long *fp_regs);
14extern void save_registers(int pid, union uml_pt_regs *regs); 14extern void save_registers(int pid, union uml_pt_regs *regs);
15extern void restore_registers(int pid, union uml_pt_regs *regs); 15extern void restore_registers(int pid, union uml_pt_regs *regs);
16extern void init_registers(int pid); 16extern void init_registers(int pid);
17extern void get_safe_registers(unsigned long * regs);
17 18
18#endif 19#endif
19 20
diff --git a/arch/um/include/sysdep-i386/ptrace_user.h b/arch/um/include/sysdep-i386/ptrace_user.h
index eca8066e7a43..899aa4b2a78d 100644
--- a/arch/um/include/sysdep-i386/ptrace_user.h
+++ b/arch/um/include/sysdep-i386/ptrace_user.h
@@ -20,11 +20,24 @@
20#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX) 20#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX)
21#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI) 21#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI)
22#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI) 22#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI)
23#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP)
23 24
24#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX) 25#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX)
25 26
27#define REGS_SYSCALL_NR EAX /* This is used before a system call */
28#define REGS_SYSCALL_ARG1 EBX
29#define REGS_SYSCALL_ARG2 ECX
30#define REGS_SYSCALL_ARG3 EDX
31#define REGS_SYSCALL_ARG4 ESI
32#define REGS_SYSCALL_ARG5 EDI
33#define REGS_SYSCALL_ARG6 EBP
34
35#define REGS_IP_INDEX EIP
36#define REGS_SP_INDEX UESP
37
26#define PT_IP_OFFSET PT_OFFSET(EIP) 38#define PT_IP_OFFSET PT_OFFSET(EIP)
27#define PT_IP(regs) ((regs)[EIP]) 39#define PT_IP(regs) ((regs)[EIP])
40#define PT_SP_OFFSET PT_OFFSET(UESP)
28#define PT_SP(regs) ((regs)[UESP]) 41#define PT_SP(regs) ((regs)[UESP])
29 42
30#ifndef FRAME_SIZE 43#ifndef FRAME_SIZE
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h
new file mode 100644
index 000000000000..d3699fe1c613
--- /dev/null
+++ b/arch/um/include/sysdep-i386/stub.h
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SYSDEP_STUB_H
7#define __SYSDEP_STUB_H
8
9#include <asm/ptrace.h>
10#include <asm/unistd.h>
11
12extern void stub_segv_handler(int sig);
13extern void stub_clone_handler(void);
14
15#define STUB_SYSCALL_RET EAX
16#define STUB_MMAP_NR __NR_mmap2
17#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)
18
19static inline long stub_syscall2(long syscall, long arg1, long arg2)
20{
21 long ret;
22
23 __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
24 __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
25 __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
26 __asm__("int $0x80;" : : : "%eax");
27 __asm__ __volatile__("movl %%eax, %0; " : "=g" (ret) :);
28 return(ret);
29}
30
31static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
32{
33 __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
34 return(stub_syscall2(syscall, arg1, arg2));
35}
36
37static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
38 long arg4)
39{
40 __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
41 return(stub_syscall3(syscall, arg1, arg2, arg3));
42}
43
44static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
45 long arg4, long arg5, long arg6)
46{
47 long ret;
48 __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
49 __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
50 __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
51 __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
52 __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
53 __asm__("movl %0, %%edi; " : : "g" (arg5) : "%edi");
54 __asm__ __volatile__("pushl %%ebp ; movl %1, %%ebp; "
55 "int $0x80; popl %%ebp ; "
56 "movl %%eax, %0; " : "=g" (ret) : "g" (arg6) : "%eax");
57 return(ret);
58}
59
60static inline void trap_myself(void)
61{
62 __asm("int3");
63}
64
65#endif
diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h
index 31729973fb14..128faf027364 100644
--- a/arch/um/include/sysdep-x86_64/ptrace_user.h
+++ b/arch/um/include/sysdep-x86_64/ptrace_user.h
@@ -55,6 +55,20 @@
55#define PTRACE_OLDSETOPTIONS 21 55#define PTRACE_OLDSETOPTIONS 21
56#endif 56#endif
57 57
58/* These are before the system call, so the the system call number is RAX
59 * rather than ORIG_RAX, and arg4 is R10 rather than RCX
60 */
61#define REGS_SYSCALL_NR PT_INDEX(RAX)
62#define REGS_SYSCALL_ARG1 PT_INDEX(RDI)
63#define REGS_SYSCALL_ARG2 PT_INDEX(RSI)
64#define REGS_SYSCALL_ARG3 PT_INDEX(RDX)
65#define REGS_SYSCALL_ARG4 PT_INDEX(R10)
66#define REGS_SYSCALL_ARG5 PT_INDEX(R8)
67#define REGS_SYSCALL_ARG6 PT_INDEX(R9)
68
69#define REGS_IP_INDEX PT_INDEX(RIP)
70#define REGS_SP_INDEX PT_INDEX(RSP)
71
58#endif 72#endif
59 73
60/* 74/*
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h
new file mode 100644
index 000000000000..f599058d8263
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/stub.h
@@ -0,0 +1,58 @@
1/*
2 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SYSDEP_STUB_H
7#define __SYSDEP_STUB_H
8
9#include <asm/ptrace.h>
10#include <asm/unistd.h>
11#include <sysdep/ptrace_user.h>
12
13extern void stub_segv_handler(int sig);
14extern void stub_clone_handler(void);
15
16#define STUB_SYSCALL_RET PT_INDEX(RAX)
17#define STUB_MMAP_NR __NR_mmap
18#define MMAP_OFFSET(o) (o)
19
20static inline long stub_syscall2(long syscall, long arg1, long arg2)
21{
22 long ret;
23
24 __asm__("movq %0, %%rsi; " : : "g" (arg2) : "%rsi");
25 __asm__("movq %0, %%rdi; " : : "g" (arg1) : "%rdi");
26 __asm__("movq %0, %%rax; " : : "g" (syscall) : "%rax");
27 __asm__("syscall;" : : : "%rax", "%r11", "%rcx");
28 __asm__ __volatile__("movq %%rax, %0; " : "=g" (ret) :);
29 return(ret);
30}
31
32static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
33{
34 __asm__("movq %0, %%rdx; " : : "g" (arg3) : "%rdx");
35 return(stub_syscall2(syscall, arg1, arg2));
36}
37
38static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
39 long arg4)
40{
41 __asm__("movq %0, %%r10; " : : "g" (arg4) : "%r10");
42 return(stub_syscall3(syscall, arg1, arg2, arg3));
43}
44
45static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
46 long arg4, long arg5, long arg6)
47{
48 __asm__("movq %0, %%r9; " : : "g" (arg6) : "%r9");
49 __asm__("movq %0, %%r8; " : : "g" (arg5) : "%r8");
50 return(stub_syscall4(syscall, arg1, arg2, arg3, arg4));
51}
52
53static inline void trap_myself(void)
54{
55 __asm("int3");
56}
57
58#endif
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
index 6793a2fcd0ae..17d7ef2141f4 100644
--- a/arch/um/include/time_user.h
+++ b/arch/um/include/time_user.h
@@ -8,11 +8,12 @@
8 8
9extern void timer(void); 9extern void timer(void);
10extern void switch_timers(int to_real); 10extern void switch_timers(int to_real);
11extern void set_interval(int timer_type);
12extern void idle_sleep(int secs); 11extern void idle_sleep(int secs);
13extern void enable_timer(void); 12extern void enable_timer(void);
13extern void prepare_timer(void * ptr);
14extern void disable_timer(void); 14extern void disable_timer(void);
15extern unsigned long time_lock(void); 15extern unsigned long time_lock(void);
16extern void time_unlock(unsigned long); 16extern void time_unlock(unsigned long);
17extern void user_time_init(void);
17 18
18#endif 19#endif
diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h
index da1097285b8c..c6f9628f39bf 100644
--- a/arch/um/include/tlb.h
+++ b/arch/um/include/tlb.h
@@ -37,31 +37,25 @@ struct host_vm_op {
37extern void mprotect_kernel_vm(int w); 37extern void mprotect_kernel_vm(int w);
38extern void force_flush_all(void); 38extern void force_flush_all(void);
39extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr, 39extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
40 unsigned long end_addr, int force, int data, 40 unsigned long end_addr, int force,
41 void (*do_ops)(int, struct host_vm_op *, int)); 41 void (*do_ops)(union mm_context *,
42 struct host_vm_op *, int));
42extern int flush_tlb_kernel_range_common(unsigned long start, 43extern int flush_tlb_kernel_range_common(unsigned long start,
43 unsigned long end); 44 unsigned long end);
44 45
45extern int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, 46extern int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
46 int r, int w, int x, struct host_vm_op *ops, int index, 47 int r, int w, int x, struct host_vm_op *ops, int index,
47 int last_filled, int data, 48 int last_filled, union mm_context *mmu,
48 void (*do_ops)(int, struct host_vm_op *, int)); 49 void (*do_ops)(union mm_context *, struct host_vm_op *,
50 int));
49extern int add_munmap(unsigned long addr, unsigned long len, 51extern int add_munmap(unsigned long addr, unsigned long len,
50 struct host_vm_op *ops, int index, int last_filled, 52 struct host_vm_op *ops, int index, int last_filled,
51 int data, void (*do_ops)(int, struct host_vm_op *, int)); 53 union mm_context *mmu,
54 void (*do_ops)(union mm_context *, struct host_vm_op *,
55 int));
52extern int add_mprotect(unsigned long addr, unsigned long len, int r, int w, 56extern int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
53 int x, struct host_vm_op *ops, int index, 57 int x, struct host_vm_op *ops, int index,
54 int last_filled, int data, 58 int last_filled, union mm_context *mmu,
55 void (*do_ops)(int, struct host_vm_op *, int)); 59 void (*do_ops)(union mm_context *, struct host_vm_op *,
60 int));
56#endif 61#endif
57
58/*
59 * Overrides for Emacs so that we follow Linus's tabbing style.
60 * Emacs will notice this stuff at the end of the file and automatically
61 * adjust the settings for this buffer only. This must remain at the end
62 * of the file.
63 * ---------------------------------------------------------------------------
64 * Local variables:
65 * c-file-style: "linux"
66 * End:
67 */
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 715b0838a68c..3942a5f245de 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -67,6 +67,12 @@ SECTIONS
67 *(.stub .text.* .gnu.linkonce.t.*) 67 *(.stub .text.* .gnu.linkonce.t.*)
68 /* .gnu.warning sections are handled specially by elf32.em. */ 68 /* .gnu.warning sections are handled specially by elf32.em. */
69 *(.gnu.warning) 69 *(.gnu.warning)
70
71 . = ALIGN(4096);
72 __syscall_stub_start = .;
73 *(.__syscall_stub*)
74 __syscall_stub_end = .;
75 . = ALIGN(4096);
70 } =0x90909090 76 } =0x90909090
71 .fini : { 77 .fini : {
72 KEEP (*(.fini)) 78 KEEP (*(.fini))
diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c
index 13b1f5c2f7ee..f83e1e8e2392 100644
--- a/arch/um/kernel/helper.c
+++ b/arch/um/kernel/helper.c
@@ -13,6 +13,7 @@
13#include "user.h" 13#include "user.h"
14#include "kern_util.h" 14#include "kern_util.h"
15#include "user_util.h" 15#include "user_util.h"
16#include "helper.h"
16#include "os.h" 17#include "os.h"
17 18
18struct helper_data { 19struct helper_data {
@@ -149,7 +150,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
149 return(pid); 150 return(pid);
150} 151}
151 152
152int helper_wait(int pid, int block) 153int helper_wait(int pid)
153{ 154{
154 int ret; 155 int ret;
155 156
@@ -160,14 +161,3 @@ int helper_wait(int pid, int block)
160 } 161 }
161 return(ret); 162 return(ret);
162} 163}
163
164/*
165 * Overrides for Emacs so that we follow Linus's tabbing style.
166 * Emacs will notice this stuff at the end of the file and automatically
167 * adjust the settings for this buffer only. This must remain at the end
168 * of the file.
169 * ---------------------------------------------------------------------------
170 * Local variables:
171 * c-file-style: "linux"
172 * End:
173 */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index d44fb5282547..9f18061ef4c9 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -124,14 +124,16 @@ void irq_unlock(unsigned long flags)
124 spin_unlock_irqrestore(&irq_spinlock, flags); 124 spin_unlock_irqrestore(&irq_spinlock, flags);
125} 125}
126 126
127/* presently hw_interrupt_type must define (startup || enable) && 127/* hw_interrupt_type must define (startup || enable) &&
128 * disable && end */ 128 * (shutdown || disable) && end */
129static void dummy(unsigned int irq) 129static void dummy(unsigned int irq)
130{ 130{
131} 131}
132 132
133static struct hw_interrupt_type SIGIO_irq_type = { 133/* This is used for everything else than the timer. */
134static struct hw_interrupt_type normal_irq_type = {
134 .typename = "SIGIO", 135 .typename = "SIGIO",
136 .release = free_irq_by_irq_and_dev,
135 .disable = dummy, 137 .disable = dummy,
136 .enable = dummy, 138 .enable = dummy,
137 .ack = dummy, 139 .ack = dummy,
@@ -140,6 +142,7 @@ static struct hw_interrupt_type SIGIO_irq_type = {
140 142
141static struct hw_interrupt_type SIGVTALRM_irq_type = { 143static struct hw_interrupt_type SIGVTALRM_irq_type = {
142 .typename = "SIGVTALRM", 144 .typename = "SIGVTALRM",
145 .release = free_irq_by_irq_and_dev,
143 .shutdown = dummy, /* never called */ 146 .shutdown = dummy, /* never called */
144 .disable = dummy, 147 .disable = dummy,
145 .enable = dummy, 148 .enable = dummy,
@@ -160,7 +163,7 @@ void __init init_IRQ(void)
160 irq_desc[i].status = IRQ_DISABLED; 163 irq_desc[i].status = IRQ_DISABLED;
161 irq_desc[i].action = NULL; 164 irq_desc[i].action = NULL;
162 irq_desc[i].depth = 1; 165 irq_desc[i].depth = 1;
163 irq_desc[i].handler = &SIGIO_irq_type; 166 irq_desc[i].handler = &normal_irq_type;
164 enable_irq(i); 167 enable_irq(i);
165 } 168 }
166} 169}
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index b3074cbaa479..c3ccaf24f3e0 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -85,8 +85,6 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
85 next = irq_fd->next; 85 next = irq_fd->next;
86 if(irq_fd->freed){ 86 if(irq_fd->freed){
87 free_irq(irq_fd->irq, irq_fd->id); 87 free_irq(irq_fd->irq, irq_fd->id);
88 free_irq_by_irq_and_dev(irq_fd->irq,
89 irq_fd->id);
90 } 88 }
91 } 89 }
92 } 90 }
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
index e59f58152678..1e1a87f1c510 100644
--- a/arch/um/kernel/main.c
+++ b/arch/um/kernel/main.c
@@ -69,7 +69,6 @@ static __init void do_uml_initcalls(void)
69 69
70static void last_ditch_exit(int sig) 70static void last_ditch_exit(int sig)
71{ 71{
72 kmalloc_ok = 0;
73 signal(SIGINT, SIG_DFL); 72 signal(SIGINT, SIG_DFL);
74 signal(SIGTERM, SIG_DFL); 73 signal(SIGTERM, SIG_DFL);
75 signal(SIGHUP, SIG_DFL); 74 signal(SIGHUP, SIG_DFL);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index c22825f13e40..5597bd39e6b5 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -53,7 +53,6 @@ static void setup_highmem(unsigned long highmem_start,
53 for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ 53 for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
54 page = &mem_map[highmem_pfn + i]; 54 page = &mem_map[highmem_pfn + i];
55 ClearPageReserved(page); 55 ClearPageReserved(page);
56 set_bit(PG_highmem, &page->flags);
57 set_page_count(page, 1); 56 set_page_count(page, 1);
58 __free_page(page); 57 __free_page(page);
59 } 58 }
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 420e6d51fa0f..a24e3b7f4bf0 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -353,6 +353,8 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
353 353
354#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) 354#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
355 355
356extern int __syscall_stub_start, __binary_start;
357
356void setup_physmem(unsigned long start, unsigned long reserve_end, 358void setup_physmem(unsigned long start, unsigned long reserve_end,
357 unsigned long len, unsigned long highmem) 359 unsigned long len, unsigned long highmem)
358{ 360{
@@ -371,6 +373,12 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
371 exit(1); 373 exit(1);
372 } 374 }
373 375
376 /* Special kludge - This page will be mapped in to userspace processes
377 * from physmem_fd, so it needs to be written out there.
378 */
379 os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
380 os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE);
381
374 bootmap_size = init_bootmem(pfn, pfn + delta); 382 bootmap_size = init_bootmem(pfn, pfn + delta);
375 free_bootmem(__pa(reserve_end) + bootmap_size, 383 free_bootmem(__pa(reserve_end) + bootmap_size,
376 len - bootmap_size - reserve); 384 len - bootmap_size - reserve);
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 1b5ef3e96c71..8b01a5584e80 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -32,6 +32,7 @@
32#include "uml-config.h" 32#include "uml-config.h"
33#include "choose-mode.h" 33#include "choose-mode.h"
34#include "mode.h" 34#include "mode.h"
35#include "tempfile.h"
35#ifdef UML_CONFIG_MODE_SKAS 36#ifdef UML_CONFIG_MODE_SKAS
36#include "skas.h" 37#include "skas.h"
37#include "skas_ptrace.h" 38#include "skas_ptrace.h"
@@ -211,12 +212,26 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit)
211 212
212static int force_sysemu_disabled = 0; 213static int force_sysemu_disabled = 0;
213 214
215int ptrace_faultinfo = 1;
216int proc_mm = 1;
217
218static int __init skas0_cmd_param(char *str, int* add)
219{
220 ptrace_faultinfo = proc_mm = 0;
221 return 0;
222}
223
214static int __init nosysemu_cmd_param(char *str, int* add) 224static int __init nosysemu_cmd_param(char *str, int* add)
215{ 225{
216 force_sysemu_disabled = 1; 226 force_sysemu_disabled = 1;
217 return 0; 227 return 0;
218} 228}
219 229
230__uml_setup("skas0", skas0_cmd_param,
231 "skas0\n"
232 " Disables SKAS3 usage, so that SKAS0 is used, unless you \n"
233 " specify mode=tt.\n\n");
234
220__uml_setup("nosysemu", nosysemu_cmd_param, 235__uml_setup("nosysemu", nosysemu_cmd_param,
221 "nosysemu\n" 236 "nosysemu\n"
222 " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n" 237 " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n"
@@ -358,49 +373,53 @@ void forward_pending_sigio(int target)
358 kill(target, SIGIO); 373 kill(target, SIGIO);
359} 374}
360 375
376extern void *__syscall_stub_start, __syscall_stub_end;
377
361#ifdef UML_CONFIG_MODE_SKAS 378#ifdef UML_CONFIG_MODE_SKAS
362static inline int check_skas3_ptrace_support(void) 379
380static inline void check_skas3_ptrace_support(void)
363{ 381{
364 struct ptrace_faultinfo fi; 382 struct ptrace_faultinfo fi;
365 int pid, n, ret = 1; 383 int pid, n;
366 384
367 printf("Checking for the skas3 patch in the host..."); 385 printf("Checking for the skas3 patch in the host...");
368 pid = start_ptraced_child(); 386 pid = start_ptraced_child();
369 387
370 n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); 388 n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
371 if (n < 0) { 389 if (n < 0) {
390 ptrace_faultinfo = 0;
372 if(errno == EIO) 391 if(errno == EIO)
373 printf("not found\n"); 392 printf("not found\n");
374 else { 393 else {
375 perror("not found"); 394 perror("not found");
376 } 395 }
377 ret = 0; 396 }
378 } else { 397 else {
379 printf("found\n"); 398 if (!ptrace_faultinfo)
399 printf("found but disabled on command line\n");
400 else
401 printf("found\n");
380 } 402 }
381 403
382 init_registers(pid); 404 init_registers(pid);
383 stop_ptraced_child(pid, 1, 1); 405 stop_ptraced_child(pid, 1, 1);
384
385 return(ret);
386} 406}
387 407
388int can_do_skas(void) 408int can_do_skas(void)
389{ 409{
390 int ret = 1;
391
392 printf("Checking for /proc/mm..."); 410 printf("Checking for /proc/mm...");
393 if (os_access("/proc/mm", OS_ACC_W_OK) < 0) { 411 if (os_access("/proc/mm", OS_ACC_W_OK) < 0) {
412 proc_mm = 0;
394 printf("not found\n"); 413 printf("not found\n");
395 ret = 0;
396 goto out;
397 } else { 414 } else {
398 printf("found\n"); 415 if (!proc_mm)
416 printf("found but disabled on command line\n");
417 else
418 printf("found\n");
399 } 419 }
400 420
401 ret = check_skas3_ptrace_support(); 421 check_skas3_ptrace_support();
402out: 422 return 1;
403 return ret;
404} 423}
405#else 424#else
406int can_do_skas(void) 425int can_do_skas(void)
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 804c6bbdf67c..d4036ed680bc 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -8,6 +8,7 @@
8#include "linux/kernel.h" 8#include "linux/kernel.h"
9#include "linux/sched.h" 9#include "linux/sched.h"
10#include "linux/interrupt.h" 10#include "linux/interrupt.h"
11#include "linux/string.h"
11#include "linux/mm.h" 12#include "linux/mm.h"
12#include "linux/slab.h" 13#include "linux/slab.h"
13#include "linux/utsname.h" 14#include "linux/utsname.h"
@@ -95,8 +96,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
95 96
96 current->thread.request.u.thread.proc = fn; 97 current->thread.request.u.thread.proc = fn;
97 current->thread.request.u.thread.arg = arg; 98 current->thread.request.u.thread.arg = arg;
98 pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL, 99 pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
99 NULL); 100 &current->thread.regs, 0, NULL, NULL);
100 if(pid < 0) 101 if(pid < 0)
101 panic("do_fork failed in kernel_thread, errno = %d", pid); 102 panic("do_fork failed in kernel_thread, errno = %d", pid);
102 return(pid); 103 return(pid);
@@ -168,7 +169,7 @@ int current_pid(void)
168 169
169void default_idle(void) 170void default_idle(void)
170{ 171{
171 uml_idle_timer(); 172 CHOOSE_MODE(uml_idle_timer(), (void) 0);
172 173
173 atomic_inc(&init_mm.mm_count); 174 atomic_inc(&init_mm.mm_count);
174 current->mm = &init_mm; 175 current->mm = &init_mm;
@@ -322,12 +323,7 @@ void do_uml_exitcalls(void)
322 323
323char *uml_strdup(char *string) 324char *uml_strdup(char *string)
324{ 325{
325 char *new; 326 return kstrdup(string, GFP_KERNEL);
326
327 new = kmalloc(strlen(string) + 1, GFP_KERNEL);
328 if(new == NULL) return(NULL);
329 strcpy(new, string);
330 return(new);
331} 327}
332 328
333int copy_to_user_proc(void __user *to, void *from, int size) 329int copy_to_user_proc(void __user *to, void *from, int size)
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 207f89d74908..a637e885c583 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -38,35 +38,28 @@ static void kill_off_processes(void)
38 38
39void uml_cleanup(void) 39void uml_cleanup(void)
40{ 40{
41 kill_off_processes(); 41 kmalloc_ok = 0;
42 do_uml_exitcalls(); 42 do_uml_exitcalls();
43 kill_off_processes();
43} 44}
44 45
45void machine_restart(char * __unused) 46void machine_restart(char * __unused)
46{ 47{
47 do_uml_exitcalls(); 48 uml_cleanup();
48 kill_off_processes();
49 CHOOSE_MODE(reboot_tt(), reboot_skas()); 49 CHOOSE_MODE(reboot_tt(), reboot_skas());
50} 50}
51 51
52EXPORT_SYMBOL(machine_restart);
53
54void machine_power_off(void) 52void machine_power_off(void)
55{ 53{
56 do_uml_exitcalls(); 54 uml_cleanup();
57 kill_off_processes();
58 CHOOSE_MODE(halt_tt(), halt_skas()); 55 CHOOSE_MODE(halt_tt(), halt_skas());
59} 56}
60 57
61EXPORT_SYMBOL(machine_power_off);
62
63void machine_halt(void) 58void machine_halt(void)
64{ 59{
65 machine_power_off(); 60 machine_power_off();
66} 61}
67 62
68EXPORT_SYMBOL(machine_halt);
69
70/* 63/*
71 * Overrides for Emacs so that we follow Linus's tabbing style. 64 * Overrides for Emacs so that we follow Linus's tabbing style.
72 * Emacs will notice this stuff at the end of the file and automatically 65 * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index d37d1bfcd6f7..d296d55ade4b 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,11 +3,14 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ 6obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
7 syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \ 7 syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \
8 8
9subdir- := util 9subdir- := util
10 10
11USER_OBJS := process.o time.o 11USER_OBJS := process.o clone.o
12 12
13include arch/um/scripts/Makefile.rules 13include arch/um/scripts/Makefile.rules
14
15# clone.o is in the stub, so it can't be built with profiling
16$(obj)/clone.o : c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
new file mode 100644
index 000000000000..4dc55f10cd18
--- /dev/null
+++ b/arch/um/kernel/skas/clone.c
@@ -0,0 +1,44 @@
1#include <sched.h>
2#include <signal.h>
3#include <sys/mman.h>
4#include <sys/time.h>
5#include <asm/unistd.h>
6#include <asm/page.h>
7#include "ptrace_user.h"
8#include "skas.h"
9#include "stub-data.h"
10#include "uml-config.h"
11#include "sysdep/stub.h"
12
13/* This is in a separate file because it needs to be compiled with any
14 * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
15 */
16void __attribute__ ((__section__ (".__syscall_stub")))
17stub_clone_handler(void)
18{
19 long err;
20 struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA;
21
22 err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
23 UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 -
24 sizeof(void *));
25 if(err != 0)
26 goto out;
27
28 err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
29 if(err)
30 goto out;
31
32 err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
33 (long) &from->timer, 0);
34 if(err)
35 goto out;
36
37 err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE,
38 PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
39 from->fd, from->offset);
40 out:
41 /* save current result. Parent: pid; child: retcode of mmap */
42 from->err = err;
43 trap_myself();
44}
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
index c6b4d5dba789..77ed7bbab219 100644
--- a/arch/um/kernel/skas/exec_kern.c
+++ b/arch/um/kernel/skas/exec_kern.c
@@ -18,7 +18,7 @@
18void flush_thread_skas(void) 18void flush_thread_skas(void)
19{ 19{
20 force_flush_all(); 20 force_flush_all();
21 switch_mm_skas(current->mm->context.skas.mm_fd); 21 switch_mm_skas(&current->mm->context.skas.id);
22} 22}
23 23
24void start_thread_skas(struct pt_regs *regs, unsigned long eip, 24void start_thread_skas(struct pt_regs *regs, unsigned long eip,
diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/kernel/skas/include/mm_id.h
new file mode 100644
index 000000000000..48dd0989ddaa
--- /dev/null
+++ b/arch/um/kernel/skas/include/mm_id.h
@@ -0,0 +1,17 @@
1/*
2 * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MM_ID_H
7#define __MM_ID_H
8
9struct mm_id {
10 union {
11 int mm_fd;
12 int pid;
13 } u;
14 unsigned long stack;
15};
16
17#endif
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
index 4cd60d7213f3..278b72f1d9ad 100644
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ b/arch/um/kernel/skas/include/mmu-skas.h
@@ -6,10 +6,15 @@
6#ifndef __SKAS_MMU_H 6#ifndef __SKAS_MMU_H
7#define __SKAS_MMU_H 7#define __SKAS_MMU_H
8 8
9#include "mm_id.h"
10
9struct mmu_context_skas { 11struct mmu_context_skas {
10 int mm_fd; 12 struct mm_id id;
13 unsigned long last_page_table;
11}; 14};
12 15
16extern void switch_mm_skas(struct mm_id * mm_idp);
17
13#endif 18#endif
14 19
15/* 20/*
diff --git a/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h
index c1e33bd788db..bcd26a6a3888 100644
--- a/arch/um/kernel/skas/include/mode-skas.h
+++ b/arch/um/kernel/skas/include/mode-skas.h
@@ -13,7 +13,6 @@ extern unsigned long exec_fp_regs[];
13extern unsigned long exec_fpx_regs[]; 13extern unsigned long exec_fpx_regs[];
14extern int have_fpx_regs; 14extern int have_fpx_regs;
15 15
16extern void user_time_init_skas(void);
17extern void sig_handler_common_skas(int sig, void *sc_ptr); 16extern void sig_handler_common_skas(int sig, void *sc_ptr);
18extern void halt_skas(void); 17extern void halt_skas(void);
19extern void reboot_skas(void); 18extern void reboot_skas(void);
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 96b51dba3471..d983ea842547 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -6,9 +6,11 @@
6#ifndef __SKAS_H 6#ifndef __SKAS_H
7#define __SKAS_H 7#define __SKAS_H
8 8
9#include "mm_id.h"
9#include "sysdep/ptrace.h" 10#include "sysdep/ptrace.h"
10 11
11extern int userspace_pid[]; 12extern int userspace_pid[];
13extern int proc_mm, ptrace_faultinfo;
12 14
13extern void switch_threads(void *me, void *next); 15extern void switch_threads(void *me, void *next);
14extern void thread_wait(void *sw, void *fb); 16extern void thread_wait(void *sw, void *fb);
@@ -22,16 +24,18 @@ extern void new_thread_proc(void *stack, void (*handler)(int sig));
22extern void remove_sigstack(void); 24extern void remove_sigstack(void);
23extern void new_thread_handler(int sig); 25extern void new_thread_handler(int sig);
24extern void handle_syscall(union uml_pt_regs *regs); 26extern void handle_syscall(union uml_pt_regs *regs);
25extern void map(int fd, unsigned long virt, unsigned long len, int r, int w, 27extern int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
26 int x, int phys_fd, unsigned long long offset); 28 int r, int w, int x, int phys_fd, unsigned long long offset);
27extern int unmap(int fd, void *addr, unsigned long len); 29extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len);
28extern int protect(int fd, unsigned long addr, unsigned long len, 30extern int protect(struct mm_id * mm_idp, unsigned long addr,
29 int r, int w, int x); 31 unsigned long len, int r, int w, int x);
30extern void user_signal(int sig, union uml_pt_regs *regs, int pid); 32extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
31extern int new_mm(int from); 33extern int new_mm(int from);
32extern void start_userspace(int cpu); 34extern int start_userspace(unsigned long stub_stack);
35extern int copy_context_skas0(unsigned long stack, int pid);
33extern void get_skas_faultinfo(int pid, struct faultinfo * fi); 36extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
34extern long execute_syscall_skas(void *r); 37extern long execute_syscall_skas(void *r);
38extern unsigned long current_stub_stack(void);
35 39
36#endif 40#endif
37 41
diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/kernel/skas/include/stub-data.h
new file mode 100644
index 000000000000..f6ed92c3727d
--- /dev/null
+++ b/arch/um/kernel/skas/include/stub-data.h
@@ -0,0 +1,18 @@
1/*
2 * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __STUB_DATA_H
7#define __STUB_DATA_H
8
9#include <sys/time.h>
10
11struct stub_data {
12 long offset;
13 int fd;
14 struct itimerval timer;
15 long err;
16};
17
18#endif
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 438db2f43456..147466d7ff4f 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -5,7 +5,9 @@
5 5
6#include "linux/config.h" 6#include "linux/config.h"
7#include "linux/mm.h" 7#include "linux/mm.h"
8#include "asm/pgtable.h"
8#include "mem_user.h" 9#include "mem_user.h"
10#include "skas.h"
9 11
10unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, 12unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
11 unsigned long *task_size_out) 13 unsigned long *task_size_out)
@@ -18,7 +20,9 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
18 *task_size_out = CONFIG_HOST_TASK_SIZE; 20 *task_size_out = CONFIG_HOST_TASK_SIZE;
19#else 21#else
20 *host_size_out = top; 22 *host_size_out = top;
21 *task_size_out = top; 23 if (proc_mm && ptrace_faultinfo)
24 *task_size_out = top;
25 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
22#endif 26#endif
23 return(((unsigned long) set_task_sizes_skas) & ~0xffffff); 27 return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
24} 28}
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
index 1310bf1e88d1..b0980ff3bd95 100644
--- a/arch/um/kernel/skas/mem_user.c
+++ b/arch/um/kernel/skas/mem_user.c
@@ -3,100 +3,171 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h>
6#include <errno.h> 7#include <errno.h>
7#include <sys/mman.h> 8#include <sys/mman.h>
9#include <sys/wait.h>
10#include <asm/page.h>
11#include <asm/unistd.h>
8#include "mem_user.h" 12#include "mem_user.h"
9#include "mem.h" 13#include "mem.h"
14#include "mm_id.h"
10#include "user.h" 15#include "user.h"
11#include "os.h" 16#include "os.h"
12#include "proc_mm.h" 17#include "proc_mm.h"
13 18#include "ptrace_user.h"
14void map(int fd, unsigned long virt, unsigned long len, int r, int w, 19#include "user_util.h"
15 int x, int phys_fd, unsigned long long offset) 20#include "kern_util.h"
21#include "task.h"
22#include "registers.h"
23#include "uml-config.h"
24#include "sysdep/ptrace.h"
25#include "sysdep/stub.h"
26#include "skas.h"
27
28extern unsigned long syscall_stub, __syscall_stub_start;
29
30extern void wait_stub_done(int pid, int sig, char * fname);
31
32static long run_syscall_stub(struct mm_id * mm_idp, int syscall,
33 unsigned long *args)
16{ 34{
17 struct proc_mm_op map; 35 int n, pid = mm_idp->u.pid;
18 int prot, n; 36 unsigned long regs[MAX_REG_NR];
19 37
20 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 38 get_safe_registers(regs);
21 (x ? PROT_EXEC : 0); 39 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
22 40 ((unsigned long) &syscall_stub -
23 map = ((struct proc_mm_op) { .op = MM_MMAP, 41 (unsigned long) &__syscall_stub_start);
24 .u = 42 /* XXX Don't have a define for starting a syscall */
25 { .mmap = 43 regs[REGS_SYSCALL_NR] = syscall;
26 { .addr = virt, 44 regs[REGS_SYSCALL_ARG1] = args[0];
27 .len = len, 45 regs[REGS_SYSCALL_ARG2] = args[1];
28 .prot = prot, 46 regs[REGS_SYSCALL_ARG3] = args[2];
29 .flags = MAP_SHARED | 47 regs[REGS_SYSCALL_ARG4] = args[3];
30 MAP_FIXED, 48 regs[REGS_SYSCALL_ARG5] = args[4];
31 .fd = phys_fd, 49 regs[REGS_SYSCALL_ARG6] = args[5];
32 .offset = offset 50 n = ptrace_setregs(pid, regs);
33 } } } ); 51 if(n < 0){
34 n = os_write_file(fd, &map, sizeof(map)); 52 printk("run_syscall_stub : PTRACE_SETREGS failed, "
35 if(n != sizeof(map)) 53 "errno = %d\n", n);
36 printk("map : /proc/mm map failed, err = %d\n", -n); 54 return(n);
55 }
56
57 wait_stub_done(pid, 0, "run_syscall_stub");
58
59 return(*((unsigned long *) mm_idp->stack));
37} 60}
38 61
39int unmap(int fd, void *addr, unsigned long len) 62int map(struct mm_id *mm_idp, unsigned long virt, unsigned long len,
63 int r, int w, int x, int phys_fd, unsigned long long offset)
40{ 64{
41 struct proc_mm_op unmap; 65 int prot, n;
42 int n; 66
43 67 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
44 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, 68 (x ? PROT_EXEC : 0);
45 .u = 69
46 { .munmap = 70 if(proc_mm){
47 { .addr = (unsigned long) addr, 71 struct proc_mm_op map;
48 .len = len } } } ); 72 int fd = mm_idp->u.mm_fd;
49 n = os_write_file(fd, &unmap, sizeof(unmap)); 73 map = ((struct proc_mm_op) { .op = MM_MMAP,
50 if(n != sizeof(unmap)) { 74 .u =
51 if(n < 0) 75 { .mmap =
52 return(n); 76 { .addr = virt,
53 else if(n > 0) 77 .len = len,
54 return(-EIO); 78 .prot = prot,
55 } 79 .flags = MAP_SHARED |
56 80 MAP_FIXED,
57 return(0); 81 .fd = phys_fd,
82 .offset= offset
83 } } } );
84 n = os_write_file(fd, &map, sizeof(map));
85 if(n != sizeof(map))
86 printk("map : /proc/mm map failed, err = %d\n", -n);
87 }
88 else {
89 long res;
90 unsigned long args[] = { virt, len, prot,
91 MAP_SHARED | MAP_FIXED, phys_fd,
92 MMAP_OFFSET(offset) };
93
94 res = run_syscall_stub(mm_idp, STUB_MMAP_NR, args);
95 if((void *) res == MAP_FAILED)
96 printk("mmap stub failed, errno = %d\n", res);
97 }
98
99 return 0;
58} 100}
59 101
60int protect(int fd, unsigned long addr, unsigned long len, int r, int w, 102int unmap(struct mm_id *mm_idp, void *addr, unsigned long len)
61 int x, int must_succeed)
62{ 103{
63 struct proc_mm_op protect; 104 int n;
64 int prot, n; 105
65 106 if(proc_mm){
66 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 107 struct proc_mm_op unmap;
67 (x ? PROT_EXEC : 0); 108 int fd = mm_idp->u.mm_fd;
68 109 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
69 protect = ((struct proc_mm_op) { .op = MM_MPROTECT, 110 .u =
70 .u = 111 { .munmap =
71 { .mprotect = 112 { .addr =
72 { .addr = (unsigned long) addr, 113 (unsigned long) addr,
73 .len = len, 114 .len = len } } } );
74 .prot = prot } } } ); 115 n = os_write_file(fd, &unmap, sizeof(unmap));
75 116 if(n != sizeof(unmap)) {
76 n = os_write_file(fd, &protect, sizeof(protect)); 117 if(n < 0)
77 if(n != sizeof(protect)) { 118 return(n);
78 if(n == 0) return(0); 119 else if(n > 0)
79 120 return(-EIO);
80 if(must_succeed) 121 }
81 panic("protect failed, err = %d", -n); 122 }
82 123 else {
83 return(-EIO); 124 int res;
84 } 125 unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
126 0 };
127
128 res = run_syscall_stub(mm_idp, __NR_munmap, args);
129 if(res < 0)
130 printk("munmap stub failed, errno = %d\n", res);
131 }
132
133 return(0);
134}
85 135
86 return(0); 136int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
137 int r, int w, int x)
138{
139 struct proc_mm_op protect;
140 int prot, n;
141
142 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
143 (x ? PROT_EXEC : 0);
144
145 if(proc_mm){
146 int fd = mm_idp->u.mm_fd;
147 protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
148 .u =
149 { .mprotect =
150 { .addr =
151 (unsigned long) addr,
152 .len = len,
153 .prot = prot } } } );
154
155 n = os_write_file(fd, &protect, sizeof(protect));
156 if(n != sizeof(protect))
157 panic("protect failed, err = %d", -n);
158 }
159 else {
160 int res;
161 unsigned long args[] = { addr, len, prot, 0, 0, 0 };
162
163 res = run_syscall_stub(mm_idp, __NR_mprotect, args);
164 if(res < 0)
165 panic("mprotect stub failed, errno = %d\n", res);
166 }
167
168 return(0);
87} 169}
88 170
89void before_mem_skas(unsigned long unused) 171void before_mem_skas(unsigned long unused)
90{ 172{
91} 173}
92
93/*
94 * Overrides for Emacs so that we follow Linus's tabbing style.
95 * Emacs will notice this stuff at the end of the file and automatically
96 * adjust the settings for this buffer only. This must remain at the end
97 * of the file.
98 * ---------------------------------------------------------------------------
99 * Local variables:
100 * c-file-style: "linux"
101 * End:
102 */
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 6cb9a6d028a9..d232daa42c31 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -3,46 +3,143 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include "linux/config.h"
6#include "linux/sched.h" 7#include "linux/sched.h"
7#include "linux/list.h" 8#include "linux/list.h"
8#include "linux/spinlock.h" 9#include "linux/spinlock.h"
9#include "linux/slab.h" 10#include "linux/slab.h"
11#include "linux/errno.h"
12#include "linux/mm.h"
10#include "asm/current.h" 13#include "asm/current.h"
11#include "asm/segment.h" 14#include "asm/segment.h"
12#include "asm/mmu.h" 15#include "asm/mmu.h"
16#include "asm/pgalloc.h"
17#include "asm/pgtable.h"
13#include "os.h" 18#include "os.h"
14#include "skas.h" 19#include "skas.h"
15 20
21extern int __syscall_stub_start;
22
23static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
24 unsigned long kernel)
25{
26 pgd_t *pgd;
27 pud_t *pud;
28 pmd_t *pmd;
29 pte_t *pte;
30
31 spin_lock(&mm->page_table_lock);
32 pgd = pgd_offset(mm, proc);
33 pud = pud_alloc(mm, pgd, proc);
34 if (!pud)
35 goto out;
36
37 pmd = pmd_alloc(mm, pud, proc);
38 if (!pmd)
39 goto out_pmd;
40
41 pte = pte_alloc_map(mm, pmd, proc);
42 if (!pte)
43 goto out_pte;
44
45 /* There's an interaction between the skas0 stub pages, stack
46 * randomization, and the BUG at the end of exit_mmap. exit_mmap
47 * checks that the number of page tables freed is the same as had
48 * been allocated. If the stack is on the last page table page,
49 * then the stack pte page will be freed, and if not, it won't. To
50 * avoid having to know where the stack is, or if the process mapped
51 * something at the top of its address space for some other reason,
52 * we set TASK_SIZE to end at the start of the last page table.
53 * This keeps exit_mmap off the last page, but introduces a leak
54 * of that page. So, we hang onto it here and free it in
55 * destroy_context_skas.
56 */
57
58 mm->context.skas.last_page_table = pmd_page_kernel(*pmd);
59
60 *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
61 *pte = pte_mkexec(*pte);
62 *pte = pte_wrprotect(*pte);
63 spin_unlock(&mm->page_table_lock);
64 return(0);
65
66 out_pmd:
67 pud_free(pud);
68 out_pte:
69 pmd_free(pmd);
70 out:
71 spin_unlock(&mm->page_table_lock);
72 return(-ENOMEM);
73}
74
16int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) 75int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
17{ 76{
18 int from; 77 struct mm_struct *cur_mm = current->mm;
78 struct mm_id *cur_mm_id = &cur_mm->context.skas.id;
79 struct mm_id *mm_id = &mm->context.skas.id;
80 unsigned long stack;
81 int from, ret;
19 82
20 if((current->mm != NULL) && (current->mm != &init_mm)) 83 if(proc_mm){
21 from = current->mm->context.skas.mm_fd; 84 if((cur_mm != NULL) && (cur_mm != &init_mm))
22 else from = -1; 85 from = cur_mm->context.skas.id.u.mm_fd;
86 else from = -1;
23 87
24 mm->context.skas.mm_fd = new_mm(from); 88 ret = new_mm(from);
25 if(mm->context.skas.mm_fd < 0){ 89 if(ret < 0){
26 printk("init_new_context_skas - new_mm failed, errno = %d\n", 90 printk("init_new_context_skas - new_mm failed, "
27 mm->context.skas.mm_fd); 91 "errno = %d\n", ret);
28 return(mm->context.skas.mm_fd); 92 return ret;
93 }
94 mm_id->u.mm_fd = ret;
29 } 95 }
96 else {
97 /* This zeros the entry that pgd_alloc didn't, needed since
98 * we are about to reinitialize it, and want mm.nr_ptes to
99 * be accurate.
100 */
101 mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
30 102
31 return(0); 103 ret = init_stub_pte(mm, CONFIG_STUB_CODE,
104 (unsigned long) &__syscall_stub_start);
105 if(ret)
106 goto out;
107
108 ret = -ENOMEM;
109 stack = get_zeroed_page(GFP_KERNEL);
110 if(stack == 0)
111 goto out;
112 mm_id->stack = stack;
113
114 ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack);
115 if(ret)
116 goto out_free;
117
118 mm->nr_ptes--;
119
120 if((cur_mm != NULL) && (cur_mm != &init_mm))
121 mm_id->u.pid = copy_context_skas0(stack,
122 cur_mm_id->u.pid);
123 else mm_id->u.pid = start_userspace(stack);
124 }
125
126 return 0;
127
128 out_free:
129 free_page(mm_id->stack);
130 out:
131 return ret;
32} 132}
33 133
34void destroy_context_skas(struct mm_struct *mm) 134void destroy_context_skas(struct mm_struct *mm)
35{ 135{
36 os_close_file(mm->context.skas.mm_fd); 136 struct mmu_context_skas *mmu = &mm->context.skas;
37}
38 137
39/* 138 if(proc_mm)
40 * Overrides for Emacs so that we follow Linus's tabbing style. 139 os_close_file(mmu->id.u.mm_fd);
41 * Emacs will notice this stuff at the end of the file and automatically 140 else {
42 * adjust the settings for this buffer only. This must remain at the end 141 os_kill_ptraced_process(mmu->id.u.pid, 1);
43 * of the file. 142 free_page(mmu->id.stack);
44 * --------------------------------------------------------------------------- 143 free_page(mmu->last_page_table);
45 * Local variables: 144 }
46 * c-file-style: "linux" 145}
47 * End:
48 */
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 773cd2b525fc..ba671dab8878 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -13,7 +13,9 @@
13#include <sys/wait.h> 13#include <sys/wait.h>
14#include <sys/mman.h> 14#include <sys/mman.h>
15#include <sys/user.h> 15#include <sys/user.h>
16#include <sys/time.h>
16#include <asm/unistd.h> 17#include <asm/unistd.h>
18#include <asm/types.h>
17#include "user.h" 19#include "user.h"
18#include "ptrace_user.h" 20#include "ptrace_user.h"
19#include "time_user.h" 21#include "time_user.h"
@@ -21,13 +23,18 @@
21#include "user_util.h" 23#include "user_util.h"
22#include "kern_util.h" 24#include "kern_util.h"
23#include "skas.h" 25#include "skas.h"
26#include "stub-data.h"
27#include "mm_id.h"
24#include "sysdep/sigcontext.h" 28#include "sysdep/sigcontext.h"
29#include "sysdep/stub.h"
25#include "os.h" 30#include "os.h"
26#include "proc_mm.h" 31#include "proc_mm.h"
27#include "skas_ptrace.h" 32#include "skas_ptrace.h"
28#include "chan_user.h" 33#include "chan_user.h"
29#include "signal_user.h" 34#include "signal_user.h"
30#include "registers.h" 35#include "registers.h"
36#include "mem.h"
37#include "uml-config.h"
31#include "process.h" 38#include "process.h"
32 39
33int is_skas_winch(int pid, int fd, void *data) 40int is_skas_winch(int pid, int fd, void *data)
@@ -39,20 +46,55 @@ int is_skas_winch(int pid, int fd, void *data)
39 return(1); 46 return(1);
40} 47}
41 48
42void get_skas_faultinfo(int pid, struct faultinfo * fi) 49void wait_stub_done(int pid, int sig, char * fname)
43{ 50{
44 int err; 51 int n, status, err;
45 52
46 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); 53 do {
47 if(err) 54 if ( sig != -1 ) {
48 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " 55 err = ptrace(PTRACE_CONT, pid, 0, sig);
49 "errno = %d\n", errno); 56 if(err)
57 panic("%s : continue failed, errno = %d\n",
58 fname, errno);
59 }
60 sig = 0;
61
62 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
63 } while((n >= 0) && WIFSTOPPED(status) &&
64 (WSTOPSIG(status) == SIGVTALRM));
65
66 if((n < 0) || !WIFSTOPPED(status) ||
67 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status != SIGTRAP))){
68 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
69 "pid = %d, n = %d, errno = %d, status = 0x%x\n",
70 fname, pid, n, errno, status);
71 }
72}
50 73
51 /* Special handling for i386, which has different structs */ 74void get_skas_faultinfo(int pid, struct faultinfo * fi)
52 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) 75{
53 memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, 76 int err;
54 sizeof(struct faultinfo) - 77
55 sizeof(struct ptrace_faultinfo)); 78 if(ptrace_faultinfo){
79 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
80 if(err)
81 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
82 "errno = %d\n", errno);
83
84 /* Special handling for i386, which has different structs */
85 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
86 memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
87 sizeof(struct faultinfo) -
88 sizeof(struct ptrace_faultinfo));
89 }
90 else {
91 wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
92
93 /* faultinfo is prepared by the stub-segv-handler at start of
94 * the stub stack page. We just have to copy it.
95 */
96 memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
97 }
56} 98}
57 99
58static void handle_segv(int pid, union uml_pt_regs * regs) 100static void handle_segv(int pid, union uml_pt_regs * regs)
@@ -91,11 +133,56 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
91 handle_syscall(regs); 133 handle_syscall(regs);
92} 134}
93 135
94static int userspace_tramp(void *arg) 136extern int __syscall_stub_start;
137
138static int userspace_tramp(void *stack)
95{ 139{
96 init_new_thread_signals(0); 140 void *addr;
97 enable_timer(); 141
98 ptrace(PTRACE_TRACEME, 0, 0, 0); 142 ptrace(PTRACE_TRACEME, 0, 0, 0);
143
144 init_new_thread_signals(1);
145 enable_timer();
146
147 if(!proc_mm){
148 /* This has a pte, but it can't be mapped in with the usual
149 * tlb_flush mechanism because this is part of that mechanism
150 */
151 int fd;
152 __u64 offset;
153
154 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
155 addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
156 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
157 if(addr == MAP_FAILED){
158 printk("mapping mmap stub failed, errno = %d\n",
159 errno);
160 exit(1);
161 }
162
163 if(stack != NULL){
164 fd = phys_mapping(to_phys(stack), &offset);
165 addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
166 PROT_READ | PROT_WRITE,
167 MAP_FIXED | MAP_SHARED, fd, offset);
168 if(addr == MAP_FAILED){
169 printk("mapping segfault stack failed, "
170 "errno = %d\n", errno);
171 exit(1);
172 }
173 }
174 }
175 if(!ptrace_faultinfo && (stack != NULL)){
176 unsigned long v = UML_CONFIG_STUB_CODE +
177 (unsigned long) stub_segv_handler -
178 (unsigned long) &__syscall_stub_start;
179
180 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
181 set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
182 SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
183 SIGUSR1, -1);
184 }
185
99 os_stop_process(os_getpid()); 186 os_stop_process(os_getpid());
100 return(0); 187 return(0);
101} 188}
@@ -105,11 +192,11 @@ static int userspace_tramp(void *arg)
105#define NR_CPUS 1 192#define NR_CPUS 1
106int userspace_pid[NR_CPUS]; 193int userspace_pid[NR_CPUS];
107 194
108void start_userspace(int cpu) 195int start_userspace(unsigned long stub_stack)
109{ 196{
110 void *stack; 197 void *stack;
111 unsigned long sp; 198 unsigned long sp;
112 int pid, status, n; 199 int pid, status, n, flags;
113 200
114 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, 201 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
115 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 202 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -117,8 +204,9 @@ void start_userspace(int cpu)
117 panic("start_userspace : mmap failed, errno = %d", errno); 204 panic("start_userspace : mmap failed, errno = %d", errno);
118 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); 205 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
119 206
120 pid = clone(userspace_tramp, (void *) sp, 207 flags = CLONE_FILES | SIGCHLD;
121 CLONE_FILES | CLONE_VM | SIGCHLD, NULL); 208 if(proc_mm) flags |= CLONE_VM;
209 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
122 if(pid < 0) 210 if(pid < 0)
123 panic("start_userspace : clone failed, errno = %d", errno); 211 panic("start_userspace : clone failed, errno = %d", errno);
124 212
@@ -140,7 +228,7 @@ void start_userspace(int cpu)
140 if(munmap(stack, PAGE_SIZE) < 0) 228 if(munmap(stack, PAGE_SIZE) < 0)
141 panic("start_userspace : munmap failed, errno = %d\n", errno); 229 panic("start_userspace : munmap failed, errno = %d\n", errno);
142 230
143 userspace_pid[cpu] = pid; 231 return(pid);
144} 232}
145 233
146void userspace(union uml_pt_regs *regs) 234void userspace(union uml_pt_regs *regs)
@@ -174,7 +262,9 @@ void userspace(union uml_pt_regs *regs)
174 if(WIFSTOPPED(status)){ 262 if(WIFSTOPPED(status)){
175 switch(WSTOPSIG(status)){ 263 switch(WSTOPSIG(status)){
176 case SIGSEGV: 264 case SIGSEGV:
177 handle_segv(pid, regs); 265 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
266 user_signal(SIGSEGV, regs, pid);
267 else handle_segv(pid, regs);
178 break; 268 break;
179 case SIGTRAP + 0x80: 269 case SIGTRAP + 0x80:
180 handle_trap(pid, regs, local_using_sysemu); 270 handle_trap(pid, regs, local_using_sysemu);
@@ -194,6 +284,7 @@ void userspace(union uml_pt_regs *regs)
194 printk("userspace - child stopped with signal " 284 printk("userspace - child stopped with signal "
195 "%d\n", WSTOPSIG(status)); 285 "%d\n", WSTOPSIG(status));
196 } 286 }
287 pid = userspace_pid[0];
197 interrupt_end(); 288 interrupt_end();
198 289
199 /* Avoid -ERESTARTSYS handling in host */ 290 /* Avoid -ERESTARTSYS handling in host */
@@ -207,6 +298,67 @@ void userspace(union uml_pt_regs *regs)
207#define INIT_JMP_HALT 3 298#define INIT_JMP_HALT 3
208#define INIT_JMP_REBOOT 4 299#define INIT_JMP_REBOOT 4
209 300
301
302int copy_context_skas0(unsigned long new_stack, int pid)
303{
304 int err;
305 unsigned long regs[MAX_REG_NR];
306 unsigned long current_stack = current_stub_stack();
307 struct stub_data *data = (struct stub_data *) current_stack;
308 struct stub_data *child_data = (struct stub_data *) new_stack;
309 __u64 new_offset;
310 int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
311
312 /* prepare offset and fd of child's stack as argument for parent's
313 * and child's mmap2 calls
314 */
315 *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
316 .fd = new_fd,
317 .timer = ((struct itimerval)
318 { { 0, 1000000 / hz() },
319 { 0, 1000000 / hz() }})});
320 get_safe_registers(regs);
321
322 /* Set parent's instruction pointer to start of clone-stub */
323 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
324 (unsigned long) stub_clone_handler -
325 (unsigned long) &__syscall_stub_start;
326 regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
327 sizeof(void *);
328 err = ptrace_setregs(pid, regs);
329 if(err < 0)
330 panic("copy_context_skas0 : PTRACE_SETREGS failed, "
331 "pid = %d, errno = %d\n", pid, errno);
332
333 /* set a well known return code for detection of child write failure */
334 child_data->err = 12345678;
335
336 /* Wait, until parent has finished its work: read child's pid from
337 * parent's stack, and check, if bad result.
338 */
339 wait_stub_done(pid, 0, "copy_context_skas0");
340
341 pid = data->err;
342 if(pid < 0)
343 panic("copy_context_skas0 - stub-parent reports error %d\n",
344 pid);
345
346 /* Wait, until child has finished too: read child's result from
347 * child's stack and check it.
348 */
349 wait_stub_done(pid, -1, "copy_context_skas0");
350 if (child_data->err != UML_CONFIG_STUB_DATA)
351 panic("copy_context_skas0 - stub-child reports error %d\n",
352 child_data->err);
353
354 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
355 (void *)PTRACE_O_TRACESYSGOOD) < 0)
356 panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, "
357 "errno = %d\n", errno);
358
359 return pid;
360}
361
210void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, 362void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
211 void (*handler)(int)) 363 void (*handler)(int))
212{ 364{
@@ -334,21 +486,19 @@ void reboot_skas(void)
334 siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); 486 siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);
335} 487}
336 488
337void switch_mm_skas(int mm_fd) 489void switch_mm_skas(struct mm_id *mm_idp)
338{ 490{
339 int err; 491 int err;
340 492
341#warning need cpu pid in switch_mm_skas 493#warning need cpu pid in switch_mm_skas
342 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); 494 if(proc_mm){
343 if(err) 495 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
344 panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", 496 mm_idp->u.mm_fd);
345 errno); 497 if(err)
346} 498 panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
347 499 "errno = %d\n", errno);
348void kill_off_processes_skas(void) 500 }
349{ 501 else userspace_pid[0] = mm_idp->u.pid;
350#warning need to loop over userspace_pids in kill_off_processes_skas
351 os_kill_ptraced_process(userspace_pid[0], 1);
352} 502}
353 503
354/* 504/*
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index fc71ef295782..cbabab104ac3 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -111,8 +111,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
111 void (*handler)(int); 111 void (*handler)(int);
112 112
113 if(current->thread.forking){ 113 if(current->thread.forking){
114 memcpy(&p->thread.regs.regs.skas, 114 memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
115 &current->thread.regs.regs.skas,
116 sizeof(p->thread.regs.regs.skas)); 115 sizeof(p->thread.regs.regs.skas));
117 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); 116 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
118 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; 117 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
@@ -176,12 +175,14 @@ static int start_kernel_proc(void *unused)
176 return(0); 175 return(0);
177} 176}
178 177
178extern int userspace_pid[];
179
179int start_uml_skas(void) 180int start_uml_skas(void)
180{ 181{
181 start_userspace(0); 182 if(proc_mm)
183 userspace_pid[0] = start_userspace(0);
182 184
183 init_new_thread_signals(1); 185 init_new_thread_signals(1);
184 uml_idle_timer();
185 186
186 init_task.thread.request.u.thread.proc = start_kernel_proc; 187 init_task.thread.request.u.thread.proc = start_kernel_proc;
187 init_task.thread.request.u.thread.arg = NULL; 188 init_task.thread.request.u.thread.arg = NULL;
@@ -202,13 +203,30 @@ int thread_pid_skas(struct task_struct *task)
202 return(userspace_pid[0]); 203 return(userspace_pid[0]);
203} 204}
204 205
205/* 206void kill_off_processes_skas(void)
206 * Overrides for Emacs so that we follow Linus's tabbing style. 207{
207 * Emacs will notice this stuff at the end of the file and automatically 208 if(proc_mm)
208 * adjust the settings for this buffer only. This must remain at the end 209#warning need to loop over userspace_pids in kill_off_processes_skas
209 * of the file. 210 os_kill_ptraced_process(userspace_pid[0], 1);
210 * --------------------------------------------------------------------------- 211 else {
211 * Local variables: 212 struct task_struct *p;
212 * c-file-style: "linux" 213 int pid, me;
213 * End: 214
214 */ 215 me = os_getpid();
216 for_each_process(p){
217 if(p->mm == NULL)
218 continue;
219
220 pid = p->mm->context.skas.id.u.pid;
221 os_kill_ptraced_process(pid, 1);
222 }
223 }
224}
225
226unsigned long current_stub_stack(void)
227{
228 if(current->mm == NULL)
229 return(0);
230
231 return(current->mm->context.skas.id.stack);
232}
diff --git a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c
index 2828e6e37721..6b0664970147 100644
--- a/arch/um/kernel/skas/syscall_user.c
+++ b/arch/um/kernel/skas/syscall_user.c
@@ -15,7 +15,7 @@
15void handle_syscall(union uml_pt_regs *regs) 15void handle_syscall(union uml_pt_regs *regs)
16{ 16{
17 long result; 17 long result;
18#if UML_CONFIG_SYSCALL_DEBUG 18#ifdef UML_CONFIG_SYSCALL_DEBUG
19 int index; 19 int index;
20 20
21 index = record_syscall_start(UPT_SYSCALL_NR(regs)); 21 index = record_syscall_start(UPT_SYSCALL_NR(regs));
@@ -27,7 +27,7 @@ void handle_syscall(union uml_pt_regs *regs)
27 REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); 27 REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
28 28
29 syscall_trace(regs, 1); 29 syscall_trace(regs, 1);
30#if UML_CONFIG_SYSCALL_DEBUG 30#ifdef UML_CONFIG_SYSCALL_DEBUG
31 record_syscall_end(index, result); 31 record_syscall_end(index, result);
32#endif 32#endif
33} 33}
diff --git a/arch/um/kernel/skas/time.c b/arch/um/kernel/skas/time.c
deleted file mode 100644
index 98091494b897..000000000000
--- a/arch/um/kernel/skas/time.c
+++ /dev/null
@@ -1,30 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <sys/signal.h>
7#include <sys/time.h>
8#include "time_user.h"
9#include "process.h"
10#include "user.h"
11
12void user_time_init_skas(void)
13{
14 if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
15 panic("Couldn't set SIGALRM handler");
16 if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
17 panic("Couldn't set SIGVTALRM handler");
18 set_interval(ITIMER_VIRTUAL);
19}
20
21/*
22 * Overrides for Emacs so that we follow Linus's tabbing style.
23 * Emacs will notice this stuff at the end of the file and automatically
24 * adjust the settings for this buffer only. This must remain at the end
25 * of the file.
26 * ---------------------------------------------------------------------------
27 * Local variables:
28 * c-file-style: "linux"
29 * End:
30 */
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
index b8c5e71763d1..6230999c672c 100644
--- a/arch/um/kernel/skas/tlb.c
+++ b/arch/um/kernel/skas/tlb.c
@@ -6,6 +6,7 @@
6 6
7#include "linux/stddef.h" 7#include "linux/stddef.h"
8#include "linux/sched.h" 8#include "linux/sched.h"
9#include "linux/config.h"
9#include "linux/mm.h" 10#include "linux/mm.h"
10#include "asm/page.h" 11#include "asm/page.h"
11#include "asm/pgtable.h" 12#include "asm/pgtable.h"
@@ -17,7 +18,7 @@
17#include "os.h" 18#include "os.h"
18#include "tlb.h" 19#include "tlb.h"
19 20
20static void do_ops(int fd, struct host_vm_op *ops, int last) 21static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
21{ 22{
22 struct host_vm_op *op; 23 struct host_vm_op *op;
23 int i; 24 int i;
@@ -26,18 +27,18 @@ static void do_ops(int fd, struct host_vm_op *ops, int last)
26 op = &ops[i]; 27 op = &ops[i];
27 switch(op->type){ 28 switch(op->type){
28 case MMAP: 29 case MMAP:
29 map(fd, op->u.mmap.addr, op->u.mmap.len, 30 map(&mmu->skas.id, op->u.mmap.addr, op->u.mmap.len,
30 op->u.mmap.r, op->u.mmap.w, op->u.mmap.x, 31 op->u.mmap.r, op->u.mmap.w, op->u.mmap.x,
31 op->u.mmap.fd, op->u.mmap.offset); 32 op->u.mmap.fd, op->u.mmap.offset);
32 break; 33 break;
33 case MUNMAP: 34 case MUNMAP:
34 unmap(fd, (void *) op->u.munmap.addr, 35 unmap(&mmu->skas.id, (void *) op->u.munmap.addr,
35 op->u.munmap.len); 36 op->u.munmap.len);
36 break; 37 break;
37 case MPROTECT: 38 case MPROTECT:
38 protect(fd, op->u.mprotect.addr, op->u.mprotect.len, 39 protect(&mmu->skas.id, op->u.mprotect.addr,
39 op->u.mprotect.r, op->u.mprotect.w, 40 op->u.mprotect.len, op->u.mprotect.r,
40 op->u.mprotect.x); 41 op->u.mprotect.w, op->u.mprotect.x);
41 break; 42 break;
42 default: 43 default:
43 printk("Unknown op type %d in do_ops\n", op->type); 44 printk("Unknown op type %d in do_ops\n", op->type);
@@ -46,12 +47,15 @@ static void do_ops(int fd, struct host_vm_op *ops, int last)
46 } 47 }
47} 48}
48 49
50extern int proc_mm;
51
49static void fix_range(struct mm_struct *mm, unsigned long start_addr, 52static void fix_range(struct mm_struct *mm, unsigned long start_addr,
50 unsigned long end_addr, int force) 53 unsigned long end_addr, int force)
51{ 54{
52 int fd = mm->context.skas.mm_fd; 55 if(!proc_mm && (end_addr > CONFIG_STUB_START))
56 end_addr = CONFIG_STUB_START;
53 57
54 fix_range_common(mm, start_addr, end_addr, force, fd, do_ops); 58 fix_range_common(mm, start_addr, end_addr, force, do_ops);
55} 59}
56 60
57void __flush_tlb_one_skas(unsigned long addr) 61void __flush_tlb_one_skas(unsigned long addr)
@@ -69,17 +73,20 @@ void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
69 73
70void flush_tlb_mm_skas(struct mm_struct *mm) 74void flush_tlb_mm_skas(struct mm_struct *mm)
71{ 75{
76 unsigned long end;
77
72 /* Don't bother flushing if this address space is about to be 78 /* Don't bother flushing if this address space is about to be
73 * destroyed. 79 * destroyed.
74 */ 80 */
75 if(atomic_read(&mm->mm_users) == 0) 81 if(atomic_read(&mm->mm_users) == 0)
76 return; 82 return;
77 83
78 fix_range(mm, 0, host_task_size, 0); 84 end = proc_mm ? task_size : CONFIG_STUB_START;
79 flush_tlb_kernel_range_common(start_vm, end_vm); 85 fix_range(mm, 0, end, 0);
80} 86}
81 87
82void force_flush_all_skas(void) 88void force_flush_all_skas(void)
83{ 89{
84 fix_range(current->mm, 0, host_task_size, 1); 90 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
91 fix_range(current->mm, 0, end, 1);
85} 92}
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index b7a55251e897..8e1a3501ff46 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -31,7 +31,8 @@ long sys_fork(void)
31 long ret; 31 long ret;
32 32
33 current->thread.forking = 1; 33 current->thread.forking = 1;
34 ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL); 34 ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
35 &current->thread.regs, 0, NULL, NULL);
35 current->thread.forking = 0; 36 current->thread.forking = 0;
36 return(ret); 37 return(ret);
37} 38}
@@ -41,8 +42,9 @@ long sys_vfork(void)
41 long ret; 42 long ret;
42 43
43 current->thread.forking = 1; 44 current->thread.forking = 1;
44 ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, 45 ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
45 NULL); 46 UPT_SP(&current->thread.regs.regs),
47 &current->thread.regs, 0, NULL, NULL);
46 current->thread.forking = 0; 48 current->thread.forking = 0;
47 return(ret); 49 return(ret);
48} 50}
@@ -162,14 +164,3 @@ int next_syscall_index(int limit)
162 spin_unlock(&syscall_lock); 164 spin_unlock(&syscall_lock);
163 return(ret); 165 return(ret);
164} 166}
165
166/*
167 * Overrides for Emacs so that we follow Linus's tabbing style.
168 * Emacs will notice this stuff at the end of the file and automatically
169 * adjust the settings for this buffer only. This must remain at the end
170 * of the file.
171 * ---------------------------------------------------------------------------
172 * Local variables:
173 * c-file-style: "linux"
174 * End:
175 */
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index c40c86a3f918..c40b611e3d93 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -33,7 +33,7 @@ void timer(void)
33 timeradd(&xtime, &local_offset, &xtime); 33 timeradd(&xtime, &local_offset, &xtime);
34} 34}
35 35
36void set_interval(int timer_type) 36static void set_interval(int timer_type)
37{ 37{
38 int usec = 1000000/hz(); 38 int usec = 1000000/hz();
39 struct itimerval interval = ((struct itimerval) { { 0, usec }, 39 struct itimerval interval = ((struct itimerval) { { 0, usec },
@@ -45,12 +45,14 @@ void set_interval(int timer_type)
45 45
46void enable_timer(void) 46void enable_timer(void)
47{ 47{
48 set_interval(ITIMER_VIRTUAL);
49}
50
51void prepare_timer(void * ptr)
52{
48 int usec = 1000000/hz(); 53 int usec = 1000000/hz();
49 struct itimerval enable = ((struct itimerval) { { 0, usec }, 54 *(struct itimerval *)ptr = ((struct itimerval) { { 0, usec },
50 { 0, usec }}); 55 { 0, usec }});
51 if(setitimer(ITIMER_VIRTUAL, &enable, NULL))
52 printk("enable_timer - setitimer failed, errno = %d\n",
53 errno);
54} 56}
55 57
56void disable_timer(void) 58void disable_timer(void)
@@ -155,13 +157,15 @@ void idle_sleep(int secs)
155 nanosleep(&ts, NULL); 157 nanosleep(&ts, NULL);
156} 158}
157 159
158/* 160/* XXX This partly duplicates init_irq_signals */
159 * Overrides for Emacs so that we follow Linus's tabbing style. 161
160 * Emacs will notice this stuff at the end of the file and automatically 162void user_time_init(void)
161 * adjust the settings for this buffer only. This must remain at the end 163{
162 * of the file. 164 set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
163 * --------------------------------------------------------------------------- 165 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
164 * Local variables: 166 SIGALRM, SIGUSR2, -1);
165 * c-file-style: "linux" 167 set_handler(SIGALRM, (__sighandler_t) alarm_handler,
166 * End: 168 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
167 */ 169 SIGVTALRM, SIGUSR2, -1);
170 set_interval(ITIMER_VIRTUAL);
171}
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 6516fc52afe0..a8b4ef601f59 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -162,7 +162,7 @@ int __init timer_init(void)
162{ 162{
163 int err; 163 int err;
164 164
165 CHOOSE_MODE(user_time_init_tt(), user_time_init_skas()); 165 user_time_init();
166 err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL); 166 err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
167 if(err != 0) 167 if(err != 0)
168 printk(KERN_ERR "timer_init : request_irq failed - " 168 printk(KERN_ERR "timer_init : request_irq failed - "
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index eda477edfdf5..83ec8d4747fd 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -18,13 +18,15 @@
18#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) 18#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
19 19
20void fix_range_common(struct mm_struct *mm, unsigned long start_addr, 20void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
21 unsigned long end_addr, int force, int data, 21 unsigned long end_addr, int force,
22 void (*do_ops)(int, struct host_vm_op *, int)) 22 void (*do_ops)(union mm_context *, struct host_vm_op *,
23 int))
23{ 24{
24 pgd_t *npgd; 25 pgd_t *npgd;
25 pud_t *npud; 26 pud_t *npud;
26 pmd_t *npmd; 27 pmd_t *npmd;
27 pte_t *npte; 28 pte_t *npte;
29 union mm_context *mmu = &mm->context;
28 unsigned long addr, end; 30 unsigned long addr, end;
29 int r, w, x; 31 int r, w, x;
30 struct host_vm_op ops[16]; 32 struct host_vm_op ops[16];
@@ -40,7 +42,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
40 end = end_addr; 42 end = end_addr;
41 if(force || pgd_newpage(*npgd)){ 43 if(force || pgd_newpage(*npgd)){
42 op_index = add_munmap(addr, end - addr, ops, 44 op_index = add_munmap(addr, end - addr, ops,
43 op_index, last_op, data, 45 op_index, last_op, mmu,
44 do_ops); 46 do_ops);
45 pgd_mkuptodate(*npgd); 47 pgd_mkuptodate(*npgd);
46 } 48 }
@@ -55,7 +57,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
55 end = end_addr; 57 end = end_addr;
56 if(force || pud_newpage(*npud)){ 58 if(force || pud_newpage(*npud)){
57 op_index = add_munmap(addr, end - addr, ops, 59 op_index = add_munmap(addr, end - addr, ops,
58 op_index, last_op, data, 60 op_index, last_op, mmu,
59 do_ops); 61 do_ops);
60 pud_mkuptodate(*npud); 62 pud_mkuptodate(*npud);
61 } 63 }
@@ -70,7 +72,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
70 end = end_addr; 72 end = end_addr;
71 if(force || pmd_newpage(*npmd)){ 73 if(force || pmd_newpage(*npmd)){
72 op_index = add_munmap(addr, end - addr, ops, 74 op_index = add_munmap(addr, end - addr, ops,
73 op_index, last_op, data, 75 op_index, last_op, mmu,
74 do_ops); 76 do_ops);
75 pmd_mkuptodate(*npmd); 77 pmd_mkuptodate(*npmd);
76 } 78 }
@@ -93,21 +95,21 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
93 op_index = add_mmap(addr, 95 op_index = add_mmap(addr,
94 pte_val(*npte) & PAGE_MASK, 96 pte_val(*npte) & PAGE_MASK,
95 PAGE_SIZE, r, w, x, ops, 97 PAGE_SIZE, r, w, x, ops,
96 op_index, last_op, data, 98 op_index, last_op, mmu,
97 do_ops); 99 do_ops);
98 else op_index = add_munmap(addr, PAGE_SIZE, ops, 100 else op_index = add_munmap(addr, PAGE_SIZE, ops,
99 op_index, last_op, data, 101 op_index, last_op, mmu,
100 do_ops); 102 do_ops);
101 } 103 }
102 else if(pte_newprot(*npte)) 104 else if(pte_newprot(*npte))
103 op_index = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, 105 op_index = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
104 op_index, last_op, data, 106 op_index, last_op, mmu,
105 do_ops); 107 do_ops);
106 108
107 *npte = pte_mkuptodate(*npte); 109 *npte = pte_mkuptodate(*npte);
108 addr += PAGE_SIZE; 110 addr += PAGE_SIZE;
109 } 111 }
110 (*do_ops)(data, ops, op_index); 112 (*do_ops)(mmu, ops, op_index);
111} 113}
112 114
113int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) 115int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
@@ -195,51 +197,6 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
195 return(updated); 197 return(updated);
196} 198}
197 199
198void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
199{
200 address &= PAGE_MASK;
201 flush_tlb_range(vma, address, address + PAGE_SIZE);
202}
203
204void flush_tlb_all(void)
205{
206 flush_tlb_mm(current->mm);
207}
208
209void flush_tlb_kernel_range(unsigned long start, unsigned long end)
210{
211 CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
212 flush_tlb_kernel_range_common, start, end);
213}
214
215void flush_tlb_kernel_vm(void)
216{
217 CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
218 flush_tlb_kernel_range_common(start_vm, end_vm));
219}
220
221void __flush_tlb_one(unsigned long addr)
222{
223 CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
224}
225
226void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
227 unsigned long end)
228{
229 CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
230 end);
231}
232
233void flush_tlb_mm(struct mm_struct *mm)
234{
235 CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
236}
237
238void force_flush_all(void)
239{
240 CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
241}
242
243pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) 200pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
244{ 201{
245 return(pgd_offset(mm, address)); 202 return(pgd_offset(mm, address));
@@ -270,9 +227,9 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
270} 227}
271 228
272int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, 229int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
273 int r, int w, int x, struct host_vm_op *ops, int index, 230 int r, int w, int x, struct host_vm_op *ops, int index,
274 int last_filled, int data, 231 int last_filled, union mm_context *mmu,
275 void (*do_ops)(int, struct host_vm_op *, int)) 232 void (*do_ops)(union mm_context *, struct host_vm_op *, int))
276{ 233{
277 __u64 offset; 234 __u64 offset;
278 struct host_vm_op *last; 235 struct host_vm_op *last;
@@ -292,7 +249,7 @@ int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
292 } 249 }
293 250
294 if(index == last_filled){ 251 if(index == last_filled){
295 (*do_ops)(data, ops, last_filled); 252 (*do_ops)(mmu, ops, last_filled);
296 index = -1; 253 index = -1;
297 } 254 }
298 255
@@ -310,8 +267,8 @@ int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
310} 267}
311 268
312int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops, 269int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
313 int index, int last_filled, int data, 270 int index, int last_filled, union mm_context *mmu,
314 void (*do_ops)(int, struct host_vm_op *, int)) 271 void (*do_ops)(union mm_context *, struct host_vm_op *, int))
315{ 272{
316 struct host_vm_op *last; 273 struct host_vm_op *last;
317 274
@@ -325,7 +282,7 @@ int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
325 } 282 }
326 283
327 if(index == last_filled){ 284 if(index == last_filled){
328 (*do_ops)(data, ops, last_filled); 285 (*do_ops)(mmu, ops, last_filled);
329 index = -1; 286 index = -1;
330 } 287 }
331 288
@@ -337,8 +294,9 @@ int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
337} 294}
338 295
339int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x, 296int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
340 struct host_vm_op *ops, int index, int last_filled, int data, 297 struct host_vm_op *ops, int index, int last_filled,
341 void (*do_ops)(int, struct host_vm_op *, int)) 298 union mm_context *mmu,
299 void (*do_ops)(union mm_context *, struct host_vm_op *, int))
342{ 300{
343 struct host_vm_op *last; 301 struct host_vm_op *last;
344 302
@@ -354,7 +312,7 @@ int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
354 } 312 }
355 313
356 if(index == last_filled){ 314 if(index == last_filled){
357 (*do_ops)(data, ops, last_filled); 315 (*do_ops)(mmu, ops, last_filled);
358 index = -1; 316 index = -1;
359 } 317 }
360 318
@@ -367,3 +325,49 @@ int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
367 .x = x } } }); 325 .x = x } } });
368 return(index); 326 return(index);
369} 327}
328
329void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
330{
331 address &= PAGE_MASK;
332 flush_tlb_range(vma, address, address + PAGE_SIZE);
333}
334
335void flush_tlb_all(void)
336{
337 flush_tlb_mm(current->mm);
338}
339
340void flush_tlb_kernel_range(unsigned long start, unsigned long end)
341{
342 CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
343 flush_tlb_kernel_range_common, start, end);
344}
345
346void flush_tlb_kernel_vm(void)
347{
348 CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
349 flush_tlb_kernel_range_common(start_vm, end_vm));
350}
351
352void __flush_tlb_one(unsigned long addr)
353{
354 CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
355}
356
357void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
358 unsigned long end)
359{
360 CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
361 end);
362}
363
364void flush_tlb_mm(struct mm_struct *mm)
365{
366 CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
367}
368
369void force_flush_all(void)
370{
371 CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
372}
373
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index c3faea21a996..6939e5af8472 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -3,27 +3,12 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6extra-y := unmap_fin.o
7targets := unmap.o
8clean-files := unmap_tmp.o
9
10obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ 6obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
11 syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \ 7 syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \
12 uaccess.o uaccess_user.o 8 uaccess.o uaccess_user.o
13 9
14obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/ 10obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
15 11
16USER_OBJS := gdb.o time.o tracer.o 12USER_OBJS := gdb.o tracer.o
17 13
18include arch/um/scripts/Makefile.rules 14include arch/um/scripts/Makefile.rules
19
20UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS))
21UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
22
23#XXX: partially copied from arch/um/scripts/Makefile.rules
24$(obj)/unmap.o: c_flags = -Wp,-MD,$(depfile) $(UNMAP_CFLAGS)
25
26$(obj)/unmap_fin.o : $(obj)/unmap.o
27 $(LD) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) -print-file-name=libc.a)
28 $(OBJCOPY) $(obj)/unmap_tmp.o $@ -G switcheroo
29
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 19a0ad7b35b3..37e22d71a0d9 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -153,10 +153,10 @@ void remove_gdb_cb(void *unused)
153 exit_debugger_cb(NULL); 153 exit_debugger_cb(NULL);
154} 154}
155 155
156int gdb_remove(char *unused) 156int gdb_remove(int unused)
157{ 157{
158 initial_thread_cb(remove_gdb_cb, NULL); 158 initial_thread_cb(remove_gdb_cb, NULL);
159 return(0); 159 return 0;
160} 160}
161 161
162void signal_usr1(int sig) 162void signal_usr1(int sig)
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
index 93fb121f86af..26506388a6aa 100644
--- a/arch/um/kernel/tt/gdb_kern.c
+++ b/arch/um/kernel/tt/gdb_kern.c
@@ -10,7 +10,7 @@
10#ifdef CONFIG_MCONSOLE 10#ifdef CONFIG_MCONSOLE
11 11
12extern int gdb_config(char *str); 12extern int gdb_config(char *str);
13extern int gdb_remove(char *unused); 13extern int gdb_remove(int n);
14 14
15static struct mc_device gdb_mc = { 15static struct mc_device gdb_mc = {
16 .name = "gdb", 16 .name = "gdb",
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/kernel/tt/include/debug.h
index 8eff674107ca..738435461e13 100644
--- a/arch/um/kernel/tt/include/debug.h
+++ b/arch/um/kernel/tt/include/debug.h
@@ -4,8 +4,8 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#ifndef __DEBUG_H 7#ifndef __UML_TT_DEBUG_H
8#define __DEBUG_H 8#define __UML_TT_DEBUG_H
9 9
10extern int debugger_proxy(int status, pid_t pid); 10extern int debugger_proxy(int status, pid_t pid);
11extern void child_proxy(pid_t pid, int status); 11extern void child_proxy(pid_t pid, int status);
@@ -13,17 +13,6 @@ extern void init_proxy (pid_t pid, int waiting, int status);
13extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd); 13extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
14extern void fake_child_exit(void); 14extern void fake_child_exit(void);
15extern int gdb_config(char *str); 15extern int gdb_config(char *str);
16extern int gdb_remove(char *unused); 16extern int gdb_remove(int unused);
17 17
18#endif 18#endif
19
20/*
21 * Overrides for Emacs so that we follow Linus's tabbing style.
22 * Emacs will notice this stuff at the end of the file and automatically
23 * adjust the settings for this buffer only. This must remain at the end
24 * of the file.
25 * ---------------------------------------------------------------------------
26 * Local variables:
27 * c-file-style: "linux"
28 * End:
29 */
diff --git a/arch/um/kernel/tt/include/mode-tt.h b/arch/um/kernel/tt/include/mode-tt.h
index efe462019069..e171e15fead5 100644
--- a/arch/um/kernel/tt/include/mode-tt.h
+++ b/arch/um/kernel/tt/include/mode-tt.h
@@ -13,7 +13,6 @@ enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
13extern int tracing_pid; 13extern int tracing_pid;
14 14
15extern int tracer(int (*init_proc)(void *), void *sp); 15extern int tracer(int (*init_proc)(void *), void *sp);
16extern void user_time_init_tt(void);
17extern void sig_handler_common_tt(int sig, void *sc); 16extern void sig_handler_common_tt(int sig, void *sc);
18extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); 17extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
19extern void reboot_tt(void); 18extern void reboot_tt(void);
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 776310fd5b8b..a189a2b92935 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -266,10 +266,10 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
266 } 266 }
267 267
268 if(current->thread.forking){ 268 if(current->thread.forking){
269 sc_to_sc(UPT_SC(&p->thread.regs.regs), 269 sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(&regs->regs));
270 UPT_SC(&current->thread.regs.regs));
271 SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); 270 SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
272 if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; 271 if(sp != 0)
272 SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
273 } 273 }
274 p->thread.mode.tt.extern_pid = new_pid; 274 p->thread.mode.tt.extern_pid = new_pid;
275 275
@@ -459,14 +459,3 @@ int is_valid_pid(int pid)
459 read_unlock(&tasklist_lock); 459 read_unlock(&tasklist_lock);
460 return(0); 460 return(0);
461} 461}
462
463/*
464 * Overrides for Emacs so that we follow Linus's tabbing style.
465 * Emacs will notice this stuff at the end of the file and automatically
466 * adjust the settings for this buffer only. This must remain at the end
467 * of the file.
468 * ---------------------------------------------------------------------------
469 * Local variables:
470 * c-file-style: "linux"
471 * End:
472 */
diff --git a/arch/um/kernel/tt/time.c b/arch/um/kernel/tt/time.c
deleted file mode 100644
index 8565b71b07cd..000000000000
--- a/arch/um/kernel/tt/time.c
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7#include <sys/time.h>
8#include <time_user.h>
9#include "process.h"
10#include "user.h"
11
12void user_time_init_tt(void)
13{
14 if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
15 panic("Couldn't set SIGVTALRM handler");
16 set_interval(ITIMER_VIRTUAL);
17}
18
19/*
20 * Overrides for Emacs so that we follow Linus's tabbing style.
21 * Emacs will notice this stuff at the end of the file and automatically
22 * adjust the settings for this buffer only. This must remain at the end
23 * of the file.
24 * ---------------------------------------------------------------------------
25 * Local variables:
26 * c-file-style: "linux"
27 * End:
28 */
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
index 203216ad86f1..2eefb43bc9c2 100644
--- a/arch/um/kernel/tt/tlb.c
+++ b/arch/um/kernel/tt/tlb.c
@@ -17,7 +17,7 @@
17#include "os.h" 17#include "os.h"
18#include "tlb.h" 18#include "tlb.h"
19 19
20static void do_ops(int unused, struct host_vm_op *ops, int last) 20static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
21{ 21{
22 struct host_vm_op *op; 22 struct host_vm_op *op;
23 int i; 23 int i;
@@ -55,7 +55,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
55 panic("fix_range fixing wrong address space, current = 0x%p", 55 panic("fix_range fixing wrong address space, current = 0x%p",
56 current); 56 current);
57 57
58 fix_range_common(mm, start_addr, end_addr, force, 0, do_ops); 58 fix_range_common(mm, start_addr, end_addr, force, do_ops);
59} 59}
60 60
61atomic_t vmchange_seq = ATOMIC_INIT(1); 61atomic_t vmchange_seq = ATOMIC_INIT(1);
diff --git a/arch/um/kernel/tt/unmap.c b/arch/um/kernel/tt/unmap.c
deleted file mode 100644
index 3f7aecdbe532..000000000000
--- a/arch/um/kernel/tt/unmap.c
+++ /dev/null
@@ -1,31 +0,0 @@
1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <sys/mman.h>
7
8int switcheroo(int fd, int prot, void *from, void *to, int size)
9{
10 if(munmap(to, size) < 0){
11 return(-1);
12 }
13 if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
14 return(-1);
15 }
16 if(munmap(from, size) < 0){
17 return(-1);
18 }
19 return(0);
20}
21
22/*
23 * Overrides for Emacs so that we follow Linus's tabbing style.
24 * Emacs will notice this stuff at the end of the file and automatically
25 * adjust the settings for this buffer only. This must remain at the end
26 * of the file.
27 * ---------------------------------------------------------------------------
28 * Local variables:
29 * c-file-style: "linux"
30 * End:
31 */
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 8736d098f0ee..ca2bb6f09a7d 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -38,6 +38,9 @@
38#include "choose-mode.h" 38#include "choose-mode.h"
39#include "mode_kern.h" 39#include "mode_kern.h"
40#include "mode.h" 40#include "mode.h"
41#ifdef UML_CONFIG_MODE_SKAS
42#include "skas.h"
43#endif
41 44
42#define DEFAULT_COMMAND_LINE "root=98:0" 45#define DEFAULT_COMMAND_LINE "root=98:0"
43 46
@@ -318,6 +321,7 @@ int linux_main(int argc, char **argv)
318 unsigned long avail, diff; 321 unsigned long avail, diff;
319 unsigned long virtmem_size, max_physmem; 322 unsigned long virtmem_size, max_physmem;
320 unsigned int i, add; 323 unsigned int i, add;
324 char * mode;
321 325
322 for (i = 1; i < argc; i++){ 326 for (i = 1; i < argc; i++){
323 if((i == 1) && (argv[i][0] == ' ')) continue; 327 if((i == 1) && (argv[i][0] == ' ')) continue;
@@ -338,6 +342,21 @@ int linux_main(int argc, char **argv)
338 exit(1); 342 exit(1);
339 } 343 }
340#endif 344#endif
345
346#ifndef CONFIG_MODE_SKAS
347 mode = "TT";
348#else
349 /* Show to the user the result of selection */
350 if (mode_tt)
351 mode = "TT";
352 else if (proc_mm && ptrace_faultinfo)
353 mode = "SKAS3";
354 else
355 mode = "SKAS0";
356#endif
357
358 printf("UML running in %s mode\n", mode);
359
341 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, 360 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
342 &host_task_size, &task_size); 361 &host_task_size, &task_size);
343 362
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index dd5355500bdc..b03326d391c9 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -14,19 +14,10 @@ SECTIONS
14 /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start 14 /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
15 * is remapped.*/ 15 * is remapped.*/
16 __binary_start = .; 16 __binary_start = .;
17#ifdef MODE_TT
18 .thread_private : {
19 __start_thread_private = .;
20 errno = .;
21 . += 4;
22 arch/um/kernel/tt/unmap_fin.o (.data)
23 __end_thread_private = .;
24 }
25 . = ALIGN(4096);
26 .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
27 17
28 /* We want it only if we are in MODE_TT. In both cases, however, when MODE_TT 18#ifdef MODE_TT
29 * is off the resulting binary segfaults.*/ 19 .remap_data : { UNMAP_PATH (.data .bss) }
20 .remap : { UNMAP_PATH (.text) }
30 21
31 . = ALIGN(4096); /* Init code and data */ 22 . = ALIGN(4096); /* Init code and data */
32#endif 23#endif
@@ -39,6 +30,7 @@ SECTIONS
39 _einittext = .; 30 _einittext = .;
40 } 31 }
41 . = ALIGN(4096); 32 . = ALIGN(4096);
33
42 .text : 34 .text :
43 { 35 {
44 *(.text) 36 *(.text)
@@ -48,6 +40,12 @@ SECTIONS
48 /* .gnu.warning sections are handled specially by elf32.em. */ 40 /* .gnu.warning sections are handled specially by elf32.em. */
49 *(.gnu.warning) 41 *(.gnu.warning)
50 *(.gnu.linkonce.t*) 42 *(.gnu.linkonce.t*)
43
44 . = ALIGN(4096);
45 __syscall_stub_start = .;
46 *(.__syscall_stub*)
47 __syscall_stub_end = .;
48 . = ALIGN(4096);
51 } 49 }
52 50
53 #include "asm/common.lds.S" 51 #include "asm/common.lds.S"
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index f0d6060e3e57..5423b1ca17c4 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -11,6 +11,7 @@
11#include <stddef.h> 11#include <stddef.h>
12#include "init.h" 12#include "init.h"
13#include "elf_user.h" 13#include "elf_user.h"
14#include <asm/elf.h>
14 15
15#if ELF_CLASS == ELFCLASS32 16#if ELF_CLASS == ELFCLASS32
16typedef Elf32_auxv_t elf_auxv_t; 17typedef Elf32_auxv_t elf_auxv_t;
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 9a0ad094d926..3125d320722c 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -121,6 +121,11 @@ void init_registers(int pid)
121 err); 121 err);
122} 122}
123 123
124void get_safe_registers(unsigned long *regs)
125{
126 memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long));
127}
128
124/* 129/*
125 * Overrides for Emacs so that we follow Linus's tabbing style. 130 * Overrides for Emacs so that we follow Linus's tabbing style.
126 * Emacs will notice this stuff at the end of the file and automatically 131 * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index 6286c974bbeb..44438d15c3d6 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -69,6 +69,11 @@ void init_registers(int pid)
69 err); 69 err);
70} 70}
71 71
72void get_safe_registers(unsigned long *regs)
73{
74 memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long));
75}
76
72/* 77/*
73 * Overrides for Emacs so that we follow Linus's tabbing style. 78 * Overrides for Emacs so that we follow Linus's tabbing style.
74 * Emacs will notice this stuff at the end of the file and automatically 79 * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 98346c711493..17f305b6bade 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -10,6 +10,17 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
10$(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \ 10$(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \
11 $(CFLAGS_$(notdir $@)) 11 $(CFLAGS_$(notdir $@))
12 12
13# The stubs and unmap.o can't try to call mcount or update basic block data
14define unprofile
15 $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
16endef
17
18
19# The stubs and unmap.o can't try to call mcount or update basic block data
20define unprofile
21 $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
22endef
23
13quiet_cmd_make_link = SYMLINK $@ 24quiet_cmd_make_link = SYMLINK $@
14cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@ 25cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
15 26
diff --git a/arch/um/scripts/Makefile.unmap b/arch/um/scripts/Makefile.unmap
new file mode 100644
index 000000000000..802d027a1e13
--- /dev/null
+++ b/arch/um/scripts/Makefile.unmap
@@ -0,0 +1,22 @@
1clean-files += unmap_tmp.o unmap_fin.o unmap.o
2
3ifdef CONFIG_MODE_TT
4
5#Always build unmap_fin.o
6extra-y += unmap_fin.o
7#Do dependency tracking for unmap.o (it will be always built, but won't get the tracking unless we use this).
8targets += unmap.o
9
10#XXX: partially copied from arch/um/scripts/Makefile.rules
11$(obj)/unmap.o: _c_flags = $(call unprofile,$(CFLAGS))
12
13quiet_cmd_wrapld = LD $@
14define cmd_wrapld
15 $(LD) $(LDFLAGS) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) $(CFLAGS) -print-file-name=libc.a); \
16 $(OBJCOPY) $(UML_OBJCOPYFLAGS) $(obj)/unmap_tmp.o $@ -G switcheroo
17endef
18
19$(obj)/unmap_fin.o : $(obj)/unmap.o FORCE
20 $(call if_changed,wrapld)
21
22endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 4351e5605506..77c3c4d29f55 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,6 +1,6 @@
1obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ 1obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
2 ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \ 2 ptrace_user.o semaphore.o signal.o sigcontext.o stub.o stub_segv.o \
3 sys_call_table.o 3 syscalls.o sysrq.o sys_call_table.o
4 4
5obj-$(CONFIG_HIGHMEM) += highmem.o 5obj-$(CONFIG_HIGHMEM) += highmem.o
6obj-$(CONFIG_MODULES) += module.o 6obj-$(CONFIG_MODULES) += module.o
@@ -16,4 +16,14 @@ semaphore.c-dir = kernel
16highmem.c-dir = mm 16highmem.c-dir = mm
17module.c-dir = kernel 17module.c-dir = kernel
18 18
19STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
20
21# _cflags works with kernel files, not with userspace ones, but c_flags does,
22# why ask why?
23$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
24
25$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
26
19subdir- := util 27subdir- := util
28
29include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index dc755b0b9db8..bd3c34aa52e5 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -4,96 +4,106 @@
4 */ 4 */
5 5
6#include "linux/config.h" 6#include "linux/config.h"
7#include "linux/sched.h"
7#include "linux/slab.h" 8#include "linux/slab.h"
9#include "linux/types.h"
8#include "asm/uaccess.h" 10#include "asm/uaccess.h"
9#include "asm/ptrace.h" 11#include "asm/ptrace.h"
12#include "asm/smp.h"
13#include "asm/ldt.h"
10#include "choose-mode.h" 14#include "choose-mode.h"
11#include "kern.h" 15#include "kern.h"
16#include "mode_kern.h"
12 17
13#ifdef CONFIG_MODE_TT 18#ifdef CONFIG_MODE_TT
14extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
15 19
16/* XXX this needs copy_to_user and copy_from_user */ 20extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
17 21
18int sys_modify_ldt_tt(int func, void __user *ptr, unsigned long bytecount) 22static int do_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
19{ 23{
20 if (!access_ok(VERIFY_READ, ptr, bytecount))
21 return -EFAULT;
22
23 return modify_ldt(func, ptr, bytecount); 24 return modify_ldt(func, ptr, bytecount);
24} 25}
26
25#endif 27#endif
26 28
27#ifdef CONFIG_MODE_SKAS 29#ifdef CONFIG_MODE_SKAS
28extern int userspace_pid[];
29 30
31#include "skas.h"
30#include "skas_ptrace.h" 32#include "skas_ptrace.h"
31 33
32int sys_modify_ldt_skas(int func, void __user *ptr, unsigned long bytecount) 34static int do_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
33{ 35{
34 struct ptrace_ldt ldt; 36 struct ptrace_ldt ldt;
35 void *buf; 37 u32 cpu;
36 int res, n; 38 int res;
37 39
38 buf = kmalloc(bytecount, GFP_KERNEL); 40 ldt = ((struct ptrace_ldt) { .func = func,
39 if(buf == NULL) 41 .ptr = ptr,
40 return(-ENOMEM); 42 .bytecount = bytecount });
41 43
42 res = 0; 44 cpu = get_cpu();
45 res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, (unsigned long) &ldt);
46 put_cpu();
47
48 return res;
49}
50#endif
51
52int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
53{
54 struct user_desc info;
55 int res = 0;
56 void *buf = NULL;
57 void *p = NULL; /* What we pass to host. */
43 58
44 switch(func){ 59 switch(func){
45 case 1: 60 case 1:
46 case 0x11: 61 case 0x11: /* write_ldt */
47 res = copy_from_user(buf, ptr, bytecount); 62 /* Do this check now to avoid overflows. */
48 break; 63 if (bytecount != sizeof(struct user_desc)) {
49 } 64 res = -EINVAL;
65 goto out;
66 }
67
68 if(copy_from_user(&info, ptr, sizeof(info))) {
69 res = -EFAULT;
70 goto out;
71 }
50 72
51 if(res != 0){ 73 p = &info;
52 res = -EFAULT; 74 break;
75 case 0:
76 case 2: /* read_ldt */
77
78 /* The use of info avoids kmalloc on the write case, not on the
79 * read one. */
80 buf = kmalloc(bytecount, GFP_KERNEL);
81 if (!buf) {
82 res = -ENOMEM;
83 goto out;
84 }
85 p = buf;
86 default:
87 res = -ENOSYS;
53 goto out; 88 goto out;
54 } 89 }
55 90
56 ldt = ((struct ptrace_ldt) { .func = func, 91 res = CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
57 .ptr = buf, 92 p, bytecount);
58 .bytecount = bytecount });
59#warning Need to look up userspace_pid by cpu
60 res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt);
61 if(res < 0) 93 if(res < 0)
62 goto out; 94 goto out;
63 95
64 switch(func){ 96 switch(func){
65 case 0: 97 case 0:
66 case 2: 98 case 2:
67 n = res; 99 /* Modify_ldt was for reading and returned the number of read
68 res = copy_to_user(ptr, buf, n); 100 * bytes.*/
69 if(res != 0) 101 if(copy_to_user(ptr, p, res))
70 res = -EFAULT; 102 res = -EFAULT;
71 else
72 res = n;
73 break; 103 break;
74 } 104 }
75 105
76 out: 106out:
77 kfree(buf); 107 kfree(buf);
78 return(res); 108 return res;
79}
80#endif
81
82int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
83{
84 return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func,
85 ptr, bytecount));
86} 109}
87
88
89
90/*
91 * Overrides for Emacs so that we follow Linus's tabbing style.
92 * Emacs will notice this stuff at the end of the file and automatically
93 * adjust the settings for this buffer only. This must remain at the end
94 * of the file.
95 * ---------------------------------------------------------------------------
96 * Local variables:
97 * c-file-style: "linux"
98 * End:
99 */
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 03913ca5d256..4efc69a039d7 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -312,7 +312,7 @@ long sys_sigreturn(struct pt_regs regs)
312 unsigned long __user *extramask = frame->extramask; 312 unsigned long __user *extramask = frame->extramask;
313 int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); 313 int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
314 314
315 if(copy_from_user(&set.sig[0], oldmask, sizeof(&set.sig[0])) || 315 if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
316 copy_from_user(&set.sig[1], extramask, sig_size)) 316 copy_from_user(&set.sig[1], extramask, sig_size))
317 goto segfault; 317 goto segfault;
318 318
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
new file mode 100644
index 000000000000..2f2c70a8f043
--- /dev/null
+++ b/arch/um/sys-i386/stub.S
@@ -0,0 +1,8 @@
1#include "uml-config.h"
2
3 .globl syscall_stub
4.section .__syscall_stub, "x"
5syscall_stub:
6 int $0x80
7 mov %eax, UML_CONFIG_STUB_DATA
8 int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
new file mode 100644
index 000000000000..b251442ad0b1
--- /dev/null
+++ b/arch/um/sys-i386/stub_segv.c
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7#include <asm/sigcontext.h>
8#include <asm/unistd.h>
9#include "uml-config.h"
10#include "sysdep/sigcontext.h"
11#include "sysdep/faultinfo.h"
12
13void __attribute__ ((__section__ (".__syscall_stub")))
14stub_segv_handler(int sig)
15{
16 struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
17
18 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
19 sc);
20
21 __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid));
22 __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;"
23 "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1));
24 /* Pop the frame pointer and return address since we need to leave
25 * the stack in its original form when we do the sigreturn here, by
26 * hand.
27 */
28 __asm__("popl %%eax ; popl %%eax ; popl %%eax ; movl %0, %%eax ; "
29 "int $0x80" : : "g" (__NR_sigreturn));
30}
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index 335e2d89504d..83e9be820a86 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -69,15 +69,11 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
69{ 69{
70 long ret; 70 long ret;
71 71
72 /* XXX: normal arch do here this pass, and also pass the regs to 72 if (!newsp)
73 * do_fork, instead of NULL. Currently the arch-independent code 73 newsp = UPT_SP(&current->thread.regs.regs);
74 * ignores these values, while the UML code (actually it's
75 * copy_thread) does the right thing. But this should change,
76 probably. */
77 /*if (!newsp)
78 newsp = UPT_SP(current->thread.regs);*/
79 current->thread.forking = 1; 74 current->thread.forking = 1;
80 ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid); 75 ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
76 child_tid);
81 current->thread.forking = 0; 77 current->thread.forking = 0;
82 return(ret); 78 return(ret);
83} 79}
@@ -197,14 +193,3 @@ long sys_sigaction(int sig, const struct old_sigaction __user *act,
197 193
198 return ret; 194 return ret;
199} 195}
200
201/*
202 * Overrides for Emacs so that we follow Linus's tabbing style.
203 * Emacs will notice this stuff at the end of the file and automatically
204 * adjust the settings for this buffer only. This must remain at the end
205 * of the file.
206 * ---------------------------------------------------------------------------
207 * Local variables:
208 * c-file-style: "linux"
209 * End:
210 */
diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c
new file mode 100644
index 000000000000..1b0ad0e4adcd
--- /dev/null
+++ b/arch/um/sys-i386/unmap.c
@@ -0,0 +1,25 @@
1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <linux/mman.h>
7#include <asm/unistd.h>
8
9static int errno;
10
11static inline _syscall2(int,munmap,void *,start,size_t,len)
12static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
13int switcheroo(int fd, int prot, void *from, void *to, int size)
14{
15 if(munmap(to, size) < 0){
16 return(-1);
17 }
18 if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){
19 return(-1);
20 }
21 if(munmap(from, size) < 0){
22 return(-1);
23 }
24 return(0);
25}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 608466ad6b22..7488206ce6f4 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -6,8 +6,8 @@
6 6
7#XXX: why into lib-y? 7#XXX: why into lib-y?
8lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \ 8lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
9 ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \ 9 ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o stub.o \
10 syscalls.o sysrq.o thunk.o syscall_table.o 10 stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o
11 11
12obj-y := ksyms.o 12obj-y := ksyms.o
13obj-$(CONFIG_MODULES) += module.o um_module.o 13obj-$(CONFIG_MODULES) += module.o um_module.o
@@ -28,4 +28,14 @@ semaphore.c-dir = kernel
28thunk.S-dir = lib 28thunk.S-dir = lib
29module.c-dir = kernel 29module.c-dir = kernel
30 30
31STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
32
33# _cflags works with kernel files, not with userspace ones, but c_flags does,
34# why ask why?
35$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
36
37$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
38
31subdir- := util 39subdir- := util
40
41include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 73a7926f7370..8fdaed06c10d 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -168,7 +168,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
168 168
169 frame = (struct rt_sigframe __user *) 169 frame = (struct rt_sigframe __user *)
170 round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8; 170 round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
171 ((unsigned char *) frame) -= 128; 171 frame = (struct rt_sigframe *) ((unsigned long) frame - 128);
172 172
173 if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) 173 if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
174 goto out; 174 goto out;
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
new file mode 100644
index 000000000000..31c14925716b
--- /dev/null
+++ b/arch/um/sys-x86_64/stub.S
@@ -0,0 +1,15 @@
1#include "uml-config.h"
2
3 .globl syscall_stub
4.section .__syscall_stub, "x"
5syscall_stub:
6 syscall
7 /* We don't have 64-bit constants, so this constructs the address
8 * we need.
9 */
10 movq $(UML_CONFIG_STUB_DATA >> 32), %rbx
11 salq $32, %rbx
12 movq $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx
13 or %rcx, %rbx
14 movq %rax, (%rbx)
15 int3
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
new file mode 100644
index 000000000000..161d1fe9c034
--- /dev/null
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7#include <linux/compiler.h>
8#include <asm/unistd.h>
9#include "uml-config.h"
10#include "sysdep/sigcontext.h"
11#include "sysdep/faultinfo.h"
12
13void __attribute__ ((__section__ (".__syscall_stub")))
14stub_segv_handler(int sig)
15{
16 struct ucontext *uc;
17
18 __asm__("movq %%rdx, %0" : "=g" (uc) :);
19 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
20 &uc->uc_mcontext);
21
22 __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid));
23 __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;"
24 "syscall": : "g" (__NR_kill), "g" (SIGUSR1));
25 /* Two popqs to restore the stack to the state just before entering
26 * the handler, one pops the return address, the other pops the frame
27 * pointer.
28 */
29 __asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g"
30 (__NR_rt_sigreturn));
31}
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 6f44f40204ed..3259a4db4534 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -174,26 +174,11 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
174{ 174{
175 long ret; 175 long ret;
176 176
177 /* XXX: normal arch do here this pass, and also pass the regs to 177 if (!newsp)
178 * do_fork, instead of NULL. Currently the arch-independent code 178 newsp = UPT_SP(&current->thread.regs.regs);
179 * ignores these values, while the UML code (actually it's
180 * copy_thread) does the right thing. But this should change,
181 probably. */
182 /*if (!newsp)
183 newsp = UPT_SP(current->thread.regs);*/
184 current->thread.forking = 1; 179 current->thread.forking = 1;
185 ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid); 180 ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
181 child_tid);
186 current->thread.forking = 0; 182 current->thread.forking = 0;
187 return(ret); 183 return(ret);
188} 184}
189
190/*
191 * Overrides for Emacs so that we follow Linus's tabbing style.
192 * Emacs will notice this stuff at the end of the file and automatically
193 * adjust the settings for this buffer only. This must remain at the end
194 * of the file.
195 * ---------------------------------------------------------------------------
196 * Local variables:
197 * c-file-style: "linux"
198 * End:
199 */
diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c
new file mode 100644
index 000000000000..f4a4bffd8a18
--- /dev/null
+++ b/arch/um/sys-x86_64/unmap.c
@@ -0,0 +1,25 @@
1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <linux/mman.h>
7#include <asm/unistd.h>
8
9static int errno;
10
11static inline _syscall2(int,munmap,void *,start,size_t,len)
12static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
13int switcheroo(int fd, int prot, void *from, void *to, int size)
14{
15 if(munmap(to, size) < 0){
16 return(-1);
17 }
18 if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){
19 return(-1);
20 }
21 if(munmap(from, size) < 0){
22 return(-1);
23 }
24 return(0);
25}