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