aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig53
-rw-r--r--arch/um/Kconfig.i38616
-rw-r--r--arch/um/Makefile30
-rw-r--r--arch/um/Makefile-i3861
-rw-r--r--arch/um/Makefile-x86_644
-rw-r--r--arch/um/drivers/chan_kern.c280
-rw-r--r--arch/um/drivers/chan_user.c2
-rw-r--r--arch/um/drivers/daemon_kern.c4
-rw-r--r--arch/um/drivers/daemon_user.c12
-rw-r--r--arch/um/drivers/fd.c10
-rw-r--r--arch/um/drivers/line.c298
-rw-r--r--arch/um/drivers/mcast_user.c20
-rw-r--r--arch/um/drivers/mconsole_kern.c232
-rw-r--r--arch/um/drivers/mconsole_user.c12
-rw-r--r--arch/um/drivers/net_kern.c29
-rw-r--r--arch/um/drivers/port_user.c9
-rw-r--r--arch/um/drivers/pty.c11
-rw-r--r--arch/um/drivers/ssl.c47
-rw-r--r--arch/um/drivers/stdio_console.c33
-rw-r--r--arch/um/drivers/tty.c9
-rw-r--r--arch/um/drivers/ubd_kern.c96
-rw-r--r--arch/um/drivers/xterm.c9
-rw-r--r--arch/um/include/chan_kern.h25
-rw-r--r--arch/um/include/chan_user.h4
-rw-r--r--arch/um/include/choose-mode.h3
-rw-r--r--arch/um/include/irq_user.h13
-rw-r--r--arch/um/include/kern.h13
-rw-r--r--arch/um/include/kern_util.h23
-rw-r--r--arch/um/include/line.h37
-rw-r--r--arch/um/include/longjmp.h19
-rw-r--r--arch/um/include/mconsole.h8
-rw-r--r--arch/um/include/mode_kern.h15
-rw-r--r--arch/um/include/os.h91
-rw-r--r--arch/um/include/signal_user.h28
-rw-r--r--arch/um/include/skas/mm_id.h (renamed from arch/um/kernel/skas/include/mm_id.h)0
-rw-r--r--arch/um/include/skas/mmu-skas.h24
-rw-r--r--arch/um/include/skas/mode-skas.h19
-rw-r--r--arch/um/include/skas/mode_kern_skas.h (renamed from arch/um/kernel/skas/include/mode_kern-skas.h)12
-rw-r--r--arch/um/include/skas/proc_mm.h (renamed from arch/um/kernel/skas/include/proc_mm.h)17
-rw-r--r--arch/um/include/skas/skas.h26
-rw-r--r--arch/um/include/skas/stub-data.h (renamed from arch/um/kernel/skas/include/stub-data.h)0
-rw-r--r--arch/um/include/skas/uaccess-skas.h21
-rw-r--r--arch/um/include/sysdep-i386/checksum.h4
-rw-r--r--arch/um/include/sysdep-i386/kernel-offsets.h (renamed from arch/um/sys-i386/kernel-offsets.c)5
-rw-r--r--arch/um/include/sysdep-i386/stub.h38
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h (renamed from arch/um/sys-x86_64/kernel-offsets.c)2
-rw-r--r--arch/um/include/sysdep-x86_64/stub.h42
-rw-r--r--arch/um/include/time_user.h19
-rw-r--r--arch/um/include/tt/debug.h (renamed from arch/um/kernel/tt/include/debug.h)2
-rw-r--r--arch/um/include/tt/mmu-tt.h12
-rw-r--r--arch/um/include/tt/mode-tt.h23
-rw-r--r--arch/um/include/tt/mode_kern_tt.h41
-rw-r--r--arch/um/include/tt/tt.h (renamed from arch/um/kernel/tt/include/tt.h)12
-rw-r--r--arch/um/include/tt/uaccess-tt.h (renamed from arch/um/kernel/tt/include/uaccess-tt.h)19
-rw-r--r--arch/um/include/um_uaccess.h21
-rw-r--r--arch/um/include/user.h1
-rw-r--r--arch/um/include/user_util.h29
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/asm-offsets.c2
-rw-r--r--arch/um/kernel/exec_kern.c1
-rw-r--r--arch/um/kernel/irq_user.c49
-rw-r--r--arch/um/kernel/process_kern.c29
-rw-r--r--arch/um/kernel/reboot.c2
-rw-r--r--arch/um/kernel/sigio_user.c85
-rw-r--r--arch/um/kernel/signal_kern.c92
-rw-r--r--arch/um/kernel/signal_user.c157
-rw-r--r--arch/um/kernel/skas/Makefile8
-rw-r--r--arch/um/kernel/skas/clone.c28
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h35
-rw-r--r--arch/um/kernel/skas/include/mode-skas.h33
-rw-r--r--arch/um/kernel/skas/include/skas.h50
-rw-r--r--arch/um/kernel/skas/include/uaccess-skas.h39
-rw-r--r--arch/um/kernel/skas/mmu.c8
-rw-r--r--arch/um/kernel/skas/process.c16
-rw-r--r--arch/um/kernel/skas/process_kern.c40
-rw-r--r--arch/um/kernel/skas/uaccess.c10
-rw-r--r--arch/um/kernel/syscall.c4
-rw-r--r--arch/um/kernel/time.c9
-rw-r--r--arch/um/kernel/time_kern.c132
-rw-r--r--arch/um/kernel/trap_kern.c34
-rw-r--r--arch/um/kernel/trap_user.c98
-rw-r--r--arch/um/kernel/tt/exec_kern.c4
-rw-r--r--arch/um/kernel/tt/gdb.c1
-rw-r--r--arch/um/kernel/tt/include/mmu-tt.h23
-rw-r--r--arch/um/kernel/tt/process_kern.c10
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c1
-rw-r--r--arch/um/kernel/tt/tracer.c1
-rw-r--r--arch/um/kernel/tt/trap_user.c21
-rw-r--r--arch/um/kernel/tt/uaccess.c8
-rw-r--r--arch/um/kernel/um_arch.c15
-rw-r--r--arch/um/kernel/umid.c323
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/aio.c467
-rw-r--r--arch/um/os-Linux/helper.c4
-rw-r--r--arch/um/os-Linux/main.c14
-rw-r--r--arch/um/os-Linux/process.c31
-rw-r--r--arch/um/os-Linux/signal.c246
-rw-r--r--arch/um/os-Linux/skas/Makefile10
-rw-r--r--arch/um/os-Linux/skas/mem.c (renamed from arch/um/kernel/skas/mem_user.c)202
-rw-r--r--arch/um/os-Linux/skas/process.c566
-rw-r--r--arch/um/os-Linux/skas/trap.c (renamed from arch/um/kernel/skas/trap_user.c)49
-rw-r--r--arch/um/os-Linux/start_up.c24
-rw-r--r--arch/um/os-Linux/time.c131
-rw-r--r--arch/um/os-Linux/trap.c41
-rw-r--r--arch/um/os-Linux/tt.c64
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/umid.c335
-rw-r--r--arch/um/os-Linux/user_syms.c5
-rw-r--r--arch/um/os-Linux/util.c (renamed from arch/um/kernel/user_util.c)69
-rw-r--r--arch/um/scripts/Makefile.rules5
-rw-r--r--arch/um/sys-i386/Makefile10
-rw-r--r--arch/um/sys-i386/ldt.c61
-rw-r--r--arch/um/sys-i386/signal.c1
-rw-r--r--arch/um/sys-i386/stub_segv.c11
-rw-r--r--arch/um/sys-x86_64/Makefile7
-rw-r--r--arch/um/sys-x86_64/stub_segv.c20
117 files changed, 3258 insertions, 2388 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 3b5f47c469..5982fe2753 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -7,7 +7,6 @@ config UML
7 bool 7 bool
8 default y 8 default y
9 9
10# XXX: does UM have a mmu/swap?
11config MMU 10config MMU
12 bool 11 bool
13 default y 12 default y
@@ -23,10 +22,6 @@ config SBUS
23config PCI 22config PCI
24 bool 23 bool
25 24
26config UID16
27 bool
28 default y
29
30config GENERIC_CALIBRATE_DELAY 25config GENERIC_CALIBRATE_DELAY
31 bool 26 bool
32 default y 27 default y
@@ -36,22 +31,16 @@ config IRQ_RELEASE_METHOD
36 bool 31 bool
37 default y 32 default y
38 33
39menu "Host processor type and features"
40
41source "arch/i386/Kconfig.cpu"
42
43endmenu
44
45menu "UML-specific options" 34menu "UML-specific options"
46 35
47config MODE_TT 36config MODE_TT
48 bool "Tracing thread support" 37 bool "Tracing thread support"
49 default y 38 default n
50 help 39 help
51 This option controls whether tracing thread support is compiled 40 This option controls whether tracing thread support is compiled
52 into UML. Normally, this should be set to Y. If you intend to 41 into UML. This option is largely obsolete, given that skas0 provides
53 use only skas mode (and the host has the skas patch applied to it), 42 skas security and performance without needing to patch the host.
54 then it is OK to say N here. 43 It is safe to say 'N' here.
55 44
56config STATIC_LINK 45config STATIC_LINK
57 bool "Force a static link" 46 bool "Force a static link"
@@ -90,7 +79,7 @@ config KERNEL_HALF_GIGS
90 of physical memory. 79 of physical memory.
91 80
92config MODE_SKAS 81config MODE_SKAS
93 bool "Separate Kernel Address Space support" 82 bool "Separate Kernel Address Space support" if MODE_TT
94 default y 83 default y
95 help 84 help
96 This option controls whether skas (separate kernel address space) 85 This option controls whether skas (separate kernel address space)
@@ -154,6 +143,7 @@ config HOSTFS
154 143
155config HPPFS 144config HPPFS
156 tristate "HoneyPot ProcFS (EXPERIMENTAL)" 145 tristate "HoneyPot ProcFS (EXPERIMENTAL)"
146 depends on EXPERIMENTAL
157 help 147 help
158 hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc 148 hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
159 entries to be overridden, removed, or fabricated from the host. 149 entries to be overridden, removed, or fabricated from the host.
@@ -166,10 +156,6 @@ config HPPFS
166 You only need this if you are setting up a UML honeypot. Otherwise, 156 You only need this if you are setting up a UML honeypot. Otherwise,
167 it is safe to say 'N' here. 157 it is safe to say 'N' here.
168 158
169 If you are actively using it, please report any problems, since it's
170 getting fixed. In this moment, it is experimental on 2.6 (it works on
171 2.4).
172
173config MCONSOLE 159config MCONSOLE
174 bool "Management console" 160 bool "Management console"
175 default y 161 default y
@@ -209,7 +195,8 @@ config MAGIC_SYSRQ
209config SMP 195config SMP
210 bool "Symmetric multi-processing support (EXPERIMENTAL)" 196 bool "Symmetric multi-processing support (EXPERIMENTAL)"
211 default n 197 default n
212 depends on (MODE_TT && EXPERIMENTAL && !SMP_BROKEN) || (BROKEN && SMP_BROKEN) 198 #SMP_BROKEN is for x86_64.
199 depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
213 help 200 help
214 This option enables UML SMP support. 201 This option enables UML SMP support.
215 It is NOT related to having a real SMP box. Not directly, at least. 202 It is NOT related to having a real SMP box. Not directly, at least.
@@ -253,8 +240,16 @@ config NEST_LEVEL
253 Only change this if you are running nested UMLs. 240 Only change this if you are running nested UMLs.
254 241
255config HIGHMEM 242config HIGHMEM
256 bool "Highmem support" 243 bool "Highmem support (EXPERIMENTAL)"
257 depends on !64BIT 244 depends on !64BIT && EXPERIMENTAL
245 default n
246 help
247 This was used to allow UML to run with big amounts of memory.
248 Currently it is unstable, so if unsure say N.
249
250 To use big amounts of memory, it is recommended to disable TT mode (i.e.
251 CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) -
252 this should allow the guest to use up to 2.75G of memory.
258 253
259config KERNEL_STACK_ORDER 254config KERNEL_STACK_ORDER
260 int "Kernel stack size order" 255 int "Kernel stack size order"
@@ -279,22 +274,20 @@ endmenu
279 274
280source "init/Kconfig" 275source "init/Kconfig"
281 276
282source "net/Kconfig" 277source "drivers/block/Kconfig"
283
284source "drivers/base/Kconfig"
285 278
286source "arch/um/Kconfig.char" 279source "arch/um/Kconfig.char"
287 280
288source "drivers/block/Kconfig" 281source "drivers/base/Kconfig"
289 282
290config NETDEVICES 283source "net/Kconfig"
291 bool
292 default NET
293 284
294source "arch/um/Kconfig.net" 285source "arch/um/Kconfig.net"
295 286
296source "drivers/net/Kconfig" 287source "drivers/net/Kconfig"
297 288
289source "drivers/connector/Kconfig"
290
298source "fs/Kconfig" 291source "fs/Kconfig"
299 292
300source "security/Kconfig" 293source "security/Kconfig"
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index 5d92cacd56..ef79ed25ae 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -1,3 +1,9 @@
1menu "Host processor type and features"
2
3source "arch/i386/Kconfig.cpu"
4
5endmenu
6
1config UML_X86 7config UML_X86
2 bool 8 bool
3 default y 9 default y
@@ -16,13 +22,17 @@ config TOP_ADDR
16 default 0x80000000 if HOST_2G_2G 22 default 0x80000000 if HOST_2G_2G
17 23
18config 3_LEVEL_PGTABLES 24config 3_LEVEL_PGTABLES
19 bool "Three-level pagetables" 25 bool "Three-level pagetables (EXPERIMENTAL)"
20 default n 26 default n
27 depends on EXPERIMENTAL
21 help 28 help
22 Three-level pagetables will let UML have more than 4G of physical 29 Three-level pagetables will let UML have more than 4G of physical
23 memory. All the memory that can't be mapped directly will be treated 30 memory. All the memory that can't be mapped directly will be treated
24 as high memory. 31 as high memory.
25 32
33 However, this it experimental on 32-bit architectures, so if unsure say
34 N (on x86-64 it's automatically enabled, instead, as it's safe there).
35
26config STUB_CODE 36config STUB_CODE
27 hex 37 hex
28 default 0xbfffe000 38 default 0xbfffe000
@@ -42,7 +52,3 @@ config ARCH_HAS_SC_SIGNALS
42config ARCH_REUSE_HOST_VSYSCALL_AREA 52config ARCH_REUSE_HOST_VSYSCALL_AREA
43 bool 53 bool
44 default y 54 default y
45
46config X86_CMPXCHG
47 bool
48 default y
diff --git a/arch/um/Makefile b/arch/um/Makefile
index e55d32e903..6430a63838 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -17,7 +17,7 @@ core-y += $(ARCH_DIR)/kernel/ \
17 17
18# Have to precede the include because the included Makefiles reference them. 18# Have to precede the include because the included Makefiles reference them.
19SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \ 19SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \
20 module.h vm-flags.h elf.h 20 module.h vm-flags.h elf.h ldt.h
21SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) 21SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
22 22
23# XXX: The "os" symlink is only used by arch/um/include/os.h, which includes 23# XXX: The "os" symlink is only used by arch/um/include/os.h, which includes
@@ -32,7 +32,7 @@ um-modes-$(CONFIG_MODE_TT) += tt
32um-modes-$(CONFIG_MODE_SKAS) += skas 32um-modes-$(CONFIG_MODE_SKAS) += skas
33 33
34MODE_INCLUDE += $(foreach mode,$(um-modes-y),\ 34MODE_INCLUDE += $(foreach mode,$(um-modes-y),\
35 -I$(srctree)/$(ARCH_DIR)/kernel/$(mode)/include) 35 -I$(srctree)/$(ARCH_DIR)/include/$(mode))
36 36
37MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\ 37MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\
38 $(srctree)/$(ARCH_DIR)/Makefile-$(mode)) 38 $(srctree)/$(ARCH_DIR)/Makefile-$(mode))
@@ -67,7 +67,8 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
67# in CFLAGS. Otherwise, it would cause ld to complain about the two different 67# in CFLAGS. Otherwise, it would cause ld to complain about the two different
68# errnos. 68# errnos.
69 69
70CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask 70CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
71 -Dmktime=kernel_mktime
71CFLAGS += $(call cc-option,-fno-unit-at-a-time,) 72CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
72 73
73include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) 74include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -189,6 +190,12 @@ define filechk_umlconfig
189 sed 's/ CONFIG/ UML_CONFIG/' 190 sed 's/ CONFIG/ UML_CONFIG/'
190endef 191endef
191 192
193$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
194 $(call filechk,umlconfig)
195
196$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
197 $(CC) $(USER_CFLAGS) -S -o $@ $<
198
192define filechk_gen-asm-offsets 199define filechk_gen-asm-offsets
193 (set -e; \ 200 (set -e; \
194 echo "/*"; \ 201 echo "/*"; \
@@ -202,24 +209,13 @@ define filechk_gen-asm-offsets
202 echo ""; ) 209 echo ""; )
203endef 210endef
204 211
205$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
206 $(call filechk,umlconfig)
207
208$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
209 $(CC) $(USER_CFLAGS) -S -o $@ $<
210
211$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s 212$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s
212 $(call filechk,gen-asm-offsets) 213 $(call filechk,gen-asm-offsets)
213 214
214CLEAN_FILES += $(ARCH_DIR)/user-offsets.s 215CLEAN_FILES += $(ARCH_DIR)/user-offsets.s
215 216
216$(ARCH_DIR)/kernel-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/kernel-offsets.c \ 217$(ARCH_DIR)/include/kern_constants.h:
217 archprepare 218 @echo ' SYMLINK $@'
218 $(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $< 219 $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@
219
220$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/kernel-offsets.s
221 $(call filechk,gen-asm-offsets)
222
223CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s
224 220
225export SUBARCH USER_CFLAGS OS 221export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index 1f7dcb064a..7a0e04e34b 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -35,4 +35,3 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
35 35
36CFLAGS += $(cflags-y) 36CFLAGS += $(cflags-y)
37USER_CFLAGS += $(cflags-y) 37USER_CFLAGS += $(cflags-y)
38
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 4f118d5cc2..38df311e75 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -12,3 +12,7 @@ CHECKFLAGS += -m64
12 12
13ELF_ARCH := i386:x86-64 13ELF_ARCH := i386:x86-64
14ELF_FORMAT := elf64-x86-64 14ELF_FORMAT := elf64-x86-64
15
16# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
17
18LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 16e7dc89f6..ab0d0b1708 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -58,7 +58,7 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
58{ 58{
59 my_puts("Using a channel type which is configured out of " 59 my_puts("Using a channel type which is configured out of "
60 "UML\n"); 60 "UML\n");
61 return(NULL); 61 return NULL;
62} 62}
63 63
64static int not_configged_open(int input, int output, int primary, void *data, 64static int not_configged_open(int input, int output, int primary, void *data,
@@ -66,7 +66,7 @@ static int not_configged_open(int input, int output, int primary, void *data,
66{ 66{
67 my_puts("Using a channel type which is configured out of " 67 my_puts("Using a channel type which is configured out of "
68 "UML\n"); 68 "UML\n");
69 return(-ENODEV); 69 return -ENODEV;
70} 70}
71 71
72static void not_configged_close(int fd, void *data) 72static void not_configged_close(int fd, void *data)
@@ -79,22 +79,21 @@ static int not_configged_read(int fd, char *c_out, void *data)
79{ 79{
80 my_puts("Using a channel type which is configured out of " 80 my_puts("Using a channel type which is configured out of "
81 "UML\n"); 81 "UML\n");
82 return(-EIO); 82 return -EIO;
83} 83}
84 84
85static int not_configged_write(int fd, const char *buf, int len, void *data) 85static int not_configged_write(int fd, const char *buf, int len, void *data)
86{ 86{
87 my_puts("Using a channel type which is configured out of " 87 my_puts("Using a channel type which is configured out of "
88 "UML\n"); 88 "UML\n");
89 return(-EIO); 89 return -EIO;
90} 90}
91 91
92static int not_configged_console_write(int fd, const char *buf, int len, 92static int not_configged_console_write(int fd, const char *buf, int len)
93 void *data)
94{ 93{
95 my_puts("Using a channel type which is configured out of " 94 my_puts("Using a channel type which is configured out of "
96 "UML\n"); 95 "UML\n");
97 return(-EIO); 96 return -EIO;
98} 97}
99 98
100static int not_configged_window_size(int fd, void *data, unsigned short *rows, 99static int not_configged_window_size(int fd, void *data, unsigned short *rows,
@@ -102,7 +101,7 @@ static int not_configged_window_size(int fd, void *data, unsigned short *rows,
102{ 101{
103 my_puts("Using a channel type which is configured out of " 102 my_puts("Using a channel type which is configured out of "
104 "UML\n"); 103 "UML\n");
105 return(-ENODEV); 104 return -ENODEV;
106} 105}
107 106
108static void not_configged_free(void *data) 107static void not_configged_free(void *data)
@@ -136,17 +135,17 @@ int generic_read(int fd, char *c_out, void *unused)
136 n = os_read_file(fd, c_out, sizeof(*c_out)); 135 n = os_read_file(fd, c_out, sizeof(*c_out));
137 136
138 if(n == -EAGAIN) 137 if(n == -EAGAIN)
139 return(0); 138 return 0;
140 else if(n == 0) 139 else if(n == 0)
141 return(-EIO); 140 return -EIO;
142 return(n); 141 return n;
143} 142}
144 143
145/* XXX Trivial wrapper around os_write_file */ 144/* XXX Trivial wrapper around os_write_file */
146 145
147int generic_write(int fd, const char *buf, int n, void *unused) 146int generic_write(int fd, const char *buf, int n, void *unused)
148{ 147{
149 return(os_write_file(fd, buf, n)); 148 return os_write_file(fd, buf, n);
150} 149}
151 150
152int generic_window_size(int fd, void *unused, unsigned short *rows_out, 151int generic_window_size(int fd, void *unused, unsigned short *rows_out,
@@ -157,14 +156,14 @@ int generic_window_size(int fd, void *unused, unsigned short *rows_out,
157 156
158 ret = os_window_size(fd, &rows, &cols); 157 ret = os_window_size(fd, &rows, &cols);
159 if(ret < 0) 158 if(ret < 0)
160 return(ret); 159 return ret;
161 160
162 ret = ((*rows_out != rows) || (*cols_out != cols)); 161 ret = ((*rows_out != rows) || (*cols_out != cols));
163 162
164 *rows_out = rows; 163 *rows_out = rows;
165 *cols_out = cols; 164 *cols_out = cols;
166 165
167 return(ret); 166 return ret;
168} 167}
169 168
170void generic_free(void *data) 169void generic_free(void *data)
@@ -187,25 +186,26 @@ static void tty_receive_char(struct tty_struct *tty, char ch)
187 } 186 }
188 } 187 }
189 188
190 if((tty->flip.flag_buf_ptr == NULL) ||
191 (tty->flip.char_buf_ptr == NULL))
192 return;
193 tty_insert_flip_char(tty, ch, TTY_NORMAL); 189 tty_insert_flip_char(tty, ch, TTY_NORMAL);
194} 190}
195 191
196static int open_one_chan(struct chan *chan, int input, int output, int primary) 192static int open_one_chan(struct chan *chan)
197{ 193{
198 int fd; 194 int fd;
199 195
200 if(chan->opened) return(0); 196 if(chan->opened)
201 if(chan->ops->open == NULL) fd = 0; 197 return 0;
202 else fd = (*chan->ops->open)(input, output, primary, chan->data, 198
203 &chan->dev); 199 if(chan->ops->open == NULL)
204 if(fd < 0) return(fd); 200 fd = 0;
201 else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary,
202 chan->data, &chan->dev);
203 if(fd < 0)
204 return fd;
205 chan->fd = fd; 205 chan->fd = fd;
206 206
207 chan->opened = 1; 207 chan->opened = 1;
208 return(0); 208 return 0;
209} 209}
210 210
211int open_chan(struct list_head *chans) 211int open_chan(struct list_head *chans)
@@ -216,11 +216,11 @@ int open_chan(struct list_head *chans)
216 216
217 list_for_each(ele, chans){ 217 list_for_each(ele, chans){
218 chan = list_entry(ele, struct chan, list); 218 chan = list_entry(ele, struct chan, list);
219 ret = open_one_chan(chan, chan->input, chan->output, 219 ret = open_one_chan(chan);
220 chan->primary); 220 if(chan->primary)
221 if(chan->primary) err = ret; 221 err = ret;
222 } 222 }
223 return(err); 223 return err;
224} 224}
225 225
226void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) 226void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
@@ -237,20 +237,65 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
237 } 237 }
238} 238}
239 239
240void enable_chan(struct list_head *chans, struct tty_struct *tty) 240void enable_chan(struct line *line)
241{ 241{
242 struct list_head *ele; 242 struct list_head *ele;
243 struct chan *chan; 243 struct chan *chan;
244 244
245 list_for_each(ele, chans){ 245 list_for_each(ele, &line->chan_list){
246 chan = list_entry(ele, struct chan, list); 246 chan = list_entry(ele, struct chan, list);
247 if(!chan->opened) continue; 247 if(open_one_chan(chan))
248 continue;
248 249
249 line_setup_irq(chan->fd, chan->input, chan->output, tty); 250 if(chan->enabled)
251 continue;
252 line_setup_irq(chan->fd, chan->input, chan->output, line,
253 chan);
254 chan->enabled = 1;
250 } 255 }
251} 256}
252 257
253void close_chan(struct list_head *chans) 258static LIST_HEAD(irqs_to_free);
259
260void free_irqs(void)
261{
262 struct chan *chan;
263
264 while(!list_empty(&irqs_to_free)){
265 chan = list_entry(irqs_to_free.next, struct chan, free_list);
266 list_del(&chan->free_list);
267
268 if(chan->input)
269 free_irq(chan->line->driver->read_irq, chan);
270 if(chan->output)
271 free_irq(chan->line->driver->write_irq, chan);
272 chan->enabled = 0;
273 }
274}
275
276static void close_one_chan(struct chan *chan, int delay_free_irq)
277{
278 if(!chan->opened)
279 return;
280
281 if(delay_free_irq){
282 list_add(&chan->free_list, &irqs_to_free);
283 }
284 else {
285 if(chan->input)
286 free_irq(chan->line->driver->read_irq, chan);
287 if(chan->output)
288 free_irq(chan->line->driver->write_irq, chan);
289 chan->enabled = 0;
290 }
291 if(chan->ops->close != NULL)
292 (*chan->ops->close)(chan->fd, chan->data);
293
294 chan->opened = 0;
295 chan->fd = -1;
296}
297
298void close_chan(struct list_head *chans, int delay_free_irq)
254{ 299{
255 struct chan *chan; 300 struct chan *chan;
256 301
@@ -260,15 +305,37 @@ void close_chan(struct list_head *chans)
260 * so it must be the last closed. 305 * so it must be the last closed.
261 */ 306 */
262 list_for_each_entry_reverse(chan, chans, list) { 307 list_for_each_entry_reverse(chan, chans, list) {
263 if(!chan->opened) continue; 308 close_one_chan(chan, delay_free_irq);
264 if(chan->ops->close != NULL)
265 (*chan->ops->close)(chan->fd, chan->data);
266 chan->opened = 0;
267 chan->fd = -1;
268 } 309 }
269} 310}
270 311
271int write_chan(struct list_head *chans, const char *buf, int len, 312void deactivate_chan(struct list_head *chans, int irq)
313{
314 struct list_head *ele;
315
316 struct chan *chan;
317 list_for_each(ele, chans) {
318 chan = list_entry(ele, struct chan, list);
319
320 if(chan->enabled && chan->input)
321 deactivate_fd(chan->fd, irq);
322 }
323}
324
325void reactivate_chan(struct list_head *chans, int irq)
326{
327 struct list_head *ele;
328 struct chan *chan;
329
330 list_for_each(ele, chans) {
331 chan = list_entry(ele, struct chan, list);
332
333 if(chan->enabled && chan->input)
334 reactivate_fd(chan->fd, irq);
335 }
336}
337
338int write_chan(struct list_head *chans, const char *buf, int len,
272 int write_irq) 339 int write_irq)
273{ 340{
274 struct list_head *ele; 341 struct list_head *ele;
@@ -286,7 +353,7 @@ int write_chan(struct list_head *chans, const char *buf, int len,
286 reactivate_fd(chan->fd, write_irq); 353 reactivate_fd(chan->fd, write_irq);
287 } 354 }
288 } 355 }
289 return(ret); 356 return ret;
290} 357}
291 358
292int console_write_chan(struct list_head *chans, const char *buf, int len) 359int console_write_chan(struct list_head *chans, const char *buf, int len)
@@ -299,22 +366,21 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
299 chan = list_entry(ele, struct chan, list); 366 chan = list_entry(ele, struct chan, list);
300 if(!chan->output || (chan->ops->console_write == NULL)) 367 if(!chan->output || (chan->ops->console_write == NULL))
301 continue; 368 continue;
302 n = chan->ops->console_write(chan->fd, buf, len, chan->data); 369 n = chan->ops->console_write(chan->fd, buf, len);
303 if(chan->primary) ret = n; 370 if(chan->primary) ret = n;
304 } 371 }
305 return(ret); 372 return ret;
306} 373}
307 374
308int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) 375int console_open_chan(struct line *line, struct console *co,
376 struct chan_opts *opts)
309{ 377{
310 if (!list_empty(&line->chan_list)) 378 int err;
311 return 0; 379
380 err = open_chan(&line->chan_list);
381 if(err)
382 return err;
312 383
313 if (0 != parse_chan_pair(line->init_str, &line->chan_list,
314 line->init_pri, co->index, opts))
315 return -1;
316 if (0 != open_chan(&line->chan_list))
317 return -1;
318 printk("Console initialized on /dev/%s%d\n",co->name,co->index); 384 printk("Console initialized on /dev/%s%d\n",co->name,co->index);
319 return 0; 385 return 0;
320} 386}
@@ -328,32 +394,36 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
328 list_for_each(ele, chans){ 394 list_for_each(ele, chans){
329 chan = list_entry(ele, struct chan, list); 395 chan = list_entry(ele, struct chan, list);
330 if(chan->primary){ 396 if(chan->primary){
331 if(chan->ops->window_size == NULL) return(0); 397 if(chan->ops->window_size == NULL)
332 return(chan->ops->window_size(chan->fd, chan->data, 398 return 0;
333 rows_out, cols_out)); 399 return chan->ops->window_size(chan->fd, chan->data,
400 rows_out, cols_out);
334 } 401 }
335 } 402 }
336 return(0); 403 return 0;
337} 404}
338 405
339void free_one_chan(struct chan *chan) 406void free_one_chan(struct chan *chan, int delay_free_irq)
340{ 407{
341 list_del(&chan->list); 408 list_del(&chan->list);
409
410 close_one_chan(chan, delay_free_irq);
411
342 if(chan->ops->free != NULL) 412 if(chan->ops->free != NULL)
343 (*chan->ops->free)(chan->data); 413 (*chan->ops->free)(chan->data);
344 free_irq_by_fd(chan->fd); 414
345 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); 415 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
346 kfree(chan); 416 kfree(chan);
347} 417}
348 418
349void free_chan(struct list_head *chans) 419void free_chan(struct list_head *chans, int delay_free_irq)
350{ 420{
351 struct list_head *ele, *next; 421 struct list_head *ele, *next;
352 struct chan *chan; 422 struct chan *chan;
353 423
354 list_for_each_safe(ele, next, chans){ 424 list_for_each_safe(ele, next, chans){
355 chan = list_entry(ele, struct chan, list); 425 chan = list_entry(ele, struct chan, list);
356 free_one_chan(chan); 426 free_one_chan(chan, delay_free_irq);
357 } 427 }
358} 428}
359 429
@@ -364,23 +434,23 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
364 434
365 if(chan == NULL){ 435 if(chan == NULL){
366 CONFIG_CHUNK(str, size, n, "none", 1); 436 CONFIG_CHUNK(str, size, n, "none", 1);
367 return(n); 437 return n;
368 } 438 }
369 439
370 CONFIG_CHUNK(str, size, n, chan->ops->type, 0); 440 CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
371 441
372 if(chan->dev == NULL){ 442 if(chan->dev == NULL){
373 CONFIG_CHUNK(str, size, n, "", 1); 443 CONFIG_CHUNK(str, size, n, "", 1);
374 return(n); 444 return n;
375 } 445 }
376 446
377 CONFIG_CHUNK(str, size, n, ":", 0); 447 CONFIG_CHUNK(str, size, n, ":", 0);
378 CONFIG_CHUNK(str, size, n, chan->dev, 0); 448 CONFIG_CHUNK(str, size, n, chan->dev, 0);
379 449
380 return(n); 450 return n;
381} 451}
382 452
383static int chan_pair_config_string(struct chan *in, struct chan *out, 453static int chan_pair_config_string(struct chan *in, struct chan *out,
384 char *str, int size, char **error_out) 454 char *str, int size, char **error_out)
385{ 455{
386 int n; 456 int n;
@@ -391,7 +461,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
391 461
392 if(in == out){ 462 if(in == out){
393 CONFIG_CHUNK(str, size, n, "", 1); 463 CONFIG_CHUNK(str, size, n, "", 1);
394 return(n); 464 return n;
395 } 465 }
396 466
397 CONFIG_CHUNK(str, size, n, ",", 1); 467 CONFIG_CHUNK(str, size, n, ",", 1);
@@ -400,10 +470,10 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
400 size -= n; 470 size -= n;
401 CONFIG_CHUNK(str, size, n, "", 1); 471 CONFIG_CHUNK(str, size, n, "", 1);
402 472
403 return(n); 473 return n;
404} 474}
405 475
406int chan_config_string(struct list_head *chans, char *str, int size, 476int chan_config_string(struct list_head *chans, char *str, int size,
407 char **error_out) 477 char **error_out)
408{ 478{
409 struct list_head *ele; 479 struct list_head *ele;
@@ -419,7 +489,7 @@ int chan_config_string(struct list_head *chans, char *str, int size,
419 out = chan; 489 out = chan;
420 } 490 }
421 491
422 return(chan_pair_config_string(in, out, str, size, error_out)); 492 return chan_pair_config_string(in, out, str, size, error_out);
423} 493}
424 494
425struct chan_type { 495struct chan_type {
@@ -463,7 +533,7 @@ struct chan_type chan_table[] = {
463#endif 533#endif
464}; 534};
465 535
466static struct chan *parse_chan(char *str, int pri, int device, 536static struct chan *parse_chan(struct line *line, char *str, int device,
467 struct chan_opts *opts) 537 struct chan_opts *opts)
468{ 538{
469 struct chan_type *entry; 539 struct chan_type *entry;
@@ -485,36 +555,42 @@ static struct chan *parse_chan(char *str, int pri, int device,
485 if(ops == NULL){ 555 if(ops == NULL){
486 my_printf("parse_chan couldn't parse \"%s\"\n", 556 my_printf("parse_chan couldn't parse \"%s\"\n",
487 str); 557 str);
488 return(NULL); 558 return NULL;
489 } 559 }
490 if(ops->init == NULL) return(NULL); 560 if(ops->init == NULL)
561 return NULL;
491 data = (*ops->init)(str, device, opts); 562 data = (*ops->init)(str, device, opts);
492 if(data == NULL) return(NULL); 563 if(data == NULL)
564 return NULL;
493 565
494 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 566 chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
495 if(chan == NULL) return(NULL); 567 if(chan == NULL)
568 return NULL;
496 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 569 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
570 .free_list =
571 LIST_HEAD_INIT(chan->free_list),
572 .line = line,
497 .primary = 1, 573 .primary = 1,
498 .input = 0, 574 .input = 0,
499 .output = 0, 575 .output = 0,
500 .opened = 0, 576 .opened = 0,
577 .enabled = 0,
501 .fd = -1, 578 .fd = -1,
502 .pri = pri,
503 .ops = ops, 579 .ops = ops,
504 .data = data }); 580 .data = data });
505 return(chan); 581 return chan;
506} 582}
507 583
508int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, 584int parse_chan_pair(char *str, struct line *line, int device,
509 struct chan_opts *opts) 585 struct chan_opts *opts)
510{ 586{
587 struct list_head *chans = &line->chan_list;
511 struct chan *new, *chan; 588 struct chan *new, *chan;
512 char *in, *out; 589 char *in, *out;
513 590
514 if(!list_empty(chans)){ 591 if(!list_empty(chans)){
515 chan = list_entry(chans->next, struct chan, list); 592 chan = list_entry(chans->next, struct chan, list);
516 if(chan->pri >= pri) return(0); 593 free_chan(chans, 0);
517 free_chan(chans);
518 INIT_LIST_HEAD(chans); 594 INIT_LIST_HEAD(chans);
519 } 595 }
520 596
@@ -523,24 +599,30 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
523 in = str; 599 in = str;
524 *out = '\0'; 600 *out = '\0';
525 out++; 601 out++;
526 new = parse_chan(in, pri, device, opts); 602 new = parse_chan(line, in, device, opts);
527 if(new == NULL) return(-1); 603 if(new == NULL)
604 return -1;
605
528 new->input = 1; 606 new->input = 1;
529 list_add(&new->list, chans); 607 list_add(&new->list, chans);
530 608
531 new = parse_chan(out, pri, device, opts); 609 new = parse_chan(line, out, device, opts);
532 if(new == NULL) return(-1); 610 if(new == NULL)
611 return -1;
612
533 list_add(&new->list, chans); 613 list_add(&new->list, chans);
534 new->output = 1; 614 new->output = 1;
535 } 615 }
536 else { 616 else {
537 new = parse_chan(str, pri, device, opts); 617 new = parse_chan(line, str, device, opts);
538 if(new == NULL) return(-1); 618 if(new == NULL)
619 return -1;
620
539 list_add(&new->list, chans); 621 list_add(&new->list, chans);
540 new->input = 1; 622 new->input = 1;
541 new->output = 1; 623 new->output = 1;
542 } 624 }
543 return(0); 625 return 0;
544} 626}
545 627
546int chan_out_fd(struct list_head *chans) 628int chan_out_fd(struct list_head *chans)
@@ -551,9 +633,9 @@ int chan_out_fd(struct list_head *chans)
551 list_for_each(ele, chans){ 633 list_for_each(ele, chans){
552 chan = list_entry(ele, struct chan, list); 634 chan = list_entry(ele, struct chan, list);
553 if(chan->primary && chan->output) 635 if(chan->primary && chan->output)
554 return(chan->fd); 636 return chan->fd;
555 } 637 }
556 return(-1); 638 return -1;
557} 639}
558 640
559void chan_interrupt(struct list_head *chans, struct work_struct *task, 641void chan_interrupt(struct list_head *chans, struct work_struct *task,
@@ -568,9 +650,8 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
568 chan = list_entry(ele, struct chan, list); 650 chan = list_entry(ele, struct chan, list);
569 if(!chan->input || (chan->ops->read == NULL)) continue; 651 if(!chan->input || (chan->ops->read == NULL)) continue;
570 do { 652 do {
571 if((tty != NULL) && 653 if (tty && !tty_buffer_request_room(tty, 1)) {
572 (tty->flip.count >= TTY_FLIPBUF_SIZE)){ 654 schedule_delayed_work(task, 1);
573 schedule_work(task);
574 goto out; 655 goto out;
575 } 656 }
576 err = chan->ops->read(chan->fd, &c, chan->data); 657 err = chan->ops->read(chan->fd, &c, chan->data);
@@ -583,29 +664,12 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
583 if(chan->primary){ 664 if(chan->primary){
584 if(tty != NULL) 665 if(tty != NULL)
585 tty_hangup(tty); 666 tty_hangup(tty);
586 line_disable(tty, irq); 667 close_chan(chans, 1);
587 close_chan(chans);
588 free_chan(chans);
589 return; 668 return;
590 } 669 }
591 else { 670 else close_one_chan(chan, 1);
592 if(chan->ops->close != NULL)
593 chan->ops->close(chan->fd, chan->data);
594 free_one_chan(chan);
595 }
596 } 671 }
597 } 672 }
598 out: 673 out:
599 if(tty) tty_flip_buffer_push(tty); 674 if(tty) tty_flip_buffer_push(tty);
600} 675}
601
602/*
603 * Overrides for Emacs so that we follow Linus's tabbing style.
604 * Emacs will notice this stuff at the end of the file and automatically
605 * adjust the settings for this buffer only. This must remain at the end
606 * of the file.
607 * ---------------------------------------------------------------------------
608 * Local variables:
609 * c-file-style: "linux"
610 * End:
611 */
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 1c55d58024..5d50d4a44a 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -20,7 +20,7 @@
20#include "choose-mode.h" 20#include "choose-mode.h"
21#include "mode.h" 21#include "mode.h"
22 22
23int generic_console_write(int fd, const char *buf, int n, void *unused) 23int generic_console_write(int fd, const char *buf, int n)
24{ 24{
25 struct termios save, new; 25 struct termios save, new;
26 int err; 26 int err;
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index 30d285b266..507e3cbac9 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -31,6 +31,10 @@ void daemon_init(struct net_device *dev, void *data)
31 dpri->fd = -1; 31 dpri->fd = -1;
32 dpri->control = -1; 32 dpri->control = -1;
33 dpri->dev = dev; 33 dpri->dev = dev;
34 /* We will free this pointer. If it contains crap we're burned. */
35 dpri->ctl_addr = NULL;
36 dpri->data_addr = NULL;
37 dpri->local_addr = NULL;
34 38
35 printk("daemon backend (uml_switch version %d) - %s:%s", 39 printk("daemon backend (uml_switch version %d) - %s:%s",
36 SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); 40 SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index c1b03f7c1d..c944265955 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -98,7 +98,7 @@ static int connect_to_switch(struct daemon_data *pri)
98 printk("daemon_open : control setup request failed, err = %d\n", 98 printk("daemon_open : control setup request failed, err = %d\n",
99 -n); 99 -n);
100 err = -ENOTCONN; 100 err = -ENOTCONN;
101 goto out; 101 goto out_free;
102 } 102 }
103 103
104 n = os_read_file(pri->control, sun, sizeof(*sun)); 104 n = os_read_file(pri->control, sun, sizeof(*sun));
@@ -106,12 +106,14 @@ static int connect_to_switch(struct daemon_data *pri)
106 printk("daemon_open : read of data socket failed, err = %d\n", 106 printk("daemon_open : read of data socket failed, err = %d\n",
107 -n); 107 -n);
108 err = -ENOTCONN; 108 err = -ENOTCONN;
109 goto out_close; 109 goto out_free;
110 } 110 }
111 111
112 pri->data_addr = sun; 112 pri->data_addr = sun;
113 return(fd); 113 return(fd);
114 114
115 out_free:
116 kfree(sun);
115 out_close: 117 out_close:
116 os_close_file(fd); 118 os_close_file(fd);
117 out: 119 out:
@@ -156,10 +158,16 @@ static void daemon_remove(void *data)
156 struct daemon_data *pri = data; 158 struct daemon_data *pri = data;
157 159
158 os_close_file(pri->fd); 160 os_close_file(pri->fd);
161 pri->fd = -1;
159 os_close_file(pri->control); 162 os_close_file(pri->control);
163 pri->control = -1;
164
160 kfree(pri->data_addr); 165 kfree(pri->data_addr);
166 pri->data_addr = NULL;
161 kfree(pri->ctl_addr); 167 kfree(pri->ctl_addr);
168 pri->ctl_addr = NULL;
162 kfree(pri->local_addr); 169 kfree(pri->local_addr);
170 pri->local_addr = NULL;
163} 171}
164 172
165int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) 173int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index f0b888f66e..c41f75e4ac 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -11,6 +11,7 @@
11#include "user.h" 11#include "user.h"
12#include "user_util.h" 12#include "user_util.h"
13#include "chan_user.h" 13#include "chan_user.h"
14#include "os.h"
14 15
15struct fd_chan { 16struct fd_chan {
16 int fd; 17 int fd;
@@ -76,13 +77,6 @@ static void fd_close(int fd, void *d)
76 } 77 }
77} 78}
78 79
79static int fd_console_write(int fd, const char *buf, int n, void *d)
80{
81 struct fd_chan *data = d;
82
83 return(generic_console_write(fd, buf, n, &data->tt));
84}
85
86struct chan_ops fd_ops = { 80struct chan_ops fd_ops = {
87 .type = "fd", 81 .type = "fd",
88 .init = fd_init, 82 .init = fd_init,
@@ -90,7 +84,7 @@ struct chan_ops fd_ops = {
90 .close = fd_close, 84 .close = fd_close,
91 .read = generic_read, 85 .read = generic_read,
92 .write = generic_write, 86 .write = generic_write,
93 .console_write = fd_console_write, 87 .console_write = generic_console_write,
94 .window_size = generic_window_size, 88 .window_size = generic_window_size,
95 .free = generic_free, 89 .free = generic_free,
96 .winch = 1, 90 .winch = 1,
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index e0fdffa2d5..46ceb25a99 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -23,8 +23,9 @@
23 23
24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) 24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
25{ 25{
26 struct tty_struct *tty = data; 26 struct chan *chan = data;
27 struct line *line = tty->driver_data; 27 struct line *line = chan->line;
28 struct tty_struct *tty = line->tty;
28 29
29 if (line) 30 if (line)
30 chan_interrupt(&line->chan_list, &line->task, tty, irq); 31 chan_interrupt(&line->chan_list, &line->task, tty, irq);
@@ -33,10 +34,11 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
33 34
34static void line_timer_cb(void *arg) 35static void line_timer_cb(void *arg)
35{ 36{
36 struct tty_struct *tty = arg; 37 struct line *line = arg;
37 struct line *line = tty->driver_data;
38 38
39 line_interrupt(line->driver->read_irq, arg, NULL); 39 if(!line->throttled)
40 chan_interrupt(&line->chan_list, &line->task, line->tty,
41 line->driver->read_irq);
40} 42}
41 43
42/* Returns the free space inside the ring buffer of this line. 44/* Returns the free space inside the ring buffer of this line.
@@ -124,7 +126,8 @@ static int buffer_data(struct line *line, const char *buf, int len)
124 if (len < end){ 126 if (len < end){
125 memcpy(line->tail, buf, len); 127 memcpy(line->tail, buf, len);
126 line->tail += len; 128 line->tail += len;
127 } else { 129 }
130 else {
128 /* The circular buffer is wrapping */ 131 /* The circular buffer is wrapping */
129 memcpy(line->tail, buf, end); 132 memcpy(line->tail, buf, end);
130 buf += end; 133 buf += end;
@@ -170,7 +173,7 @@ static int flush_buffer(struct line *line)
170 } 173 }
171 174
172 count = line->tail - line->head; 175 count = line->tail - line->head;
173 n = write_chan(&line->chan_list, line->head, count, 176 n = write_chan(&line->chan_list, line->head, count,
174 line->driver->write_irq); 177 line->driver->write_irq);
175 178
176 if(n < 0) 179 if(n < 0)
@@ -227,7 +230,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
227 if (err <= 0 && (err != -EAGAIN || !ret)) 230 if (err <= 0 && (err != -EAGAIN || !ret))
228 ret = err; 231 ret = err;
229 } else { 232 } else {
230 n = write_chan(&line->chan_list, buf, len, 233 n = write_chan(&line->chan_list, buf, len,
231 line->driver->write_irq); 234 line->driver->write_irq);
232 if (n < 0) { 235 if (n < 0) {
233 ret = n; 236 ret = n;
@@ -338,11 +341,36 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
338 return ret; 341 return ret;
339} 342}
340 343
344void line_throttle(struct tty_struct *tty)
345{
346 struct line *line = tty->driver_data;
347
348 deactivate_chan(&line->chan_list, line->driver->read_irq);
349 line->throttled = 1;
350}
351
352void line_unthrottle(struct tty_struct *tty)
353{
354 struct line *line = tty->driver_data;
355
356 line->throttled = 0;
357 chan_interrupt(&line->chan_list, &line->task, tty,
358 line->driver->read_irq);
359
360 /* Maybe there is enough stuff pending that calling the interrupt
361 * throttles us again. In this case, line->throttled will be 1
362 * again and we shouldn't turn the interrupt back on.
363 */
364 if(!line->throttled)
365 reactivate_chan(&line->chan_list, line->driver->read_irq);
366}
367
341static irqreturn_t line_write_interrupt(int irq, void *data, 368static irqreturn_t line_write_interrupt(int irq, void *data,
342 struct pt_regs *unused) 369 struct pt_regs *unused)
343{ 370{
344 struct tty_struct *tty = data; 371 struct chan *chan = data;
345 struct line *line = tty->driver_data; 372 struct line *line = chan->line;
373 struct tty_struct *tty = line->tty;
346 int err; 374 int err;
347 375
348 /* Interrupts are enabled here because we registered the interrupt with 376 /* Interrupts are enabled here because we registered the interrupt with
@@ -364,7 +392,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
364 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && 392 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
365 (tty->ldisc.write_wakeup != NULL)) 393 (tty->ldisc.write_wakeup != NULL))
366 (tty->ldisc.write_wakeup)(tty); 394 (tty->ldisc.write_wakeup)(tty);
367 395
368 /* BLOCKING mode 396 /* BLOCKING mode
369 * In blocking mode, everything sleeps on tty->write_wait. 397 * In blocking mode, everything sleeps on tty->write_wait.
370 * Sleeping in the console driver would break non-blocking 398 * Sleeping in the console driver would break non-blocking
@@ -376,53 +404,29 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
376 return IRQ_HANDLED; 404 return IRQ_HANDLED;
377} 405}
378 406
379int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) 407int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
380{ 408{
381 struct line *line = tty->driver_data;
382 struct line_driver *driver = line->driver; 409 struct line_driver *driver = line->driver;
383 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; 410 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
384 411
385 if (input) 412 if (input)
386 err = um_request_irq(driver->read_irq, fd, IRQ_READ, 413 err = um_request_irq(driver->read_irq, fd, IRQ_READ,
387 line_interrupt, flags, 414 line_interrupt, flags,
388 driver->read_irq_name, tty); 415 driver->read_irq_name, data);
389 if (err) 416 if (err)
390 return err; 417 return err;
391 if (output) 418 if (output)
392 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 419 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
393 line_write_interrupt, flags, 420 line_write_interrupt, flags,
394 driver->write_irq_name, tty); 421 driver->write_irq_name, data);
395 line->have_irq = 1; 422 line->have_irq = 1;
396 return err; 423 return err;
397} 424}
398 425
399void line_disable(struct tty_struct *tty, int current_irq) 426int line_open(struct line *lines, struct tty_struct *tty)
400{
401 struct line *line = tty->driver_data;
402
403 if(!line->have_irq)
404 return;
405
406 if(line->driver->read_irq == current_irq)
407 free_irq_later(line->driver->read_irq, tty);
408 else {
409 free_irq(line->driver->read_irq, tty);
410 }
411
412 if(line->driver->write_irq == current_irq)
413 free_irq_later(line->driver->write_irq, tty);
414 else {
415 free_irq(line->driver->write_irq, tty);
416 }
417
418 line->have_irq = 0;
419}
420
421int line_open(struct line *lines, struct tty_struct *tty,
422 struct chan_opts *opts)
423{ 427{
424 struct line *line; 428 struct line *line;
425 int err = 0; 429 int err = -ENODEV;
426 430
427 line = &lines[tty->index]; 431 line = &lines[tty->index];
428 tty->driver_data = line; 432 tty->driver_data = line;
@@ -430,31 +434,29 @@ int line_open(struct line *lines, struct tty_struct *tty,
430 /* The IRQ which takes this lock is not yet enabled and won't be run 434 /* The IRQ which takes this lock is not yet enabled and won't be run
431 * before the end, so we don't need to use spin_lock_irq.*/ 435 * before the end, so we don't need to use spin_lock_irq.*/
432 spin_lock(&line->lock); 436 spin_lock(&line->lock);
433 if (tty->count == 1) { 437
434 if (!line->valid) { 438 tty->driver_data = line;
435 err = -ENODEV; 439 line->tty = tty;
436 goto out; 440 if(!line->valid)
437 } 441 goto out;
438 if (list_empty(&line->chan_list)) { 442
439 err = parse_chan_pair(line->init_str, &line->chan_list, 443 if(tty->count == 1){
440 line->init_pri, tty->index, opts); 444 /* Here the device is opened, if necessary, and interrupt
441 if(err) goto out; 445 * is registered.
442 err = open_chan(&line->chan_list); 446 */
443 if(err) goto out; 447 enable_chan(line);
448 INIT_WORK(&line->task, line_timer_cb, line);
449
450 if(!line->sigio){
451 chan_enable_winch(&line->chan_list, tty);
452 line->sigio = 1;
444 } 453 }
445 /* Here the interrupt is registered.*/
446 enable_chan(&line->chan_list, tty);
447 INIT_WORK(&line->task, line_timer_cb, tty);
448 }
449 454
450 if(!line->sigio){ 455 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
451 chan_enable_winch(&line->chan_list, tty); 456 &tty->winsize.ws_col);
452 line->sigio = 1;
453 } 457 }
454 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
455 &tty->winsize.ws_col);
456 line->count++;
457 458
459 err = 0;
458out: 460out:
459 spin_unlock(&line->lock); 461 spin_unlock(&line->lock);
460 return err; 462 return err;
@@ -474,15 +476,14 @@ void line_close(struct tty_struct *tty, struct file * filp)
474 /* We ignore the error anyway! */ 476 /* We ignore the error anyway! */
475 flush_buffer(line); 477 flush_buffer(line);
476 478
477 line->count--; 479 if(tty->count == 1){
478 if (tty->count == 1) { 480 line->tty = NULL;
479 line_disable(tty, -1);
480 tty->driver_data = NULL; 481 tty->driver_data = NULL;
481 }
482 482
483 if((line->count == 0) && line->sigio){ 483 if(line->sigio){
484 unregister_winch(tty); 484 unregister_winch(tty);
485 line->sigio = 0; 485 line->sigio = 0;
486 }
486 } 487 }
487 488
488 spin_unlock_irq(&line->lock); 489 spin_unlock_irq(&line->lock);
@@ -493,17 +494,15 @@ void close_lines(struct line *lines, int nlines)
493 int i; 494 int i;
494 495
495 for(i = 0; i < nlines; i++) 496 for(i = 0; i < nlines; i++)
496 close_chan(&lines[i].chan_list); 497 close_chan(&lines[i].chan_list, 0);
497} 498}
498 499
499/* Common setup code for both startup command line and mconsole initialization. 500/* Common setup code for both startup command line and mconsole initialization.
500 * @lines contains the the array (of size @num) to modify; 501 * @lines contains the the array (of size @num) to modify;
501 * @init is the setup string; 502 * @init is the setup string;
502 * @all_allowed is a boolean saying if we can setup the whole @lines 503 */
503 * at once. For instance, it will be usually true for startup init. (where we
504 * can use con=xterm) and false for mconsole.*/
505 504
506int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed) 505int line_setup(struct line *lines, unsigned int num, char *init)
507{ 506{
508 int i, n; 507 int i, n;
509 char *end; 508 char *end;
@@ -512,10 +511,11 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
512 /* We said con=/ssl= instead of con#=, so we are configuring all 511 /* We said con=/ssl= instead of con#=, so we are configuring all
513 * consoles at once.*/ 512 * consoles at once.*/
514 n = -1; 513 n = -1;
515 } else { 514 }
515 else {
516 n = simple_strtoul(init, &end, 0); 516 n = simple_strtoul(init, &end, 0);
517 if(*end != '='){ 517 if(*end != '='){
518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
519 init); 519 init);
520 return 0; 520 return 0;
521 } 521 }
@@ -527,8 +527,9 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n", 527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
528 n, num - 1); 528 n, num - 1);
529 return 0; 529 return 0;
530 } else if (n >= 0){ 530 }
531 if (lines[n].count > 0) { 531 else if (n >= 0){
532 if (lines[n].tty != NULL) {
532 printk("line_setup - device %d is open\n", n); 533 printk("line_setup - device %d is open\n", n);
533 return 0; 534 return 0;
534 } 535 }
@@ -539,13 +540,10 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
539 else { 540 else {
540 lines[n].init_str = init; 541 lines[n].init_str = init;
541 lines[n].valid = 1; 542 lines[n].valid = 1;
542 } 543 }
543 } 544 }
544 } else if(!all_allowed){ 545 }
545 printk("line_setup - can't configure all devices from " 546 else {
546 "mconsole\n");
547 return 0;
548 } else {
549 for(i = 0; i < num; i++){ 547 for(i = 0; i < num; i++){
550 if(lines[i].init_pri <= INIT_ALL){ 548 if(lines[i].init_pri <= INIT_ALL){
551 lines[i].init_pri = INIT_ALL; 549 lines[i].init_pri = INIT_ALL;
@@ -557,18 +555,33 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
557 } 555 }
558 } 556 }
559 } 557 }
560 return 1; 558 return n == -1 ? num : n;
561} 559}
562 560
563int line_config(struct line *lines, unsigned int num, char *str) 561int line_config(struct line *lines, unsigned int num, char *str,
562 struct chan_opts *opts)
564{ 563{
565 char *new = uml_strdup(str); 564 struct line *line;
565 char *new;
566 int n;
566 567
568 if(*str == '='){
569 printk("line_config - can't configure all devices from "
570 "mconsole\n");
571 return 1;
572 }
573
574 new = kstrdup(str, GFP_KERNEL);
567 if(new == NULL){ 575 if(new == NULL){
568 printk("line_config - uml_strdup failed\n"); 576 printk("line_config - kstrdup failed\n");
569 return -ENOMEM; 577 return 1;
570 } 578 }
571 return !line_setup(lines, num, new, 0); 579 n = line_setup(lines, num, new);
580 if(n < 0)
581 return 1;
582
583 line = &lines[n];
584 return parse_chan_pair(line->init_str, line, n, opts);
572} 585}
573 586
574int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 587int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -594,7 +607,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
594 spin_lock(&line->lock); 607 spin_lock(&line->lock);
595 if(!line->valid) 608 if(!line->valid)
596 CONFIG_CHUNK(str, size, n, "none", 1); 609 CONFIG_CHUNK(str, size, n, "none", 1);
597 else if(line->count == 0) 610 else if(line->tty == NULL)
598 CONFIG_CHUNK(str, size, n, line->init_str, 1); 611 CONFIG_CHUNK(str, size, n, line->init_str, 1);
599 else n = chan_config_string(&line->chan_list, str, size, error_out); 612 else n = chan_config_string(&line->chan_list, str, size, error_out);
600 spin_unlock(&line->lock); 613 spin_unlock(&line->lock);
@@ -619,14 +632,18 @@ int line_id(char **str, int *start_out, int *end_out)
619 632
620int line_remove(struct line *lines, unsigned int num, int n) 633int line_remove(struct line *lines, unsigned int num, int n)
621{ 634{
635 int err;
622 char config[sizeof("conxxxx=none\0")]; 636 char config[sizeof("conxxxx=none\0")];
623 637
624 sprintf(config, "%d=none", n); 638 sprintf(config, "%d=none", n);
625 return !line_setup(lines, num, config, 0); 639 err = line_setup(lines, num, config);
640 if(err >= 0)
641 err = 0;
642 return err;
626} 643}
627 644
628struct tty_driver *line_register_devfs(struct lines *set, 645struct tty_driver *line_register_devfs(struct lines *set,
629 struct line_driver *line_driver, 646 struct line_driver *line_driver,
630 struct tty_operations *ops, struct line *lines, 647 struct tty_operations *ops, struct line *lines,
631 int nlines) 648 int nlines)
632{ 649{
@@ -655,7 +672,7 @@ struct tty_driver *line_register_devfs(struct lines *set,
655 } 672 }
656 673
657 for(i = 0; i < nlines; i++){ 674 for(i = 0; i < nlines; i++){
658 if(!lines[i].valid) 675 if(!lines[i].valid)
659 tty_unregister_device(driver, i); 676 tty_unregister_device(driver, i);
660 } 677 }
661 678
@@ -663,24 +680,28 @@ struct tty_driver *line_register_devfs(struct lines *set,
663 return driver; 680 return driver;
664} 681}
665 682
666static spinlock_t winch_handler_lock; 683static DEFINE_SPINLOCK(winch_handler_lock);
667LIST_HEAD(winch_handlers); 684static LIST_HEAD(winch_handlers);
668 685
669void lines_init(struct line *lines, int nlines) 686void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
670{ 687{
671 struct line *line; 688 struct line *line;
672 int i; 689 int i;
673 690
674 spin_lock_init(&winch_handler_lock);
675 for(i = 0; i < nlines; i++){ 691 for(i = 0; i < nlines; i++){
676 line = &lines[i]; 692 line = &lines[i];
677 INIT_LIST_HEAD(&line->chan_list); 693 INIT_LIST_HEAD(&line->chan_list);
678 spin_lock_init(&line->lock); 694
679 if(line->init_str != NULL){ 695 if(line->init_str == NULL)
680 line->init_str = uml_strdup(line->init_str); 696 continue;
681 if(line->init_str == NULL) 697
682 printk("lines_init - uml_strdup returned " 698 line->init_str = kstrdup(line->init_str, GFP_KERNEL);
683 "NULL\n"); 699 if(line->init_str == NULL)
700 printk("lines_init - kstrdup returned NULL\n");
701
702 if(parse_chan_pair(line->init_str, line, i, opts)){
703 printk("parse_chan_pair failed for device %d\n", i);
704 line->valid = 0;
684 } 705 }
685 } 706 }
686} 707}
@@ -717,8 +738,7 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
717 tty = winch->tty; 738 tty = winch->tty;
718 if (tty != NULL) { 739 if (tty != NULL) {
719 line = tty->driver_data; 740 line = tty->driver_data;
720 chan_window_size(&line->chan_list, 741 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
721 &tty->winsize.ws_row,
722 &tty->winsize.ws_col); 742 &tty->winsize.ws_col);
723 kill_pg(tty->pgrp, SIGWINCH, 1); 743 kill_pg(tty->pgrp, SIGWINCH, 1);
724 } 744 }
@@ -749,60 +769,54 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
749 spin_unlock(&winch_handler_lock); 769 spin_unlock(&winch_handler_lock);
750 770
751 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 771 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
752 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 772 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
753 "winch", winch) < 0) 773 "winch", winch) < 0)
754 printk("register_winch_irq - failed to register IRQ\n"); 774 printk("register_winch_irq - failed to register IRQ\n");
755} 775}
756 776
777static void free_winch(struct winch *winch)
778{
779 list_del(&winch->list);
780
781 if(winch->pid != -1)
782 os_kill_process(winch->pid, 1);
783 if(winch->fd != -1)
784 os_close_file(winch->fd);
785
786 free_irq(WINCH_IRQ, winch);
787 kfree(winch);
788}
789
757static void unregister_winch(struct tty_struct *tty) 790static void unregister_winch(struct tty_struct *tty)
758{ 791{
759 struct list_head *ele; 792 struct list_head *ele;
760 struct winch *winch, *found = NULL; 793 struct winch *winch;
761 794
762 spin_lock(&winch_handler_lock); 795 spin_lock(&winch_handler_lock);
796
763 list_for_each(ele, &winch_handlers){ 797 list_for_each(ele, &winch_handlers){
764 winch = list_entry(ele, struct winch, list); 798 winch = list_entry(ele, struct winch, list);
765 if(winch->tty == tty){ 799 if(winch->tty == tty){
766 found = winch; 800 free_winch(winch);
767 break; 801 break;
768 } 802 }
769 } 803 }
770 if(found == NULL)
771 goto err;
772
773 list_del(&winch->list);
774 spin_unlock(&winch_handler_lock);
775
776 if(winch->pid != -1)
777 os_kill_process(winch->pid, 1);
778
779 free_irq(WINCH_IRQ, winch);
780 kfree(winch);
781
782 return;
783err:
784 spin_unlock(&winch_handler_lock); 804 spin_unlock(&winch_handler_lock);
785} 805}
786 806
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? */
789static void winch_cleanup(void) 807static void winch_cleanup(void)
790{ 808{
791 struct list_head *ele; 809 struct list_head *ele, *next;
792 struct winch *winch; 810 struct winch *winch;
793 811
794 list_for_each(ele, &winch_handlers){ 812 spin_lock(&winch_handler_lock);
813
814 list_for_each_safe(ele, next, &winch_handlers){
795 winch = list_entry(ele, struct winch, list); 815 winch = list_entry(ele, struct winch, list);
796 if(winch->fd != -1){ 816 free_winch(winch);
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... */
800 deactivate_fd(winch->fd, WINCH_IRQ);
801 os_close_file(winch->fd);
802 }
803 if(winch->pid != -1)
804 os_kill_process(winch->pid, 1);
805 } 817 }
818
819 spin_unlock(&winch_handler_lock);
806} 820}
807__uml_exitcall(winch_cleanup); 821__uml_exitcall(winch_cleanup);
808 822
@@ -811,10 +825,10 @@ char *add_xterm_umid(char *base)
811 char *umid, *title; 825 char *umid, *title;
812 int len; 826 int len;
813 827
814 umid = get_umid(1); 828 umid = get_umid();
815 if(umid == NULL) 829 if(*umid == '\0')
816 return base; 830 return base;
817 831
818 len = strlen(base) + strlen(" ()") + strlen(umid) + 1; 832 len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
819 title = kmalloc(len, GFP_KERNEL); 833 title = kmalloc(len, GFP_KERNEL);
820 if(title == NULL){ 834 if(title == NULL){
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 5db136e265..afe85bfa66 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -54,7 +54,7 @@ static int mcast_open(void *data)
54 struct mcast_data *pri = data; 54 struct mcast_data *pri = data;
55 struct sockaddr_in *sin = pri->mcast_addr; 55 struct sockaddr_in *sin = pri->mcast_addr;
56 struct ip_mreq mreq; 56 struct ip_mreq mreq;
57 int fd, yes = 1, err = 0; 57 int fd, yes = 1, err = -EINVAL;
58 58
59 59
60 if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) 60 if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
@@ -63,40 +63,40 @@ static int mcast_open(void *data)
63 fd = socket(AF_INET, SOCK_DGRAM, 0); 63 fd = socket(AF_INET, SOCK_DGRAM, 0);
64 64
65 if (fd < 0){ 65 if (fd < 0){
66 err = -errno;
66 printk("mcast_open : data socket failed, errno = %d\n", 67 printk("mcast_open : data socket failed, errno = %d\n",
67 errno); 68 errno);
68 err = -errno;
69 goto out; 69 goto out;
70 } 70 }
71 71
72 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { 72 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
73 err = -errno;
73 printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", 74 printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
74 errno); 75 errno);
75 err = -errno;
76 goto out_close; 76 goto out_close;
77 } 77 }
78 78
79 /* set ttl according to config */ 79 /* set ttl according to config */
80 if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, 80 if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl,
81 sizeof(pri->ttl)) < 0) { 81 sizeof(pri->ttl)) < 0) {
82 err = -errno;
82 printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", 83 printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
83 errno); 84 errno);
84 err = -errno;
85 goto out_close; 85 goto out_close;
86 } 86 }
87 87
88 /* set LOOP, so data does get fed back to local sockets */ 88 /* set LOOP, so data does get fed back to local sockets */
89 if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { 89 if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
90 err = -errno;
90 printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", 91 printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
91 errno); 92 errno);
92 err = -errno;
93 goto out_close; 93 goto out_close;
94 } 94 }
95 95
96 /* bind socket to mcast address */ 96 /* bind socket to mcast address */
97 if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { 97 if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
98 printk("mcast_open : data bind failed, errno = %d\n", errno);
99 err = -errno; 98 err = -errno;
99 printk("mcast_open : data bind failed, errno = %d\n", errno);
100 goto out_close; 100 goto out_close;
101 } 101 }
102 102
@@ -105,22 +105,22 @@ static int mcast_open(void *data)
105 mreq.imr_interface.s_addr = 0; 105 mreq.imr_interface.s_addr = 0;
106 if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, 106 if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP,
107 &mreq, sizeof(mreq)) < 0) { 107 &mreq, sizeof(mreq)) < 0) {
108 err = -errno;
108 printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", 109 printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n",
109 errno); 110 errno);
110 printk("There appears not to be a multicast-capable network " 111 printk("There appears not to be a multicast-capable network "
111 "interface on the host.\n"); 112 "interface on the host.\n");
112 printk("eth0 should be configured in order to use the " 113 printk("eth0 should be configured in order to use the "
113 "multicast transport.\n"); 114 "multicast transport.\n");
114 err = -errno; 115 goto out_close;
115 goto out_close;
116 } 116 }
117 117
118 return fd; 118 return fd;
119 119
120 out_close: 120 out_close:
121 os_close_file(fd); 121 os_close_file(fd);
122 out: 122 out:
123 return err; 123 return err;
124} 124}
125 125
126static void mcast_close(int fd, void *data) 126static void mcast_close(int fd, void *data)
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 12c9536812..e3d5765671 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -20,6 +20,7 @@
20#include "linux/namei.h" 20#include "linux/namei.h"
21#include "linux/proc_fs.h" 21#include "linux/proc_fs.h"
22#include "linux/syscalls.h" 22#include "linux/syscalls.h"
23#include "linux/console.h"
23#include "asm/irq.h" 24#include "asm/irq.h"
24#include "asm/uaccess.h" 25#include "asm/uaccess.h"
25#include "user_util.h" 26#include "user_util.h"
@@ -34,7 +35,7 @@
34#include "irq_kern.h" 35#include "irq_kern.h"
35#include "choose-mode.h" 36#include "choose-mode.h"
36 37
37static int do_unlink_socket(struct notifier_block *notifier, 38static int do_unlink_socket(struct notifier_block *notifier,
38 unsigned long what, void *data) 39 unsigned long what, void *data)
39{ 40{
40 return(mconsole_unlink_socket()); 41 return(mconsole_unlink_socket());
@@ -46,12 +47,12 @@ static struct notifier_block reboot_notifier = {
46 .priority = 0, 47 .priority = 0,
47}; 48};
48 49
49/* Safe without explicit locking for now. Tasklets provide their own 50/* Safe without explicit locking for now. Tasklets provide their own
50 * locking, and the interrupt handler is safe because it can't interrupt 51 * locking, and the interrupt handler is safe because it can't interrupt
51 * itself and it can only happen on CPU 0. 52 * itself and it can only happen on CPU 0.
52 */ 53 */
53 54
54LIST_HEAD(mc_requests); 55static LIST_HEAD(mc_requests);
55 56
56static void mc_work_proc(void *unused) 57static void mc_work_proc(void *unused)
57{ 58{
@@ -60,7 +61,7 @@ static void mc_work_proc(void *unused)
60 61
61 while(!list_empty(&mc_requests)){ 62 while(!list_empty(&mc_requests)){
62 local_save_flags(flags); 63 local_save_flags(flags);
63 req = list_entry(mc_requests.next, struct mconsole_entry, 64 req = list_entry(mc_requests.next, struct mconsole_entry,
64 list); 65 list);
65 list_del(&req->list); 66 list_del(&req->list);
66 local_irq_restore(flags); 67 local_irq_restore(flags);
@@ -69,7 +70,7 @@ static void mc_work_proc(void *unused)
69 } 70 }
70} 71}
71 72
72DECLARE_WORK(mconsole_work, mc_work_proc, NULL); 73static DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
73 74
74static irqreturn_t mconsole_interrupt(int irq, void *dev_id, 75static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
75 struct pt_regs *regs) 76 struct pt_regs *regs)
@@ -103,8 +104,8 @@ void mconsole_version(struct mc_request *req)
103{ 104{
104 char version[256]; 105 char version[256];
105 106
106 sprintf(version, "%s %s %s %s %s", system_utsname.sysname, 107 sprintf(version, "%s %s %s %s %s", system_utsname.sysname,
107 system_utsname.nodename, system_utsname.release, 108 system_utsname.nodename, system_utsname.release,
108 system_utsname.version, system_utsname.machine); 109 system_utsname.version, system_utsname.machine);
109 mconsole_reply(req, version, 0, 0); 110 mconsole_reply(req, version, 0, 0);
110} 111}
@@ -348,7 +349,7 @@ static struct mc_device *mconsole_find_dev(char *name)
348 349
349#define CONFIG_BUF_SIZE 64 350#define CONFIG_BUF_SIZE 64
350 351
351static void mconsole_get_config(int (*get_config)(char *, char *, int, 352static void mconsole_get_config(int (*get_config)(char *, char *, int,
352 char **), 353 char **),
353 struct mc_request *req, char *name) 354 struct mc_request *req, char *name)
354{ 355{
@@ -389,7 +390,6 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
389 out: 390 out:
390 if(buf != default_buf) 391 if(buf != default_buf)
391 kfree(buf); 392 kfree(buf);
392
393} 393}
394 394
395void mconsole_config(struct mc_request *req) 395void mconsole_config(struct mc_request *req)
@@ -420,9 +420,9 @@ void mconsole_config(struct mc_request *req)
420 420
421void mconsole_remove(struct mc_request *req) 421void mconsole_remove(struct mc_request *req)
422{ 422{
423 struct mc_device *dev; 423 struct mc_device *dev;
424 char *ptr = req->request.data, *err_msg = ""; 424 char *ptr = req->request.data, *err_msg = "";
425 char error[256]; 425 char error[256];
426 int err, start, end, n; 426 int err, start, end, n;
427 427
428 ptr += strlen("remove"); 428 ptr += strlen("remove");
@@ -433,37 +433,112 @@ void mconsole_remove(struct mc_request *req)
433 return; 433 return;
434 } 434 }
435 435
436 ptr = &ptr[strlen(dev->name)]; 436 ptr = &ptr[strlen(dev->name)];
437 437
438 err = 1; 438 err = 1;
439 n = (*dev->id)(&ptr, &start, &end); 439 n = (*dev->id)(&ptr, &start, &end);
440 if(n < 0){ 440 if(n < 0){
441 err_msg = "Couldn't parse device number"; 441 err_msg = "Couldn't parse device number";
442 goto out; 442 goto out;
443 } 443 }
444 else if((n < start) || (n > end)){ 444 else if((n < start) || (n > end)){
445 sprintf(error, "Invalid device number - must be between " 445 sprintf(error, "Invalid device number - must be between "
446 "%d and %d", start, end); 446 "%d and %d", start, end);
447 err_msg = error; 447 err_msg = error;
448 goto out; 448 goto out;
449 } 449 }
450 450
451 err = (*dev->remove)(n); 451 err = (*dev->remove)(n);
452 switch(err){ 452 switch(err){
453 case -ENODEV: 453 case -ENODEV:
454 err_msg = "Device doesn't exist"; 454 err_msg = "Device doesn't exist";
455 break; 455 break;
456 case -EBUSY: 456 case -EBUSY:
457 err_msg = "Device is currently open"; 457 err_msg = "Device is currently open";
458 break; 458 break;
459 default: 459 default:
460 break; 460 break;
461 } 461 }
462 out: 462out:
463 mconsole_reply(req, err_msg, err, 0); 463 mconsole_reply(req, err_msg, err, 0);
464} 464}
465 465
466static DEFINE_SPINLOCK(console_lock);
467static LIST_HEAD(clients);
468static char console_buf[MCONSOLE_MAX_DATA];
469static int console_index = 0;
470
471static void console_write(struct console *console, const char *string,
472 unsigned len)
473{
474 struct list_head *ele;
475 int n;
476
477 if(list_empty(&clients))
478 return;
479
480 while(1){
481 n = min(len, ARRAY_SIZE(console_buf) - console_index);
482 strncpy(&console_buf[console_index], string, n);
483 console_index += n;
484 string += n;
485 len -= n;
486 if(len == 0)
487 return;
488
489 list_for_each(ele, &clients){
490 struct mconsole_entry *entry;
491
492 entry = list_entry(ele, struct mconsole_entry, list);
493 mconsole_reply_len(&entry->request, console_buf,
494 console_index, 0, 1);
495 }
496
497 console_index = 0;
498 }
499}
500
501static struct console mc_console = { .name = "mc",
502 .write = console_write,
503 .flags = CON_ENABLED,
504 .index = -1 };
505
506static int mc_add_console(void)
507{
508 register_console(&mc_console);
509 return 0;
510}
511
512late_initcall(mc_add_console);
513
514static void with_console(struct mc_request *req, void (*proc)(void *),
515 void *arg)
516{
517 struct mconsole_entry entry;
518 unsigned long flags;
519
520 INIT_LIST_HEAD(&entry.list);
521 entry.request = *req;
522 list_add(&entry.list, &clients);
523 spin_lock_irqsave(&console_lock, flags);
524
525 (*proc)(arg);
526
527 mconsole_reply_len(req, console_buf, console_index, 0, 0);
528 console_index = 0;
529
530 spin_unlock_irqrestore(&console_lock, flags);
531 list_del(&entry.list);
532}
533
466#ifdef CONFIG_MAGIC_SYSRQ 534#ifdef CONFIG_MAGIC_SYSRQ
535static void sysrq_proc(void *arg)
536{
537 char *op = arg;
538
539 handle_sysrq(*op, &current->thread.regs, NULL);
540}
541
467void mconsole_sysrq(struct mc_request *req) 542void mconsole_sysrq(struct mc_request *req)
468{ 543{
469 char *ptr = req->request.data; 544 char *ptr = req->request.data;
@@ -471,8 +546,13 @@ void mconsole_sysrq(struct mc_request *req)
471 ptr += strlen("sysrq"); 546 ptr += strlen("sysrq");
472 while(isspace(*ptr)) ptr++; 547 while(isspace(*ptr)) ptr++;
473 548
474 mconsole_reply(req, "", 0, 0); 549 /* With 'b', the system will shut down without a chance to reply,
475 handle_sysrq(*ptr, &current->thread.regs, NULL); 550 * so in this case, we reply first.
551 */
552 if(*ptr == 'b')
553 mconsole_reply(req, "", 0, 0);
554
555 with_console(req, sysrq_proc, ptr);
476} 556}
477#else 557#else
478void mconsole_sysrq(struct mc_request *req) 558void mconsole_sysrq(struct mc_request *req)
@@ -481,6 +561,14 @@ void mconsole_sysrq(struct mc_request *req)
481} 561}
482#endif 562#endif
483 563
564static void stack_proc(void *arg)
565{
566 struct task_struct *from = current, *to = arg;
567
568 to->thread.saved_task = from;
569 switch_to(from, to, from);
570}
571
484/* Mconsole stack trace 572/* Mconsole stack trace
485 * Added by Allan Graves, Jeff Dike 573 * Added by Allan Graves, Jeff Dike
486 * Dumps a stacks registers to the linux console. 574 * Dumps a stacks registers to the linux console.
@@ -488,37 +576,34 @@ void mconsole_sysrq(struct mc_request *req)
488 */ 576 */
489void do_stack(struct mc_request *req) 577void do_stack(struct mc_request *req)
490{ 578{
491 char *ptr = req->request.data; 579 char *ptr = req->request.data;
492 int pid_requested= -1; 580 int pid_requested= -1;
493 struct task_struct *from = NULL; 581 struct task_struct *from = NULL;
494 struct task_struct *to = NULL; 582 struct task_struct *to = NULL;
495 583
496 /* Would be nice: 584 /* Would be nice:
497 * 1) Send showregs output to mconsole. 585 * 1) Send showregs output to mconsole.
498 * 2) Add a way to stack dump all pids. 586 * 2) Add a way to stack dump all pids.
499 */ 587 */
500 588
501 ptr += strlen("stack"); 589 ptr += strlen("stack");
502 while(isspace(*ptr)) ptr++; 590 while(isspace(*ptr)) ptr++;
503
504 /* Should really check for multiple pids or reject bad args here */
505 /* What do the arguments in mconsole_reply mean? */
506 if(sscanf(ptr, "%d", &pid_requested) == 0){
507 mconsole_reply(req, "Please specify a pid", 1, 0);
508 return;
509 }
510 591
511 from = current; 592 /* Should really check for multiple pids or reject bad args here */
512 to = find_task_by_pid(pid_requested); 593 /* What do the arguments in mconsole_reply mean? */
594 if(sscanf(ptr, "%d", &pid_requested) == 0){
595 mconsole_reply(req, "Please specify a pid", 1, 0);
596 return;
597 }
513 598
514 if((to == NULL) || (pid_requested == 0)) { 599 from = current;
515 mconsole_reply(req, "Couldn't find that pid", 1, 0);
516 return;
517 }
518 to->thread.saved_task = current;
519 600
520 switch_to(from, to, from); 601 to = find_task_by_pid(pid_requested);
521 mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); 602 if((to == NULL) || (pid_requested == 0)) {
603 mconsole_reply(req, "Couldn't find that pid", 1, 0);
604 return;
605 }
606 with_console(req, stack_proc, to);
522} 607}
523 608
524void mconsole_stack(struct mc_request *req) 609void mconsole_stack(struct mc_request *req)
@@ -534,9 +619,9 @@ void mconsole_stack(struct mc_request *req)
534/* Changed by mconsole_setup, which is __setup, and called before SMP is 619/* Changed by mconsole_setup, which is __setup, and called before SMP is
535 * active. 620 * active.
536 */ 621 */
537static char *notify_socket = NULL; 622static char *notify_socket = NULL;
538 623
539int mconsole_init(void) 624static int mconsole_init(void)
540{ 625{
541 /* long to avoid size mismatch warnings from gcc */ 626 /* long to avoid size mismatch warnings from gcc */
542 long sock; 627 long sock;
@@ -563,16 +648,16 @@ int mconsole_init(void)
563 } 648 }
564 649
565 if(notify_socket != NULL){ 650 if(notify_socket != NULL){
566 notify_socket = uml_strdup(notify_socket); 651 notify_socket = kstrdup(notify_socket, GFP_KERNEL);
567 if(notify_socket != NULL) 652 if(notify_socket != NULL)
568 mconsole_notify(notify_socket, MCONSOLE_SOCKET, 653 mconsole_notify(notify_socket, MCONSOLE_SOCKET,
569 mconsole_socket_name, 654 mconsole_socket_name,
570 strlen(mconsole_socket_name) + 1); 655 strlen(mconsole_socket_name) + 1);
571 else printk(KERN_ERR "mconsole_setup failed to strdup " 656 else printk(KERN_ERR "mconsole_setup failed to strdup "
572 "string\n"); 657 "string\n");
573 } 658 }
574 659
575 printk("mconsole (version %d) initialized on %s\n", 660 printk("mconsole (version %d) initialized on %s\n",
576 MCONSOLE_VERSION, mconsole_socket_name); 661 MCONSOLE_VERSION, mconsole_socket_name);
577 return(0); 662 return(0);
578} 663}
@@ -585,7 +670,7 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer,
585 char *buf; 670 char *buf;
586 671
587 buf = kmalloc(count + 1, GFP_KERNEL); 672 buf = kmalloc(count + 1, GFP_KERNEL);
588 if(buf == NULL) 673 if(buf == NULL)
589 return(-ENOMEM); 674 return(-ENOMEM);
590 675
591 if(copy_from_user(buf, buffer, count)){ 676 if(copy_from_user(buf, buffer, count)){
@@ -661,7 +746,7 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1,
661 746
662 if(notify_socket == NULL) return(0); 747 if(notify_socket == NULL) return(0);
663 748
664 mconsole_notify(notify_socket, MCONSOLE_PANIC, message, 749 mconsole_notify(notify_socket, MCONSOLE_PANIC, message,
665 strlen(message) + 1); 750 strlen(message) + 1);
666 return(0); 751 return(0);
667} 752}
@@ -686,14 +771,3 @@ char *mconsole_notify_socket(void)
686} 771}
687 772
688EXPORT_SYMBOL(mconsole_notify_socket); 773EXPORT_SYMBOL(mconsole_notify_socket);
689
690/*
691 * Overrides for Emacs so that we follow Linus's tabbing style.
692 * Emacs will notice this stuff at the end of the file and automatically
693 * adjust the settings for this buffer only. This must remain at the end
694 * of the file.
695 * ---------------------------------------------------------------------------
696 * Local variables:
697 * c-file-style: "linux"
698 * End:
699 */
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 310c1f823f..4b109fe7ff 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -122,12 +122,12 @@ int mconsole_get_request(int fd, struct mc_request *req)
122 return(1); 122 return(1);
123} 123}
124 124
125int mconsole_reply(struct mc_request *req, char *str, int err, int more) 125int mconsole_reply_len(struct mc_request *req, const char *str, int total,
126 int err, int more)
126{ 127{
127 struct mconsole_reply reply; 128 struct mconsole_reply reply;
128 int total, len, n; 129 int len, n;
129 130
130 total = strlen(str);
131 do { 131 do {
132 reply.err = err; 132 reply.err = err;
133 133
@@ -155,6 +155,12 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
155 return(0); 155 return(0);
156} 156}
157 157
158int mconsole_reply(struct mc_request *req, const char *str, int err, int more)
159{
160 return mconsole_reply_len(req, str, strlen(str), err, more);
161}
162
163
158int mconsole_unlink_socket(void) 164int mconsole_unlink_socket(void)
159{ 165{
160 unlink(mconsole_socket_name); 166 unlink(mconsole_socket_name);
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 84c73a300a..8ebb2241ad 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -34,7 +34,7 @@
34#define DRIVER_NAME "uml-netdev" 34#define DRIVER_NAME "uml-netdev"
35 35
36static DEFINE_SPINLOCK(opened_lock); 36static DEFINE_SPINLOCK(opened_lock);
37LIST_HEAD(opened); 37static LIST_HEAD(opened);
38 38
39static int uml_net_rx(struct net_device *dev) 39static int uml_net_rx(struct net_device *dev)
40{ 40{
@@ -68,6 +68,11 @@ static int uml_net_rx(struct net_device *dev)
68 return pkt_len; 68 return pkt_len;
69} 69}
70 70
71static void uml_dev_close(void* dev)
72{
73 dev_close( (struct net_device *) dev);
74}
75
71irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) 76irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
72{ 77{
73 struct net_device *dev = dev_id; 78 struct net_device *dev = dev_id;
@@ -80,15 +85,21 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
80 spin_lock(&lp->lock); 85 spin_lock(&lp->lock);
81 while((err = uml_net_rx(dev)) > 0) ; 86 while((err = uml_net_rx(dev)) > 0) ;
82 if(err < 0) { 87 if(err < 0) {
88 DECLARE_WORK(close_work, uml_dev_close, dev);
83 printk(KERN_ERR 89 printk(KERN_ERR
84 "Device '%s' read returned %d, shutting it down\n", 90 "Device '%s' read returned %d, shutting it down\n",
85 dev->name, err); 91 dev->name, err);
86 dev_close(dev); 92 /* dev_close can't be called in interrupt context, and takes
93 * again lp->lock.
94 * And dev_close() can be safely called multiple times on the
95 * same device, since it tests for (dev->flags & IFF_UP). So
96 * there's no harm in delaying the device shutdown. */
97 schedule_work(&close_work);
87 goto out; 98 goto out;
88 } 99 }
89 reactivate_fd(lp->fd, UM_ETH_IRQ); 100 reactivate_fd(lp->fd, UM_ETH_IRQ);
90 101
91 out: 102out:
92 spin_unlock(&lp->lock); 103 spin_unlock(&lp->lock);
93 return(IRQ_HANDLED); 104 return(IRQ_HANDLED);
94} 105}
@@ -150,6 +161,7 @@ static int uml_net_close(struct net_device *dev)
150 if(lp->close != NULL) 161 if(lp->close != NULL)
151 (*lp->close)(lp->fd, &lp->user); 162 (*lp->close)(lp->fd, &lp->user);
152 lp->fd = -1; 163 lp->fd = -1;
164 list_del(&lp->list);
153 165
154 spin_unlock(&lp->lock); 166 spin_unlock(&lp->lock);
155 return 0; 167 return 0;
@@ -266,7 +278,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
266} 278}
267 279
268static DEFINE_SPINLOCK(devices_lock); 280static DEFINE_SPINLOCK(devices_lock);
269static struct list_head devices = LIST_HEAD_INIT(devices); 281static LIST_HEAD(devices);
270 282
271static struct platform_driver uml_net_driver = { 283static struct platform_driver uml_net_driver = {
272 .driver = { 284 .driver = {
@@ -316,6 +328,11 @@ static int eth_configure(int n, void *init, char *mac,
316 return 1; 328 return 1;
317 } 329 }
318 330
331 lp = dev->priv;
332 /* This points to the transport private data. It's still clear, but we
333 * must memset it to 0 *now*. Let's help the drivers. */
334 memset(lp, 0, size);
335
319 /* sysfs register */ 336 /* sysfs register */
320 if (!driver_registered) { 337 if (!driver_registered) {
321 platform_driver_register(&uml_net_driver); 338 platform_driver_register(&uml_net_driver);
@@ -357,7 +374,6 @@ static int eth_configure(int n, void *init, char *mac,
357 free_netdev(dev); 374 free_netdev(dev);
358 return 1; 375 return 1;
359 } 376 }
360 lp = dev->priv;
361 377
362 /* lp.user is the first four bytes of the transport data, which 378 /* lp.user is the first four bytes of the transport data, which
363 * has already been initialized. This structure assignment will 379 * has already been initialized. This structure assignment will
@@ -586,7 +602,7 @@ static int net_config(char *str)
586 err = eth_parse(str, &n, &str); 602 err = eth_parse(str, &n, &str);
587 if(err) return(err); 603 if(err) return(err);
588 604
589 str = uml_strdup(str); 605 str = kstrdup(str, GFP_KERNEL);
590 if(str == NULL){ 606 if(str == NULL){
591 printk(KERN_ERR "net_config failed to strdup string\n"); 607 printk(KERN_ERR "net_config failed to strdup string\n");
592 return(-1); 608 return(-1);
@@ -715,6 +731,7 @@ static void close_devices(void)
715 731
716 list_for_each(ele, &opened){ 732 list_for_each(ele, &opened){
717 lp = list_entry(ele, struct uml_net_private, list); 733 lp = list_entry(ele, struct uml_net_private, list);
734 free_irq(lp->dev->irq, lp->dev);
718 if((lp->close != NULL) && (lp->fd >= 0)) 735 if((lp->close != NULL) && (lp->fd >= 0))
719 (*lp->close)(lp->fd, &lp->user); 736 (*lp->close)(lp->fd, &lp->user);
720 if(lp->remove != NULL) (*lp->remove)(&lp->user); 737 if(lp->remove != NULL) (*lp->remove)(&lp->user);
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index ed4a1a6c5d..c43e8bb325 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -100,13 +100,6 @@ static void port_close(int fd, void *d)
100 os_close_file(fd); 100 os_close_file(fd);
101} 101}
102 102
103static int port_console_write(int fd, const char *buf, int n, void *d)
104{
105 struct port_chan *data = d;
106
107 return(generic_console_write(fd, buf, n, &data->tt));
108}
109
110struct chan_ops port_ops = { 103struct chan_ops port_ops = {
111 .type = "port", 104 .type = "port",
112 .init = port_init, 105 .init = port_init,
@@ -114,7 +107,7 @@ struct chan_ops port_ops = {
114 .close = port_close, 107 .close = port_close,
115 .read = generic_read, 108 .read = generic_read,
116 .write = generic_write, 109 .write = generic_write,
117 .console_write = port_console_write, 110 .console_write = generic_console_write,
118 .window_size = generic_window_size, 111 .window_size = generic_window_size,
119 .free = port_free, 112 .free = port_free,
120 .winch = 1, 113 .winch = 1,
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 0306a1b215..1c555c38de 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -118,13 +118,6 @@ static int pty_open(int input, int output, int primary, void *d,
118 return(fd); 118 return(fd);
119} 119}
120 120
121static int pty_console_write(int fd, const char *buf, int n, void *d)
122{
123 struct pty_chan *data = d;
124
125 return(generic_console_write(fd, buf, n, &data->tt));
126}
127
128struct chan_ops pty_ops = { 121struct chan_ops pty_ops = {
129 .type = "pty", 122 .type = "pty",
130 .init = pty_chan_init, 123 .init = pty_chan_init,
@@ -132,7 +125,7 @@ struct chan_ops pty_ops = {
132 .close = generic_close, 125 .close = generic_close,
133 .read = generic_read, 126 .read = generic_read,
134 .write = generic_write, 127 .write = generic_write,
135 .console_write = pty_console_write, 128 .console_write = generic_console_write,
136 .window_size = generic_window_size, 129 .window_size = generic_window_size,
137 .free = generic_free, 130 .free = generic_free,
138 .winch = 0, 131 .winch = 0,
@@ -145,7 +138,7 @@ struct chan_ops pts_ops = {
145 .close = generic_close, 138 .close = generic_close,
146 .read = generic_read, 139 .read = generic_read,
147 .write = generic_write, 140 .write = generic_write,
148 .console_write = pty_console_write, 141 .console_write = generic_console_write,
149 .window_size = generic_window_size, 142 .window_size = generic_window_size,
150 .free = generic_free, 143 .free = generic_free,
151 .winch = 0, 144 .winch = 0,
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 62e04ecfad..a32ef55cb2 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -69,7 +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 .id = line_id,
73 .remove = ssl_remove, 73 .remove = ssl_remove,
74 }, 74 },
75}; 75};
@@ -84,26 +84,23 @@ static struct lines lines = LINES_INIT(NR_PORTS);
84 84
85static int ssl_config(char *str) 85static int ssl_config(char *str)
86{ 86{
87 return(line_config(serial_lines, 87 return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts);
88 sizeof(serial_lines)/sizeof(serial_lines[0]), str));
89} 88}
90 89
91static int ssl_get_config(char *dev, char *str, int size, char **error_out) 90static int ssl_get_config(char *dev, char *str, int size, char **error_out)
92{ 91{
93 return(line_get_config(dev, serial_lines, 92 return line_get_config(dev, serial_lines, ARRAY_SIZE(serial_lines), str,
94 sizeof(serial_lines)/sizeof(serial_lines[0]), 93 size, error_out);
95 str, size, error_out));
96} 94}
97 95
98static int ssl_remove(int n) 96static int ssl_remove(int n)
99{ 97{
100 return line_remove(serial_lines, 98 return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n);
101 sizeof(serial_lines)/sizeof(serial_lines[0]), n);
102} 99}
103 100
104int ssl_open(struct tty_struct *tty, struct file *filp) 101int ssl_open(struct tty_struct *tty, struct file *filp)
105{ 102{
106 return line_open(serial_lines, tty, &opts); 103 return line_open(serial_lines, tty);
107} 104}
108 105
109#if 0 106#if 0
@@ -112,16 +109,6 @@ static void ssl_flush_buffer(struct tty_struct *tty)
112 return; 109 return;
113} 110}
114 111
115static void ssl_throttle(struct tty_struct * tty)
116{
117 printk(KERN_ERR "Someone should implement ssl_throttle\n");
118}
119
120static void ssl_unthrottle(struct tty_struct * tty)
121{
122 printk(KERN_ERR "Someone should implement ssl_unthrottle\n");
123}
124
125static void ssl_stop(struct tty_struct *tty) 112static void ssl_stop(struct tty_struct *tty)
126{ 113{
127 printk(KERN_ERR "Someone should implement ssl_stop\n"); 114 printk(KERN_ERR "Someone should implement ssl_stop\n");
@@ -148,9 +135,9 @@ static struct tty_operations ssl_ops = {
148 .flush_chars = line_flush_chars, 135 .flush_chars = line_flush_chars,
149 .set_termios = line_set_termios, 136 .set_termios = line_set_termios,
150 .ioctl = line_ioctl, 137 .ioctl = line_ioctl,
138 .throttle = line_throttle,
139 .unthrottle = line_unthrottle,
151#if 0 140#if 0
152 .throttle = ssl_throttle,
153 .unthrottle = ssl_unthrottle,
154 .stop = ssl_stop, 141 .stop = ssl_stop,
155 .start = ssl_start, 142 .start = ssl_start,
156 .hangup = ssl_hangup, 143 .hangup = ssl_hangup,
@@ -183,7 +170,7 @@ static int ssl_console_setup(struct console *co, char *options)
183{ 170{
184 struct line *line = &serial_lines[co->index]; 171 struct line *line = &serial_lines[co->index];
185 172
186 return console_open_chan(line,co,&opts); 173 return console_open_chan(line, co, &opts);
187} 174}
188 175
189static struct console ssl_cons = { 176static struct console ssl_cons = {
@@ -199,12 +186,13 @@ int ssl_init(void)
199{ 186{
200 char *new_title; 187 char *new_title;
201 188
202 printk(KERN_INFO "Initializing software serial port version %d\n", 189 printk(KERN_INFO "Initializing software serial port version %d\n",
203 ssl_version); 190 ssl_version);
204 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops, 191 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops,
205 serial_lines, ARRAY_SIZE(serial_lines)); 192 serial_lines,
193 ARRAY_SIZE(serial_lines));
206 194
207 lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); 195 lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
208 196
209 new_title = add_xterm_umid(opts.xterm_title); 197 new_title = add_xterm_umid(opts.xterm_title);
210 if (new_title != NULL) 198 if (new_title != NULL)
@@ -212,7 +200,7 @@ int ssl_init(void)
212 200
213 ssl_init_done = 1; 201 ssl_init_done = 1;
214 register_console(&ssl_cons); 202 register_console(&ssl_cons);
215 return(0); 203 return 0;
216} 204}
217late_initcall(ssl_init); 205late_initcall(ssl_init);
218 206
@@ -220,16 +208,13 @@ static void ssl_exit(void)
220{ 208{
221 if (!ssl_init_done) 209 if (!ssl_init_done)
222 return; 210 return;
223 close_lines(serial_lines, 211 close_lines(serial_lines, ARRAY_SIZE(serial_lines));
224 sizeof(serial_lines)/sizeof(serial_lines[0]));
225} 212}
226__uml_exitcall(ssl_exit); 213__uml_exitcall(ssl_exit);
227 214
228static int ssl_chan_setup(char *str) 215static int ssl_chan_setup(char *str)
229{ 216{
230 return(line_setup(serial_lines, 217 return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str);
231 sizeof(serial_lines)/sizeof(serial_lines[0]),
232 str, 1));
233} 218}
234 219
235__setup("ssl", ssl_chan_setup); 220__setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 005aa6333b..61db8b2fc8 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -75,7 +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 .id = line_id,
79 .remove = con_remove, 79 .remove = con_remove,
80 }, 80 },
81}; 81};
@@ -86,28 +86,27 @@ static struct lines console_lines = LINES_INIT(MAX_TTYS);
86 * individual elements are protected by individual semaphores. 86 * individual elements are protected by individual semaphores.
87 */ 87 */
88struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), 88struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
89 [ 1 ... MAX_TTYS - 1 ] = 89 [ 1 ... MAX_TTYS - 1 ] =
90 LINE_INIT(CONFIG_CON_CHAN, &driver) }; 90 LINE_INIT(CONFIG_CON_CHAN, &driver) };
91 91
92static int con_config(char *str) 92static int con_config(char *str)
93{ 93{
94 return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); 94 return line_config(vts, ARRAY_SIZE(vts), str, &opts);
95} 95}
96 96
97static int con_get_config(char *dev, char *str, int size, char **error_out) 97static int con_get_config(char *dev, char *str, int size, char **error_out)
98{ 98{
99 return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, 99 return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out);
100 size, error_out));
101} 100}
102 101
103static int con_remove(int n) 102static int con_remove(int n)
104{ 103{
105 return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n); 104 return line_remove(vts, ARRAY_SIZE(vts), n);
106} 105}
107 106
108static int con_open(struct tty_struct *tty, struct file *filp) 107static int con_open(struct tty_struct *tty, struct file *filp)
109{ 108{
110 return line_open(vts, tty, &opts); 109 return line_open(vts, tty);
111} 110}
112 111
113static int con_init_done = 0; 112static int con_init_done = 0;
@@ -117,16 +116,18 @@ static struct tty_operations console_ops = {
117 .close = line_close, 116 .close = line_close,
118 .write = line_write, 117 .write = line_write,
119 .put_char = line_put_char, 118 .put_char = line_put_char,
120 .write_room = line_write_room, 119 .write_room = line_write_room,
121 .chars_in_buffer = line_chars_in_buffer, 120 .chars_in_buffer = line_chars_in_buffer,
122 .flush_buffer = line_flush_buffer, 121 .flush_buffer = line_flush_buffer,
123 .flush_chars = line_flush_chars, 122 .flush_chars = line_flush_chars,
124 .set_termios = line_set_termios, 123 .set_termios = line_set_termios,
125 .ioctl = line_ioctl, 124 .ioctl = line_ioctl,
125 .throttle = line_throttle,
126 .unthrottle = line_unthrottle,
126}; 127};
127 128
128static void uml_console_write(struct console *console, const char *string, 129static void uml_console_write(struct console *console, const char *string,
129 unsigned len) 130 unsigned len)
130{ 131{
131 struct line *line = &vts[console->index]; 132 struct line *line = &vts[console->index];
132 unsigned long flags; 133 unsigned long flags;
@@ -146,7 +147,7 @@ static int uml_console_setup(struct console *co, char *options)
146{ 147{
147 struct line *line = &vts[co->index]; 148 struct line *line = &vts[co->index];
148 149
149 return console_open_chan(line,co,&opts); 150 return console_open_chan(line, co, &opts);
150} 151}
151 152
152static struct console stdiocons = { 153static struct console stdiocons = {
@@ -156,7 +157,7 @@ static struct console stdiocons = {
156 .setup = uml_console_setup, 157 .setup = uml_console_setup,
157 .flags = CON_PRINTBUFFER, 158 .flags = CON_PRINTBUFFER,
158 .index = -1, 159 .index = -1,
159 .data = &vts, 160 .data = &vts,
160}; 161};
161 162
162int stdio_init(void) 163int stdio_init(void)
@@ -166,11 +167,11 @@ int stdio_init(void)
166 console_driver = line_register_devfs(&console_lines, &driver, 167 console_driver = line_register_devfs(&console_lines, &driver,
167 &console_ops, vts, 168 &console_ops, vts,
168 ARRAY_SIZE(vts)); 169 ARRAY_SIZE(vts));
169 if (NULL == console_driver) 170 if (console_driver == NULL)
170 return -1; 171 return -1;
171 printk(KERN_INFO "Initialized stdio console driver\n"); 172 printk(KERN_INFO "Initialized stdio console driver\n");
172 173
173 lines_init(vts, sizeof(vts)/sizeof(vts[0])); 174 lines_init(vts, ARRAY_SIZE(vts), &opts);
174 175
175 new_title = add_xterm_umid(opts.xterm_title); 176 new_title = add_xterm_umid(opts.xterm_title);
176 if(new_title != NULL) 177 if(new_title != NULL)
@@ -178,7 +179,7 @@ int stdio_init(void)
178 179
179 con_init_done = 1; 180 con_init_done = 1;
180 register_console(&stdiocons); 181 register_console(&stdiocons);
181 return(0); 182 return 0;
182} 183}
183late_initcall(stdio_init); 184late_initcall(stdio_init);
184 185
@@ -186,13 +187,13 @@ static void console_exit(void)
186{ 187{
187 if (!con_init_done) 188 if (!con_init_done)
188 return; 189 return;
189 close_lines(vts, sizeof(vts)/sizeof(vts[0])); 190 close_lines(vts, ARRAY_SIZE(vts));
190} 191}
191__uml_exitcall(console_exit); 192__uml_exitcall(console_exit);
192 193
193static int console_chan_setup(char *str) 194static int console_chan_setup(char *str)
194{ 195{
195 return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); 196 return line_setup(vts, ARRAY_SIZE(vts), str);
196} 197}
197__setup("con", console_chan_setup); 198__setup("con", console_chan_setup);
198__channel_help(console_chan_setup, "con"); 199__channel_help(console_chan_setup, "con");
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index 6fbb670ee2..94c9265a4f 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -60,13 +60,6 @@ static int tty_open(int input, int output, int primary, void *d,
60 return(fd); 60 return(fd);
61} 61}
62 62
63static int tty_console_write(int fd, const char *buf, int n, void *d)
64{
65 struct tty_chan *data = d;
66
67 return(generic_console_write(fd, buf, n, &data->tt));
68}
69
70struct chan_ops tty_ops = { 63struct chan_ops tty_ops = {
71 .type = "tty", 64 .type = "tty",
72 .init = tty_chan_init, 65 .init = tty_chan_init,
@@ -74,7 +67,7 @@ struct chan_ops tty_ops = {
74 .close = generic_close, 67 .close = generic_close,
75 .read = generic_read, 68 .read = generic_read,
76 .write = generic_write, 69 .write = generic_write,
77 .console_write = tty_console_write, 70 .console_write = generic_console_write,
78 .window_size = generic_window_size, 71 .window_size = generic_window_size,
79 .free = generic_free, 72 .free = generic_free,
80 .winch = 0, 73 .winch = 0,
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 93898917cb..101efd26d4 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -117,6 +117,7 @@ static int ubd_open(struct inode * inode, struct file * filp);
117static int ubd_release(struct inode * inode, struct file * file); 117static int ubd_release(struct inode * inode, struct file * file);
118static int ubd_ioctl(struct inode * inode, struct file * file, 118static int ubd_ioctl(struct inode * inode, struct file * file,
119 unsigned int cmd, unsigned long arg); 119 unsigned int cmd, unsigned long arg);
120static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
120 121
121#define MAX_DEV (8) 122#define MAX_DEV (8)
122 123
@@ -125,6 +126,7 @@ static struct block_device_operations ubd_blops = {
125 .open = ubd_open, 126 .open = ubd_open,
126 .release = ubd_release, 127 .release = ubd_release,
127 .ioctl = ubd_ioctl, 128 .ioctl = ubd_ioctl,
129 .getgeo = ubd_getgeo,
128}; 130};
129 131
130/* Protected by the queue_lock */ 132/* Protected by the queue_lock */
@@ -706,7 +708,7 @@ static int ubd_config(char *str)
706{ 708{
707 int n, err; 709 int n, err;
708 710
709 str = uml_strdup(str); 711 str = kstrdup(str, GFP_KERNEL);
710 if(str == NULL){ 712 if(str == NULL){
711 printk(KERN_ERR "ubd_config failed to strdup string\n"); 713 printk(KERN_ERR "ubd_config failed to strdup string\n");
712 return(1); 714 return(1);
@@ -1058,10 +1060,19 @@ static void do_ubd_request(request_queue_t *q)
1058 } 1060 }
1059} 1061}
1060 1062
1063static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1064{
1065 struct ubd *dev = bdev->bd_disk->private_data;
1066
1067 geo->heads = 128;
1068 geo->sectors = 32;
1069 geo->cylinders = dev->size / (128 * 32 * 512);
1070 return 0;
1071}
1072
1061static int ubd_ioctl(struct inode * inode, struct file * file, 1073static int ubd_ioctl(struct inode * inode, struct file * file,
1062 unsigned int cmd, unsigned long arg) 1074 unsigned int cmd, unsigned long arg)
1063{ 1075{
1064 struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
1065 struct ubd *dev = inode->i_bdev->bd_disk->private_data; 1076 struct ubd *dev = inode->i_bdev->bd_disk->private_data;
1066 struct hd_driveid ubd_id = { 1077 struct hd_driveid ubd_id = {
1067 .cyls = 0, 1078 .cyls = 0,
@@ -1070,16 +1081,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1070 }; 1081 };
1071 1082
1072 switch (cmd) { 1083 switch (cmd) {
1073 struct hd_geometry g;
1074 struct cdrom_volctrl volume; 1084 struct cdrom_volctrl volume;
1075 case HDIO_GETGEO:
1076 if(!loc) return(-EINVAL);
1077 g.heads = 128;
1078 g.sectors = 32;
1079 g.cylinders = dev->size / (128 * 32 * 512);
1080 g.start = get_start_sect(inode->i_bdev);
1081 return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
1082
1083 case HDIO_GET_IDENTITY: 1085 case HDIO_GET_IDENTITY:
1084 ubd_id.cyls = dev->size / (128 * 32 * 512); 1086 ubd_id.cyls = dev->size / (128 * 32 * 512);
1085 if(copy_to_user((char __user *) arg, (char *) &ubd_id, 1087 if(copy_to_user((char __user *) arg, (char *) &ubd_id,
@@ -1101,31 +1103,33 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1101 return(-EINVAL); 1103 return(-EINVAL);
1102} 1104}
1103 1105
1104static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) 1106static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
1105{ 1107{
1106 struct uml_stat buf1, buf2; 1108 struct uml_stat buf1, buf2;
1107 int err; 1109 int err;
1108 1110
1109 if(from_cmdline == NULL) return(1); 1111 if(from_cmdline == NULL)
1110 if(!strcmp(from_cmdline, from_cow)) return(1); 1112 return 0;
1113 if(!strcmp(from_cmdline, from_cow))
1114 return 0;
1111 1115
1112 err = os_stat_file(from_cmdline, &buf1); 1116 err = os_stat_file(from_cmdline, &buf1);
1113 if(err < 0){ 1117 if(err < 0){
1114 printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); 1118 printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
1115 return(1); 1119 return 0;
1116 } 1120 }
1117 err = os_stat_file(from_cow, &buf2); 1121 err = os_stat_file(from_cow, &buf2);
1118 if(err < 0){ 1122 if(err < 0){
1119 printk("Couldn't stat '%s', err = %d\n", from_cow, -err); 1123 printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
1120 return(1); 1124 return 1;
1121 } 1125 }
1122 if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) 1126 if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
1123 return(1); 1127 return 0;
1124 1128
1125 printk("Backing file mismatch - \"%s\" requested,\n" 1129 printk("Backing file mismatch - \"%s\" requested,\n"
1126 "\"%s\" specified in COW header of \"%s\"\n", 1130 "\"%s\" specified in COW header of \"%s\"\n",
1127 from_cmdline, from_cow, cow); 1131 from_cmdline, from_cow, cow);
1128 return(0); 1132 return 1;
1129} 1133}
1130 1134
1131static int backing_file_mismatch(char *file, __u64 size, time_t mtime) 1135static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
@@ -1187,18 +1191,19 @@ int open_ubd_file(char *file, struct openflags *openflags,
1187 unsigned long long size; 1191 unsigned long long size;
1188 __u32 version, align; 1192 __u32 version, align;
1189 char *backing_file; 1193 char *backing_file;
1190 int fd, err, sectorsize, same, mode = 0644; 1194 int fd, err, sectorsize, asked_switch, mode = 0644;
1191 1195
1192 fd = os_open_file(file, *openflags, mode); 1196 fd = os_open_file(file, *openflags, mode);
1193 if(fd < 0){ 1197 if (fd < 0) {
1194 if((fd == -ENOENT) && (create_cow_out != NULL)) 1198 if ((fd == -ENOENT) && (create_cow_out != NULL))
1195 *create_cow_out = 1; 1199 *create_cow_out = 1;
1196 if(!openflags->w || 1200 if (!openflags->w ||
1197 ((fd != -EROFS) && (fd != -EACCES))) return(fd); 1201 ((fd != -EROFS) && (fd != -EACCES)))
1202 return fd;
1198 openflags->w = 0; 1203 openflags->w = 0;
1199 fd = os_open_file(file, *openflags, mode); 1204 fd = os_open_file(file, *openflags, mode);
1200 if(fd < 0) 1205 if (fd < 0)
1201 return(fd); 1206 return fd;
1202 } 1207 }
1203 1208
1204 err = os_lock_file(fd, openflags->w); 1209 err = os_lock_file(fd, openflags->w);
@@ -1207,7 +1212,9 @@ int open_ubd_file(char *file, struct openflags *openflags,
1207 goto out_close; 1212 goto out_close;
1208 } 1213 }
1209 1214
1210 if(backing_file_out == NULL) return(fd); 1215 /* Succesful return case! */
1216 if(backing_file_out == NULL)
1217 return(fd);
1211 1218
1212 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, 1219 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
1213 &size, &sectorsize, &align, bitmap_offset_out); 1220 &size, &sectorsize, &align, bitmap_offset_out);
@@ -1216,34 +1223,34 @@ int open_ubd_file(char *file, struct openflags *openflags,
1216 "errno = %d\n", file, -err); 1223 "errno = %d\n", file, -err);
1217 goto out_close; 1224 goto out_close;
1218 } 1225 }
1219 if(err) return(fd); 1226 if(err)
1220 1227 return(fd);
1221 if(backing_file_out == NULL) return(fd);
1222 1228
1223 same = same_backing_files(*backing_file_out, backing_file, file); 1229 asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
1224 1230
1225 if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ 1231 /* Allow switching only if no mismatch. */
1232 if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
1226 printk("Switching backing file to '%s'\n", *backing_file_out); 1233 printk("Switching backing file to '%s'\n", *backing_file_out);
1227 err = write_cow_header(file, fd, *backing_file_out, 1234 err = write_cow_header(file, fd, *backing_file_out,
1228 sectorsize, align, &size); 1235 sectorsize, align, &size);
1229 if(err){ 1236 if (err) {
1230 printk("Switch failed, errno = %d\n", -err); 1237 printk("Switch failed, errno = %d\n", -err);
1231 return(err); 1238 goto out_close;
1232 } 1239 }
1233 } 1240 } else {
1234 else {
1235 *backing_file_out = backing_file; 1241 *backing_file_out = backing_file;
1236 err = backing_file_mismatch(*backing_file_out, size, mtime); 1242 err = backing_file_mismatch(*backing_file_out, size, mtime);
1237 if(err) goto out_close; 1243 if (err)
1244 goto out_close;
1238 } 1245 }
1239 1246
1240 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, 1247 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
1241 bitmap_len_out, data_offset_out); 1248 bitmap_len_out, data_offset_out);
1242 1249
1243 return(fd); 1250 return fd;
1244 out_close: 1251 out_close:
1245 os_close_file(fd); 1252 os_close_file(fd);
1246 return(err); 1253 return err;
1247} 1254}
1248 1255
1249int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, 1256int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
@@ -1387,15 +1394,6 @@ int io_thread(void *arg)
1387 printk("io_thread - write failed, fd = %d, err = %d\n", 1394 printk("io_thread - write failed, fd = %d, err = %d\n",
1388 kernel_fd, -n); 1395 kernel_fd, -n);
1389 } 1396 }
1390}
1391 1397
1392/* 1398 return 0;
1393 * Overrides for Emacs so that we follow Linus's tabbing style. 1399}
1394 * Emacs will notice this stuff at the end of the file and automatically
1395 * adjust the settings for this buffer only. This must remain at the end
1396 * of the file.
1397 * ---------------------------------------------------------------------------
1398 * Local variables:
1399 * c-file-style: "linux"
1400 * End:
1401 */
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index b530f1a654..aaa6366610 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -194,13 +194,6 @@ static void xterm_free(void *d)
194 free(d); 194 free(d);
195} 195}
196 196
197static int xterm_console_write(int fd, const char *buf, int n, void *d)
198{
199 struct xterm_chan *data = d;
200
201 return(generic_console_write(fd, buf, n, &data->tt));
202}
203
204struct chan_ops xterm_ops = { 197struct chan_ops xterm_ops = {
205 .type = "xterm", 198 .type = "xterm",
206 .init = xterm_init, 199 .init = xterm_init,
@@ -208,7 +201,7 @@ struct chan_ops xterm_ops = {
208 .close = xterm_close, 201 .close = xterm_close,
209 .read = generic_read, 202 .read = generic_read,
210 .write = generic_write, 203 .write = generic_write,
211 .console_write = xterm_console_write, 204 .console_write = generic_console_write,
212 .window_size = generic_window_size, 205 .window_size = generic_window_size,
213 .free = xterm_free, 206 .free = xterm_free,
214 .winch = 1, 207 .winch = 1,
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index da9a6717e7..1bb5e9d942 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -14,21 +14,23 @@
14 14
15struct chan { 15struct chan {
16 struct list_head list; 16 struct list_head list;
17 struct list_head free_list;
18 struct line *line;
17 char *dev; 19 char *dev;
18 unsigned int primary:1; 20 unsigned int primary:1;
19 unsigned int input:1; 21 unsigned int input:1;
20 unsigned int output:1; 22 unsigned int output:1;
21 unsigned int opened:1; 23 unsigned int opened:1;
24 unsigned int enabled:1;
22 int fd; 25 int fd;
23 enum chan_init_pri pri;
24 struct chan_ops *ops; 26 struct chan_ops *ops;
25 void *data; 27 void *data;
26}; 28};
27 29
28extern void chan_interrupt(struct list_head *chans, struct work_struct *task, 30extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
29 struct tty_struct *tty, int irq); 31 struct tty_struct *tty, int irq);
30extern int parse_chan_pair(char *str, struct list_head *chans, int pri, 32extern int parse_chan_pair(char *str, struct line *line, int device,
31 int device, struct chan_opts *opts); 33 struct chan_opts *opts);
32extern int open_chan(struct list_head *chans); 34extern int open_chan(struct list_head *chans);
33extern int write_chan(struct list_head *chans, const char *buf, int len, 35extern int write_chan(struct list_head *chans, const char *buf, int len,
34 int write_irq); 36 int write_irq);
@@ -36,9 +38,11 @@ extern int console_write_chan(struct list_head *chans, const char *buf,
36 int len); 38 int len);
37extern int console_open_chan(struct line *line, struct console *co, 39extern int console_open_chan(struct line *line, struct console *co,
38 struct chan_opts *opts); 40 struct chan_opts *opts);
39extern void close_chan(struct list_head *chans); 41extern void deactivate_chan(struct list_head *chans, int irq);
42extern void reactivate_chan(struct list_head *chans, int irq);
40extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); 43extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
41extern void enable_chan(struct list_head *chans, struct tty_struct *tty); 44extern void enable_chan(struct line *line);
45extern void close_chan(struct list_head *chans, int delay_free_irq);
42extern int chan_window_size(struct list_head *chans, 46extern int chan_window_size(struct list_head *chans,
43 unsigned short *rows_out, 47 unsigned short *rows_out,
44 unsigned short *cols_out); 48 unsigned short *cols_out);
@@ -47,14 +51,3 @@ extern int chan_config_string(struct list_head *chans, char *str, int size,
47 char **error_out); 51 char **error_out);
48 52
49#endif 53#endif
50
51/*
52 * Overrides for Emacs so that we follow Linus's tabbing style.
53 * Emacs will notice this stuff at the end of the file and automatically
54 * adjust the settings for this buffer only. This must remain at the end
55 * of the file.
56 * ---------------------------------------------------------------------------
57 * Local variables:
58 * c-file-style: "linux"
59 * End:
60 */
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index f77d9aa4c1..659bb3cac3 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -25,7 +25,7 @@ struct chan_ops {
25 void (*close)(int, void *); 25 void (*close)(int, void *);
26 int (*read)(int, char *, void *); 26 int (*read)(int, char *, void *);
27 int (*write)(int, const char *, int, void *); 27 int (*write)(int, const char *, int, void *);
28 int (*console_write)(int, const char *, int, void *); 28 int (*console_write)(int, const char *, int);
29 int (*window_size)(int, void *, unsigned short *, unsigned short *); 29 int (*window_size)(int, void *, unsigned short *, unsigned short *);
30 void (*free)(void *); 30 void (*free)(void *);
31 int winch; 31 int winch;
@@ -37,7 +37,7 @@ extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops,
37extern void generic_close(int fd, void *unused); 37extern void generic_close(int fd, void *unused);
38extern int generic_read(int fd, char *c_out, void *unused); 38extern int generic_read(int fd, char *c_out, void *unused);
39extern int generic_write(int fd, const char *buf, int n, void *unused); 39extern int generic_write(int fd, const char *buf, int n, void *unused);
40extern int generic_console_write(int fd, const char *buf, int n, void *state); 40extern int generic_console_write(int fd, const char *buf, int n);
41extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, 41extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
42 unsigned short *cols_out); 42 unsigned short *cols_out);
43extern void generic_free(void *data); 43extern void generic_free(void *data);
diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h
index f25fa83a5d..b87b36a87d 100644
--- a/arch/um/include/choose-mode.h
+++ b/arch/um/include/choose-mode.h
@@ -23,6 +23,9 @@ static inline void *__choose_mode(void *tt, void *skas) {
23 23
24#elif defined(UML_CONFIG_MODE_TT) 24#elif defined(UML_CONFIG_MODE_TT)
25#define CHOOSE_MODE(tt, skas) (tt) 25#define CHOOSE_MODE(tt, skas) (tt)
26
27#else
28#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled
26#endif 29#endif
27 30
28#define CHOOSE_MODE_PROC(tt, skas, args...) \ 31#define CHOOSE_MODE_PROC(tt, skas, args...) \
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index f724b71721..b61deb8b36 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -18,19 +18,8 @@ extern int deactivate_all_fds(void);
18extern void forward_interrupts(int pid); 18extern void forward_interrupts(int pid);
19extern void init_irq_signals(int on_sigstack); 19extern void init_irq_signals(int on_sigstack);
20extern void forward_ipi(int fd, int pid); 20extern void forward_ipi(int fd, int pid);
21extern void free_irq_later(int irq, void *dev_id);
22extern int activate_ipi(int fd, int pid); 21extern int activate_ipi(int fd, int pid);
23extern unsigned long irq_lock(void); 22extern unsigned long irq_lock(void);
24extern void irq_unlock(unsigned long flags); 23extern void irq_unlock(unsigned long flags);
25#endif
26 24
27/* 25#endif
28 * Overrides for Emacs so that we follow Linus's tabbing style.
29 * Emacs will notice this stuff at the end of the file and automatically
30 * adjust the settings for this buffer only. This must remain at the end
31 * of the file.
32 * ---------------------------------------------------------------------------
33 * Local variables:
34 * c-file-style: "linux"
35 * End:
36 */
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 1e3170768b..7d223beccb 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -17,7 +17,7 @@ extern int errno;
17 17
18extern int clone(int (*proc)(void *), void *sp, int flags, void *data); 18extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
19extern int sleep(int); 19extern int sleep(int);
20extern int printf(char *fmt, ...); 20extern int printf(const char *fmt, ...);
21extern char *strerror(int errnum); 21extern char *strerror(int errnum);
22extern char *ptsname(int __fd); 22extern char *ptsname(int __fd);
23extern int munmap(void *, int); 23extern int munmap(void *, int);
@@ -35,15 +35,6 @@ extern int read(unsigned int, char *, int);
35extern int pipe(int *); 35extern int pipe(int *);
36extern int sched_yield(void); 36extern int sched_yield(void);
37extern int ptrace(int op, int pid, long addr, long data); 37extern int ptrace(int op, int pid, long addr, long data);
38
38#endif 39#endif
39 40
40/*
41 * Overrides for Emacs so that we follow Linus's tabbing style.
42 * Emacs will notice this stuff at the end of the file and automatically
43 * adjust the settings for this buffer only. This must remain at the end
44 * of the file.
45 * ---------------------------------------------------------------------------
46 * Local variables:
47 * c-file-style: "linux"
48 * End:
49 */
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index e5fec55701..c649108a9e 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -10,6 +10,19 @@
10#include "sysdep/ptrace.h" 10#include "sysdep/ptrace.h"
11#include "sysdep/faultinfo.h" 11#include "sysdep/faultinfo.h"
12 12
13typedef void (*kern_hndl)(int, union uml_pt_regs *);
14
15struct kern_handlers {
16 kern_hndl relay_signal;
17 kern_hndl winch;
18 kern_hndl bus_handler;
19 kern_hndl page_fault;
20 kern_hndl sigio_handler;
21 kern_hndl timer_handler;
22};
23
24extern struct kern_handlers handlinfo_kern;
25
13extern int ncpus; 26extern int ncpus;
14extern char *linux_prog; 27extern char *linux_prog;
15extern char *gdb_init; 28extern char *gdb_init;
@@ -51,8 +64,6 @@ extern void timer_handler(int sig, union uml_pt_regs *regs);
51extern int set_signals(int enable); 64extern int set_signals(int enable);
52extern void force_sigbus(void); 65extern void force_sigbus(void);
53extern int pid_to_processor_id(int pid); 66extern int pid_to_processor_id(int pid);
54extern void block_signals(void);
55extern void unblock_signals(void);
56extern void deliver_signals(void *t); 67extern void deliver_signals(void *t);
57extern int next_syscall_index(int max); 68extern int next_syscall_index(int max);
58extern int next_trap_index(int max); 69extern int next_trap_index(int max);
@@ -109,9 +120,13 @@ extern void machine_halt(void);
109extern int is_syscall(unsigned long addr); 120extern int is_syscall(unsigned long addr);
110extern void arch_switch(void); 121extern void arch_switch(void);
111extern void free_irq(unsigned int, void *); 122extern void free_irq(unsigned int, void *);
112extern int um_in_interrupt(void);
113extern int cpu(void); 123extern int cpu(void);
114 124
125/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
126extern int __cant_sleep(void);
127extern void segv_handler(int sig, union uml_pt_regs *regs);
128extern void sigio_handler(int sig, union uml_pt_regs *regs);
129
115#endif 130#endif
116 131
117/* 132/*
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 5323d22a6c..6f4d680dc1 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -32,11 +32,13 @@ struct line_driver {
32}; 32};
33 33
34struct line { 34struct line {
35 struct tty_struct *tty;
35 char *init_str; 36 char *init_str;
36 int init_pri; 37 int init_pri;
37 struct list_head chan_list; 38 struct list_head chan_list;
38 int valid; 39 int valid;
39 int count; 40 int count;
41 int throttled;
40 /*This lock is actually, mostly, local to*/ 42 /*This lock is actually, mostly, local to*/
41 spinlock_t lock; 43 spinlock_t lock;
42 44
@@ -58,14 +60,15 @@ struct line {
58#define LINE_INIT(str, d) \ 60#define LINE_INIT(str, d) \
59 { init_str : str, \ 61 { init_str : str, \
60 init_pri : INIT_STATIC, \ 62 init_pri : INIT_STATIC, \
61 chan_list : { }, \
62 valid : 1, \ 63 valid : 1, \
64 throttled : 0, \
65 lock : SPIN_LOCK_UNLOCKED, \
63 buffer : NULL, \ 66 buffer : NULL, \
64 head : NULL, \ 67 head : NULL, \
65 tail : NULL, \ 68 tail : NULL, \
66 sigio : 0, \ 69 sigio : 0, \
67 driver : d, \ 70 driver : d, \
68 have_irq : 0 } 71 have_irq : 0 }
69 72
70struct lines { 73struct lines {
71 int num; 74 int num;
@@ -74,11 +77,11 @@ struct lines {
74#define LINES_INIT(n) { num : n } 77#define LINES_INIT(n) { num : n }
75 78
76extern void line_close(struct tty_struct *tty, struct file * filp); 79extern void line_close(struct tty_struct *tty, struct file * filp);
77extern int line_open(struct line *lines, struct tty_struct *tty, 80extern int line_open(struct line *lines, struct tty_struct *tty);
78 struct chan_opts *opts); 81extern int line_setup(struct line *lines, unsigned int sizeof_lines,
79extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, 82 char *init);
80 int all_allowed); 83extern int line_write(struct tty_struct *tty, const unsigned char *buf,
81extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); 84 int len);
82extern void line_put_char(struct tty_struct *tty, unsigned char ch); 85extern void line_put_char(struct tty_struct *tty, unsigned char ch);
83extern void line_set_termios(struct tty_struct *tty, struct termios * old); 86extern void line_set_termios(struct tty_struct *tty, struct termios * old);
84extern int line_chars_in_buffer(struct tty_struct *tty); 87extern int line_chars_in_buffer(struct tty_struct *tty);
@@ -87,23 +90,27 @@ extern void line_flush_chars(struct tty_struct *tty);
87extern int line_write_room(struct tty_struct *tty); 90extern int line_write_room(struct tty_struct *tty);
88extern int line_ioctl(struct tty_struct *tty, struct file * file, 91extern int line_ioctl(struct tty_struct *tty, struct file * file,
89 unsigned int cmd, unsigned long arg); 92 unsigned int cmd, unsigned long arg);
93extern void line_throttle(struct tty_struct *tty);
94extern void line_unthrottle(struct tty_struct *tty);
90 95
91extern char *add_xterm_umid(char *base); 96extern char *add_xterm_umid(char *base);
92extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty); 97extern int line_setup_irq(int fd, int input, int output, struct line *line,
98 void *data);
93extern void line_close_chan(struct line *line); 99extern void line_close_chan(struct line *line);
94extern void line_disable(struct tty_struct *tty, int current_irq); 100extern struct tty_driver * line_register_devfs(struct lines *set,
95extern struct tty_driver * line_register_devfs(struct lines *set, 101 struct line_driver *line_driver,
96 struct line_driver *line_driver,
97 struct tty_operations *driver, 102 struct tty_operations *driver,
98 struct line *lines, 103 struct line *lines,
99 int nlines); 104 int nlines);
100extern void lines_init(struct line *lines, int nlines); 105extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
101extern void close_lines(struct line *lines, int nlines); 106extern void close_lines(struct line *lines, int nlines);
102 107
103extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str); 108extern int line_config(struct line *lines, unsigned int sizeof_lines,
109 char *str, struct chan_opts *opts);
104extern int line_id(char **str, int *start_out, int *end_out); 110extern int line_id(char **str, int *start_out, int *end_out);
105extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); 111extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
106extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str, 112extern int line_get_config(char *dev, struct line *lines,
113 unsigned int sizeof_lines, char *str,
107 int size, char **error_out); 114 int size, char **error_out);
108 115
109#endif 116#endif
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
new file mode 100644
index 0000000000..018b3819ab
--- /dev/null
+++ b/arch/um/include/longjmp.h
@@ -0,0 +1,19 @@
1#ifndef __UML_LONGJMP_H
2#define __UML_LONGJMP_H
3
4#include <setjmp.h>
5#include "os.h"
6
7#define UML_SIGLONGJMP(buf, val) do { \
8 longjmp(*buf, val); \
9} while(0)
10
11#define UML_SIGSETJMP(buf, enable) ({ \
12 int n; \
13 enable = get_signals(); \
14 n = setjmp(*buf); \
15 if(n != 0) \
16 set_signals(enable); \
17 n; })
18
19#endif
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index b1b512f470..58f67d3911 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -32,7 +32,7 @@ struct mconsole_reply {
32 32
33struct mconsole_notify { 33struct mconsole_notify {
34 u32 magic; 34 u32 magic;
35 u32 version; 35 u32 version;
36 enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, 36 enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
37 MCONSOLE_USER_NOTIFY } type; 37 MCONSOLE_USER_NOTIFY } type;
38 u32 len; 38 u32 len;
@@ -66,7 +66,9 @@ struct mc_request
66extern char mconsole_socket_name[]; 66extern char mconsole_socket_name[];
67 67
68extern int mconsole_unlink_socket(void); 68extern int mconsole_unlink_socket(void);
69extern int mconsole_reply(struct mc_request *req, char *reply, int err, 69extern int mconsole_reply_len(struct mc_request *req, const char *reply,
70 int len, int err, int more);
71extern int mconsole_reply(struct mc_request *req, const char *str, int err,
70 int more); 72 int more);
71 73
72extern void mconsole_version(struct mc_request *req); 74extern void mconsole_version(struct mc_request *req);
@@ -84,7 +86,7 @@ extern void mconsole_proc(struct mc_request *req);
84extern void mconsole_stack(struct mc_request *req); 86extern void mconsole_stack(struct mc_request *req);
85 87
86extern int mconsole_get_request(int fd, struct mc_request *req); 88extern int mconsole_get_request(int fd, struct mc_request *req);
87extern int mconsole_notify(char *sock_name, int type, const void *data, 89extern int mconsole_notify(char *sock_name, int type, const void *data,
88 int len); 90 int len);
89extern char *mconsole_notify_socket(void); 91extern char *mconsole_notify_socket(void);
90extern void lock_notify(void); 92extern void lock_notify(void);
diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h
index 2d88afd0cf..e7539a8451 100644
--- a/arch/um/include/mode_kern.h
+++ b/arch/um/include/mode_kern.h
@@ -9,22 +9,11 @@
9#include "linux/config.h" 9#include "linux/config.h"
10 10
11#ifdef CONFIG_MODE_TT 11#ifdef CONFIG_MODE_TT
12#include "mode_kern-tt.h" 12#include "mode_kern_tt.h"
13#endif 13#endif
14 14
15#ifdef CONFIG_MODE_SKAS 15#ifdef CONFIG_MODE_SKAS
16#include "mode_kern-skas.h" 16#include "mode_kern_skas.h"
17#endif 17#endif
18 18
19#endif 19#endif
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/include/os.h b/arch/um/include/os.h
index 2cccfa5b8a..eb1710b812 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -9,6 +9,9 @@
9#include "uml-config.h" 9#include "uml-config.h"
10#include "asm/types.h" 10#include "asm/types.h"
11#include "../os/include/file.h" 11#include "../os/include/file.h"
12#include "sysdep/ptrace.h"
13#include "kern_util.h"
14#include "skas/mm_id.h"
12 15
13#define OS_TYPE_FILE 1 16#define OS_TYPE_FILE 1
14#define OS_TYPE_DIR 2 17#define OS_TYPE_DIR 2
@@ -188,11 +191,12 @@ extern int os_protect_memory(void *addr, unsigned long len,
188 int r, int w, int x); 191 int r, int w, int x);
189extern int os_unmap_memory(void *addr, int len); 192extern int os_unmap_memory(void *addr, int len);
190extern void os_flush_stdout(void); 193extern void os_flush_stdout(void);
191extern unsigned long long os_usecs(void);
192 194
193/* tt.c 195/* tt.c
194 * for tt mode only (will be deleted in future...) 196 * for tt mode only (will be deleted in future...)
195 */ 197 */
198extern void stop(void);
199extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
196extern int protect_memory(unsigned long addr, unsigned long len, 200extern int protect_memory(unsigned long addr, unsigned long len,
197 int r, int w, int x, int must_succeed); 201 int r, int w, int x, int must_succeed);
198extern void forward_pending_sigio(int target); 202extern void forward_pending_sigio(int target);
@@ -213,15 +217,78 @@ extern int run_helper_thread(int (*proc)(void *), void *arg,
213 int stack_order); 217 int stack_order);
214extern int helper_wait(int pid); 218extern int helper_wait(int pid);
215 219
216#endif 220/* umid.c */
217 221
218/* 222extern int umid_file_name(char *name, char *buf, int len);
219 * Overrides for Emacs so that we follow Linus's tabbing style. 223extern int set_umid(char *name);
220 * Emacs will notice this stuff at the end of the file and automatically 224extern char *get_umid(void);
221 * adjust the settings for this buffer only. This must remain at the end 225
222 * of the file. 226/* signal.c */
223 * --------------------------------------------------------------------------- 227extern void set_sigstack(void *sig_stack, int size);
224 * Local variables: 228extern void remove_sigstack(void);
225 * c-file-style: "linux" 229extern void set_handler(int sig, void (*handler)(int), int flags, ...);
226 * End: 230extern int change_sig(int signal, int on);
227 */ 231extern void block_signals(void);
232extern void unblock_signals(void);
233extern int get_signals(void);
234extern int set_signals(int enable);
235extern void os_usr1_signal(int on);
236
237/* trap.c */
238extern void os_fill_handlinfo(struct kern_handlers h);
239extern void do_longjmp(void *p, int val);
240
241/* util.c */
242extern void stack_protections(unsigned long address);
243extern void task_protections(unsigned long address);
244extern int raw(int fd);
245extern void setup_machinename(char *machine_out);
246extern void setup_hostinfo(void);
247extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
248
249/* time.c */
250#define BILLION (1000 * 1000 * 1000)
251
252extern void switch_timers(int to_real);
253extern void idle_sleep(int secs);
254extern void enable_timer(void);
255extern void disable_timer(void);
256extern void user_time_init(void);
257extern void uml_idle_timer(void);
258extern unsigned long long os_nsecs(void);
259
260/* skas/mem.c */
261extern long run_syscall_stub(struct mm_id * mm_idp,
262 int syscall, unsigned long *args, long expected,
263 void **addr, int done);
264extern long syscall_stub_data(struct mm_id * mm_idp,
265 unsigned long *data, int data_count,
266 void **addr, void **stub_addr);
267extern int map(struct mm_id * mm_idp, unsigned long virt,
268 unsigned long len, int r, int w, int x, int phys_fd,
269 unsigned long long offset, int done, void **data);
270extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
271 int done, void **data);
272extern int protect(struct mm_id * mm_idp, unsigned long addr,
273 unsigned long len, int r, int w, int x, int done,
274 void **data);
275
276/* skas/process.c */
277extern int is_skas_winch(int pid, int fd, void *data);
278extern int start_userspace(unsigned long stub_stack);
279extern int copy_context_skas0(unsigned long stack, int pid);
280extern void userspace(union uml_pt_regs *regs);
281extern void map_stub_pages(int fd, unsigned long code,
282 unsigned long data, unsigned long stack);
283extern void new_thread(void *stack, void **switch_buf_ptr,
284 void **fork_buf_ptr, void (*handler)(int));
285extern void thread_wait(void *sw, void *fb);
286extern void switch_threads(void *me, void *next);
287extern int start_idle_thread(void *stack, void *switch_buf_ptr,
288 void **fork_buf_ptr);
289extern void initial_thread_cb_skas(void (*proc)(void *),
290 void *arg);
291extern void halt_skas(void);
292extern void reboot_skas(void);
293
294#endif
diff --git a/arch/um/include/signal_user.h b/arch/um/include/signal_user.h
deleted file mode 100644
index b075e543d8..0000000000
--- a/arch/um/include/signal_user.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SIGNAL_USER_H__
7#define __SIGNAL_USER_H__
8
9extern int signal_stack_size;
10
11extern int change_sig(int signal, int on);
12extern void set_sigstack(void *stack, int size);
13extern void set_handler(int sig, void (*handler)(int), int flags, ...);
14extern int set_signals(int enable);
15extern int get_signals(void);
16
17#endif
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/skas/include/mm_id.h b/arch/um/include/skas/mm_id.h
index 48dd0989dd..48dd0989dd 100644
--- a/arch/um/kernel/skas/include/mm_id.h
+++ b/arch/um/include/skas/mm_id.h
diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h
new file mode 100644
index 0000000000..d8869a6ef1
--- /dev/null
+++ b/arch/um/include/skas/mmu-skas.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_MMU_H
7#define __SKAS_MMU_H
8
9#include "linux/config.h"
10#include "mm_id.h"
11#include "asm/ldt.h"
12
13struct mmu_context_skas {
14 struct mm_id id;
15 unsigned long last_page_table;
16#ifdef CONFIG_3_LEVEL_PGTABLES
17 unsigned long last_pmd;
18#endif
19 uml_ldt_t ldt;
20};
21
22extern void switch_mm_skas(struct mm_id * mm_idp);
23
24#endif
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
new file mode 100644
index 0000000000..260065cfee
--- /dev/null
+++ b/arch/um/include/skas/mode-skas.h
@@ -0,0 +1,19 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MODE_SKAS_H__
7#define __MODE_SKAS_H__
8
9#include <sysdep/ptrace.h>
10
11extern unsigned long exec_regs[];
12extern unsigned long exec_fp_regs[];
13extern unsigned long exec_fpx_regs[];
14extern int have_fpx_regs;
15
16extern void sig_handler_common_skas(int sig, void *sc_ptr);
17extern void kill_off_processes_skas(void);
18
19#endif
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/include/skas/mode_kern_skas.h
index c97a80dfe3..63c58739bd 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/include/skas/mode_kern_skas.h
@@ -18,7 +18,6 @@ extern int copy_thread_skas(int nr, unsigned long clone_flags,
18 unsigned long sp, unsigned long stack_top, 18 unsigned long sp, unsigned long stack_top,
19 struct task_struct *p, struct pt_regs *regs); 19 struct task_struct *p, struct pt_regs *regs);
20extern void release_thread_skas(struct task_struct *task); 20extern void release_thread_skas(struct task_struct *task);
21extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
22extern void init_idle_skas(void); 21extern void init_idle_skas(void);
23extern void flush_tlb_kernel_range_skas(unsigned long start, 22extern void flush_tlb_kernel_range_skas(unsigned long start,
24 unsigned long end); 23 unsigned long end);
@@ -39,14 +38,3 @@ extern int thread_pid_skas(struct task_struct *task);
39#define kmem_end_skas (host_task_size - 1024 * 1024) 38#define kmem_end_skas (host_task_size - 1024 * 1024)
40 39
41#endif 40#endif
42
43/*
44 * Overrides for Emacs so that we follow Linus's tabbing style.
45 * Emacs will notice this stuff at the end of the file and automatically
46 * adjust the settings for this buffer only. This must remain at the end
47 * of the file.
48 * ---------------------------------------------------------------------------
49 * Local variables:
50 * c-file-style: "linux"
51 * End:
52 */
diff --git a/arch/um/kernel/skas/include/proc_mm.h b/arch/um/include/skas/proc_mm.h
index cce61a6790..9028092096 100644
--- a/arch/um/kernel/skas/include/proc_mm.h
+++ b/arch/um/include/skas/proc_mm.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -22,13 +22,13 @@ struct mm_mmap {
22 22
23struct mm_munmap { 23struct mm_munmap {
24 unsigned long addr; 24 unsigned long addr;
25 unsigned long len; 25 unsigned long len;
26}; 26};
27 27
28struct mm_mprotect { 28struct mm_mprotect {
29 unsigned long addr; 29 unsigned long addr;
30 unsigned long len; 30 unsigned long len;
31 unsigned int prot; 31 unsigned int prot;
32}; 32};
33 33
34struct proc_mm_op { 34struct proc_mm_op {
@@ -42,14 +42,3 @@ struct proc_mm_op {
42}; 42};
43 43
44#endif 44#endif
45
46/*
47 * Overrides for Emacs so that we follow Linus's tabbing style.
48 * Emacs will notice this stuff at the end of the file and automatically
49 * adjust the settings for this buffer only. This must remain at the end
50 * of the file.
51 * ---------------------------------------------------------------------------
52 * Local variables:
53 * c-file-style: "linux"
54 * End:
55 */
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
new file mode 100644
index 0000000000..86357282d6
--- /dev/null
+++ b/arch/um/include/skas/skas.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_H
7#define __SKAS_H
8
9#include "mm_id.h"
10#include "sysdep/ptrace.h"
11
12extern int userspace_pid[];
13extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
14extern int skas_needs_stub;
15
16extern int user_thread(unsigned long stack, int flags);
17extern void new_thread_proc(void *stack, void (*handler)(int sig));
18extern void new_thread_handler(int sig);
19extern void handle_syscall(union uml_pt_regs *regs);
20extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
21extern int new_mm(unsigned long stack);
22extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
23extern long execute_syscall_skas(void *r);
24extern unsigned long current_stub_stack(void);
25
26#endif
diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/include/skas/stub-data.h
index f6ed92c372..f6ed92c372 100644
--- a/arch/um/kernel/skas/include/stub-data.h
+++ b/arch/um/include/skas/stub-data.h
diff --git a/arch/um/include/skas/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h
new file mode 100644
index 0000000000..224a75f4c0
--- /dev/null
+++ b/arch/um/include/skas/uaccess-skas.h
@@ -0,0 +1,21 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_UACCESS_H
7#define __SKAS_UACCESS_H
8
9#include "asm/errno.h"
10
11/* No SKAS-specific checking. */
12#define access_ok_skas(type, addr, size) 0
13
14extern int copy_from_user_skas(void *to, const void __user *from, int n);
15extern int copy_to_user_skas(void __user *to, const void *from, int n);
16extern int strncpy_from_user_skas(char *dst, const char __user *src, int count);
17extern int __clear_user_skas(void __user *mem, int len);
18extern int clear_user_skas(void __user *mem, int len);
19extern int strnlen_user_skas(const void __user *str, int len);
20
21#endif
diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
index 764ba4db47..7d3d202d7f 100644
--- a/arch/um/include/sysdep-i386/checksum.h
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -36,7 +36,7 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
36 int len, int sum) 36 int len, int sum)
37{ 37{
38 memcpy(dst, src, len); 38 memcpy(dst, src, len);
39 return(csum_partial(dst, len, sum)); 39 return csum_partial(dst, len, sum);
40} 40}
41 41
42/* 42/*
@@ -104,7 +104,7 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
104 : "=r" (sum), "=r" (iph), "=r" (ihl) 104 : "=r" (sum), "=r" (iph), "=r" (ihl)
105 : "1" (iph), "2" (ihl) 105 : "1" (iph), "2" (ihl)
106 : "memory"); 106 : "memory");
107 return(sum); 107 return sum;
108} 108}
109 109
110/* 110/*
diff --git a/arch/um/sys-i386/kernel-offsets.c b/arch/um/include/sysdep-i386/kernel-offsets.h
index 35db850575..82f96c5741 100644
--- a/arch/um/sys-i386/kernel-offsets.c
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -1,12 +1,9 @@
1#include <linux/config.h>
2#include <linux/stddef.h> 1#include <linux/stddef.h>
3#include <linux/sched.h> 2#include <linux/sched.h>
4#include <linux/time.h>
5#include <linux/elf.h> 3#include <linux/elf.h>
6#include <asm/page.h>
7 4
8#define DEFINE(sym, val) \ 5#define DEFINE(sym, val) \
9 asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 6 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
10 7
11#define STR(x) #x 8#define STR(x) #x
12#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : ) 9#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h
index a49ceb199e..b492b12b4a 100644
--- a/arch/um/include/sysdep-i386/stub.h
+++ b/arch/um/include/sysdep-i386/stub.h
@@ -6,8 +6,12 @@
6#ifndef __SYSDEP_STUB_H 6#ifndef __SYSDEP_STUB_H
7#define __SYSDEP_STUB_H 7#define __SYSDEP_STUB_H
8 8
9#include <sys/mman.h>
9#include <asm/ptrace.h> 10#include <asm/ptrace.h>
10#include <asm/unistd.h> 11#include <asm/unistd.h>
12#include "stub-data.h"
13#include "kern_constants.h"
14#include "uml-config.h"
11 15
12extern void stub_segv_handler(int sig); 16extern void stub_segv_handler(int sig);
13extern void stub_clone_handler(void); 17extern void stub_clone_handler(void);
@@ -16,6 +20,15 @@ extern void stub_clone_handler(void);
16#define STUB_MMAP_NR __NR_mmap2 20#define STUB_MMAP_NR __NR_mmap2
17#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) 21#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)
18 22
23static inline long stub_syscall0(long syscall)
24{
25 long ret;
26
27 __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall));
28
29 return ret;
30}
31
19static inline long stub_syscall1(long syscall, long arg1) 32static inline long stub_syscall1(long syscall, long arg1)
20{ 33{
21 long ret; 34 long ret;
@@ -67,23 +80,22 @@ static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
67 return ret; 80 return ret;
68} 81}
69 82
70static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, 83static inline void trap_myself(void)
71 long arg4, long arg5, long arg6)
72{ 84{
73 long ret; 85 __asm("int3");
74
75 __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; "
76 "int $0x80 ; pop %%ebp"
77 : "=a" (ret)
78 : "g" (syscall), "b" (arg1), "c" (arg2), "d" (arg3),
79 "S" (arg4), "D" (arg5), "0" (arg6));
80
81 return ret;
82} 86}
83 87
84static inline void trap_myself(void) 88static inline void remap_stack(int fd, unsigned long offset)
85{ 89{
86 __asm("int3"); 90 __asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;"
91 "movl %7, %%ebx ; movl %%eax, (%%ebx)"
92 : : "g" (STUB_MMAP_NR), "b" (UML_CONFIG_STUB_DATA),
93 "c" (UM_KERN_PAGE_SIZE),
94 "d" (PROT_READ | PROT_WRITE),
95 "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
96 "a" (offset),
97 "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err)
98 : "memory");
87} 99}
88 100
89#endif 101#endif
diff --git a/arch/um/sys-x86_64/kernel-offsets.c b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index bfcb104b84..5ce93abd0b 100644
--- a/arch/um/sys-x86_64/kernel-offsets.c
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -6,7 +6,7 @@
6#include <asm/page.h> 6#include <asm/page.h>
7 7
8#define DEFINE(sym, val) \ 8#define DEFINE(sym, val) \
9 asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 9 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
10 10
11#define DEFINE_STR1(x) #x 11#define DEFINE_STR1(x) #x
12#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : ) 12#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h
index 2bd6e7a972..92e989f817 100644
--- a/arch/um/include/sysdep-x86_64/stub.h
+++ b/arch/um/include/sysdep-x86_64/stub.h
@@ -6,9 +6,12 @@
6#ifndef __SYSDEP_STUB_H 6#ifndef __SYSDEP_STUB_H
7#define __SYSDEP_STUB_H 7#define __SYSDEP_STUB_H
8 8
9#include <asm/ptrace.h> 9#include <sys/mman.h>
10#include <asm/unistd.h> 10#include <asm/unistd.h>
11#include <sysdep/ptrace_user.h> 11#include <sysdep/ptrace_user.h>
12#include "stub-data.h"
13#include "kern_constants.h"
14#include "uml-config.h"
12 15
13extern void stub_segv_handler(int sig); 16extern void stub_segv_handler(int sig);
14extern void stub_clone_handler(void); 17extern void stub_clone_handler(void);
@@ -20,6 +23,17 @@ extern void stub_clone_handler(void);
20#define __syscall_clobber "r11","rcx","memory" 23#define __syscall_clobber "r11","rcx","memory"
21#define __syscall "syscall" 24#define __syscall "syscall"
22 25
26static inline long stub_syscall0(long syscall)
27{
28 long ret;
29
30 __asm__ volatile (__syscall
31 : "=a" (ret)
32 : "0" (syscall) : __syscall_clobber );
33
34 return ret;
35}
36
23static inline long stub_syscall2(long syscall, long arg1, long arg2) 37static inline long stub_syscall2(long syscall, long arg1, long arg2)
24{ 38{
25 long ret; 39 long ret;
@@ -71,23 +85,23 @@ static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
71 return ret; 85 return ret;
72} 86}
73 87
74static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, 88static inline void trap_myself(void)
75 long arg4, long arg5, long arg6)
76{ 89{
77 long ret; 90 __asm("int3");
78
79 __asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; "
80 "movq %7, %%r9; " __syscall : "=a" (ret)
81 : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
82 "g" (arg4), "g" (arg5), "g" (arg6)
83 : __syscall_clobber, "r10", "r8", "r9" );
84
85 return ret;
86} 91}
87 92
88static inline void trap_myself(void) 93static inline void remap_stack(long fd, unsigned long offset)
89{ 94{
90 __asm("int3"); 95 __asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; "
96 "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; "
97 "movq %%rax, (%%rbx)":
98 : "a" (STUB_MMAP_NR), "D" (UML_CONFIG_STUB_DATA),
99 "S" (UM_KERN_PAGE_SIZE),
100 "d" (PROT_READ | PROT_WRITE),
101 "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
102 "g" (offset),
103 "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err)
104 : __syscall_clobber, "r10", "r8", "r9" );
91} 105}
92 106
93#endif 107#endif
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
deleted file mode 100644
index 17d7ef2141..0000000000
--- a/arch/um/include/time_user.h
+++ /dev/null
@@ -1,19 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TIME_USER_H__
7#define __TIME_USER_H__
8
9extern void timer(void);
10extern void switch_timers(int to_real);
11extern void idle_sleep(int secs);
12extern void enable_timer(void);
13extern void prepare_timer(void * ptr);
14extern void disable_timer(void);
15extern unsigned long time_lock(void);
16extern void time_unlock(unsigned long);
17extern void user_time_init(void);
18
19#endif
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/include/tt/debug.h
index 738435461e..9778fa8382 100644
--- a/arch/um/kernel/tt/include/debug.h
+++ b/arch/um/include/tt/debug.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and
3 * Lars Brinkhoff. 3 * Lars Brinkhoff.
4 * Licensed under the GPL 4 * Licensed under the GPL
diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h
new file mode 100644
index 0000000000..572a78b225
--- /dev/null
+++ b/arch/um/include/tt/mmu-tt.h
@@ -0,0 +1,12 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MMU_H
7#define __TT_MMU_H
8
9struct mmu_context_tt {
10};
11
12#endif
diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h
new file mode 100644
index 0000000000..2823cd56ee
--- /dev/null
+++ b/arch/um/include/tt/mode-tt.h
@@ -0,0 +1,23 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MODE_TT_H__
7#define __MODE_TT_H__
8
9#include "sysdep/ptrace.h"
10
11enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
12
13extern int tracing_pid;
14
15extern int tracer(int (*init_proc)(void *), void *sp);
16extern void sig_handler_common_tt(int sig, void *sc);
17extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
18extern void reboot_tt(void);
19extern void halt_tt(void);
20extern int is_tracer_winch(int pid, int fd, void *data);
21extern void kill_off_processes_tt(void);
22
23#endif
diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h
new file mode 100644
index 0000000000..efa0012550
--- /dev/null
+++ b/arch/um/include/tt/mode_kern_tt.h
@@ -0,0 +1,41 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MODE_KERN_H__
7#define __TT_MODE_KERN_H__
8
9#include "linux/sched.h"
10#include "asm/page.h"
11#include "asm/ptrace.h"
12#include "asm/uaccess.h"
13
14extern void switch_to_tt(void *prev, void *next);
15extern void flush_thread_tt(void);
16extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
17 unsigned long esp);
18extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
19 unsigned long stack_top, struct task_struct *p,
20 struct pt_regs *regs);
21extern void release_thread_tt(struct task_struct *task);
22extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
23extern void init_idle_tt(void);
24extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
25extern void flush_tlb_kernel_vm_tt(void);
26extern void __flush_tlb_one_tt(unsigned long addr);
27extern void flush_tlb_range_tt(struct vm_area_struct *vma,
28 unsigned long start, unsigned long end);
29extern void flush_tlb_mm_tt(struct mm_struct *mm);
30extern void force_flush_all_tt(void);
31extern long execute_syscall_tt(void *r);
32extern void before_mem_tt(unsigned long brk_start);
33extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
34 unsigned long *task_size_out);
35extern int start_uml_tt(void);
36extern int external_pid_tt(struct task_struct *task);
37extern int thread_pid_tt(struct task_struct *task);
38
39#define kmem_end_tt (host_task_size - ABOVE_KMEM)
40
41#endif
diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/include/tt/tt.h
index c667b67af4..8085219801 100644
--- a/arch/um/kernel/tt/include/tt.h
+++ b/arch/um/include/tt/tt.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -34,13 +34,3 @@ extern long execute_syscall_tt(void *r);
34 34
35#endif 35#endif
36 36
37/*
38 * Overrides for Emacs so that we follow Linus's tabbing style.
39 * Emacs will notice this stuff at the end of the file and automatically
40 * adjust the settings for this buffer only. This must remain at the end
41 * of the file.
42 * ---------------------------------------------------------------------------
43 * Local variables:
44 * c-file-style: "linux"
45 * End:
46 */
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h
index dc2ebfa8c5..b19645f32f 100644
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ b/arch/um/include/tt/uaccess-tt.h
@@ -19,19 +19,13 @@
19extern unsigned long end_vm; 19extern unsigned long end_vm;
20extern unsigned long uml_physmem; 20extern unsigned long uml_physmem;
21 21
22#define under_task_size(addr, size) \
23 (((unsigned long) (addr) < TASK_SIZE) && \
24 (((unsigned long) (addr) + (size)) < TASK_SIZE))
25
26#define is_stack(addr, size) \ 22#define is_stack(addr, size) \
27 (((unsigned long) (addr) < STACK_TOP) && \ 23 (((unsigned long) (addr) < STACK_TOP) && \
28 ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ 24 ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \
29 (((unsigned long) (addr) + (size)) <= STACK_TOP)) 25 (((unsigned long) (addr) + (size)) <= STACK_TOP))
30 26
31#define access_ok_tt(type, addr, size) \ 27#define access_ok_tt(type, addr, size) \
32 ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ 28 (is_stack(addr, size))
33 (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
34 (under_task_size(addr, size) || is_stack(addr, size))))
35 29
36extern unsigned long get_fault_addr(void); 30extern unsigned long get_fault_addr(void);
37 31
@@ -52,14 +46,3 @@ extern int clear_user_tt(void __user *mem, int len);
52extern int strnlen_user_tt(const void __user *str, int len); 46extern int strnlen_user_tt(const void __user *str, int len);
53 47
54#endif 48#endif
55
56/*
57 * Overrides for Emacs so that we follow Linus's tabbing style.
58 * Emacs will notice this stuff at the end of the file and automatically
59 * adjust the settings for this buffer only. This must remain at the end
60 * of the file.
61 * ---------------------------------------------------------------------------
62 * Local variables:
63 * c-file-style: "linux"
64 * End:
65 */
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index 84c0868cd5..4567f1eeb4 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -17,8 +17,27 @@
17#include "uaccess-skas.h" 17#include "uaccess-skas.h"
18#endif 18#endif
19 19
20#include "asm/fixmap.h"
21
22#define __under_task_size(addr, size) \
23 (((unsigned long) (addr) < TASK_SIZE) && \
24 (((unsigned long) (addr) + (size)) < TASK_SIZE))
25
26#define __access_ok_vsyscall(type, addr, size) \
27 ((type == VERIFY_READ) && \
28 ((unsigned long) (addr) >= FIXADDR_USER_START) && \
29 ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
30 ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
31
32#define __addr_range_nowrap(addr, size) \
33 ((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
34
20#define access_ok(type, addr, size) \ 35#define access_ok(type, addr, size) \
21 CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) 36 (__addr_range_nowrap(addr, size) && \
37 (__under_task_size(addr, size) || \
38 __access_ok_vsyscall(type, addr, size) || \
39 segment_eq(get_fs(), KERNEL_DS) || \
40 CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size)))
22 41
23static inline int copy_from_user(void *to, const void __user *from, int n) 42static inline int copy_from_user(void *to, const void __user *from, int n)
24{ 43{
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 0f865ef469..91b0ac4ad8 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -18,6 +18,7 @@ extern int open_gdb_chan(void);
18extern unsigned long strlcpy(char *, const char *, unsigned long); 18extern unsigned long strlcpy(char *, const char *, unsigned long);
19extern unsigned long strlcat(char *, const char *, unsigned long); 19extern unsigned long strlcat(char *, const char *, unsigned long);
20extern void *um_vmalloc(int size); 20extern void *um_vmalloc(int size);
21extern void *um_vmalloc_atomic(int size);
21extern void vfree(void *ptr); 22extern void vfree(void *ptr);
22 23
23#endif 24#endif
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index bb505e01d9..a6f1f176cf 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -23,12 +23,7 @@ struct cpu_task {
23 23
24extern struct cpu_task cpu_tasks[]; 24extern struct cpu_task cpu_tasks[];
25 25
26struct signal_info { 26extern void (*sig_info[])(int, union uml_pt_regs *);
27 void (*handler)(int, union uml_pt_regs *);
28 int is_irq;
29};
30
31extern struct signal_info sig_info[];
32 27
33extern unsigned long low_physmem; 28extern unsigned long low_physmem;
34extern unsigned long high_physmem; 29extern unsigned long high_physmem;
@@ -49,10 +44,6 @@ extern unsigned long brk_start;
49extern int pty_output_sigio; 44extern int pty_output_sigio;
50extern int pty_close_sigio; 45extern int pty_close_sigio;
51 46
52extern void stop(void);
53extern void stack_protections(unsigned long address);
54extern void task_protections(unsigned long address);
55extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
56extern void *add_signal_handler(int sig, void (*handler)(int)); 47extern void *add_signal_handler(int sig, void (*handler)(int));
57extern int linux_main(int argc, char **argv); 48extern int linux_main(int argc, char **argv);
58extern void set_cmdline(char *cmd); 49extern void set_cmdline(char *cmd);
@@ -60,12 +51,8 @@ extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
60extern int get_pty(void); 51extern int get_pty(void);
61extern void *um_kmalloc(int size); 52extern void *um_kmalloc(int size);
62extern int switcheroo(int fd, int prot, void *from, void *to, int size); 53extern int switcheroo(int fd, int prot, void *from, void *to, int size);
63extern void setup_machinename(char *machine_out);
64extern void setup_hostinfo(void);
65extern void do_exec(int old_pid, int new_pid); 54extern void do_exec(int old_pid, int new_pid);
66extern void tracer_panic(char *msg, ...); 55extern void tracer_panic(char *msg, ...);
67extern char *get_umid(int only_if_set);
68extern void do_longjmp(void *p, int val);
69extern int detach(int pid, int sig); 56extern int detach(int pid, int sig);
70extern int attach(int pid); 57extern int attach(int pid);
71extern void kill_child_dead(int pid); 58extern void kill_child_dead(int pid);
@@ -77,18 +64,6 @@ extern int cpu_feature(char *what, char *buf, int len);
77extern int arch_handle_signal(int sig, union uml_pt_regs *regs); 64extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
78extern int arch_fixup(unsigned long address, void *sc_ptr); 65extern int arch_fixup(unsigned long address, void *sc_ptr);
79extern void arch_init_thread(void); 66extern void arch_init_thread(void);
80extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
81extern int raw(int fd); 67extern int raw(int fd);
82 68
83#endif 69#endif
84
85/*
86 * Overrides for Emacs so that we follow Linus's tabbing style.
87 * Emacs will notice this stuff at the end of the file and automatically
88 * adjust the settings for this buffer only. This must remain at the end
89 * of the file.
90 * ---------------------------------------------------------------------------
91 * Local variables:
92 * c-file-style: "linux"
93 * End:
94 */
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 3de9d21e36..693018ba80 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -9,9 +9,8 @@ clean-files :=
9obj-y = config.o exec_kern.o exitcode.o \ 9obj-y = config.o exec_kern.o exitcode.o \
10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ 10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ 11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
12 signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ 12 signal_kern.o smp.o syscall_kern.o sysrq.o \
13 time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ 13 time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
14 umid.o user_util.o
15 14
16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 15obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
17obj-$(CONFIG_GPROF) += gprof_syms.o 16obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -24,7 +23,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
24 23
25user-objs-$(CONFIG_TTY_LOG) += tty_log.o 24user-objs-$(CONFIG_TTY_LOG) += tty_log.o
26 25
27USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o 26USER_OBJS := $(user-objs-y) config.o tty_log.o
28 27
29include arch/um/scripts/Makefile.rules 28include arch/um/scripts/Makefile.rules
30 29
diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c
index c13a64a288..91ea538e16 100644
--- a/arch/um/kernel/asm-offsets.c
+++ b/arch/um/kernel/asm-offsets.c
@@ -1 +1 @@
/* Dummy file to make kbuild happy - unused! */ #include "sysdep/kernel-offsets.h"
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index efd222ffe2..569fe8b9b0 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -17,7 +17,6 @@
17#include "irq_user.h" 17#include "irq_user.h"
18#include "tlb.h" 18#include "tlb.h"
19#include "os.h" 19#include "os.h"
20#include "time_user.h"
21#include "choose-mode.h" 20#include "choose-mode.h"
22#include "mode_kern.h" 21#include "mode_kern.h"
23 22
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index c3ccaf24f3..0e32f5f4a8 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -15,7 +15,6 @@
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user.h" 16#include "user.h"
17#include "process.h" 17#include "process.h"
18#include "signal_user.h"
19#include "sigio.h" 18#include "sigio.h"
20#include "irq_user.h" 19#include "irq_user.h"
21#include "os.h" 20#include "os.h"
@@ -29,7 +28,6 @@ struct irq_fd {
29 int pid; 28 int pid;
30 int events; 29 int events;
31 int current_events; 30 int current_events;
32 int freed;
33}; 31};
34 32
35static struct irq_fd *active_fds = NULL; 33static struct irq_fd *active_fds = NULL;
@@ -41,9 +39,11 @@ static int pollfds_size = 0;
41 39
42extern int io_count, intr_count; 40extern int io_count, intr_count;
43 41
42extern void free_irqs(void);
43
44void sigio_handler(int sig, union uml_pt_regs *regs) 44void sigio_handler(int sig, union uml_pt_regs *regs)
45{ 45{
46 struct irq_fd *irq_fd, *next; 46 struct irq_fd *irq_fd;
47 int i, n; 47 int i, n;
48 48
49 if(smp_sigio_handler()) return; 49 if(smp_sigio_handler()) return;
@@ -66,29 +66,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
66 irq_fd = irq_fd->next; 66 irq_fd = irq_fd->next;
67 } 67 }
68 68
69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ 69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
70 next = irq_fd->next;
71 if(irq_fd->current_events != 0){ 70 if(irq_fd->current_events != 0){
72 irq_fd->current_events = 0; 71 irq_fd->current_events = 0;
73 do_IRQ(irq_fd->irq, regs); 72 do_IRQ(irq_fd->irq, regs);
74
75 /* This is here because the next irq may be
76 * freed in the handler. If a console goes
77 * away, both the read and write irqs will be
78 * freed. After do_IRQ, ->next will point to
79 * a good IRQ.
80 * Irqs can't be freed inside their handlers,
81 * so the next best thing is to have them
82 * marked as needing freeing, so that they
83 * can be freed here.
84 */
85 next = irq_fd->next;
86 if(irq_fd->freed){
87 free_irq(irq_fd->irq, irq_fd->id);
88 }
89 } 73 }
90 } 74 }
91 } 75 }
76
77 free_irqs();
92} 78}
93 79
94int activate_ipi(int fd, int pid) 80int activate_ipi(int fd, int pid)
@@ -136,8 +122,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
136 .irq = irq, 122 .irq = irq,
137 .pid = pid, 123 .pid = pid,
138 .events = events, 124 .events = events,
139 .current_events = 0, 125 .current_events = 0 } );
140 .freed = 0 } );
141 126
142 /* Critical section - locked by a spinlock because this stuff can 127 /* Critical section - locked by a spinlock because this stuff can
143 * be changed from interrupt handlers. The stuff above is done 128 * be changed from interrupt handlers. The stuff above is done
@@ -313,26 +298,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
313 return(irq); 298 return(irq);
314} 299}
315 300
316void free_irq_later(int irq, void *dev_id)
317{
318 struct irq_fd *irq_fd;
319 unsigned long flags;
320
321 flags = irq_lock();
322 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
323 if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
324 break;
325 }
326 if(irq_fd == NULL){
327 printk("free_irq_later found no irq, irq = %d, "
328 "dev_id = 0x%p\n", irq, dev_id);
329 goto out;
330 }
331 irq_fd->freed = 1;
332 out:
333 irq_unlock(flags);
334}
335
336void reactivate_fd(int fd, int irqnum) 301void reactivate_fd(int fd, int irqnum)
337{ 302{
338 struct irq_fd *irq; 303 struct irq_fd *irq;
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 34b54a3e21..3113cab867 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -36,11 +36,9 @@
36#include "kern_util.h" 36#include "kern_util.h"
37#include "kern.h" 37#include "kern.h"
38#include "signal_kern.h" 38#include "signal_kern.h"
39#include "signal_user.h"
40#include "init.h" 39#include "init.h"
41#include "irq_user.h" 40#include "irq_user.h"
42#include "mem_user.h" 41#include "mem_user.h"
43#include "time_user.h"
44#include "tlb.h" 42#include "tlb.h"
45#include "frame_kern.h" 43#include "frame_kern.h"
46#include "sigcontext.h" 44#include "sigcontext.h"
@@ -108,7 +106,7 @@ void set_current(void *t)
108{ 106{
109 struct task_struct *task = t; 107 struct task_struct *task = t;
110 108
111 cpu_tasks[task->thread_info->cpu] = ((struct cpu_task) 109 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
112 { external_pid(task), task }); 110 { external_pid(task), task });
113} 111}
114 112
@@ -289,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt);
289 287
290void *um_kmalloc(int size) 288void *um_kmalloc(int size)
291{ 289{
292 return(kmalloc(size, GFP_KERNEL)); 290 return kmalloc(size, GFP_KERNEL);
293} 291}
294 292
295void *um_kmalloc_atomic(int size) 293void *um_kmalloc_atomic(int size)
296{ 294{
297 return(kmalloc(size, GFP_ATOMIC)); 295 return kmalloc(size, GFP_ATOMIC);
298} 296}
299 297
300void *um_vmalloc(int size) 298void *um_vmalloc(int size)
301{ 299{
302 return(vmalloc(size)); 300 return vmalloc(size);
301}
302
303void *um_vmalloc_atomic(int size)
304{
305 return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
306}
307
308int __cant_sleep(void) {
309 return in_atomic() || irqs_disabled() || in_interrupt();
310 /* Is in_interrupt() really needed? */
303} 311}
304 312
305unsigned long get_fault_addr(void) 313unsigned long get_fault_addr(void)
@@ -324,10 +332,6 @@ int user_context(unsigned long sp)
324 return(stack != (unsigned long) current_thread); 332 return(stack != (unsigned long) current_thread);
325} 333}
326 334
327extern void remove_umid_dir(void);
328
329__uml_exitcall(remove_umid_dir);
330
331extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; 335extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
332 336
333void do_uml_exitcalls(void) 337void do_uml_exitcalls(void)
@@ -375,11 +379,6 @@ int smp_sigio_handler(void)
375 return(0); 379 return(0);
376} 380}
377 381
378int um_in_interrupt(void)
379{
380 return(in_interrupt());
381}
382
383int cpu(void) 382int cpu(void)
384{ 383{
385 return(current_thread->cpu); 384 return(current_thread->cpu);
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index a637e885c5..6f1a3a2881 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -12,6 +12,8 @@
12#include "mode.h" 12#include "mode.h"
13#include "choose-mode.h" 13#include "choose-mode.h"
14 14
15void (*pm_power_off)(void);
16
15#ifdef CONFIG_SMP 17#ifdef CONFIG_SMP
16static void kill_idlers(int me) 18static void kill_idlers(int me)
17{ 19{
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 48b1f644b9..f7b18e157d 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -216,6 +216,8 @@ static int write_sigio_thread(void *unused)
216 "err = %d\n", -n); 216 "err = %d\n", -n);
217 } 217 }
218 } 218 }
219
220 return 0;
219} 221}
220 222
221static int need_poll(int n) 223static int need_poll(int n)
@@ -335,70 +337,103 @@ int ignore_sigio_fd(int fd)
335 return(err); 337 return(err);
336} 338}
337 339
338static int setup_initial_poll(int fd) 340static struct pollfd* setup_initial_poll(int fd)
339{ 341{
340 struct pollfd *p; 342 struct pollfd *p;
341 343
342 p = um_kmalloc_atomic(sizeof(struct pollfd)); 344 p = um_kmalloc(sizeof(struct pollfd));
343 if(p == NULL){ 345 if (p == NULL) {
344 printk("setup_initial_poll : failed to allocate poll\n"); 346 printk("setup_initial_poll : failed to allocate poll\n");
345 return(-1); 347 return NULL;
346 } 348 }
347 *p = ((struct pollfd) { .fd = fd, 349 *p = ((struct pollfd) { .fd = fd,
348 .events = POLLIN, 350 .events = POLLIN,
349 .revents = 0 }); 351 .revents = 0 });
350 current_poll = ((struct pollfds) { .poll = p, 352 return p;
351 .used = 1,
352 .size = 1 });
353 return(0);
354} 353}
355 354
356void write_sigio_workaround(void) 355void write_sigio_workaround(void)
357{ 356{
358 unsigned long stack; 357 unsigned long stack;
358 struct pollfd *p;
359 int err; 359 int err;
360 int l_write_sigio_fds[2];
361 int l_sigio_private[2];
362 int l_write_sigio_pid;
360 363
364 /* We call this *tons* of times - and most ones we must just fail. */
361 sigio_lock(); 365 sigio_lock();
362 if(write_sigio_pid != -1) 366 l_write_sigio_pid = write_sigio_pid;
363 goto out; 367 sigio_unlock();
368
369 if (l_write_sigio_pid != -1)
370 return;
364 371
365 err = os_pipe(write_sigio_fds, 1, 1); 372 err = os_pipe(l_write_sigio_fds, 1, 1);
366 if(err < 0){ 373 if(err < 0){
367 printk("write_sigio_workaround - os_pipe 1 failed, " 374 printk("write_sigio_workaround - os_pipe 1 failed, "
368 "err = %d\n", -err); 375 "err = %d\n", -err);
369 goto out; 376 return;
370 } 377 }
371 err = os_pipe(sigio_private, 1, 1); 378 err = os_pipe(l_sigio_private, 1, 1);
372 if(err < 0){ 379 if(err < 0){
373 printk("write_sigio_workaround - os_pipe 2 failed, " 380 printk("write_sigio_workaround - os_pipe 1 failed, "
374 "err = %d\n", -err); 381 "err = %d\n", -err);
375 goto out_close1; 382 goto out_close1;
376 } 383 }
377 if(setup_initial_poll(sigio_private[1])) 384
385 p = setup_initial_poll(l_sigio_private[1]);
386 if(!p)
378 goto out_close2; 387 goto out_close2;
379 388
380 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 389 sigio_lock();
390
391 /* Did we race? Don't try to optimize this, please, it's not so likely
392 * to happen, and no more than once at the boot. */
393 if(write_sigio_pid != -1)
394 goto out_unlock;
395
396 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
381 CLONE_FILES | CLONE_VM, &stack, 0); 397 CLONE_FILES | CLONE_VM, &stack, 0);
382 398
383 if(write_sigio_pid < 0) goto out_close2; 399 if (write_sigio_pid < 0)
400 goto out_clear;
384 401
385 if(write_sigio_irq(write_sigio_fds[0])) 402 if (write_sigio_irq(l_write_sigio_fds[0]))
386 goto out_kill; 403 goto out_kill;
387 404
388 out: 405 /* Success, finally. */
406 memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
407 memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
408
409 current_poll = ((struct pollfds) { .poll = p,
410 .used = 1,
411 .size = 1 });
412
389 sigio_unlock(); 413 sigio_unlock();
390 return; 414 return;
391 415
392 out_kill: 416 out_kill:
393 os_kill_process(write_sigio_pid, 1); 417 l_write_sigio_pid = write_sigio_pid;
418 write_sigio_pid = -1;
419 sigio_unlock();
420 /* Going to call waitpid, avoid holding the lock. */
421 os_kill_process(l_write_sigio_pid, 1);
422 goto out_free;
423
424 out_clear:
394 write_sigio_pid = -1; 425 write_sigio_pid = -1;
426 out_unlock:
427 sigio_unlock();
428 out_free:
429 kfree(p);
395 out_close2: 430 out_close2:
396 os_close_file(sigio_private[0]); 431 os_close_file(l_sigio_private[0]);
397 os_close_file(sigio_private[1]); 432 os_close_file(l_sigio_private[1]);
398 out_close1: 433 out_close1:
399 os_close_file(write_sigio_fds[0]); 434 os_close_file(l_write_sigio_fds[0]);
400 os_close_file(write_sigio_fds[1]); 435 os_close_file(l_write_sigio_fds[1]);
401 sigio_unlock(); 436 return;
402} 437}
403 438
404int read_sigio_fd(int fd) 439int read_sigio_fd(int fd)
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 03618bd13d..da17b7541e 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -22,7 +22,6 @@
22#include "asm/ucontext.h" 22#include "asm/ucontext.h"
23#include "kern_util.h" 23#include "kern_util.h"
24#include "signal_kern.h" 24#include "signal_kern.h"
25#include "signal_user.h"
26#include "kern.h" 25#include "kern.h"
27#include "frame_kern.h" 26#include "frame_kern.h"
28#include "sigcontext.h" 27#include "sigcontext.h"
@@ -100,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
100 return err; 99 return err;
101} 100}
102 101
103static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) 102static int kern_do_signal(struct pt_regs *regs)
104{ 103{
105 struct k_sigaction ka_copy; 104 struct k_sigaction ka_copy;
106 siginfo_t info; 105 siginfo_t info;
106 sigset_t *oldset;
107 int sig, handled_sig = 0; 107 int sig, handled_sig = 0;
108 108
109 if (test_thread_flag(TIF_RESTORE_SIGMASK))
110 oldset = &current->saved_sigmask;
111 else
112 oldset = &current->blocked;
113
109 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ 114 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
110 handled_sig = 1; 115 handled_sig = 1;
111 /* Whee! Actually deliver the signal. */ 116 /* Whee! Actually deliver the signal. */
112 if(!handle_signal(regs, sig, &ka_copy, &info, oldset)) 117 if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
118 /* a signal was successfully delivered; the saved
119 * sigmask will have been stored in the signal frame,
120 * and will be restored by sigreturn, so we can simply
121 * clear the TIF_RESTORE_SIGMASK flag */
122 if (test_thread_flag(TIF_RESTORE_SIGMASK))
123 clear_thread_flag(TIF_RESTORE_SIGMASK);
113 break; 124 break;
125 }
114 } 126 }
115 127
116 /* Did we come from a system call? */ 128 /* Did we come from a system call? */
117 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ 129 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
118 /* Restart the system call - no handlers present */ 130 /* Restart the system call - no handlers present */
119 if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || 131 switch(PT_REGS_SYSCALL_RET(regs)){
120 PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || 132 case -ERESTARTNOHAND:
121 PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ 133 case -ERESTARTSYS:
134 case -ERESTARTNOINTR:
122 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 135 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
123 PT_REGS_RESTART_SYSCALL(regs); 136 PT_REGS_RESTART_SYSCALL(regs);
124 } 137 break;
125 else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){ 138 case -ERESTART_RESTARTBLOCK:
126 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; 139 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
127 PT_REGS_RESTART_SYSCALL(regs); 140 PT_REGS_RESTART_SYSCALL(regs);
141 break;
128 } 142 }
129 } 143 }
130 144
@@ -138,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
138 if(current->ptrace & PT_DTRACE) 152 if(current->ptrace & PT_DTRACE)
139 current->thread.singlestep_syscall = 153 current->thread.singlestep_syscall =
140 is_syscall(PT_REGS_IP(&current->thread.regs)); 154 is_syscall(PT_REGS_IP(&current->thread.regs));
155
156 /* if there's no signal to deliver, we just put the saved sigmask
157 * back */
158 if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
159 clear_thread_flag(TIF_RESTORE_SIGMASK);
160 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
161 }
141 return(handled_sig); 162 return(handled_sig);
142} 163}
143 164
144int do_signal(void) 165int do_signal(void)
145{ 166{
146 return(kern_do_signal(&current->thread.regs, &current->blocked)); 167 return(kern_do_signal(&current->thread.regs));
147} 168}
148 169
149/* 170/*
@@ -151,63 +172,20 @@ int do_signal(void)
151 */ 172 */
152long sys_sigsuspend(int history0, int history1, old_sigset_t mask) 173long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
153{ 174{
154 sigset_t saveset;
155
156 mask &= _BLOCKABLE; 175 mask &= _BLOCKABLE;
157 spin_lock_irq(&current->sighand->siglock); 176 spin_lock_irq(&current->sighand->siglock);
158 saveset = current->blocked; 177 current->saved_sigmask = current->blocked;
159 siginitset(&current->blocked, mask); 178 siginitset(&current->blocked, mask);
160 recalc_sigpending(); 179 recalc_sigpending();
161 spin_unlock_irq(&current->sighand->siglock); 180 spin_unlock_irq(&current->sighand->siglock);
162 181
163 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR; 182 current->state = TASK_INTERRUPTIBLE;
164 while (1) { 183 schedule();
165 current->state = TASK_INTERRUPTIBLE; 184 set_thread_flag(TIF_RESTORE_SIGMASK);
166 schedule(); 185 return -ERESTARTNOHAND;
167 if(kern_do_signal(&current->thread.regs, &saveset))
168 return(-EINTR);
169 }
170}
171
172long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
173{
174 sigset_t saveset, newset;
175
176 /* XXX: Don't preclude handling different sized sigset_t's. */
177 if (sigsetsize != sizeof(sigset_t))
178 return -EINVAL;
179
180 if (copy_from_user(&newset, unewset, sizeof(newset)))
181 return -EFAULT;
182 sigdelsetmask(&newset, ~_BLOCKABLE);
183
184 spin_lock_irq(&current->sighand->siglock);
185 saveset = current->blocked;
186 current->blocked = newset;
187 recalc_sigpending();
188 spin_unlock_irq(&current->sighand->siglock);
189
190 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
191 while (1) {
192 current->state = TASK_INTERRUPTIBLE;
193 schedule();
194 if (kern_do_signal(&current->thread.regs, &saveset))
195 return(-EINTR);
196 }
197} 186}
198 187
199long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) 188long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
200{ 189{
201 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs))); 190 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
202} 191}
203
204/*
205 * Overrides for Emacs so that we follow Linus's tabbing style.
206 * Emacs will notice this stuff at the end of the file and automatically
207 * adjust the settings for this buffer only. This must remain at the end
208 * of the file.
209 * ---------------------------------------------------------------------------
210 * Local variables:
211 * c-file-style: "linux"
212 * End:
213 */
diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c
deleted file mode 100644
index 62f457835f..0000000000
--- a/arch/um/kernel/signal_user.c
+++ /dev/null
@@ -1,157 +0,0 @@
1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <signal.h>
10#include <errno.h>
11#include <stdarg.h>
12#include <string.h>
13#include <sys/mman.h>
14#include "user_util.h"
15#include "kern_util.h"
16#include "user.h"
17#include "signal_user.h"
18#include "signal_kern.h"
19#include "sysdep/sigcontext.h"
20#include "sigcontext.h"
21
22void set_sigstack(void *sig_stack, int size)
23{
24 stack_t stack = ((stack_t) { .ss_flags = 0,
25 .ss_sp = (__ptr_t) sig_stack,
26 .ss_size = size - sizeof(void *) });
27
28 if(sigaltstack(&stack, NULL) != 0)
29 panic("enabling signal stack failed, errno = %d\n", errno);
30}
31
32void set_handler(int sig, void (*handler)(int), int flags, ...)
33{
34 struct sigaction action;
35 va_list ap;
36 int mask;
37
38 va_start(ap, flags);
39 action.sa_handler = handler;
40 sigemptyset(&action.sa_mask);
41 while((mask = va_arg(ap, int)) != -1){
42 sigaddset(&action.sa_mask, mask);
43 }
44 va_end(ap);
45 action.sa_flags = flags;
46 action.sa_restorer = NULL;
47 if(sigaction(sig, &action, NULL) < 0)
48 panic("sigaction failed");
49}
50
51int change_sig(int signal, int on)
52{
53 sigset_t sigset, old;
54
55 sigemptyset(&sigset);
56 sigaddset(&sigset, signal);
57 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
58 return(!sigismember(&old, signal));
59}
60
61/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
62 * disable profiling; it's safe because the profiling code does not interact
63 * with the kernel code at all.*/
64
65static void change_signals(int type)
66{
67 sigset_t mask;
68
69 sigemptyset(&mask);
70 sigaddset(&mask, SIGVTALRM);
71 sigaddset(&mask, SIGALRM);
72 sigaddset(&mask, SIGIO);
73 if(sigprocmask(type, &mask, NULL) < 0)
74 panic("Failed to change signal mask - errno = %d", errno);
75}
76
77void block_signals(void)
78{
79 change_signals(SIG_BLOCK);
80}
81
82void unblock_signals(void)
83{
84 change_signals(SIG_UNBLOCK);
85}
86
87/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
88 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
89 * be able to profile all of UML, not just the non-critical sections. If
90 * profiling is not thread-safe, then that is not my problem. We can disable
91 * profiling when SMP is enabled in that case.
92 */
93#define SIGIO_BIT 0
94#define SIGVTALRM_BIT 1
95
96static int enable_mask(sigset_t *mask)
97{
98 int sigs;
99
100 sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
101 sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
102 sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
103 return(sigs);
104}
105
106int get_signals(void)
107{
108 sigset_t mask;
109
110 if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
111 panic("Failed to get signal mask");
112 return(enable_mask(&mask));
113}
114
115int set_signals(int enable)
116{
117 sigset_t mask;
118 int ret;
119
120 sigemptyset(&mask);
121 if(enable & (1 << SIGIO_BIT))
122 sigaddset(&mask, SIGIO);
123 if(enable & (1 << SIGVTALRM_BIT)){
124 sigaddset(&mask, SIGVTALRM);
125 sigaddset(&mask, SIGALRM);
126 }
127
128 /* This is safe - sigprocmask is guaranteed to copy locally the
129 * value of new_set, do his work and then, at the end, write to
130 * old_set.
131 */
132 if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
133 panic("Failed to enable signals");
134 ret = enable_mask(&mask);
135 sigemptyset(&mask);
136 if((enable & (1 << SIGIO_BIT)) == 0)
137 sigaddset(&mask, SIGIO);
138 if((enable & (1 << SIGVTALRM_BIT)) == 0){
139 sigaddset(&mask, SIGVTALRM);
140 sigaddset(&mask, SIGALRM);
141 }
142 if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
143 panic("Failed to block signals");
144
145 return(ret);
146}
147
148/*
149 * Overrides for Emacs so that we follow Linus's tabbing style.
150 * Emacs will notice this stuff at the end of the file and automatically
151 * adjust the settings for this buffer only. This must remain at the end
152 * of the file.
153 * ---------------------------------------------------------------------------
154 * Local variables:
155 * c-file-style: "linux"
156 * End:
157 */
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 8de471b59c..57181a920d 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -1,12 +1,12 @@
1# 1#
2# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.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
6obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ 6obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
7 syscall.o tlb.o trap_user.o uaccess.o 7 syscall.o tlb.o uaccess.o
8 8
9USER_OBJS := process.o clone.o 9USER_OBJS := clone.o
10 10
11include arch/um/scripts/Makefile.rules 11include arch/um/scripts/Makefile.rules
12 12
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 4dc55f10cd..47b812b3bc 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -9,18 +9,23 @@
9#include "stub-data.h" 9#include "stub-data.h"
10#include "uml-config.h" 10#include "uml-config.h"
11#include "sysdep/stub.h" 11#include "sysdep/stub.h"
12#include "kern_constants.h"
12 13
13/* This is in a separate file because it needs to be compiled with any 14/* 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 * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
16 *
17 * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize
18 * on some systems.
15 */ 19 */
20
16void __attribute__ ((__section__ (".__syscall_stub"))) 21void __attribute__ ((__section__ (".__syscall_stub")))
17stub_clone_handler(void) 22stub_clone_handler(void)
18{ 23{
24 struct stub_data *data = (struct stub_data *) UML_CONFIG_STUB_DATA;
19 long err; 25 long err;
20 struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA;
21 26
22 err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, 27 err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
23 UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 - 28 UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 -
24 sizeof(void *)); 29 sizeof(void *));
25 if(err != 0) 30 if(err != 0)
26 goto out; 31 goto out;
@@ -29,16 +34,21 @@ stub_clone_handler(void)
29 if(err) 34 if(err)
30 goto out; 35 goto out;
31 36
32 err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, 37 err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
33 (long) &from->timer, 0); 38 (long) &data->timer, 0);
34 if(err) 39 if(err)
35 goto out; 40 goto out;
36 41
37 err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE, 42 remap_stack(data->fd, data->offset);
38 PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, 43 goto done;
39 from->fd, from->offset); 44
40 out: 45 out:
41 /* save current result. Parent: pid; child: retcode of mmap */ 46 /* save current result.
42 from->err = err; 47 * Parent: pid;
48 * child: retcode of mmap already saved and it jumps around this
49 * assignment
50 */
51 data->err = err;
52 done:
43 trap_myself(); 53 trap_myself();
44} 54}
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
deleted file mode 100644
index 44110c521e..0000000000
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_MMU_H
7#define __SKAS_MMU_H
8
9#include "linux/config.h"
10#include "mm_id.h"
11#include "asm/ldt.h"
12
13struct mmu_context_skas {
14 struct mm_id id;
15 unsigned long last_page_table;
16#ifdef CONFIG_3_LEVEL_PGTABLES
17 unsigned long last_pmd;
18#endif
19 uml_ldt_t ldt;
20};
21
22extern void switch_mm_skas(struct mm_id * mm_idp);
23
24#endif
25
26/*
27 * Overrides for Emacs so that we follow Linus's tabbing style.
28 * Emacs will notice this stuff at the end of the file and automatically
29 * adjust the settings for this buffer only. This must remain at the end
30 * of the file.
31 * ---------------------------------------------------------------------------
32 * Local variables:
33 * c-file-style: "linux"
34 * End:
35 */
diff --git a/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h
deleted file mode 100644
index bcd26a6a38..0000000000
--- a/arch/um/kernel/skas/include/mode-skas.h
+++ /dev/null
@@ -1,33 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MODE_SKAS_H__
7#define __MODE_SKAS_H__
8
9#include <sysdep/ptrace.h>
10
11extern unsigned long exec_regs[];
12extern unsigned long exec_fp_regs[];
13extern unsigned long exec_fpx_regs[];
14extern int have_fpx_regs;
15
16extern void sig_handler_common_skas(int sig, void *sc_ptr);
17extern void halt_skas(void);
18extern void reboot_skas(void);
19extern void kill_off_processes_skas(void);
20extern int is_skas_winch(int pid, int fd, void *data);
21
22#endif
23
24/*
25 * Overrides for Emacs so that we follow Linus's tabbing style.
26 * Emacs will notice this stuff at the end of the file and automatically
27 * adjust the settings for this buffer only. This must remain at the end
28 * of the file.
29 * ---------------------------------------------------------------------------
30 * Local variables:
31 * c-file-style: "linux"
32 * End:
33 */
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
deleted file mode 100644
index daa2f85b68..0000000000
--- a/arch/um/kernel/skas/include/skas.h
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_H
7#define __SKAS_H
8
9#include "mm_id.h"
10#include "sysdep/ptrace.h"
11
12extern int userspace_pid[];
13extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
14extern int skas_needs_stub;
15
16extern void switch_threads(void *me, void *next);
17extern void thread_wait(void *sw, void *fb);
18extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
19 void (*handler)(int));
20extern int start_idle_thread(void *stack, void *switch_buf_ptr,
21 void **fork_buf_ptr);
22extern int user_thread(unsigned long stack, int flags);
23extern void userspace(union uml_pt_regs *regs);
24extern void new_thread_proc(void *stack, void (*handler)(int sig));
25extern void remove_sigstack(void);
26extern void new_thread_handler(int sig);
27extern void handle_syscall(union uml_pt_regs *regs);
28extern int map(struct mm_id * mm_idp, unsigned long virt,
29 unsigned long len, int r, int w, int x, int phys_fd,
30 unsigned long long offset, int done, void **data);
31extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
32 int done, void **data);
33extern int protect(struct mm_id * mm_idp, unsigned long addr,
34 unsigned long len, int r, int w, int x, int done,
35 void **data);
36extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
37extern int new_mm(int from, unsigned long stack);
38extern int start_userspace(unsigned long stub_stack);
39extern int copy_context_skas0(unsigned long stack, int pid);
40extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
41extern long execute_syscall_skas(void *r);
42extern unsigned long current_stub_stack(void);
43extern long run_syscall_stub(struct mm_id * mm_idp,
44 int syscall, unsigned long *args, long expected,
45 void **addr, int done);
46extern long syscall_stub_data(struct mm_id * mm_idp,
47 unsigned long *data, int data_count,
48 void **addr, void **stub_addr);
49
50#endif
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h
deleted file mode 100644
index 7da0c2def0..0000000000
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ /dev/null
@@ -1,39 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_UACCESS_H
7#define __SKAS_UACCESS_H
8
9#include "asm/errno.h"
10#include "asm/fixmap.h"
11
12#define access_ok_skas(type, addr, size) \
13 ((segment_eq(get_fs(), KERNEL_DS)) || \
14 (((unsigned long) (addr) < TASK_SIZE) && \
15 ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \
16 ((type == VERIFY_READ ) && \
17 ((unsigned long) (addr) >= FIXADDR_USER_START) && \
18 ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
19 ((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
20
21extern int copy_from_user_skas(void *to, const void __user *from, int n);
22extern int copy_to_user_skas(void __user *to, const void *from, int n);
23extern int strncpy_from_user_skas(char *dst, const char __user *src, int count);
24extern int __clear_user_skas(void __user *mem, int len);
25extern int clear_user_skas(void __user *mem, int len);
26extern int strnlen_user_skas(const void __user *str, int len);
27
28#endif
29
30/*
31 * Overrides for Emacs so that we follow Linus's tabbing style.
32 * Emacs will notice this stuff at the end of the file and automatically
33 * adjust the settings for this buffer only. This must remain at the end
34 * of the file.
35 * ---------------------------------------------------------------------------
36 * Local variables:
37 * c-file-style: "linux"
38 * End:
39 */
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 677871f1b3..c5c9885a82 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -78,7 +78,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
78 struct mmu_context_skas *from_mm = NULL; 78 struct mmu_context_skas *from_mm = NULL;
79 struct mmu_context_skas *to_mm = &mm->context.skas; 79 struct mmu_context_skas *to_mm = &mm->context.skas;
80 unsigned long stack = 0; 80 unsigned long stack = 0;
81 int from_fd, ret = -ENOMEM; 81 int ret = -ENOMEM;
82 82
83 if(skas_needs_stub){ 83 if(skas_needs_stub){
84 stack = get_zeroed_page(GFP_KERNEL); 84 stack = get_zeroed_page(GFP_KERNEL);
@@ -108,11 +108,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
108 from_mm = &current->mm->context.skas; 108 from_mm = &current->mm->context.skas;
109 109
110 if(proc_mm){ 110 if(proc_mm){
111 if(from_mm) 111 ret = new_mm(stack);
112 from_fd = from_mm->id.u.mm_fd;
113 else from_fd = -1;
114
115 ret = new_mm(from_fd, stack);
116 if(ret < 0){ 112 if(ret < 0){
117 printk("init_new_context_skas - new_mm failed, " 113 printk("init_new_context_skas - new_mm failed, "
118 "errno = %d\n", ret); 114 "errno = %d\n", ret);
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 599d679bd4..eea1c9c4bb 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -18,7 +18,6 @@
18#include <asm/types.h> 18#include <asm/types.h>
19#include "user.h" 19#include "user.h"
20#include "ptrace_user.h" 20#include "ptrace_user.h"
21#include "time_user.h"
22#include "sysdep/ptrace.h" 21#include "sysdep/ptrace.h"
23#include "user_util.h" 22#include "user_util.h"
24#include "kern_util.h" 23#include "kern_util.h"
@@ -31,7 +30,6 @@
31#include "proc_mm.h" 30#include "proc_mm.h"
32#include "skas_ptrace.h" 31#include "skas_ptrace.h"
33#include "chan_user.h" 32#include "chan_user.h"
34#include "signal_user.h"
35#include "registers.h" 33#include "registers.h"
36#include "mem.h" 34#include "mem.h"
37#include "uml-config.h" 35#include "uml-config.h"
@@ -69,7 +67,7 @@ void wait_stub_done(int pid, int sig, char * fname)
69 67
70 if((n < 0) || !WIFSTOPPED(status) || 68 if((n < 0) || !WIFSTOPPED(status) ||
71 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ 69 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
72 unsigned long regs[FRAME_SIZE]; 70 unsigned long regs[HOST_FRAME_SIZE];
73 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 71 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
74 printk("Failed to get registers from stub, " 72 printk("Failed to get registers from stub, "
75 "errno = %d\n", errno); 73 "errno = %d\n", errno);
@@ -77,7 +75,7 @@ void wait_stub_done(int pid, int sig, char * fname)
77 int i; 75 int i;
78 76
79 printk("Stub registers -\n"); 77 printk("Stub registers -\n");
80 for(i = 0; i < FRAME_SIZE; i++) 78 for(i = 0; i < HOST_FRAME_SIZE; i++)
81 printk("\t%d - %lx\n", i, regs[i]); 79 printk("\t%d - %lx\n", i, regs[i]);
82 } 80 }
83 panic("%s : failed to wait for SIGUSR1/SIGTRAP, " 81 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
@@ -514,16 +512,6 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
514 siglongjmp(**switch_buf, 1); 512 siglongjmp(**switch_buf, 1);
515} 513}
516 514
517void remove_sigstack(void)
518{
519 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
520 .ss_sp = NULL,
521 .ss_size = 0 });
522
523 if(sigaltstack(&stack, NULL) != 0)
524 panic("disabling signal stack failed, errno = %d\n", errno);
525}
526
527void initial_thread_cb_skas(void (*proc)(void *), void *arg) 515void initial_thread_cb_skas(void (*proc)(void *), void *arg)
528{ 516{
529 sigjmp_buf here; 517 sigjmp_buf here;
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 9c99025396..3f70a2e12f 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -13,15 +13,12 @@
13#include "asm/uaccess.h" 13#include "asm/uaccess.h"
14#include "asm/atomic.h" 14#include "asm/atomic.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "time_user.h"
17#include "signal_user.h"
18#include "skas.h" 16#include "skas.h"
19#include "os.h" 17#include "os.h"
20#include "user_util.h" 18#include "user_util.h"
21#include "tlb.h" 19#include "tlb.h"
22#include "kern.h" 20#include "kern.h"
23#include "mode.h" 21#include "mode.h"
24#include "proc_mm.h"
25#include "registers.h" 22#include "registers.h"
26 23
27void switch_to_skas(void *prev, void *next) 24void switch_to_skas(void *prev, void *next)
@@ -35,7 +32,7 @@ void switch_to_skas(void *prev, void *next)
35 if(current->pid == 0) 32 if(current->pid == 0)
36 switch_timers(0); 33 switch_timers(0);
37 34
38 switch_threads(&from->thread.mode.skas.switch_buf, 35 switch_threads(&from->thread.mode.skas.switch_buf,
39 to->thread.mode.skas.switch_buf); 36 to->thread.mode.skas.switch_buf);
40 37
41 if(current->pid == 0) 38 if(current->pid == 0)
@@ -51,8 +48,8 @@ void new_thread_handler(int sig)
51 48
52 fn = current->thread.request.u.thread.proc; 49 fn = current->thread.request.u.thread.proc;
53 arg = current->thread.request.u.thread.arg; 50 arg = current->thread.request.u.thread.arg;
54 change_sig(SIGUSR1, 1); 51 os_usr1_signal(1);
55 thread_wait(&current->thread.mode.skas.switch_buf, 52 thread_wait(&current->thread.mode.skas.switch_buf,
56 current->thread.mode.skas.fork_buf); 53 current->thread.mode.skas.fork_buf);
57 54
58 if(current->thread.prev_sched != NULL) 55 if(current->thread.prev_sched != NULL)
@@ -83,8 +80,8 @@ void release_thread_skas(struct task_struct *task)
83 80
84void fork_handler(int sig) 81void fork_handler(int sig)
85{ 82{
86 change_sig(SIGUSR1, 1); 83 os_usr1_signal(1);
87 thread_wait(&current->thread.mode.skas.switch_buf, 84 thread_wait(&current->thread.mode.skas.switch_buf,
88 current->thread.mode.skas.fork_buf); 85 current->thread.mode.skas.fork_buf);
89 86
90 force_flush_all(); 87 force_flush_all();
@@ -94,13 +91,13 @@ void fork_handler(int sig)
94 schedule_tail(current->thread.prev_sched); 91 schedule_tail(current->thread.prev_sched);
95 current->thread.prev_sched = NULL; 92 current->thread.prev_sched = NULL;
96 93
97 /* Handle any immediate reschedules or signals */ 94/* Handle any immediate reschedules or signals */
98 interrupt_end(); 95 interrupt_end();
99 userspace(&current->thread.regs.regs); 96 userspace(&current->thread.regs.regs);
100} 97}
101 98
102int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, 99int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
103 unsigned long stack_top, struct task_struct * p, 100 unsigned long stack_top, struct task_struct * p,
104 struct pt_regs *regs) 101 struct pt_regs *regs)
105{ 102{
106 void (*handler)(int); 103 void (*handler)(int);
@@ -119,32 +116,19 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
119 handler = new_thread_handler; 116 handler = new_thread_handler;
120 } 117 }
121 118
122 new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, 119 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
123 &p->thread.mode.skas.fork_buf, handler); 120 &p->thread.mode.skas.fork_buf, handler);
124 return(0); 121 return(0);
125} 122}
126 123
127extern void map_stub_pages(int fd, unsigned long code, 124int new_mm(unsigned long stack)
128 unsigned long data, unsigned long stack);
129int new_mm(int from, unsigned long stack)
130{ 125{
131 struct proc_mm_op copy; 126 int fd;
132 int n, fd;
133 127
134 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 128 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
135 if(fd < 0) 129 if(fd < 0)
136 return(fd); 130 return(fd);
137 131
138 if(from != -1){
139 copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
140 .u =
141 { .copy_segments = from } } );
142 n = os_write_file(fd, &copy, sizeof(copy));
143 if(n != sizeof(copy))
144 printk("new_mm : /proc/mm copy_segments failed, "
145 "err = %d\n", -n);
146 }
147
148 if(skas_needs_stub) 132 if(skas_needs_stub)
149 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); 133 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
150 134
@@ -186,7 +170,7 @@ int start_uml_skas(void)
186 170
187 init_task.thread.request.u.thread.proc = start_kernel_proc; 171 init_task.thread.request.u.thread.proc = start_kernel_proc;
188 init_task.thread.request.u.thread.arg = NULL; 172 init_task.thread.request.u.thread.arg = NULL;
189 return(start_idle_thread(init_task.thread_info, 173 return(start_idle_thread(task_stack_page(&init_task),
190 &init_task.thread.mode.skas.switch_buf, 174 &init_task.thread.mode.skas.switch_buf,
191 &init_task.thread.mode.skas.fork_buf)); 175 &init_task.thread.mode.skas.fork_buf));
192} 176}
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 7519528108..5992c32571 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -13,7 +13,7 @@
13#include "asm/pgtable.h" 13#include "asm/pgtable.h"
14#include "asm/uaccess.h" 14#include "asm/uaccess.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user_util.h" 16#include "os.h"
17 17
18extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 18extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
19 pte_t *pte_out); 19 pte_t *pte_out);
@@ -143,7 +143,7 @@ int copy_from_user_skas(void *to, const void __user *from, int n)
143 return(0); 143 return(0);
144 } 144 }
145 145
146 return(access_ok_skas(VERIFY_READ, from, n) ? 146 return(access_ok(VERIFY_READ, from, n) ?
147 buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): 147 buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
148 n); 148 n);
149} 149}
@@ -164,7 +164,7 @@ int copy_to_user_skas(void __user *to, const void *from, int n)
164 return(0); 164 return(0);
165 } 165 }
166 166
167 return(access_ok_skas(VERIFY_WRITE, to, n) ? 167 return(access_ok(VERIFY_WRITE, to, n) ?
168 buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : 168 buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
169 n); 169 n);
170} 170}
@@ -193,7 +193,7 @@ int strncpy_from_user_skas(char *dst, const char __user *src, int count)
193 return(strnlen(dst, count)); 193 return(strnlen(dst, count));
194 } 194 }
195 195
196 if(!access_ok_skas(VERIFY_READ, src, 1)) 196 if(!access_ok(VERIFY_READ, src, 1))
197 return(-EFAULT); 197 return(-EFAULT);
198 198
199 n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, 199 n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
@@ -221,7 +221,7 @@ int clear_user_skas(void __user *mem, int len)
221 return(0); 221 return(0);
222 } 222 }
223 223
224 return(access_ok_skas(VERIFY_WRITE, mem, len) ? 224 return(access_ok(VERIFY_WRITE, mem, len) ?
225 buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); 225 buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
226} 226}
227 227
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 1429c13187..1731d90e68 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -25,12 +25,12 @@ int record_syscall_start(int syscall)
25 syscall_record[index].syscall = syscall; 25 syscall_record[index].syscall = syscall;
26 syscall_record[index].pid = current_pid(); 26 syscall_record[index].pid = current_pid();
27 syscall_record[index].result = 0xdeadbeef; 27 syscall_record[index].result = 0xdeadbeef;
28 syscall_record[index].start = os_usecs(); 28 syscall_record[index].start = os_nsecs();
29 return(index); 29 return(index);
30} 30}
31 31
32void record_syscall_end(int index, long result) 32void record_syscall_end(int index, long result)
33{ 33{
34 syscall_record[index].result = result; 34 syscall_record[index].result = result;
35 syscall_record[index].end = os_usecs(); 35 syscall_record[index].end = os_nsecs();
36} 36}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index c40b611e3d..8fa2ae7f30 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -14,9 +14,9 @@
14#include "kern_util.h" 14#include "kern_util.h"
15#include "user.h" 15#include "user.h"
16#include "process.h" 16#include "process.h"
17#include "signal_user.h"
18#include "time_user.h" 17#include "time_user.h"
19#include "kern_constants.h" 18#include "kern_constants.h"
19#include "os.h"
20 20
21/* XXX This really needs to be declared and initialized in a kernel file since 21/* XXX This really needs to be declared and initialized in a kernel file since
22 * it's in <linux/time.h> 22 * it's in <linux/time.h>
@@ -99,7 +99,8 @@ void uml_idle_timer(void)
99 set_interval(ITIMER_REAL); 99 set_interval(ITIMER_REAL);
100} 100}
101 101
102extern int do_posix_clock_monotonic_gettime(struct timespec *tp); 102extern void ktime_get_ts(struct timespec *ts);
103#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
103 104
104void time_init(void) 105void time_init(void)
105{ 106{
@@ -114,8 +115,8 @@ void time_init(void)
114 wall_to_monotonic.tv_nsec = -now.tv_nsec; 115 wall_to_monotonic.tv_nsec = -now.tv_nsec;
115} 116}
116 117
117/* Declared in linux/time.h, which can't be included here */ 118/* Defined in linux/ktimer.h, which can't be included here */
118extern void clock_was_set(void); 119#define clock_was_set() do { } while (0)
119 120
120void do_gettimeofday(struct timeval *tv) 121void do_gettimeofday(struct timeval *tv)
121{ 122{
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 020ca79b8d..3c7626cdba 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -13,12 +13,12 @@
13#include "linux/interrupt.h" 13#include "linux/interrupt.h"
14#include "linux/init.h" 14#include "linux/init.h"
15#include "linux/delay.h" 15#include "linux/delay.h"
16#include "linux/hrtimer.h"
16#include "asm/irq.h" 17#include "asm/irq.h"
17#include "asm/param.h" 18#include "asm/param.h"
18#include "asm/current.h" 19#include "asm/current.h"
19#include "kern_util.h" 20#include "kern_util.h"
20#include "user_util.h" 21#include "user_util.h"
21#include "time_user.h"
22#include "mode.h" 22#include "mode.h"
23#include "os.h" 23#include "os.h"
24 24
@@ -39,7 +39,7 @@ unsigned long long sched_clock(void)
39int timer_irq_inited = 0; 39int timer_irq_inited = 0;
40 40
41static int first_tick; 41static int first_tick;
42static unsigned long long prev_usecs; 42static unsigned long long prev_nsecs;
43#ifdef CONFIG_UML_REAL_TIME_CLOCK 43#ifdef CONFIG_UML_REAL_TIME_CLOCK
44static long long delta; /* Deviation per interval */ 44static long long delta; /* Deviation per interval */
45#endif 45#endif
@@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs)
58 if(first_tick){ 58 if(first_tick){
59#ifdef CONFIG_UML_REAL_TIME_CLOCK 59#ifdef CONFIG_UML_REAL_TIME_CLOCK
60 /* We've had 1 tick */ 60 /* We've had 1 tick */
61 unsigned long long usecs = os_usecs(); 61 unsigned long long nsecs = os_nsecs();
62 62
63 delta += usecs - prev_usecs; 63 delta += nsecs - prev_nsecs;
64 prev_usecs = usecs; 64 prev_nsecs = nsecs;
65 65
66 /* Protect against the host clock being set backwards */ 66 /* Protect against the host clock being set backwards */
67 if(delta < 0) 67 if(delta < 0)
68 delta = 0; 68 delta = 0;
69 69
70 ticks += (delta * HZ) / MILLION; 70 ticks += (delta * HZ) / BILLION;
71 delta -= (ticks * MILLION) / HZ; 71 delta -= (ticks * BILLION) / HZ;
72#else 72#else
73 ticks = 1; 73 ticks = 1;
74#endif 74#endif
75 } 75 }
76 else { 76 else {
77 prev_usecs = os_usecs(); 77 prev_nsecs = os_nsecs();
78 first_tick = 1; 78 first_tick = 1;
79 } 79 }
80 80
@@ -84,49 +84,102 @@ void timer_irq(union uml_pt_regs *regs)
84 } 84 }
85} 85}
86 86
87void boot_timer_handler(int sig) 87void do_boot_timer_handler(struct sigcontext * sc)
88{ 88{
89 struct pt_regs regs; 89 struct pt_regs regs;
90 90
91 CHOOSE_MODE((void) 91 CHOOSE_MODE((void) (UPT_SC(&regs.regs) = sc),
92 (UPT_SC(&regs.regs) = (struct sigcontext *) (&sig + 1)),
93 (void) (regs.regs.skas.is_user = 0)); 92 (void) (regs.regs.skas.is_user = 0));
94 do_timer(&regs); 93 do_timer(&regs);
95} 94}
96 95
96static DEFINE_SPINLOCK(timer_spinlock);
97
98static unsigned long long local_offset = 0;
99
100static inline unsigned long long get_time(void)
101{
102 unsigned long long nsecs;
103 unsigned long flags;
104
105 spin_lock_irqsave(&timer_spinlock, flags);
106 nsecs = os_nsecs();
107 nsecs += local_offset;
108 spin_unlock_irqrestore(&timer_spinlock, flags);
109
110 return nsecs;
111}
112
97irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) 113irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
98{ 114{
115 unsigned long long nsecs;
99 unsigned long flags; 116 unsigned long flags;
100 117
101 do_timer(regs); 118 do_timer(regs);
119
102 write_seqlock_irqsave(&xtime_lock, flags); 120 write_seqlock_irqsave(&xtime_lock, flags);
103 timer(); 121 nsecs = get_time() + local_offset;
122 xtime.tv_sec = nsecs / NSEC_PER_SEC;
123 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
104 write_sequnlock_irqrestore(&xtime_lock, flags); 124 write_sequnlock_irqrestore(&xtime_lock, flags);
125
105 return(IRQ_HANDLED); 126 return(IRQ_HANDLED);
106} 127}
107 128
108long um_time(int __user *tloc) 129long um_time(int __user *tloc)
109{ 130{
110 struct timeval now; 131 long ret = get_time() / NSEC_PER_SEC;
111 132
112 do_gettimeofday(&now); 133 if((tloc != NULL) && put_user(ret, tloc))
113 if (tloc) { 134 return -EFAULT;
114 if (put_user(now.tv_sec, tloc)) 135
115 now.tv_sec = -EFAULT; 136 return ret;
116 } 137}
117 return now.tv_sec; 138
139void do_gettimeofday(struct timeval *tv)
140{
141 unsigned long long nsecs = get_time();
142
143 tv->tv_sec = nsecs / NSEC_PER_SEC;
144 /* Careful about calculations here - this was originally done as
145 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
146 * which gave bogus (> 1000000) values. Dunno why, suspect gcc
147 * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
148 * problem that I missed.
149 */
150 nsecs -= tv->tv_sec * NSEC_PER_SEC;
151 tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
152}
153
154static inline void set_time(unsigned long long nsecs)
155{
156 unsigned long long now;
157 unsigned long flags;
158
159 spin_lock_irqsave(&timer_spinlock, flags);
160 now = os_nsecs();
161 local_offset = nsecs - now;
162 spin_unlock_irqrestore(&timer_spinlock, flags);
163
164 clock_was_set();
118} 165}
119 166
120long um_stime(int __user *tptr) 167long um_stime(int __user *tptr)
121{ 168{
122 int value; 169 int value;
123 struct timespec new;
124 170
125 if (get_user(value, tptr)) 171 if (get_user(value, tptr))
126 return -EFAULT; 172 return -EFAULT;
127 new.tv_sec = value; 173
128 new.tv_nsec = 0; 174 set_time((unsigned long long) value * NSEC_PER_SEC);
129 do_settimeofday(&new); 175
176 return 0;
177}
178
179int do_settimeofday(struct timespec *tv)
180{
181 set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
182
130 return 0; 183 return 0;
131} 184}
132 185
@@ -134,29 +187,15 @@ void timer_handler(int sig, union uml_pt_regs *regs)
134{ 187{
135 local_irq_disable(); 188 local_irq_disable();
136 irq_enter(); 189 irq_enter();
137 update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), 190 update_process_times(CHOOSE_MODE(
138 (regs)->skas.is_user)); 191 (UPT_SC(regs) && user_context(UPT_SP(regs))),
192 (regs)->skas.is_user));
139 irq_exit(); 193 irq_exit();
140 local_irq_enable(); 194 local_irq_enable();
141 if(current_thread->cpu == 0) 195 if(current_thread->cpu == 0)
142 timer_irq(regs); 196 timer_irq(regs);
143} 197}
144 198
145static DEFINE_SPINLOCK(timer_spinlock);
146
147unsigned long time_lock(void)
148{
149 unsigned long flags;
150
151 spin_lock_irqsave(&timer_spinlock, flags);
152 return(flags);
153}
154
155void time_unlock(unsigned long flags)
156{
157 spin_unlock_irqrestore(&timer_spinlock, flags);
158}
159
160int __init timer_init(void) 199int __init timer_init(void)
161{ 200{
162 int err; 201 int err;
@@ -171,14 +210,3 @@ int __init timer_init(void)
171} 210}
172 211
173__initcall(timer_init); 212__initcall(timer_init);
174
175/*
176 * Overrides for Emacs so that we follow Linus's tabbing style.
177 * Emacs will notice this stuff at the end of the file and automatically
178 * adjust the settings for this buffer only. This must remain at the end
179 * of the file.
180 * ---------------------------------------------------------------------------
181 * Local variables:
182 * c-file-style: "linux"
183 * End:
184 */
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 95c8f8733b..d56046c2ab 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -26,9 +26,13 @@
26#include "mconsole_kern.h" 26#include "mconsole_kern.h"
27#include "mem.h" 27#include "mem.h"
28#include "mem_kern.h" 28#include "mem_kern.h"
29#include "sysdep/sigcontext.h"
30#include "sysdep/ptrace.h"
31#include "os.h"
29#ifdef CONFIG_MODE_SKAS 32#ifdef CONFIG_MODE_SKAS
30#include "skas.h" 33#include "skas.h"
31#endif 34#endif
35#include "os.h"
32 36
33/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ 37/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
34int handle_page_fault(unsigned long address, unsigned long ip, 38int handle_page_fault(unsigned long address, unsigned long ip,
@@ -95,7 +99,16 @@ survive:
95 pte = pte_offset_kernel(pmd, address); 99 pte = pte_offset_kernel(pmd, address);
96 } while(!pte_present(*pte)); 100 } while(!pte_present(*pte));
97 err = 0; 101 err = 0;
102 /* The below warning was added in place of
103 * pte_mkyoung(); if (is_write) pte_mkdirty();
104 * If it's triggered, we'd see normally a hang here (a clean pte is
105 * marked read-only to emulate the dirty bit).
106 * However, the generic code can mark a PTE writable but clean on a
107 * concurrent read fault, triggering this harmlessly. So comment it out.
108 */
109#if 0
98 WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); 110 WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte)));
111#endif
99 flush_tlb_page(vma, address); 112 flush_tlb_page(vma, address);
100out: 113out:
101 up_read(&mm->mmap_sem); 114 up_read(&mm->mmap_sem);
@@ -116,6 +129,25 @@ out_of_memory:
116 goto out; 129 goto out;
117} 130}
118 131
132void segv_handler(int sig, union uml_pt_regs *regs)
133{
134 struct faultinfo * fi = UPT_FAULTINFO(regs);
135
136 if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
137 bad_segv(*fi, UPT_IP(regs));
138 return;
139 }
140 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
141}
142
143struct kern_handlers handlinfo_kern = {
144 .relay_signal = relay_signal,
145 .winch = winch,
146 .bus_handler = relay_signal,
147 .page_fault = segv_handler,
148 .sigio_handler = sigio_handler,
149 .timer_handler = timer_handler
150};
119/* 151/*
120 * We give a *copy* of the faultinfo in the regs to segv. 152 * We give a *copy* of the faultinfo in the regs to segv.
121 * This must be done, since nesting SEGVs could overwrite 153 * This must be done, since nesting SEGVs could overwrite
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
deleted file mode 100644
index e9ccd6b8d3..0000000000
--- a/arch/um/kernel/trap_user.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <errno.h>
8#include <setjmp.h>
9#include <signal.h>
10#include <sys/time.h>
11#include <sys/wait.h>
12#include <asm/page.h>
13#include <asm/unistd.h>
14#include <asm/ptrace.h>
15#include "init.h"
16#include "sysdep/ptrace.h"
17#include "sigcontext.h"
18#include "sysdep/sigcontext.h"
19#include "irq_user.h"
20#include "signal_user.h"
21#include "time_user.h"
22#include "task.h"
23#include "mode.h"
24#include "choose-mode.h"
25#include "kern_util.h"
26#include "user_util.h"
27#include "os.h"
28
29void kill_child_dead(int pid)
30{
31 kill(pid, SIGKILL);
32 kill(pid, SIGCONT);
33 do {
34 int n;
35 CATCH_EINTR(n = waitpid(pid, NULL, 0));
36 if (n > 0)
37 kill(pid, SIGCONT);
38 else
39 break;
40 } while(1);
41}
42
43void segv_handler(int sig, union uml_pt_regs *regs)
44{
45 struct faultinfo * fi = UPT_FAULTINFO(regs);
46
47 if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
48 bad_segv(*fi, UPT_IP(regs));
49 return;
50 }
51 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
52}
53
54void usr2_handler(int sig, union uml_pt_regs *regs)
55{
56 CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
57}
58
59struct signal_info sig_info[] = {
60 [ SIGTRAP ] { .handler = relay_signal,
61 .is_irq = 0 },
62 [ SIGFPE ] { .handler = relay_signal,
63 .is_irq = 0 },
64 [ SIGILL ] { .handler = relay_signal,
65 .is_irq = 0 },
66 [ SIGWINCH ] { .handler = winch,
67 .is_irq = 1 },
68 [ SIGBUS ] { .handler = bus_handler,
69 .is_irq = 0 },
70 [ SIGSEGV] { .handler = segv_handler,
71 .is_irq = 0 },
72 [ SIGIO ] { .handler = sigio_handler,
73 .is_irq = 1 },
74 [ SIGVTALRM ] { .handler = timer_handler,
75 .is_irq = 1 },
76 [ SIGALRM ] { .handler = timer_handler,
77 .is_irq = 1 },
78 [ SIGUSR2 ] { .handler = usr2_handler,
79 .is_irq = 0 },
80};
81
82void do_longjmp(void *b, int val)
83{
84 sigjmp_buf *buf = b;
85
86 siglongjmp(*buf, val);
87}
88
89/*
90 * Overrides for Emacs so that we follow Linus's tabbing style.
91 * Emacs will notice this stuff at the end of the file and automatically
92 * adjust the settings for this buffer only. This must remain at the end
93 * of the file.
94 * ---------------------------------------------------------------------------
95 * Local variables:
96 * c-file-style: "linux"
97 * End:
98 */
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 065b504a65..5c1e4cc1c0 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -13,8 +13,6 @@
13#include "user_util.h" 13#include "user_util.h"
14#include "kern_util.h" 14#include "kern_util.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "time_user.h"
17#include "signal_user.h"
18#include "mem_user.h" 16#include "mem_user.h"
19#include "os.h" 17#include "os.h"
20#include "tlb.h" 18#include "tlb.h"
@@ -40,7 +38,7 @@ void flush_thread_tt(void)
40 do_exit(SIGKILL); 38 do_exit(SIGKILL);
41 } 39 }
42 40
43 new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp); 41 new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp);
44 if(new_pid < 0){ 42 if(new_pid < 0){
45 printk(KERN_ERR 43 printk(KERN_ERR
46 "flush_thread : new thread failed, errno = %d\n", 44 "flush_thread : new thread failed, errno = %d\n",
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 37e22d71a0..786e4edd86 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -20,6 +20,7 @@
20#include "user_util.h" 20#include "user_util.h"
21#include "tt.h" 21#include "tt.h"
22#include "sysdep/thread.h" 22#include "sysdep/thread.h"
23#include "os.h"
23 24
24extern int debugger_pid; 25extern int debugger_pid;
25extern int debugger_fd; 26extern int debugger_fd;
diff --git a/arch/um/kernel/tt/include/mmu-tt.h b/arch/um/kernel/tt/include/mmu-tt.h
deleted file mode 100644
index 0440510ab3..0000000000
--- a/arch/um/kernel/tt/include/mmu-tt.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MMU_H
7#define __TT_MMU_H
8
9struct mmu_context_tt {
10};
11
12#endif
13
14/*
15 * Overrides for Emacs so that we follow Linus's tabbing style.
16 * Emacs will notice this stuff at the end of the file and automatically
17 * adjust the settings for this buffer only. This must remain at the end
18 * of the file.
19 * ---------------------------------------------------------------------------
20 * Local variables:
21 * c-file-style: "linux"
22 * End:
23 */
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index cfaa373a6e..295c1ac817 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -13,13 +13,11 @@
13#include "asm/ptrace.h" 13#include "asm/ptrace.h"
14#include "asm/tlbflush.h" 14#include "asm/tlbflush.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "signal_user.h"
17#include "kern_util.h" 16#include "kern_util.h"
18#include "user_util.h" 17#include "user_util.h"
19#include "os.h" 18#include "os.h"
20#include "kern.h" 19#include "kern.h"
21#include "sigcontext.h" 20#include "sigcontext.h"
22#include "time_user.h"
23#include "mem_user.h" 21#include "mem_user.h"
24#include "tlb.h" 22#include "tlb.h"
25#include "mode.h" 23#include "mode.h"
@@ -37,7 +35,7 @@ void switch_to_tt(void *prev, void *next)
37 from = prev; 35 from = prev;
38 to = next; 36 to = next;
39 37
40 cpu = from->thread_info->cpu; 38 cpu = task_thread_info(from)->cpu;
41 if(cpu == 0) 39 if(cpu == 0)
42 forward_interrupts(to->thread.mode.tt.extern_pid); 40 forward_interrupts(to->thread.mode.tt.extern_pid);
43#ifdef CONFIG_SMP 41#ifdef CONFIG_SMP
@@ -254,7 +252,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
254 252
255 clone_flags &= CLONE_VM; 253 clone_flags &= CLONE_VM;
256 p->thread.temp_stack = stack; 254 p->thread.temp_stack = stack;
257 new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp); 255 new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp);
258 if(new_pid < 0){ 256 if(new_pid < 0){
259 printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", 257 printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
260 -new_pid); 258 -new_pid);
@@ -344,7 +342,7 @@ int do_proc_op(void *t, int proc_id)
344 pid = thread->request.u.exec.pid; 342 pid = thread->request.u.exec.pid;
345 do_exec(thread->mode.tt.extern_pid, pid); 343 do_exec(thread->mode.tt.extern_pid, pid);
346 thread->mode.tt.extern_pid = pid; 344 thread->mode.tt.extern_pid = pid;
347 cpu_tasks[task->thread_info->cpu].pid = pid; 345 cpu_tasks[task_thread_info(task)->cpu].pid = pid;
348 break; 346 break;
349 case OP_FORK: 347 case OP_FORK:
350 attach_process(thread->request.u.fork.pid); 348 attach_process(thread->request.u.fork.pid);
@@ -426,7 +424,7 @@ int start_uml_tt(void)
426 int pages; 424 int pages;
427 425
428 pages = (1 << CONFIG_KERNEL_STACK_ORDER); 426 pages = (1 << CONFIG_KERNEL_STACK_ORDER);
429 sp = (void *) ((unsigned long) init_task.thread_info) + 427 sp = task_stack_page(&init_task) +
430 pages * PAGE_SIZE - sizeof(unsigned long); 428 pages * PAGE_SIZE - sizeof(unsigned long);
431 return(tracer(start_kernel_proc, sp)); 429 return(tracer(start_kernel_proc, sp));
432} 430}
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 528a5fc8d8..03774427d4 100644
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -20,6 +20,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
20#include "kern_util.h" 20#include "kern_util.h"
21#include "ptrace_user.h" 21#include "ptrace_user.h"
22#include "tt.h" 22#include "tt.h"
23#include "os.h"
23 24
24long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, 25long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
25 long arg3, long arg4, pid_t child, int *ret) 26 long arg3, long arg4, pid_t child, int *ret)
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index a5f0e01e21..99f178319d 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -15,6 +15,7 @@ terms and conditions.
15#include "ptrace_user.h" 15#include "ptrace_user.h"
16#include "user_util.h" 16#include "user_util.h"
17#include "user.h" 17#include "user.h"
18#include "os.h"
18 19
19int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, 20int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
20 long *arg5) 21 long *arg5)
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index d11e7399d7..71daae24e4 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -19,7 +19,6 @@
19#include "sigcontext.h" 19#include "sigcontext.h"
20#include "sysdep/sigcontext.h" 20#include "sysdep/sigcontext.h"
21#include "os.h" 21#include "os.h"
22#include "signal_user.h"
23#include "user_util.h" 22#include "user_util.h"
24#include "mem_user.h" 23#include "mem_user.h"
25#include "process.h" 24#include "process.h"
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index fc108615be..b5d9d64d91 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -8,18 +8,18 @@
8#include <signal.h> 8#include <signal.h>
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/sigcontext.h" 10#include "sysdep/sigcontext.h"
11#include "signal_user.h"
12#include "user_util.h" 11#include "user_util.h"
13#include "kern_util.h" 12#include "kern_util.h"
14#include "task.h" 13#include "task.h"
15#include "tt.h" 14#include "tt.h"
15#include "os.h"
16 16
17void sig_handler_common_tt(int sig, void *sc_ptr) 17void sig_handler_common_tt(int sig, void *sc_ptr)
18{ 18{
19 struct sigcontext *sc = sc_ptr; 19 struct sigcontext *sc = sc_ptr;
20 struct tt_regs save_regs, *r; 20 struct tt_regs save_regs, *r;
21 struct signal_info *info; 21 int save_errno = errno, is_user = 0;
22 int save_errno = errno, is_user; 22 void (*handler)(int, union uml_pt_regs *);
23 23
24 /* This is done because to allow SIGSEGV to be delivered inside a SEGV 24 /* This is done because to allow SIGSEGV to be delivered inside a SEGV
25 * handler. This can happen in copy_user, and if SEGV is disabled, 25 * handler. This can happen in copy_user, and if SEGV is disabled,
@@ -35,15 +35,20 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
35 GET_FAULTINFO_FROM_SC(r->faultinfo, sc); 35 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
36 } 36 }
37 save_regs = *r; 37 save_regs = *r;
38 is_user = user_context(SC_SP(sc)); 38 if (sc)
39 is_user = user_context(SC_SP(sc));
39 r->sc = sc; 40 r->sc = sc;
40 if(sig != SIGUSR2) 41 if(sig != SIGUSR2)
41 r->syscall = -1; 42 r->syscall = -1;
42 43
43 info = &sig_info[sig]; 44 handler = sig_info[sig];
44 if(!info->is_irq) unblock_signals(); 45
46 /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
47 if (sig != SIGIO && sig != SIGWINCH &&
48 sig != SIGVTALRM && sig != SIGALRM)
49 unblock_signals();
45 50
46 (*info->handler)(sig, (union uml_pt_regs *) r); 51 handler(sig, (union uml_pt_regs *) r);
47 52
48 if(is_user){ 53 if(is_user){
49 interrupt_end(); 54 interrupt_end();
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c
index a72aa63297..1cb6072656 100644
--- a/arch/um/kernel/tt/uaccess.c
+++ b/arch/um/kernel/tt/uaccess.c
@@ -8,7 +8,7 @@
8 8
9int copy_from_user_tt(void *to, const void __user *from, int n) 9int copy_from_user_tt(void *to, const void __user *from, int n)
10{ 10{
11 if(!access_ok_tt(VERIFY_READ, from, n)) 11 if(!access_ok(VERIFY_READ, from, n))
12 return(n); 12 return(n);
13 13
14 return(__do_copy_from_user(to, from, n, &current->thread.fault_addr, 14 return(__do_copy_from_user(to, from, n, &current->thread.fault_addr,
@@ -17,7 +17,7 @@ int copy_from_user_tt(void *to, const void __user *from, int n)
17 17
18int copy_to_user_tt(void __user *to, const void *from, int n) 18int copy_to_user_tt(void __user *to, const void *from, int n)
19{ 19{
20 if(!access_ok_tt(VERIFY_WRITE, to, n)) 20 if(!access_ok(VERIFY_WRITE, to, n))
21 return(n); 21 return(n);
22 22
23 return(__do_copy_to_user(to, from, n, &current->thread.fault_addr, 23 return(__do_copy_to_user(to, from, n, &current->thread.fault_addr,
@@ -28,7 +28,7 @@ int strncpy_from_user_tt(char *dst, const char __user *src, int count)
28{ 28{
29 int n; 29 int n;
30 30
31 if(!access_ok_tt(VERIFY_READ, src, 1)) 31 if(!access_ok(VERIFY_READ, src, 1))
32 return(-EFAULT); 32 return(-EFAULT);
33 33
34 n = __do_strncpy_from_user(dst, src, count, 34 n = __do_strncpy_from_user(dst, src, count,
@@ -47,7 +47,7 @@ int __clear_user_tt(void __user *mem, int len)
47 47
48int clear_user_tt(void __user *mem, int len) 48int clear_user_tt(void __user *mem, int len)
49{ 49{
50 if(!access_ok_tt(VERIFY_WRITE, mem, len)) 50 if(!access_ok(VERIFY_WRITE, mem, len))
51 return(len); 51 return(len);
52 52
53 return(__do_clear_user(mem, len, &current->thread.fault_addr, 53 return(__do_clear_user(mem, len, &current->thread.fault_addr,
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 142a949391..e2d3ca445e 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -146,8 +146,8 @@ void set_cmdline(char *cmd)
146 146
147 if(CHOOSE_MODE(honeypot, 0)) return; 147 if(CHOOSE_MODE(honeypot, 0)) return;
148 148
149 umid = get_umid(1); 149 umid = get_umid();
150 if(umid != NULL){ 150 if(*umid != '\0'){
151 snprintf(argv1_begin, 151 snprintf(argv1_begin,
152 (argv1_end - argv1_begin) * sizeof(*ptr), 152 (argv1_end - argv1_begin) * sizeof(*ptr),
153 "(%s) ", umid); 153 "(%s) ", umid);
@@ -243,10 +243,6 @@ static int __init mode_tt_setup(char *line, int *add)
243 return(0); 243 return(0);
244} 244}
245 245
246#else
247
248#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled
249
250#endif 246#endif
251#endif 247#endif
252#endif 248#endif
@@ -363,6 +359,11 @@ int linux_main(int argc, char **argv)
363 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, 359 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
364 &host_task_size, &task_size); 360 &host_task_size, &task_size);
365 361
362 /*
363 * Setting up handlers to 'sig_info' struct
364 */
365 os_fill_handlinfo(handlinfo_kern);
366
366 brk_start = (unsigned long) sbrk(0); 367 brk_start = (unsigned long) sbrk(0);
367 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); 368 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
368 /* Increase physical memory size for exec-shield users 369 /* Increase physical memory size for exec-shield users
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 0b21d59ba0..4eaee823bf 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -3,61 +3,30 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <stdio.h> 6#include "asm/errno.h"
7#include <unistd.h>
8#include <errno.h>
9#include <string.h>
10#include <stdlib.h>
11#include <dirent.h>
12#include <signal.h>
13#include <sys/stat.h>
14#include <sys/param.h>
15#include "user.h"
16#include "umid.h"
17#include "init.h" 7#include "init.h"
18#include "os.h" 8#include "os.h"
19#include "user_util.h" 9#include "kern.h"
20#include "choose-mode.h" 10#include "linux/kernel.h"
21 11
22#define UMID_LEN 64 12/* Changed by set_umid_arg */
23#define UML_DIR "~/.uml/"
24
25/* Changed by set_umid and make_umid, which are run early in boot */
26static char umid[UMID_LEN] = { 0 };
27
28/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
29static char *uml_dir = UML_DIR;
30
31/* Changed by set_umid */
32static int umid_is_random = 1;
33static int umid_inited = 0; 13static int umid_inited = 0;
34/* Have we created the files? Should we remove them? */
35static int umid_owned = 0;
36 14
37static int make_umid(int (*printer)(const char *fmt, ...)); 15static int __init set_umid_arg(char *name, int *add)
38
39static int __init set_umid(char *name, int is_random,
40 int (*printer)(const char *fmt, ...))
41{ 16{
42 if(umid_inited){ 17 int err;
43 (*printer)("Unique machine name can't be set twice\n");
44 return(-1);
45 }
46 18
47 if(strlen(name) > UMID_LEN - 1) 19 if(umid_inited)
48 (*printer)("Unique machine name is being truncated to %d " 20 return 0;
49 "characters\n", UMID_LEN);
50 strlcpy(umid, name, sizeof(umid));
51 21
52 umid_is_random = is_random;
53 umid_inited = 1;
54 return 0;
55}
56
57static int __init set_umid_arg(char *name, int *add)
58{
59 *add = 0; 22 *add = 0;
60 return(set_umid(name, 0, printf)); 23 err = set_umid(name);
24 if(err == -EEXIST)
25 printf("umid '%s' already in use\n", name);
26 else if(!err)
27 umid_inited = 1;
28
29 return 0;
61} 30}
62 31
63__uml_setup("umid=", set_umid_arg, 32__uml_setup("umid=", set_umid_arg,
@@ -66,265 +35,3 @@ __uml_setup("umid=", set_umid_arg,
66" is used for naming the pid file and management console socket.\n\n" 35" is used for naming the pid file and management console socket.\n\n"
67); 36);
68 37
69int __init umid_file_name(char *name, char *buf, int len)
70{
71 int n;
72
73 if(!umid_inited && make_umid(printk)) return(-1);
74
75 n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
76 if(n > len){
77 printk("umid_file_name : buffer too short\n");
78 return(-1);
79 }
80
81 sprintf(buf, "%s%s/%s", uml_dir, umid, name);
82 return(0);
83}
84
85extern int tracing_pid;
86
87static void __init create_pid_file(void)
88{
89 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
90 char pid[sizeof("nnnnn\0")];
91 int fd, n;
92
93 if(umid_file_name("pid", file, sizeof(file)))
94 return;
95
96 fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
97 0644);
98 if(fd < 0){
99 printf("Open of machine pid file \"%s\" failed: %s\n",
100 file, strerror(-fd));
101 return;
102 }
103
104 sprintf(pid, "%d\n", os_getpid());
105 n = os_write_file(fd, pid, strlen(pid));
106 if(n != strlen(pid))
107 printf("Write of pid file failed - err = %d\n", -n);
108 os_close_file(fd);
109}
110
111static int actually_do_remove(char *dir)
112{
113 DIR *directory;
114 struct dirent *ent;
115 int len;
116 char file[256];
117
118 directory = opendir(dir);
119 if(directory == NULL){
120 printk("actually_do_remove : couldn't open directory '%s', "
121 "errno = %d\n", dir, errno);
122 return(1);
123 }
124 while((ent = readdir(directory)) != NULL){
125 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
126 continue;
127 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
128 if(len > sizeof(file)){
129 printk("Not deleting '%s' from '%s' - name too long\n",
130 ent->d_name, dir);
131 continue;
132 }
133 sprintf(file, "%s/%s", dir, ent->d_name);
134 if(unlink(file) < 0){
135 printk("actually_do_remove : couldn't remove '%s' "
136 "from '%s', errno = %d\n", ent->d_name, dir,
137 errno);
138 return(1);
139 }
140 }
141 if(rmdir(dir) < 0){
142 printk("actually_do_remove : couldn't rmdir '%s', "
143 "errno = %d\n", dir, errno);
144 return(1);
145 }
146 return(0);
147}
148
149void remove_umid_dir(void)
150{
151 char dir[strlen(uml_dir) + UMID_LEN + 1];
152 if (!umid_owned)
153 return;
154
155 sprintf(dir, "%s%s", uml_dir, umid);
156 actually_do_remove(dir);
157}
158
159char *get_umid(int only_if_set)
160{
161 if(only_if_set && umid_is_random)
162 return NULL;
163 return umid;
164}
165
166static int not_dead_yet(char *dir)
167{
168 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
169 char pid[sizeof("nnnnn\0")], *end;
170 int dead, fd, p, n;
171
172 sprintf(file, "%s/pid", dir);
173 dead = 0;
174 fd = os_open_file(file, of_read(OPENFLAGS()), 0);
175 if(fd < 0){
176 if(fd != -ENOENT){
177 printk("not_dead_yet : couldn't open pid file '%s', "
178 "err = %d\n", file, -fd);
179 return(1);
180 }
181 dead = 1;
182 }
183 if(fd > 0){
184 n = os_read_file(fd, pid, sizeof(pid));
185 if(n < 0){
186 printk("not_dead_yet : couldn't read pid file '%s', "
187 "err = %d\n", file, -n);
188 return(1);
189 }
190 p = strtoul(pid, &end, 0);
191 if(end == pid){
192 printk("not_dead_yet : couldn't parse pid file '%s', "
193 "errno = %d\n", file, errno);
194 dead = 1;
195 }
196 if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
197 (p == CHOOSE_MODE(tracing_pid, os_getpid())))
198 dead = 1;
199 }
200 if(!dead)
201 return(1);
202 return(actually_do_remove(dir));
203}
204
205static int __init set_uml_dir(char *name, int *add)
206{
207 if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
208 uml_dir = malloc(strlen(name) + 2);
209 if(uml_dir == NULL){
210 printf("Failed to malloc uml_dir - error = %d\n",
211 errno);
212 uml_dir = name;
213 /* Return 0 here because do_initcalls doesn't look at
214 * the return value.
215 */
216 return(0);
217 }
218 sprintf(uml_dir, "%s/", name);
219 }
220 else uml_dir = name;
221 return(0);
222}
223
224static int __init make_uml_dir(void)
225{
226 char dir[MAXPATHLEN + 1] = { '\0' };
227 int len;
228
229 if(*uml_dir == '~'){
230 char *home = getenv("HOME");
231
232 if(home == NULL){
233 printf("make_uml_dir : no value in environment for "
234 "$HOME\n");
235 exit(1);
236 }
237 strlcpy(dir, home, sizeof(dir));
238 uml_dir++;
239 }
240 strlcat(dir, uml_dir, sizeof(dir));
241 len = strlen(dir);
242 if (len > 0 && dir[len - 1] != '/')
243 strlcat(dir, "/", sizeof(dir));
244
245 uml_dir = malloc(strlen(dir) + 1);
246 if (uml_dir == NULL) {
247 printf("make_uml_dir : malloc failed, errno = %d\n", errno);
248 exit(1);
249 }
250 strcpy(uml_dir, dir);
251
252 if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
253 printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno));
254 return(-1);
255 }
256 return 0;
257}
258
259static int __init make_umid(int (*printer)(const char *fmt, ...))
260{
261 int fd, err;
262 char tmp[strlen(uml_dir) + UMID_LEN + 1];
263
264 strlcpy(tmp, uml_dir, sizeof(tmp));
265
266 if(!umid_inited){
267 strcat(tmp, "XXXXXX");
268 fd = mkstemp(tmp);
269 if(fd < 0){
270 (*printer)("make_umid - mkstemp(%s) failed: %s\n",
271 tmp,strerror(errno));
272 return(1);
273 }
274
275 os_close_file(fd);
276 /* There's a nice tiny little race between this unlink and
277 * the mkdir below. It'd be nice if there were a mkstemp
278 * for directories.
279 */
280 unlink(tmp);
281 set_umid(&tmp[strlen(uml_dir)], 1, printer);
282 }
283
284 sprintf(tmp, "%s%s", uml_dir, umid);
285
286 err = mkdir(tmp, 0777);
287 if(err < 0){
288 if(errno == EEXIST){
289 if(not_dead_yet(tmp)){
290 (*printer)("umid '%s' is in use\n", umid);
291 umid_owned = 0;
292 return(-1);
293 }
294 err = mkdir(tmp, 0777);
295 }
296 }
297 if(err < 0){
298 (*printer)("Failed to create %s - errno = %d\n", umid, errno);
299 return(-1);
300 }
301
302 umid_owned = 1;
303 return 0;
304}
305
306__uml_setup("uml_dir=", set_uml_dir,
307"uml_dir=<directory>\n"
308" The location to place the pid and umid files.\n\n"
309);
310
311static int __init make_umid_setup(void)
312{
313 /* one function with the ordering we need ... */
314 make_uml_dir();
315 make_umid(printf);
316 create_pid_file();
317 return 0;
318}
319__uml_postsetup(make_umid_setup);
320
321/*
322 * Overrides for Emacs so that we follow Linus's tabbing style.
323 * Emacs will notice this stuff at the end of the file and automatically
324 * adjust the settings for this buffer only. This must remain at the end
325 * of the file.
326 * ---------------------------------------------------------------------------
327 * Local variables:
328 * c-file-style: "linux"
329 * End:
330 */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index b83ac8e21c..08a4e628b2 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,11 +4,13 @@
4# 4#
5 5
6obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ 6obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
7 start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \ 7 start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \
8 sys-$(SUBARCH)/ 8 util.o drivers/ sys-$(SUBARCH)/
9
10obj-$(CONFIG_MODE_SKAS) += skas/
9 11
10USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ 12USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
11 start_up.o time.o tt.o tty.o uaccess.o 13 start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o util.o
12 14
13elf_aux.o: $(ARCH_DIR)/kernel-offsets.h 15elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
14CFLAGS_elf_aux.o += -I$(objtree)/arch/um 16CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index ffa759addd..f897140cc4 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -16,12 +16,12 @@
16#include "mode.h" 16#include "mode.h"
17 17
18struct aio_thread_req { 18struct aio_thread_req {
19 enum aio_type type; 19 enum aio_type type;
20 int io_fd; 20 int io_fd;
21 unsigned long long offset; 21 unsigned long long offset;
22 char *buf; 22 char *buf;
23 int len; 23 int len;
24 struct aio_context *aio; 24 struct aio_context *aio;
25}; 25};
26 26
27static int aio_req_fd_r = -1; 27static int aio_req_fd_r = -1;
@@ -38,18 +38,18 @@ static int aio_req_fd_w = -1;
38 38
39static long io_setup(int n, aio_context_t *ctxp) 39static long io_setup(int n, aio_context_t *ctxp)
40{ 40{
41 return syscall(__NR_io_setup, n, ctxp); 41 return syscall(__NR_io_setup, n, ctxp);
42} 42}
43 43
44static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) 44static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
45{ 45{
46 return syscall(__NR_io_submit, ctx, nr, iocbpp); 46 return syscall(__NR_io_submit, ctx, nr, iocbpp);
47} 47}
48 48
49static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, 49static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
50 struct io_event *events, struct timespec *timeout) 50 struct io_event *events, struct timespec *timeout)
51{ 51{
52 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout); 52 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
53} 53}
54 54
55#endif 55#endif
@@ -66,243 +66,245 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
66 */ 66 */
67 67
68static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, 68static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
69 int len, unsigned long long offset, struct aio_context *aio) 69 int len, unsigned long long offset, struct aio_context *aio)
70{ 70{
71 struct iocb iocb, *iocbp = &iocb; 71 struct iocb iocb, *iocbp = &iocb;
72 char c; 72 char c;
73 int err; 73 int err;
74 74
75 iocb = ((struct iocb) { .aio_data = (unsigned long) aio, 75 iocb = ((struct iocb) { .aio_data = (unsigned long) aio,
76 .aio_reqprio = 0, 76 .aio_reqprio = 0,
77 .aio_fildes = fd, 77 .aio_fildes = fd,
78 .aio_buf = (unsigned long) buf, 78 .aio_buf = (unsigned long) buf,
79 .aio_nbytes = len, 79 .aio_nbytes = len,
80 .aio_offset = offset, 80 .aio_offset = offset,
81 .aio_reserved1 = 0, 81 .aio_reserved1 = 0,
82 .aio_reserved2 = 0, 82 .aio_reserved2 = 0,
83 .aio_reserved3 = 0 }); 83 .aio_reserved3 = 0 });
84 84
85 switch(type){ 85 switch(type){
86 case AIO_READ: 86 case AIO_READ:
87 iocb.aio_lio_opcode = IOCB_CMD_PREAD; 87 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
88 err = io_submit(ctx, 1, &iocbp); 88 err = io_submit(ctx, 1, &iocbp);
89 break; 89 break;
90 case AIO_WRITE: 90 case AIO_WRITE:
91 iocb.aio_lio_opcode = IOCB_CMD_PWRITE; 91 iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
92 err = io_submit(ctx, 1, &iocbp); 92 err = io_submit(ctx, 1, &iocbp);
93 break; 93 break;
94 case AIO_MMAP: 94 case AIO_MMAP:
95 iocb.aio_lio_opcode = IOCB_CMD_PREAD; 95 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
96 iocb.aio_buf = (unsigned long) &c; 96 iocb.aio_buf = (unsigned long) &c;
97 iocb.aio_nbytes = sizeof(c); 97 iocb.aio_nbytes = sizeof(c);
98 err = io_submit(ctx, 1, &iocbp); 98 err = io_submit(ctx, 1, &iocbp);
99 break; 99 break;
100 default: 100 default:
101 printk("Bogus op in do_aio - %d\n", type); 101 printk("Bogus op in do_aio - %d\n", type);
102 err = -EINVAL; 102 err = -EINVAL;
103 break; 103 break;
104 } 104 }
105 105
106 if(err > 0) 106 if(err > 0)
107 err = 0; 107 err = 0;
108 else 108 else
109 err = -errno; 109 err = -errno;
110 110
111 return err; 111 return err;
112} 112}
113 113
114static aio_context_t ctx = 0; 114static aio_context_t ctx = 0;
115 115
116static int aio_thread(void *arg) 116static int aio_thread(void *arg)
117{ 117{
118 struct aio_thread_reply reply; 118 struct aio_thread_reply reply;
119 struct io_event event; 119 struct io_event event;
120 int err, n, reply_fd; 120 int err, n, reply_fd;
121 121
122 signal(SIGWINCH, SIG_IGN); 122 signal(SIGWINCH, SIG_IGN);
123 123
124 while(1){ 124 while(1){
125 n = io_getevents(ctx, 1, 1, &event, NULL); 125 n = io_getevents(ctx, 1, 1, &event, NULL);
126 if(n < 0){ 126 if(n < 0){
127 if(errno == EINTR) 127 if(errno == EINTR)
128 continue; 128 continue;
129 printk("aio_thread - io_getevents failed, " 129 printk("aio_thread - io_getevents failed, "
130 "errno = %d\n", errno); 130 "errno = %d\n", errno);
131 } 131 }
132 else { 132 else {
133 reply = ((struct aio_thread_reply) 133 reply = ((struct aio_thread_reply)
134 { .data = (void *) (long) event.data, 134 { .data = (void *) (long) event.data,
135 .err = event.res }); 135 .err = event.res });
136 reply_fd = ((struct aio_context *) reply.data)->reply_fd; 136 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
137 err = os_write_file(reply_fd, &reply, sizeof(reply)); 137 err = os_write_file(reply_fd, &reply, sizeof(reply));
138 if(err != sizeof(reply)) 138 if(err != sizeof(reply))
139 printk("aio_thread - write failed, fd = %d, " 139 printk("aio_thread - write failed, fd = %d, "
140 "err = %d\n", aio_req_fd_r, -err); 140 "err = %d\n", aio_req_fd_r, -err);
141 } 141 }
142 } 142 }
143 return 0; 143 return 0;
144} 144}
145 145
146#endif 146#endif
147 147
148static int do_not_aio(struct aio_thread_req *req) 148static int do_not_aio(struct aio_thread_req *req)
149{ 149{
150 char c; 150 char c;
151 int err; 151 int err;
152 152
153 switch(req->type){ 153 switch(req->type){
154 case AIO_READ: 154 case AIO_READ:
155 err = os_seek_file(req->io_fd, req->offset); 155 err = os_seek_file(req->io_fd, req->offset);
156 if(err) 156 if(err)
157 goto out; 157 goto out;
158 158
159 err = os_read_file(req->io_fd, req->buf, req->len); 159 err = os_read_file(req->io_fd, req->buf, req->len);
160 break; 160 break;
161 case AIO_WRITE: 161 case AIO_WRITE:
162 err = os_seek_file(req->io_fd, req->offset); 162 err = os_seek_file(req->io_fd, req->offset);
163 if(err) 163 if(err)
164 goto out; 164 goto out;
165 165
166 err = os_write_file(req->io_fd, req->buf, req->len); 166 err = os_write_file(req->io_fd, req->buf, req->len);
167 break; 167 break;
168 case AIO_MMAP: 168 case AIO_MMAP:
169 err = os_seek_file(req->io_fd, req->offset); 169 err = os_seek_file(req->io_fd, req->offset);
170 if(err) 170 if(err)
171 goto out; 171 goto out;
172 172
173 err = os_read_file(req->io_fd, &c, sizeof(c)); 173 err = os_read_file(req->io_fd, &c, sizeof(c));
174 break; 174 break;
175 default: 175 default:
176 printk("do_not_aio - bad request type : %d\n", req->type); 176 printk("do_not_aio - bad request type : %d\n", req->type);
177 err = -EINVAL; 177 err = -EINVAL;
178 break; 178 break;
179 } 179 }
180 180
181 out: 181out:
182 return err; 182 return err;
183} 183}
184 184
185static int not_aio_thread(void *arg) 185static int not_aio_thread(void *arg)
186{ 186{
187 struct aio_thread_req req; 187 struct aio_thread_req req;
188 struct aio_thread_reply reply; 188 struct aio_thread_reply reply;
189 int err; 189 int err;
190 190
191 signal(SIGWINCH, SIG_IGN); 191 signal(SIGWINCH, SIG_IGN);
192 while(1){ 192 while(1){
193 err = os_read_file(aio_req_fd_r, &req, sizeof(req)); 193 err = os_read_file(aio_req_fd_r, &req, sizeof(req));
194 if(err != sizeof(req)){ 194 if(err != sizeof(req)){
195 if(err < 0) 195 if(err < 0)
196 printk("not_aio_thread - read failed, " 196 printk("not_aio_thread - read failed, "
197 "fd = %d, err = %d\n", aio_req_fd_r, 197 "fd = %d, err = %d\n", aio_req_fd_r,
198 -err); 198 -err);
199 else { 199 else {
200 printk("not_aio_thread - short read, fd = %d, " 200 printk("not_aio_thread - short read, fd = %d, "
201 "length = %d\n", aio_req_fd_r, err); 201 "length = %d\n", aio_req_fd_r, err);
202 } 202 }
203 continue; 203 continue;
204 } 204 }
205 err = do_not_aio(&req); 205 err = do_not_aio(&req);
206 reply = ((struct aio_thread_reply) { .data = req.aio, 206 reply = ((struct aio_thread_reply) { .data = req.aio,
207 .err = err }); 207 .err = err });
208 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); 208 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
209 if(err != sizeof(reply)) 209 if(err != sizeof(reply))
210 printk("not_aio_thread - write failed, fd = %d, " 210 printk("not_aio_thread - write failed, fd = %d, "
211 "err = %d\n", aio_req_fd_r, -err); 211 "err = %d\n", aio_req_fd_r, -err);
212 } 212 }
213
214 return 0;
213} 215}
214 216
215static int aio_pid = -1; 217static int aio_pid = -1;
216 218
217static int init_aio_24(void) 219static int init_aio_24(void)
218{ 220{
219 unsigned long stack; 221 unsigned long stack;
220 int fds[2], err; 222 int fds[2], err;
221 223
222 err = os_pipe(fds, 1, 1); 224 err = os_pipe(fds, 1, 1);
223 if(err) 225 if(err)
224 goto out; 226 goto out;
225 227
226 aio_req_fd_w = fds[0]; 228 aio_req_fd_w = fds[0];
227 aio_req_fd_r = fds[1]; 229 aio_req_fd_r = fds[1];
228 err = run_helper_thread(not_aio_thread, NULL, 230 err = run_helper_thread(not_aio_thread, NULL,
229 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); 231 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
230 if(err < 0) 232 if(err < 0)
231 goto out_close_pipe; 233 goto out_close_pipe;
232 234
233 aio_pid = err; 235 aio_pid = err;
234 goto out; 236 goto out;
235 237
236 out_close_pipe: 238out_close_pipe:
237 os_close_file(fds[0]); 239 os_close_file(fds[0]);
238 os_close_file(fds[1]); 240 os_close_file(fds[1]);
239 aio_req_fd_w = -1; 241 aio_req_fd_w = -1;
240 aio_req_fd_r = -1; 242 aio_req_fd_r = -1;
241 out: 243out:
242#ifndef HAVE_AIO_ABI 244#ifndef HAVE_AIO_ABI
243 printk("/usr/include/linux/aio_abi.h not present during build\n"); 245 printk("/usr/include/linux/aio_abi.h not present during build\n");
244#endif 246#endif
245 printk("2.6 host AIO support not used - falling back to I/O " 247 printk("2.6 host AIO support not used - falling back to I/O "
246 "thread\n"); 248 "thread\n");
247 return 0; 249 return 0;
248} 250}
249 251
250#ifdef HAVE_AIO_ABI 252#ifdef HAVE_AIO_ABI
251#define DEFAULT_24_AIO 0 253#define DEFAULT_24_AIO 0
252static int init_aio_26(void) 254static int init_aio_26(void)
253{ 255{
254 unsigned long stack; 256 unsigned long stack;
255 int err; 257 int err;
256 258
257 if(io_setup(256, &ctx)){ 259 if(io_setup(256, &ctx)){
258 err = -errno; 260 err = -errno;
259 printk("aio_thread failed to initialize context, err = %d\n", 261 printk("aio_thread failed to initialize context, err = %d\n",
260 errno); 262 errno);
261 return err; 263 return err;
262 } 264 }
263 265
264 err = run_helper_thread(aio_thread, NULL, 266 err = run_helper_thread(aio_thread, NULL,
265 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); 267 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
266 if(err < 0) 268 if(err < 0)
267 return err; 269 return err;
268 270
269 aio_pid = err; 271 aio_pid = err;
270 272
271 printk("Using 2.6 host AIO\n"); 273 printk("Using 2.6 host AIO\n");
272 return 0; 274 return 0;
273} 275}
274 276
275static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, 277static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
276 unsigned long long offset, struct aio_context *aio) 278 unsigned long long offset, struct aio_context *aio)
277{ 279{
278 struct aio_thread_reply reply; 280 struct aio_thread_reply reply;
279 int err; 281 int err;
280 282
281 err = do_aio(ctx, type, io_fd, buf, len, offset, aio); 283 err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
282 if(err){ 284 if(err){
283 reply = ((struct aio_thread_reply) { .data = aio, 285 reply = ((struct aio_thread_reply) { .data = aio,
284 .err = err }); 286 .err = err });
285 err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); 287 err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
286 if(err != sizeof(reply)) 288 if(err != sizeof(reply))
287 printk("submit_aio_26 - write failed, " 289 printk("submit_aio_26 - write failed, "
288 "fd = %d, err = %d\n", aio->reply_fd, -err); 290 "fd = %d, err = %d\n", aio->reply_fd, -err);
289 else err = 0; 291 else err = 0;
290 } 292 }
291 293
292 return err; 294 return err;
293} 295}
294 296
295#else 297#else
296#define DEFAULT_24_AIO 1 298#define DEFAULT_24_AIO 1
297static int init_aio_26(void) 299static int init_aio_26(void)
298{ 300{
299 return -ENOSYS; 301 return -ENOSYS;
300} 302}
301 303
302static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, 304static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
303 unsigned long long offset, struct aio_context *aio) 305 unsigned long long offset, struct aio_context *aio)
304{ 306{
305 return -ENOSYS; 307 return -ENOSYS;
306} 308}
307#endif 309#endif
308 310
@@ -310,8 +312,8 @@ static int aio_24 = DEFAULT_24_AIO;
310 312
311static int __init set_aio_24(char *name, int *add) 313static int __init set_aio_24(char *name, int *add)
312{ 314{
313 aio_24 = 1; 315 aio_24 = 1;
314 return 0; 316 return 0;
315} 317}
316 318
317__uml_setup("aio=2.4", set_aio_24, 319__uml_setup("aio=2.4", set_aio_24,
@@ -328,28 +330,27 @@ __uml_setup("aio=2.4", set_aio_24,
328 330
329static int init_aio(void) 331static int init_aio(void)
330{ 332{
331 int err; 333 int err;
332 334
333 CHOOSE_MODE(({ 335 CHOOSE_MODE(({ if(!aio_24){
334 if(!aio_24){ 336 printk("Disabling 2.6 AIO in tt mode\n");
335 printk("Disabling 2.6 AIO in tt mode\n"); 337 aio_24 = 1;
336 aio_24 = 1; 338 } }), (void) 0);
337 } }), (void) 0); 339
338 340 if(!aio_24){
339 if(!aio_24){ 341 err = init_aio_26();
340 err = init_aio_26(); 342 if(err && (errno == ENOSYS)){
341 if(err && (errno == ENOSYS)){ 343 printk("2.6 AIO not supported on the host - "
342 printk("2.6 AIO not supported on the host - " 344 "reverting to 2.4 AIO\n");
343 "reverting to 2.4 AIO\n"); 345 aio_24 = 1;
344 aio_24 = 1; 346 }
345 } 347 else return err;
346 else return err; 348 }
347 } 349
348 350 if(aio_24)
349 if(aio_24) 351 return init_aio_24();
350 return init_aio_24(); 352
351 353 return 0;
352 return 0;
353} 354}
354 355
355/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio 356/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
@@ -362,8 +363,8 @@ __initcall(init_aio);
362 363
363static void exit_aio(void) 364static void exit_aio(void)
364{ 365{
365 if(aio_pid != -1) 366 if(aio_pid != -1)
366 os_kill_process(aio_pid, 1); 367 os_kill_process(aio_pid, 1);
367} 368}
368 369
369__uml_exitcall(exit_aio); 370__uml_exitcall(exit_aio);
@@ -371,30 +372,30 @@ __uml_exitcall(exit_aio);
371static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, 372static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
372 unsigned long long offset, struct aio_context *aio) 373 unsigned long long offset, struct aio_context *aio)
373{ 374{
374 struct aio_thread_req req = { .type = type, 375 struct aio_thread_req req = { .type = type,
375 .io_fd = io_fd, 376 .io_fd = io_fd,
376 .offset = offset, 377 .offset = offset,
377 .buf = buf, 378 .buf = buf,
378 .len = len, 379 .len = len,
379 .aio = aio, 380 .aio = aio,
380 }; 381 };
381 int err; 382 int err;
382 383
383 err = os_write_file(aio_req_fd_w, &req, sizeof(req)); 384 err = os_write_file(aio_req_fd_w, &req, sizeof(req));
384 if(err == sizeof(req)) 385 if(err == sizeof(req))
385 err = 0; 386 err = 0;
386 387
387 return err; 388 return err;
388} 389}
389 390
390int submit_aio(enum aio_type type, int io_fd, char *buf, int len, 391int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
391 unsigned long long offset, int reply_fd, 392 unsigned long long offset, int reply_fd,
392 struct aio_context *aio) 393 struct aio_context *aio)
393{ 394{
394 aio->reply_fd = reply_fd; 395 aio->reply_fd = reply_fd;
395 if(aio_24) 396 if(aio_24)
396 return submit_aio_24(type, io_fd, buf, len, offset, aio); 397 return submit_aio_24(type, io_fd, buf, len, offset, aio);
397 else { 398 else {
398 return submit_aio_26(type, io_fd, buf, len, offset, aio); 399 return submit_aio_26(type, io_fd, buf, len, offset, aio);
399 } 400 }
400} 401}
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 36cc8475bc..6490a4ff40 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -60,7 +60,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
60 60
61 if((stack_out != NULL) && (*stack_out != 0)) 61 if((stack_out != NULL) && (*stack_out != 0))
62 stack = *stack_out; 62 stack = *stack_out;
63 else stack = alloc_stack(0, um_in_interrupt()); 63 else stack = alloc_stack(0, __cant_sleep());
64 if(stack == 0) 64 if(stack == 0)
65 return(-ENOMEM); 65 return(-ENOMEM);
66 66
@@ -124,7 +124,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
124 unsigned long stack, sp; 124 unsigned long stack, sp;
125 int pid, status, err; 125 int pid, status, err;
126 126
127 stack = alloc_stack(stack_order, um_in_interrupt()); 127 stack = alloc_stack(stack_order, __cant_sleep());
128 if(stack == 0) return(-ENOMEM); 128 if(stack == 0) return(-ENOMEM);
129 129
130 sp = stack + (page_size() << stack_order) - sizeof(void *); 130 sp = stack + (page_size() << stack_order) - sizeof(void *);
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 23da27d225..2878e89a67 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -16,8 +16,6 @@
16#include "user_util.h" 16#include "user_util.h"
17#include "kern_util.h" 17#include "kern_util.h"
18#include "mem_user.h" 18#include "mem_user.h"
19#include "signal_user.h"
20#include "time_user.h"
21#include "irq_user.h" 19#include "irq_user.h"
22#include "user.h" 20#include "user.h"
23#include "init.h" 21#include "init.h"
@@ -83,20 +81,8 @@ extern void scan_elf_aux( char **envp);
83int main(int argc, char **argv, char **envp) 81int main(int argc, char **argv, char **envp)
84{ 82{
85 char **new_argv; 83 char **new_argv;
86 sigset_t mask;
87 int ret, i, err; 84 int ret, i, err;
88 85
89 /* Enable all signals except SIGIO - in some environments, we can
90 * enter with some signals blocked
91 */
92
93 sigemptyset(&mask);
94 sigaddset(&mask, SIGIO);
95 if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
96 perror("sigprocmask");
97 exit(1);
98 }
99
100#ifdef UML_CONFIG_CMDLINE_ON_HOST 86#ifdef UML_CONFIG_CMDLINE_ON_HOST
101 /* Allocate memory for thread command lines */ 87 /* Allocate memory for thread command lines */
102 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ 88 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index d9c52387c4..7f5e2dac2a 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -15,10 +15,10 @@
15#include "os.h" 15#include "os.h"
16#include "user.h" 16#include "user.h"
17#include "user_util.h" 17#include "user_util.h"
18#include "signal_user.h"
19#include "process.h" 18#include "process.h"
20#include "irq_user.h" 19#include "irq_user.h"
21#include "kern_util.h" 20#include "kern_util.h"
21#include "longjmp.h"
22 22
23#define ARBITRARY_ADDR -1 23#define ARBITRARY_ADDR -1
24#define FAILURE_PID -1 24#define FAILURE_PID -1
@@ -206,24 +206,13 @@ void init_new_thread_signals(int altstack)
206 206
207int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) 207int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
208{ 208{
209 sigjmp_buf buf; 209 sigjmp_buf buf;
210 int n; 210 int n, enable;
211 211
212 *jmp_ptr = &buf; 212 *jmp_ptr = &buf;
213 n = sigsetjmp(buf, 1); 213 n = UML_SIGSETJMP(&buf, enable);
214 if(n != 0) 214 if(n != 0)
215 return(n); 215 return(n);
216 (*fn)(arg); 216 (*fn)(arg);
217 return(0); 217 return(0);
218} 218}
219
220/*
221 * Overrides for Emacs so that we follow Linus's tabbing style.
222 * Emacs will notice this stuff at the end of the file and automatically
223 * adjust the settings for this buffer only. This must remain at the end
224 * of the file.
225 * ---------------------------------------------------------------------------
226 * Local variables:
227 * c-file-style: "linux"
228 * End:
229 */
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index c7bfd5ee39..f11b3124a0 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -4,27 +4,74 @@
4 */ 4 */
5 5
6#include <signal.h> 6#include <signal.h>
7#include "time_user.h" 7#include <stdio.h>
8#include "mode.h" 8#include <unistd.h>
9#include <stdlib.h>
10#include <errno.h>
11#include <stdarg.h>
12#include <string.h>
13#include <sys/mman.h>
14#include "user_util.h"
15#include "user.h"
16#include "signal_kern.h"
17#include "sysdep/sigcontext.h"
9#include "sysdep/signal.h" 18#include "sysdep/signal.h"
19#include "sigcontext.h"
20#include "mode.h"
21#include "os.h"
22
23/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
24 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
25 * be able to profile all of UML, not just the non-critical sections. If
26 * profiling is not thread-safe, then that is not my problem. We can disable
27 * profiling when SMP is enabled in that case.
28 */
29#define SIGIO_BIT 0
30#define SIGIO_MASK (1 << SIGIO_BIT)
31
32#define SIGVTALRM_BIT 1
33#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
34
35#define SIGALRM_BIT 2
36#define SIGALRM_MASK (1 << SIGALRM_BIT)
37
38static int signals_enabled = 1;
39static int pending = 0;
10 40
11void sig_handler(ARCH_SIGHDLR_PARAM) 41void sig_handler(ARCH_SIGHDLR_PARAM)
12{ 42{
13 struct sigcontext *sc; 43 struct sigcontext *sc;
44 int enabled;
45
46 /* Must be the first thing that this handler does - x86_64 stores
47 * the sigcontext in %rdx, and we need to save it before it has a
48 * chance to get trashed.
49 */
14 50
15 ARCH_GET_SIGCONTEXT(sc, sig); 51 ARCH_GET_SIGCONTEXT(sc, sig);
52
53 enabled = signals_enabled;
54 if(!enabled && (sig == SIGIO)){
55 pending |= SIGIO_MASK;
56 return;
57 }
58
59 block_signals();
60
16 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, 61 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
17 sig, sc); 62 sig, sc);
63
64 set_signals(enabled);
18} 65}
19 66
20extern int timer_irq_inited; 67extern int timer_irq_inited;
21 68
22void alarm_handler(ARCH_SIGHDLR_PARAM) 69static void real_alarm_handler(int sig, struct sigcontext *sc)
23{ 70{
24 struct sigcontext *sc; 71 if(!timer_irq_inited){
25 72 signals_enabled = 1;
26 ARCH_GET_SIGCONTEXT(sc, sig); 73 return;
27 if(!timer_irq_inited) return; 74 }
28 75
29 if(sig == SIGALRM) 76 if(sig == SIGALRM)
30 switch_timers(0); 77 switch_timers(0);
@@ -34,15 +81,180 @@ void alarm_handler(ARCH_SIGHDLR_PARAM)
34 81
35 if(sig == SIGALRM) 82 if(sig == SIGALRM)
36 switch_timers(1); 83 switch_timers(1);
84
37} 85}
38 86
39/* 87void alarm_handler(ARCH_SIGHDLR_PARAM)
40 * Overrides for Emacs so that we follow Linus's tabbing style. 88{
41 * Emacs will notice this stuff at the end of the file and automatically 89 struct sigcontext *sc;
42 * adjust the settings for this buffer only. This must remain at the end 90 int enabled;
43 * of the file. 91
44 * --------------------------------------------------------------------------- 92 ARCH_GET_SIGCONTEXT(sc, sig);
45 * Local variables: 93
46 * c-file-style: "linux" 94 enabled = signals_enabled;
47 * End: 95 if(!signals_enabled){
48 */ 96 if(sig == SIGVTALRM)
97 pending |= SIGVTALRM_MASK;
98 else pending |= SIGALRM_MASK;
99
100 return;
101 }
102
103 block_signals();
104
105 real_alarm_handler(sig, sc);
106 set_signals(enabled);
107}
108
109extern void do_boot_timer_handler(struct sigcontext * sc);
110
111void boot_timer_handler(ARCH_SIGHDLR_PARAM)
112{
113 struct sigcontext *sc;
114 int enabled;
115
116 ARCH_GET_SIGCONTEXT(sc, sig);
117
118 enabled = signals_enabled;
119 if(!enabled){
120 if(sig == SIGVTALRM)
121 pending |= SIGVTALRM_MASK;
122 else pending |= SIGALRM_MASK;
123 return;
124 }
125
126 block_signals();
127
128 do_boot_timer_handler(sc);
129 set_signals(enabled);
130}
131
132void set_sigstack(void *sig_stack, int size)
133{
134 stack_t stack = ((stack_t) { .ss_flags = 0,
135 .ss_sp = (__ptr_t) sig_stack,
136 .ss_size = size - sizeof(void *) });
137
138 if(sigaltstack(&stack, NULL) != 0)
139 panic("enabling signal stack failed, errno = %d\n", errno);
140}
141
142void remove_sigstack(void)
143{
144 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
145 .ss_sp = NULL,
146 .ss_size = 0 });
147
148 if(sigaltstack(&stack, NULL) != 0)
149 panic("disabling signal stack failed, errno = %d\n", errno);
150}
151
152void set_handler(int sig, void (*handler)(int), int flags, ...)
153{
154 struct sigaction action;
155 va_list ap;
156 sigset_t sig_mask;
157 int mask;
158
159 va_start(ap, flags);
160 action.sa_handler = handler;
161 sigemptyset(&action.sa_mask);
162 while((mask = va_arg(ap, int)) != -1){
163 sigaddset(&action.sa_mask, mask);
164 }
165 va_end(ap);
166 action.sa_flags = flags;
167 action.sa_restorer = NULL;
168 if(sigaction(sig, &action, NULL) < 0)
169 panic("sigaction failed - errno = %d\n", errno);
170
171 sigemptyset(&sig_mask);
172 sigaddset(&sig_mask, sig);
173 if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
174 panic("sigprocmask failed - errno = %d\n", errno);
175}
176
177int change_sig(int signal, int on)
178{
179 sigset_t sigset, old;
180
181 sigemptyset(&sigset);
182 sigaddset(&sigset, signal);
183 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
184 return(!sigismember(&old, signal));
185}
186
187void block_signals(void)
188{
189 signals_enabled = 0;
190}
191
192void unblock_signals(void)
193{
194 int save_pending;
195
196 if(signals_enabled == 1)
197 return;
198
199 /* We loop because the IRQ handler returns with interrupts off. So,
200 * interrupts may have arrived and we need to re-enable them and
201 * recheck pending.
202 */
203 while(1){
204 /* Save and reset save_pending after enabling signals. This
205 * way, pending won't be changed while we're reading it.
206 */
207 signals_enabled = 1;
208
209 save_pending = pending;
210 if(save_pending == 0)
211 return;
212
213 pending = 0;
214
215 /* We have pending interrupts, so disable signals, as the
216 * handlers expect them off when they are called. They will
217 * be enabled again above.
218 */
219
220 signals_enabled = 0;
221
222 /* Deal with SIGIO first because the alarm handler might
223 * schedule, leaving the pending SIGIO stranded until we come
224 * back here.
225 */
226 if(save_pending & SIGIO_MASK)
227 CHOOSE_MODE_PROC(sig_handler_common_tt,
228 sig_handler_common_skas, SIGIO, NULL);
229
230 if(save_pending & SIGALRM_MASK)
231 real_alarm_handler(SIGALRM, NULL);
232
233 if(save_pending & SIGVTALRM_MASK)
234 real_alarm_handler(SIGVTALRM, NULL);
235 }
236}
237
238int get_signals(void)
239{
240 return signals_enabled;
241}
242
243int set_signals(int enable)
244{
245 int ret;
246 if(signals_enabled == enable)
247 return enable;
248
249 ret = signals_enabled;
250 if(enable)
251 unblock_signals();
252 else block_signals();
253
254 return ret;
255}
256
257void os_usr1_signal(int on)
258{
259 change_sig(SIGUSR1, on);
260}
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
new file mode 100644
index 0000000000..5fd8d4dad6
--- /dev/null
+++ b/arch/um/os-Linux/skas/Makefile
@@ -0,0 +1,10 @@
1#
2# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
3# Licensed under the GPL
4#
5
6obj-y := mem.o process.o trap.o
7
8USER_OBJS := mem.o process.o trap.o
9
10include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/os-Linux/skas/mem.c
index 1d89640bd5..9890e9090f 100644
--- a/arch/um/kernel/skas/mem_user.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -32,7 +32,7 @@ extern void wait_stub_done(int pid, int sig, char * fname);
32static inline unsigned long *check_init_stack(struct mm_id * mm_idp, 32static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
33 unsigned long *stack) 33 unsigned long *stack)
34{ 34{
35 if(stack == NULL){ 35 if(stack == NULL) {
36 stack = (unsigned long *) mm_idp->stack + 2; 36 stack = (unsigned long *) mm_idp->stack + 2;
37 *stack = 0; 37 *stack = 0;
38 } 38 }
@@ -45,13 +45,14 @@ int single_count = 0;
45int multi_count = 0; 45int multi_count = 0;
46int multi_op_count = 0; 46int multi_op_count = 0;
47 47
48static long do_syscall_stub(struct mm_id *mm_idp, void **addr) 48static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
49{ 49{
50 unsigned long regs[MAX_REG_NR]; 50 unsigned long regs[MAX_REG_NR];
51 unsigned long *data; 51 int n;
52 unsigned long *syscall;
53 long ret, offset; 52 long ret, offset;
54 int n, pid = mm_idp->u.pid; 53 unsigned long * data;
54 unsigned long * syscall;
55 int pid = mm_idp->u.pid;
55 56
56 if(proc_mm) 57 if(proc_mm)
57#warning Need to look up userspace_pid by cpu 58#warning Need to look up userspace_pid by cpu
@@ -59,10 +60,11 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
59 60
60 multi_count++; 61 multi_count++;
61 62
62 get_safe_registers(regs); 63 get_safe_registers(regs);
63 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + 64 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
64 ((unsigned long) &batch_syscall_stub - 65 ((unsigned long) &batch_syscall_stub -
65 (unsigned long) &__syscall_stub_start); 66 (unsigned long) &__syscall_stub_start);
67
66 n = ptrace_setregs(pid, regs); 68 n = ptrace_setregs(pid, regs);
67 if(n < 0) 69 if(n < 0)
68 panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", 70 panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
@@ -80,6 +82,8 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
80 if (offset) { 82 if (offset) {
81 data = (unsigned long *)(mm_idp->stack + 83 data = (unsigned long *)(mm_idp->stack +
82 offset - UML_CONFIG_STUB_DATA); 84 offset - UML_CONFIG_STUB_DATA);
85 printk("do_syscall_stub : ret = %d, offset = %d, "
86 "data = 0x%x\n", ret, offset, data);
83 syscall = (unsigned long *)((unsigned long)data + data[0]); 87 syscall = (unsigned long *)((unsigned long)data + data[0]);
84 printk("do_syscall_stub: syscall %ld failed, return value = " 88 printk("do_syscall_stub: syscall %ld failed, return value = "
85 "0x%lx, expected return value = 0x%lx\n", 89 "0x%lx, expected return value = 0x%lx\n",
@@ -107,32 +111,32 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
107 111
108long run_syscall_stub(struct mm_id * mm_idp, int syscall, 112long run_syscall_stub(struct mm_id * mm_idp, int syscall,
109 unsigned long *args, long expected, void **addr, 113 unsigned long *args, long expected, void **addr,
110 int done) 114 int done)
111{ 115{
112 unsigned long *stack = check_init_stack(mm_idp, *addr); 116 unsigned long *stack = check_init_stack(mm_idp, *addr);
113 117
114 if(done && *addr == NULL) 118 if(done && *addr == NULL)
115 single_count++; 119 single_count++;
116 120
117 *stack += sizeof(long); 121 *stack += sizeof(long);
118 stack += *stack / sizeof(long); 122 stack += *stack / sizeof(long);
119 123
120 *stack++ = syscall; 124 *stack++ = syscall;
121 *stack++ = args[0]; 125 *stack++ = args[0];
122 *stack++ = args[1]; 126 *stack++ = args[1];
123 *stack++ = args[2]; 127 *stack++ = args[2];
124 *stack++ = args[3]; 128 *stack++ = args[3];
125 *stack++ = args[4]; 129 *stack++ = args[4];
126 *stack++ = args[5]; 130 *stack++ = args[5];
127 *stack++ = expected; 131 *stack++ = expected;
128 *stack = 0; 132 *stack = 0;
129 multi_op_count++; 133 multi_op_count++;
130 134
131 if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < 135 if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
132 PAGE_SIZE - 10 * sizeof(long))){ 136 PAGE_SIZE - 10 * sizeof(long))){
133 *addr = stack; 137 *addr = stack;
134 return 0; 138 return 0;
135 } 139 }
136 140
137 return do_syscall_stub(mm_idp, addr); 141 return do_syscall_stub(mm_idp, addr);
138} 142}
@@ -150,7 +154,7 @@ long syscall_stub_data(struct mm_id * mm_idp,
150 if((((unsigned long) *addr) & ~PAGE_MASK) >= 154 if((((unsigned long) *addr) & ~PAGE_MASK) >=
151 PAGE_SIZE - (10 + data_count) * sizeof(long)) { 155 PAGE_SIZE - (10 + data_count) * sizeof(long)) {
152 ret = do_syscall_stub(mm_idp, addr); 156 ret = do_syscall_stub(mm_idp, addr);
153 /* in case of error, don't overwrite data on stack */ 157 /* in case of error, don't overwrite data on stack */
154 if(ret) 158 if(ret)
155 return ret; 159 return ret;
156 } 160 }
@@ -172,39 +176,39 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
172 int r, int w, int x, int phys_fd, unsigned long long offset, 176 int r, int w, int x, int phys_fd, unsigned long long offset,
173 int done, void **data) 177 int done, void **data)
174{ 178{
175 int prot, ret; 179 int prot, ret;
176 180
177 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 181 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
178 (x ? PROT_EXEC : 0); 182 (x ? PROT_EXEC : 0);
179 183
180 if(proc_mm){ 184 if(proc_mm){
181 struct proc_mm_op map; 185 struct proc_mm_op map;
182 int fd = mm_idp->u.mm_fd; 186 int fd = mm_idp->u.mm_fd;
183 187
184 map = ((struct proc_mm_op) { .op = MM_MMAP, 188 map = ((struct proc_mm_op) { .op = MM_MMAP,
185 .u = 189 .u =
186 { .mmap = 190 { .mmap =
187 { .addr = virt, 191 { .addr = virt,
188 .len = len, 192 .len = len,
189 .prot = prot, 193 .prot = prot,
190 .flags = MAP_SHARED | 194 .flags = MAP_SHARED |
191 MAP_FIXED, 195 MAP_FIXED,
192 .fd = phys_fd, 196 .fd = phys_fd,
193 .offset= offset 197 .offset= offset
194 } } } ); 198 } } } );
195 ret = os_write_file(fd, &map, sizeof(map)); 199 ret = os_write_file(fd, &map, sizeof(map));
196 if(ret != sizeof(map)) 200 if(ret != sizeof(map))
197 printk("map : /proc/mm map failed, err = %d\n", -ret); 201 printk("map : /proc/mm map failed, err = %d\n", -ret);
198 else ret = 0; 202 else ret = 0;
199 } 203 }
200 else { 204 else {
201 unsigned long args[] = { virt, len, prot, 205 unsigned long args[] = { virt, len, prot,
202 MAP_SHARED | MAP_FIXED, phys_fd, 206 MAP_SHARED | MAP_FIXED, phys_fd,
203 MMAP_OFFSET(offset) }; 207 MMAP_OFFSET(offset) };
204 208
205 ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, 209 ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
206 data, done); 210 data, done);
207 } 211 }
208 212
209 return ret; 213 return ret;
210} 214}
@@ -212,68 +216,66 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
212int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, 216int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
213 void **data) 217 void **data)
214{ 218{
215 int ret; 219 int ret;
216 220
217 if(proc_mm){ 221 if(proc_mm){
218 struct proc_mm_op unmap; 222 struct proc_mm_op unmap;
219 int fd = mm_idp->u.mm_fd; 223 int fd = mm_idp->u.mm_fd;
220 224
221 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, 225 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
222 .u = 226 .u =
223 { .munmap = 227 { .munmap =
224 { .addr = 228 { .addr =
225 (unsigned long) addr, 229 (unsigned long) addr,
226 .len = len } } } ); 230 .len = len } } } );
227 ret = os_write_file(fd, &unmap, sizeof(unmap)); 231 ret = os_write_file(fd, &unmap, sizeof(unmap));
228 if(ret != sizeof(unmap)) 232 if(ret != sizeof(unmap))
229 printk("unmap - proc_mm write returned %d\n", ret); 233 printk("unmap - proc_mm write returned %d\n", ret);
230 else ret = 0; 234 else ret = 0;
231 } 235 }
232 else { 236 else {
233 unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, 237 unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
234 0 }; 238 0 };
235 239
236 ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, 240 ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
237 data, done); 241 data, done);
238 if(ret < 0) 242 }
239 printk("munmap stub failed, errno = %d\n", ret);
240 }
241 243
242 return ret; 244 return ret;
243} 245}
244 246
245int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, 247int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
246 int r, int w, int x, int done, void **data) 248 int r, int w, int x, int done, void **data)
247{ 249{
248 struct proc_mm_op protect; 250 struct proc_mm_op protect;
249 int prot, ret; 251 int prot, ret;
250 252
251 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 253 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
252 (x ? PROT_EXEC : 0); 254 (x ? PROT_EXEC : 0);
253 255 if(proc_mm){
254 if(proc_mm){ 256 int fd = mm_idp->u.mm_fd;
255 int fd = mm_idp->u.mm_fd; 257
256 protect = ((struct proc_mm_op) { .op = MM_MPROTECT, 258 protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
257 .u = 259 .u =
258 { .mprotect = 260 { .mprotect =
259 { .addr = 261 { .addr =
260 (unsigned long) addr, 262 (unsigned long) addr,
261 .len = len, 263 .len = len,
262 .prot = prot } } } ); 264 .prot = prot } } } );
263 265
264 ret = os_write_file(fd, &protect, sizeof(protect)); 266 ret = os_write_file(fd, &protect, sizeof(protect));
265 if(ret != sizeof(protect)) 267 if(ret != sizeof(protect))
266 printk("protect failed, err = %d", -ret); 268 printk("protect failed, err = %d", -ret);
267 else ret = 0; 269 else ret = 0;
268 } 270 }
269 else { 271 else {
270 unsigned long args[] = { addr, len, prot, 0, 0, 0 }; 272 unsigned long args[] = { addr, len, prot, 0, 0, 0 };
271 273
272 ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, 274 ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
273 data, done); 275 data, done);
274 } 276 }
275 277
276 return ret; 278 return ret;
277} 279}
278 280
279void before_mem_skas(unsigned long unused) 281void before_mem_skas(unsigned long unused)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
new file mode 100644
index 0000000000..120a21c588
--- /dev/null
+++ b/arch/um/os-Linux/skas/process.c
@@ -0,0 +1,566 @@
1/*
2 * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9#include <errno.h>
10#include <signal.h>
11#include <setjmp.h>
12#include <sched.h>
13#include "ptrace_user.h"
14#include <sys/wait.h>
15#include <sys/mman.h>
16#include <sys/user.h>
17#include <sys/time.h>
18#include <asm/unistd.h>
19#include <asm/types.h>
20#include "user.h"
21#include "sysdep/ptrace.h"
22#include "user_util.h"
23#include "kern_util.h"
24#include "skas.h"
25#include "stub-data.h"
26#include "mm_id.h"
27#include "sysdep/sigcontext.h"
28#include "sysdep/stub.h"
29#include "os.h"
30#include "proc_mm.h"
31#include "skas_ptrace.h"
32#include "chan_user.h"
33#include "registers.h"
34#include "mem.h"
35#include "uml-config.h"
36#include "process.h"
37#include "longjmp.h"
38
39int is_skas_winch(int pid, int fd, void *data)
40{
41 if(pid != os_getpgrp())
42 return(0);
43
44 register_winch_irq(-1, fd, -1, data);
45 return(1);
46}
47
48void wait_stub_done(int pid, int sig, char * fname)
49{
50 int n, status, err;
51
52 do {
53 if ( sig != -1 ) {
54 err = ptrace(PTRACE_CONT, pid, 0, sig);
55 if(err)
56 panic("%s : continue failed, errno = %d\n",
57 fname, errno);
58 }
59 sig = 0;
60
61 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
62 } while((n >= 0) && WIFSTOPPED(status) &&
63 ((WSTOPSIG(status) == SIGVTALRM) ||
64 /* running UML inside a detached screen can cause
65 * SIGWINCHes
66 */
67 (WSTOPSIG(status) == SIGWINCH)));
68
69 if((n < 0) || !WIFSTOPPED(status) ||
70 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
71 unsigned long regs[HOST_FRAME_SIZE];
72
73 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
74 printk("Failed to get registers from stub, "
75 "errno = %d\n", errno);
76 else {
77 int i;
78
79 printk("Stub registers -\n");
80 for(i = 0; i < HOST_FRAME_SIZE; i++)
81 printk("\t%d - %lx\n", i, regs[i]);
82 }
83 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
84 "pid = %d, n = %d, errno = %d, status = 0x%x\n",
85 fname, pid, n, errno, status);
86 }
87}
88
89extern unsigned long current_stub_stack(void);
90
91void get_skas_faultinfo(int pid, struct faultinfo * fi)
92{
93 int err;
94
95 if(ptrace_faultinfo){
96 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
97 if(err)
98 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
99 "errno = %d\n", errno);
100
101 /* Special handling for i386, which has different structs */
102 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
103 memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
104 sizeof(struct faultinfo) -
105 sizeof(struct ptrace_faultinfo));
106 }
107 else {
108 wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
109
110 /* faultinfo is prepared by the stub-segv-handler at start of
111 * the stub stack page. We just have to copy it.
112 */
113 memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
114 }
115}
116
117static void handle_segv(int pid, union uml_pt_regs * regs)
118{
119 get_skas_faultinfo(pid, &regs->skas.faultinfo);
120 segv(regs->skas.faultinfo, 0, 1, NULL);
121}
122
123/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
124static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
125{
126 int err, status;
127
128 /* Mark this as a syscall */
129 UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);
130
131 if (!local_using_sysemu)
132 {
133 err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
134 __NR_getpid);
135 if(err < 0)
136 panic("handle_trap - nullifying syscall failed errno = %d\n",
137 errno);
138
139 err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
140 if(err < 0)
141 panic("handle_trap - continuing to end of syscall failed, "
142 "errno = %d\n", errno);
143
144 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
145 if((err < 0) || !WIFSTOPPED(status) ||
146 (WSTOPSIG(status) != SIGTRAP + 0x80))
147 panic("handle_trap - failed to wait at end of syscall, "
148 "errno = %d, status = %d\n", errno, status);
149 }
150
151 handle_syscall(regs);
152}
153
154extern int __syscall_stub_start;
155
156static int userspace_tramp(void *stack)
157{
158 void *addr;
159
160 ptrace(PTRACE_TRACEME, 0, 0, 0);
161
162 init_new_thread_signals(1);
163 enable_timer();
164
165 if(!proc_mm){
166 /* This has a pte, but it can't be mapped in with the usual
167 * tlb_flush mechanism because this is part of that mechanism
168 */
169 int fd;
170 __u64 offset;
171 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
172 addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
173 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
174 if(addr == MAP_FAILED){
175 printk("mapping mmap stub failed, errno = %d\n",
176 errno);
177 exit(1);
178 }
179
180 if(stack != NULL){
181 fd = phys_mapping(to_phys(stack), &offset);
182 addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
183 PROT_READ | PROT_WRITE,
184 MAP_FIXED | MAP_SHARED, fd, offset);
185 if(addr == MAP_FAILED){
186 printk("mapping segfault stack failed, "
187 "errno = %d\n", errno);
188 exit(1);
189 }
190 }
191 }
192 if(!ptrace_faultinfo && (stack != NULL)){
193 unsigned long v = UML_CONFIG_STUB_CODE +
194 (unsigned long) stub_segv_handler -
195 (unsigned long) &__syscall_stub_start;
196
197 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
198 set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
199 SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
200 SIGUSR1, -1);
201 }
202
203 os_stop_process(os_getpid());
204 return(0);
205}
206
207/* Each element set once, and only accessed by a single processor anyway */
208#undef NR_CPUS
209#define NR_CPUS 1
210int userspace_pid[NR_CPUS];
211
212int start_userspace(unsigned long stub_stack)
213{
214 void *stack;
215 unsigned long sp;
216 int pid, status, n, flags;
217
218 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
219 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
220 if(stack == MAP_FAILED)
221 panic("start_userspace : mmap failed, errno = %d", errno);
222 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
223
224 flags = CLONE_FILES | SIGCHLD;
225 if(proc_mm) flags |= CLONE_VM;
226 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
227 if(pid < 0)
228 panic("start_userspace : clone failed, errno = %d", errno);
229
230 do {
231 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
232 if(n < 0)
233 panic("start_userspace : wait failed, errno = %d",
234 errno);
235 } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
236
237 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
238 panic("start_userspace : expected SIGSTOP, got status = %d",
239 status);
240
241 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
242 panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
243 errno);
244
245 if(munmap(stack, PAGE_SIZE) < 0)
246 panic("start_userspace : munmap failed, errno = %d\n", errno);
247
248 return(pid);
249}
250
251void userspace(union uml_pt_regs *regs)
252{
253 int err, status, op, pid = userspace_pid[0];
254 int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
255
256 while(1){
257 restore_registers(pid, regs);
258
259 /* Now we set local_using_sysemu to be used for one loop */
260 local_using_sysemu = get_using_sysemu();
261
262 op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
263
264 err = ptrace(op, pid, 0, 0);
265 if(err)
266 panic("userspace - could not resume userspace process, "
267 "pid=%d, ptrace operation = %d, errno = %d\n",
268 op, errno);
269
270 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
271 if(err < 0)
272 panic("userspace - waitpid failed, errno = %d\n",
273 errno);
274
275 regs->skas.is_user = 1;
276 save_registers(pid, regs);
277 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
278
279 if(WIFSTOPPED(status)){
280 switch(WSTOPSIG(status)){
281 case SIGSEGV:
282 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
283 user_signal(SIGSEGV, regs, pid);
284 else handle_segv(pid, regs);
285 break;
286 case SIGTRAP + 0x80:
287 handle_trap(pid, regs, local_using_sysemu);
288 break;
289 case SIGTRAP:
290 relay_signal(SIGTRAP, regs);
291 break;
292 case SIGIO:
293 case SIGVTALRM:
294 case SIGILL:
295 case SIGBUS:
296 case SIGFPE:
297 case SIGWINCH:
298 user_signal(WSTOPSIG(status), regs, pid);
299 break;
300 default:
301 printk("userspace - child stopped with signal "
302 "%d\n", WSTOPSIG(status));
303 }
304 pid = userspace_pid[0];
305 interrupt_end();
306
307 /* Avoid -ERESTARTSYS handling in host */
308 if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
309 PT_SYSCALL_NR(regs->skas.regs) = -1;
310 }
311 }
312}
313#define INIT_JMP_NEW_THREAD 0
314#define INIT_JMP_REMOVE_SIGSTACK 1
315#define INIT_JMP_CALLBACK 2
316#define INIT_JMP_HALT 3
317#define INIT_JMP_REBOOT 4
318
319int copy_context_skas0(unsigned long new_stack, int pid)
320{
321 int err;
322 unsigned long regs[MAX_REG_NR];
323 unsigned long current_stack = current_stub_stack();
324 struct stub_data *data = (struct stub_data *) current_stack;
325 struct stub_data *child_data = (struct stub_data *) new_stack;
326 __u64 new_offset;
327 int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
328
329 /* prepare offset and fd of child's stack as argument for parent's
330 * and child's mmap2 calls
331 */
332 *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
333 .fd = new_fd,
334 .timer = ((struct itimerval)
335 { { 0, 1000000 / hz() },
336 { 0, 1000000 / hz() }})});
337 get_safe_registers(regs);
338
339 /* Set parent's instruction pointer to start of clone-stub */
340 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
341 (unsigned long) stub_clone_handler -
342 (unsigned long) &__syscall_stub_start;
343 regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
344 sizeof(void *);
345#ifdef __SIGNAL_FRAMESIZE
346 regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
347#endif
348 err = ptrace_setregs(pid, regs);
349 if(err < 0)
350 panic("copy_context_skas0 : PTRACE_SETREGS failed, "
351 "pid = %d, errno = %d\n", pid, errno);
352
353 /* set a well known return code for detection of child write failure */
354 child_data->err = 12345678;
355
356 /* Wait, until parent has finished its work: read child's pid from
357 * parent's stack, and check, if bad result.
358 */
359 wait_stub_done(pid, 0, "copy_context_skas0");
360
361 pid = data->err;
362 if(pid < 0)
363 panic("copy_context_skas0 - stub-parent reports error %d\n",
364 pid);
365
366 /* Wait, until child has finished too: read child's result from
367 * child's stack and check it.
368 */
369 wait_stub_done(pid, -1, "copy_context_skas0");
370 if (child_data->err != UML_CONFIG_STUB_DATA)
371 panic("copy_context_skas0 - stub-child reports error %d\n",
372 child_data->err);
373
374 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
375 (void *)PTRACE_O_TRACESYSGOOD) < 0)
376 panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
377 "errno = %d\n", errno);
378
379 return pid;
380}
381
382/*
383 * This is used only, if stub pages are needed, while proc_mm is
384 * availabl. Opening /proc/mm creates a new mm_context, which lacks
385 * the stub-pages. Thus, we map them using /proc/mm-fd
386 */
387void map_stub_pages(int fd, unsigned long code,
388 unsigned long data, unsigned long stack)
389{
390 struct proc_mm_op mmop;
391 int n;
392 __u64 code_offset;
393 int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start),
394 &code_offset);
395
396 mmop = ((struct proc_mm_op) { .op = MM_MMAP,
397 .u =
398 { .mmap =
399 { .addr = code,
400 .len = PAGE_SIZE,
401 .prot = PROT_EXEC,
402 .flags = MAP_FIXED | MAP_PRIVATE,
403 .fd = code_fd,
404 .offset = code_offset
405 } } });
406 n = os_write_file(fd, &mmop, sizeof(mmop));
407 if(n != sizeof(mmop))
408 panic("map_stub_pages : /proc/mm map for code failed, "
409 "err = %d\n", -n);
410
411 if ( stack ) {
412 __u64 map_offset;
413 int map_fd = phys_mapping(to_phys((void *)stack), &map_offset);
414 mmop = ((struct proc_mm_op)
415 { .op = MM_MMAP,
416 .u =
417 { .mmap =
418 { .addr = data,
419 .len = PAGE_SIZE,
420 .prot = PROT_READ | PROT_WRITE,
421 .flags = MAP_FIXED | MAP_SHARED,
422 .fd = map_fd,
423 .offset = map_offset
424 } } });
425 n = os_write_file(fd, &mmop, sizeof(mmop));
426 if(n != sizeof(mmop))
427 panic("map_stub_pages : /proc/mm map for data failed, "
428 "err = %d\n", -n);
429 }
430}
431
432void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
433 void (*handler)(int))
434{
435 unsigned long flags;
436 sigjmp_buf switch_buf, fork_buf;
437 int enable;
438
439 *switch_buf_ptr = &switch_buf;
440 *fork_buf_ptr = &fork_buf;
441
442 /* Somewhat subtle - siglongjmp restores the signal mask before doing
443 * the longjmp. This means that when jumping from one stack to another
444 * when the target stack has interrupts enabled, an interrupt may occur
445 * on the source stack. This is bad when starting up a process because
446 * it's not supposed to get timer ticks until it has been scheduled.
447 * So, we disable interrupts around the sigsetjmp to ensure that
448 * they can't happen until we get back here where they are safe.
449 */
450 flags = get_signals();
451 block_signals();
452 if(UML_SIGSETJMP(&fork_buf, enable) == 0)
453 new_thread_proc(stack, handler);
454
455 remove_sigstack();
456
457 set_signals(flags);
458}
459
460void thread_wait(void *sw, void *fb)
461{
462 sigjmp_buf buf, **switch_buf = sw, *fork_buf;
463 int enable;
464
465 *switch_buf = &buf;
466 fork_buf = fb;
467 if(UML_SIGSETJMP(&buf, enable) == 0)
468 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
469}
470
471void switch_threads(void *me, void *next)
472{
473 sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
474 int enable;
475
476 *me_ptr = &my_buf;
477 if(UML_SIGSETJMP(&my_buf, enable) == 0)
478 UML_SIGLONGJMP(next_buf, 1);
479}
480
481static sigjmp_buf initial_jmpbuf;
482
483/* XXX Make these percpu */
484static void (*cb_proc)(void *arg);
485static void *cb_arg;
486static sigjmp_buf *cb_back;
487
488int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
489{
490 sigjmp_buf **switch_buf = switch_buf_ptr;
491 int n, enable;
492
493 set_handler(SIGWINCH, (__sighandler_t) sig_handler,
494 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
495 SIGVTALRM, -1);
496
497 *fork_buf_ptr = &initial_jmpbuf;
498 n = UML_SIGSETJMP(&initial_jmpbuf, enable);
499 switch(n){
500 case INIT_JMP_NEW_THREAD:
501 new_thread_proc((void *) stack, new_thread_handler);
502 break;
503 case INIT_JMP_REMOVE_SIGSTACK:
504 remove_sigstack();
505 break;
506 case INIT_JMP_CALLBACK:
507 (*cb_proc)(cb_arg);
508 UML_SIGLONGJMP(cb_back, 1);
509 break;
510 case INIT_JMP_HALT:
511 kmalloc_ok = 0;
512 return(0);
513 case INIT_JMP_REBOOT:
514 kmalloc_ok = 0;
515 return(1);
516 default:
517 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
518 }
519 UML_SIGLONGJMP(*switch_buf, 1);
520}
521
522void initial_thread_cb_skas(void (*proc)(void *), void *arg)
523{
524 sigjmp_buf here;
525 int enable;
526
527 cb_proc = proc;
528 cb_arg = arg;
529 cb_back = &here;
530
531 block_signals();
532 if(UML_SIGSETJMP(&here, enable) == 0)
533 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
534 unblock_signals();
535
536 cb_proc = NULL;
537 cb_arg = NULL;
538 cb_back = NULL;
539}
540
541void halt_skas(void)
542{
543 block_signals();
544 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
545}
546
547void reboot_skas(void)
548{
549 block_signals();
550 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
551}
552
553void switch_mm_skas(struct mm_id *mm_idp)
554{
555 int err;
556
557#warning need cpu pid in switch_mm_skas
558 if(proc_mm){
559 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
560 mm_idp->u.mm_fd);
561 if(err)
562 panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
563 "errno = %d\n", errno);
564 }
565 else userspace_pid[0] = mm_idp->u.pid;
566}
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/os-Linux/skas/trap.c
index 9950a6716f..9ad5fbec45 100644
--- a/arch/um/kernel/skas/trap_user.c
+++ b/arch/um/os-Linux/skas/trap.c
@@ -1,11 +1,10 @@
1/* 1/*
2 * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h> 6#include <signal.h>
7#include <errno.h> 7#include <errno.h>
8#include "signal_user.h"
9#include "user_util.h" 8#include "user_util.h"
10#include "kern_util.h" 9#include "kern_util.h"
11#include "task.h" 10#include "task.h"
@@ -14,12 +13,13 @@
14#include "ptrace_user.h" 13#include "ptrace_user.h"
15#include "sysdep/ptrace.h" 14#include "sysdep/ptrace.h"
16#include "sysdep/ptrace_user.h" 15#include "sysdep/ptrace_user.h"
16#include "os.h"
17 17
18void sig_handler_common_skas(int sig, void *sc_ptr) 18void sig_handler_common_skas(int sig, void *sc_ptr)
19{ 19{
20 struct sigcontext *sc = sc_ptr; 20 struct sigcontext *sc = sc_ptr;
21 struct skas_regs *r; 21 struct skas_regs *r;
22 struct signal_info *info; 22 void (*handler)(int, union uml_pt_regs *);
23 int save_errno = errno; 23 int save_errno = errno;
24 int save_user; 24 int save_user;
25 25
@@ -34,17 +34,22 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
34 r = &TASK_REGS(get_current())->skas; 34 r = &TASK_REGS(get_current())->skas;
35 save_user = r->is_user; 35 save_user = r->is_user;
36 r->is_user = 0; 36 r->is_user = 0;
37 if ( sig == SIGFPE || sig == SIGSEGV || 37 if ( sig == SIGFPE || sig == SIGSEGV ||
38 sig == SIGBUS || sig == SIGILL || 38 sig == SIGBUS || sig == SIGILL ||
39 sig == SIGTRAP ) { 39 sig == SIGTRAP ) {
40 GET_FAULTINFO_FROM_SC(r->faultinfo, sc); 40 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
41 } 41 }
42 42
43 change_sig(SIGUSR1, 1); 43 change_sig(SIGUSR1, 1);
44 info = &sig_info[sig];
45 if(!info->is_irq) unblock_signals();
46 44
47 (*info->handler)(sig, (union uml_pt_regs *) r); 45 handler = sig_info[sig];
46
47 /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
48 if (sig != SIGIO && sig != SIGWINCH &&
49 sig != SIGVTALRM && sig != SIGALRM)
50 unblock_signals();
51
52 handler(sig, (union uml_pt_regs *) r);
48 53
49 errno = save_errno; 54 errno = save_errno;
50 r->is_user = save_user; 55 r->is_user = save_user;
@@ -54,25 +59,15 @@ extern int ptrace_faultinfo;
54 59
55void user_signal(int sig, union uml_pt_regs *regs, int pid) 60void user_signal(int sig, union uml_pt_regs *regs, int pid)
56{ 61{
57 struct signal_info *info; 62 void (*handler)(int, union uml_pt_regs *);
58 int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || 63 int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
59 (sig == SIGILL) || (sig == SIGTRAP)); 64 (sig == SIGILL) || (sig == SIGTRAP));
60 65
61 if (segv) 66 if (segv)
62 get_skas_faultinfo(pid, &regs->skas.faultinfo); 67 get_skas_faultinfo(pid, &regs->skas.faultinfo);
63 info = &sig_info[sig]; 68
64 (*info->handler)(sig, regs); 69 handler = sig_info[sig];
70 handler(sig, (union uml_pt_regs *) regs);
65 71
66 unblock_signals(); 72 unblock_signals();
67} 73}
68
69/*
70 * Overrides for Emacs so that we follow Linus's tabbing style.
71 * Emacs will notice this stuff at the end of the file and automatically
72 * adjust the settings for this buffer only. This must remain at the end
73 * of the file.
74 * ---------------------------------------------------------------------------
75 * Local variables:
76 * c-file-style: "linux"
77 * End:
78 */
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 37517d49c4..6c5b17ed59 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -24,13 +24,11 @@
24#include "kern_util.h" 24#include "kern_util.h"
25#include "user.h" 25#include "user.h"
26#include "signal_kern.h" 26#include "signal_kern.h"
27#include "signal_user.h"
28#include "sysdep/ptrace.h" 27#include "sysdep/ptrace.h"
29#include "sysdep/sigcontext.h" 28#include "sysdep/sigcontext.h"
30#include "irq_user.h" 29#include "irq_user.h"
31#include "ptrace_user.h" 30#include "ptrace_user.h"
32#include "mem_user.h" 31#include "mem_user.h"
33#include "time_user.h"
34#include "init.h" 32#include "init.h"
35#include "os.h" 33#include "os.h"
36#include "uml-config.h" 34#include "uml-config.h"
@@ -116,16 +114,16 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode,
116 if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { 114 if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
117 int exit_with = WEXITSTATUS(status); 115 int exit_with = WEXITSTATUS(status);
118 if (exit_with == 2) 116 if (exit_with == 2)
119 printk("check_ptrace : child exited with status 2. " 117 printf("check_ptrace : child exited with status 2. "
120 "Serious trouble happening! Try updating your " 118 "Serious trouble happening! Try updating your "
121 "host skas patch!\nDisabling SYSEMU support."); 119 "host skas patch!\nDisabling SYSEMU support.");
122 printk("check_ptrace : child exited with exitcode %d, while " 120 printf("check_ptrace : child exited with exitcode %d, while "
123 "expecting %d; status 0x%x", exit_with, 121 "expecting %d; status 0x%x", exit_with,
124 exitcode, status); 122 exitcode, status);
125 if (mustpanic) 123 if (mustpanic)
126 panic("\n"); 124 panic("\n");
127 else 125 else
128 printk("\n"); 126 printf("\n");
129 ret = -1; 127 ret = -1;
130 } 128 }
131 129
@@ -183,7 +181,7 @@ static void __init check_sysemu(void)
183 void *stack; 181 void *stack;
184 int pid, n, status, count=0; 182 int pid, n, status, count=0;
185 183
186 printk("Checking syscall emulation patch for ptrace..."); 184 printf("Checking syscall emulation patch for ptrace...");
187 sysemu_supported = 0; 185 sysemu_supported = 0;
188 pid = start_ptraced_child(&stack); 186 pid = start_ptraced_child(&stack);
189 187
@@ -207,10 +205,10 @@ static void __init check_sysemu(void)
207 goto fail_stopped; 205 goto fail_stopped;
208 206
209 sysemu_supported = 1; 207 sysemu_supported = 1;
210 printk("OK\n"); 208 printf("OK\n");
211 set_using_sysemu(!force_sysemu_disabled); 209 set_using_sysemu(!force_sysemu_disabled);
212 210
213 printk("Checking advanced syscall emulation patch for ptrace..."); 211 printf("Checking advanced syscall emulation patch for ptrace...");
214 pid = start_ptraced_child(&stack); 212 pid = start_ptraced_child(&stack);
215 213
216 if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, 214 if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
@@ -246,7 +244,7 @@ static void __init check_sysemu(void)
246 goto fail_stopped; 244 goto fail_stopped;
247 245
248 sysemu_supported = 2; 246 sysemu_supported = 2;
249 printk("OK\n"); 247 printf("OK\n");
250 248
251 if ( !force_sysemu_disabled ) 249 if ( !force_sysemu_disabled )
252 set_using_sysemu(sysemu_supported); 250 set_using_sysemu(sysemu_supported);
@@ -255,7 +253,7 @@ static void __init check_sysemu(void)
255fail: 253fail:
256 stop_ptraced_child(pid, stack, 1, 0); 254 stop_ptraced_child(pid, stack, 1, 0);
257fail_stopped: 255fail_stopped:
258 printk("missing\n"); 256 printf("missing\n");
259} 257}
260 258
261static void __init check_ptrace(void) 259static void __init check_ptrace(void)
@@ -263,7 +261,7 @@ static void __init check_ptrace(void)
263 void *stack; 261 void *stack;
264 int pid, syscall, n, status; 262 int pid, syscall, n, status;
265 263
266 printk("Checking that ptrace can change system call numbers..."); 264 printf("Checking that ptrace can change system call numbers...");
267 pid = start_ptraced_child(&stack); 265 pid = start_ptraced_child(&stack);
268 266
269 if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) 267 if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
@@ -292,7 +290,7 @@ static void __init check_ptrace(void)
292 } 290 }
293 } 291 }
294 stop_ptraced_child(pid, stack, 0, 1); 292 stop_ptraced_child(pid, stack, 0, 1);
295 printk("OK\n"); 293 printf("OK\n");
296 check_sysemu(); 294 check_sysemu();
297} 295}
298 296
@@ -472,6 +470,8 @@ int can_do_skas(void)
472 470
473int have_devanon = 0; 471int have_devanon = 0;
474 472
473/* Runs on boot kernel stack - already safe to use printk. */
474
475void check_devanon(void) 475void check_devanon(void)
476{ 476{
477 int fd; 477 int fd;
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index cf30a39bc4..6f7626775a 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -1,21 +1,128 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
1#include <stdlib.h> 7#include <stdlib.h>
8#include <unistd.h>
9#include <time.h>
2#include <sys/time.h> 10#include <sys/time.h>
11#include <signal.h>
12#include <errno.h>
13#include "user_util.h"
14#include "kern_util.h"
15#include "user.h"
16#include "process.h"
17#include "kern_constants.h"
18#include "os.h"
19
20/* XXX This really needs to be declared and initialized in a kernel file since
21 * it's in <linux/time.h>
22 */
23extern struct timespec wall_to_monotonic;
24
25static void set_interval(int timer_type)
26{
27 int usec = 1000000/hz();
28 struct itimerval interval = ((struct itimerval) { { 0, usec },
29 { 0, usec } });
30
31 if(setitimer(timer_type, &interval, NULL) == -1)
32 panic("setitimer failed - errno = %d\n", errno);
33}
34
35void enable_timer(void)
36{
37 set_interval(ITIMER_VIRTUAL);
38}
39
40void disable_timer(void)
41{
42 struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
43 if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
44 (setitimer(ITIMER_REAL, &disable, NULL) < 0))
45 printk("disnable_timer - setitimer failed, errno = %d\n",
46 errno);
47 /* If there are signals already queued, after unblocking ignore them */
48 set_handler(SIGALRM, SIG_IGN, 0, -1);
49 set_handler(SIGVTALRM, SIG_IGN, 0, -1);
50}
51
52void switch_timers(int to_real)
53{
54 struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
55 struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
56 { 0, 1000000/hz() }});
57 int old, new;
58
59 if(to_real){
60 old = ITIMER_VIRTUAL;
61 new = ITIMER_REAL;
62 }
63 else {
64 old = ITIMER_REAL;
65 new = ITIMER_VIRTUAL;
66 }
67
68 if((setitimer(old, &disable, NULL) < 0) ||
69 (setitimer(new, &enable, NULL)))
70 printk("switch_timers - setitimer failed, errno = %d\n",
71 errno);
72}
3 73
4unsigned long long os_usecs(void) 74void uml_idle_timer(void)
75{
76 if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
77 panic("Couldn't unset SIGVTALRM handler");
78
79 set_handler(SIGALRM, (__sighandler_t) alarm_handler,
80 SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
81 set_interval(ITIMER_REAL);
82}
83
84extern void ktime_get_ts(struct timespec *ts);
85#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
86
87void time_init(void)
88{
89 struct timespec now;
90
91 if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
92 panic("Couldn't set SIGVTALRM handler");
93 set_interval(ITIMER_VIRTUAL);
94
95 do_posix_clock_monotonic_gettime(&now);
96 wall_to_monotonic.tv_sec = -now.tv_sec;
97 wall_to_monotonic.tv_nsec = -now.tv_nsec;
98}
99
100unsigned long long os_nsecs(void)
5{ 101{
6 struct timeval tv; 102 struct timeval tv;
7 103
8 gettimeofday(&tv, NULL); 104 gettimeofday(&tv, NULL);
9 return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec); 105 return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000);
10} 106}
11 107
12/* 108void idle_sleep(int secs)
13 * Overrides for Emacs so that we follow Linus's tabbing style. 109{
14 * Emacs will notice this stuff at the end of the file and automatically 110 struct timespec ts;
15 * adjust the settings for this buffer only. This must remain at the end 111
16 * of the file. 112 ts.tv_sec = secs;
17 * --------------------------------------------------------------------------- 113 ts.tv_nsec = 0;
18 * Local variables: 114 nanosleep(&ts, NULL);
19 * c-file-style: "linux" 115}
20 * End: 116
21 */ 117/* XXX This partly duplicates init_irq_signals */
118
119void user_time_init(void)
120{
121 set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
122 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
123 SIGALRM, SIGUSR2, -1);
124 set_handler(SIGALRM, (__sighandler_t) alarm_handler,
125 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
126 SIGVTALRM, SIGUSR2, -1);
127 set_interval(ITIMER_VIRTUAL);
128}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
new file mode 100644
index 0000000000..a9f6b26f98
--- /dev/null
+++ b/arch/um/os-Linux/trap.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <signal.h>
8#include <setjmp.h>
9#include "kern_util.h"
10#include "user_util.h"
11#include "os.h"
12#include "mode.h"
13#include "longjmp.h"
14
15void usr2_handler(int sig, union uml_pt_regs *regs)
16{
17 CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
18}
19
20void (*sig_info[NSIG])(int, union uml_pt_regs *);
21
22void os_fill_handlinfo(struct kern_handlers h)
23{
24 sig_info[SIGTRAP] = h.relay_signal;
25 sig_info[SIGFPE] = h.relay_signal;
26 sig_info[SIGILL] = h.relay_signal;
27 sig_info[SIGWINCH] = h.winch;
28 sig_info[SIGBUS] = h.bus_handler;
29 sig_info[SIGSEGV] = h.page_fault;
30 sig_info[SIGIO] = h.sigio_handler;
31 sig_info[SIGVTALRM] = h.timer_handler;
32 sig_info[SIGALRM] = h.timer_handler;
33 sig_info[SIGUSR2] = usr2_handler;
34}
35
36void do_longjmp(void *b, int val)
37{
38 sigjmp_buf *buf = b;
39
40 UML_SIGLONGJMP(buf, val);
41}
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index a6db887793..919d19f115 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -23,12 +23,10 @@
23#include "kern_util.h" 23#include "kern_util.h"
24#include "user.h" 24#include "user.h"
25#include "signal_kern.h" 25#include "signal_kern.h"
26#include "signal_user.h"
27#include "sysdep/ptrace.h" 26#include "sysdep/ptrace.h"
28#include "sysdep/sigcontext.h" 27#include "sysdep/sigcontext.h"
29#include "irq_user.h" 28#include "irq_user.h"
30#include "ptrace_user.h" 29#include "ptrace_user.h"
31#include "time_user.h"
32#include "init.h" 30#include "init.h"
33#include "os.h" 31#include "os.h"
34#include "uml-config.h" 32#include "uml-config.h"
@@ -50,6 +48,68 @@ int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
50 return(0); 48 return(0);
51} 49}
52 50
51void kill_child_dead(int pid)
52{
53 kill(pid, SIGKILL);
54 kill(pid, SIGCONT);
55 do {
56 int n;
57 CATCH_EINTR(n = waitpid(pid, NULL, 0));
58 if (n > 0)
59 kill(pid, SIGCONT);
60 else
61 break;
62 } while(1);
63}
64
65void stop(void)
66{
67 while(1) sleep(1000000);
68}
69
70int wait_for_stop(int pid, int sig, int cont_type, void *relay)
71{
72 sigset_t *relay_signals = relay;
73 int status, ret;
74
75 while(1){
76 CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
77 if((ret < 0) ||
78 !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
79 if(ret < 0){
80 printk("wait failed, errno = %d\n",
81 errno);
82 }
83 else if(WIFEXITED(status))
84 printk("process %d exited with status %d\n",
85 pid, WEXITSTATUS(status));
86 else if(WIFSIGNALED(status))
87 printk("process %d exited with signal %d\n",
88 pid, WTERMSIG(status));
89 else if((WSTOPSIG(status) == SIGVTALRM) ||
90 (WSTOPSIG(status) == SIGALRM) ||
91 (WSTOPSIG(status) == SIGIO) ||
92 (WSTOPSIG(status) == SIGPROF) ||
93 (WSTOPSIG(status) == SIGCHLD) ||
94 (WSTOPSIG(status) == SIGWINCH) ||
95 (WSTOPSIG(status) == SIGINT)){
96 ptrace(cont_type, pid, 0, WSTOPSIG(status));
97 continue;
98 }
99 else if((relay_signals != NULL) &&
100 sigismember(relay_signals, WSTOPSIG(status))){
101 ptrace(cont_type, pid, 0, WSTOPSIG(status));
102 continue;
103 }
104 else printk("process %d stopped with signal %d\n",
105 pid, WSTOPSIG(status));
106 panic("wait_for_stop failed to wait for %d to stop "
107 "with %d\n", pid, sig);
108 }
109 return(status);
110 }
111}
112
53/* 113/*
54 *------------------------- 114 *-------------------------
55 * only for tt mode (will be deleted in future...) 115 * only for tt mode (will be deleted in future...)
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 38d710158c..166fb66995 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -6,6 +6,7 @@
6 6
7#include <setjmp.h> 7#include <setjmp.h>
8#include <string.h> 8#include <string.h>
9#include "longjmp.h"
9 10
10unsigned long __do_user_copy(void *to, const void *from, int n, 11unsigned long __do_user_copy(void *to, const void *from, int n,
11 void **fault_addr, void **fault_catcher, 12 void **fault_addr, void **fault_catcher,
@@ -13,10 +14,11 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
13 int n), int *faulted_out) 14 int n), int *faulted_out)
14{ 15{
15 unsigned long *faddrp = (unsigned long *) fault_addr, ret; 16 unsigned long *faddrp = (unsigned long *) fault_addr, ret;
17 int enable;
16 18
17 sigjmp_buf jbuf; 19 sigjmp_buf jbuf;
18 *fault_catcher = &jbuf; 20 *fault_catcher = &jbuf;
19 if(sigsetjmp(jbuf, 1) == 0){ 21 if(UML_SIGSETJMP(&jbuf, enable) == 0){
20 (*op)(to, from, n); 22 (*op)(to, from, n);
21 ret = 0; 23 ret = 0;
22 *faulted_out = 0; 24 *faulted_out = 0;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
new file mode 100644
index 0000000000..ecf107ae5a
--- /dev/null
+++ b/arch/um/os-Linux/umid.c
@@ -0,0 +1,335 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <string.h>
5#include <errno.h>
6#include <signal.h>
7#include <dirent.h>
8#include <sys/fcntl.h>
9#include <sys/stat.h>
10#include <sys/param.h>
11#include "init.h"
12#include "os.h"
13#include "user.h"
14#include "mode.h"
15
16#define UML_DIR "~/.uml/"
17
18#define UMID_LEN 64
19
20/* Changed by set_umid, which is run early in boot */
21char umid[UMID_LEN] = { 0 };
22
23/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
24static char *uml_dir = UML_DIR;
25
26static int __init make_uml_dir(void)
27{
28 char dir[512] = { '\0' };
29 int len, err;
30
31 if(*uml_dir == '~'){
32 char *home = getenv("HOME");
33
34 err = -ENOENT;
35 if(home == NULL){
36 printk("make_uml_dir : no value in environment for "
37 "$HOME\n");
38 goto err;
39 }
40 strlcpy(dir, home, sizeof(dir));
41 uml_dir++;
42 }
43 strlcat(dir, uml_dir, sizeof(dir));
44 len = strlen(dir);
45 if (len > 0 && dir[len - 1] != '/')
46 strlcat(dir, "/", sizeof(dir));
47
48 err = -ENOMEM;
49 uml_dir = malloc(strlen(dir) + 1);
50 if (uml_dir == NULL) {
51 printf("make_uml_dir : malloc failed, errno = %d\n", errno);
52 goto err;
53 }
54 strcpy(uml_dir, dir);
55
56 if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
57 printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno));
58 err = -errno;
59 goto err_free;
60 }
61 return 0;
62
63err_free:
64 free(uml_dir);
65err:
66 uml_dir = NULL;
67 return err;
68}
69
70static int actually_do_remove(char *dir)
71{
72 DIR *directory;
73 struct dirent *ent;
74 int len;
75 char file[256];
76
77 directory = opendir(dir);
78 if(directory == NULL)
79 return -errno;
80
81 while((ent = readdir(directory)) != NULL){
82 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
83 continue;
84 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
85 if(len > sizeof(file))
86 return -E2BIG;
87
88 sprintf(file, "%s/%s", dir, ent->d_name);
89 if(unlink(file) < 0)
90 return -errno;
91 }
92 if(rmdir(dir) < 0)
93 return -errno;
94
95 return 0;
96}
97
98/* This says that there isn't already a user of the specified directory even if
99 * there are errors during the checking. This is because if these errors
100 * happen, the directory is unusable by the pre-existing UML, so we might as
101 * well take it over. This could happen either by
102 * the existing UML somehow corrupting its umid directory
103 * something other than UML sticking stuff in the directory
104 * this boot racing with a shutdown of the other UML
105 * In any of these cases, the directory isn't useful for anything else.
106 */
107
108static int not_dead_yet(char *dir)
109{
110 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
111 char pid[sizeof("nnnnn\0")], *end;
112 int dead, fd, p, n, err;
113
114 n = snprintf(file, sizeof(file), "%s/pid", dir);
115 if(n >= sizeof(file)){
116 printk("not_dead_yet - pid filename too long\n");
117 err = -E2BIG;
118 goto out;
119 }
120
121 dead = 0;
122 fd = open(file, O_RDONLY);
123 if(fd < 0){
124 if(fd != -ENOENT){
125 printk("not_dead_yet : couldn't open pid file '%s', "
126 "err = %d\n", file, -fd);
127 }
128 goto out;
129 }
130
131 err = 0;
132 n = read(fd, pid, sizeof(pid));
133 if(n <= 0){
134 printk("not_dead_yet : couldn't read pid file '%s', "
135 "err = %d\n", file, -n);
136 goto out_close;
137 }
138
139 p = strtoul(pid, &end, 0);
140 if(end == pid){
141 printk("not_dead_yet : couldn't parse pid file '%s', "
142 "errno = %d\n", file, errno);
143 goto out_close;
144 }
145
146 if((kill(p, 0) == 0) || (errno != ESRCH))
147 return 1;
148
149 err = actually_do_remove(dir);
150 if(err)
151 printk("not_dead_yet - actually_do_remove failed with "
152 "err = %d\n", err);
153
154 return err;
155
156 out_close:
157 close(fd);
158 out:
159 return 0;
160}
161
162static void __init create_pid_file(void)
163{
164 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
165 char pid[sizeof("nnnnn\0")];
166 int fd, n;
167
168 if(umid_file_name("pid", file, sizeof(file)))
169 return;
170
171 fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
172 if(fd < 0){
173 printk("Open of machine pid file \"%s\" failed: %s\n",
174 file, strerror(-fd));
175 return;
176 }
177
178 snprintf(pid, sizeof(pid), "%d\n", getpid());
179 n = write(fd, pid, strlen(pid));
180 if(n != strlen(pid))
181 printk("Write of pid file failed - err = %d\n", -n);
182
183 close(fd);
184}
185
186int __init set_umid(char *name)
187{
188 if(strlen(name) > UMID_LEN - 1)
189 return -E2BIG;
190
191 strlcpy(umid, name, sizeof(umid));
192
193 return 0;
194}
195
196static int umid_setup = 0;
197
198int __init make_umid(void)
199{
200 int fd, err;
201 char tmp[256];
202
203 if(umid_setup)
204 return 0;
205
206 make_uml_dir();
207
208 if(*umid == '\0'){
209 strlcpy(tmp, uml_dir, sizeof(tmp));
210 strlcat(tmp, "XXXXXX", sizeof(tmp));
211 fd = mkstemp(tmp);
212 if(fd < 0){
213 printk("make_umid - mkstemp(%s) failed: %s\n",
214 tmp, strerror(errno));
215 err = -errno;
216 goto err;
217 }
218
219 close(fd);
220
221 set_umid(&tmp[strlen(uml_dir)]);
222
223 /* There's a nice tiny little race between this unlink and
224 * the mkdir below. It'd be nice if there were a mkstemp
225 * for directories.
226 */
227 if(unlink(tmp)){
228 err = -errno;
229 goto err;
230 }
231 }
232
233 snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid);
234 err = mkdir(tmp, 0777);
235 if(err < 0){
236 err = -errno;
237 if(errno != EEXIST)
238 goto err;
239
240 if(not_dead_yet(tmp) < 0)
241 goto err;
242
243 err = mkdir(tmp, 0777);
244 }
245 if(err < 0){
246 printk("Failed to create '%s' - err = %d\n", umid, err);
247 goto err_rmdir;
248 }
249
250 umid_setup = 1;
251
252 create_pid_file();
253
254 return 0;
255
256 err_rmdir:
257 rmdir(tmp);
258 err:
259 return err;
260}
261
262static int __init make_umid_init(void)
263{
264 make_umid();
265
266 return 0;
267}
268
269__initcall(make_umid_init);
270
271int __init umid_file_name(char *name, char *buf, int len)
272{
273 int n, err;
274
275 err = make_umid();
276 if(err)
277 return err;
278
279 n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name);
280 if(n >= len){
281 printk("umid_file_name : buffer too short\n");
282 return -E2BIG;
283 }
284
285 return 0;
286}
287
288char *get_umid(void)
289{
290 return umid;
291}
292
293static int __init set_uml_dir(char *name, int *add)
294{
295 if(*name == '\0'){
296 printf("uml_dir can't be an empty string\n");
297 return 0;
298 }
299
300 if(name[strlen(name) - 1] == '/'){
301 uml_dir = name;
302 return 0;
303 }
304
305 uml_dir = malloc(strlen(name) + 2);
306 if(uml_dir == NULL){
307 printf("Failed to malloc uml_dir - error = %d\n", errno);
308
309 /* Return 0 here because do_initcalls doesn't look at
310 * the return value.
311 */
312 return 0;
313 }
314 sprintf(uml_dir, "%s/", name);
315
316 return 0;
317}
318
319__uml_setup("uml_dir=", set_uml_dir,
320"uml_dir=<directory>\n"
321" The location to place the pid and umid files.\n\n"
322);
323
324static void remove_umid_dir(void)
325{
326 char dir[strlen(uml_dir) + UMID_LEN + 1], err;
327
328 sprintf(dir, "%s%s", uml_dir, umid);
329 err = actually_do_remove(dir);
330 if(err)
331 printf("remove_umid_dir - actually_do_remove failed with "
332 "err = %d\n", err);
333}
334
335__uml_exitcall(remove_umid_dir);
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 56d3f87092..8da6ab3115 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -34,6 +34,11 @@ EXPORT_SYMBOL(strstr);
34 int sym(void); \ 34 int sym(void); \
35 EXPORT_SYMBOL(sym); 35 EXPORT_SYMBOL(sym);
36 36
37extern void readdir64(void) __attribute__((weak));
38EXPORT_SYMBOL(readdir64);
39extern void truncate64(void) __attribute__((weak));
40EXPORT_SYMBOL(truncate64);
41
37#ifdef SUBARCH_i386 42#ifdef SUBARCH_i386
38EXPORT_SYMBOL(vsyscall_ehdr); 43EXPORT_SYMBOL(vsyscall_ehdr);
39EXPORT_SYMBOL(vsyscall_end); 44EXPORT_SYMBOL(vsyscall_end);
diff --git a/arch/um/kernel/user_util.c b/arch/um/os-Linux/util.c
index 4c231161f2..e32065e2fd 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/os-Linux/util.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -29,17 +29,14 @@
29#include "init.h" 29#include "init.h"
30#include "ptrace_user.h" 30#include "ptrace_user.h"
31#include "uml-config.h" 31#include "uml-config.h"
32 32#include "os.h"
33void stop(void) 33#include "longjmp.h"
34{
35 while(1) sleep(1000000);
36}
37 34
38void stack_protections(unsigned long address) 35void stack_protections(unsigned long address)
39{ 36{
40 int prot = PROT_READ | PROT_WRITE | PROT_EXEC; 37 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
41 38
42 if(mprotect((void *) address, page_size(), prot) < 0) 39 if(mprotect((void *) address, page_size(), prot) < 0)
43 panic("protecting stack failed, errno = %d", errno); 40 panic("protecting stack failed, errno = %d", errno);
44} 41}
45 42
@@ -59,49 +56,6 @@ void task_protections(unsigned long address)
59 panic("protecting stack failed, errno = %d", errno); 56 panic("protecting stack failed, errno = %d", errno);
60} 57}
61 58
62int wait_for_stop(int pid, int sig, int cont_type, void *relay)
63{
64 sigset_t *relay_signals = relay;
65 int status, ret;
66
67 while(1){
68 CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
69 if((ret < 0) ||
70 !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
71 if(ret < 0){
72 printk("wait failed, errno = %d\n",
73 errno);
74 }
75 else if(WIFEXITED(status))
76 printk("process %d exited with status %d\n",
77 pid, WEXITSTATUS(status));
78 else if(WIFSIGNALED(status))
79 printk("process %d exited with signal %d\n",
80 pid, WTERMSIG(status));
81 else if((WSTOPSIG(status) == SIGVTALRM) ||
82 (WSTOPSIG(status) == SIGALRM) ||
83 (WSTOPSIG(status) == SIGIO) ||
84 (WSTOPSIG(status) == SIGPROF) ||
85 (WSTOPSIG(status) == SIGCHLD) ||
86 (WSTOPSIG(status) == SIGWINCH) ||
87 (WSTOPSIG(status) == SIGINT)){
88 ptrace(cont_type, pid, 0, WSTOPSIG(status));
89 continue;
90 }
91 else if((relay_signals != NULL) &&
92 sigismember(relay_signals, WSTOPSIG(status))){
93 ptrace(cont_type, pid, 0, WSTOPSIG(status));
94 continue;
95 }
96 else printk("process %d stopped with signal %d\n",
97 pid, WSTOPSIG(status));
98 panic("wait_for_stop failed to wait for %d to stop "
99 "with %d\n", pid, sig);
100 }
101 return(status);
102 }
103}
104
105int raw(int fd) 59int raw(int fd)
106{ 60{
107 struct termios tt; 61 struct termios tt;
@@ -113,7 +67,7 @@ int raw(int fd)
113 67
114 cfmakeraw(&tt); 68 cfmakeraw(&tt);
115 69
116 CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); 70 CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
117 if(err < 0) 71 if(err < 0)
118 return -errno; 72 return -errno;
119 73
@@ -149,7 +103,7 @@ void setup_hostinfo(void)
149 103
150int setjmp_wrapper(void (*proc)(void *, void *), ...) 104int setjmp_wrapper(void (*proc)(void *, void *), ...)
151{ 105{
152 va_list args; 106 va_list args;
153 sigjmp_buf buf; 107 sigjmp_buf buf;
154 int n; 108 int n;
155 109
@@ -161,14 +115,3 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
161 va_end(args); 115 va_end(args);
162 return(n); 116 return(n);
163} 117}
164
165/*
166 * Overrides for Emacs so that we follow Linus's tabbing style.
167 * Emacs will notice this stuff at the end of the file and automatically
168 * adjust the settings for this buffer only. This must remain at the end
169 * of the file.
170 * ---------------------------------------------------------------------------
171 * Local variables:
172 * c-file-style: "linux"
173 * End:
174 */
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index b3fbf12570..2e41cabd3d 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -21,11 +21,6 @@ define unprofile
21endef 21endef
22 22
23 23
24# The stubs and unmap.o can't try to call mcount or update basic block data
25define unprofile
26 $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
27endef
28
29# cmd_make_link checks to see if the $(foo-dir) variable starts with a /. If 24# cmd_make_link checks to see if the $(foo-dir) variable starts with a /. If
30# so, it's considered to be a path relative to $(srcdir) rather than 25# so, it's considered to be a path relative to $(srcdir) rather than
31# $(srcdir)/arch/$(SUBARCH). This is because x86_64 wants to get ldt.c from 26# $(srcdir)/arch/$(SUBARCH). This is because x86_64 wants to get ldt.c from
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 6dfeb70f69..f5fd5b0156 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,11 +1,13 @@
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 stub.o stub_segv.o \ 2 ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \
3 syscalls.o sysrq.o sys_call_table.o 3 sys_call_table.o
4
5obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
4 6
5obj-$(CONFIG_HIGHMEM) += highmem.o 7obj-$(CONFIG_HIGHMEM) += highmem.o
6obj-$(CONFIG_MODULES) += module.o 8obj-$(CONFIG_MODULES) += module.o
7 9
8USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o 10USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o stub_segv.o
9 11
10SYMLINKS = bitops.c semaphore.c highmem.c module.c 12SYMLINKS = bitops.c semaphore.c highmem.c module.c
11 13
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 6360f1c958..0cdfd4481d 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -16,6 +16,8 @@
16#include "choose-mode.h" 16#include "choose-mode.h"
17#include "kern.h" 17#include "kern.h"
18#include "mode_kern.h" 18#include "mode_kern.h"
19#include "proc_mm.h"
20#include "os.h"
19 21
20extern int modify_ldt(int func, void *ptr, unsigned long bytecount); 22extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
21 23
@@ -228,7 +230,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
228 size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; 230 size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
229 if(size > bytecount) 231 if(size > bytecount)
230 size = bytecount; 232 size = bytecount;
231 if(copy_to_user(ptr, ldt->entries, size)) 233 if(copy_to_user(ptr, ldt->u.entries, size))
232 err = -EFAULT; 234 err = -EFAULT;
233 bytecount -= size; 235 bytecount -= size;
234 ptr += size; 236 ptr += size;
@@ -239,7 +241,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
239 size = PAGE_SIZE; 241 size = PAGE_SIZE;
240 if(size > bytecount) 242 if(size > bytecount)
241 size = bytecount; 243 size = bytecount;
242 if(copy_to_user(ptr, ldt->pages[i], size)){ 244 if(copy_to_user(ptr, ldt->u.pages[i], size)){
243 err = -EFAULT; 245 err = -EFAULT;
244 break; 246 break;
245 } 247 }
@@ -321,10 +323,11 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
321 i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; 323 i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
322 i++){ 324 i++){
323 if(i == 0) 325 if(i == 0)
324 memcpy(&entry0, ldt->entries, sizeof(entry0)); 326 memcpy(&entry0, ldt->u.entries,
325 ldt->pages[i] = (struct ldt_entry *) 327 sizeof(entry0));
326 __get_free_page(GFP_KERNEL|__GFP_ZERO); 328 ldt->u.pages[i] = (struct ldt_entry *)
327 if(!ldt->pages[i]){ 329 __get_free_page(GFP_KERNEL|__GFP_ZERO);
330 if(!ldt->u.pages[i]){
328 err = -ENOMEM; 331 err = -ENOMEM;
329 /* Undo the change in host */ 332 /* Undo the change in host */
330 memset(&ldt_info, 0, sizeof(ldt_info)); 333 memset(&ldt_info, 0, sizeof(ldt_info));
@@ -332,8 +335,9 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
332 goto out_unlock; 335 goto out_unlock;
333 } 336 }
334 if(i == 0) { 337 if(i == 0) {
335 memcpy(ldt->pages[0], &entry0, sizeof(entry0)); 338 memcpy(ldt->u.pages[0], &entry0,
336 memcpy(ldt->pages[0]+1, ldt->entries+1, 339 sizeof(entry0));
340 memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
337 sizeof(entry0)*(LDT_DIRECT_ENTRIES-1)); 341 sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
338 } 342 }
339 ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; 343 ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
@@ -343,9 +347,9 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
343 ldt->entry_count = ldt_info.entry_number + 1; 347 ldt->entry_count = ldt_info.entry_number + 1;
344 348
345 if(ldt->entry_count <= LDT_DIRECT_ENTRIES) 349 if(ldt->entry_count <= LDT_DIRECT_ENTRIES)
346 ldt_p = ldt->entries + ldt_info.entry_number; 350 ldt_p = ldt->u.entries + ldt_info.entry_number;
347 else 351 else
348 ldt_p = ldt->pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + 352 ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
349 ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; 353 ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
350 354
351 if(ldt_info.base_addr == 0 && ldt_info.limit == 0 && 355 if(ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
@@ -454,13 +458,14 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
454 int i; 458 int i;
455 long page, err=0; 459 long page, err=0;
456 void *addr = NULL; 460 void *addr = NULL;
461 struct proc_mm_op copy;
457 462
458 memset(&desc, 0, sizeof(desc));
459 463
460 if(!ptrace_ldt) 464 if(!ptrace_ldt)
461 init_MUTEX(&new_mm->ldt.semaphore); 465 init_MUTEX(&new_mm->ldt.semaphore);
462 466
463 if(!from_mm){ 467 if(!from_mm){
468 memset(&desc, 0, sizeof(desc));
464 /* 469 /*
465 * We have to initialize a clean ldt. 470 * We have to initialize a clean ldt.
466 */ 471 */
@@ -492,8 +497,26 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
492 } 497 }
493 } 498 }
494 new_mm->ldt.entry_count = 0; 499 new_mm->ldt.entry_count = 0;
500
501 goto out;
495 } 502 }
496 else if (!ptrace_ldt) { 503
504 if(proc_mm){
505 /* We have a valid from_mm, so we now have to copy the LDT of
506 * from_mm to new_mm, because using proc_mm an new mm with
507 * an empty/default LDT was created in new_mm()
508 */
509 copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
510 .u =
511 { .copy_segments =
512 from_mm->id.u.mm_fd } } );
513 i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
514 if(i != sizeof(copy))
515 printk("new_mm : /proc/mm copy_segments failed, "
516 "err = %d\n", -i);
517 }
518
519 if(!ptrace_ldt) {
497 /* Our local LDT is used to supply the data for 520 /* Our local LDT is used to supply the data for
498 * modify_ldt(READLDT), if PTRACE_LDT isn't available, 521 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
499 * i.e., we have to use the stub for modify_ldt, which 522 * i.e., we have to use the stub for modify_ldt, which
@@ -501,8 +524,8 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
501 */ 524 */
502 down(&from_mm->ldt.semaphore); 525 down(&from_mm->ldt.semaphore);
503 if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){ 526 if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){
504 memcpy(new_mm->ldt.entries, from_mm->ldt.entries, 527 memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
505 sizeof(new_mm->ldt.entries)); 528 sizeof(new_mm->ldt.u.entries));
506 } 529 }
507 else{ 530 else{
508 i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; 531 i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
@@ -512,15 +535,17 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
512 err = -ENOMEM; 535 err = -ENOMEM;
513 break; 536 break;
514 } 537 }
515 new_mm->ldt.pages[i] = (struct ldt_entry*)page; 538 new_mm->ldt.u.pages[i] =
516 memcpy(new_mm->ldt.pages[i], 539 (struct ldt_entry *) page;
517 from_mm->ldt.pages[i], PAGE_SIZE); 540 memcpy(new_mm->ldt.u.pages[i],
541 from_mm->ldt.u.pages[i], PAGE_SIZE);
518 } 542 }
519 } 543 }
520 new_mm->ldt.entry_count = from_mm->ldt.entry_count; 544 new_mm->ldt.entry_count = from_mm->ldt.entry_count;
521 up(&from_mm->ldt.semaphore); 545 up(&from_mm->ldt.semaphore);
522 } 546 }
523 547
548 out:
524 return err; 549 return err;
525} 550}
526 551
@@ -532,7 +557,7 @@ void free_ldt(struct mmu_context_skas * mm)
532 if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){ 557 if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){
533 i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; 558 i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
534 while(i-- > 0){ 559 while(i-- > 0){
535 free_page((long )mm->ldt.pages[i]); 560 free_page((long )mm->ldt.u.pages[i]);
536 } 561 }
537 } 562 }
538 mm->ldt.entry_count = 0; 563 mm->ldt.entry_count = 0;
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 16bc19928b..7cd1a82dc8 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -10,7 +10,6 @@
10#include "asm/uaccess.h" 10#include "asm/uaccess.h"
11#include "asm/unistd.h" 11#include "asm/unistd.h"
12#include "frame_kern.h" 12#include "frame_kern.h"
13#include "signal_user.h"
14#include "sigcontext.h" 13#include "sigcontext.h"
15#include "registers.h" 14#include "registers.h"
16#include "mode.h" 15#include "mode.h"
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index 1e88b275ed..a37f672ec9 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -3,9 +3,11 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <asm/signal.h> 6#include <signal.h>
7#include <sys/select.h> /* The only way I can see to get sigset_t */
7#include <asm/unistd.h> 8#include <asm/unistd.h>
8#include "uml-config.h" 9#include "uml-config.h"
10#include "sysdep/stub.h"
9#include "sysdep/sigcontext.h" 11#include "sysdep/sigcontext.h"
10#include "sysdep/faultinfo.h" 12#include "sysdep/faultinfo.h"
11 13
@@ -13,13 +15,14 @@ void __attribute__ ((__section__ (".__syscall_stub")))
13stub_segv_handler(int sig) 15stub_segv_handler(int sig)
14{ 16{
15 struct sigcontext *sc = (struct sigcontext *) (&sig + 1); 17 struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
18 int pid;
16 19
17 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), 20 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
18 sc); 21 sc);
19 22
20 __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid)); 23 pid = stub_syscall0(__NR_getpid);
21 __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;" 24 stub_syscall2(__NR_kill, pid, SIGUSR1);
22 "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1)); 25
23 /* Load pointer to sigcontext into esp, since we need to leave 26 /* Load pointer to sigcontext into esp, since we need to leave
24 * the stack in its original form when we do the sigreturn here, by 27 * the stack in its original form when we do the sigreturn here, by
25 * hand. 28 * hand.
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index ea977df395..a351091fbd 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -6,13 +6,14 @@
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 ldt.o mem.o memcpy.o \ 8lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \
9 ptrace.o ptrace_user.o sigcontext.o signal.o stub.o \ 9 ptrace.o ptrace_user.o sigcontext.o signal.o syscalls.o \
10 stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o 10 syscall_table.o sysrq.o thunk.o
11lib-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
11 12
12obj-y := ksyms.o 13obj-y := ksyms.o
13obj-$(CONFIG_MODULES) += module.o um_module.o 14obj-$(CONFIG_MODULES) += module.o um_module.o
14 15
15USER_OBJS := ptrace_user.o sigcontext.o 16USER_OBJS := ptrace_user.o sigcontext.o stub_segv.o
16 17
17SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \ 18SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \
18 thunk.S module.c 19 thunk.S module.c
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index d1e53bdf2e..a270995331 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -3,14 +3,14 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <asm/signal.h> 6#include <stddef.h>
7#include <signal.h>
7#include <linux/compiler.h> 8#include <linux/compiler.h>
8#include <asm/unistd.h> 9#include <asm/unistd.h>
9#include <asm/ucontext.h>
10#include "uml-config.h" 10#include "uml-config.h"
11#include "sysdep/sigcontext.h" 11#include "sysdep/sigcontext.h"
12#include "sysdep/faultinfo.h" 12#include "sysdep/faultinfo.h"
13#include <stddef.h> 13#include "sysdep/stub.h"
14 14
15/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition 15/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition
16 * in the libc headers anywhere. 16 * in the libc headers anywhere.
@@ -31,21 +31,21 @@ void __attribute__ ((__section__ (".__syscall_stub")))
31stub_segv_handler(int sig) 31stub_segv_handler(int sig)
32{ 32{
33 struct ucontext *uc; 33 struct ucontext *uc;
34 int pid;
34 35
35 __asm__("movq %%rdx, %0" : "=g" (uc) :); 36 __asm__("movq %%rdx, %0" : "=g" (uc) :);
36 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), 37 GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
37 &uc->uc_mcontext); 38 &uc->uc_mcontext);
38 39
39 __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); 40 pid = stub_syscall0(__NR_getpid);
40 __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" 41 stub_syscall2(__NR_kill, pid, SIGUSR1);
41 "syscall": : "g" (__NR_kill), "g" (SIGUSR1) : 42
42 "%rdi", "%rax", "%rsi");
43 /* sys_sigreturn expects that the stack pointer will be 8 bytes into 43 /* sys_sigreturn expects that the stack pointer will be 8 bytes into
44 * the signal frame. So, we use the ucontext pointer, which we know 44 * the signal frame. So, we use the ucontext pointer, which we know
45 * already, to get the signal frame pointer, and add 8 to that. 45 * already, to get the signal frame pointer, and add 8 to that.
46 */ 46 */
47 __asm__("movq %0, %%rsp": : 47 __asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
48 "g" ((unsigned long) container_of(uc, struct rt_sigframe, 48 "g" ((unsigned long) container_of(uc, struct rt_sigframe,
49 uc) + 8)); 49 uc) + 8),
50 __asm__("movq %0, %%rax ; syscall" : : "g" (__NR_rt_sigreturn)); 50 "g" (__NR_rt_sigreturn));
51} 51}