aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorWim Van Sebroeck <wim@iguana.be>2007-05-11 15:03:13 -0400
committerWim Van Sebroeck <wim@iguana.be>2007-05-11 15:03:13 -0400
commit5c34202b8bf942da411b6599668a76b07449bbfd (patch)
tree5719c361321eaddc8e4f1b0c8a7994f0e9a6fdd3 /arch/um
parent0d4804b31f91cfbcff6d62af0bc09a893a1c8ae0 (diff)
parent1f8a6b658a943b4f04a1fc7b3a420360202c86cd (diff)
Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig19
-rw-r--r--arch/um/Kconfig.scsi58
-rw-r--r--arch/um/defconfig3
-rw-r--r--arch/um/drivers/chan_kern.c1
-rw-r--r--arch/um/drivers/chan_user.c14
-rw-r--r--arch/um/drivers/cow_sys.h18
-rw-r--r--arch/um/drivers/daemon_user.c31
-rw-r--r--arch/um/drivers/fd.c1
-rw-r--r--arch/um/drivers/harddog_user.c1
-rw-r--r--arch/um/drivers/line.c1
-rw-r--r--arch/um/drivers/mcast_user.c16
-rw-r--r--arch/um/drivers/mconsole_kern.c1
-rw-r--r--arch/um/drivers/mconsole_user.c1
-rw-r--r--arch/um/drivers/mmapper_kern.c1
-rw-r--r--arch/um/drivers/net_kern.c165
-rw-r--r--arch/um/drivers/net_user.c4
-rw-r--r--arch/um/drivers/pcap_kern.c27
-rw-r--r--arch/um/drivers/pcap_user.c61
-rw-r--r--arch/um/drivers/port_user.c1
-rw-r--r--arch/um/drivers/pty.c2
-rw-r--r--arch/um/drivers/slip_user.c7
-rw-r--r--arch/um/drivers/slirp_user.c4
-rw-r--r--arch/um/drivers/ssl.c5
-rw-r--r--arch/um/drivers/stdio_console.c5
-rw-r--r--arch/um/drivers/tty.c1
-rw-r--r--arch/um/drivers/ubd_kern.c351
-rw-r--r--arch/um/drivers/ubd_user.c16
-rw-r--r--arch/um/drivers/xterm.c1
-rw-r--r--arch/um/include/arch.h15
-rw-r--r--arch/um/include/as-layout.h35
-rw-r--r--arch/um/include/common-offsets.h4
-rw-r--r--arch/um/include/kern_util.h16
-rw-r--r--arch/um/include/net_kern.h2
-rw-r--r--arch/um/include/net_user.h2
-rw-r--r--arch/um/include/os.h18
-rw-r--r--arch/um/include/skas/mode_kern_skas.h2
-rw-r--r--arch/um/include/sysdep-i386/archsetjmp.h2
-rw-r--r--arch/um/include/sysdep-x86_64/archsetjmp.h2
-rw-r--r--arch/um/include/tlb.h8
-rw-r--r--arch/um/include/tt/uaccess-tt.h2
-rw-r--r--arch/um/include/um_malloc.h1
-rw-r--r--arch/um/include/user.h29
-rw-r--r--arch/um/include/user_util.h69
-rw-r--r--arch/um/kernel/dyn.lds.S2
-rw-r--r--arch/um/kernel/exec.c2
-rw-r--r--arch/um/kernel/init_task.c31
-rw-r--r--arch/um/kernel/initrd.c33
-rw-r--r--arch/um/kernel/irq.c131
-rw-r--r--arch/um/kernel/ksyms.c2
-rw-r--r--arch/um/kernel/mem.c4
-rw-r--r--arch/um/kernel/physmem.c230
-rw-r--r--arch/um/kernel/process.c125
-rw-r--r--arch/um/kernel/reboot.c1
-rw-r--r--arch/um/kernel/signal.c1
-rw-r--r--arch/um/kernel/skas/exec.c12
-rw-r--r--arch/um/kernel/skas/process.c15
-rw-r--r--arch/um/kernel/skas/tlb.c87
-rw-r--r--arch/um/kernel/smp.c28
-rw-r--r--arch/um/kernel/syscall.c1
-rw-r--r--arch/um/kernel/sysrq.c1
-rw-r--r--arch/um/kernel/time.c19
-rw-r--r--arch/um/kernel/tlb.c226
-rw-r--r--arch/um/kernel/trap.c50
-rw-r--r--arch/um/kernel/tt/exec_kern.c3
-rw-r--r--arch/um/kernel/tt/exec_user.c1
-rw-r--r--arch/um/kernel/tt/gdb.c3
-rw-r--r--arch/um/kernel/tt/include/mode_kern-tt.h52
-rw-r--r--arch/um/kernel/tt/mem.c1
-rw-r--r--arch/um/kernel/tt/mem_user.c1
-rw-r--r--arch/um/kernel/tt/process_kern.c6
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c6
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c1
-rw-r--r--arch/um/kernel/tt/syscall_user.c1
-rw-r--r--arch/um/kernel/tt/tlb.c1
-rw-r--r--arch/um/kernel/tt/tracer.c1
-rw-r--r--arch/um/kernel/tt/trap_user.c1
-rw-r--r--arch/um/kernel/tt/uaccess_user.c1
-rw-r--r--arch/um/kernel/um_arch.c86
-rw-r--r--arch/um/kernel/uml.lds.S2
-rw-r--r--arch/um/os-Linux/aio.c61
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c66
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c44
-rw-r--r--arch/um/os-Linux/file.c47
-rw-r--r--arch/um/os-Linux/helper.c31
-rw-r--r--arch/um/os-Linux/irq.c1
-rw-r--r--arch/um/os-Linux/main.c23
-rw-r--r--arch/um/os-Linux/mem.c15
-rw-r--r--arch/um/os-Linux/process.c47
-rw-r--r--arch/um/os-Linux/sigio.c164
-rw-r--r--arch/um/os-Linux/signal.c51
-rw-r--r--arch/um/os-Linux/skas/mem.c77
-rw-r--r--arch/um/os-Linux/skas/process.c205
-rw-r--r--arch/um/os-Linux/skas/trap.c49
-rw-r--r--arch/um/os-Linux/start_up.c173
-rw-r--r--arch/um/os-Linux/sys-i386/signal.c8
-rw-r--r--arch/um/os-Linux/sys-i386/tls.c2
-rw-r--r--arch/um/os-Linux/sys-x86_64/signal.c6
-rw-r--r--arch/um/os-Linux/time.c1
-rw-r--r--arch/um/os-Linux/trap.c1
-rw-r--r--arch/um/os-Linux/tt.c4
-rw-r--r--arch/um/os-Linux/tty_log.c28
-rw-r--r--arch/um/os-Linux/util.c39
-rw-r--r--arch/um/sys-i386/bugs.c78
-rw-r--r--arch/um/sys-i386/fault.c18
-rw-r--r--arch/um/sys-i386/ptrace_user.c17
-rw-r--r--arch/um/sys-i386/signal.c84
-rw-r--r--arch/um/sys-i386/tls.c11
-rw-r--r--arch/um/sys-i386/user-offsets.c10
-rw-r--r--arch/um/sys-ppc/sigcontext.c1
-rw-r--r--arch/um/sys-x86_64/bugs.c104
-rw-r--r--arch/um/sys-x86_64/fault.c30
-rw-r--r--arch/um/sys-x86_64/signal.c32
-rw-r--r--arch/um/sys-x86_64/user-offsets.c6
115 files changed, 1747 insertions, 1980 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 354cc6b70530..c504312219b4 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -277,7 +277,8 @@ config HIGHMEM
277 277
278config KERNEL_STACK_ORDER 278config KERNEL_STACK_ORDER
279 int "Kernel stack size order" 279 int "Kernel stack size order"
280 default 2 280 default 1 if 64BIT
281 default 0 if !64BIT
281 help 282 help
282 This option determines the size of UML kernel stacks. They will 283 This option determines the size of UML kernel stacks. They will
283 be 1 << order pages. The default is OK unless you're running Valgrind 284 be 1 << order pages. The default is OK unless you're running Valgrind
@@ -320,21 +321,7 @@ source "crypto/Kconfig"
320 321
321source "lib/Kconfig" 322source "lib/Kconfig"
322 323
323menu "SCSI support" 324source "drivers/scsi/Kconfig"
324depends on BROKEN
325
326config SCSI
327 tristate "SCSI support"
328
329# This gives us free_dma, which scsi.c wants.
330config GENERIC_ISA_DMA
331 bool
332 depends on SCSI
333 default y
334
335source "arch/um/Kconfig.scsi"
336
337endmenu
338 325
339source "drivers/md/Kconfig" 326source "drivers/md/Kconfig"
340 327
diff --git a/arch/um/Kconfig.scsi b/arch/um/Kconfig.scsi
deleted file mode 100644
index c291c942b1a8..000000000000
--- a/arch/um/Kconfig.scsi
+++ /dev/null
@@ -1,58 +0,0 @@
1comment "SCSI support type (disk, tape, CD-ROM)"
2 depends on SCSI
3
4config BLK_DEV_SD
5 tristate "SCSI disk support"
6 depends on SCSI
7
8config SD_EXTRA_DEVS
9 int "Maximum number of SCSI disks that can be loaded as modules"
10 depends on BLK_DEV_SD
11 default "40"
12
13config CHR_DEV_ST
14 tristate "SCSI tape support"
15 depends on SCSI
16
17config BLK_DEV_SR
18 tristate "SCSI CD-ROM support"
19 depends on SCSI
20
21config BLK_DEV_SR_VENDOR
22 bool "Enable vendor-specific extensions (for SCSI CDROM)"
23 depends on BLK_DEV_SR
24
25config SR_EXTRA_DEVS
26 int "Maximum number of CDROM devices that can be loaded as modules"
27 depends on BLK_DEV_SR
28 default "2"
29
30config CHR_DEV_SG
31 tristate "SCSI generic support"
32 depends on SCSI
33
34comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
35 depends on SCSI
36
37#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
38config SCSI_DEBUG_QUEUES
39 bool "Enable extra checks in new queueing code"
40 depends on SCSI
41
42#fi
43config SCSI_MULTI_LUN
44 bool "Probe all LUNs on each SCSI device"
45 depends on SCSI
46
47config SCSI_CONSTANTS
48 bool "Verbose SCSI error reporting (kernel size +=12K)"
49 depends on SCSI
50
51config SCSI_LOGGING
52 bool "SCSI logging facility"
53 depends on SCSI
54
55config SCSI_DEBUG
56 tristate "SCSI debugging host simulator (EXPERIMENTAL)"
57 depends on SCSI
58
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 780cc0a4a128..a54d0efecae1 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -41,6 +41,7 @@ CONFIG_M686=y
41# CONFIG_MGEODE_LX is not set 41# CONFIG_MGEODE_LX is not set
42# CONFIG_MCYRIXIII is not set 42# CONFIG_MCYRIXIII is not set
43# CONFIG_MVIAC3_2 is not set 43# CONFIG_MVIAC3_2 is not set
44# CONFIG_MVIAC7 is not set
44# CONFIG_X86_GENERIC is not set 45# CONFIG_X86_GENERIC is not set
45CONFIG_X86_CMPXCHG=y 46CONFIG_X86_CMPXCHG=y
46CONFIG_X86_XADD=y 47CONFIG_X86_XADD=y
@@ -85,7 +86,7 @@ CONFIG_MCONSOLE=y
85# CONFIG_MAGIC_SYSRQ is not set 86# CONFIG_MAGIC_SYSRQ is not set
86CONFIG_NEST_LEVEL=0 87CONFIG_NEST_LEVEL=0
87# CONFIG_HIGHMEM is not set 88# CONFIG_HIGHMEM is not set
88CONFIG_KERNEL_STACK_ORDER=2 89CONFIG_KERNEL_STACK_ORDER=0
89CONFIG_UML_REAL_TIME_CLOCK=y 90CONFIG_UML_REAL_TIME_CLOCK=y
90 91
91# 92#
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 9fdfad649536..3aa351611763 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -12,7 +12,6 @@
12#include <linux/tty_flip.h> 12#include <linux/tty_flip.h>
13#include <asm/irq.h> 13#include <asm/irq.h>
14#include "chan_kern.h" 14#include "chan_kern.h"
15#include "user_util.h"
16#include "kern.h" 15#include "kern.h"
17#include "irq_user.h" 16#include "irq_user.h"
18#include "sigio.h" 17#include "sigio.h"
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 0cad3546cb89..13f0bf852b2a 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -14,7 +14,6 @@
14#include <sys/ioctl.h> 14#include <sys/ioctl.h>
15#include <sys/socket.h> 15#include <sys/socket.h>
16#include "kern_util.h" 16#include "kern_util.h"
17#include "user_util.h"
18#include "chan_user.h" 17#include "chan_user.h"
19#include "user.h" 18#include "user.h"
20#include "os.h" 19#include "os.h"
@@ -158,7 +157,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
158 */ 157 */
159 err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0); 158 err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0);
160 if(err < 0){ 159 if(err < 0){
161 printk("fork of winch_thread failed - errno = %d\n", errno); 160 printk("fork of winch_thread failed - errno = %d\n", -err);
162 goto out_close; 161 goto out_close;
163 } 162 }
164 163
@@ -204,14 +203,3 @@ void register_winch(int fd, struct tty_struct *tty)
204 } 203 }
205 } 204 }
206} 205}
207
208/*
209 * Overrides for Emacs so that we follow Linus's tabbing style.
210 * Emacs will notice this stuff at the end of the file and automatically
211 * adjust the settings for this buffer only. This must remain at the end
212 * of the file.
213 * ---------------------------------------------------------------------------
214 * Local variables:
215 * c-file-style: "linux"
216 * End:
217 */
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index c6a308464acb..15453845d2ba 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -2,14 +2,13 @@
2#define __COW_SYS_H__ 2#define __COW_SYS_H__
3 3
4#include "kern_util.h" 4#include "kern_util.h"
5#include "user_util.h"
6#include "os.h" 5#include "os.h"
7#include "user.h" 6#include "user.h"
8#include "um_malloc.h" 7#include "um_malloc.h"
9 8
10static inline void *cow_malloc(int size) 9static inline void *cow_malloc(int size)
11{ 10{
12 return(um_kmalloc(size)); 11 return um_kmalloc(size);
13} 12}
14 13
15static inline void cow_free(void *ptr) 14static inline void cow_free(void *ptr)
@@ -21,29 +20,22 @@ static inline void cow_free(void *ptr)
21 20
22static inline char *cow_strdup(char *str) 21static inline char *cow_strdup(char *str)
23{ 22{
24 return(uml_strdup(str)); 23 return uml_strdup(str);
25} 24}
26 25
27static inline int cow_seek_file(int fd, __u64 offset) 26static inline int cow_seek_file(int fd, __u64 offset)
28{ 27{
29 return(os_seek_file(fd, offset)); 28 return os_seek_file(fd, offset);
30} 29}
31 30
32static inline int cow_file_size(char *file, unsigned long long *size_out) 31static inline int cow_file_size(char *file, unsigned long long *size_out)
33{ 32{
34 return(os_file_size(file, size_out)); 33 return os_file_size(file, size_out);
35} 34}
36 35
37static inline int cow_write_file(int fd, void *buf, int size) 36static inline int cow_write_file(int fd, void *buf, int size)
38{ 37{
39 return(os_write_file(fd, buf, size)); 38 return os_write_file(fd, buf, size);
40} 39}
41 40
42#endif 41#endif
43
44/*
45 * ---------------------------------------------------------------------------
46 * Local variables:
47 * c-file-style: "linux"
48 * End:
49 */
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index 021b82c7a759..b869e3899683 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -14,7 +14,6 @@
14#include "net_user.h" 14#include "net_user.h"
15#include "daemon.h" 15#include "daemon.h"
16#include "kern_util.h" 16#include "kern_util.h"
17#include "user_util.h"
18#include "user.h" 17#include "user.h"
19#include "os.h" 18#include "os.h"
20#include "um_malloc.h" 19#include "um_malloc.h"
@@ -39,11 +38,11 @@ static struct sockaddr_un *new_addr(void *name, int len)
39 sun = um_kmalloc(sizeof(struct sockaddr_un)); 38 sun = um_kmalloc(sizeof(struct sockaddr_un));
40 if(sun == NULL){ 39 if(sun == NULL){
41 printk("new_addr: allocation of sockaddr_un failed\n"); 40 printk("new_addr: allocation of sockaddr_un failed\n");
42 return(NULL); 41 return NULL;
43 } 42 }
44 sun->sun_family = AF_UNIX; 43 sun->sun_family = AF_UNIX;
45 memcpy(sun->sun_path, name, len); 44 memcpy(sun->sun_path, name, len);
46 return(sun); 45 return sun;
47} 46}
48 47
49static int connect_to_switch(struct daemon_data *pri) 48static int connect_to_switch(struct daemon_data *pri)
@@ -112,7 +111,7 @@ static int connect_to_switch(struct daemon_data *pri)
112 } 111 }
113 112
114 pri->data_addr = sun; 113 pri->data_addr = sun;
115 return(fd); 114 return fd;
116 115
117 out_free: 116 out_free:
118 kfree(sun); 117 kfree(sun);
@@ -120,10 +119,10 @@ static int connect_to_switch(struct daemon_data *pri)
120 os_close_file(fd); 119 os_close_file(fd);
121 out: 120 out:
122 os_close_file(pri->control); 121 os_close_file(pri->control);
123 return(err); 122 return err;
124} 123}
125 124
126static void daemon_user_init(void *data, void *dev) 125static int daemon_user_init(void *data, void *dev)
127{ 126{
128 struct daemon_data *pri = data; 127 struct daemon_data *pri = data;
129 struct timeval tv; 128 struct timeval tv;
@@ -146,13 +145,16 @@ static void daemon_user_init(void *data, void *dev)
146 if(pri->fd < 0){ 145 if(pri->fd < 0){
147 kfree(pri->local_addr); 146 kfree(pri->local_addr);
148 pri->local_addr = NULL; 147 pri->local_addr = NULL;
148 return pri->fd;
149 } 149 }
150
151 return 0;
150} 152}
151 153
152static int daemon_open(void *data) 154static int daemon_open(void *data)
153{ 155{
154 struct daemon_data *pri = data; 156 struct daemon_data *pri = data;
155 return(pri->fd); 157 return pri->fd;
156} 158}
157 159
158static void daemon_remove(void *data) 160static void daemon_remove(void *data)
@@ -176,12 +178,12 @@ int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
176{ 178{
177 struct sockaddr_un *data_addr = pri->data_addr; 179 struct sockaddr_un *data_addr = pri->data_addr;
178 180
179 return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); 181 return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
180} 182}
181 183
182static int daemon_set_mtu(int mtu, void *data) 184static int daemon_set_mtu(int mtu, void *data)
183{ 185{
184 return(mtu); 186 return mtu;
185} 187}
186 188
187const struct net_user_info daemon_user_info = { 189const struct net_user_info daemon_user_info = {
@@ -194,14 +196,3 @@ const struct net_user_info daemon_user_info = {
194 .delete_address = NULL, 196 .delete_address = NULL,
195 .max_packet = MAX_PACKET - ETH_HEADER_OTHER 197 .max_packet = MAX_PACKET - ETH_HEADER_OTHER
196}; 198};
197
198/*
199 * Overrides for Emacs so that we follow Linus's tabbing style.
200 * Emacs will notice this stuff at the end of the file and automatically
201 * adjust the settings for this buffer only. This must remain at the end
202 * of the file.
203 * ---------------------------------------------------------------------------
204 * Local variables:
205 * c-file-style: "linux"
206 * End:
207 */
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 218aa0e9b792..7f083ec47a4f 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -9,7 +9,6 @@
9#include <termios.h> 9#include <termios.h>
10#include <errno.h> 10#include <errno.h>
11#include "user.h" 11#include "user.h"
12#include "user_util.h"
13#include "chan_user.h" 12#include "chan_user.h"
14#include "os.h" 13#include "os.h"
15#include "um_malloc.h" 14#include "um_malloc.h"
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index c495ecf263b1..5eeecf8917c3 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -6,7 +6,6 @@
6#include <stdio.h> 6#include <stdio.h>
7#include <unistd.h> 7#include <unistd.h>
8#include <errno.h> 8#include <errno.h>
9#include "user_util.h"
10#include "user.h" 9#include "user.h"
11#include "mconsole.h" 10#include "mconsole.h"
12#include "os.h" 11#include "os.h"
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index f75d7b05c481..ced99106f798 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -13,7 +13,6 @@
13#include "irq_user.h" 13#include "irq_user.h"
14#include "line.h" 14#include "line.h"
15#include "kern.h" 15#include "kern.h"
16#include "user_util.h"
17#include "kern_util.h" 16#include "kern_util.h"
18#include "os.h" 17#include "os.h"
19#include "irq_kern.h" 18#include "irq_kern.h"
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index b827e82884c9..d319db16d4ec 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -20,7 +20,6 @@
20#include "net_user.h" 20#include "net_user.h"
21#include "mcast.h" 21#include "mcast.h"
22#include "kern_util.h" 22#include "kern_util.h"
23#include "user_util.h"
24#include "user.h" 23#include "user.h"
25#include "os.h" 24#include "os.h"
26#include "um_malloc.h" 25#include "um_malloc.h"
@@ -34,20 +33,21 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
34 sin = um_kmalloc(sizeof(struct sockaddr_in)); 33 sin = um_kmalloc(sizeof(struct sockaddr_in));
35 if(sin == NULL){ 34 if(sin == NULL){
36 printk("new_addr: allocation of sockaddr_in failed\n"); 35 printk("new_addr: allocation of sockaddr_in failed\n");
37 return(NULL); 36 return NULL;
38 } 37 }
39 sin->sin_family = AF_INET; 38 sin->sin_family = AF_INET;
40 sin->sin_addr.s_addr = in_aton(addr); 39 sin->sin_addr.s_addr = in_aton(addr);
41 sin->sin_port = htons(port); 40 sin->sin_port = htons(port);
42 return(sin); 41 return sin;
43} 42}
44 43
45static void mcast_user_init(void *data, void *dev) 44static int mcast_user_init(void *data, void *dev)
46{ 45{
47 struct mcast_data *pri = data; 46 struct mcast_data *pri = data;
48 47
49 pri->mcast_addr = new_addr(pri->addr, pri->port); 48 pri->mcast_addr = new_addr(pri->addr, pri->port);
50 pri->dev = dev; 49 pri->dev = dev;
50 return 0;
51} 51}
52 52
53static void mcast_remove(void *data) 53static void mcast_remove(void *data)
@@ -107,8 +107,8 @@ static int mcast_open(void *data)
107 err = -errno; 107 err = -errno;
108 printk("mcast_open : data bind failed, errno = %d\n", errno); 108 printk("mcast_open : data bind failed, errno = %d\n", errno);
109 goto out_close; 109 goto out_close;
110 } 110 }
111 111
112 /* subscribe to the multicast group */ 112 /* subscribe to the multicast group */
113 mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; 113 mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
114 mreq.imr_interface.s_addr = 0; 114 mreq.imr_interface.s_addr = 0;
@@ -153,12 +153,12 @@ int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
153{ 153{
154 struct sockaddr_in *data_addr = pri->mcast_addr; 154 struct sockaddr_in *data_addr = pri->mcast_addr;
155 155
156 return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); 156 return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr));
157} 157}
158 158
159static int mcast_set_mtu(int mtu, void *data) 159static int mcast_set_mtu(int mtu, void *data)
160{ 160{
161 return(mtu); 161 return mtu;
162} 162}
163 163
164const struct net_user_info mcast_user_info = { 164const struct net_user_info mcast_user_info = {
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 65ad2932672c..542c9ef858f8 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -25,7 +25,6 @@
25#include "linux/console.h" 25#include "linux/console.h"
26#include "asm/irq.h" 26#include "asm/irq.h"
27#include "asm/uaccess.h" 27#include "asm/uaccess.h"
28#include "user_util.h"
29#include "kern_util.h" 28#include "kern_util.h"
30#include "kern.h" 29#include "kern.h"
31#include "mconsole.h" 30#include "mconsole.h"
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index f02634fbf32a..62e5ad63181a 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -17,7 +17,6 @@
17#include "sysdep/ptrace.h" 17#include "sysdep/ptrace.h"
18#include "mconsole.h" 18#include "mconsole.h"
19#include "os.h" 19#include "os.h"
20#include "user_util.h"
21 20
22static struct mconsole_command commands[] = { 21static struct mconsole_command commands[] = {
23 /* With uts namespaces, uts information becomes process-specific, so 22 /* With uts namespaces, uts information becomes process-specific, so
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index df3516e47d4d..e41a08f04694 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -15,7 +15,6 @@
15#include <linux/miscdevice.h> 15#include <linux/miscdevice.h>
16#include <asm/uaccess.h> 16#include <asm/uaccess.h>
17#include "mem_user.h" 17#include "mem_user.h"
18#include "user_util.h"
19 18
20/* These are set in mmapper_init, which is called at boot time */ 19/* These are set in mmapper_init, which is called at boot time */
21static unsigned long mmapper_size; 20static unsigned long mmapper_size;
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 859303730b2f..72773dd54425 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -21,7 +21,6 @@
21#include "linux/ethtool.h" 21#include "linux/ethtool.h"
22#include "linux/platform_device.h" 22#include "linux/platform_device.h"
23#include "asm/uaccess.h" 23#include "asm/uaccess.h"
24#include "user_util.h"
25#include "kern_util.h" 24#include "kern_util.h"
26#include "net_kern.h" 25#include "net_kern.h"
27#include "net_user.h" 26#include "net_user.h"
@@ -284,7 +283,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
284#endif 283#endif
285} 284}
286 285
287static void setup_etheraddr(char *str, unsigned char *addr) 286static void setup_etheraddr(char *str, unsigned char *addr, char *name)
288{ 287{
289 char *end; 288 char *end;
290 int i; 289 int i;
@@ -303,15 +302,34 @@ static void setup_etheraddr(char *str, unsigned char *addr)
303 } 302 }
304 str = end + 1; 303 str = end + 1;
305 } 304 }
306 if(addr[0] & 1){ 305 if (is_multicast_ether_addr(addr)) {
307 printk(KERN_ERR 306 printk(KERN_ERR
308 "Attempt to assign a broadcast ethernet address to a " 307 "Attempt to assign a multicast ethernet address to a "
309 "device disallowed\n"); 308 "device disallowed\n");
310 goto random; 309 goto random;
311 } 310 }
311 if (!is_valid_ether_addr(addr)) {
312 printk(KERN_ERR
313 "Attempt to assign an invalid ethernet address to a "
314 "device disallowed\n");
315 goto random;
316 }
317 if (!is_local_ether_addr(addr)) {
318 printk(KERN_WARNING
319 "Warning: attempt to assign a globally valid ethernet "
320 "address to a device\n");
321 printk(KERN_WARNING "You should better enable the 2nd "
322 "rightmost bit in the first byte of the MAC,\n");
323 printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n",
324 addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
325 addr[5]);
326 goto random;
327 }
312 return; 328 return;
313 329
314random: 330random:
331 printk(KERN_INFO
332 "Choosing a random ethernet address for device %s\n", name);
315 random_ether_addr(addr); 333 random_ether_addr(addr);
316} 334}
317 335
@@ -325,31 +343,53 @@ static struct platform_driver uml_net_driver = {
325}; 343};
326static int driver_registered; 344static int driver_registered;
327 345
328static int eth_configure(int n, void *init, char *mac, 346static void net_device_release(struct device *dev)
329 struct transport *transport) 347{
348 struct uml_net *device = dev->driver_data;
349 struct net_device *netdev = device->dev;
350 struct uml_net_private *lp = netdev->priv;
351
352 if(lp->remove != NULL)
353 (*lp->remove)(&lp->user);
354 list_del(&device->list);
355 kfree(device);
356 free_netdev(netdev);
357}
358
359static void eth_configure(int n, void *init, char *mac,
360 struct transport *transport)
330{ 361{
331 struct uml_net *device; 362 struct uml_net *device;
332 struct net_device *dev; 363 struct net_device *dev;
333 struct uml_net_private *lp; 364 struct uml_net_private *lp;
334 int save, err, size; 365 int err, size;
335 366
336 size = transport->private_size + sizeof(struct uml_net_private) + 367 size = transport->private_size + sizeof(struct uml_net_private);
337 sizeof(((struct uml_net_private *) 0)->user);
338 368
339 device = kzalloc(sizeof(*device), GFP_KERNEL); 369 device = kzalloc(sizeof(*device), GFP_KERNEL);
340 if (device == NULL) { 370 if (device == NULL) {
341 printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); 371 printk(KERN_ERR "eth_configure failed to allocate struct "
342 return(1); 372 "uml_net\n");
373 return;
374 }
375
376 dev = alloc_etherdev(size);
377 if (dev == NULL) {
378 printk(KERN_ERR "eth_configure: failed to allocate struct "
379 "net_device for eth%d\n", n);
380 goto out_free_device;
343 } 381 }
344 382
345 INIT_LIST_HEAD(&device->list); 383 INIT_LIST_HEAD(&device->list);
346 device->index = n; 384 device->index = n;
347 385
348 spin_lock(&devices_lock); 386 /* If this name ends up conflicting with an existing registered
349 list_add(&device->list, &devices); 387 * netdevice, that is OK, register_netdev{,ice}() will notice this
350 spin_unlock(&devices_lock); 388 * and fail.
389 */
390 snprintf(dev->name, sizeof(dev->name), "eth%d", n);
351 391
352 setup_etheraddr(mac, device->mac); 392 setup_etheraddr(mac, device->mac, dev->name);
353 393
354 printk(KERN_INFO "Netdevice %d ", n); 394 printk(KERN_INFO "Netdevice %d ", n);
355 printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", 395 printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
@@ -357,11 +397,6 @@ static int eth_configure(int n, void *init, char *mac,
357 device->mac[2], device->mac[3], 397 device->mac[2], device->mac[3],
358 device->mac[4], device->mac[5]); 398 device->mac[4], device->mac[5]);
359 printk(": "); 399 printk(": ");
360 dev = alloc_etherdev(size);
361 if (dev == NULL) {
362 printk(KERN_ERR "eth_configure: failed to allocate device\n");
363 return 1;
364 }
365 400
366 lp = dev->priv; 401 lp = dev->priv;
367 /* This points to the transport private data. It's still clear, but we 402 /* This points to the transport private data. It's still clear, but we
@@ -376,47 +411,20 @@ static int eth_configure(int n, void *init, char *mac,
376 } 411 }
377 device->pdev.id = n; 412 device->pdev.id = n;
378 device->pdev.name = DRIVER_NAME; 413 device->pdev.name = DRIVER_NAME;
379 platform_device_register(&device->pdev); 414 device->pdev.dev.release = net_device_release;
415 device->pdev.dev.driver_data = device;
416 if(platform_device_register(&device->pdev))
417 goto out_free_netdev;
380 SET_NETDEV_DEV(dev,&device->pdev.dev); 418 SET_NETDEV_DEV(dev,&device->pdev.dev);
381 419
382 /* If this name ends up conflicting with an existing registered
383 * netdevice, that is OK, register_netdev{,ice}() will notice this
384 * and fail.
385 */
386 snprintf(dev->name, sizeof(dev->name), "eth%d", n);
387 device->dev = dev; 420 device->dev = dev;
388 421
422 /*
423 * These just fill in a data structure, so there's no failure
424 * to be worried about.
425 */
389 (*transport->kern->init)(dev, init); 426 (*transport->kern->init)(dev, init);
390 427
391 dev->mtu = transport->user->max_packet;
392 dev->open = uml_net_open;
393 dev->hard_start_xmit = uml_net_start_xmit;
394 dev->stop = uml_net_close;
395 dev->get_stats = uml_net_get_stats;
396 dev->set_multicast_list = uml_net_set_multicast_list;
397 dev->tx_timeout = uml_net_tx_timeout;
398 dev->set_mac_address = uml_net_set_mac;
399 dev->change_mtu = uml_net_change_mtu;
400 dev->ethtool_ops = &uml_net_ethtool_ops;
401 dev->watchdog_timeo = (HZ >> 1);
402 dev->irq = UM_ETH_IRQ;
403
404 rtnl_lock();
405 err = register_netdevice(dev);
406 rtnl_unlock();
407 if (err) {
408 device->dev = NULL;
409 /* XXX: should we call ->remove() here? */
410 free_netdev(dev);
411 return 1;
412 }
413
414 /* lp.user is the first four bytes of the transport data, which
415 * has already been initialized. This structure assignment will
416 * overwrite that, so we make sure that .user gets overwritten with
417 * what it already has.
418 */
419 save = lp->user[0];
420 *lp = ((struct uml_net_private) 428 *lp = ((struct uml_net_private)
421 { .list = LIST_HEAD_INIT(lp->list), 429 { .list = LIST_HEAD_INIT(lp->list),
422 .dev = dev, 430 .dev = dev,
@@ -430,20 +438,53 @@ static int eth_configure(int n, void *init, char *mac,
430 .write = transport->kern->write, 438 .write = transport->kern->write,
431 .add_address = transport->user->add_address, 439 .add_address = transport->user->add_address,
432 .delete_address = transport->user->delete_address, 440 .delete_address = transport->user->delete_address,
433 .set_mtu = transport->user->set_mtu, 441 .set_mtu = transport->user->set_mtu });
434 .user = { save } });
435 442
436 init_timer(&lp->tl); 443 init_timer(&lp->tl);
437 spin_lock_init(&lp->lock); 444 spin_lock_init(&lp->lock);
438 lp->tl.function = uml_net_user_timer_expire; 445 lp->tl.function = uml_net_user_timer_expire;
439 memcpy(lp->mac, device->mac, sizeof(lp->mac)); 446 memcpy(lp->mac, device->mac, sizeof(lp->mac));
440 447
441 if (transport->user->init) 448 if ((transport->user->init != NULL) &&
442 (*transport->user->init)(&lp->user, dev); 449 ((*transport->user->init)(&lp->user, dev) != 0))
450 goto out_unregister;
443 451
444 set_ether_mac(dev, device->mac); 452 set_ether_mac(dev, device->mac);
453 dev->mtu = transport->user->max_packet;
454 dev->open = uml_net_open;
455 dev->hard_start_xmit = uml_net_start_xmit;
456 dev->stop = uml_net_close;
457 dev->get_stats = uml_net_get_stats;
458 dev->set_multicast_list = uml_net_set_multicast_list;
459 dev->tx_timeout = uml_net_tx_timeout;
460 dev->set_mac_address = uml_net_set_mac;
461 dev->change_mtu = uml_net_change_mtu;
462 dev->ethtool_ops = &uml_net_ethtool_ops;
463 dev->watchdog_timeo = (HZ >> 1);
464 dev->irq = UM_ETH_IRQ;
445 465
446 return 0; 466 rtnl_lock();
467 err = register_netdevice(dev);
468 rtnl_unlock();
469 if (err)
470 goto out_undo_user_init;
471
472 spin_lock(&devices_lock);
473 list_add(&device->list, &devices);
474 spin_unlock(&devices_lock);
475
476 return;
477
478out_undo_user_init:
479 if (transport->user->remove != NULL)
480 (*transport->user->remove)(&lp->user);
481out_unregister:
482 platform_device_unregister(&device->pdev);
483 return; /* platform_device_unregister frees dev and device */
484out_free_netdev:
485 free_netdev(dev);
486out_free_device:
487 kfree(device);
447} 488}
448 489
449static struct uml_net *find_device(int n) 490static struct uml_net *find_device(int n)
@@ -666,13 +707,9 @@ static int net_remove(int n, char **error_out)
666 lp = dev->priv; 707 lp = dev->priv;
667 if(lp->fd > 0) 708 if(lp->fd > 0)
668 return -EBUSY; 709 return -EBUSY;
669 if(lp->remove != NULL) (*lp->remove)(&lp->user);
670 unregister_netdev(dev); 710 unregister_netdev(dev);
671 platform_device_unregister(&device->pdev); 711 platform_device_unregister(&device->pdev);
672 712
673 list_del(&device->list);
674 kfree(device);
675 free_netdev(dev);
676 return 0; 713 return 0;
677} 714}
678 715
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 0ffd7ac295d4..3503cff867c3 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -14,11 +14,11 @@
14#include <sys/wait.h> 14#include <sys/wait.h>
15#include <sys/time.h> 15#include <sys/time.h>
16#include "user.h" 16#include "user.h"
17#include "user_util.h"
18#include "kern_util.h" 17#include "kern_util.h"
19#include "net_user.h" 18#include "net_user.h"
20#include "os.h" 19#include "os.h"
21#include "um_malloc.h" 20#include "um_malloc.h"
21#include "kern_constants.h"
22 22
23int tap_open_common(void *dev, char *gate_addr) 23int tap_open_common(void *dev, char *gate_addr)
24{ 24{
@@ -216,7 +216,7 @@ static void change(char *dev, char *what, unsigned char *addr,
216 sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], 216 sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
217 netmask[2], netmask[3]); 217 netmask[2], netmask[3]);
218 218
219 output_len = page_size(); 219 output_len = UM_KERN_PAGE_SIZE;
220 output = um_kmalloc(output_len); 220 output = um_kmalloc(output_len);
221 if(output == NULL) 221 if(output == NULL)
222 printk("change : failed to allocate output buffer\n"); 222 printk("change : failed to allocate output buffer\n");
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c
index 948849343ca4..c329931673d6 100644
--- a/arch/um/drivers/pcap_kern.c
+++ b/arch/um/drivers/pcap_kern.c
@@ -29,21 +29,25 @@ void pcap_init(struct net_device *dev, void *data)
29 ppri->promisc = init->promisc; 29 ppri->promisc = init->promisc;
30 ppri->optimize = init->optimize; 30 ppri->optimize = init->optimize;
31 ppri->filter = init->filter; 31 ppri->filter = init->filter;
32
33 printk("pcap backend, host interface %s\n", ppri->host_if);
32} 34}
33 35
34static int pcap_read(int fd, struct sk_buff **skb, 36static int pcap_read(int fd, struct sk_buff **skb,
35 struct uml_net_private *lp) 37 struct uml_net_private *lp)
36{ 38{
37 *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); 39 *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
38 if(*skb == NULL) return(-ENOMEM); 40 if(*skb == NULL)
39 return(pcap_user_read(fd, skb_mac_header(*skb), 41 return -ENOMEM;
42
43 return pcap_user_read(fd, skb_mac_header(*skb),
40 (*skb)->dev->mtu + ETH_HEADER_OTHER, 44 (*skb)->dev->mtu + ETH_HEADER_OTHER,
41 (struct pcap_data *) &lp->user)); 45 (struct pcap_data *) &lp->user);
42} 46}
43 47
44static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) 48static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
45{ 49{
46 return(-EPERM); 50 return -EPERM;
47} 51}
48 52
49static const struct net_kern_info pcap_kern_info = { 53static const struct net_kern_info pcap_kern_info = {
@@ -65,12 +69,12 @@ int pcap_setup(char *str, char **mac_out, void *data)
65 .optimize = 0, 69 .optimize = 0,
66 .filter = NULL }); 70 .filter = NULL });
67 71
68 remain = split_if_spec(str, &host_if, &init->filter, 72 remain = split_if_spec(str, &host_if, &init->filter,
69 &options[0], &options[1], NULL); 73 &options[0], &options[1], mac_out, NULL);
70 if(remain != NULL){ 74 if(remain != NULL){
71 printk(KERN_ERR "pcap_setup - Extra garbage on " 75 printk(KERN_ERR "pcap_setup - Extra garbage on "
72 "specification : '%s'\n", remain); 76 "specification : '%s'\n", remain);
73 return(0); 77 return 0;
74 } 78 }
75 79
76 if(host_if != NULL) 80 if(host_if != NULL)
@@ -87,10 +91,13 @@ int pcap_setup(char *str, char **mac_out, void *data)
87 init->optimize = 1; 91 init->optimize = 1;
88 else if(!strcmp(options[i], "nooptimize")) 92 else if(!strcmp(options[i], "nooptimize"))
89 init->optimize = 0; 93 init->optimize = 0;
90 else printk("pcap_setup : bad option - '%s'\n", options[i]); 94 else {
95 printk("pcap_setup : bad option - '%s'\n", options[i]);
96 return 0;
97 }
91 } 98 }
92 99
93 return(1); 100 return 1;
94} 101}
95 102
96static struct transport pcap_transport = { 103static struct transport pcap_transport = {
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index 11921a7baa7b..483aa15222a4 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -13,12 +13,13 @@
13#include "pcap_user.h" 13#include "pcap_user.h"
14#include "user.h" 14#include "user.h"
15#include "um_malloc.h" 15#include "um_malloc.h"
16#include "kern_constants.h"
16 17
17#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) 18#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
18 19
19#define PCAP_FD(p) (*(int *)(p)) 20#define PCAP_FD(p) (*(int *)(p))
20 21
21static void pcap_user_init(void *data, void *dev) 22static int pcap_user_init(void *data, void *dev)
22{ 23{
23 struct pcap_data *pri = data; 24 struct pcap_data *pri = data;
24 pcap_t *p; 25 pcap_t *p;
@@ -26,13 +27,14 @@ static void pcap_user_init(void *data, void *dev)
26 27
27 p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors); 28 p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors);
28 if(p == NULL){ 29 if(p == NULL){
29 printk("pcap_user_init : pcap_open_live failed - '%s'\n", 30 printk(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - "
30 errors); 31 "'%s'\n", errors);
31 return; 32 return -EINVAL;
32 } 33 }
33 34
34 pri->dev = dev; 35 pri->dev = dev;
35 pri->pcap = p; 36 pri->pcap = p;
37 return 0;
36} 38}
37 39
38static int pcap_open(void *data) 40static int pcap_open(void *data)
@@ -42,39 +44,39 @@ static int pcap_open(void *data)
42 int err; 44 int err;
43 45
44 if(pri->pcap == NULL) 46 if(pri->pcap == NULL)
45 return(-ENODEV); 47 return -ENODEV;
46 48
47 if(pri->filter != NULL){ 49 if(pri->filter != NULL){
48 err = dev_netmask(pri->dev, &netmask); 50 err = dev_netmask(pri->dev, &netmask);
49 if(err < 0){ 51 if(err < 0){
50 printk("pcap_open : dev_netmask failed\n"); 52 printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n");
51 return(-EIO); 53 return -EIO;
52 } 54 }
53 55
54 pri->compiled = um_kmalloc(sizeof(struct bpf_program)); 56 pri->compiled = um_kmalloc(sizeof(struct bpf_program));
55 if(pri->compiled == NULL){ 57 if(pri->compiled == NULL){
56 printk("pcap_open : kmalloc failed\n"); 58 printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
57 return(-ENOMEM); 59 return -ENOMEM;
58 } 60 }
59 61
60 err = pcap_compile(pri->pcap, 62 err = pcap_compile(pri->pcap,
61 (struct bpf_program *) pri->compiled, 63 (struct bpf_program *) pri->compiled,
62 pri->filter, pri->optimize, netmask); 64 pri->filter, pri->optimize, netmask);
63 if(err < 0){ 65 if(err < 0){
64 printk("pcap_open : pcap_compile failed - '%s'\n", 66 printk(UM_KERN_ERR "pcap_open : pcap_compile failed - "
65 pcap_geterr(pri->pcap)); 67 "'%s'\n", pcap_geterr(pri->pcap));
66 return(-EIO); 68 return -EIO;
67 } 69 }
68 70
69 err = pcap_setfilter(pri->pcap, pri->compiled); 71 err = pcap_setfilter(pri->pcap, pri->compiled);
70 if(err < 0){ 72 if(err < 0){
71 printk("pcap_open : pcap_setfilter failed - '%s'\n", 73 printk(UM_KERN_ERR "pcap_open : pcap_setfilter "
72 pcap_geterr(pri->pcap)); 74 "failed - '%s'\n", pcap_geterr(pri->pcap));
73 return(-EIO); 75 return -EIO;
74 } 76 }
75 } 77 }
76 78
77 return(PCAP_FD(pri->pcap)); 79 return PCAP_FD(pri->pcap);
78} 80}
79 81
80static void pcap_remove(void *data) 82static void pcap_remove(void *data)
@@ -84,7 +86,8 @@ static void pcap_remove(void *data)
84 if(pri->compiled != NULL) 86 if(pri->compiled != NULL)
85 pcap_freecode(pri->compiled); 87 pcap_freecode(pri->compiled);
86 88
87 pcap_close(pri->pcap); 89 if(pri->pcap != NULL)
90 pcap_close(pri->pcap);
88} 91}
89 92
90struct pcap_handler_data { 93struct pcap_handler_data {
@@ -113,12 +116,13 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
113 116
114 n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); 117 n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
115 if(n < 0){ 118 if(n < 0){
116 printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); 119 printk(UM_KERN_ERR "pcap_dispatch failed - %s\n",
117 return(-EIO); 120 pcap_geterr(pri->pcap));
121 return -EIO;
118 } 122 }
119 else if(n == 0) 123 else if(n == 0)
120 return(0); 124 return 0;
121 return(hdata.len); 125 return hdata.len;
122} 126}
123 127
124const struct net_user_info pcap_user_info = { 128const struct net_user_info pcap_user_info = {
@@ -131,14 +135,3 @@ const struct net_user_info pcap_user_info = {
131 .delete_address = NULL, 135 .delete_address = NULL,
132 .max_packet = MAX_PACKET - ETH_HEADER_OTHER 136 .max_packet = MAX_PACKET - ETH_HEADER_OTHER
133}; 137};
134
135/*
136 * Overrides for Emacs so that we follow Linus's tabbing style.
137 * Emacs will notice this stuff at the end of the file and automatically
138 * adjust the settings for this buffer only. This must remain at the end
139 * of the file.
140 * ---------------------------------------------------------------------------
141 * Local variables:
142 * c-file-style: "linux"
143 * End:
144 */
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 80508023054f..3f6357d24bee 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -13,7 +13,6 @@
13#include <sys/socket.h> 13#include <sys/socket.h>
14#include <sys/un.h> 14#include <sys/un.h>
15#include <netinet/in.h> 15#include <netinet/in.h>
16#include "user_util.h"
17#include "kern_util.h" 16#include "kern_util.h"
18#include "user.h" 17#include "user.h"
19#include "chan_user.h" 18#include "chan_user.h"
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 829a5eca8c07..df4976c9eef2 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -4,13 +4,13 @@
4 */ 4 */
5 5
6#include <stdio.h> 6#include <stdio.h>
7#include <stdlib.h>
7#include <unistd.h> 8#include <unistd.h>
8#include <string.h> 9#include <string.h>
9#include <errno.h> 10#include <errno.h>
10#include <termios.h> 11#include <termios.h>
11#include "chan_user.h" 12#include "chan_user.h"
12#include "user.h" 13#include "user.h"
13#include "user_util.h"
14#include "kern_util.h" 14#include "kern_util.h"
15#include "os.h" 15#include "os.h"
16#include "um_malloc.h" 16#include "um_malloc.h"
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 7eddacc53b6e..78f0e515da8f 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -8,7 +8,6 @@
8#include <sys/termios.h> 8#include <sys/termios.h>
9#include <sys/wait.h> 9#include <sys/wait.h>
10#include <sys/signal.h> 10#include <sys/signal.h>
11#include "user_util.h"
12#include "kern_util.h" 11#include "kern_util.h"
13#include "user.h" 12#include "user.h"
14#include "net_user.h" 13#include "net_user.h"
@@ -16,12 +15,14 @@
16#include "slip_common.h" 15#include "slip_common.h"
17#include "os.h" 16#include "os.h"
18#include "um_malloc.h" 17#include "um_malloc.h"
18#include "kern_constants.h"
19 19
20void slip_user_init(void *data, void *dev) 20static int slip_user_init(void *data, void *dev)
21{ 21{
22 struct slip_data *pri = data; 22 struct slip_data *pri = data;
23 23
24 pri->dev = dev; 24 pri->dev = dev;
25 return 0;
25} 26}
26 27
27static int set_up_tty(int fd) 28static int set_up_tty(int fd)
@@ -89,7 +90,7 @@ static int slip_tramp(char **argv, int fd)
89 goto out_close; 90 goto out_close;
90 pid = err; 91 pid = err;
91 92
92 output_len = page_size(); 93 output_len = UM_KERN_PAGE_SIZE;
93 output = um_kmalloc(output_len); 94 output = um_kmalloc(output_len);
94 if(output == NULL){ 95 if(output == NULL){
95 printk("slip_tramp : failed to allocate output buffer\n"); 96 printk("slip_tramp : failed to allocate output buffer\n");
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index ce5e85d1de3d..39f889fe9949 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -7,7 +7,6 @@
7#include <errno.h> 7#include <errno.h>
8#include <sys/wait.h> 8#include <sys/wait.h>
9#include <sys/signal.h> 9#include <sys/signal.h>
10#include "user_util.h"
11#include "kern_util.h" 10#include "kern_util.h"
12#include "user.h" 11#include "user.h"
13#include "net_user.h" 12#include "net_user.h"
@@ -15,11 +14,12 @@
15#include "slip_common.h" 14#include "slip_common.h"
16#include "os.h" 15#include "os.h"
17 16
18void slirp_user_init(void *data, void *dev) 17static int slirp_user_init(void *data, void *dev)
19{ 18{
20 struct slirp_data *pri = data; 19 struct slirp_data *pri = data;
21 20
22 pri->dev = dev; 21 pri->dev = dev;
22 return 0;
23} 23}
24 24
25struct slirp_pre_exec_data { 25struct slirp_pre_exec_data {
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 4b382a6e710f..fd09ad9e9c0a 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -15,7 +15,6 @@
15#include "line.h" 15#include "line.h"
16#include "ssl.h" 16#include "ssl.h"
17#include "chan_kern.h" 17#include "chan_kern.h"
18#include "user_util.h"
19#include "kern_util.h" 18#include "kern_util.h"
20#include "kern.h" 19#include "kern.h"
21#include "init.h" 20#include "init.h"
@@ -192,12 +191,12 @@ static int ssl_init(void)
192 ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, 191 ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
193 ARRAY_SIZE(serial_lines)); 192 ARRAY_SIZE(serial_lines));
194 193
195 lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
196
197 new_title = add_xterm_umid(opts.xterm_title); 194 new_title = add_xterm_umid(opts.xterm_title);
198 if (new_title != NULL) 195 if (new_title != NULL)
199 opts.xterm_title = new_title; 196 opts.xterm_title = new_title;
200 197
198 lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
199
201 ssl_init_done = 1; 200 ssl_init_done = 1;
202 register_console(&ssl_cons); 201 register_console(&ssl_cons);
203 return 0; 202 return 0;
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 76d1f1c980ef..2bb4193ac1aa 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -22,7 +22,6 @@
22#include "stdio_console.h" 22#include "stdio_console.h"
23#include "line.h" 23#include "line.h"
24#include "chan_kern.h" 24#include "chan_kern.h"
25#include "user_util.h"
26#include "kern_util.h" 25#include "kern_util.h"
27#include "irq_user.h" 26#include "irq_user.h"
28#include "mconsole_kern.h" 27#include "mconsole_kern.h"
@@ -167,12 +166,12 @@ int stdio_init(void)
167 return -1; 166 return -1;
168 printk(KERN_INFO "Initialized stdio console driver\n"); 167 printk(KERN_INFO "Initialized stdio console driver\n");
169 168
170 lines_init(vts, ARRAY_SIZE(vts), &opts);
171
172 new_title = add_xterm_umid(opts.xterm_title); 169 new_title = add_xterm_umid(opts.xterm_title);
173 if(new_title != NULL) 170 if(new_title != NULL)
174 opts.xterm_title = new_title; 171 opts.xterm_title = new_title;
175 172
173 lines_init(vts, ARRAY_SIZE(vts), &opts);
174
176 con_init_done = 1; 175 con_init_done = 1;
177 register_console(&stdiocons); 176 register_console(&stdiocons);
178 return 0; 177 return 0;
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index d95d64309eaf..c07d0d562780 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -8,7 +8,6 @@
8#include <errno.h> 8#include <errno.h>
9#include <unistd.h> 9#include <unistd.h>
10#include "chan_user.h" 10#include "chan_user.h"
11#include "user_util.h"
12#include "user.h" 11#include "user.h"
13#include "os.h" 12#include "os.h"
14#include "um_malloc.h" 13#include "um_malloc.h"
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 8bd9204ac1ab..70509ddaac03 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -39,7 +39,6 @@
39#include "asm/irq.h" 39#include "asm/irq.h"
40#include "asm/types.h" 40#include "asm/types.h"
41#include "asm/tlbflush.h" 41#include "asm/tlbflush.h"
42#include "user_util.h"
43#include "mem_user.h" 42#include "mem_user.h"
44#include "kern_util.h" 43#include "kern_util.h"
45#include "kern.h" 44#include "kern.h"
@@ -90,7 +89,7 @@ static inline int ubd_test_bit(__u64 bit, unsigned char *data)
90 bits = sizeof(data[0]) * 8; 89 bits = sizeof(data[0]) * 8;
91 n = bit / bits; 90 n = bit / bits;
92 off = bit % bits; 91 off = bit % bits;
93 return((data[n] & (1 << off)) != 0); 92 return (data[n] & (1 << off)) != 0;
94} 93}
95 94
96static inline void ubd_set_bit(__u64 bit, unsigned char *data) 95static inline void ubd_set_bit(__u64 bit, unsigned char *data)
@@ -147,10 +146,13 @@ struct cow {
147 unsigned long *bitmap; 146 unsigned long *bitmap;
148 unsigned long bitmap_len; 147 unsigned long bitmap_len;
149 int bitmap_offset; 148 int bitmap_offset;
150 int data_offset; 149 int data_offset;
151}; 150};
152 151
152#define MAX_SG 64
153
153struct ubd { 154struct ubd {
155 struct list_head restart;
154 /* name (and fd, below) of the file opened for writing, either the 156 /* name (and fd, below) of the file opened for writing, either the
155 * backing or the cow file. */ 157 * backing or the cow file. */
156 char *file; 158 char *file;
@@ -165,15 +167,17 @@ struct ubd {
165 struct platform_device pdev; 167 struct platform_device pdev;
166 struct request_queue *queue; 168 struct request_queue *queue;
167 spinlock_t lock; 169 spinlock_t lock;
168 int active; 170 struct scatterlist sg[MAX_SG];
171 struct request *request;
172 int start_sg, end_sg;
169}; 173};
170 174
171#define DEFAULT_COW { \ 175#define DEFAULT_COW { \
172 .file = NULL, \ 176 .file = NULL, \
173 .fd = -1, \ 177 .fd = -1, \
174 .bitmap = NULL, \ 178 .bitmap = NULL, \
175 .bitmap_offset = 0, \ 179 .bitmap_offset = 0, \
176 .data_offset = 0, \ 180 .data_offset = 0, \
177} 181}
178 182
179#define DEFAULT_UBD { \ 183#define DEFAULT_UBD { \
@@ -183,11 +187,13 @@ struct ubd {
183 .size = -1, \ 187 .size = -1, \
184 .boot_openflags = OPEN_FLAGS, \ 188 .boot_openflags = OPEN_FLAGS, \
185 .openflags = OPEN_FLAGS, \ 189 .openflags = OPEN_FLAGS, \
186 .no_cow = 0, \ 190 .no_cow = 0, \
187 .shared = 0, \ 191 .shared = 0, \
188 .cow = DEFAULT_COW, \ 192 .cow = DEFAULT_COW, \
189 .lock = SPIN_LOCK_UNLOCKED, \ 193 .lock = SPIN_LOCK_UNLOCKED, \
190 .active = 0, \ 194 .request = NULL, \
195 .start_sg = 0, \
196 .end_sg = 0, \
191} 197}
192 198
193/* Protected by ubd_lock */ 199/* Protected by ubd_lock */
@@ -243,7 +249,7 @@ static void make_ide_entries(char *dev_name)
243static int fake_ide_setup(char *str) 249static int fake_ide_setup(char *str)
244{ 250{
245 fake_ide = 1; 251 fake_ide = 1;
246 return(1); 252 return 1;
247} 253}
248 254
249__setup("fake_ide", fake_ide_setup); 255__setup("fake_ide", fake_ide_setup);
@@ -261,7 +267,7 @@ static int parse_unit(char **ptr)
261 if(isdigit(*str)) { 267 if(isdigit(*str)) {
262 n = simple_strtoul(str, &end, 0); 268 n = simple_strtoul(str, &end, 0);
263 if(end == str) 269 if(end == str)
264 return(-1); 270 return -1;
265 *ptr = end; 271 *ptr = end;
266 } 272 }
267 else if (('a' <= *str) && (*str <= 'z')) { 273 else if (('a' <= *str) && (*str <= 'z')) {
@@ -269,7 +275,7 @@ static int parse_unit(char **ptr)
269 str++; 275 str++;
270 *ptr = str; 276 *ptr = str;
271 } 277 }
272 return(n); 278 return n;
273} 279}
274 280
275/* If *index_out == -1 at exit, the passed option was a general one; 281/* If *index_out == -1 at exit, the passed option was a general one;
@@ -436,7 +442,7 @@ static int udb_setup(char *str)
436{ 442{
437 printk("udb%s specified on command line is almost certainly a ubd -> " 443 printk("udb%s specified on command line is almost certainly a ubd -> "
438 "udb TYPO\n", str); 444 "udb TYPO\n", str);
439 return(1); 445 return 1;
440} 446}
441 447
442__setup("udb", udb_setup); 448__setup("udb", udb_setup);
@@ -467,66 +473,75 @@ static void do_ubd_request(request_queue_t * q);
467/* Only changed by ubd_init, which is an initcall. */ 473/* Only changed by ubd_init, which is an initcall. */
468int thread_fd = -1; 474int thread_fd = -1;
469 475
470/* call ubd_finish if you need to serialize */ 476static void ubd_end_request(struct request *req, int bytes, int uptodate)
471static void __ubd_finish(struct request *req, int error)
472{ 477{
473 int nsect; 478 if (!end_that_request_first(req, uptodate, bytes >> 9)) {
474 479 struct ubd *dev = req->rq_disk->private_data;
475 if(error){ 480 unsigned long flags;
476 end_request(req, 0); 481
477 return; 482 add_disk_randomness(req->rq_disk);
483 spin_lock_irqsave(&dev->lock, flags);
484 end_that_request_last(req, uptodate);
485 spin_unlock_irqrestore(&dev->lock, flags);
478 } 486 }
479 nsect = req->current_nr_sectors;
480 req->sector += nsect;
481 req->buffer += nsect << 9;
482 req->errors = 0;
483 req->nr_sectors -= nsect;
484 req->current_nr_sectors = 0;
485 end_request(req, 1);
486} 487}
487 488
488/* Callable only from interrupt context - otherwise you need to do 489/* Callable only from interrupt context - otherwise you need to do
489 * spin_lock_irq()/spin_lock_irqsave() */ 490 * spin_lock_irq()/spin_lock_irqsave() */
490static inline void ubd_finish(struct request *req, int error) 491static inline void ubd_finish(struct request *req, int bytes)
491{ 492{
492 struct ubd *dev = req->rq_disk->private_data; 493 if(bytes < 0){
493 494 ubd_end_request(req, 0, 0);
494 spin_lock(&dev->lock); 495 return;
495 __ubd_finish(req, error); 496 }
496 spin_unlock(&dev->lock); 497 ubd_end_request(req, bytes, 1);
497} 498}
498 499
500static LIST_HEAD(restart);
501
499/* XXX - move this inside ubd_intr. */ 502/* XXX - move this inside ubd_intr. */
500/* Called without dev->lock held, and only in interrupt context. */ 503/* Called without dev->lock held, and only in interrupt context. */
501static void ubd_handler(void) 504static void ubd_handler(void)
502{ 505{
503 struct io_thread_req req; 506 struct io_thread_req *req;
504 struct request *rq; 507 struct request *rq;
505 struct ubd *dev; 508 struct ubd *ubd;
509 struct list_head *list, *next_ele;
510 unsigned long flags;
506 int n; 511 int n;
507 512
508 n = os_read_file(thread_fd, &req, sizeof(req)); 513 while(1){
509 if(n != sizeof(req)){ 514 n = os_read_file(thread_fd, &req,
510 printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " 515 sizeof(struct io_thread_req *));
511 "err = %d\n", os_getpid(), -n); 516 if(n != sizeof(req)){
512 return; 517 if(n == -EAGAIN)
513 } 518 break;
514 519 printk(KERN_ERR "spurious interrupt in ubd_handler, "
515 rq = req.req; 520 "err = %d\n", -n);
516 dev = rq->rq_disk->private_data; 521 return;
517 dev->active = 0; 522 }
518 523
519 ubd_finish(rq, req.error); 524 rq = req->req;
525 rq->nr_sectors -= req->length >> 9;
526 if(rq->nr_sectors == 0)
527 ubd_finish(rq, rq->hard_nr_sectors << 9);
528 kfree(req);
529 }
520 reactivate_fd(thread_fd, UBD_IRQ); 530 reactivate_fd(thread_fd, UBD_IRQ);
521 spin_lock(&dev->lock); 531
522 do_ubd_request(dev->queue); 532 list_for_each_safe(list, next_ele, &restart){
523 spin_unlock(&dev->lock); 533 ubd = container_of(list, struct ubd, restart);
534 list_del_init(&ubd->restart);
535 spin_lock_irqsave(&ubd->lock, flags);
536 do_ubd_request(ubd->queue);
537 spin_unlock_irqrestore(&ubd->lock, flags);
538 }
524} 539}
525 540
526static irqreturn_t ubd_intr(int irq, void *dev) 541static irqreturn_t ubd_intr(int irq, void *dev)
527{ 542{
528 ubd_handler(); 543 ubd_handler();
529 return(IRQ_HANDLED); 544 return IRQ_HANDLED;
530} 545}
531 546
532/* Only changed by ubd_init, which is an initcall. */ 547/* Only changed by ubd_init, which is an initcall. */
@@ -545,7 +560,7 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
545 char *file; 560 char *file;
546 561
547 file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; 562 file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
548 return(os_file_size(file, size_out)); 563 return os_file_size(file, size_out);
549} 564}
550 565
551static void ubd_close_dev(struct ubd *ubd_dev) 566static void ubd_close_dev(struct ubd *ubd_dev)
@@ -617,10 +632,18 @@ static int ubd_open_dev(struct ubd *ubd_dev)
617 if(err < 0) goto error; 632 if(err < 0) goto error;
618 ubd_dev->cow.fd = err; 633 ubd_dev->cow.fd = err;
619 } 634 }
620 return(0); 635 return 0;
621 error: 636 error:
622 os_close_file(ubd_dev->fd); 637 os_close_file(ubd_dev->fd);
623 return(err); 638 return err;
639}
640
641static void ubd_device_release(struct device *dev)
642{
643 struct ubd *ubd_dev = dev->driver_data;
644
645 blk_cleanup_queue(ubd_dev->queue);
646 *ubd_dev = ((struct ubd) DEFAULT_UBD);
624} 647}
625 648
626static int ubd_disk_register(int major, u64 size, int unit, 649static int ubd_disk_register(int major, u64 size, int unit,
@@ -630,7 +653,7 @@ static int ubd_disk_register(int major, u64 size, int unit,
630 653
631 disk = alloc_disk(1 << UBD_SHIFT); 654 disk = alloc_disk(1 << UBD_SHIFT);
632 if(disk == NULL) 655 if(disk == NULL)
633 return(-ENOMEM); 656 return -ENOMEM;
634 657
635 disk->major = major; 658 disk->major = major;
636 disk->first_minor = unit << UBD_SHIFT; 659 disk->first_minor = unit << UBD_SHIFT;
@@ -645,6 +668,8 @@ static int ubd_disk_register(int major, u64 size, int unit,
645 if (major == MAJOR_NR) { 668 if (major == MAJOR_NR) {
646 ubd_devs[unit].pdev.id = unit; 669 ubd_devs[unit].pdev.id = unit;
647 ubd_devs[unit].pdev.name = DRIVER_NAME; 670 ubd_devs[unit].pdev.name = DRIVER_NAME;
671 ubd_devs[unit].pdev.dev.release = ubd_device_release;
672 ubd_devs[unit].pdev.dev.driver_data = &ubd_devs[unit];
648 platform_device_register(&ubd_devs[unit].pdev); 673 platform_device_register(&ubd_devs[unit].pdev);
649 disk->driverfs_dev = &ubd_devs[unit].pdev.dev; 674 disk->driverfs_dev = &ubd_devs[unit].pdev.dev;
650 } 675 }
@@ -675,6 +700,8 @@ static int ubd_add(int n, char **error_out)
675 700
676 ubd_dev->size = ROUND_BLOCK(ubd_dev->size); 701 ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
677 702
703 INIT_LIST_HEAD(&ubd_dev->restart);
704
678 err = -ENOMEM; 705 err = -ENOMEM;
679 ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock); 706 ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock);
680 if (ubd_dev->queue == NULL) { 707 if (ubd_dev->queue == NULL) {
@@ -683,6 +710,7 @@ static int ubd_add(int n, char **error_out)
683 } 710 }
684 ubd_dev->queue->queuedata = ubd_dev; 711 ubd_dev->queue->queuedata = ubd_dev;
685 712
713 blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG);
686 err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); 714 err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
687 if(err){ 715 if(err){
688 *error_out = "Failed to register device"; 716 *error_out = "Failed to register device";
@@ -730,14 +758,14 @@ static int ubd_config(char *str, char **error_out)
730 goto err_free; 758 goto err_free;
731 } 759 }
732 760
733 mutex_lock(&ubd_lock); 761 mutex_lock(&ubd_lock);
734 ret = ubd_add(n, error_out); 762 ret = ubd_add(n, error_out);
735 if (ret) 763 if (ret)
736 ubd_devs[n].file = NULL; 764 ubd_devs[n].file = NULL;
737 mutex_unlock(&ubd_lock); 765 mutex_unlock(&ubd_lock);
738 766
739out: 767out:
740 return ret; 768 return ret;
741 769
742err_free: 770err_free:
743 kfree(str); 771 kfree(str);
@@ -752,7 +780,7 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
752 n = parse_unit(&name); 780 n = parse_unit(&name);
753 if((n >= MAX_DEV) || (n < 0)){ 781 if((n >= MAX_DEV) || (n < 0)){
754 *error_out = "ubd_get_config : device number out of range"; 782 *error_out = "ubd_get_config : device number out of range";
755 return(-1); 783 return -1;
756 } 784 }
757 785
758 ubd_dev = &ubd_devs[n]; 786 ubd_dev = &ubd_devs[n];
@@ -773,29 +801,27 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
773 801
774 out: 802 out:
775 mutex_unlock(&ubd_lock); 803 mutex_unlock(&ubd_lock);
776 return(len); 804 return len;
777} 805}
778 806
779static int ubd_id(char **str, int *start_out, int *end_out) 807static int ubd_id(char **str, int *start_out, int *end_out)
780{ 808{
781 int n; 809 int n;
782 810
783 n = parse_unit(str); 811 n = parse_unit(str);
784 *start_out = 0; 812 *start_out = 0;
785 *end_out = MAX_DEV - 1; 813 *end_out = MAX_DEV - 1;
786 return n; 814 return n;
787} 815}
788 816
789static int ubd_remove(int n, char **error_out) 817static int ubd_remove(int n, char **error_out)
790{ 818{
819 struct gendisk *disk = ubd_gendisk[n];
791 struct ubd *ubd_dev; 820 struct ubd *ubd_dev;
792 int err = -ENODEV; 821 int err = -ENODEV;
793 822
794 mutex_lock(&ubd_lock); 823 mutex_lock(&ubd_lock);
795 824
796 if(ubd_gendisk[n] == NULL)
797 goto out;
798
799 ubd_dev = &ubd_devs[n]; 825 ubd_dev = &ubd_devs[n];
800 826
801 if(ubd_dev->file == NULL) 827 if(ubd_dev->file == NULL)
@@ -806,9 +832,11 @@ static int ubd_remove(int n, char **error_out)
806 if(ubd_dev->count > 0) 832 if(ubd_dev->count > 0)
807 goto out; 833 goto out;
808 834
809 del_gendisk(ubd_gendisk[n]);
810 put_disk(ubd_gendisk[n]);
811 ubd_gendisk[n] = NULL; 835 ubd_gendisk[n] = NULL;
836 if(disk != NULL){
837 del_gendisk(disk);
838 put_disk(disk);
839 }
812 840
813 if(fake_gendisk[n] != NULL){ 841 if(fake_gendisk[n] != NULL){
814 del_gendisk(fake_gendisk[n]); 842 del_gendisk(fake_gendisk[n]);
@@ -816,10 +844,8 @@ static int ubd_remove(int n, char **error_out)
816 fake_gendisk[n] = NULL; 844 fake_gendisk[n] = NULL;
817 } 845 }
818 846
819 blk_cleanup_queue(ubd_dev->queue);
820 platform_device_unregister(&ubd_dev->pdev);
821 *ubd_dev = ((struct ubd) DEFAULT_UBD);
822 err = 0; 847 err = 0;
848 platform_device_unregister(&ubd_dev->pdev);
823out: 849out:
824 mutex_unlock(&ubd_lock); 850 mutex_unlock(&ubd_lock);
825 return err; 851 return err;
@@ -832,7 +858,7 @@ static struct mc_device ubd_mc = {
832 .list = LIST_HEAD_INIT(ubd_mc.list), 858 .list = LIST_HEAD_INIT(ubd_mc.list),
833 .name = "ubd", 859 .name = "ubd",
834 .config = ubd_config, 860 .config = ubd_config,
835 .get_config = ubd_get_config, 861 .get_config = ubd_get_config,
836 .id = ubd_id, 862 .id = ubd_id,
837 .remove = ubd_remove, 863 .remove = ubd_remove,
838}; 864};
@@ -854,7 +880,7 @@ static int __init ubd0_init(void)
854 ubd_dev->file = "root_fs"; 880 ubd_dev->file = "root_fs";
855 mutex_unlock(&ubd_lock); 881 mutex_unlock(&ubd_lock);
856 882
857 return(0); 883 return 0;
858} 884}
859 885
860__initcall(ubd0_init); 886__initcall(ubd0_init);
@@ -882,14 +908,14 @@ static int __init ubd_init(void)
882 return -1; 908 return -1;
883 } 909 }
884 platform_driver_register(&ubd_driver); 910 platform_driver_register(&ubd_driver);
885 mutex_lock(&ubd_lock); 911 mutex_lock(&ubd_lock);
886 for (i = 0; i < MAX_DEV; i++){ 912 for (i = 0; i < MAX_DEV; i++){
887 err = ubd_add(i, &error); 913 err = ubd_add(i, &error);
888 if(err) 914 if(err)
889 printk(KERN_ERR "Failed to initialize ubd device %d :" 915 printk(KERN_ERR "Failed to initialize ubd device %d :"
890 "%s\n", i, error); 916 "%s\n", i, error);
891 } 917 }
892 mutex_unlock(&ubd_lock); 918 mutex_unlock(&ubd_lock);
893 return 0; 919 return 0;
894} 920}
895 921
@@ -913,7 +939,7 @@ static int __init ubd_driver_init(void){
913 "ubd : Failed to start I/O thread (errno = %d) - " 939 "ubd : Failed to start I/O thread (errno = %d) - "
914 "falling back to synchronous I/O\n", -io_pid); 940 "falling back to synchronous I/O\n", -io_pid);
915 io_pid = -1; 941 io_pid = -1;
916 return(0); 942 return 0;
917 } 943 }
918 err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, 944 err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
919 IRQF_DISABLED, "ubd", ubd_devs); 945 IRQF_DISABLED, "ubd", ubd_devs);
@@ -948,7 +974,7 @@ static int ubd_open(struct inode *inode, struct file *filp)
948 err = -EROFS; 974 err = -EROFS;
949 }*/ 975 }*/
950 out: 976 out:
951 return(err); 977 return err;
952} 978}
953 979
954static int ubd_release(struct inode * inode, struct file * file) 980static int ubd_release(struct inode * inode, struct file * file)
@@ -958,7 +984,7 @@ static int ubd_release(struct inode * inode, struct file * file)
958 984
959 if(--ubd_dev->count == 0) 985 if(--ubd_dev->count == 0)
960 ubd_close_dev(ubd_dev); 986 ubd_close_dev(ubd_dev);
961 return(0); 987 return 0;
962} 988}
963 989
964static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, 990static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
@@ -1014,7 +1040,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1014 if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) 1040 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
1015 ubd_set_bit(i, (unsigned char *) 1041 ubd_set_bit(i, (unsigned char *)
1016 &req->sector_mask); 1042 &req->sector_mask);
1017 } 1043 }
1018 } 1044 }
1019 else cowify_bitmap(req->offset, req->length, &req->sector_mask, 1045 else cowify_bitmap(req->offset, req->length, &req->sector_mask,
1020 &req->cow_offset, bitmap, bitmap_offset, 1046 &req->cow_offset, bitmap, bitmap_offset,
@@ -1022,26 +1048,16 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1022} 1048}
1023 1049
1024/* Called with dev->lock held */ 1050/* Called with dev->lock held */
1025static int prepare_request(struct request *req, struct io_thread_req *io_req) 1051static void prepare_request(struct request *req, struct io_thread_req *io_req,
1052 unsigned long long offset, int page_offset,
1053 int len, struct page *page)
1026{ 1054{
1027 struct gendisk *disk = req->rq_disk; 1055 struct gendisk *disk = req->rq_disk;
1028 struct ubd *ubd_dev = disk->private_data; 1056 struct ubd *ubd_dev = disk->private_data;
1029 __u64 offset;
1030 int len;
1031
1032 /* This should be impossible now */
1033 if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){
1034 printk("Write attempted on readonly ubd device %s\n",
1035 disk->disk_name);
1036 end_request(req, 0);
1037 return(1);
1038 }
1039
1040 offset = ((__u64) req->sector) << 9;
1041 len = req->current_nr_sectors << 9;
1042 1057
1043 io_req->req = req; 1058 io_req->req = req;
1044 io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; 1059 io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd :
1060 ubd_dev->fd;
1045 io_req->fds[1] = ubd_dev->fd; 1061 io_req->fds[1] = ubd_dev->fd;
1046 io_req->cow_offset = -1; 1062 io_req->cow_offset = -1;
1047 io_req->offset = offset; 1063 io_req->offset = offset;
@@ -1052,45 +1068,66 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
1052 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; 1068 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
1053 io_req->offsets[0] = 0; 1069 io_req->offsets[0] = 0;
1054 io_req->offsets[1] = ubd_dev->cow.data_offset; 1070 io_req->offsets[1] = ubd_dev->cow.data_offset;
1055 io_req->buffer = req->buffer; 1071 io_req->buffer = page_address(page) + page_offset;
1056 io_req->sectorsize = 1 << 9; 1072 io_req->sectorsize = 1 << 9;
1057 1073
1058 if(ubd_dev->cow.file != NULL) 1074 if(ubd_dev->cow.file != NULL)
1059 cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset, 1075 cowify_req(io_req, ubd_dev->cow.bitmap,
1060 ubd_dev->cow.bitmap_len); 1076 ubd_dev->cow.bitmap_offset, ubd_dev->cow.bitmap_len);
1061 1077
1062 return(0);
1063} 1078}
1064 1079
1065/* Called with dev->lock held */ 1080/* Called with dev->lock held */
1066static void do_ubd_request(request_queue_t *q) 1081static void do_ubd_request(request_queue_t *q)
1067{ 1082{
1068 struct io_thread_req io_req; 1083 struct io_thread_req *io_req;
1069 struct request *req; 1084 struct request *req;
1070 int err, n; 1085 int n;
1071 1086
1072 if(thread_fd == -1){ 1087 while(1){
1073 while((req = elv_next_request(q)) != NULL){
1074 err = prepare_request(req, &io_req);
1075 if(!err){
1076 do_io(&io_req);
1077 __ubd_finish(req, io_req.error);
1078 }
1079 }
1080 }
1081 else {
1082 struct ubd *dev = q->queuedata; 1088 struct ubd *dev = q->queuedata;
1083 if(dev->active || (req = elv_next_request(q)) == NULL) 1089 if(dev->end_sg == 0){
1084 return; 1090 struct request *req = elv_next_request(q);
1085 err = prepare_request(req, &io_req); 1091 if(req == NULL)
1086 if(!err){ 1092 return;
1087 dev->active = 1; 1093
1088 n = os_write_file(thread_fd, (char *) &io_req, 1094 dev->request = req;
1089 sizeof(io_req)); 1095 blkdev_dequeue_request(req);
1090 if(n != sizeof(io_req)) 1096 dev->start_sg = 0;
1091 printk("write to io thread failed, " 1097 dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
1092 "errno = %d\n", -n);
1093 } 1098 }
1099
1100 req = dev->request;
1101 while(dev->start_sg < dev->end_sg){
1102 struct scatterlist *sg = &dev->sg[dev->start_sg];
1103
1104 io_req = kmalloc(sizeof(struct io_thread_req),
1105 GFP_ATOMIC);
1106 if(io_req == NULL){
1107 if(list_empty(&dev->restart))
1108 list_add(&dev->restart, &restart);
1109 return;
1110 }
1111 prepare_request(req, io_req,
1112 (unsigned long long) req->sector << 9,
1113 sg->offset, sg->length, sg->page);
1114
1115 n = os_write_file(thread_fd, &io_req,
1116 sizeof(struct io_thread_req *));
1117 if(n != sizeof(struct io_thread_req *)){
1118 if(n != -EAGAIN)
1119 printk("write to io thread failed, "
1120 "errno = %d\n", -n);
1121 else if(list_empty(&dev->restart))
1122 list_add(&dev->restart, &restart);
1123 return;
1124 }
1125
1126 req->sector += sg->length >> 9;
1127 dev->start_sg++;
1128 }
1129 dev->end_sg = 0;
1130 dev->request = NULL;
1094 } 1131 }
1095} 1132}
1096 1133
@@ -1120,21 +1157,21 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1120 ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); 1157 ubd_id.cyls = ubd_dev->size / (128 * 32 * 512);
1121 if(copy_to_user((char __user *) arg, (char *) &ubd_id, 1158 if(copy_to_user((char __user *) arg, (char *) &ubd_id,
1122 sizeof(ubd_id))) 1159 sizeof(ubd_id)))
1123 return(-EFAULT); 1160 return -EFAULT;
1124 return(0); 1161 return 0;
1125 1162
1126 case CDROMVOLREAD: 1163 case CDROMVOLREAD:
1127 if(copy_from_user(&volume, (char __user *) arg, sizeof(volume))) 1164 if(copy_from_user(&volume, (char __user *) arg, sizeof(volume)))
1128 return(-EFAULT); 1165 return -EFAULT;
1129 volume.channel0 = 255; 1166 volume.channel0 = 255;
1130 volume.channel1 = 255; 1167 volume.channel1 = 255;
1131 volume.channel2 = 255; 1168 volume.channel2 = 255;
1132 volume.channel3 = 255; 1169 volume.channel3 = 255;
1133 if(copy_to_user((char __user *) arg, &volume, sizeof(volume))) 1170 if(copy_to_user((char __user *) arg, &volume, sizeof(volume)))
1134 return(-EFAULT); 1171 return -EFAULT;
1135 return(0); 1172 return 0;
1136 } 1173 }
1137 return(-EINVAL); 1174 return -EINVAL;
1138} 1175}
1139 1176
1140static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow) 1177static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
@@ -1176,29 +1213,29 @@ static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
1176 if(err < 0){ 1213 if(err < 0){
1177 printk("Failed to get modification time of backing file " 1214 printk("Failed to get modification time of backing file "
1178 "\"%s\", err = %d\n", file, -err); 1215 "\"%s\", err = %d\n", file, -err);
1179 return(err); 1216 return err;
1180 } 1217 }
1181 1218
1182 err = os_file_size(file, &actual); 1219 err = os_file_size(file, &actual);
1183 if(err < 0){ 1220 if(err < 0){
1184 printk("Failed to get size of backing file \"%s\", " 1221 printk("Failed to get size of backing file \"%s\", "
1185 "err = %d\n", file, -err); 1222 "err = %d\n", file, -err);
1186 return(err); 1223 return err;
1187 } 1224 }
1188 1225
1189 if(actual != size){ 1226 if(actual != size){
1190 /*__u64 can be a long on AMD64 and with %lu GCC complains; so 1227 /*__u64 can be a long on AMD64 and with %lu GCC complains; so
1191 * the typecast.*/ 1228 * the typecast.*/
1192 printk("Size mismatch (%llu vs %llu) of COW header vs backing " 1229 printk("Size mismatch (%llu vs %llu) of COW header vs backing "
1193 "file\n", (unsigned long long) size, actual); 1230 "file\n", (unsigned long long) size, actual);
1194 return(-EINVAL); 1231 return -EINVAL;
1195 } 1232 }
1196 if(modtime != mtime){ 1233 if(modtime != mtime){
1197 printk("mtime mismatch (%ld vs %ld) of COW header vs backing " 1234 printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
1198 "file\n", mtime, modtime); 1235 "file\n", mtime, modtime);
1199 return(-EINVAL); 1236 return -EINVAL;
1200 } 1237 }
1201 return(0); 1238 return 0;
1202} 1239}
1203 1240
1204int read_cow_bitmap(int fd, void *buf, int offset, int len) 1241int read_cow_bitmap(int fd, void *buf, int offset, int len)
@@ -1207,13 +1244,13 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len)
1207 1244
1208 err = os_seek_file(fd, offset); 1245 err = os_seek_file(fd, offset);
1209 if(err < 0) 1246 if(err < 0)
1210 return(err); 1247 return err;
1211 1248
1212 err = os_read_file(fd, buf, len); 1249 err = os_read_file(fd, buf, len);
1213 if(err < 0) 1250 if(err < 0)
1214 return(err); 1251 return err;
1215 1252
1216 return(0); 1253 return 0;
1217} 1254}
1218 1255
1219int open_ubd_file(char *file, struct openflags *openflags, int shared, 1256int open_ubd_file(char *file, struct openflags *openflags, int shared,
@@ -1231,14 +1268,14 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
1231 if (fd < 0) { 1268 if (fd < 0) {
1232 if ((fd == -ENOENT) && (create_cow_out != NULL)) 1269 if ((fd == -ENOENT) && (create_cow_out != NULL))
1233 *create_cow_out = 1; 1270 *create_cow_out = 1;
1234 if (!openflags->w || 1271 if (!openflags->w ||
1235 ((fd != -EROFS) && (fd != -EACCES))) 1272 ((fd != -EROFS) && (fd != -EACCES)))
1236 return fd; 1273 return fd;
1237 openflags->w = 0; 1274 openflags->w = 0;
1238 fd = os_open_file(file, *openflags, mode); 1275 fd = os_open_file(file, *openflags, mode);
1239 if (fd < 0) 1276 if (fd < 0)
1240 return fd; 1277 return fd;
1241 } 1278 }
1242 1279
1243 if(shared) 1280 if(shared)
1244 printk("Not locking \"%s\" on the host\n", file); 1281 printk("Not locking \"%s\" on the host\n", file);
@@ -1252,7 +1289,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
1252 1289
1253 /* Successful return case! */ 1290 /* Successful return case! */
1254 if(backing_file_out == NULL) 1291 if(backing_file_out == NULL)
1255 return(fd); 1292 return fd;
1256 1293
1257 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, 1294 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
1258 &size, &sectorsize, &align, bitmap_offset_out); 1295 &size, &sectorsize, &align, bitmap_offset_out);
@@ -1262,7 +1299,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
1262 goto out_close; 1299 goto out_close;
1263 } 1300 }
1264 if(err) 1301 if(err)
1265 return(fd); 1302 return fd;
1266 1303
1267 asked_switch = path_requires_switch(*backing_file_out, backing_file, file); 1304 asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
1268 1305
@@ -1285,7 +1322,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
1285 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, 1322 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
1286 bitmap_len_out, data_offset_out); 1323 bitmap_len_out, data_offset_out);
1287 1324
1288 return fd; 1325 return fd;
1289 out_close: 1326 out_close:
1290 os_close_file(fd); 1327 os_close_file(fd);
1291 return err; 1328 return err;
@@ -1310,10 +1347,10 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
1310 bitmap_offset_out, bitmap_len_out, 1347 bitmap_offset_out, bitmap_len_out,
1311 data_offset_out); 1348 data_offset_out);
1312 if(!err) 1349 if(!err)
1313 return(fd); 1350 return fd;
1314 os_close_file(fd); 1351 os_close_file(fd);
1315 out: 1352 out:
1316 return(err); 1353 return err;
1317} 1354}
1318 1355
1319static int update_bitmap(struct io_thread_req *req) 1356static int update_bitmap(struct io_thread_req *req)
@@ -1321,23 +1358,23 @@ static int update_bitmap(struct io_thread_req *req)
1321 int n; 1358 int n;
1322 1359
1323 if(req->cow_offset == -1) 1360 if(req->cow_offset == -1)
1324 return(0); 1361 return 0;
1325 1362
1326 n = os_seek_file(req->fds[1], req->cow_offset); 1363 n = os_seek_file(req->fds[1], req->cow_offset);
1327 if(n < 0){ 1364 if(n < 0){
1328 printk("do_io - bitmap lseek failed : err = %d\n", -n); 1365 printk("do_io - bitmap lseek failed : err = %d\n", -n);
1329 return(1); 1366 return 1;
1330 } 1367 }
1331 1368
1332 n = os_write_file(req->fds[1], &req->bitmap_words, 1369 n = os_write_file(req->fds[1], &req->bitmap_words,
1333 sizeof(req->bitmap_words)); 1370 sizeof(req->bitmap_words));
1334 if(n != sizeof(req->bitmap_words)){ 1371 if(n != sizeof(req->bitmap_words)){
1335 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, 1372 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
1336 req->fds[1]); 1373 req->fds[1]);
1337 return(1); 1374 return 1;
1338 } 1375 }
1339 1376
1340 return(0); 1377 return 0;
1341} 1378}
1342 1379
1343void do_io(struct io_thread_req *req) 1380void do_io(struct io_thread_req *req)
@@ -1409,13 +1446,14 @@ static int io_count = 0;
1409 1446
1410int io_thread(void *arg) 1447int io_thread(void *arg)
1411{ 1448{
1412 struct io_thread_req req; 1449 struct io_thread_req *req;
1413 int n; 1450 int n;
1414 1451
1415 ignore_sigwinch_sig(); 1452 ignore_sigwinch_sig();
1416 while(1){ 1453 while(1){
1417 n = os_read_file(kernel_fd, &req, sizeof(req)); 1454 n = os_read_file(kernel_fd, &req,
1418 if(n != sizeof(req)){ 1455 sizeof(struct io_thread_req *));
1456 if(n != sizeof(struct io_thread_req *)){
1419 if(n < 0) 1457 if(n < 0)
1420 printk("io_thread - read failed, fd = %d, " 1458 printk("io_thread - read failed, fd = %d, "
1421 "err = %d\n", kernel_fd, -n); 1459 "err = %d\n", kernel_fd, -n);
@@ -1426,9 +1464,10 @@ int io_thread(void *arg)
1426 continue; 1464 continue;
1427 } 1465 }
1428 io_count++; 1466 io_count++;
1429 do_io(&req); 1467 do_io(req);
1430 n = os_write_file(kernel_fd, &req, sizeof(req)); 1468 n = os_write_file(kernel_fd, &req,
1431 if(n != sizeof(req)) 1469 sizeof(struct io_thread_req *));
1470 if(n != sizeof(struct io_thread_req *))
1432 printk("io_thread - write failed, fd = %d, err = %d\n", 1471 printk("io_thread - write failed, fd = %d, err = %d\n",
1433 kernel_fd, -n); 1472 kernel_fd, -n);
1434 } 1473 }
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index b94d2bc4fe06..4707b3f14c2f 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -16,7 +16,6 @@
16#include <sys/mman.h> 16#include <sys/mman.h>
17#include <sys/param.h> 17#include <sys/param.h>
18#include "asm/types.h" 18#include "asm/types.h"
19#include "user_util.h"
20#include "kern_util.h" 19#include "kern_util.h"
21#include "user.h" 20#include "user.h"
22#include "ubd_user.h" 21#include "ubd_user.h"
@@ -47,8 +46,8 @@ int start_io_thread(unsigned long sp, int *fd_out)
47 pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, 46 pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
48 NULL); 47 NULL);
49 if(pid < 0){ 48 if(pid < 0){
50 printk("start_io_thread - clone failed : errno = %d\n", errno);
51 err = -errno; 49 err = -errno;
50 printk("start_io_thread - clone failed : errno = %d\n", errno);
52 goto out_close; 51 goto out_close;
53 } 52 }
54 53
@@ -60,16 +59,5 @@ int start_io_thread(unsigned long sp, int *fd_out)
60 kernel_fd = -1; 59 kernel_fd = -1;
61 *fd_out = -1; 60 *fd_out = -1;
62 out: 61 out:
63 return(err); 62 return err;
64} 63}
65
66/*
67 * Overrides for Emacs so that we follow Linus's tabbing style.
68 * Emacs will notice this stuff at the end of the file and automatically
69 * adjust the settings for this buffer only. This must remain at the end
70 * of the file.
71 * ---------------------------------------------------------------------------
72 * Local variables:
73 * c-file-style: "linux"
74 * End:
75 */
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 850221d9b4c9..571c2b3325d5 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -14,7 +14,6 @@
14#include <sys/socket.h> 14#include <sys/socket.h>
15#include "kern_util.h" 15#include "kern_util.h"
16#include "chan_user.h" 16#include "chan_user.h"
17#include "user_util.h"
18#include "user.h" 17#include "user.h"
19#include "os.h" 18#include "os.h"
20#include "xterm.h" 19#include "xterm.h"
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
new file mode 100644
index 000000000000..10ad52daa8c5
--- /dev/null
+++ b/arch/um/include/arch.h
@@ -0,0 +1,15 @@
1/*
2 * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __ARCH_H__
7#define __ARCH_H__
8
9#include "sysdep/ptrace.h"
10
11extern void arch_check_bugs(void);
12extern int arch_fixup(unsigned long address, union uml_pt_regs *regs);
13extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
14
15#endif
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
new file mode 100644
index 000000000000..fccf187bf4e1
--- /dev/null
+++ b/arch/um/include/as-layout.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __START_H__
7#define __START_H__
8
9#include "sysdep/ptrace.h"
10
11struct cpu_task {
12 int pid;
13 void *task;
14};
15
16extern struct cpu_task cpu_tasks[];
17
18extern unsigned long low_physmem;
19extern unsigned long high_physmem;
20extern unsigned long uml_physmem;
21extern unsigned long uml_reserved;
22extern unsigned long end_vm;
23extern unsigned long start_vm;
24extern unsigned long long highmem;
25
26extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
27extern unsigned long _unprotected_end;
28extern unsigned long brk_start;
29
30extern int linux_main(int argc, char **argv);
31extern void set_cmdline(char *cmd);
32
33extern void (*sig_info[])(int, union uml_pt_regs *);
34
35#endif
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 461175f8b1d9..541f4a8ca512 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -24,5 +24,9 @@ DEFINE(UM_ELF_CLASS, ELF_CLASS);
24DEFINE(UM_ELFCLASS32, ELFCLASS32); 24DEFINE(UM_ELFCLASS32, ELFCLASS32);
25DEFINE(UM_ELFCLASS64, ELFCLASS64); 25DEFINE(UM_ELFCLASS64, ELFCLASS64);
26 26
27DEFINE(UM_NR_CPUS, NR_CPUS);
28
27/* For crypto assembler code. */ 29/* For crypto assembler code. */
28DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); 30DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
31
32DEFINE(UM_THREAD_SIZE, THREAD_SIZE);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 173af029d12b..8d7f7c1cb9c6 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -8,6 +8,7 @@
8 8
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/faultinfo.h" 10#include "sysdep/faultinfo.h"
11#include "uml-config.h"
11 12
12typedef void (*kern_hndl)(int, union uml_pt_regs *); 13typedef void (*kern_hndl)(int, union uml_pt_regs *);
13 14
@@ -23,7 +24,6 @@ struct kern_handlers {
23extern const struct kern_handlers handlinfo_kern; 24extern const struct kern_handlers handlinfo_kern;
24 25
25extern int ncpus; 26extern int ncpus;
26extern char *linux_prog;
27extern char *gdb_init; 27extern char *gdb_init;
28extern int kmalloc_ok; 28extern int kmalloc_ok;
29extern int jail; 29extern int jail;
@@ -34,7 +34,9 @@ extern int nsyscalls;
34 UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) 34 UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
35 35
36extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); 36extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
37#ifdef UML_CONFIG_MODE_TT
37extern unsigned long stack_sp(unsigned long page); 38extern unsigned long stack_sp(unsigned long page);
39#endif
38extern int kernel_thread_proc(void *data); 40extern int kernel_thread_proc(void *data);
39extern void syscall_segv(int sig); 41extern void syscall_segv(int sig);
40extern int current_pid(void); 42extern int current_pid(void);
@@ -42,7 +44,7 @@ extern unsigned long alloc_stack(int order, int atomic);
42extern int do_signal(void); 44extern int do_signal(void);
43extern int is_stack_fault(unsigned long sp); 45extern int is_stack_fault(unsigned long sp);
44extern unsigned long segv(struct faultinfo fi, unsigned long ip, 46extern unsigned long segv(struct faultinfo fi, unsigned long ip,
45 int is_user, void *sc); 47 int is_user, union uml_pt_regs *regs);
46extern int handle_page_fault(unsigned long address, unsigned long ip, 48extern int handle_page_fault(unsigned long address, unsigned long ip,
47 int is_write, int is_user, int *code_out); 49 int is_write, int is_user, int *code_out);
48extern void syscall_ready(void); 50extern void syscall_ready(void);
@@ -50,7 +52,6 @@ extern void set_tracing(void *t, int tracing);
50extern int is_tracing(void *task); 52extern int is_tracing(void *task);
51extern int segv_syscall(void); 53extern int segv_syscall(void);
52extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); 54extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
53extern int page_size(void);
54extern unsigned long page_mask(void); 55extern unsigned long page_mask(void);
55extern int need_finish_fork(void); 56extern int need_finish_fork(void);
56extern void free_stack(unsigned long stack, int order); 57extern void free_stack(unsigned long stack, int order);
@@ -58,7 +59,6 @@ extern void add_input_request(int op, void (*proc)(int), void *arg);
58extern char *current_cmd(void); 59extern char *current_cmd(void);
59extern void timer_handler(int sig, union uml_pt_regs *regs); 60extern void timer_handler(int sig, union uml_pt_regs *regs);
60extern int set_signals(int enable); 61extern int set_signals(int enable);
61extern void force_sigbus(void);
62extern int pid_to_processor_id(int pid); 62extern int pid_to_processor_id(int pid);
63extern void deliver_signals(void *t); 63extern void deliver_signals(void *t);
64extern int next_trap_index(int max); 64extern int next_trap_index(int max);
@@ -70,7 +70,6 @@ extern void *syscall_sp(void *t);
70extern void syscall_trace(union uml_pt_regs *regs, int entryexit); 70extern void syscall_trace(union uml_pt_regs *regs, int entryexit);
71extern int hz(void); 71extern int hz(void);
72extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); 72extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
73extern int external_pid(void *t);
74extern void interrupt_end(void); 73extern void interrupt_end(void);
75extern void initial_thread_cb(void (*proc)(void *), void *arg); 74extern void initial_thread_cb(void (*proc)(void *), void *arg);
76extern int debugger_signal(int status, int pid); 75extern int debugger_signal(int status, int pid);
@@ -81,7 +80,6 @@ extern int init_parent_proxy(int pid);
81extern int singlestepping(void *t); 80extern int singlestepping(void *t);
82extern void check_stack_overflow(void *ptr); 81extern void check_stack_overflow(void *ptr);
83extern void relay_signal(int sig, union uml_pt_regs *regs); 82extern void relay_signal(int sig, union uml_pt_regs *regs);
84extern void not_implemented(void);
85extern int user_context(unsigned long sp); 83extern int user_context(unsigned long sp);
86extern void timer_irq(union uml_pt_regs *regs); 84extern void timer_irq(union uml_pt_regs *regs);
87extern void unprotect_stack(unsigned long stack); 85extern void unprotect_stack(unsigned long stack);
@@ -93,7 +91,6 @@ extern char *uml_strdup(char *string);
93extern void unprotect_kernel_mem(void); 91extern void unprotect_kernel_mem(void);
94extern void protect_kernel_mem(void); 92extern void protect_kernel_mem(void);
95extern void uml_cleanup(void); 93extern void uml_cleanup(void);
96extern void set_current(void *t);
97extern void lock_signalled_task(void *t); 94extern void lock_signalled_task(void *t);
98extern void IPI_handler(int cpu); 95extern void IPI_handler(int cpu);
99extern int jail_setup(char *line, int *add); 96extern int jail_setup(char *line, int *add);
@@ -118,4 +115,9 @@ extern void time_init_kern(void);
118extern int __cant_sleep(void); 115extern int __cant_sleep(void);
119extern void sigio_handler(int sig, union uml_pt_regs *regs); 116extern void sigio_handler(int sig, union uml_pt_regs *regs);
120 117
118extern void copy_sc(union uml_pt_regs *regs, void *from);
119
120unsigned long to_irq_stack(int sig, unsigned long *mask_out);
121unsigned long from_irq_stack(int nested);
122
121#endif 123#endif
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 125ab42df18a..9237056b9103 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -40,7 +40,7 @@ struct uml_net_private {
40 void (*add_address)(unsigned char *, unsigned char *, void *); 40 void (*add_address)(unsigned char *, unsigned char *, void *);
41 void (*delete_address)(unsigned char *, unsigned char *, void *); 41 void (*delete_address)(unsigned char *, unsigned char *, void *);
42 int (*set_mtu)(int mtu, void *); 42 int (*set_mtu)(int mtu, void *);
43 int user[1]; 43 char user[0];
44}; 44};
45 45
46struct net_kern_info { 46struct net_kern_info {
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 19f207cd70fe..cfe7c50634b9 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -14,7 +14,7 @@
14#define UML_NET_VERSION (4) 14#define UML_NET_VERSION (4)
15 15
16struct net_user_info { 16struct net_user_info {
17 void (*init)(void *, void *); 17 int (*init)(void *, void *);
18 int (*open)(void *); 18 int (*open)(void *);
19 void (*close)(int, void *); 19 void (*close)(int, void *);
20 void (*remove)(void *); 20 void (*remove)(void *);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 5c74da410451..4d9fb26387d5 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -16,6 +16,8 @@
16#include "sysdep/tls.h" 16#include "sysdep/tls.h"
17#include "sysdep/archsetjmp.h" 17#include "sysdep/archsetjmp.h"
18 18
19#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
20
19#define OS_TYPE_FILE 1 21#define OS_TYPE_FILE 1
20#define OS_TYPE_DIR 2 22#define OS_TYPE_DIR 2
21#define OS_TYPE_SYMLINK 3 23#define OS_TYPE_SYMLINK 3
@@ -270,11 +272,11 @@ extern void do_longjmp(void *p, int val);
270 272
271/* util.c */ 273/* util.c */
272extern void stack_protections(unsigned long address); 274extern void stack_protections(unsigned long address);
273extern void task_protections(unsigned long address);
274extern int raw(int fd); 275extern int raw(int fd);
275extern void setup_machinename(char *machine_out); 276extern void setup_machinename(char *machine_out);
276extern void setup_hostinfo(void); 277extern void setup_hostinfo(char *buf, int len);
277extern int setjmp_wrapper(void (*proc)(void *, void *), ...); 278extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
279extern void os_dump_core(void);
278 280
279/* time.c */ 281/* time.c */
280#define BILLION (1000 * 1000 * 1000) 282#define BILLION (1000 * 1000 * 1000)
@@ -297,13 +299,12 @@ extern long syscall_stub_data(struct mm_id * mm_idp,
297 unsigned long *data, int data_count, 299 unsigned long *data, int data_count,
298 void **addr, void **stub_addr); 300 void **addr, void **stub_addr);
299extern int map(struct mm_id * mm_idp, unsigned long virt, 301extern int map(struct mm_id * mm_idp, unsigned long virt,
300 unsigned long len, int r, int w, int x, int phys_fd, 302 unsigned long len, int prot, int phys_fd,
301 unsigned long long offset, int done, void **data); 303 unsigned long long offset, int done, void **data);
302extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, 304extern int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
303 int done, void **data); 305 int done, void **data);
304extern int protect(struct mm_id * mm_idp, unsigned long addr, 306extern int protect(struct mm_id * mm_idp, unsigned long addr,
305 unsigned long len, int r, int w, int x, int done, 307 unsigned long len, unsigned int prot, int done, void **data);
306 void **data);
307 308
308/* skas/process.c */ 309/* skas/process.c */
309extern int is_skas_winch(int pid, int fd, void *data); 310extern int is_skas_winch(int pid, int fd, void *data);
@@ -339,8 +340,11 @@ extern void maybe_sigio_broken(int fd, int read);
339 340
340/* skas/trap */ 341/* skas/trap */
341extern void sig_handler_common_skas(int sig, void *sc_ptr); 342extern void sig_handler_common_skas(int sig, void *sc_ptr);
342extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
343 343
344/* sys-x86_64/prctl.c */
344extern int os_arch_prctl(int pid, int code, unsigned long *addr); 345extern int os_arch_prctl(int pid, int code, unsigned long *addr);
345 346
347/* tty.c */
348int get_pty(void);
349
346#endif 350#endif
diff --git a/arch/um/include/skas/mode_kern_skas.h b/arch/um/include/skas/mode_kern_skas.h
index 9cd9c6ec9a63..8ee6285dfacc 100644
--- a/arch/um/include/skas/mode_kern_skas.h
+++ b/arch/um/include/skas/mode_kern_skas.h
@@ -33,6 +33,8 @@ extern unsigned long set_task_sizes_skas(unsigned long *task_size_out);
33extern int start_uml_skas(void); 33extern int start_uml_skas(void);
34extern int external_pid_skas(struct task_struct *task); 34extern int external_pid_skas(struct task_struct *task);
35extern int thread_pid_skas(struct task_struct *task); 35extern int thread_pid_skas(struct task_struct *task);
36extern void flush_tlb_page_skas(struct vm_area_struct *vma,
37 unsigned long address);
36 38
37#define kmem_end_skas (host_task_size - 1024 * 1024) 39#define kmem_end_skas (host_task_size - 1024 * 1024)
38 40
diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h
index 11bafab669e9..0f312085ce1d 100644
--- a/arch/um/include/sysdep-i386/archsetjmp.h
+++ b/arch/um/include/sysdep-i386/archsetjmp.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/i386/include/klibc/archsetjmp.h 2 * arch/um/include/sysdep-i386/archsetjmp.h
3 */ 3 */
4 4
5#ifndef _KLIBC_ARCHSETJMP_H 5#ifndef _KLIBC_ARCHSETJMP_H
diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h
index 9a5e1a6ec800..2af8f12ca161 100644
--- a/arch/um/include/sysdep-x86_64/archsetjmp.h
+++ b/arch/um/include/sysdep-x86_64/archsetjmp.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/x86_64/include/klibc/archsetjmp.h 2 * arch/um/include/sysdep-x86_64/archsetjmp.h
3 */ 3 */
4 4
5#ifndef _KLIBC_ARCHSETJMP_H 5#ifndef _KLIBC_ARCHSETJMP_H
diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h
index 8efc1e0f1b84..bcd1a4afb842 100644
--- a/arch/um/include/tlb.h
+++ b/arch/um/include/tlb.h
@@ -14,9 +14,7 @@ struct host_vm_op {
14 struct { 14 struct {
15 unsigned long addr; 15 unsigned long addr;
16 unsigned long len; 16 unsigned long len;
17 unsigned int r:1; 17 unsigned int prot;
18 unsigned int w:1;
19 unsigned int x:1;
20 int fd; 18 int fd;
21 __u64 offset; 19 __u64 offset;
22 } mmap; 20 } mmap;
@@ -27,9 +25,7 @@ struct host_vm_op {
27 struct { 25 struct {
28 unsigned long addr; 26 unsigned long addr;
29 unsigned long len; 27 unsigned long len;
30 unsigned int r:1; 28 unsigned int prot;
31 unsigned int w:1;
32 unsigned int x:1;
33 } mprotect; 29 } mprotect;
34 } u; 30 } u;
35}; 31};
diff --git a/arch/um/include/tt/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h
index b19645f32f24..13a64f61fcf4 100644
--- a/arch/um/include/tt/uaccess-tt.h
+++ b/arch/um/include/tt/uaccess-tt.h
@@ -27,8 +27,6 @@ extern unsigned long uml_physmem;
27#define access_ok_tt(type, addr, size) \ 27#define access_ok_tt(type, addr, size) \
28 (is_stack(addr, size)) 28 (is_stack(addr, size))
29 29
30extern unsigned long get_fault_addr(void);
31
32extern int __do_copy_from_user(void *to, const void *from, int n, 30extern int __do_copy_from_user(void *to, const void *from, int n,
33 void **fault_addr, void **fault_catcher); 31 void **fault_addr, void **fault_catcher);
34extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, 32extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h
index 0363a9b53f8d..e6d7c5aa3f4e 100644
--- a/arch/um/include/um_malloc.h
+++ b/arch/um/include/um_malloc.h
@@ -11,7 +11,6 @@ extern void *um_kmalloc_atomic(int size);
11extern void kfree(const void *ptr); 11extern void kfree(const void *ptr);
12 12
13extern void *um_vmalloc(int size); 13extern void *um_vmalloc(int size);
14extern void *um_vmalloc_atomic(int size);
15extern void vfree(void *ptr); 14extern void vfree(void *ptr);
16 15
17#endif /* __UM_MALLOC_H__ */ 16#endif /* __UM_MALLOC_H__ */
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index acadce3f271f..d380e6d91a90 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -6,6 +6,19 @@
6#ifndef __USER_H__ 6#ifndef __USER_H__
7#define __USER_H__ 7#define __USER_H__
8 8
9/*
10 * The usual definition - copied here because the kernel provides its own,
11 * fancier, type-safe, definition. Using that one would require
12 * copying too much infrastructure for my taste, so userspace files
13 * get less checking than kernel files.
14 */
15#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
16
17/*
18 * This will provide the size_t definition in both kernel and userspace builds
19 */
20#include <linux/types.h>
21
9extern void panic(const char *fmt, ...) 22extern void panic(const char *fmt, ...)
10 __attribute__ ((format (printf, 1, 2))); 23 __attribute__ ((format (printf, 1, 2)));
11extern int printk(const char *fmt, ...) 24extern int printk(const char *fmt, ...)
@@ -13,19 +26,7 @@ extern int printk(const char *fmt, ...)
13extern void schedule(void); 26extern void schedule(void);
14extern int in_aton(char *str); 27extern int in_aton(char *str);
15extern int open_gdb_chan(void); 28extern int open_gdb_chan(void);
16/* These use size_t, however unsigned long is correct on both i386 and x86_64. */ 29extern size_t strlcpy(char *, const char *, size_t);
17extern unsigned long strlcpy(char *, const char *, unsigned long); 30extern size_t strlcat(char *, const char *, size_t);
18extern unsigned long strlcat(char *, const char *, unsigned long);
19 31
20#endif 32#endif
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/include/user_util.h b/arch/um/include/user_util.h
deleted file mode 100644
index 023575f67343..000000000000
--- a/arch/um/include/user_util.h
+++ /dev/null
@@ -1,69 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __USER_UTIL_H__
7#define __USER_UTIL_H__
8
9#include "sysdep/ptrace.h"
10
11/* Copied from kernel.h */
12#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
13
14#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
15
16extern int mode_tt;
17
18extern int grantpt(int __fd);
19extern int unlockpt(int __fd);
20extern char *ptsname(int __fd);
21
22struct cpu_task {
23 int pid;
24 void *task;
25};
26
27extern struct cpu_task cpu_tasks[];
28
29extern void (*sig_info[])(int, union uml_pt_regs *);
30
31extern unsigned long low_physmem;
32extern unsigned long high_physmem;
33extern unsigned long uml_physmem;
34extern unsigned long uml_reserved;
35extern unsigned long end_vm;
36extern unsigned long start_vm;
37extern unsigned long long highmem;
38
39extern char host_info[];
40
41extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
42extern unsigned long _unprotected_end;
43extern unsigned long brk_start;
44
45extern int pty_output_sigio;
46extern int pty_close_sigio;
47
48extern void *add_signal_handler(int sig, void (*handler)(int));
49extern int linux_main(int argc, char **argv);
50extern void set_cmdline(char *cmd);
51extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
52extern int get_pty(void);
53extern int switcheroo(int fd, int prot, void *from, void *to, int size);
54extern void do_exec(int old_pid, int new_pid);
55extern void tracer_panic(char *msg, ...)
56 __attribute__ ((format (printf, 1, 2)));
57extern int detach(int pid, int sig);
58extern int attach(int pid);
59extern void kill_child_dead(int pid);
60extern int cont(int pid);
61extern void check_sigio(void);
62extern void arch_check_bugs(void);
63extern int cpu_feature(char *what, char *buf, int len);
64extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
65extern int arch_fixup(unsigned long address, void *sc_ptr);
66extern void arch_init_thread(void);
67extern int raw(int fd);
68
69#endif
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index e36f92b463ce..87a4e4427d8d 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -97,6 +97,8 @@ SECTIONS
97 .data : { 97 .data : {
98 . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ 98 . = ALIGN(KERNEL_STACK_SIZE); /* init_task */
99 *(.data.init_task) 99 *(.data.init_task)
100 . = ALIGN(KERNEL_STACK_SIZE);
101 *(.data.init_irqstack)
100 *(.data .data.* .gnu.linkonce.d.*) 102 *(.data .data.* .gnu.linkonce.d.*)
101 SORT(CONSTRUCTORS) 103 SORT(CONSTRUCTORS)
102 } 104 }
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 121166400e25..356e50f5aaed 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -10,8 +10,8 @@
10#include "asm/pgtable.h" 10#include "asm/pgtable.h"
11#include "asm/tlbflush.h" 11#include "asm/tlbflush.h"
12#include "asm/uaccess.h" 12#include "asm/uaccess.h"
13#include "user_util.h"
14#include "kern_util.h" 13#include "kern_util.h"
14#include "as-layout.h"
15#include "mem_user.h" 15#include "mem_user.h"
16#include "kern.h" 16#include "kern.h"
17#include "irq_user.h" 17#include "irq_user.h"
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index 8cde431348cc..d4f1d1ab252b 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,intel.linux}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -10,7 +10,6 @@
10#include "linux/mqueue.h" 10#include "linux/mqueue.h"
11#include "asm/uaccess.h" 11#include "asm/uaccess.h"
12#include "asm/pgtable.h" 12#include "asm/pgtable.h"
13#include "user_util.h"
14#include "mem_user.h" 13#include "mem_user.h"
15#include "os.h" 14#include "os.h"
16 15
@@ -34,28 +33,20 @@ EXPORT_SYMBOL(init_task);
34/* 33/*
35 * Initial thread structure. 34 * Initial thread structure.
36 * 35 *
37 * We need to make sure that this is 16384-byte aligned due to the 36 * We need to make sure that this is aligned due to the
38 * way process stacks are handled. This is done by having a special 37 * way process stacks are handled. This is done by having a special
39 * "init_task" linker map entry.. 38 * "init_task" linker map entry..
40 */ 39 */
41 40
42union thread_union init_thread_union 41union thread_union init_thread_union
43__attribute__((__section__(".data.init_task"))) = 42 __attribute__((__section__(".data.init_task"))) =
44{ INIT_THREAD_INFO(init_task) }; 43 { INIT_THREAD_INFO(init_task) };
44
45union thread_union cpu0_irqstack
46 __attribute__((__section__(".data.init_irqstack"))) =
47 { INIT_THREAD_INFO(init_task) };
45 48
46void unprotect_stack(unsigned long stack) 49void unprotect_stack(unsigned long stack)
47{ 50{
48 os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, 51 os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0);
49 1, 1, 0);
50} 52}
51
52/*
53 * Overrides for Emacs so that we follow Linus's tabbing style.
54 * Emacs will notice this stuff at the end of the file and automatically
55 * adjust the settings for this buffer only. This must remain at the end
56 * of the file.
57 * ---------------------------------------------------------------------------
58 * Local variables:
59 * c-file-style: "linux"
60 * End:
61 */
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 82ecf904b09c..16dc43e9d940 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -7,7 +7,6 @@
7#include "linux/bootmem.h" 7#include "linux/bootmem.h"
8#include "linux/initrd.h" 8#include "linux/initrd.h"
9#include "asm/types.h" 9#include "asm/types.h"
10#include "user_util.h"
11#include "kern_util.h" 10#include "kern_util.h"
12#include "initrd.h" 11#include "initrd.h"
13#include "init.h" 12#include "init.h"
@@ -22,12 +21,20 @@ static int __init read_initrd(void)
22 long long size; 21 long long size;
23 int err; 22 int err;
24 23
25 if(initrd == NULL) return 0; 24 if(initrd == NULL)
25 return 0;
26
26 err = os_file_size(initrd, &size); 27 err = os_file_size(initrd, &size);
27 if(err) return 0; 28 if(err)
29 return 0;
30
28 area = alloc_bootmem(size); 31 area = alloc_bootmem(size);
29 if(area == NULL) return 0; 32 if(area == NULL)
30 if(load_initrd(initrd, area, size) == -1) return 0; 33 return 0;
34
35 if(load_initrd(initrd, area, size) == -1)
36 return 0;
37
31 initrd_start = (unsigned long) area; 38 initrd_start = (unsigned long) area;
32 initrd_end = initrd_start + size; 39 initrd_end = initrd_start + size;
33 return 0; 40 return 0;
@@ -54,25 +61,15 @@ int load_initrd(char *filename, void *buf, int size)
54 fd = os_open_file(filename, of_read(OPENFLAGS()), 0); 61 fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
55 if(fd < 0){ 62 if(fd < 0){
56 printk("Opening '%s' failed - err = %d\n", filename, -fd); 63 printk("Opening '%s' failed - err = %d\n", filename, -fd);
57 return(-1); 64 return -1;
58 } 65 }
59 n = os_read_file(fd, buf, size); 66 n = os_read_file(fd, buf, size);
60 if(n != size){ 67 if(n != size){
61 printk("Read of %d bytes from '%s' failed, err = %d\n", size, 68 printk("Read of %d bytes from '%s' failed, err = %d\n", size,
62 filename, -n); 69 filename, -n);
63 return(-1); 70 return -1;
64 } 71 }
65 72
66 os_close_file(fd); 73 os_close_file(fd);
67 return(0); 74 return 0;
68} 75}
69/*
70 * Overrides for Emacs so that we follow Linus's tabbing style.
71 * Emacs will notice this stuff at the end of the file and automatically
72 * adjust the settings for this buffer only. This must remain at the end
73 * of the file.
74 * ---------------------------------------------------------------------------
75 * Local variables:
76 * c-file-style: "linux"
77 * End:
78 */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index dbf2f5bc842f..dba04d88b432 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: 4 * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
@@ -25,7 +25,6 @@
25#include "asm/system.h" 25#include "asm/system.h"
26#include "asm/errno.h" 26#include "asm/errno.h"
27#include "asm/uaccess.h" 27#include "asm/uaccess.h"
28#include "user_util.h"
29#include "kern_util.h" 28#include "kern_util.h"
30#include "irq_user.h" 29#include "irq_user.h"
31#include "irq_kern.h" 30#include "irq_kern.h"
@@ -33,6 +32,7 @@
33#include "sigio.h" 32#include "sigio.h"
34#include "um_malloc.h" 33#include "um_malloc.h"
35#include "misc_constants.h" 34#include "misc_constants.h"
35#include "as-layout.h"
36 36
37/* 37/*
38 * Generic, controller-independent functions: 38 * Generic, controller-independent functions:
@@ -54,7 +54,7 @@ int show_interrupts(struct seq_file *p, void *v)
54 if (i < NR_IRQS) { 54 if (i < NR_IRQS) {
55 spin_lock_irqsave(&irq_desc[i].lock, flags); 55 spin_lock_irqsave(&irq_desc[i].lock, flags);
56 action = irq_desc[i].action; 56 action = irq_desc[i].action;
57 if (!action) 57 if (!action)
58 goto skip; 58 goto skip;
59 seq_printf(p, "%3d: ",i); 59 seq_printf(p, "%3d: ",i);
60#ifndef CONFIG_SMP 60#ifndef CONFIG_SMP
@@ -79,6 +79,14 @@ skip:
79 return 0; 79 return 0;
80} 80}
81 81
82/*
83 * This list is accessed under irq_lock, except in sigio_handler,
84 * where it is safe from being modified. IRQ handlers won't change it -
85 * if an IRQ source has vanished, it will be freed by free_irqs just
86 * before returning from sigio_handler. That will process a separate
87 * list of irqs to free, with its own locking, coming back here to
88 * remove list elements, taking the irq_lock to do so.
89 */
82static struct irq_fd *active_fds = NULL; 90static struct irq_fd *active_fds = NULL;
83static struct irq_fd **last_irq_ptr = &active_fds; 91static struct irq_fd **last_irq_ptr = &active_fds;
84 92
@@ -244,6 +252,7 @@ void free_irq_by_fd(int fd)
244 free_irq_by_cb(same_fd, &fd); 252 free_irq_by_cb(same_fd, &fd);
245} 253}
246 254
255/* Must be called with irq_lock held */
247static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) 256static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
248{ 257{
249 struct irq_fd *irq; 258 struct irq_fd *irq;
@@ -309,6 +318,12 @@ void deactivate_fd(int fd, int irqnum)
309 ignore_sigio_fd(fd); 318 ignore_sigio_fd(fd);
310} 319}
311 320
321/*
322 * Called just before shutdown in order to provide a clean exec
323 * environment in case the system is rebooting. No locking because
324 * that would cause a pointless shutdown hang if something hadn't
325 * released the lock.
326 */
312int deactivate_all_fds(void) 327int deactivate_all_fds(void)
313{ 328{
314 struct irq_fd *irq; 329 struct irq_fd *irq;
@@ -454,3 +469,113 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
454 out: 469 out:
455 return err; 470 return err;
456} 471}
472
473/*
474 * IRQ stack entry and exit:
475 *
476 * Unlike i386, UML doesn't receive IRQs on the normal kernel stack
477 * and switch over to the IRQ stack after some preparation. We use
478 * sigaltstack to receive signals on a separate stack from the start.
479 * These two functions make sure the rest of the kernel won't be too
480 * upset by being on a different stack. The IRQ stack has a
481 * thread_info structure at the bottom so that current et al continue
482 * to work.
483 *
484 * to_irq_stack copies the current task's thread_info to the IRQ stack
485 * thread_info and sets the tasks's stack to point to the IRQ stack.
486 *
487 * from_irq_stack copies the thread_info struct back (flags may have
488 * been modified) and resets the task's stack pointer.
489 *
490 * Tricky bits -
491 *
492 * What happens when two signals race each other? UML doesn't block
493 * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal
494 * could arrive while a previous one is still setting up the
495 * thread_info.
496 *
497 * There are three cases -
498 * The first interrupt on the stack - sets up the thread_info and
499 * handles the interrupt
500 * A nested interrupt interrupting the copying of the thread_info -
501 * can't handle the interrupt, as the stack is in an unknown state
502 * A nested interrupt not interrupting the copying of the
503 * thread_info - doesn't do any setup, just handles the interrupt
504 *
505 * The first job is to figure out whether we interrupted stack setup.
506 * This is done by xchging the signal mask with thread_info->pending.
507 * If the value that comes back is zero, then there is no setup in
508 * progress, and the interrupt can be handled. If the value is
509 * non-zero, then there is stack setup in progress. In order to have
510 * the interrupt handled, we leave our signal in the mask, and it will
511 * be handled by the upper handler after it has set up the stack.
512 *
513 * Next is to figure out whether we are the outer handler or a nested
514 * one. As part of setting up the stack, thread_info->real_thread is
515 * set to non-NULL (and is reset to NULL on exit). This is the
516 * nesting indicator. If it is non-NULL, then the stack is already
517 * set up and the handler can run.
518 */
519
520static unsigned long pending_mask;
521
522unsigned long to_irq_stack(int sig, unsigned long *mask_out)
523{
524 struct thread_info *ti;
525 unsigned long mask, old;
526 int nested;
527
528 mask = xchg(&pending_mask, 1 << sig);
529 if(mask != 0){
530 /* If any interrupts come in at this point, we want to
531 * make sure that their bits aren't lost by our
532 * putting our bit in. So, this loop accumulates bits
533 * until xchg returns the same value that we put in.
534 * When that happens, there were no new interrupts,
535 * and pending_mask contains a bit for each interrupt
536 * that came in.
537 */
538 old = 1 << sig;
539 do {
540 old |= mask;
541 mask = xchg(&pending_mask, old);
542 } while(mask != old);
543 return 1;
544 }
545
546 ti = current_thread_info();
547 nested = (ti->real_thread != NULL);
548 if(!nested){
549 struct task_struct *task;
550 struct thread_info *tti;
551
552 task = cpu_tasks[ti->cpu].task;
553 tti = task_thread_info(task);
554 *ti = *tti;
555 ti->real_thread = tti;
556 task->stack = ti;
557 }
558
559 mask = xchg(&pending_mask, 0);
560 *mask_out |= mask | nested;
561 return 0;
562}
563
564unsigned long from_irq_stack(int nested)
565{
566 struct thread_info *ti, *to;
567 unsigned long mask;
568
569 ti = current_thread_info();
570
571 pending_mask = 1;
572
573 to = ti->real_thread;
574 current->stack = to;
575 ti->real_thread = NULL;
576 *to = *ti;
577
578 mask = xchg(&pending_mask, 0);
579 return mask & ~1;
580}
581
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 0e00cf93f900..7b3e53fb8070 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -16,7 +16,7 @@
16#include "asm/page.h" 16#include "asm/page.h"
17#include "asm/tlbflush.h" 17#include "asm/tlbflush.h"
18#include "kern_util.h" 18#include "kern_util.h"
19#include "user_util.h" 19#include "as-layout.h"
20#include "mem_user.h" 20#include "mem_user.h"
21#include "os.h" 21#include "os.h"
22 22
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index df7d662b98ce..72ff85693a39 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -13,8 +13,8 @@
13#include "asm/page.h" 13#include "asm/page.h"
14#include "asm/fixmap.h" 14#include "asm/fixmap.h"
15#include "asm/pgalloc.h" 15#include "asm/pgalloc.h"
16#include "user_util.h"
17#include "kern_util.h" 16#include "kern_util.h"
17#include "as-layout.h"
18#include "kern.h" 18#include "kern.h"
19#include "mem_user.h" 19#include "mem_user.h"
20#include "uml_uaccess.h" 20#include "uml_uaccess.h"
@@ -216,7 +216,7 @@ static void __init fixaddr_user_init( void)
216#endif 216#endif
217} 217}
218 218
219void paging_init(void) 219void __init paging_init(void)
220{ 220{
221 unsigned long zones_size[MAX_NR_ZONES], vaddr; 221 unsigned long zones_size[MAX_NR_ZONES], vaddr;
222 int i; 222 int i;
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 638f3b5f6094..3ba6e4c841da 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -13,7 +13,7 @@
13#include "asm/types.h" 13#include "asm/types.h"
14#include "asm/pgtable.h" 14#include "asm/pgtable.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user_util.h" 16#include "as-layout.h"
17#include "mode_kern.h" 17#include "mode_kern.h"
18#include "mem.h" 18#include "mem.h"
19#include "mem_user.h" 19#include "mem_user.h"
@@ -21,229 +21,8 @@
21#include "kern.h" 21#include "kern.h"
22#include "init.h" 22#include "init.h"
23 23
24struct phys_desc {
25 struct rb_node rb;
26 int fd;
27 __u64 offset;
28 void *virt;
29 unsigned long phys;
30 struct list_head list;
31};
32
33static struct rb_root phys_mappings = RB_ROOT;
34
35static struct rb_node **find_rb(void *virt)
36{
37 struct rb_node **n = &phys_mappings.rb_node;
38 struct phys_desc *d;
39
40 while(*n != NULL){
41 d = rb_entry(*n, struct phys_desc, rb);
42 if(d->virt == virt)
43 return n;
44
45 if(d->virt > virt)
46 n = &(*n)->rb_left;
47 else
48 n = &(*n)->rb_right;
49 }
50
51 return n;
52}
53
54static struct phys_desc *find_phys_mapping(void *virt)
55{
56 struct rb_node **n = find_rb(virt);
57
58 if(*n == NULL)
59 return NULL;
60
61 return rb_entry(*n, struct phys_desc, rb);
62}
63
64static void insert_phys_mapping(struct phys_desc *desc)
65{
66 struct rb_node **n = find_rb(desc->virt);
67
68 if(*n != NULL)
69 panic("Physical remapping for %p already present",
70 desc->virt);
71
72 rb_link_node(&desc->rb, rb_parent(*n), n);
73 rb_insert_color(&desc->rb, &phys_mappings);
74}
75
76LIST_HEAD(descriptor_mappings);
77
78struct desc_mapping {
79 int fd;
80 struct list_head list;
81 struct list_head pages;
82};
83
84static struct desc_mapping *find_mapping(int fd)
85{
86 struct desc_mapping *desc;
87 struct list_head *ele;
88
89 list_for_each(ele, &descriptor_mappings){
90 desc = list_entry(ele, struct desc_mapping, list);
91 if(desc->fd == fd)
92 return desc;
93 }
94
95 return NULL;
96}
97
98static struct desc_mapping *descriptor_mapping(int fd)
99{
100 struct desc_mapping *desc;
101
102 desc = find_mapping(fd);
103 if(desc != NULL)
104 return desc;
105
106 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
107 if(desc == NULL)
108 return NULL;
109
110 *desc = ((struct desc_mapping)
111 { .fd = fd,
112 .list = LIST_HEAD_INIT(desc->list),
113 .pages = LIST_HEAD_INIT(desc->pages) });
114 list_add(&desc->list, &descriptor_mappings);
115
116 return desc;
117}
118
119int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
120{
121 struct desc_mapping *fd_maps;
122 struct phys_desc *desc;
123 unsigned long phys;
124 int err;
125
126 fd_maps = descriptor_mapping(fd);
127 if(fd_maps == NULL)
128 return -ENOMEM;
129
130 phys = __pa(virt);
131 desc = find_phys_mapping(virt);
132 if(desc != NULL)
133 panic("Address 0x%p is already substituted\n", virt);
134
135 err = -ENOMEM;
136 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
137 if(desc == NULL)
138 goto out;
139
140 *desc = ((struct phys_desc)
141 { .fd = fd,
142 .offset = offset,
143 .virt = virt,
144 .phys = __pa(virt),
145 .list = LIST_HEAD_INIT(desc->list) });
146 insert_phys_mapping(desc);
147
148 list_add(&desc->list, &fd_maps->pages);
149
150 virt = (void *) ((unsigned long) virt & PAGE_MASK);
151 err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0);
152 if(!err)
153 goto out;
154
155 rb_erase(&desc->rb, &phys_mappings);
156 kfree(desc);
157 out:
158 return err;
159}
160
161static int physmem_fd = -1; 24static int physmem_fd = -1;
162 25
163static void remove_mapping(struct phys_desc *desc)
164{
165 void *virt = desc->virt;
166 int err;
167
168 rb_erase(&desc->rb, &phys_mappings);
169 list_del(&desc->list);
170 kfree(desc);
171
172 err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0);
173 if(err)
174 panic("Failed to unmap block device page from physical memory, "
175 "errno = %d", -err);
176}
177
178int physmem_remove_mapping(void *virt)
179{
180 struct phys_desc *desc;
181
182 virt = (void *) ((unsigned long) virt & PAGE_MASK);
183 desc = find_phys_mapping(virt);
184 if(desc == NULL)
185 return 0;
186
187 remove_mapping(desc);
188 return 1;
189}
190
191void physmem_forget_descriptor(int fd)
192{
193 struct desc_mapping *desc;
194 struct phys_desc *page;
195 struct list_head *ele, *next;
196 __u64 offset;
197 void *addr;
198 int err;
199
200 desc = find_mapping(fd);
201 if(desc == NULL)
202 return;
203
204 list_for_each_safe(ele, next, &desc->pages){
205 page = list_entry(ele, struct phys_desc, list);
206 offset = page->offset;
207 addr = page->virt;
208 remove_mapping(page);
209 err = os_seek_file(fd, offset);
210 if(err)
211 panic("physmem_forget_descriptor - failed to seek "
212 "to %lld in fd %d, error = %d\n",
213 offset, fd, -err);
214 err = os_read_file(fd, addr, PAGE_SIZE);
215 if(err < 0)
216 panic("physmem_forget_descriptor - failed to read "
217 "from fd %d to 0x%p, error = %d\n",
218 fd, addr, -err);
219 }
220
221 list_del(&desc->list);
222 kfree(desc);
223}
224
225EXPORT_SYMBOL(physmem_forget_descriptor);
226EXPORT_SYMBOL(physmem_remove_mapping);
227EXPORT_SYMBOL(physmem_subst_mapping);
228
229void arch_free_page(struct page *page, int order)
230{
231 void *virt;
232 int i;
233
234 for(i = 0; i < (1 << order); i++){
235 virt = __va(page_to_phys(page + i));
236 physmem_remove_mapping(virt);
237 }
238}
239
240int is_remapped(void *virt)
241{
242 struct phys_desc *desc = find_phys_mapping(virt);
243
244 return desc != NULL;
245}
246
247/* Changed during early boot */ 26/* Changed during early boot */
248unsigned long high_physmem; 27unsigned long high_physmem;
249 28
@@ -350,14 +129,9 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
350 129
351int phys_mapping(unsigned long phys, __u64 *offset_out) 130int phys_mapping(unsigned long phys, __u64 *offset_out)
352{ 131{
353 struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK));
354 int fd = -1; 132 int fd = -1;
355 133
356 if(desc != NULL){ 134 if(phys < physmem_size){
357 fd = desc->fd;
358 *offset_out = desc->offset;
359 }
360 else if(phys < physmem_size){
361 fd = physmem_fd; 135 fd = physmem_fd;
362 *offset_out = phys; 136 *offset_out = phys;
363 } 137 }
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 348b272bb766..8d2c5496532b 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -32,8 +32,8 @@
32#include "asm/tlbflush.h" 32#include "asm/tlbflush.h"
33#include "asm/uaccess.h" 33#include "asm/uaccess.h"
34#include "asm/user.h" 34#include "asm/user.h"
35#include "user_util.h"
36#include "kern_util.h" 35#include "kern_util.h"
36#include "as-layout.h"
37#include "kern.h" 37#include "kern.h"
38#include "signal_kern.h" 38#include "signal_kern.h"
39#include "init.h" 39#include "init.h"
@@ -54,11 +54,9 @@
54 */ 54 */
55struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; 55struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
56 56
57int external_pid(void *t) 57static inline int external_pid(struct task_struct *task)
58{ 58{
59 struct task_struct *task = t ? t : current; 59 return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task);
60
61 return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
62} 60}
63 61
64int pid_to_processor_id(int pid) 62int pid_to_processor_id(int pid)
@@ -66,9 +64,10 @@ int pid_to_processor_id(int pid)
66 int i; 64 int i;
67 65
68 for(i = 0; i < ncpus; i++){ 66 for(i = 0; i < ncpus; i++){
69 if(cpu_tasks[i].pid == pid) return(i); 67 if(cpu_tasks[i].pid == pid)
68 return i;
70 } 69 }
71 return(-1); 70 return -1;
72} 71}
73 72
74void free_stack(unsigned long stack, int order) 73void free_stack(unsigned long stack, int order)
@@ -85,9 +84,9 @@ unsigned long alloc_stack(int order, int atomic)
85 flags = GFP_ATOMIC; 84 flags = GFP_ATOMIC;
86 page = __get_free_pages(flags, order); 85 page = __get_free_pages(flags, order);
87 if(page == 0) 86 if(page == 0)
88 return(0); 87 return 0;
89 stack_protections(page); 88 stack_protections(page);
90 return(page); 89 return page;
91} 90}
92 91
93int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 92int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
@@ -98,15 +97,11 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
98 current->thread.request.u.thread.arg = arg; 97 current->thread.request.u.thread.arg = arg;
99 pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, 98 pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
100 &current->thread.regs, 0, NULL, NULL); 99 &current->thread.regs, 0, NULL, NULL);
101 if(pid < 0) 100 return pid;
102 panic("do_fork failed in kernel_thread, errno = %d", pid);
103 return(pid);
104} 101}
105 102
106void set_current(void *t) 103static inline void set_current(struct task_struct *task)
107{ 104{
108 struct task_struct *task = t;
109
110 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) 105 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
111 { external_pid(task), task }); 106 { external_pid(task), task });
112} 107}
@@ -128,14 +123,16 @@ void *_switch_to(void *prev, void *next, void *last)
128 prev= current; 123 prev= current;
129 } while(current->thread.saved_task); 124 } while(current->thread.saved_task);
130 125
131 return(current->thread.prev_sched); 126 return current->thread.prev_sched;
132 127
133} 128}
134 129
135void interrupt_end(void) 130void interrupt_end(void)
136{ 131{
137 if(need_resched()) schedule(); 132 if(need_resched())
138 if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); 133 schedule();
134 if(test_tsk_thread_flag(current, TIF_SIGPENDING))
135 do_signal();
139} 136}
140 137
141void release_thread(struct task_struct *task) 138void release_thread(struct task_struct *task)
@@ -150,7 +147,7 @@ void exit_thread(void)
150 147
151void *get_current(void) 148void *get_current(void)
152{ 149{
153 return(current); 150 return current;
154} 151}
155 152
156int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, 153int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
@@ -188,15 +185,12 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
188 kmalloc_ok = save_kmalloc_ok; 185 kmalloc_ok = save_kmalloc_ok;
189} 186}
190 187
188#ifdef CONFIG_MODE_TT
191unsigned long stack_sp(unsigned long page) 189unsigned long stack_sp(unsigned long page)
192{ 190{
193 return(page + PAGE_SIZE - sizeof(void *)); 191 return page + PAGE_SIZE - sizeof(void *);
194}
195
196int current_pid(void)
197{
198 return(current->pid);
199} 192}
193#endif
200 194
201void default_idle(void) 195void default_idle(void)
202{ 196{
@@ -221,11 +215,6 @@ void cpu_idle(void)
221 CHOOSE_MODE(init_idle_tt(), init_idle_skas()); 215 CHOOSE_MODE(init_idle_tt(), init_idle_skas());
222} 216}
223 217
224int page_size(void)
225{
226 return(PAGE_SIZE);
227}
228
229void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 218void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
230 pte_t *pte_out) 219 pte_t *pte_out)
231{ 220{
@@ -236,68 +225,43 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
236 pte_t ptent; 225 pte_t ptent;
237 226
238 if(task->mm == NULL) 227 if(task->mm == NULL)
239 return(ERR_PTR(-EINVAL)); 228 return ERR_PTR(-EINVAL);
240 pgd = pgd_offset(task->mm, addr); 229 pgd = pgd_offset(task->mm, addr);
241 if(!pgd_present(*pgd)) 230 if(!pgd_present(*pgd))
242 return(ERR_PTR(-EINVAL)); 231 return ERR_PTR(-EINVAL);
243 232
244 pud = pud_offset(pgd, addr); 233 pud = pud_offset(pgd, addr);
245 if(!pud_present(*pud)) 234 if(!pud_present(*pud))
246 return(ERR_PTR(-EINVAL)); 235 return ERR_PTR(-EINVAL);
247 236
248 pmd = pmd_offset(pud, addr); 237 pmd = pmd_offset(pud, addr);
249 if(!pmd_present(*pmd)) 238 if(!pmd_present(*pmd))
250 return(ERR_PTR(-EINVAL)); 239 return ERR_PTR(-EINVAL);
251 240
252 pte = pte_offset_kernel(pmd, addr); 241 pte = pte_offset_kernel(pmd, addr);
253 ptent = *pte; 242 ptent = *pte;
254 if(!pte_present(ptent)) 243 if(!pte_present(ptent))
255 return(ERR_PTR(-EINVAL)); 244 return ERR_PTR(-EINVAL);
256 245
257 if(pte_out != NULL) 246 if(pte_out != NULL)
258 *pte_out = ptent; 247 *pte_out = ptent;
259 return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK)); 248 return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
260} 249}
261 250
262char *current_cmd(void) 251char *current_cmd(void)
263{ 252{
264#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) 253#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
265 return("(Unknown)"); 254 return "(Unknown)";
266#else 255#else
267 void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); 256 void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
268 return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); 257 return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
269#endif 258#endif
270} 259}
271 260
272void force_sigbus(void)
273{
274 printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
275 current->pid);
276 lock_kernel();
277 sigaddset(&current->pending.signal, SIGBUS);
278 recalc_sigpending();
279 current->flags |= PF_SIGNALED;
280 do_exit(SIGBUS | 0x80);
281}
282
283void dump_thread(struct pt_regs *regs, struct user *u) 261void dump_thread(struct pt_regs *regs, struct user *u)
284{ 262{
285} 263}
286 264
287void enable_hlt(void)
288{
289 panic("enable_hlt");
290}
291
292EXPORT_SYMBOL(enable_hlt);
293
294void disable_hlt(void)
295{
296 panic("disable_hlt");
297}
298
299EXPORT_SYMBOL(disable_hlt);
300
301void *um_kmalloc(int size) 265void *um_kmalloc(int size)
302{ 266{
303 return kmalloc(size, GFP_KERNEL); 267 return kmalloc(size, GFP_KERNEL);
@@ -313,36 +277,17 @@ void *um_vmalloc(int size)
313 return vmalloc(size); 277 return vmalloc(size);
314} 278}
315 279
316void *um_vmalloc_atomic(int size)
317{
318 return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
319}
320
321int __cant_sleep(void) { 280int __cant_sleep(void) {
322 return in_atomic() || irqs_disabled() || in_interrupt(); 281 return in_atomic() || irqs_disabled() || in_interrupt();
323 /* Is in_interrupt() really needed? */ 282 /* Is in_interrupt() really needed? */
324} 283}
325 284
326unsigned long get_fault_addr(void)
327{
328 return((unsigned long) current->thread.fault_addr);
329}
330
331EXPORT_SYMBOL(get_fault_addr);
332
333void not_implemented(void)
334{
335 printk(KERN_DEBUG "Something isn't implemented in here\n");
336}
337
338EXPORT_SYMBOL(not_implemented);
339
340int user_context(unsigned long sp) 285int user_context(unsigned long sp)
341{ 286{
342 unsigned long stack; 287 unsigned long stack;
343 288
344 stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); 289 stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
345 return(stack != (unsigned long) current_thread); 290 return stack != (unsigned long) current_thread;
346} 291}
347 292
348extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; 293extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -363,22 +308,22 @@ char *uml_strdup(char *string)
363 308
364int copy_to_user_proc(void __user *to, void *from, int size) 309int copy_to_user_proc(void __user *to, void *from, int size)
365{ 310{
366 return(copy_to_user(to, from, size)); 311 return copy_to_user(to, from, size);
367} 312}
368 313
369int copy_from_user_proc(void *to, void __user *from, int size) 314int copy_from_user_proc(void *to, void __user *from, int size)
370{ 315{
371 return(copy_from_user(to, from, size)); 316 return copy_from_user(to, from, size);
372} 317}
373 318
374int clear_user_proc(void __user *buf, int size) 319int clear_user_proc(void __user *buf, int size)
375{ 320{
376 return(clear_user(buf, size)); 321 return clear_user(buf, size);
377} 322}
378 323
379int strlen_user_proc(char __user *str) 324int strlen_user_proc(char __user *str)
380{ 325{
381 return(strlen_user(str)); 326 return strlen_user(str);
382} 327}
383 328
384int smp_sigio_handler(void) 329int smp_sigio_handler(void)
@@ -387,14 +332,14 @@ int smp_sigio_handler(void)
387 int cpu = current_thread->cpu; 332 int cpu = current_thread->cpu;
388 IPI_handler(cpu); 333 IPI_handler(cpu);
389 if(cpu != 0) 334 if(cpu != 0)
390 return(1); 335 return 1;
391#endif 336#endif
392 return(0); 337 return 0;
393} 338}
394 339
395int cpu(void) 340int cpu(void)
396{ 341{
397 return(current_thread->cpu); 342 return current_thread->cpu;
398} 343}
399 344
400static atomic_t using_sysemu = ATOMIC_INIT(0); 345static atomic_t using_sysemu = ATOMIC_INIT(0);
@@ -443,7 +388,7 @@ int __init make_proc_sysemu(void)
443 if (ent == NULL) 388 if (ent == NULL)
444 { 389 {
445 printk(KERN_WARNING "Failed to register /proc/sysemu\n"); 390 printk(KERN_WARNING "Failed to register /proc/sysemu\n");
446 return(0); 391 return 0;
447 } 392 }
448 393
449 ent->read_proc = proc_read_sysemu; 394 ent->read_proc = proc_read_sysemu;
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index f602623644aa..7e4305a1fd3c 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -6,7 +6,6 @@
6#include "linux/module.h" 6#include "linux/module.h"
7#include "linux/sched.h" 7#include "linux/sched.h"
8#include "asm/smp.h" 8#include "asm/smp.h"
9#include "user_util.h"
10#include "kern_util.h" 9#include "kern_util.h"
11#include "kern.h" 10#include "kern.h"
12#include "os.h" 11#include "os.h"
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 3c798cdde550..c4020c3d7857 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -17,7 +17,6 @@
17#include "asm/signal.h" 17#include "asm/signal.h"
18#include "asm/uaccess.h" 18#include "asm/uaccess.h"
19#include "asm/unistd.h" 19#include "asm/unistd.h"
20#include "user_util.h"
21#include "asm/ucontext.h" 20#include "asm/ucontext.h"
22#include "kern_util.h" 21#include "kern_util.h"
23#include "signal_kern.h" 22#include "signal_kern.h"
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
index 54b795951372..580eb6468949 100644
--- a/arch/um/kernel/skas/exec.c
+++ b/arch/um/kernel/skas/exec.c
@@ -17,7 +17,17 @@
17 17
18void flush_thread_skas(void) 18void flush_thread_skas(void)
19{ 19{
20 force_flush_all(); 20 void *data = NULL;
21 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
22 int ret;
23
24 ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
25 if(ret){
26 printk("flush_thread_skas - clearing address space failed, "
27 "err = %d\n", ret);
28 force_sig(SIGKILL, current);
29 }
30
21 switch_mm_skas(&current->mm->context.skas.id); 31 switch_mm_skas(&current->mm->context.skas.id);
22} 32}
23 33
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index ae4fa71d3b8b..2a69a7ce5792 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -13,9 +13,9 @@
13#include "asm/uaccess.h" 13#include "asm/uaccess.h"
14#include "asm/atomic.h" 14#include "asm/atomic.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "as-layout.h"
16#include "skas.h" 17#include "skas.h"
17#include "os.h" 18#include "os.h"
18#include "user_util.h"
19#include "tlb.h" 19#include "tlb.h"
20#include "kern.h" 20#include "kern.h"
21#include "mode.h" 21#include "mode.h"
@@ -163,8 +163,12 @@ static int start_kernel_proc(void *unused)
163 163
164extern int userspace_pid[]; 164extern int userspace_pid[];
165 165
166extern char cpu0_irqstack[];
167
166int start_uml_skas(void) 168int start_uml_skas(void)
167{ 169{
170 stack_protections((unsigned long) &cpu0_irqstack);
171 set_sigstack(cpu0_irqstack, THREAD_SIZE);
168 if(proc_mm) 172 if(proc_mm)
169 userspace_pid[0] = start_userspace(0); 173 userspace_pid[0] = start_userspace(0);
170 174
@@ -178,20 +182,23 @@ int start_uml_skas(void)
178 182
179int external_pid_skas(struct task_struct *task) 183int external_pid_skas(struct task_struct *task)
180{ 184{
181#warning Need to look up userspace_pid by cpu 185 /* FIXME: Need to look up userspace_pid by cpu */
182 return(userspace_pid[0]); 186 return(userspace_pid[0]);
183} 187}
184 188
185int thread_pid_skas(struct task_struct *task) 189int thread_pid_skas(struct task_struct *task)
186{ 190{
187#warning Need to look up userspace_pid by cpu 191 /* FIXME: Need to look up userspace_pid by cpu */
188 return(userspace_pid[0]); 192 return(userspace_pid[0]);
189} 193}
190 194
191void kill_off_processes_skas(void) 195void kill_off_processes_skas(void)
192{ 196{
193 if(proc_mm) 197 if(proc_mm)
194#warning need to loop over userspace_pids in kill_off_processes_skas 198 /*
199 * FIXME: need to loop over userspace_pids in
200 * kill_off_processes_skas
201 */
195 os_kill_ptraced_process(userspace_pid[0], 1); 202 os_kill_ptraced_process(userspace_pid[0], 1);
196 else { 203 else {
197 struct task_struct *p; 204 struct task_struct *p;
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
index 27eb29ce666b..c0f0693743ba 100644
--- a/arch/um/kernel/skas/tlb.c
+++ b/arch/um/kernel/skas/tlb.c
@@ -10,7 +10,6 @@
10#include "asm/page.h" 10#include "asm/page.h"
11#include "asm/pgtable.h" 11#include "asm/pgtable.h"
12#include "asm/mmu.h" 12#include "asm/mmu.h"
13#include "user_util.h"
14#include "mem_user.h" 13#include "mem_user.h"
15#include "mem.h" 14#include "mem.h"
16#include "skas.h" 15#include "skas.h"
@@ -28,19 +27,17 @@ static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
28 switch(op->type){ 27 switch(op->type){
29 case MMAP: 28 case MMAP:
30 ret = map(&mmu->skas.id, op->u.mmap.addr, 29 ret = map(&mmu->skas.id, op->u.mmap.addr,
31 op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, 30 op->u.mmap.len, op->u.mmap.prot,
32 op->u.mmap.x, op->u.mmap.fd, 31 op->u.mmap.fd, op->u.mmap.offset, finished,
33 op->u.mmap.offset, finished, flush); 32 flush);
34 break; 33 break;
35 case MUNMAP: 34 case MUNMAP:
36 ret = unmap(&mmu->skas.id, 35 ret = unmap(&mmu->skas.id, op->u.munmap.addr,
37 (void *) op->u.munmap.addr,
38 op->u.munmap.len, finished, flush); 36 op->u.munmap.len, finished, flush);
39 break; 37 break;
40 case MPROTECT: 38 case MPROTECT:
41 ret = protect(&mmu->skas.id, op->u.mprotect.addr, 39 ret = protect(&mmu->skas.id, op->u.mprotect.addr,
42 op->u.mprotect.len, op->u.mprotect.r, 40 op->u.mprotect.len, op->u.mprotect.prot,
43 op->u.mprotect.w, op->u.mprotect.x,
44 finished, flush); 41 finished, flush);
45 break; 42 break;
46 default: 43 default:
@@ -92,6 +89,76 @@ void flush_tlb_mm_skas(struct mm_struct *mm)
92 89
93void force_flush_all_skas(void) 90void force_flush_all_skas(void)
94{ 91{
95 unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; 92 struct mm_struct *mm = current->mm;
96 fix_range(current->mm, 0, end, 1); 93 struct vm_area_struct *vma = mm->mmap;
94
95 while(vma != NULL) {
96 fix_range(mm, vma->vm_start, vma->vm_end, 1);
97 vma = vma->vm_next;
98 }
99}
100
101void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address)
102{
103 pgd_t *pgd;
104 pud_t *pud;
105 pmd_t *pmd;
106 pte_t *pte;
107 struct mm_struct *mm = vma->vm_mm;
108 void *flush = NULL;
109 int r, w, x, prot, err = 0;
110 struct mm_id *mm_id;
111
112 pgd = pgd_offset(mm, address);
113 if(!pgd_present(*pgd))
114 goto kill;
115
116 pud = pud_offset(pgd, address);
117 if(!pud_present(*pud))
118 goto kill;
119
120 pmd = pmd_offset(pud, address);
121 if(!pmd_present(*pmd))
122 goto kill;
123
124 pte = pte_offset_kernel(pmd, address);
125
126 r = pte_read(*pte);
127 w = pte_write(*pte);
128 x = pte_exec(*pte);
129 if (!pte_young(*pte)) {
130 r = 0;
131 w = 0;
132 } else if (!pte_dirty(*pte)) {
133 w = 0;
134 }
135
136 mm_id = &mm->context.skas.id;
137 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
138 (x ? UM_PROT_EXEC : 0));
139 if(pte_newpage(*pte)){
140 if(pte_present(*pte)){
141 unsigned long long offset;
142 int fd;
143
144 fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
145 err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
146 1, &flush);
147 }
148 else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
149 }
150 else if(pte_newprot(*pte))
151 err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
152
153 if(err)
154 goto kill;
155
156 *pte = pte_mkuptodate(*pte);
157
158 return;
159
160kill:
161 printk("Failed to flush page for address 0x%lx\n", address);
162 force_sig(SIGKILL, current);
97} 163}
164
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 759b07053160..e6a7778006ad 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
21#include "asm/smp.h" 21#include "asm/smp.h"
22#include "asm/processor.h" 22#include "asm/processor.h"
23#include "asm/spinlock.h" 23#include "asm/spinlock.h"
24#include "user_util.h"
25#include "kern_util.h" 24#include "kern_util.h"
26#include "kern.h" 25#include "kern.h"
27#include "irq_user.h" 26#include "irq_user.h"
@@ -90,7 +89,7 @@ static int idle_proc(void *cpup)
90 89
91 cpu_set(cpu, cpu_online_map); 90 cpu_set(cpu, cpu_online_map);
92 default_idle(); 91 default_idle();
93 return(0); 92 return 0;
94} 93}
95 94
96static struct task_struct *idle_thread(int cpu) 95static struct task_struct *idle_thread(int cpu)
@@ -98,8 +97,8 @@ static struct task_struct *idle_thread(int cpu)
98 struct task_struct *new_task; 97 struct task_struct *new_task;
99 unsigned char c; 98 unsigned char c;
100 99
101 current->thread.request.u.thread.proc = idle_proc; 100 current->thread.request.u.thread.proc = idle_proc;
102 current->thread.request.u.thread.arg = (void *) cpu; 101 current->thread.request.u.thread.arg = (void *) cpu;
103 new_task = fork_idle(cpu); 102 new_task = fork_idle(cpu);
104 if(IS_ERR(new_task)) 103 if(IS_ERR(new_task))
105 panic("copy_process failed in idle_thread, error = %ld", 104 panic("copy_process failed in idle_thread, error = %ld",
@@ -110,9 +109,9 @@ static struct task_struct *idle_thread(int cpu)
110 .task = new_task } ); 109 .task = new_task } );
111 idle_threads[cpu] = new_task; 110 idle_threads[cpu] = new_task;
112 CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, 111 CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
113 sizeof(c)), 112 sizeof(c)),
114 ({ panic("skas mode doesn't support SMP"); })); 113 ({ panic("skas mode doesn't support SMP"); }));
115 return(new_task); 114 return new_task;
116} 115}
117 116
118void smp_prepare_cpus(unsigned int maxcpus) 117void smp_prepare_cpus(unsigned int maxcpus)
@@ -163,13 +162,13 @@ int __cpu_up(unsigned int cpu)
163 cpu_set(cpu, smp_commenced_mask); 162 cpu_set(cpu, smp_commenced_mask);
164 while (!cpu_isset(cpu, cpu_online_map)) 163 while (!cpu_isset(cpu, cpu_online_map))
165 mb(); 164 mb();
166 return(0); 165 return 0;
167} 166}
168 167
169int setup_profiling_timer(unsigned int multiplier) 168int setup_profiling_timer(unsigned int multiplier)
170{ 169{
171 printk(KERN_INFO "setup_profiling_timer\n"); 170 printk(KERN_INFO "setup_profiling_timer\n");
172 return(0); 171 return 0;
173} 172}
174 173
175void smp_call_function_slave(int cpu); 174void smp_call_function_slave(int cpu);
@@ -205,7 +204,7 @@ void IPI_handler(int cpu)
205 204
206int hard_smp_processor_id(void) 205int hard_smp_processor_id(void)
207{ 206{
208 return(pid_to_processor_id(os_getpid())); 207 return pid_to_processor_id(os_getpid());
209} 208}
210 209
211static DEFINE_SPINLOCK(call_lock); 210static DEFINE_SPINLOCK(call_lock);
@@ -254,14 +253,3 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
254} 253}
255 254
256#endif 255#endif
257
258/*
259 * Overrides for Emacs so that we follow Linus's tabbing style.
260 * Emacs will notice this stuff at the end of the file and automatically
261 * adjust the settings for this buffer only. This must remain at the end
262 * of the file.
263 * ---------------------------------------------------------------------------
264 * Local variables:
265 * c-file-style: "linux"
266 * End:
267 */
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 2828c5283227..237c4eab7cfd 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -18,7 +18,6 @@
18#include "asm/mman.h" 18#include "asm/mman.h"
19#include "asm/uaccess.h" 19#include "asm/uaccess.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "user_util.h"
22#include "sysdep/syscalls.h" 21#include "sysdep/syscalls.h"
23#include "mode_kern.h" 22#include "mode_kern.h"
24#include "choose-mode.h" 23#include "choose-mode.h"
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index f9e02b31a97a..93263571d813 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -10,7 +10,6 @@
10#include "asm/page.h" 10#include "asm/page.h"
11#include "asm/processor.h" 11#include "asm/processor.h"
12#include "sysrq.h" 12#include "sysrq.h"
13#include "user_util.h"
14 13
15/* Catch non-i386 SUBARCH's. */ 14/* Catch non-i386 SUBARCH's. */
16#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) 15#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index b1f8b0752419..259c49da7ff5 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -18,7 +18,6 @@
18#include "asm/param.h" 18#include "asm/param.h"
19#include "asm/current.h" 19#include "asm/current.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "user_util.h"
22#include "mode.h" 21#include "mode.h"
23#include "os.h" 22#include "os.h"
24 23
@@ -35,8 +34,8 @@ unsigned long long sched_clock(void)
35 return (unsigned long long)jiffies_64 * (1000000000 / HZ); 34 return (unsigned long long)jiffies_64 * (1000000000 / HZ);
36} 35}
37 36
38static unsigned long long prev_nsecs[NR_CPUS];
39#ifdef CONFIG_UML_REAL_TIME_CLOCK 37#ifdef CONFIG_UML_REAL_TIME_CLOCK
38static unsigned long long prev_nsecs[NR_CPUS];
40static long long delta[NR_CPUS]; /* Deviation per interval */ 39static long long delta[NR_CPUS]; /* Deviation per interval */
41#endif 40#endif
42 41
@@ -95,7 +94,12 @@ irqreturn_t um_timer(int irq, void *dev)
95 94
96 do_timer(1); 95 do_timer(1);
97 96
97#ifdef CONFIG_UML_REAL_TIME_CLOCK
98 nsecs = get_time(); 98 nsecs = get_time();
99#else
100 nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec +
101 BILLION / HZ;
102#endif
99 xtime.tv_sec = nsecs / NSEC_PER_SEC; 103 xtime.tv_sec = nsecs / NSEC_PER_SEC;
100 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; 104 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
101 105
@@ -128,13 +132,18 @@ void time_init(void)
128 nsecs = os_nsecs(); 132 nsecs = os_nsecs();
129 set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, 133 set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
130 -nsecs % BILLION); 134 -nsecs % BILLION);
135 set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION);
131 late_time_init = register_timer; 136 late_time_init = register_timer;
132} 137}
133 138
134void do_gettimeofday(struct timeval *tv) 139void do_gettimeofday(struct timeval *tv)
135{ 140{
141#ifdef CONFIG_UML_REAL_TIME_CLOCK
136 unsigned long long nsecs = get_time(); 142 unsigned long long nsecs = get_time();
137 143#else
144 unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION +
145 xtime.tv_nsec;
146#endif
138 tv->tv_sec = nsecs / NSEC_PER_SEC; 147 tv->tv_sec = nsecs / NSEC_PER_SEC;
139 /* Careful about calculations here - this was originally done as 148 /* Careful about calculations here - this was originally done as
140 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC 149 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
@@ -168,6 +177,8 @@ int do_settimeofday(struct timespec *tv)
168 177
169void timer_handler(int sig, union uml_pt_regs *regs) 178void timer_handler(int sig, union uml_pt_regs *regs)
170{ 179{
180 if(current_thread->cpu == 0)
181 timer_irq(regs);
171 local_irq_disable(); 182 local_irq_disable();
172 irq_enter(); 183 irq_enter();
173 update_process_times(CHOOSE_MODE( 184 update_process_times(CHOOSE_MODE(
@@ -175,6 +186,4 @@ void timer_handler(int sig, union uml_pt_regs *regs)
175 (regs)->skas.is_user)); 186 (regs)->skas.is_user));
176 irq_exit(); 187 irq_exit();
177 local_irq_enable(); 188 local_irq_enable();
178 if(current_thread->cpu == 0)
179 timer_irq(regs);
180} 189}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 54a5ff25645a..8a8d52851443 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -6,17 +6,18 @@
6#include "linux/mm.h" 6#include "linux/mm.h"
7#include "asm/page.h" 7#include "asm/page.h"
8#include "asm/pgalloc.h" 8#include "asm/pgalloc.h"
9#include "asm/pgtable.h"
9#include "asm/tlbflush.h" 10#include "asm/tlbflush.h"
10#include "choose-mode.h" 11#include "choose-mode.h"
11#include "mode_kern.h" 12#include "mode_kern.h"
12#include "user_util.h" 13#include "as-layout.h"
13#include "tlb.h" 14#include "tlb.h"
14#include "mem.h" 15#include "mem.h"
15#include "mem_user.h" 16#include "mem_user.h"
16#include "os.h" 17#include "os.h"
17 18
18static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, 19static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
19 int r, int w, int x, struct host_vm_op *ops, int *index, 20 unsigned int prot, struct host_vm_op *ops, int *index,
20 int last_filled, union mm_context *mmu, void **flush, 21 int last_filled, union mm_context *mmu, void **flush,
21 int (*do_ops)(union mm_context *, struct host_vm_op *, 22 int (*do_ops)(union mm_context *, struct host_vm_op *,
22 int, int, void **)) 23 int, int, void **))
@@ -30,8 +31,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
30 last = &ops[*index]; 31 last = &ops[*index];
31 if((last->type == MMAP) && 32 if((last->type == MMAP) &&
32 (last->u.mmap.addr + last->u.mmap.len == virt) && 33 (last->u.mmap.addr + last->u.mmap.len == virt) &&
33 (last->u.mmap.r == r) && (last->u.mmap.w == w) && 34 (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) &&
34 (last->u.mmap.x == x) && (last->u.mmap.fd == fd) &&
35 (last->u.mmap.offset + last->u.mmap.len == offset)){ 35 (last->u.mmap.offset + last->u.mmap.len == offset)){
36 last->u.mmap.len += len; 36 last->u.mmap.len += len;
37 return 0; 37 return 0;
@@ -47,9 +47,7 @@ static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
47 .u = { .mmap = { 47 .u = { .mmap = {
48 .addr = virt, 48 .addr = virt,
49 .len = len, 49 .len = len,
50 .r = r, 50 .prot = prot,
51 .w = w,
52 .x = x,
53 .fd = fd, 51 .fd = fd,
54 .offset = offset } 52 .offset = offset }
55 } }); 53 } });
@@ -86,8 +84,8 @@ static int add_munmap(unsigned long addr, unsigned long len,
86 return ret; 84 return ret;
87} 85}
88 86
89static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, 87static int add_mprotect(unsigned long addr, unsigned long len,
90 int x, struct host_vm_op *ops, int *index, 88 unsigned int prot, struct host_vm_op *ops, int *index,
91 int last_filled, union mm_context *mmu, void **flush, 89 int last_filled, union mm_context *mmu, void **flush,
92 int (*do_ops)(union mm_context *, struct host_vm_op *, 90 int (*do_ops)(union mm_context *, struct host_vm_op *,
93 int, int, void **)) 91 int, int, void **))
@@ -99,8 +97,7 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
99 last = &ops[*index]; 97 last = &ops[*index];
100 if((last->type == MPROTECT) && 98 if((last->type == MPROTECT) &&
101 (last->u.mprotect.addr + last->u.mprotect.len == addr) && 99 (last->u.mprotect.addr + last->u.mprotect.len == addr) &&
102 (last->u.mprotect.r == r) && (last->u.mprotect.w == w) && 100 (last->u.mprotect.prot == prot)){
103 (last->u.mprotect.x == x)){
104 last->u.mprotect.len += len; 101 last->u.mprotect.len += len;
105 return 0; 102 return 0;
106 } 103 }
@@ -115,114 +112,145 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
115 .u = { .mprotect = { 112 .u = { .mprotect = {
116 .addr = addr, 113 .addr = addr,
117 .len = len, 114 .len = len,
118 .r = r, 115 .prot = prot } } });
119 .w = w,
120 .x = x } } });
121 return ret; 116 return ret;
122} 117}
123 118
124#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) 119#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
125 120
121static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
122 unsigned long end, struct host_vm_op *ops,
123 int last_op, int *op_index, int force,
124 union mm_context *mmu, void **flush,
125 int (*do_ops)(union mm_context *,
126 struct host_vm_op *, int, int,
127 void **))
128{
129 pte_t *pte;
130 int r, w, x, prot, ret = 0;
131
132 pte = pte_offset_kernel(pmd, addr);
133 do {
134 r = pte_read(*pte);
135 w = pte_write(*pte);
136 x = pte_exec(*pte);
137 if (!pte_young(*pte)) {
138 r = 0;
139 w = 0;
140 } else if (!pte_dirty(*pte)) {
141 w = 0;
142 }
143 prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
144 (x ? UM_PROT_EXEC : 0));
145 if(force || pte_newpage(*pte)){
146 if(pte_present(*pte))
147 ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
148 PAGE_SIZE, prot, ops, op_index,
149 last_op, mmu, flush, do_ops);
150 else ret = add_munmap(addr, PAGE_SIZE, ops, op_index,
151 last_op, mmu, flush, do_ops);
152 }
153 else if(pte_newprot(*pte))
154 ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index,
155 last_op, mmu, flush, do_ops);
156 *pte = pte_mkuptodate(*pte);
157 } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
158 return ret;
159}
160
161static inline int update_pmd_range(pud_t *pud, unsigned long addr,
162 unsigned long end, struct host_vm_op *ops,
163 int last_op, int *op_index, int force,
164 union mm_context *mmu, void **flush,
165 int (*do_ops)(union mm_context *,
166 struct host_vm_op *, int, int,
167 void **))
168{
169 pmd_t *pmd;
170 unsigned long next;
171 int ret = 0;
172
173 pmd = pmd_offset(pud, addr);
174 do {
175 next = pmd_addr_end(addr, end);
176 if(!pmd_present(*pmd)){
177 if(force || pmd_newpage(*pmd)){
178 ret = add_munmap(addr, next - addr, ops,
179 op_index, last_op, mmu,
180 flush, do_ops);
181 pmd_mkuptodate(*pmd);
182 }
183 }
184 else ret = update_pte_range(pmd, addr, next, ops, last_op,
185 op_index, force, mmu, flush,
186 do_ops);
187 } while (pmd++, addr = next, ((addr != end) && !ret));
188 return ret;
189}
190
191static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
192 unsigned long end, struct host_vm_op *ops,
193 int last_op, int *op_index, int force,
194 union mm_context *mmu, void **flush,
195 int (*do_ops)(union mm_context *,
196 struct host_vm_op *, int, int,
197 void **))
198{
199 pud_t *pud;
200 unsigned long next;
201 int ret = 0;
202
203 pud = pud_offset(pgd, addr);
204 do {
205 next = pud_addr_end(addr, end);
206 if(!pud_present(*pud)){
207 if(force || pud_newpage(*pud)){
208 ret = add_munmap(addr, next - addr, ops,
209 op_index, last_op, mmu,
210 flush, do_ops);
211 pud_mkuptodate(*pud);
212 }
213 }
214 else ret = update_pmd_range(pud, addr, next, ops, last_op,
215 op_index, force, mmu, flush,
216 do_ops);
217 } while (pud++, addr = next, ((addr != end) && !ret));
218 return ret;
219}
220
126void fix_range_common(struct mm_struct *mm, unsigned long start_addr, 221void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
127 unsigned long end_addr, int force, 222 unsigned long end_addr, int force,
128 int (*do_ops)(union mm_context *, struct host_vm_op *, 223 int (*do_ops)(union mm_context *, struct host_vm_op *,
129 int, int, void **)) 224 int, int, void **))
130{ 225{
131 pgd_t *npgd; 226 pgd_t *pgd;
132 pud_t *npud;
133 pmd_t *npmd;
134 pte_t *npte;
135 union mm_context *mmu = &mm->context; 227 union mm_context *mmu = &mm->context;
136 unsigned long addr, end;
137 int r, w, x;
138 struct host_vm_op ops[1]; 228 struct host_vm_op ops[1];
229 unsigned long addr = start_addr, next;
230 int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1;
139 void *flush = NULL; 231 void *flush = NULL;
140 int op_index = -1, last_op = ARRAY_SIZE(ops) - 1;
141 int ret = 0;
142
143 if(mm == NULL)
144 return;
145 232
146 ops[0].type = NONE; 233 ops[0].type = NONE;
147 for(addr = start_addr; addr < end_addr && !ret;){ 234 pgd = pgd_offset(mm, addr);
148 npgd = pgd_offset(mm, addr); 235 do {
149 if(!pgd_present(*npgd)){ 236 next = pgd_addr_end(addr, end_addr);
150 end = ADD_ROUND(addr, PGDIR_SIZE); 237 if(!pgd_present(*pgd)){
151 if(end > end_addr) 238 if (force || pgd_newpage(*pgd)){
152 end = end_addr; 239 ret = add_munmap(addr, next - addr, ops,
153 if(force || pgd_newpage(*npgd)){
154 ret = add_munmap(addr, end - addr, ops,
155 &op_index, last_op, mmu,
156 &flush, do_ops);
157 pgd_mkuptodate(*npgd);
158 }
159 addr = end;
160 continue;
161 }
162
163 npud = pud_offset(npgd, addr);
164 if(!pud_present(*npud)){
165 end = ADD_ROUND(addr, PUD_SIZE);
166 if(end > end_addr)
167 end = end_addr;
168 if(force || pud_newpage(*npud)){
169 ret = add_munmap(addr, end - addr, ops,
170 &op_index, last_op, mmu,
171 &flush, do_ops);
172 pud_mkuptodate(*npud);
173 }
174 addr = end;
175 continue;
176 }
177
178 npmd = pmd_offset(npud, addr);
179 if(!pmd_present(*npmd)){
180 end = ADD_ROUND(addr, PMD_SIZE);
181 if(end > end_addr)
182 end = end_addr;
183 if(force || pmd_newpage(*npmd)){
184 ret = add_munmap(addr, end - addr, ops,
185 &op_index, last_op, mmu, 240 &op_index, last_op, mmu,
186 &flush, do_ops); 241 &flush, do_ops);
187 pmd_mkuptodate(*npmd); 242 pgd_mkuptodate(*pgd);
188 } 243 }
189 addr = end;
190 continue;
191 }
192
193 npte = pte_offset_kernel(npmd, addr);
194 r = pte_read(*npte);
195 w = pte_write(*npte);
196 x = pte_exec(*npte);
197 if (!pte_young(*npte)) {
198 r = 0;
199 w = 0;
200 } else if (!pte_dirty(*npte)) {
201 w = 0;
202 }
203 if(force || pte_newpage(*npte)){
204 if(pte_present(*npte))
205 ret = add_mmap(addr,
206 pte_val(*npte) & PAGE_MASK,
207 PAGE_SIZE, r, w, x, ops,
208 &op_index, last_op, mmu,
209 &flush, do_ops);
210 else ret = add_munmap(addr, PAGE_SIZE, ops,
211 &op_index, last_op, mmu,
212 &flush, do_ops);
213 } 244 }
214 else if(pte_newprot(*npte)) 245 else ret = update_pud_range(pgd, addr, next, ops, last_op,
215 ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, 246 &op_index, force, mmu, &flush,
216 &op_index, last_op, mmu, 247 do_ops);
217 &flush, do_ops); 248 } while (pgd++, addr = next, ((addr != end_addr) && !ret));
218 249
219 *npte = pte_mkuptodate(*npte);
220 addr += PAGE_SIZE;
221 }
222 if(!ret) 250 if(!ret)
223 ret = (*do_ops)(mmu, ops, op_index, 1, &flush); 251 ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
224 252
225/* This is not an else because ret is modified above */ 253 /* This is not an else because ret is modified above */
226 if(ret) { 254 if(ret) {
227 printk("fix_range_common: failed, killing current process\n"); 255 printk("fix_range_common: failed, killing current process\n");
228 force_sig(SIGKILL, current); 256 force_sig(SIGKILL, current);
@@ -343,12 +371,6 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
343 return(pte_offset_map(pmd, addr)); 371 return(pte_offset_map(pmd, addr));
344} 372}
345 373
346void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
347{
348 address &= PAGE_MASK;
349 flush_tlb_range(vma, address, address + PAGE_SIZE);
350}
351
352void flush_tlb_all(void) 374void flush_tlb_all(void)
353{ 375{
354 flush_tlb_mm(current->mm); 376 flush_tlb_mm(current->mm);
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 26f15c458574..abab90c3803f 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -18,8 +18,9 @@
18#include "asm/current.h" 18#include "asm/current.h"
19#include "asm/irq.h" 19#include "asm/irq.h"
20#include "sysdep/sigcontext.h" 20#include "sysdep/sigcontext.h"
21#include "user_util.h"
22#include "kern_util.h" 21#include "kern_util.h"
22#include "as-layout.h"
23#include "arch.h"
23#include "kern.h" 24#include "kern.h"
24#include "chan_kern.h" 25#include "chan_kern.h"
25#include "mconsole_kern.h" 26#include "mconsole_kern.h"
@@ -71,8 +72,8 @@ good_area:
71 goto out; 72 goto out;
72 73
73 /* Don't require VM_READ|VM_EXEC for write faults! */ 74 /* Don't require VM_READ|VM_EXEC for write faults! */
74 if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) 75 if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
75 goto out; 76 goto out;
76 77
77 do { 78 do {
78survive: 79survive:
@@ -156,20 +157,23 @@ static void segv_handler(int sig, union uml_pt_regs *regs)
156 * the info in the regs. A pointer to the info then would 157 * the info in the regs. A pointer to the info then would
157 * give us bad data! 158 * give us bad data!
158 */ 159 */
159unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) 160unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
161 union uml_pt_regs *regs)
160{ 162{
161 struct siginfo si; 163 struct siginfo si;
162 void *catcher; 164 void *catcher;
163 int err; 165 int err;
164 int is_write = FAULT_WRITE(fi); 166 int is_write = FAULT_WRITE(fi);
165 unsigned long address = FAULT_ADDRESS(fi); 167 unsigned long address = FAULT_ADDRESS(fi);
166 168
167 if(!is_user && (address >= start_vm) && (address < end_vm)){ 169 if(!is_user && (address >= start_vm) && (address < end_vm)){
168 flush_tlb_kernel_vm(); 170 flush_tlb_kernel_vm();
169 return(0); 171 return 0;
170 } 172 }
171 else if(current->mm == NULL) 173 else if(current->mm == NULL) {
172 panic("Segfault with no mm"); 174 show_regs(container_of(regs, struct pt_regs, regs));
175 panic("Segfault with no mm");
176 }
173 177
174 if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) 178 if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
175 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); 179 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
@@ -182,26 +186,28 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
182 186
183 catcher = current->thread.fault_catcher; 187 catcher = current->thread.fault_catcher;
184 if(!err) 188 if(!err)
185 return(0); 189 return 0;
186 else if(catcher != NULL){ 190 else if(catcher != NULL){
187 current->thread.fault_addr = (void *) address; 191 current->thread.fault_addr = (void *) address;
188 do_longjmp(catcher, 1); 192 do_longjmp(catcher, 1);
189 } 193 }
190 else if(current->thread.fault_addr != NULL) 194 else if(current->thread.fault_addr != NULL)
191 panic("fault_addr set but no fault catcher"); 195 panic("fault_addr set but no fault catcher");
192 else if(!is_user && arch_fixup(ip, sc)) 196 else if(!is_user && arch_fixup(ip, regs))
193 return(0); 197 return 0;
194 198
195 if(!is_user) 199 if(!is_user) {
200 show_regs(container_of(regs, struct pt_regs, regs));
196 panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", 201 panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
197 address, ip); 202 address, ip);
203 }
198 204
199 if (err == -EACCES) { 205 if (err == -EACCES) {
200 si.si_signo = SIGBUS; 206 si.si_signo = SIGBUS;
201 si.si_errno = 0; 207 si.si_errno = 0;
202 si.si_code = BUS_ADRERR; 208 si.si_code = BUS_ADRERR;
203 si.si_addr = (void __user *)address; 209 si.si_addr = (void __user *)address;
204 current->thread.arch.faultinfo = fi; 210 current->thread.arch.faultinfo = fi;
205 force_sig_info(SIGBUS, &si, current); 211 force_sig_info(SIGBUS, &si, current);
206 } else if (err == -ENOMEM) { 212 } else if (err == -ENOMEM) {
207 printk("VM: killing process %s\n", current->comm); 213 printk("VM: killing process %s\n", current->comm);
@@ -210,10 +216,10 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
210 BUG_ON(err != -EFAULT); 216 BUG_ON(err != -EFAULT);
211 si.si_signo = SIGSEGV; 217 si.si_signo = SIGSEGV;
212 si.si_addr = (void __user *) address; 218 si.si_addr = (void __user *) address;
213 current->thread.arch.faultinfo = fi; 219 current->thread.arch.faultinfo = fi;
214 force_sig_info(SIGSEGV, &si, current); 220 force_sig_info(SIGSEGV, &si, current);
215 } 221 }
216 return(0); 222 return 0;
217} 223}
218 224
219void relay_signal(int sig, union uml_pt_regs *regs) 225void relay_signal(int sig, union uml_pt_regs *regs)
@@ -223,12 +229,12 @@ void relay_signal(int sig, union uml_pt_regs *regs)
223 229
224 if(!UPT_IS_USER(regs)){ 230 if(!UPT_IS_USER(regs)){
225 if(sig == SIGBUS) 231 if(sig == SIGBUS)
226 printk("Bus error - the /dev/shm or /tmp mount likely " 232 printk("Bus error - the host /dev/shm or /tmp mount "
227 "just ran out of space\n"); 233 "likely just ran out of space\n");
228 panic("Kernel mode signal %d", sig); 234 panic("Kernel mode signal %d", sig);
229 } 235 }
230 236
231 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); 237 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
232 force_sig(sig, current); 238 force_sig(sig, current);
233} 239}
234 240
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index ad66df17d9d7..40126cb51801 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -10,7 +10,6 @@
10#include "asm/uaccess.h" 10#include "asm/uaccess.h"
11#include "asm/pgalloc.h" 11#include "asm/pgalloc.h"
12#include "asm/tlbflush.h" 12#include "asm/tlbflush.h"
13#include "user_util.h"
14#include "kern_util.h" 13#include "kern_util.h"
15#include "irq_user.h" 14#include "irq_user.h"
16#include "mem_user.h" 15#include "mem_user.h"
@@ -58,7 +57,7 @@ void flush_thread_tt(void)
58 enable_timer(); 57 enable_timer();
59 free_page(stack); 58 free_page(stack);
60 protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); 59 protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
61 task_protections((unsigned long) current_thread); 60 stack_protections((unsigned long) current_thread);
62 force_flush_all(); 61 force_flush_all();
63 unblock_signals(); 62 unblock_signals();
64} 63}
diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c
index a92c02ff2ce3..7b5f2181cf51 100644
--- a/arch/um/kernel/tt/exec_user.c
+++ b/arch/um/kernel/tt/exec_user.c
@@ -10,7 +10,6 @@
10#include <errno.h> 10#include <errno.h>
11#include <sys/wait.h> 11#include <sys/wait.h>
12#include <signal.h> 12#include <signal.h>
13#include "user_util.h"
14#include "kern_util.h" 13#include "kern_util.h"
15#include "user.h" 14#include "user.h"
16#include "ptrace_user.h" 15#include "ptrace_user.h"
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 8eba8f7dca68..030e4658f36b 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -17,7 +17,6 @@
17#include "user.h" 17#include "user.h"
18#include "debug.h" 18#include "debug.h"
19#include "kern_util.h" 19#include "kern_util.h"
20#include "user_util.h"
21#include "tt.h" 20#include "tt.h"
22#include "sysdep/thread.h" 21#include "sysdep/thread.h"
23#include "os.h" 22#include "os.h"
@@ -115,6 +114,8 @@ struct gdb_data {
115 int err; 114 int err;
116}; 115};
117 116
117extern char *linux_prog;
118
118static void config_gdb_cb(void *arg) 119static void config_gdb_cb(void *arg)
119{ 120{
120 struct gdb_data *data = arg; 121 struct gdb_data *data = arg;
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
deleted file mode 100644
index 2a35b15c5fef..000000000000
--- a/arch/um/kernel/tt/include/mode_kern-tt.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MODE_KERN_H__
7#define __TT_MODE_KERN_H__
8
9#include "linux/sched.h"
10#include "asm/page.h"
11#include "asm/ptrace.h"
12#include "asm/uaccess.h"
13
14extern void switch_to_tt(void *prev, void *next);
15extern void flush_thread_tt(void);
16extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
17 unsigned long esp);
18extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
19 unsigned long stack_top, struct task_struct *p,
20 struct pt_regs *regs);
21extern void release_thread_tt(struct task_struct *task);
22extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
23extern void init_idle_tt(void);
24extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
25extern void flush_tlb_kernel_vm_tt(void);
26extern void __flush_tlb_one_tt(unsigned long addr);
27extern void flush_tlb_range_tt(struct vm_area_struct *vma,
28 unsigned long start, unsigned long end);
29extern void flush_tlb_mm_tt(struct mm_struct *mm);
30extern void force_flush_all_tt(void);
31extern long execute_syscall_tt(void *r);
32extern void before_mem_tt(unsigned long brk_start);
33extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
34 unsigned long *task_size_out);
35extern int start_uml_tt(void);
36extern int external_pid_tt(struct task_struct *task);
37extern int thread_pid_tt(struct task_struct *task);
38
39#define kmem_end_tt (host_task_size - ABOVE_KMEM)
40
41#endif
42
43/*
44 * Overrides for Emacs so that we follow Linus's tabbing style.
45 * Emacs will notice this stuff at the end of the file and automatically
46 * adjust the settings for this buffer only. This must remain at the end
47 * of the file.
48 * ---------------------------------------------------------------------------
49 * Local variables:
50 * c-file-style: "linux"
51 * End:
52 */
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
index 4d1929dfa285..d0c3c4975f28 100644
--- a/arch/um/kernel/tt/mem.c
+++ b/arch/um/kernel/tt/mem.c
@@ -8,7 +8,6 @@
8#include "asm/uaccess.h" 8#include "asm/uaccess.h"
9#include "mem_user.h" 9#include "mem_user.h"
10#include "kern_util.h" 10#include "kern_util.h"
11#include "user_util.h"
12#include "kern.h" 11#include "kern.h"
13#include "tt.h" 12#include "tt.h"
14 13
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c
index 03e589895388..9774f6360c32 100644
--- a/arch/um/kernel/tt/mem_user.c
+++ b/arch/um/kernel/tt/mem_user.c
@@ -11,7 +11,6 @@
11#include <sys/mman.h> 11#include <sys/mman.h>
12#include "tt.h" 12#include "tt.h"
13#include "mem_user.h" 13#include "mem_user.h"
14#include "user_util.h"
15#include "os.h" 14#include "os.h"
16 15
17void remap_data(void *segment_start, void *segment_end, int w) 16void remap_data(void *segment_start, void *segment_end, int w)
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 1e86f0bfef72..74347adf81bf 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -14,7 +14,6 @@
14#include "asm/tlbflush.h" 14#include "asm/tlbflush.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "kern_util.h" 16#include "kern_util.h"
17#include "user_util.h"
18#include "os.h" 17#include "os.h"
19#include "kern.h" 18#include "kern.h"
20#include "sigcontext.h" 19#include "sigcontext.h"
@@ -65,7 +64,8 @@ void switch_to_tt(void *prev, void *next)
65 if(from->thread.mode.tt.switch_pipe[0] == -1) 64 if(from->thread.mode.tt.switch_pipe[0] == -1)
66 os_kill_process(os_getpid(), 0); 65 os_kill_process(os_getpid(), 0);
67 66
68 err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); 67 err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c,
68 sizeof(c));
69 if(err != sizeof(c)) 69 if(err != sizeof(c))
70 panic("read of switch_pipe failed, errno = %d", -err); 70 panic("read of switch_pipe failed, errno = %d", -err);
71 71
@@ -209,7 +209,7 @@ void finish_fork_handler(int sig)
209 if(current->mm != current->parent->mm) 209 if(current->mm != current->parent->mm)
210 protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 210 protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
211 1, 0, 1); 211 1, 0, 1);
212 task_protections((unsigned long) current_thread); 212 stack_protections((unsigned long) current_thread);
213 213
214 free_page(current->thread.temp_stack); 214 free_page(current->thread.temp_stack);
215 local_irq_disable(); 215 local_irq_disable();
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
index 58800c50b10e..420c23f311f3 100644
--- a/arch/um/kernel/tt/ptproxy/proxy.c
+++ b/arch/um/kernel/tt/ptproxy/proxy.c
@@ -26,7 +26,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
26#include "sysdep.h" 26#include "sysdep.h"
27#include "wait.h" 27#include "wait.h"
28 28
29#include "user_util.h"
30#include "user.h" 29#include "user.h"
31#include "os.h" 30#include "os.h"
32#include "tempfile.h" 31#include "tempfile.h"
@@ -339,11 +338,12 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out)
339 "err = %d\n", -fd); 338 "err = %d\n", -fd);
340 exit(1); 339 exit(1);
341 } 340 }
342 os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1); 341 os_write_file(fd, gdb_init_string,
342 sizeof(gdb_init_string) - 1);
343 if(startup){ 343 if(startup){
344 if(stop){ 344 if(stop){
345 os_write_file(fd, "b start_kernel\n", 345 os_write_file(fd, "b start_kernel\n",
346 strlen("b start_kernel\n")); 346 strlen("b start_kernel\n"));
347 } 347 }
348 os_write_file(fd, "c\n", strlen("c\n")); 348 os_write_file(fd, "c\n", strlen("c\n"));
349 } 349 }
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 03774427d468..4b4f6179b212 100644
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -16,7 +16,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
16 16
17#include "ptproxy.h" 17#include "ptproxy.h"
18#include "debug.h" 18#include "debug.h"
19#include "user_util.h"
20#include "kern_util.h" 19#include "kern_util.h"
21#include "ptrace_user.h" 20#include "ptrace_user.h"
22#include "tt.h" 21#include "tt.h"
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index 99f178319d03..e0e1ab0588ad 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -13,7 +13,6 @@ terms and conditions.
13#include <sys/types.h> 13#include <sys/types.h>
14#include <linux/unistd.h> 14#include <linux/unistd.h>
15#include "ptrace_user.h" 15#include "ptrace_user.h"
16#include "user_util.h"
17#include "user.h" 16#include "user.h"
18#include "os.h" 17#include "os.h"
19 18
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
index 12f6319d8d76..bdd4af4b65fc 100644
--- a/arch/um/kernel/tt/ptproxy/wait.c
+++ b/arch/um/kernel/tt/ptproxy/wait.c
@@ -13,7 +13,6 @@ terms and conditions.
13#include "ptproxy.h" 13#include "ptproxy.h"
14#include "sysdep.h" 14#include "sysdep.h"
15#include "wait.h" 15#include "wait.h"
16#include "user_util.h"
17#include "ptrace_user.h" 16#include "ptrace_user.h"
18#include "sysdep/ptrace.h" 17#include "sysdep/ptrace.h"
19#include "sysdep/sigcontext.h" 18#include "sysdep/sigcontext.h"
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
index 902987bf379b..f52b47aff1d2 100644
--- a/arch/um/kernel/tt/syscall_user.c
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -11,7 +11,6 @@
11#include "sigcontext.h" 11#include "sigcontext.h"
12#include "ptrace_user.h" 12#include "ptrace_user.h"
13#include "task.h" 13#include "task.h"
14#include "user_util.h"
15#include "kern_util.h" 14#include "kern_util.h"
16#include "syscall.h" 15#include "syscall.h"
17#include "tt.h" 16#include "tt.h"
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
index ae6217c86135..7caa24fe05df 100644
--- a/arch/um/kernel/tt/tlb.c
+++ b/arch/um/kernel/tt/tlb.c
@@ -12,7 +12,6 @@
12#include "asm/pgtable.h" 12#include "asm/pgtable.h"
13#include "asm/uaccess.h" 13#include "asm/uaccess.h"
14#include "asm/tlbflush.h" 14#include "asm/tlbflush.h"
15#include "user_util.h"
16#include "mem_user.h" 15#include "mem_user.h"
17#include "os.h" 16#include "os.h"
18#include "tlb.h" 17#include "tlb.h"
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index b9195355075a..c23588393f6e 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -19,7 +19,6 @@
19#include "sigcontext.h" 19#include "sigcontext.h"
20#include "sysdep/sigcontext.h" 20#include "sysdep/sigcontext.h"
21#include "os.h" 21#include "os.h"
22#include "user_util.h"
23#include "mem_user.h" 22#include "mem_user.h"
24#include "process.h" 23#include "process.h"
25#include "kern_util.h" 24#include "kern_util.h"
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index b5d9d64d91e4..3032eb5e2467 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -8,7 +8,6 @@
8#include <signal.h> 8#include <signal.h>
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/sigcontext.h" 10#include "sysdep/sigcontext.h"
11#include "user_util.h"
12#include "kern_util.h" 11#include "kern_util.h"
13#include "task.h" 12#include "task.h"
14#include "tt.h" 13#include "tt.h"
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
index ed1abcf4d057..0e5c82c5e5b7 100644
--- a/arch/um/kernel/tt/uaccess_user.c
+++ b/arch/um/kernel/tt/uaccess_user.c
@@ -5,7 +5,6 @@
5 */ 5 */
6 6
7#include <string.h> 7#include <string.h>
8#include "user_util.h"
9#include "uml_uaccess.h" 8#include "uml_uaccess.h"
10#include "task.h" 9#include "task.h"
11#include "kern_util.h" 10#include "kern_util.h"
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 89c6dba731f8..ecc458fe51b9 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -17,6 +17,7 @@
17#include "linux/seq_file.h" 17#include "linux/seq_file.h"
18#include "linux/delay.h" 18#include "linux/delay.h"
19#include "linux/module.h" 19#include "linux/module.h"
20#include "linux/utsname.h"
20#include "asm/page.h" 21#include "asm/page.h"
21#include "asm/pgtable.h" 22#include "asm/pgtable.h"
22#include "asm/ptrace.h" 23#include "asm/ptrace.h"
@@ -25,8 +26,9 @@
25#include "asm/setup.h" 26#include "asm/setup.h"
26#include "ubd_user.h" 27#include "ubd_user.h"
27#include "asm/current.h" 28#include "asm/current.h"
28#include "user_util.h"
29#include "kern_util.h" 29#include "kern_util.h"
30#include "as-layout.h"
31#include "arch.h"
30#include "kern.h" 32#include "kern.h"
31#include "mem_user.h" 33#include "mem_user.h"
32#include "mem.h" 34#include "mem.h"
@@ -42,7 +44,7 @@
42 44
43#define DEFAULT_COMMAND_LINE "root=98:0" 45#define DEFAULT_COMMAND_LINE "root=98:0"
44 46
45/* Changed in linux_main and setup_arch, which run before SMP is started */ 47/* Changed in add_arg and setup_arch, which run before SMP is started */
46static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; 48static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
47 49
48static void __init add_arg(char *arg) 50static void __init add_arg(char *arg)
@@ -56,17 +58,25 @@ static void __init add_arg(char *arg)
56 strcat(command_line, arg); 58 strcat(command_line, arg);
57} 59}
58 60
59struct cpuinfo_um boot_cpu_data = { 61/*
62 * These fields are initialized at boot time and not changed.
63 * XXX This structure is used only in the non-SMP case. Maybe this
64 * should be moved to smp.c.
65 */
66struct cpuinfo_um boot_cpu_data = {
60 .loops_per_jiffy = 0, 67 .loops_per_jiffy = 0,
61 .ipi_pipe = { -1, -1 } 68 .ipi_pipe = { -1, -1 }
62}; 69};
63 70
64unsigned long thread_saved_pc(struct task_struct *task) 71unsigned long thread_saved_pc(struct task_struct *task)
65{ 72{
66 return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, 73 return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
67 task))); 74 task));
68} 75}
69 76
77/* Changed in setup_arch, which is called in early boot */
78static char host_info[(__NEW_UTS_LEN + 1) * 5];
79
70static int show_cpuinfo(struct seq_file *m, void *v) 80static int show_cpuinfo(struct seq_file *m, void *v)
71{ 81{
72 int index = 0; 82 int index = 0;
@@ -86,7 +96,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
86 loops_per_jiffy/(500000/HZ), 96 loops_per_jiffy/(500000/HZ),
87 (loops_per_jiffy/(5000/HZ)) % 100); 97 (loops_per_jiffy/(5000/HZ)) % 100);
88 98
89 return(0); 99 return 0;
90} 100}
91 101
92static void *c_start(struct seq_file *m, loff_t *pos) 102static void *c_start(struct seq_file *m, loff_t *pos)
@@ -114,14 +124,12 @@ const struct seq_operations cpuinfo_op = {
114/* Set in linux_main */ 124/* Set in linux_main */
115unsigned long host_task_size; 125unsigned long host_task_size;
116unsigned long task_size; 126unsigned long task_size;
117
118unsigned long uml_start;
119
120/* Set in early boot */
121unsigned long uml_physmem; 127unsigned long uml_physmem;
122unsigned long uml_reserved; 128unsigned long uml_reserved; /* Also modified in mem_init */
123unsigned long start_vm; 129unsigned long start_vm;
124unsigned long end_vm; 130unsigned long end_vm;
131
132/* Set in uml_ncpus_setup */
125int ncpus = 1; 133int ncpus = 1;
126 134
127#ifdef CONFIG_CMDLINE_ON_HOST 135#ifdef CONFIG_CMDLINE_ON_HOST
@@ -135,6 +143,8 @@ static char *argv1_end = NULL;
135 143
136/* Set in early boot */ 144/* Set in early boot */
137static int have_root __initdata = 0; 145static int have_root __initdata = 0;
146
147/* Set in uml_mem_setup and modified in linux_main */
138long long physmem_size = 32 * 1024 * 1024; 148long long physmem_size = 32 * 1024 * 1024;
139 149
140void set_cmdline(char *cmd) 150void set_cmdline(char *cmd)
@@ -212,12 +222,12 @@ __uml_setup("debug", no_skas_debug_setup,
212#ifdef CONFIG_SMP 222#ifdef CONFIG_SMP
213static int __init uml_ncpus_setup(char *line, int *add) 223static int __init uml_ncpus_setup(char *line, int *add)
214{ 224{
215 if (!sscanf(line, "%d", &ncpus)) { 225 if (!sscanf(line, "%d", &ncpus)) {
216 printf("Couldn't parse [%s]\n", line); 226 printf("Couldn't parse [%s]\n", line);
217 return -1; 227 return -1;
218 } 228 }
219 229
220 return 0; 230 return 0;
221} 231}
222 232
223__uml_setup("ncpus=", uml_ncpus_setup, 233__uml_setup("ncpus=", uml_ncpus_setup,
@@ -234,7 +244,7 @@ static int force_tt = 0;
234static int __init mode_tt_setup(char *line, int *add) 244static int __init mode_tt_setup(char *line, int *add)
235{ 245{
236 force_tt = 1; 246 force_tt = 1;
237 return(0); 247 return 0;
238} 248}
239 249
240#else 250#else
@@ -245,7 +255,7 @@ static int __init mode_tt_setup(char *line, int *add)
245static int __init mode_tt_setup(char *line, int *add) 255static int __init mode_tt_setup(char *line, int *add)
246{ 256{
247 printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); 257 printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
248 return(0); 258 return 0;
249} 259}
250 260
251#else 261#else
@@ -256,7 +266,7 @@ static int __init mode_tt_setup(char *line, int *add)
256static int __init mode_tt_setup(char *line, int *add) 266static int __init mode_tt_setup(char *line, int *add)
257{ 267{
258 printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); 268 printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
259 return(0); 269 return 0;
260} 270}
261 271
262#endif 272#endif
@@ -274,16 +284,15 @@ int mode_tt = DEFAULT_TT;
274 284
275static int __init Usage(char *line, int *add) 285static int __init Usage(char *line, int *add)
276{ 286{
277 const char **p; 287 const char **p;
278 288
279 printf(usage_string, init_utsname()->release); 289 printf(usage_string, init_utsname()->release);
280 p = &__uml_help_start; 290 p = &__uml_help_start;
281 while (p < &__uml_help_end) { 291 while (p < &__uml_help_end) {
282 printf("%s", *p); 292 printf("%s", *p);
283 p++; 293 p++;
284 } 294 }
285 exit(0); 295 exit(0);
286
287 return 0; 296 return 0;
288} 297}
289 298
@@ -374,13 +383,12 @@ int __init linux_main(int argc, char **argv)
374 383
375 printf("UML running in %s mode\n", mode); 384 printf("UML running in %s mode\n", mode);
376 385
377 uml_start = (unsigned long) &__binary_start;
378 host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, 386 host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt,
379 set_task_sizes_skas, &task_size); 387 set_task_sizes_skas, &task_size);
380 388
381 /* 389 /*
382 * Setting up handlers to 'sig_info' struct 390 * Setting up handlers to 'sig_info' struct
383 */ 391 */
384 os_fill_handlinfo(handlinfo_kern); 392 os_fill_handlinfo(handlinfo_kern);
385 393
386 brk_start = (unsigned long) sbrk(0); 394 brk_start = (unsigned long) sbrk(0);
@@ -396,7 +404,7 @@ int __init linux_main(int argc, char **argv)
396 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 404 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
397 } 405 }
398 406
399 uml_physmem = uml_start & PAGE_MASK; 407 uml_physmem = (unsigned long) &__binary_start & PAGE_MASK;
400 408
401 /* Reserve up to 4M after the current brk */ 409 /* Reserve up to 4M after the current brk */
402 uml_reserved = ROUND_4M(brk_start) + (1 << 22); 410 uml_reserved = ROUND_4M(brk_start) + (1 << 22);
@@ -407,7 +415,7 @@ int __init linux_main(int argc, char **argv)
407 argv1_begin = argv[1]; 415 argv1_begin = argv[1];
408 argv1_end = &argv[1][strlen(argv[1])]; 416 argv1_end = &argv[1][strlen(argv[1])];
409#endif 417#endif
410 418
411 highmem = 0; 419 highmem = 0;
412 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; 420 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
413 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; 421 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
@@ -449,12 +457,12 @@ int __init linux_main(int argc, char **argv)
449 printf("Kernel virtual memory size shrunk to %lu bytes\n", 457 printf("Kernel virtual memory size shrunk to %lu bytes\n",
450 virtmem_size); 458 virtmem_size);
451 459
452 uml_postsetup(); 460 uml_postsetup();
453 461
454 task_protections((unsigned long) &init_thread_info); 462 stack_protections((unsigned long) &init_thread_info);
455 os_flush_stdout(); 463 os_flush_stdout();
456 464
457 return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); 465 return CHOOSE_MODE(start_uml_tt(), start_uml_skas());
458} 466}
459 467
460extern int uml_exitcode; 468extern int uml_exitcode;
@@ -466,8 +474,8 @@ static int panic_exit(struct notifier_block *self, unsigned long unused1,
466 show_regs(&(current->thread.regs)); 474 show_regs(&(current->thread.regs));
467 bust_spinlocks(0); 475 bust_spinlocks(0);
468 uml_exitcode = 1; 476 uml_exitcode = 1;
469 machine_halt(); 477 os_dump_core();
470 return(0); 478 return 0;
471} 479}
472 480
473static struct notifier_block panic_exit_notifier = { 481static struct notifier_block panic_exit_notifier = {
@@ -482,14 +490,14 @@ void __init setup_arch(char **cmdline_p)
482 &panic_exit_notifier); 490 &panic_exit_notifier);
483 paging_init(); 491 paging_init();
484 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); 492 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
485 *cmdline_p = command_line; 493 *cmdline_p = command_line;
486 setup_hostinfo(); 494 setup_hostinfo(host_info, sizeof host_info);
487} 495}
488 496
489void __init check_bugs(void) 497void __init check_bugs(void)
490{ 498{
491 arch_check_bugs(); 499 arch_check_bugs();
492 os_check_bugs(); 500 os_check_bugs();
493} 501}
494 502
495void apply_alternatives(struct alt_instr *start, struct alt_instr *end) 503void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index f6301274cf3c..bc59f97e34d0 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -59,6 +59,8 @@ SECTIONS
59 { 59 {
60 . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ 60 . = ALIGN(KERNEL_STACK_SIZE); /* init_task */
61 *(.data.init_task) 61 *(.data.init_task)
62 . = ALIGN(KERNEL_STACK_SIZE);
63 *(.data.init_irqstack)
62 *(.data) 64 *(.data)
63 *(.gnu.linkonce.d*) 65 *(.gnu.linkonce.d*)
64 CONSTRUCTORS 66 CONSTRUCTORS
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 6ff12743a0bd..9bf944f6a1db 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -132,10 +132,10 @@ static int aio_thread(void *arg)
132 { .data = (void *) (long) event.data, 132 { .data = (void *) (long) event.data,
133 .err = event.res }); 133 .err = event.res });
134 reply_fd = ((struct aio_context *) reply.data)->reply_fd; 134 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
135 err = os_write_file(reply_fd, &reply, sizeof(reply)); 135 err = write(reply_fd, &reply, sizeof(reply));
136 if(err != sizeof(reply)) 136 if(err != sizeof(reply))
137 printk("aio_thread - write failed, fd = %d, " 137 printk("aio_thread - write failed, fd = %d, "
138 "err = %d\n", reply_fd, -err); 138 "err = %d\n", reply_fd, errno);
139 } 139 }
140 } 140 }
141 return 0; 141 return 0;
@@ -146,38 +146,31 @@ static int aio_thread(void *arg)
146static int do_not_aio(struct aio_thread_req *req) 146static int do_not_aio(struct aio_thread_req *req)
147{ 147{
148 char c; 148 char c;
149 int err; 149 unsigned long long actual;
150 int n;
151
152 actual = lseek64(req->io_fd, req->offset, SEEK_SET);
153 if(actual != req->offset)
154 return -errno;
150 155
151 switch(req->type){ 156 switch(req->type){
152 case AIO_READ: 157 case AIO_READ:
153 err = os_seek_file(req->io_fd, req->offset); 158 n = read(req->io_fd, req->buf, req->len);
154 if(err)
155 goto out;
156
157 err = os_read_file(req->io_fd, req->buf, req->len);
158 break; 159 break;
159 case AIO_WRITE: 160 case AIO_WRITE:
160 err = os_seek_file(req->io_fd, req->offset); 161 n = write(req->io_fd, req->buf, req->len);
161 if(err)
162 goto out;
163
164 err = os_write_file(req->io_fd, req->buf, req->len);
165 break; 162 break;
166 case AIO_MMAP: 163 case AIO_MMAP:
167 err = os_seek_file(req->io_fd, req->offset); 164 n = read(req->io_fd, &c, sizeof(c));
168 if(err)
169 goto out;
170
171 err = os_read_file(req->io_fd, &c, sizeof(c));
172 break; 165 break;
173 default: 166 default:
174 printk("do_not_aio - bad request type : %d\n", req->type); 167 printk("do_not_aio - bad request type : %d\n", req->type);
175 err = -EINVAL; 168 return -EINVAL;
176 break;
177 } 169 }
178 170
179out: 171 if(n < 0)
180 return err; 172 return -errno;
173 return 0;
181} 174}
182 175
183/* These are initialized in initcalls and not changed */ 176/* These are initialized in initcalls and not changed */
@@ -193,12 +186,12 @@ static int not_aio_thread(void *arg)
193 186
194 signal(SIGWINCH, SIG_IGN); 187 signal(SIGWINCH, SIG_IGN);
195 while(1){ 188 while(1){
196 err = os_read_file(aio_req_fd_r, &req, sizeof(req)); 189 err = read(aio_req_fd_r, &req, sizeof(req));
197 if(err != sizeof(req)){ 190 if(err != sizeof(req)){
198 if(err < 0) 191 if(err < 0)
199 printk("not_aio_thread - read failed, " 192 printk("not_aio_thread - read failed, "
200 "fd = %d, err = %d\n", aio_req_fd_r, 193 "fd = %d, err = %d\n", aio_req_fd_r,
201 -err); 194 errno);
202 else { 195 else {
203 printk("not_aio_thread - short read, fd = %d, " 196 printk("not_aio_thread - short read, fd = %d, "
204 "length = %d\n", aio_req_fd_r, err); 197 "length = %d\n", aio_req_fd_r, err);
@@ -207,11 +200,11 @@ static int not_aio_thread(void *arg)
207 } 200 }
208 err = do_not_aio(&req); 201 err = do_not_aio(&req);
209 reply = ((struct aio_thread_reply) { .data = req.aio, 202 reply = ((struct aio_thread_reply) { .data = req.aio,
210 .err = err }); 203 .err = err });
211 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); 204 err = write(req.aio->reply_fd, &reply, sizeof(reply));
212 if(err != sizeof(reply)) 205 if(err != sizeof(reply))
213 printk("not_aio_thread - write failed, fd = %d, " 206 printk("not_aio_thread - write failed, fd = %d, "
214 "err = %d\n", req.aio->reply_fd, -err); 207 "err = %d\n", req.aio->reply_fd, errno);
215 } 208 }
216 209
217 return 0; 210 return 0;
@@ -228,6 +221,11 @@ static int init_aio_24(void)
228 221
229 aio_req_fd_w = fds[0]; 222 aio_req_fd_w = fds[0];
230 aio_req_fd_r = fds[1]; 223 aio_req_fd_r = fds[1];
224
225 err = os_set_fd_block(aio_req_fd_w, 0);
226 if(err)
227 goto out_close_pipe;
228
231 err = run_helper_thread(not_aio_thread, NULL, 229 err = run_helper_thread(not_aio_thread, NULL,
232 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); 230 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
233 if(err < 0) 231 if(err < 0)
@@ -285,10 +283,12 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
285 if(err){ 283 if(err){
286 reply = ((struct aio_thread_reply) { .data = aio, 284 reply = ((struct aio_thread_reply) { .data = aio,
287 .err = err }); 285 .err = err });
288 err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); 286 err = write(aio->reply_fd, &reply, sizeof(reply));
289 if(err != sizeof(reply)) 287 if(err != sizeof(reply)){
288 err = -errno;
290 printk("submit_aio_26 - write failed, " 289 printk("submit_aio_26 - write failed, "
291 "fd = %d, err = %d\n", aio->reply_fd, -err); 290 "fd = %d, err = %d\n", aio->reply_fd, -err);
291 }
292 else err = 0; 292 else err = 0;
293 } 293 }
294 294
@@ -383,9 +383,10 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
383 }; 383 };
384 int err; 384 int err;
385 385
386 err = os_write_file(aio_req_fd_w, &req, sizeof(req)); 386 err = write(aio_req_fd_w, &req, sizeof(req));
387 if(err == sizeof(req)) 387 if(err == sizeof(req))
388 err = 0; 388 err = 0;
389 else err = -errno;
389 390
390 return err; 391 return err;
391} 392}
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 863981ba1468..acba30161287 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
3 * James Leu (jleu@mindspring.net). 3 * James Leu (jleu@mindspring.net).
4 * Copyright (C) 2001 by various other people who didn't put their name here. 4 * Copyright (C) 2001 by various other people who didn't put their name here.
5 * Licensed under the GPL. 5 * Licensed under the GPL.
@@ -16,19 +16,20 @@
16#include <net/if.h> 16#include <net/if.h>
17#include "user.h" 17#include "user.h"
18#include "kern_util.h" 18#include "kern_util.h"
19#include "user_util.h"
20#include "net_user.h" 19#include "net_user.h"
21#include "etap.h" 20#include "etap.h"
22#include "os.h" 21#include "os.h"
23#include "um_malloc.h" 22#include "um_malloc.h"
23#include "kern_constants.h"
24 24
25#define MAX_PACKET ETH_MAX_PACKET 25#define MAX_PACKET ETH_MAX_PACKET
26 26
27void etap_user_init(void *data, void *dev) 27static int etap_user_init(void *data, void *dev)
28{ 28{
29 struct ethertap_data *pri = data; 29 struct ethertap_data *pri = data;
30 30
31 pri->dev = dev; 31 pri->dev = dev;
32 return 0;
32} 33}
33 34
34struct addr_change { 35struct addr_change {
@@ -47,13 +48,16 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
47 change.what = op; 48 change.what = op;
48 memcpy(change.addr, addr, sizeof(change.addr)); 49 memcpy(change.addr, addr, sizeof(change.addr));
49 memcpy(change.netmask, netmask, sizeof(change.netmask)); 50 memcpy(change.netmask, netmask, sizeof(change.netmask));
50 n = os_write_file(fd, &change, sizeof(change)); 51 CATCH_EINTR(n = write(fd, &change, sizeof(change)));
51 if(n != sizeof(change)) 52 if(n != sizeof(change)){
52 printk("etap_change - request failed, err = %d\n", -n); 53 printk("etap_change - request failed, err = %d\n", errno);
53 output = um_kmalloc(page_size()); 54 return;
55 }
56
57 output = um_kmalloc(UM_KERN_PAGE_SIZE);
54 if(output == NULL) 58 if(output == NULL)
55 printk("etap_change : Failed to allocate output buffer\n"); 59 printk("etap_change : Failed to allocate output buffer\n");
56 read_output(fd, output, page_size()); 60 read_output(fd, output, UM_KERN_PAGE_SIZE);
57 if(output != NULL){ 61 if(output != NULL){
58 printk("%s", output); 62 printk("%s", output);
59 kfree(output); 63 kfree(output);
@@ -115,13 +119,15 @@ static int etap_tramp(char *dev, char *gate, int control_me,
115 pe_data.data_me = data_me; 119 pe_data.data_me = data_me;
116 pid = run_helper(etap_pre_exec, &pe_data, args, NULL); 120 pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
117 121
118 if(pid < 0) err = pid; 122 if(pid < 0)
123 err = pid;
119 os_close_file(data_remote); 124 os_close_file(data_remote);
120 os_close_file(control_remote); 125 os_close_file(control_remote);
121 n = os_read_file(control_me, &c, sizeof(c)); 126 CATCH_EINTR(n = read(control_me, &c, sizeof(c)));
122 if(n != sizeof(c)){ 127 if(n != sizeof(c)){
123 printk("etap_tramp : read of status failed, err = %d\n", -n); 128 err = -errno;
124 return(-EINVAL); 129 printk("etap_tramp : read of status failed, err = %d\n", -err);
130 return err;
125 } 131 }
126 if(c != 1){ 132 if(c != 1){
127 printk("etap_tramp : uml_net failed\n"); 133 printk("etap_tramp : uml_net failed\n");
@@ -132,7 +138,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
132 else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) 138 else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
133 printk("uml_net didn't exit with status 1\n"); 139 printk("uml_net didn't exit with status 1\n");
134 } 140 }
135 return(err); 141 return err;
136} 142}
137 143
138static int etap_open(void *data) 144static int etap_open(void *data)
@@ -142,23 +148,24 @@ static int etap_open(void *data)
142 int data_fds[2], control_fds[2], err, output_len; 148 int data_fds[2], control_fds[2], err, output_len;
143 149
144 err = tap_open_common(pri->dev, pri->gate_addr); 150 err = tap_open_common(pri->dev, pri->gate_addr);
145 if(err) return(err); 151 if(err)
152 return err;
146 153
147 err = os_pipe(data_fds, 0, 0); 154 err = os_pipe(data_fds, 0, 0);
148 if(err < 0){ 155 if(err < 0){
149 printk("data os_pipe failed - err = %d\n", -err); 156 printk("data os_pipe failed - err = %d\n", -err);
150 return(err); 157 return err;
151 } 158 }
152 159
153 err = os_pipe(control_fds, 1, 0); 160 err = os_pipe(control_fds, 1, 0);
154 if(err < 0){ 161 if(err < 0){
155 printk("control os_pipe failed - err = %d\n", -err); 162 printk("control os_pipe failed - err = %d\n", -err);
156 return(err); 163 return err;
157 } 164 }
158 165
159 err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], 166 err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
160 control_fds[1], data_fds[0], data_fds[1]); 167 control_fds[1], data_fds[0], data_fds[1]);
161 output_len = page_size(); 168 output_len = UM_KERN_PAGE_SIZE;
162 output = um_kmalloc(output_len); 169 output = um_kmalloc(output_len);
163 read_output(control_fds[0], output, output_len); 170 read_output(control_fds[0], output, output_len);
164 171
@@ -171,13 +178,13 @@ static int etap_open(void *data)
171 178
172 if(err < 0){ 179 if(err < 0){
173 printk("etap_tramp failed - err = %d\n", -err); 180 printk("etap_tramp failed - err = %d\n", -err);
174 return(err); 181 return err;
175 } 182 }
176 183
177 pri->data_fd = data_fds[0]; 184 pri->data_fd = data_fds[0];
178 pri->control_fd = control_fds[0]; 185 pri->control_fd = control_fds[0];
179 iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); 186 iter_addresses(pri->dev, etap_open_addr, &pri->control_fd);
180 return(data_fds[0]); 187 return data_fds[0];
181} 188}
182 189
183static void etap_close(int fd, void *data) 190static void etap_close(int fd, void *data)
@@ -195,7 +202,7 @@ static void etap_close(int fd, void *data)
195 202
196static int etap_set_mtu(int mtu, void *data) 203static int etap_set_mtu(int mtu, void *data)
197{ 204{
198 return(mtu); 205 return mtu;
199} 206}
200 207
201static void etap_add_addr(unsigned char *addr, unsigned char *netmask, 208static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
@@ -204,7 +211,8 @@ static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
204 struct ethertap_data *pri = data; 211 struct ethertap_data *pri = data;
205 212
206 tap_check_ips(pri->gate_addr, addr); 213 tap_check_ips(pri->gate_addr, addr);
207 if(pri->control_fd == -1) return; 214 if(pri->control_fd == -1)
215 return;
208 etap_open_addr(addr, netmask, &pri->control_fd); 216 etap_open_addr(addr, netmask, &pri->control_fd);
209} 217}
210 218
@@ -213,7 +221,8 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
213{ 221{
214 struct ethertap_data *pri = data; 222 struct ethertap_data *pri = data;
215 223
216 if(pri->control_fd == -1) return; 224 if(pri->control_fd == -1)
225 return;
217 etap_close_addr(addr, netmask, &pri->control_fd); 226 etap_close_addr(addr, netmask, &pri->control_fd);
218} 227}
219 228
@@ -227,14 +236,3 @@ const struct net_user_info ethertap_user_info = {
227 .delete_address = etap_del_addr, 236 .delete_address = etap_del_addr,
228 .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP 237 .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP
229}; 238};
230
231/*
232 * Overrides for Emacs so that we follow Linus's tabbing style.
233 * Emacs will notice this stuff at the end of the file and automatically
234 * adjust the settings for this buffer only. This must remain at the end
235 * of the file.
236 * ---------------------------------------------------------------------------
237 * Local variables:
238 * c-file-style: "linux"
239 * End:
240 */
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index e846b23f7558..11a9779dc9f1 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -18,17 +18,17 @@
18#include "net_user.h" 18#include "net_user.h"
19#include "tuntap.h" 19#include "tuntap.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "user_util.h"
22#include "user.h" 21#include "user.h"
23#include "os.h" 22#include "os.h"
24 23
25#define MAX_PACKET ETH_MAX_PACKET 24#define MAX_PACKET ETH_MAX_PACKET
26 25
27void tuntap_user_init(void *data, void *dev) 26static int tuntap_user_init(void *data, void *dev)
28{ 27{
29 struct tuntap_data *pri = data; 28 struct tuntap_data *pri = data;
30 29
31 pri->dev = dev; 30 pri->dev = dev;
31 return 0;
32} 32}
33 33
34static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, 34static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
@@ -37,7 +37,8 @@ static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
37 struct tuntap_data *pri = data; 37 struct tuntap_data *pri = data;
38 38
39 tap_check_ips(pri->gate_addr, addr); 39 tap_check_ips(pri->gate_addr, addr);
40 if((pri->fd == -1) || pri->fixed_config) return; 40 if((pri->fd == -1) || pri->fixed_config)
41 return;
41 open_addr(addr, netmask, pri->dev_name); 42 open_addr(addr, netmask, pri->dev_name);
42} 43}
43 44
@@ -46,7 +47,8 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask,
46{ 47{
47 struct tuntap_data *pri = data; 48 struct tuntap_data *pri = data;
48 49
49 if((pri->fd == -1) || pri->fixed_config) return; 50 if((pri->fd == -1) || pri->fixed_config)
51 return;
50 close_addr(addr, netmask, pri->dev_name); 52 close_addr(addr, netmask, pri->dev_name);
51} 53}
52 54
@@ -58,7 +60,7 @@ struct tuntap_pre_exec_data {
58static void tuntap_pre_exec(void *arg) 60static void tuntap_pre_exec(void *arg)
59{ 61{
60 struct tuntap_pre_exec_data *data = arg; 62 struct tuntap_pre_exec_data *data = arg;
61 63
62 dup2(data->stdout, 1); 64 dup2(data->stdout, 1);
63 os_close_file(data->close_me); 65 os_close_file(data->close_me);
64} 66}
@@ -83,7 +85,8 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
83 85
84 pid = run_helper(tuntap_pre_exec, &data, argv, NULL); 86 pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
85 87
86 if(pid < 0) return(-pid); 88 if(pid < 0)
89 return -pid;
87 90
88 os_close_file(remote); 91 os_close_file(remote);
89 92
@@ -114,16 +117,16 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
114 cmsg = CMSG_FIRSTHDR(&msg); 117 cmsg = CMSG_FIRSTHDR(&msg);
115 if(cmsg == NULL){ 118 if(cmsg == NULL){
116 printk("tuntap_open_tramp : didn't receive a message\n"); 119 printk("tuntap_open_tramp : didn't receive a message\n");
117 return(-EINVAL); 120 return -EINVAL;
118 } 121 }
119 if((cmsg->cmsg_level != SOL_SOCKET) || 122 if((cmsg->cmsg_level != SOL_SOCKET) ||
120 (cmsg->cmsg_type != SCM_RIGHTS)){ 123 (cmsg->cmsg_type != SCM_RIGHTS)){
121 printk("tuntap_open_tramp : didn't receive a descriptor\n"); 124 printk("tuntap_open_tramp : didn't receive a descriptor\n");
122 return(-EINVAL); 125 return -EINVAL;
123 } 126 }
124 *fd_out = ((int *) CMSG_DATA(cmsg))[0]; 127 *fd_out = ((int *) CMSG_DATA(cmsg))[0];
125 os_set_exec_close(*fd_out, 1); 128 os_set_exec_close(*fd_out, 1);
126 return(0); 129 return 0;
127} 130}
128 131
129static int tuntap_open(void *data) 132static int tuntap_open(void *data)
@@ -135,7 +138,7 @@ static int tuntap_open(void *data)
135 138
136 err = tap_open_common(pri->dev, pri->gate_addr); 139 err = tap_open_common(pri->dev, pri->gate_addr);
137 if(err < 0) 140 if(err < 0)
138 return(err); 141 return err;
139 142
140 if(pri->fixed_config){ 143 if(pri->fixed_config){
141 pri->fd = os_open_file("/dev/net/tun", 144 pri->fd = os_open_file("/dev/net/tun",
@@ -143,7 +146,7 @@ static int tuntap_open(void *data)
143 if(pri->fd < 0){ 146 if(pri->fd < 0){
144 printk("Failed to open /dev/net/tun, err = %d\n", 147 printk("Failed to open /dev/net/tun, err = %d\n",
145 -pri->fd); 148 -pri->fd);
146 return(pri->fd); 149 return pri->fd;
147 } 150 }
148 memset(&ifr, 0, sizeof(ifr)); 151 memset(&ifr, 0, sizeof(ifr));
149 ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 152 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
@@ -160,7 +163,7 @@ static int tuntap_open(void *data)
160 if(err < 0){ 163 if(err < 0){
161 printk("tuntap_open : os_pipe failed - err = %d\n", 164 printk("tuntap_open : os_pipe failed - err = %d\n",
162 -err); 165 -err);
163 return(err); 166 return err;
164 } 167 }
165 168
166 buffer = get_output_buffer(&len); 169 buffer = get_output_buffer(&len);
@@ -175,7 +178,7 @@ static int tuntap_open(void *data)
175 printk("%s", output); 178 printk("%s", output);
176 free_output_buffer(buffer); 179 free_output_buffer(buffer);
177 printk("tuntap_open_tramp failed - err = %d\n", -err); 180 printk("tuntap_open_tramp failed - err = %d\n", -err);
178 return(err); 181 return err;
179 } 182 }
180 183
181 pri->dev_name = uml_strdup(buffer); 184 pri->dev_name = uml_strdup(buffer);
@@ -187,7 +190,7 @@ static int tuntap_open(void *data)
187 iter_addresses(pri->dev, open_addr, pri->dev_name); 190 iter_addresses(pri->dev, open_addr, pri->dev_name);
188 } 191 }
189 192
190 return(pri->fd); 193 return pri->fd;
191} 194}
192 195
193static void tuntap_close(int fd, void *data) 196static void tuntap_close(int fd, void *data)
@@ -202,7 +205,7 @@ static void tuntap_close(int fd, void *data)
202 205
203static int tuntap_set_mtu(int mtu, void *data) 206static int tuntap_set_mtu(int mtu, void *data)
204{ 207{
205 return(mtu); 208 return mtu;
206} 209}
207 210
208const struct net_user_info tuntap_user_info = { 211const struct net_user_info tuntap_user_info = {
@@ -215,14 +218,3 @@ const struct net_user_info tuntap_user_info = {
215 .delete_address = tuntap_del_addr, 218 .delete_address = tuntap_del_addr,
216 .max_packet = MAX_PACKET 219 .max_packet = MAX_PACKET
217}; 220};
218
219/*
220 * Overrides for Emacs so that we follow Linus's tabbing style.
221 * Emacs will notice this stuff at the end of the file and automatically
222 * adjust the settings for this buffer only. This must remain at the end
223 * of the file.
224 * ---------------------------------------------------------------------------
225 * Local variables:
226 * c-file-style: "linux"
227 * End:
228 */
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 371b4335f46d..6f92f732d253 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -18,7 +18,6 @@
18#include "os.h" 18#include "os.h"
19#include "user.h" 19#include "user.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "user_util.h"
22 21
23static void copy_stat(struct uml_stat *dst, struct stat64 *src) 22static void copy_stat(struct uml_stat *dst, struct stat64 *src)
24{ 23{
@@ -291,54 +290,22 @@ int os_seek_file(int fd, __u64 offset)
291 return 0; 290 return 0;
292} 291}
293 292
294static int fault_buffer(void *start, int len, 293int os_read_file(int fd, void *buf, int len)
295 int (*copy_proc)(void *addr, void *buf, int len))
296{
297 int page = getpagesize(), i;
298 char c;
299
300 for(i = 0; i < len; i += page){
301 if((*copy_proc)(start + i, &c, sizeof(c)))
302 return -EFAULT;
303 }
304 if((len % page) != 0){
305 if((*copy_proc)(start + len - 1, &c, sizeof(c)))
306 return -EFAULT;
307 }
308 return 0;
309}
310
311static int file_io(int fd, void *buf, int len,
312 int (*io_proc)(int fd, void *buf, int len),
313 int (*copy_user_proc)(void *addr, void *buf, int len))
314{ 294{
315 int n, err; 295 int n = read(fd, buf, len);
316
317 do {
318 n = (*io_proc)(fd, buf, len);
319 if((n < 0) && (errno == EFAULT)){
320 err = fault_buffer(buf, len, copy_user_proc);
321 if(err)
322 return err;
323 n = (*io_proc)(fd, buf, len);
324 }
325 } while((n < 0) && (errno == EINTR));
326 296
327 if(n < 0) 297 if(n < 0)
328 return -errno; 298 return -errno;
329 return n; 299 return n;
330} 300}
331 301
332int os_read_file(int fd, void *buf, int len)
333{
334 return file_io(fd, buf, len, (int (*)(int, void *, int)) read,
335 copy_from_user_proc);
336}
337
338int os_write_file(int fd, const void *buf, int len) 302int os_write_file(int fd, const void *buf, int len)
339{ 303{
340 return file_io(fd, (void *) buf, len, 304 int n = write(fd, (void *) buf, len);
341 (int (*)(int, void *, int)) write, copy_to_user_proc); 305
306 if(n < 0)
307 return -errno;
308 return n;
342} 309}
343 310
344int os_file_size(char *file, unsigned long long *size_out) 311int os_file_size(char *file, unsigned long long *size_out)
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index c7ad6306e22f..97bed16bf4c7 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -13,9 +13,9 @@
13#include <sys/wait.h> 13#include <sys/wait.h>
14#include "user.h" 14#include "user.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user_util.h"
17#include "os.h" 16#include "os.h"
18#include "um_malloc.h" 17#include "um_malloc.h"
18#include "kern_constants.h"
19 19
20struct helper_data { 20struct helper_data {
21 void (*pre_exec)(void*); 21 void (*pre_exec)(void*);
@@ -25,28 +25,18 @@ struct helper_data {
25 char *buf; 25 char *buf;
26}; 26};
27 27
28/* Debugging aid, changed only from gdb */
29int helper_pause = 0;
30
31static void helper_hup(int sig)
32{
33}
34
35static int helper_child(void *arg) 28static int helper_child(void *arg)
36{ 29{
37 struct helper_data *data = arg; 30 struct helper_data *data = arg;
38 char **argv = data->argv; 31 char **argv = data->argv;
39 int errval; 32 int errval;
40 33
41 if (helper_pause){
42 signal(SIGHUP, helper_hup);
43 pause();
44 }
45 if (data->pre_exec != NULL) 34 if (data->pre_exec != NULL)
46 (*data->pre_exec)(data->pre_data); 35 (*data->pre_exec)(data->pre_data);
47 errval = execvp_noalloc(data->buf, argv[0], argv); 36 errval = execvp_noalloc(data->buf, argv[0], argv);
48 printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], -errval); 37 printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0],
49 os_write_file(data->fd, &errval, sizeof(errval)); 38 -errval);
39 write(data->fd, &errval, sizeof(errval));
50 kill(os_getpid(), SIGKILL); 40 kill(os_getpid(), SIGKILL);
51 return 0; 41 return 0;
52} 42}
@@ -81,7 +71,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
81 goto out_close; 71 goto out_close;
82 } 72 }
83 73
84 sp = stack + page_size() - sizeof(void *); 74 sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *);
85 data.pre_exec = pre_exec; 75 data.pre_exec = pre_exec;
86 data.pre_data = pre_data; 76 data.pre_data = pre_data;
87 data.argv = argv; 77 data.argv = argv;
@@ -98,13 +88,16 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
98 close(fds[1]); 88 close(fds[1]);
99 fds[1] = -1; 89 fds[1] = -1;
100 90
101 /* Read the errno value from the child, if the exec failed, or get 0 if 91 /*
102 * the exec succeeded because the pipe fd was set as close-on-exec. */ 92 * Read the errno value from the child, if the exec failed, or get 0 if
103 n = os_read_file(fds[0], &ret, sizeof(ret)); 93 * the exec succeeded because the pipe fd was set as close-on-exec.
94 */
95 n = read(fds[0], &ret, sizeof(ret));
104 if (n == 0) { 96 if (n == 0) {
105 ret = pid; 97 ret = pid;
106 } else { 98 } else {
107 if (n < 0) { 99 if (n < 0) {
100 n = -errno;
108 printk("run_helper : read on pipe failed, ret = %d\n", 101 printk("run_helper : read on pipe failed, ret = %d\n",
109 -n); 102 -n);
110 ret = n; 103 ret = n;
@@ -135,7 +128,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
135 if (stack == 0) 128 if (stack == 0)
136 return -ENOMEM; 129 return -ENOMEM;
137 130
138 sp = stack + (page_size() << stack_order) - sizeof(void *); 131 sp = stack + (UM_KERN_PAGE_SIZE << stack_order) - sizeof(void *);
139 pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); 132 pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
140 if (pid < 0) { 133 if (pid < 0) {
141 err = -errno; 134 err = -errno;
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index d1b61d474e0a..a633fa8e0a94 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -11,7 +11,6 @@
11#include <sys/poll.h> 11#include <sys/poll.h>
12#include <sys/types.h> 12#include <sys/types.h>
13#include <sys/time.h> 13#include <sys/time.h>
14#include "user_util.h"
15#include "kern_util.h" 14#include "kern_util.h"
16#include "user.h" 15#include "user.h"
17#include "process.h" 16#include "process.h"
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 685feaab65d2..ea9a23696f36 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -13,8 +13,8 @@
13#include <sys/mman.h> 13#include <sys/mman.h>
14#include <sys/user.h> 14#include <sys/user.h>
15#include <asm/page.h> 15#include <asm/page.h>
16#include "user_util.h"
17#include "kern_util.h" 16#include "kern_util.h"
17#include "as-layout.h"
18#include "mem_user.h" 18#include "mem_user.h"
19#include "irq_user.h" 19#include "irq_user.h"
20#include "user.h" 20#include "user.h"
@@ -25,12 +25,7 @@
25#include "os.h" 25#include "os.h"
26#include "um_malloc.h" 26#include "um_malloc.h"
27 27
28/* Set in set_stklim, which is called from main and __wrap_malloc. 28/* Set in main, unchanged thereafter */
29 * __wrap_malloc only calls it if main hasn't started.
30 */
31unsigned long stacksizelim;
32
33/* Set in main */
34char *linux_prog; 29char *linux_prog;
35 30
36#define PGD_BOUND (4 * 1024 * 1024) 31#define PGD_BOUND (4 * 1024 * 1024)
@@ -52,7 +47,6 @@ static void set_stklim(void)
52 exit(1); 47 exit(1);
53 } 48 }
54 } 49 }
55 stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
56} 50}
57 51
58static __init void do_uml_initcalls(void) 52static __init void do_uml_initcalls(void)
@@ -126,7 +120,7 @@ extern int uml_exitcode;
126 120
127extern void scan_elf_aux( char **envp); 121extern void scan_elf_aux( char **envp);
128 122
129int main(int argc, char **argv, char **envp) 123int __init main(int argc, char **argv, char **envp)
130{ 124{
131 char **new_argv; 125 char **new_argv;
132 int ret, i, err; 126 int ret, i, err;
@@ -224,7 +218,7 @@ int main(int argc, char **argv, char **envp)
224 ret = 1; 218 ret = 1;
225 } 219 }
226 printf("\n"); 220 printf("\n");
227 return(uml_exitcode); 221 return uml_exitcode;
228} 222}
229 223
230#define CAN_KMALLOC() \ 224#define CAN_KMALLOC() \
@@ -237,7 +231,7 @@ void *__wrap_malloc(int size)
237 void *ret; 231 void *ret;
238 232
239 if(!CAN_KMALLOC()) 233 if(!CAN_KMALLOC())
240 return(__real_malloc(size)); 234 return __real_malloc(size);
241 else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/ 235 else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
242 ret = um_kmalloc(size); 236 ret = um_kmalloc(size);
243 else ret = um_vmalloc(size); 237 else ret = um_vmalloc(size);
@@ -248,16 +242,17 @@ void *__wrap_malloc(int size)
248 if(ret == NULL) 242 if(ret == NULL)
249 errno = ENOMEM; 243 errno = ENOMEM;
250 244
251 return(ret); 245 return ret;
252} 246}
253 247
254void *__wrap_calloc(int n, int size) 248void *__wrap_calloc(int n, int size)
255{ 249{
256 void *ptr = __wrap_malloc(n * size); 250 void *ptr = __wrap_malloc(n * size);
257 251
258 if(ptr == NULL) return(NULL); 252 if(ptr == NULL)
253 return NULL;
259 memset(ptr, 0, n * size); 254 memset(ptr, 0, n * size);
260 return(ptr); 255 return ptr;
261} 256}
262 257
263extern void __real_free(void *); 258extern void __real_free(void *);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index f1ea169db85e..c6378c6d10d2 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -11,7 +11,6 @@
11#include <sys/statfs.h> 11#include <sys/statfs.h>
12#include "kern_util.h" 12#include "kern_util.h"
13#include "user.h" 13#include "user.h"
14#include "user_util.h"
15#include "mem_user.h" 14#include "mem_user.h"
16#include "init.h" 15#include "init.h"
17#include "os.h" 16#include "os.h"
@@ -165,7 +164,8 @@ found:
165 * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). 164 * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
166 * So it isn't 'static' yet. 165 * So it isn't 'static' yet.
167 */ 166 */
168int make_tempfile(const char *template, char **out_tempname, int do_unlink) 167int __init make_tempfile(const char *template, char **out_tempname,
168 int do_unlink)
169{ 169{
170 char *tempname; 170 char *tempname;
171 int fd; 171 int fd;
@@ -206,7 +206,7 @@ out:
206 * This proc is used in start_up.c 206 * This proc is used in start_up.c
207 * So it isn't 'static'. 207 * So it isn't 'static'.
208 */ 208 */
209int create_tmp_file(unsigned long long len) 209int __init create_tmp_file(unsigned long long len)
210{ 210{
211 int fd, err; 211 int fd, err;
212 char zero; 212 char zero;
@@ -232,17 +232,16 @@ int create_tmp_file(unsigned long long len)
232 232
233 zero = 0; 233 zero = 0;
234 234
235 err = os_write_file(fd, &zero, 1); 235 err = write(fd, &zero, 1);
236 if(err != 1){ 236 if(err != 1){
237 errno = -err; 237 perror("write");
238 perror("os_write_file");
239 exit(1); 238 exit(1);
240 } 239 }
241 240
242 return fd; 241 return fd;
243} 242}
244 243
245int create_mem_file(unsigned long long len) 244int __init create_mem_file(unsigned long long len)
246{ 245{
247 int err, fd; 246 int err, fd;
248 247
@@ -257,7 +256,7 @@ int create_mem_file(unsigned long long len)
257} 256}
258 257
259 258
260void check_tmpexec(void) 259void __init check_tmpexec(void)
261{ 260{
262 void *addr; 261 void *addr;
263 int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); 262 int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 76bdd6712417..2d9d2ca39299 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -14,7 +14,6 @@
14#include "ptrace_user.h" 14#include "ptrace_user.h"
15#include "os.h" 15#include "os.h"
16#include "user.h" 16#include "user.h"
17#include "user_util.h"
18#include "process.h" 17#include "process.h"
19#include "irq_user.h" 18#include "irq_user.h"
20#include "kern_util.h" 19#include "kern_util.h"
@@ -22,6 +21,7 @@
22#include "skas_ptrace.h" 21#include "skas_ptrace.h"
23#include "kern_constants.h" 22#include "kern_constants.h"
24#include "uml-config.h" 23#include "uml-config.h"
24#include "init.h"
25 25
26#define ARBITRARY_ADDR -1 26#define ARBITRARY_ADDR -1
27#define FAILURE_PID -1 27#define FAILURE_PID -1
@@ -40,14 +40,14 @@ unsigned long os_process_pc(int pid)
40 if(fd < 0){ 40 if(fd < 0){
41 printk("os_process_pc - couldn't open '%s', err = %d\n", 41 printk("os_process_pc - couldn't open '%s', err = %d\n",
42 proc_stat, -fd); 42 proc_stat, -fd);
43 return(ARBITRARY_ADDR); 43 return ARBITRARY_ADDR;
44 } 44 }
45 err = os_read_file(fd, buf, sizeof(buf)); 45 CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
46 if(err < 0){ 46 if(err < 0){
47 printk("os_process_pc - couldn't read '%s', err = %d\n", 47 printk("os_process_pc - couldn't read '%s', err = %d\n",
48 proc_stat, -err); 48 proc_stat, errno);
49 os_close_file(fd); 49 os_close_file(fd);
50 return(ARBITRARY_ADDR); 50 return ARBITRARY_ADDR;
51 } 51 }
52 os_close_file(fd); 52 os_close_file(fd);
53 pc = ARBITRARY_ADDR; 53 pc = ARBITRARY_ADDR;
@@ -56,7 +56,7 @@ unsigned long os_process_pc(int pid)
56 "%*d %*d %*d %*d %*d %lu", &pc) != 1){ 56 "%*d %*d %*d %*d %*d %lu", &pc) != 1){
57 printk("os_process_pc - couldn't find pc in '%s'\n", buf); 57 printk("os_process_pc - couldn't find pc in '%s'\n", buf);
58 } 58 }
59 return(pc); 59 return pc;
60} 60}
61 61
62int os_process_parent(int pid) 62int os_process_parent(int pid)
@@ -65,21 +65,22 @@ int os_process_parent(int pid)
65 char data[256]; 65 char data[256];
66 int parent, n, fd; 66 int parent, n, fd;
67 67
68 if(pid == -1) return(-1); 68 if(pid == -1)
69 return -1;
69 70
70 snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); 71 snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
71 fd = os_open_file(stat, of_read(OPENFLAGS()), 0); 72 fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
72 if(fd < 0){ 73 if(fd < 0){
73 printk("Couldn't open '%s', err = %d\n", stat, -fd); 74 printk("Couldn't open '%s', err = %d\n", stat, -fd);
74 return(FAILURE_PID); 75 return FAILURE_PID;
75 } 76 }
76 77
77 n = os_read_file(fd, data, sizeof(data)); 78 CATCH_EINTR(n = read(fd, data, sizeof(data)));
78 os_close_file(fd); 79 os_close_file(fd);
79 80
80 if(n < 0){ 81 if(n < 0){
81 printk("Couldn't read '%s', err = %d\n", stat, -n); 82 printk("Couldn't read '%s', err = %d\n", stat, errno);
82 return(FAILURE_PID); 83 return FAILURE_PID;
83 } 84 }
84 85
85 parent = FAILURE_PID; 86 parent = FAILURE_PID;
@@ -87,7 +88,7 @@ int os_process_parent(int pid)
87 if(n != 1) 88 if(n != 1)
88 printk("Failed to scan '%s'\n", data); 89 printk("Failed to scan '%s'\n", data);
89 90
90 return(parent); 91 return parent;
91} 92}
92 93
93void os_stop_process(int pid) 94void os_stop_process(int pid)
@@ -145,7 +146,7 @@ void os_usr1_process(int pid)
145 146
146int os_getpid(void) 147int os_getpid(void)
147{ 148{
148 return(syscall(__NR_getpid)); 149 return syscall(__NR_getpid);
149} 150}
150 151
151int os_getpgrp(void) 152int os_getpgrp(void)
@@ -165,8 +166,8 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
165 loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, 166 loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
166 fd, off); 167 fd, off);
167 if(loc == MAP_FAILED) 168 if(loc == MAP_FAILED)
168 return(-errno); 169 return -errno;
169 return(0); 170 return 0;
170} 171}
171 172
172int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) 173int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
@@ -175,8 +176,8 @@ int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
175 (x ? PROT_EXEC : 0)); 176 (x ? PROT_EXEC : 0));
176 177
177 if(mprotect(addr, len, prot) < 0) 178 if(mprotect(addr, len, prot) < 0)
178 return(-errno); 179 return -errno;
179 return(0); 180 return 0;
180} 181}
181 182
182int os_unmap_memory(void *addr, int len) 183int os_unmap_memory(void *addr, int len)
@@ -185,15 +186,15 @@ int os_unmap_memory(void *addr, int len)
185 186
186 err = munmap(addr, len); 187 err = munmap(addr, len);
187 if(err < 0) 188 if(err < 0)
188 return(-errno); 189 return -errno;
189 return(0); 190 return 0;
190} 191}
191 192
192#ifndef MADV_REMOVE 193#ifndef MADV_REMOVE
193#define MADV_REMOVE KERNEL_MADV_REMOVE 194#define MADV_REMOVE KERNEL_MADV_REMOVE
194#endif 195#endif
195 196
196int os_drop_memory(void *addr, int length) 197int __init os_drop_memory(void *addr, int length)
197{ 198{
198 int err; 199 int err;
199 200
@@ -203,7 +204,7 @@ int os_drop_memory(void *addr, int length)
203 return err; 204 return err;
204} 205}
205 206
206int can_drop_memory(void) 207int __init can_drop_memory(void)
207{ 208{
208 void *addr; 209 void *addr;
209 int fd, ok = 0; 210 int fd, ok = 0;
@@ -238,13 +239,14 @@ out:
238 return ok; 239 return ok;
239} 240}
240 241
242#ifdef UML_CONFIG_MODE_TT
241void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) 243void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
242{ 244{
243 int flags = 0, pages; 245 int flags = 0, pages;
244 246
245 if(sig_stack != NULL){ 247 if(sig_stack != NULL){
246 pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); 248 pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
247 set_sigstack(sig_stack, pages * page_size()); 249 set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE);
248 flags = SA_ONSTACK; 250 flags = SA_ONSTACK;
249 } 251 }
250 if(usr1_handler){ 252 if(usr1_handler){
@@ -259,6 +261,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
259 "errno = %d\n", errno); 261 "errno = %d\n", errno);
260 } 262 }
261} 263}
264#endif
262 265
263void init_new_thread_signals(void) 266void init_new_thread_signals(void)
264{ 267{
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 3fc43b33db66..8d4e0c6b8c92 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -8,6 +8,7 @@
8#include <termios.h> 8#include <termios.h>
9#include <pty.h> 9#include <pty.h>
10#include <signal.h> 10#include <signal.h>
11#include <fcntl.h>
11#include <errno.h> 12#include <errno.h>
12#include <string.h> 13#include <string.h>
13#include <sched.h> 14#include <sched.h>
@@ -16,10 +17,10 @@
16#include "init.h" 17#include "init.h"
17#include "user.h" 18#include "user.h"
18#include "kern_util.h" 19#include "kern_util.h"
19#include "user_util.h"
20#include "sigio.h" 20#include "sigio.h"
21#include "os.h" 21#include "os.h"
22#include "um_malloc.h" 22#include "um_malloc.h"
23#include "init.h"
23 24
24/* Protected by sigio_lock(), also used by sigio_cleanup, which is an 25/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
25 * exitcall. 26 * exitcall.
@@ -68,11 +69,12 @@ static int write_sigio_thread(void *unused)
68 p = &fds->poll[i]; 69 p = &fds->poll[i];
69 if(p->revents == 0) continue; 70 if(p->revents == 0) continue;
70 if(p->fd == sigio_private[1]){ 71 if(p->fd == sigio_private[1]){
71 n = os_read_file(sigio_private[1], &c, sizeof(c)); 72 CATCH_EINTR(n = read(sigio_private[1], &c,
73 sizeof(c)));
72 if(n != sizeof(c)) 74 if(n != sizeof(c))
73 printk("write_sigio_thread : " 75 printk("write_sigio_thread : "
74 "read on socket failed, " 76 "read on socket failed, "
75 "err = %d\n", -n); 77 "err = %d\n", errno);
76 tmp = current_poll; 78 tmp = current_poll;
77 current_poll = next_poll; 79 current_poll = next_poll;
78 next_poll = tmp; 80 next_poll = tmp;
@@ -85,10 +87,10 @@ static int write_sigio_thread(void *unused)
85 (fds->used - i) * sizeof(*fds->poll)); 87 (fds->used - i) * sizeof(*fds->poll));
86 } 88 }
87 89
88 n = os_write_file(respond_fd, &c, sizeof(c)); 90 CATCH_EINTR(n = write(respond_fd, &c, sizeof(c)));
89 if(n != sizeof(c)) 91 if(n != sizeof(c))
90 printk("write_sigio_thread : write on socket " 92 printk("write_sigio_thread : write on socket "
91 "failed, err = %d\n", -n); 93 "failed, err = %d\n", errno);
92 } 94 }
93 } 95 }
94 96
@@ -126,15 +128,15 @@ static void update_thread(void)
126 char c; 128 char c;
127 129
128 flags = set_signals(0); 130 flags = set_signals(0);
129 n = os_write_file(sigio_private[0], &c, sizeof(c)); 131 n = write(sigio_private[0], &c, sizeof(c));
130 if(n != sizeof(c)){ 132 if(n != sizeof(c)){
131 printk("update_thread : write failed, err = %d\n", -n); 133 printk("update_thread : write failed, err = %d\n", errno);
132 goto fail; 134 goto fail;
133 } 135 }
134 136
135 n = os_read_file(sigio_private[0], &c, sizeof(c)); 137 CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c)));
136 if(n != sizeof(c)){ 138 if(n != sizeof(c)){
137 printk("update_thread : read failed, err = %d\n", -n); 139 printk("update_thread : read failed, err = %d\n", errno);
138 goto fail; 140 goto fail;
139 } 141 }
140 142
@@ -320,6 +322,10 @@ out_close1:
320 close(l_write_sigio_fds[1]); 322 close(l_write_sigio_fds[1]);
321} 323}
322 324
325/* Changed during early boot */
326static int pty_output_sigio = 0;
327static int pty_close_sigio = 0;
328
323void maybe_sigio_broken(int fd, int read) 329void maybe_sigio_broken(int fd, int read)
324{ 330{
325 int err; 331 int err;
@@ -357,3 +363,143 @@ static void sigio_cleanup(void)
357} 363}
358 364
359__uml_exitcall(sigio_cleanup); 365__uml_exitcall(sigio_cleanup);
366
367/* Used as a flag during SIGIO testing early in boot */
368static volatile int got_sigio = 0;
369
370static void __init handler(int sig)
371{
372 got_sigio = 1;
373}
374
375struct openpty_arg {
376 int master;
377 int slave;
378 int err;
379};
380
381static void openpty_cb(void *arg)
382{
383 struct openpty_arg *info = arg;
384
385 info->err = 0;
386 if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
387 info->err = -errno;
388}
389
390static int async_pty(int master, int slave)
391{
392 int flags;
393
394 flags = fcntl(master, F_GETFL);
395 if(flags < 0)
396 return -errno;
397
398 if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
399 (fcntl(master, F_SETOWN, os_getpid()) < 0))
400 return -errno;
401
402 if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
403 return -errno;
404
405 return(0);
406}
407
408static void __init check_one_sigio(void (*proc)(int, int))
409{
410 struct sigaction old, new;
411 struct openpty_arg pty = { .master = -1, .slave = -1 };
412 int master, slave, err;
413
414 initial_thread_cb(openpty_cb, &pty);
415 if(pty.err){
416 printk("openpty failed, errno = %d\n", -pty.err);
417 return;
418 }
419
420 master = pty.master;
421 slave = pty.slave;
422
423 if((master == -1) || (slave == -1)){
424 printk("openpty failed to allocate a pty\n");
425 return;
426 }
427
428 /* Not now, but complain so we now where we failed. */
429 err = raw(master);
430 if (err < 0)
431 panic("check_sigio : __raw failed, errno = %d\n", -err);
432
433 err = async_pty(master, slave);
434 if(err < 0)
435 panic("tty_fds : sigio_async failed, err = %d\n", -err);
436
437 if(sigaction(SIGIO, NULL, &old) < 0)
438 panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
439 new = old;
440 new.sa_handler = handler;
441 if(sigaction(SIGIO, &new, NULL) < 0)
442 panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
443
444 got_sigio = 0;
445 (*proc)(master, slave);
446
447 close(master);
448 close(slave);
449
450 if(sigaction(SIGIO, &old, NULL) < 0)
451 panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
452}
453
454static void tty_output(int master, int slave)
455{
456 int n;
457 char buf[512];
458
459 printk("Checking that host ptys support output SIGIO...");
460
461 memset(buf, 0, sizeof(buf));
462
463 while(write(master, buf, sizeof(buf)) > 0) ;
464 if(errno != EAGAIN)
465 panic("tty_output : write failed, errno = %d\n", errno);
466 while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
467
468 if(got_sigio){
469 printk("Yes\n");
470 pty_output_sigio = 1;
471 }
472 else if(n == -EAGAIN)
473 printk("No, enabling workaround\n");
474 else panic("tty_output : read failed, err = %d\n", n);
475}
476
477static void tty_close(int master, int slave)
478{
479 printk("Checking that host ptys support SIGIO on close...");
480
481 close(slave);
482 if(got_sigio){
483 printk("Yes\n");
484 pty_close_sigio = 1;
485 }
486 else printk("No, enabling workaround\n");
487}
488
489void __init check_sigio(void)
490{
491 if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
492 (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
493 printk("No pseudo-terminals available - skipping pty SIGIO "
494 "check\n");
495 return;
496 }
497 check_one_sigio(tty_output);
498 check_one_sigio(tty_close);
499}
500
501/* Here because it only does the SIGIO testing for now */
502void __init os_check_bugs(void)
503{
504 check_sigio();
505}
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 266768629fee..18e5c8b67eb8 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -11,7 +11,6 @@
11#include <stdarg.h> 11#include <stdarg.h>
12#include <string.h> 12#include <string.h>
13#include <sys/mman.h> 13#include <sys/mman.h>
14#include "user_util.h"
15#include "user.h" 14#include "user.h"
16#include "signal_kern.h" 15#include "signal_kern.h"
17#include "sysdep/sigcontext.h" 16#include "sysdep/sigcontext.h"
@@ -62,15 +61,19 @@ void sig_handler(int sig, struct sigcontext *sc)
62 61
63static void real_alarm_handler(int sig, struct sigcontext *sc) 62static void real_alarm_handler(int sig, struct sigcontext *sc)
64{ 63{
64 union uml_pt_regs regs;
65
65 if(sig == SIGALRM) 66 if(sig == SIGALRM)
66 switch_timers(0); 67 switch_timers(0);
67 68
68 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, 69 if(sc != NULL)
69 sig, sc); 70 copy_sc(&regs, sc);
71 regs.skas.is_user = 0;
72 unblock_signals();
73 timer_handler(sig, &regs);
70 74
71 if(sig == SIGALRM) 75 if(sig == SIGALRM)
72 switch_timers(1); 76 switch_timers(1);
73
74} 77}
75 78
76void alarm_handler(int sig, struct sigcontext *sc) 79void alarm_handler(int sig, struct sigcontext *sc)
@@ -114,6 +117,46 @@ void remove_sigstack(void)
114 117
115void (*handlers[_NSIG])(int sig, struct sigcontext *sc); 118void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
116 119
120void handle_signal(int sig, struct sigcontext *sc)
121{
122 unsigned long pending = 0;
123
124 do {
125 int nested, bail;
126
127 /*
128 * pending comes back with one bit set for each
129 * interrupt that arrived while setting up the stack,
130 * plus a bit for this interrupt, plus the zero bit is
131 * set if this is a nested interrupt.
132 * If bail is true, then we interrupted another
133 * handler setting up the stack. In this case, we
134 * have to return, and the upper handler will deal
135 * with this interrupt.
136 */
137 bail = to_irq_stack(sig, &pending);
138 if(bail)
139 return;
140
141 nested = pending & 1;
142 pending &= ~1;
143
144 while((sig = ffs(pending)) != 0){
145 sig--;
146 pending &= ~(1 << sig);
147 (*handlers[sig])(sig, sc);
148 }
149
150 /* Again, pending comes back with a mask of signals
151 * that arrived while tearing down the stack. If this
152 * is non-zero, we just go back, set up the stack
153 * again, and handle the new interrupts.
154 */
155 if(!nested)
156 pending = from_irq_stack(nested);
157 } while(pending);
158}
159
117extern void hard_handler(int sig); 160extern void hard_handler(int sig);
118 161
119void set_handler(int sig, void (*handler)(int), int flags, ...) 162void set_handler(int sig, void (*handler)(int), int flags, ...)
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 9383e8751ae7..5c8946320799 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -6,6 +6,7 @@
6#include <signal.h> 6#include <signal.h>
7#include <errno.h> 7#include <errno.h>
8#include <string.h> 8#include <string.h>
9#include <unistd.h>
9#include <sys/mman.h> 10#include <sys/mman.h>
10#include <sys/wait.h> 11#include <sys/wait.h>
11#include <asm/page.h> 12#include <asm/page.h>
@@ -17,17 +18,17 @@
17#include "os.h" 18#include "os.h"
18#include "proc_mm.h" 19#include "proc_mm.h"
19#include "ptrace_user.h" 20#include "ptrace_user.h"
20#include "user_util.h"
21#include "kern_util.h" 21#include "kern_util.h"
22#include "task.h" 22#include "task.h"
23#include "registers.h" 23#include "registers.h"
24#include "uml-config.h" 24#include "uml-config.h"
25#include "sysdep/ptrace.h" 25#include "sysdep/ptrace.h"
26#include "sysdep/stub.h" 26#include "sysdep/stub.h"
27#include "init.h"
27 28
28extern unsigned long batch_syscall_stub, __syscall_stub_start; 29extern unsigned long batch_syscall_stub, __syscall_stub_start;
29 30
30extern void wait_stub_done(int pid, int sig, char * fname); 31extern void wait_stub_done(int pid);
31 32
32static inline unsigned long *check_init_stack(struct mm_id * mm_idp, 33static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
33 unsigned long *stack) 34 unsigned long *stack)
@@ -39,6 +40,19 @@ static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
39 return stack; 40 return stack;
40} 41}
41 42
43static unsigned long syscall_regs[MAX_REG_NR];
44
45static int __init init_syscall_regs(void)
46{
47 get_safe_registers(syscall_regs, NULL);
48 syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
49 ((unsigned long) &batch_syscall_stub -
50 (unsigned long) &__syscall_stub_start);
51 return 0;
52}
53
54__initcall(init_syscall_regs);
55
42extern int proc_mm; 56extern int proc_mm;
43 57
44int single_count = 0; 58int single_count = 0;
@@ -47,34 +61,33 @@ int multi_op_count = 0;
47 61
48static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) 62static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
49{ 63{
50 unsigned long regs[MAX_REG_NR];
51 int n, i; 64 int n, i;
52 long ret, offset; 65 long ret, offset;
53 unsigned long * data; 66 unsigned long * data;
54 unsigned long * syscall; 67 unsigned long * syscall;
55 int pid = mm_idp->u.pid; 68 int err, pid = mm_idp->u.pid;
56 69
57 if(proc_mm) 70 if(proc_mm)
58#warning Need to look up userspace_pid by cpu 71 /* FIXME: Need to look up userspace_pid by cpu */
59 pid = userspace_pid[0]; 72 pid = userspace_pid[0];
60 73
61 multi_count++; 74 multi_count++;
62 75
63 get_safe_registers(regs, NULL); 76 n = ptrace_setregs(pid, syscall_regs);
64 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
65 ((unsigned long) &batch_syscall_stub -
66 (unsigned long) &__syscall_stub_start);
67
68 n = ptrace_setregs(pid, regs);
69 if(n < 0){ 77 if(n < 0){
70 printk("Registers - \n"); 78 printk("Registers - \n");
71 for(i = 0; i < MAX_REG_NR; i++) 79 for(i = 0; i < MAX_REG_NR; i++)
72 printk("\t%d\t0x%lx\n", i, regs[i]); 80 printk("\t%d\t0x%lx\n", i, syscall_regs[i]);
73 panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", 81 panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
74 -n); 82 -n);
75 } 83 }
76 84
77 wait_stub_done(pid, 0, "do_syscall_stub"); 85 err = ptrace(PTRACE_CONT, pid, 0, 0);
86 if(err)
87 panic("Failed to continue stub, pid = %d, errno = %d\n", pid,
88 errno);
89
90 wait_stub_done(pid);
78 91
79 /* When the stub stops, we find the following values on the 92 /* When the stub stops, we find the following values on the
80 * beginning of the stack: 93 * beginning of the stack:
@@ -176,14 +189,10 @@ long syscall_stub_data(struct mm_id * mm_idp,
176 return 0; 189 return 0;
177} 190}
178 191
179int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, 192int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot,
180 int r, int w, int x, int phys_fd, unsigned long long offset, 193 int phys_fd, unsigned long long offset, int done, void **data)
181 int done, void **data)
182{ 194{
183 int prot, ret; 195 int ret;
184
185 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
186 (x ? PROT_EXEC : 0);
187 196
188 if(proc_mm){ 197 if(proc_mm){
189 struct proc_mm_op map; 198 struct proc_mm_op map;
@@ -200,9 +209,11 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
200 .fd = phys_fd, 209 .fd = phys_fd,
201 .offset= offset 210 .offset= offset
202 } } } ); 211 } } } );
203 ret = os_write_file(fd, &map, sizeof(map)); 212 CATCH_EINTR(ret = write(fd, &map, sizeof(map)));
204 if(ret != sizeof(map)) 213 if(ret != sizeof(map)){
214 ret = -errno;
205 printk("map : /proc/mm map failed, err = %d\n", -ret); 215 printk("map : /proc/mm map failed, err = %d\n", -ret);
216 }
206 else ret = 0; 217 else ret = 0;
207 } 218 }
208 else { 219 else {
@@ -217,8 +228,8 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
217 return ret; 228 return ret;
218} 229}
219 230
220int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, 231int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
221 void **data) 232 int done, void **data)
222{ 233{
223 int ret; 234 int ret;
224 235
@@ -232,9 +243,11 @@ int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
232 { .addr = 243 { .addr =
233 (unsigned long) addr, 244 (unsigned long) addr,
234 .len = len } } } ); 245 .len = len } } } );
235 ret = os_write_file(fd, &unmap, sizeof(unmap)); 246 CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap)));
236 if(ret != sizeof(unmap)) 247 if(ret != sizeof(unmap)){
248 ret = -errno;
237 printk("unmap - proc_mm write returned %d\n", ret); 249 printk("unmap - proc_mm write returned %d\n", ret);
250 }
238 else ret = 0; 251 else ret = 0;
239 } 252 }
240 else { 253 else {
@@ -249,13 +262,11 @@ int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
249} 262}
250 263
251int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, 264int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
252 int r, int w, int x, int done, void **data) 265 unsigned int prot, int done, void **data)
253{ 266{
254 struct proc_mm_op protect; 267 struct proc_mm_op protect;
255 int prot, ret; 268 int ret;
256 269
257 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
258 (x ? PROT_EXEC : 0);
259 if(proc_mm){ 270 if(proc_mm){
260 int fd = mm_idp->u.mm_fd; 271 int fd = mm_idp->u.mm_fd;
261 272
@@ -267,9 +278,11 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
267 .len = len, 278 .len = len,
268 .prot = prot } } } ); 279 .prot = prot } } } );
269 280
270 ret = os_write_file(fd, &protect, sizeof(protect)); 281 CATCH_EINTR(ret = write(fd, &protect, sizeof(protect)));
271 if(ret != sizeof(protect)) 282 if(ret != sizeof(protect)){
283 ret = -errno;
272 printk("protect failed, err = %d", -ret); 284 printk("protect failed, err = %d", -ret);
285 }
273 else ret = 0; 286 else ret = 0;
274 } 287 }
275 else { 288 else {
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 0564422c155f..f9d2f8545afe 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -18,7 +18,6 @@
18#include <asm/types.h> 18#include <asm/types.h>
19#include "user.h" 19#include "user.h"
20#include "sysdep/ptrace.h" 20#include "sysdep/ptrace.h"
21#include "user_util.h"
22#include "kern_util.h" 21#include "kern_util.h"
23#include "skas.h" 22#include "skas.h"
24#include "stub-data.h" 23#include "stub-data.h"
@@ -34,6 +33,8 @@
34#include "uml-config.h" 33#include "uml-config.h"
35#include "process.h" 34#include "process.h"
36#include "longjmp.h" 35#include "longjmp.h"
36#include "kern_constants.h"
37#include "as-layout.h"
37 38
38int is_skas_winch(int pid, int fd, void *data) 39int is_skas_winch(int pid, int fd, void *data)
39{ 40{
@@ -44,45 +45,58 @@ int is_skas_winch(int pid, int fd, void *data)
44 return(1); 45 return(1);
45} 46}
46 47
47void wait_stub_done(int pid, int sig, char * fname) 48static int ptrace_dump_regs(int pid)
48{ 49{
49 int n, status, err; 50 unsigned long regs[MAX_REG_NR];
51 int i;
52
53 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
54 return -errno;
55 else {
56 printk("Stub registers -\n");
57 for(i = 0; i < ARRAY_SIZE(regs); i++)
58 printk("\t%d - %lx\n", i, regs[i]);
59 }
60
61 return 0;
62}
50 63
51 do { 64/*
52 if ( sig != -1 ) { 65 * Signals that are OK to receive in the stub - we'll just continue it.
53 err = ptrace(PTRACE_CONT, pid, 0, sig); 66 * SIGWINCH will happen when UML is inside a detached screen.
54 if(err) 67 */
55 panic("%s : continue failed, errno = %d\n", 68#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))
56 fname, errno);
57 }
58 sig = 0;
59 69
70/* Signals that the stub will finish with - anything else is an error */
71#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
72
73void wait_stub_done(int pid)
74{
75 int n, status, err;
76
77 while(1){
60 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 78 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
61 } while((n >= 0) && WIFSTOPPED(status) && 79 if((n < 0) || !WIFSTOPPED(status))
62 ((WSTOPSIG(status) == SIGVTALRM) || 80 goto bad_wait;
63 /* running UML inside a detached screen can cause 81
64 * SIGWINCHes 82 if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
65 */ 83 break;
66 (WSTOPSIG(status) == SIGWINCH))); 84
67 85 err = ptrace(PTRACE_CONT, pid, 0, 0);
68 if((n < 0) || !WIFSTOPPED(status) || 86 if(err)
69 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ 87 panic("wait_stub_done : continue failed, errno = %d\n",
70 unsigned long regs[MAX_REG_NR]; 88 errno);
71
72 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
73 printk("Failed to get registers from stub, "
74 "errno = %d\n", errno);
75 else {
76 int i;
77
78 printk("Stub registers -\n");
79 for(i = 0; i < ARRAY_SIZE(regs); i++)
80 printk("\t%d - %lx\n", i, regs[i]);
81 }
82 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
83 "pid = %d, n = %d, errno = %d, status = 0x%x\n",
84 fname, pid, n, errno, status);
85 } 89 }
90
91 if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
92 return;
93
94bad_wait:
95 err = ptrace_dump_regs(pid);
96 if(err)
97 printk("Failed to get registers from stub, errno = %d\n", -err);
98 panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
99 "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
86} 100}
87 101
88extern unsigned long current_stub_stack(void); 102extern unsigned long current_stub_stack(void);
@@ -104,7 +118,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
104 sizeof(struct ptrace_faultinfo)); 118 sizeof(struct ptrace_faultinfo));
105 } 119 }
106 else { 120 else {
107 wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); 121 err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
122 if(err)
123 panic("Failed to continue stub, pid = %d, errno = %d\n",
124 pid, errno);
125 wait_stub_done(pid);
108 126
109 /* faultinfo is prepared by the stub-segv-handler at start of 127 /* faultinfo is prepared by the stub-segv-handler at start of
110 * the stub stack page. We just have to copy it. 128 * the stub stack page. We just have to copy it.
@@ -142,9 +160,14 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
142 160
143 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); 161 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
144 if((err < 0) || !WIFSTOPPED(status) || 162 if((err < 0) || !WIFSTOPPED(status) ||
145 (WSTOPSIG(status) != SIGTRAP + 0x80)) 163 (WSTOPSIG(status) != SIGTRAP + 0x80)){
164 err = ptrace_dump_regs(pid);
165 if(err)
166 printk("Failed to get registers from process, "
167 "errno = %d\n", -err);
146 panic("handle_trap - failed to wait at end of syscall, " 168 panic("handle_trap - failed to wait at end of syscall, "
147 "errno = %d, status = %d\n", errno, status); 169 "errno = %d, status = %d\n", errno, status);
170 }
148 } 171 }
149 172
150 handle_syscall(regs); 173 handle_syscall(regs);
@@ -172,7 +195,7 @@ static int userspace_tramp(void *stack)
172 int fd; 195 int fd;
173 __u64 offset; 196 __u64 offset;
174 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); 197 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
175 addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), 198 addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE,
176 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); 199 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
177 if(addr == MAP_FAILED){ 200 if(addr == MAP_FAILED){
178 printk("mapping mmap stub failed, errno = %d\n", 201 printk("mapping mmap stub failed, errno = %d\n",
@@ -182,8 +205,8 @@ static int userspace_tramp(void *stack)
182 205
183 if(stack != NULL){ 206 if(stack != NULL){
184 fd = phys_mapping(to_phys(stack), &offset); 207 fd = phys_mapping(to_phys(stack), &offset);
185 addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), 208 addr = mmap((void *) UML_CONFIG_STUB_DATA,
186 PROT_READ | PROT_WRITE, 209 UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
187 MAP_FIXED | MAP_SHARED, fd, offset); 210 MAP_FIXED | MAP_SHARED, fd, offset);
188 if(addr == MAP_FAILED){ 211 if(addr == MAP_FAILED){
189 printk("mapping segfault stack failed, " 212 printk("mapping segfault stack failed, "
@@ -199,7 +222,7 @@ static int userspace_tramp(void *stack)
199 (unsigned long) stub_segv_handler - 222 (unsigned long) stub_segv_handler -
200 (unsigned long) &__syscall_stub_start; 223 (unsigned long) &__syscall_stub_start;
201 224
202 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); 225 set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE);
203 sigemptyset(&sa.sa_mask); 226 sigemptyset(&sa.sa_mask);
204 sigaddset(&sa.sa_mask, SIGIO); 227 sigaddset(&sa.sa_mask, SIGIO);
205 sigaddset(&sa.sa_mask, SIGWINCH); 228 sigaddset(&sa.sa_mask, SIGWINCH);
@@ -265,7 +288,8 @@ int start_userspace(unsigned long stub_stack)
265void userspace(union uml_pt_regs *regs) 288void userspace(union uml_pt_regs *regs)
266{ 289{
267 int err, status, op, pid = userspace_pid[0]; 290 int err, status, op, pid = userspace_pid[0];
268 int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ 291 /* To prevent races if using_sysemu changes under us.*/
292 int local_using_sysemu;
269 293
270 while(1){ 294 while(1){
271 restore_registers(pid, regs); 295 restore_registers(pid, regs);
@@ -273,7 +297,8 @@ void userspace(union uml_pt_regs *regs)
273 /* Now we set local_using_sysemu to be used for one loop */ 297 /* Now we set local_using_sysemu to be used for one loop */
274 local_using_sysemu = get_using_sysemu(); 298 local_using_sysemu = get_using_sysemu();
275 299
276 op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); 300 op = SELECT_PTRACE_OPERATION(local_using_sysemu,
301 singlestepping(NULL));
277 302
278 err = ptrace(op, pid, 0, 0); 303 err = ptrace(op, pid, 0, 0);
279 if(err) 304 if(err)
@@ -291,10 +316,13 @@ void userspace(union uml_pt_regs *regs)
291 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ 316 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
292 317
293 if(WIFSTOPPED(status)){ 318 if(WIFSTOPPED(status)){
294 switch(WSTOPSIG(status)){ 319 int sig = WSTOPSIG(status);
320 switch(sig){
295 case SIGSEGV: 321 case SIGSEGV:
296 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) 322 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){
297 user_signal(SIGSEGV, regs, pid); 323 get_skas_faultinfo(pid, &regs->skas.faultinfo);
324 (*sig_info[SIGSEGV])(SIGSEGV, regs);
325 }
298 else handle_segv(pid, regs); 326 else handle_segv(pid, regs);
299 break; 327 break;
300 case SIGTRAP + 0x80: 328 case SIGTRAP + 0x80:
@@ -309,11 +337,13 @@ void userspace(union uml_pt_regs *regs)
309 case SIGBUS: 337 case SIGBUS:
310 case SIGFPE: 338 case SIGFPE:
311 case SIGWINCH: 339 case SIGWINCH:
312 user_signal(WSTOPSIG(status), regs, pid); 340 block_signals();
341 (*sig_info[sig])(sig, regs);
342 unblock_signals();
313 break; 343 break;
314 default: 344 default:
315 printk("userspace - child stopped with signal " 345 printk("userspace - child stopped with signal "
316 "%d\n", WSTOPSIG(status)); 346 "%d\n", sig);
317 } 347 }
318 pid = userspace_pid[0]; 348 pid = userspace_pid[0];
319 interrupt_end(); 349 interrupt_end();
@@ -325,11 +355,29 @@ void userspace(union uml_pt_regs *regs)
325 } 355 }
326} 356}
327 357
358static unsigned long thread_regs[MAX_REG_NR];
359static unsigned long thread_fp_regs[HOST_FP_SIZE];
360
361static int __init init_thread_regs(void)
362{
363 get_safe_registers(thread_regs, thread_fp_regs);
364 /* Set parent's instruction pointer to start of clone-stub */
365 thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
366 (unsigned long) stub_clone_handler -
367 (unsigned long) &__syscall_stub_start;
368 thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
369 sizeof(void *);
370#ifdef __SIGNAL_FRAMESIZE
371 thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
372#endif
373 return 0;
374}
375
376__initcall(init_thread_regs);
377
328int copy_context_skas0(unsigned long new_stack, int pid) 378int copy_context_skas0(unsigned long new_stack, int pid)
329{ 379{
330 int err; 380 int err;
331 unsigned long regs[MAX_REG_NR];
332 unsigned long fp_regs[HOST_FP_SIZE];
333 unsigned long current_stack = current_stub_stack(); 381 unsigned long current_stack = current_stub_stack();
334 struct stub_data *data = (struct stub_data *) current_stack; 382 struct stub_data *data = (struct stub_data *) current_stack;
335 struct stub_data *child_data = (struct stub_data *) new_stack; 383 struct stub_data *child_data = (struct stub_data *) new_stack;
@@ -344,23 +392,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
344 .timer = ((struct itimerval) 392 .timer = ((struct itimerval)
345 { { 0, 1000000 / hz() }, 393 { { 0, 1000000 / hz() },
346 { 0, 1000000 / hz() }})}); 394 { 0, 1000000 / hz() }})});
347 get_safe_registers(regs, fp_regs); 395 err = ptrace_setregs(pid, thread_regs);
348
349 /* Set parent's instruction pointer to start of clone-stub */
350 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
351 (unsigned long) stub_clone_handler -
352 (unsigned long) &__syscall_stub_start;
353 regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
354 sizeof(void *);
355#ifdef __SIGNAL_FRAMESIZE
356 regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
357#endif
358 err = ptrace_setregs(pid, regs);
359 if(err < 0) 396 if(err < 0)
360 panic("copy_context_skas0 : PTRACE_SETREGS failed, " 397 panic("copy_context_skas0 : PTRACE_SETREGS failed, "
361 "pid = %d, errno = %d\n", pid, -err); 398 "pid = %d, errno = %d\n", pid, -err);
362 399
363 err = ptrace_setfpregs(pid, fp_regs); 400 err = ptrace_setfpregs(pid, thread_fp_regs);
364 if(err < 0) 401 if(err < 0)
365 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " 402 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
366 "pid = %d, errno = %d\n", pid, -err); 403 "pid = %d, errno = %d\n", pid, -err);
@@ -371,7 +408,11 @@ int copy_context_skas0(unsigned long new_stack, int pid)
371 /* Wait, until parent has finished its work: read child's pid from 408 /* Wait, until parent has finished its work: read child's pid from
372 * parent's stack, and check, if bad result. 409 * parent's stack, and check, if bad result.
373 */ 410 */
374 wait_stub_done(pid, 0, "copy_context_skas0"); 411 err = ptrace(PTRACE_CONT, pid, 0, 0);
412 if(err)
413 panic("Failed to continue new process, pid = %d, "
414 "errno = %d\n", pid, errno);
415 wait_stub_done(pid);
375 416
376 pid = data->err; 417 pid = data->err;
377 if(pid < 0) 418 if(pid < 0)
@@ -381,7 +422,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
381 /* Wait, until child has finished too: read child's result from 422 /* Wait, until child has finished too: read child's result from
382 * child's stack and check it. 423 * child's stack and check it.
383 */ 424 */
384 wait_stub_done(pid, -1, "copy_context_skas0"); 425 wait_stub_done(pid);
385 if (child_data->err != UML_CONFIG_STUB_DATA) 426 if (child_data->err != UML_CONFIG_STUB_DATA)
386 panic("copy_context_skas0 - stub-child reports error %ld\n", 427 panic("copy_context_skas0 - stub-child reports error %ld\n",
387 child_data->err); 428 child_data->err);
@@ -396,7 +437,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
396 437
397/* 438/*
398 * This is used only, if stub pages are needed, while proc_mm is 439 * This is used only, if stub pages are needed, while proc_mm is
399 * availabl. Opening /proc/mm creates a new mm_context, which lacks 440 * available. Opening /proc/mm creates a new mm_context, which lacks
400 * the stub-pages. Thus, we map them using /proc/mm-fd 441 * the stub-pages. Thus, we map them using /proc/mm-fd
401 */ 442 */
402void map_stub_pages(int fd, unsigned long code, 443void map_stub_pages(int fd, unsigned long code,
@@ -418,12 +459,13 @@ void map_stub_pages(int fd, unsigned long code,
418 .fd = code_fd, 459 .fd = code_fd,
419 .offset = code_offset 460 .offset = code_offset
420 } } }); 461 } } });
421 n = os_write_file(fd, &mmop, sizeof(mmop)); 462 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
422 if(n != sizeof(mmop)){ 463 if(n != sizeof(mmop)){
464 n = errno;
423 printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", 465 printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n",
424 code, code_fd, (unsigned long long) code_offset); 466 code, code_fd, (unsigned long long) code_offset);
425 panic("map_stub_pages : /proc/mm map for code failed, " 467 panic("map_stub_pages : /proc/mm map for code failed, "
426 "err = %d\n", -n); 468 "err = %d\n", n);
427 } 469 }
428 470
429 if ( stack ) { 471 if ( stack ) {
@@ -440,18 +482,18 @@ void map_stub_pages(int fd, unsigned long code,
440 .fd = map_fd, 482 .fd = map_fd,
441 .offset = map_offset 483 .offset = map_offset
442 } } }); 484 } } });
443 n = os_write_file(fd, &mmop, sizeof(mmop)); 485 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
444 if(n != sizeof(mmop)) 486 if(n != sizeof(mmop))
445 panic("map_stub_pages : /proc/mm map for data failed, " 487 panic("map_stub_pages : /proc/mm map for data failed, "
446 "err = %d\n", -n); 488 "err = %d\n", errno);
447 } 489 }
448} 490}
449 491
450void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) 492void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
451{ 493{
452 (*buf)[0].JB_IP = (unsigned long) handler; 494 (*buf)[0].JB_IP = (unsigned long) handler;
453 (*buf)[0].JB_SP = (unsigned long) stack + 495 (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE -
454 (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *); 496 sizeof(void *);
455} 497}
456 498
457#define INIT_JMP_NEW_THREAD 0 499#define INIT_JMP_NEW_THREAD 0
@@ -480,17 +522,24 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
480 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, 522 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
481 SIGVTALRM, -1); 523 SIGVTALRM, -1);
482 524
483 n = UML_SETJMP(&initial_jmpbuf); 525 /*
526 * Can't use UML_SETJMP or UML_LONGJMP here because they save
527 * and restore signals, with the possible side-effect of
528 * trying to handle any signals which came when they were
529 * blocked, which can't be done on this stack.
530 * Signals must be blocked when jumping back here and restored
531 * after returning to the jumper.
532 */
533 n = setjmp(initial_jmpbuf);
484 switch(n){ 534 switch(n){
485 case INIT_JMP_NEW_THREAD: 535 case INIT_JMP_NEW_THREAD:
486 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; 536 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
487 (*switch_buf)[0].JB_SP = (unsigned long) stack + 537 (*switch_buf)[0].JB_SP = (unsigned long) stack +
488 (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - 538 UM_THREAD_SIZE - sizeof(void *);
489 sizeof(void *);
490 break; 539 break;
491 case INIT_JMP_CALLBACK: 540 case INIT_JMP_CALLBACK:
492 (*cb_proc)(cb_arg); 541 (*cb_proc)(cb_arg);
493 UML_LONGJMP(cb_back, 1); 542 longjmp(*cb_back, 1);
494 break; 543 break;
495 case INIT_JMP_HALT: 544 case INIT_JMP_HALT:
496 kmalloc_ok = 0; 545 kmalloc_ok = 0;
@@ -501,7 +550,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
501 default: 550 default:
502 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 551 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
503 } 552 }
504 UML_LONGJMP(switch_buf, 1); 553 longjmp(*switch_buf, 1);
505} 554}
506 555
507void initial_thread_cb_skas(void (*proc)(void *), void *arg) 556void initial_thread_cb_skas(void (*proc)(void *), void *arg)
@@ -538,7 +587,7 @@ void switch_mm_skas(struct mm_id *mm_idp)
538{ 587{
539 int err; 588 int err;
540 589
541#warning need cpu pid in switch_mm_skas 590 /* FIXME: need cpu pid in switch_mm_skas */
542 if(proc_mm){ 591 if(proc_mm){
543 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, 592 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
544 mm_idp->u.mm_fd); 593 mm_idp->u.mm_fd);
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c
index 9ad5fbec4593..3b600c2e63b8 100644
--- a/arch/um/os-Linux/skas/trap.c
+++ b/arch/um/os-Linux/skas/trap.c
@@ -5,8 +5,8 @@
5 5
6#include <signal.h> 6#include <signal.h>
7#include <errno.h> 7#include <errno.h>
8#include "user_util.h"
9#include "kern_util.h" 8#include "kern_util.h"
9#include "as-layout.h"
10#include "task.h" 10#include "task.h"
11#include "sigcontext.h" 11#include "sigcontext.h"
12#include "skas.h" 12#include "skas.h"
@@ -15,29 +15,39 @@
15#include "sysdep/ptrace_user.h" 15#include "sysdep/ptrace_user.h"
16#include "os.h" 16#include "os.h"
17 17
18static union uml_pt_regs ksig_regs[UM_NR_CPUS];
19
18void sig_handler_common_skas(int sig, void *sc_ptr) 20void sig_handler_common_skas(int sig, void *sc_ptr)
19{ 21{
20 struct sigcontext *sc = sc_ptr; 22 struct sigcontext *sc = sc_ptr;
21 struct skas_regs *r; 23 union uml_pt_regs *r;
22 void (*handler)(int, union uml_pt_regs *); 24 void (*handler)(int, union uml_pt_regs *);
23 int save_errno = errno; 25 int save_user, save_errno = errno;
24 int save_user;
25 26
26 /* This is done because to allow SIGSEGV to be delivered inside a SEGV 27 /* This is done because to allow SIGSEGV to be delivered inside a SEGV
27 * handler. This can happen in copy_user, and if SEGV is disabled, 28 * handler. This can happen in copy_user, and if SEGV is disabled,
28 * the process will die. 29 * the process will die.
29 * XXX Figure out why this is better than SA_NODEFER 30 * XXX Figure out why this is better than SA_NODEFER
30 */ 31 */
31 if(sig == SIGSEGV) 32 if(sig == SIGSEGV) {
32 change_sig(SIGSEGV, 1); 33 change_sig(SIGSEGV, 1);
34 /* For segfaults, we want the data from the
35 * sigcontext. In this case, we don't want to mangle
36 * the process registers, so use a static set of
37 * registers. For other signals, the process
38 * registers are OK.
39 */
40 r = &ksig_regs[cpu()];
41 copy_sc(r, sc_ptr);
42 }
43 else r = TASK_REGS(get_current());
33 44
34 r = &TASK_REGS(get_current())->skas; 45 save_user = r->skas.is_user;
35 save_user = r->is_user; 46 r->skas.is_user = 0;
36 r->is_user = 0;
37 if ( sig == SIGFPE || sig == SIGSEGV || 47 if ( sig == SIGFPE || sig == SIGSEGV ||
38 sig == SIGBUS || sig == SIGILL || 48 sig == SIGBUS || sig == SIGILL ||
39 sig == SIGTRAP ) { 49 sig == SIGTRAP ) {
40 GET_FAULTINFO_FROM_SC(r->faultinfo, sc); 50 GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc);
41 } 51 }
42 52
43 change_sig(SIGUSR1, 1); 53 change_sig(SIGUSR1, 1);
@@ -49,25 +59,8 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
49 sig != SIGVTALRM && sig != SIGALRM) 59 sig != SIGVTALRM && sig != SIGALRM)
50 unblock_signals(); 60 unblock_signals();
51 61
52 handler(sig, (union uml_pt_regs *) r); 62 handler(sig, r);
53 63
54 errno = save_errno; 64 errno = save_errno;
55 r->is_user = save_user; 65 r->skas.is_user = save_user;
56}
57
58extern int ptrace_faultinfo;
59
60void user_signal(int sig, union uml_pt_regs *regs, int pid)
61{
62 void (*handler)(int, union uml_pt_regs *);
63 int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
64 (sig == SIGILL) || (sig == SIGTRAP));
65
66 if (segv)
67 get_skas_faultinfo(pid, &regs->skas.faultinfo);
68
69 handler = sig_info[sig];
70 handler(sig, (union uml_pt_regs *) regs);
71
72 unblock_signals();
73} 66}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 5178eba9afa5..79471f85eb89 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -17,10 +17,10 @@
17#include <sys/time.h> 17#include <sys/time.h>
18#include <sys/wait.h> 18#include <sys/wait.h>
19#include <sys/mman.h> 19#include <sys/mman.h>
20#include <sys/resource.h>
20#include <asm/unistd.h> 21#include <asm/unistd.h>
21#include <asm/page.h> 22#include <asm/page.h>
22#include <sys/types.h> 23#include <sys/types.h>
23#include "user_util.h"
24#include "kern_util.h" 24#include "kern_util.h"
25#include "user.h" 25#include "user.h"
26#include "signal_kern.h" 26#include "signal_kern.h"
@@ -329,8 +329,32 @@ static void __init check_ptrace(void)
329 329
330extern void check_tmpexec(void); 330extern void check_tmpexec(void);
331 331
332void os_early_checks(void) 332static void __init check_coredump_limit(void)
333{ 333{
334 struct rlimit lim;
335 int err = getrlimit(RLIMIT_CORE, &lim);
336
337 if(err){
338 perror("Getting core dump limit");
339 return;
340 }
341
342 printf("Core dump limits :\n\tsoft - ");
343 if(lim.rlim_cur == RLIM_INFINITY)
344 printf("NONE\n");
345 else printf("%lu\n", lim.rlim_cur);
346
347 printf("\thard - ");
348 if(lim.rlim_max == RLIM_INFINITY)
349 printf("NONE\n");
350 else printf("%lu\n", lim.rlim_max);
351}
352
353void __init os_early_checks(void)
354{
355 /* Print out the core dump limits early */
356 check_coredump_limit();
357
334 check_ptrace(); 358 check_ptrace();
335 359
336 /* Need to check this early because mmapping happens before the 360 /* Need to check this early because mmapping happens before the
@@ -528,148 +552,3 @@ int __init parse_iomem(char *str, int *add)
528 out: 552 out:
529 return 1; 553 return 1;
530} 554}
531
532
533/* Changed during early boot */
534int pty_output_sigio = 0;
535int pty_close_sigio = 0;
536
537/* Used as a flag during SIGIO testing early in boot */
538static volatile int got_sigio = 0;
539
540static void __init handler(int sig)
541{
542 got_sigio = 1;
543}
544
545struct openpty_arg {
546 int master;
547 int slave;
548 int err;
549};
550
551static void openpty_cb(void *arg)
552{
553 struct openpty_arg *info = arg;
554
555 info->err = 0;
556 if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
557 info->err = -errno;
558}
559
560static int async_pty(int master, int slave)
561{
562 int flags;
563
564 flags = fcntl(master, F_GETFL);
565 if(flags < 0)
566 return -errno;
567
568 if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
569 (fcntl(master, F_SETOWN, os_getpid()) < 0))
570 return -errno;
571
572 if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
573 return -errno;
574
575 return(0);
576}
577
578static void __init check_one_sigio(void (*proc)(int, int))
579{
580 struct sigaction old, new;
581 struct openpty_arg pty = { .master = -1, .slave = -1 };
582 int master, slave, err;
583
584 initial_thread_cb(openpty_cb, &pty);
585 if(pty.err){
586 printk("openpty failed, errno = %d\n", -pty.err);
587 return;
588 }
589
590 master = pty.master;
591 slave = pty.slave;
592
593 if((master == -1) || (slave == -1)){
594 printk("openpty failed to allocate a pty\n");
595 return;
596 }
597
598 /* Not now, but complain so we now where we failed. */
599 err = raw(master);
600 if (err < 0)
601 panic("check_sigio : __raw failed, errno = %d\n", -err);
602
603 err = async_pty(master, slave);
604 if(err < 0)
605 panic("tty_fds : sigio_async failed, err = %d\n", -err);
606
607 if(sigaction(SIGIO, NULL, &old) < 0)
608 panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
609 new = old;
610 new.sa_handler = handler;
611 if(sigaction(SIGIO, &new, NULL) < 0)
612 panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
613
614 got_sigio = 0;
615 (*proc)(master, slave);
616
617 close(master);
618 close(slave);
619
620 if(sigaction(SIGIO, &old, NULL) < 0)
621 panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
622}
623
624static void tty_output(int master, int slave)
625{
626 int n;
627 char buf[512];
628
629 printk("Checking that host ptys support output SIGIO...");
630
631 memset(buf, 0, sizeof(buf));
632
633 while(os_write_file(master, buf, sizeof(buf)) > 0) ;
634 if(errno != EAGAIN)
635 panic("check_sigio : write failed, errno = %d\n", errno);
636 while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
637
638 if(got_sigio){
639 printk("Yes\n");
640 pty_output_sigio = 1;
641 }
642 else if(n == -EAGAIN) printk("No, enabling workaround\n");
643 else panic("check_sigio : read failed, err = %d\n", n);
644}
645
646static void tty_close(int master, int slave)
647{
648 printk("Checking that host ptys support SIGIO on close...");
649
650 close(slave);
651 if(got_sigio){
652 printk("Yes\n");
653 pty_close_sigio = 1;
654 }
655 else printk("No, enabling workaround\n");
656}
657
658void __init check_sigio(void)
659{
660 if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
661 (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
662 printk("No pseudo-terminals available - skipping pty SIGIO "
663 "check\n");
664 return;
665 }
666 check_one_sigio(tty_output);
667 check_one_sigio(tty_close);
668}
669
670void os_check_bugs(void)
671{
672 check_ptrace();
673 check_sigio();
674}
675
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
index 0d3eae518352..f311609f93da 100644
--- a/arch/um/os-Linux/sys-i386/signal.c
+++ b/arch/um/os-Linux/sys-i386/signal.c
@@ -1,15 +1,13 @@
1/* 1/*
2 * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h> 6#include <signal.h>
7 7
8extern void (*handlers[])(int sig, struct sigcontext *sc); 8extern void handle_signal(int sig, struct sigcontext *sc);
9 9
10void hard_handler(int sig) 10void hard_handler(int sig)
11{ 11{
12 struct sigcontext *sc = (struct sigcontext *) (&sig + 1); 12 handle_signal(sig, (struct sigcontext *) (&sig + 1));
13
14 (*handlers[sig])(sig, sc);
15} 13}
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c
index 256532034c62..32ed41ec1a3d 100644
--- a/arch/um/os-Linux/sys-i386/tls.c
+++ b/arch/um/os-Linux/sys-i386/tls.c
@@ -5,7 +5,7 @@
5#include <unistd.h> 5#include <unistd.h>
6 6
7#include "sysdep/tls.h" 7#include "sysdep/tls.h"
8#include "user_util.h" 8#include "user.h"
9 9
10/* Checks whether host supports TLS, and sets *tls_min according to the value 10/* Checks whether host supports TLS, and sets *tls_min according to the value
11 * valid on the host. 11 * valid on the host.
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
index 3f369e5f976b..82a388822cd3 100644
--- a/arch/um/os-Linux/sys-x86_64/signal.c
+++ b/arch/um/os-Linux/sys-x86_64/signal.c
@@ -1,16 +1,16 @@
1/* 1/*
2 * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h> 6#include <signal.h>
7 7
8extern void (*handlers[])(int sig, struct sigcontext *sc); 8extern void handle_signal(int sig, struct sigcontext *sc);
9 9
10void hard_handler(int sig) 10void hard_handler(int sig)
11{ 11{
12 struct ucontext *uc; 12 struct ucontext *uc;
13 asm("movq %%rdx, %0" : "=r" (uc)); 13 asm("movq %%rdx, %0" : "=r" (uc));
14 14
15 (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext); 15 handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext);
16} 16}
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 2115b8beb541..5de169b168f6 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -10,7 +10,6 @@
10#include <sys/time.h> 10#include <sys/time.h>
11#include <signal.h> 11#include <signal.h>
12#include <errno.h> 12#include <errno.h>
13#include "user_util.h"
14#include "kern_util.h" 13#include "kern_util.h"
15#include "user.h" 14#include "user.h"
16#include "process.h" 15#include "process.h"
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index d221214d2ed5..295da657931a 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -6,7 +6,6 @@
6#include <stdlib.h> 6#include <stdlib.h>
7#include <signal.h> 7#include <signal.h>
8#include "kern_util.h" 8#include "kern_util.h"
9#include "user_util.h"
10#include "os.h" 9#include "os.h"
11#include "mode.h" 10#include "mode.h"
12#include "longjmp.h" 11#include "longjmp.h"
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index 3dc3a02d6263..bcf9359c4e9f 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -18,7 +18,6 @@
18#include <asm/ptrace.h> 18#include <asm/ptrace.h>
19#include <asm/unistd.h> 19#include <asm/unistd.h>
20#include <asm/page.h> 20#include <asm/page.h>
21#include "user_util.h"
22#include "kern_util.h" 21#include "kern_util.h"
23#include "user.h" 22#include "user.h"
24#include "signal_kern.h" 23#include "signal_kern.h"
@@ -32,6 +31,7 @@
32#include "choose-mode.h" 31#include "choose-mode.h"
33#include "mode.h" 32#include "mode.h"
34#include "tempfile.h" 33#include "tempfile.h"
34#include "kern_constants.h"
35 35
36int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, 36int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
37 int must_succeed) 37 int must_succeed)
@@ -143,7 +143,7 @@ int outer_tramp(void *arg)
143 int sig = sigkill; 143 int sig = sigkill;
144 144
145 t = arg; 145 t = arg;
146 t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2, 146 t->pid = clone(t->tramp, (void *) t->temp_stack + UM_KERN_PAGE_SIZE/2,
147 t->flags, t->tramp_data); 147 t->flags, t->tramp_data);
148 if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); 148 if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL);
149 kill(os_getpid(), sig); 149 kill(os_getpid(), sig);
diff --git a/arch/um/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c
index c6ba56c1560f..d11a55baa6bd 100644
--- a/arch/um/os-Linux/tty_log.c
+++ b/arch/um/os-Linux/tty_log.c
@@ -53,9 +53,9 @@ int open_tty_log(void *tty, void *current_tty)
53 .direction = 0, 53 .direction = 0,
54 .sec = tv.tv_sec, 54 .sec = tv.tv_sec,
55 .usec = tv.tv_usec } ); 55 .usec = tv.tv_usec } );
56 os_write_file(tty_log_fd, &data, sizeof(data)); 56 write(tty_log_fd, &data, sizeof(data));
57 os_write_file(tty_log_fd, &current_tty, data.len); 57 write(tty_log_fd, &current_tty, data.len);
58 return(tty_log_fd); 58 return tty_log_fd;
59 } 59 }
60 60
61 sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, 61 sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
@@ -67,7 +67,7 @@ int open_tty_log(void *tty, void *current_tty)
67 printk("open_tty_log : couldn't open '%s', errno = %d\n", 67 printk("open_tty_log : couldn't open '%s', errno = %d\n",
68 buf, -fd); 68 buf, -fd);
69 } 69 }
70 return(fd); 70 return fd;
71} 71}
72 72
73void close_tty_log(int fd, void *tty) 73void close_tty_log(int fd, void *tty)
@@ -83,7 +83,7 @@ void close_tty_log(int fd, void *tty)
83 .direction = 0, 83 .direction = 0,
84 .sec = tv.tv_sec, 84 .sec = tv.tv_sec,
85 .usec = tv.tv_usec } ); 85 .usec = tv.tv_usec } );
86 os_write_file(tty_log_fd, &data, sizeof(data)); 86 write(tty_log_fd, &data, sizeof(data));
87 return; 87 return;
88 } 88 }
89 os_close_file(fd); 89 os_close_file(fd);
@@ -98,21 +98,21 @@ static int log_chunk(int fd, const char *buf, int len)
98 try = (len > sizeof(chunk)) ? sizeof(chunk) : len; 98 try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
99 missed = copy_from_user_proc(chunk, (char *) buf, try); 99 missed = copy_from_user_proc(chunk, (char *) buf, try);
100 try -= missed; 100 try -= missed;
101 n = os_write_file(fd, chunk, try); 101 n = write(fd, chunk, try);
102 if(n != try) { 102 if(n != try) {
103 if(n < 0) 103 if(n < 0)
104 return(n); 104 return -errno;
105 return(-EIO); 105 return -EIO;
106 } 106 }
107 if(missed != 0) 107 if(missed != 0)
108 return(-EFAULT); 108 return -EFAULT;
109 109
110 len -= try; 110 len -= try;
111 total += try; 111 total += try;
112 buf += try; 112 buf += try;
113 } 113 }
114 114
115 return(total); 115 return total;
116} 116}
117 117
118int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read) 118int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
@@ -130,10 +130,10 @@ int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
130 .direction = direction, 130 .direction = direction,
131 .sec = tv.tv_sec, 131 .sec = tv.tv_sec,
132 .usec = tv.tv_usec } ); 132 .usec = tv.tv_usec } );
133 os_write_file(tty_log_fd, &data, sizeof(data)); 133 write(tty_log_fd, &data, sizeof(data));
134 } 134 }
135 135
136 return(log_chunk(fd, buf, len)); 136 return log_chunk(fd, buf, len);
137} 137}
138 138
139void log_exec(char **argv, void *tty) 139void log_exec(char **argv, void *tty)
@@ -161,7 +161,7 @@ void log_exec(char **argv, void *tty)
161 .direction = 0, 161 .direction = 0,
162 .sec = tv.tv_sec, 162 .sec = tv.tv_sec,
163 .usec = tv.tv_usec } ); 163 .usec = tv.tv_usec } );
164 os_write_file(tty_log_fd, &data, sizeof(data)); 164 write(tty_log_fd, &data, sizeof(data));
165 165
166 for(ptr = argv; ; ptr++){ 166 for(ptr = argv; ; ptr++){
167 if(copy_from_user_proc(&arg, ptr, sizeof(arg))) 167 if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
@@ -179,7 +179,7 @@ extern void register_tty_logger(int (*opener)(void *, void *),
179static int register_logger(void) 179static int register_logger(void)
180{ 180{
181 register_tty_logger(open_tty_log, write_tty_log, close_tty_log); 181 register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
182 return(0); 182 return 0;
183} 183}
184 184
185__uml_initcall(register_logger); 185__uml_initcall(register_logger);
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 56b8a50e8bc2..7cbcf484e13d 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -21,7 +21,6 @@
21#include <sched.h> 21#include <sched.h>
22#include <termios.h> 22#include <termios.h>
23#include <string.h> 23#include <string.h>
24#include "user_util.h"
25#include "kern_util.h" 24#include "kern_util.h"
26#include "user.h" 25#include "user.h"
27#include "mem_user.h" 26#include "mem_user.h"
@@ -30,28 +29,12 @@
30#include "uml-config.h" 29#include "uml-config.h"
31#include "os.h" 30#include "os.h"
32#include "longjmp.h" 31#include "longjmp.h"
32#include "kern_constants.h"
33 33
34void stack_protections(unsigned long address) 34void stack_protections(unsigned long address)
35{ 35{
36 int prot = PROT_READ | PROT_WRITE | PROT_EXEC; 36 if(mprotect((void *) address, UM_THREAD_SIZE,
37 37 PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
38 if(mprotect((void *) address, page_size(), prot) < 0)
39 panic("protecting stack failed, errno = %d", errno);
40}
41
42void task_protections(unsigned long address)
43{
44 unsigned long guard = address + page_size();
45 unsigned long stack = guard + page_size();
46 int prot = 0, pages;
47
48#ifdef notdef
49 if(mprotect((void *) stack, page_size(), prot) < 0)
50 panic("protecting guard page failed, errno = %d", errno);
51#endif
52 pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
53 prot = PROT_READ | PROT_WRITE | PROT_EXEC;
54 if(mprotect((void *) stack, pages * page_size(), prot) < 0)
55 panic("protecting stack failed, errno = %d", errno); 38 panic("protecting stack failed, errno = %d", errno);
56} 39}
57 40
@@ -72,7 +55,7 @@ int raw(int fd)
72 55
73 /* XXX tcsetattr could have applied only some changes 56 /* XXX tcsetattr could have applied only some changes
74 * (and cfmakeraw() is a set of changes) */ 57 * (and cfmakeraw() is a set of changes) */
75 return(0); 58 return 0;
76} 59}
77 60
78void setup_machinename(char *machine_out) 61void setup_machinename(char *machine_out)
@@ -96,15 +79,13 @@ void setup_machinename(char *machine_out)
96 strcpy(machine_out, host.machine); 79 strcpy(machine_out, host.machine);
97} 80}
98 81
99char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1]; 82void setup_hostinfo(char *buf, int len)
100
101void setup_hostinfo(void)
102{ 83{
103 struct utsname host; 84 struct utsname host;
104 85
105 uname(&host); 86 uname(&host);
106 sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename, 87 snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename,
107 host.release, host.version, host.machine); 88 host.release, host.version, host.machine);
108} 89}
109 90
110int setjmp_wrapper(void (*proc)(void *, void *), ...) 91int setjmp_wrapper(void (*proc)(void *, void *), ...)
@@ -121,3 +102,9 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
121 va_end(args); 102 va_end(args);
122 return n; 103 return n;
123} 104}
105
106void os_dump_core(void)
107{
108 signal(SIGSEGV, SIG_DFL);
109 abort();
110}
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index f1bcd399ac90..0393e44813e7 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -13,7 +13,6 @@
13#include "sysdep/ptrace.h" 13#include "sysdep/ptrace.h"
14#include "task.h" 14#include "task.h"
15#include "os.h" 15#include "os.h"
16#include "user_util.h"
17 16
18#define MAXTOKEN 64 17#define MAXTOKEN 64
19 18
@@ -32,21 +31,21 @@ static char token(int fd, char *buf, int len, char stop)
32 n = os_read_file(fd, ptr, sizeof(*ptr)); 31 n = os_read_file(fd, ptr, sizeof(*ptr));
33 c = *ptr++; 32 c = *ptr++;
34 if(n != sizeof(*ptr)){ 33 if(n != sizeof(*ptr)){
35 if(n == 0) return(0); 34 if(n == 0)
35 return 0;
36 printk("Reading /proc/cpuinfo failed, err = %d\n", -n); 36 printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
37 if(n < 0) 37 if(n < 0)
38 return(n); 38 return n;
39 else 39 else return -EIO;
40 return(-EIO);
41 } 40 }
42 } while((c != '\n') && (c != stop) && (ptr < end)); 41 } while((c != '\n') && (c != stop) && (ptr < end));
43 42
44 if(ptr == end){ 43 if(ptr == end){
45 printk("Failed to find '%c' in /proc/cpuinfo\n", stop); 44 printk("Failed to find '%c' in /proc/cpuinfo\n", stop);
46 return(-1); 45 return -1;
47 } 46 }
48 *(ptr - 1) = '\0'; 47 *(ptr - 1) = '\0';
49 return(c); 48 return c;
50} 49}
51 50
52static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) 51static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
@@ -58,48 +57,25 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
58 while(1){ 57 while(1){
59 c = token(fd, scratch, len - 1, ':'); 58 c = token(fd, scratch, len - 1, ':');
60 if(c <= 0) 59 if(c <= 0)
61 return(0); 60 return 0;
62 else if(c != ':'){ 61 else if(c != ':'){
63 printk("Failed to find ':' in /proc/cpuinfo\n"); 62 printk("Failed to find ':' in /proc/cpuinfo\n");
64 return(0); 63 return 0;
65 } 64 }
66 65
67 if(!strncmp(scratch, key, strlen(key))) 66 if(!strncmp(scratch, key, strlen(key)))
68 return(1); 67 return 1;
69 68
70 do { 69 do {
71 n = os_read_file(fd, &c, sizeof(c)); 70 n = os_read_file(fd, &c, sizeof(c));
72 if(n != sizeof(c)){ 71 if(n != sizeof(c)){
73 printk("Failed to find newline in " 72 printk("Failed to find newline in "
74 "/proc/cpuinfo, err = %d\n", -n); 73 "/proc/cpuinfo, err = %d\n", -n);
75 return(0); 74 return 0;
76 } 75 }
77 } while(c != '\n'); 76 } while(c != '\n');
78 } 77 }
79 return(0); 78 return 0;
80}
81
82int cpu_feature(char *what, char *buf, int len)
83{
84 int fd, ret = 0;
85
86 fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
87 if(fd < 0){
88 printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
89 return(0);
90 }
91
92 if(!find_cpuinfo_line(fd, what, buf, len)){
93 printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
94 goto out_close;
95 }
96
97 token(fd, buf, len, '\n');
98 ret = 1;
99
100 out_close:
101 os_close_file(fd);
102 return(ret);
103} 79}
104 80
105static int check_cpu_flag(char *feature, int *have_it) 81static int check_cpu_flag(char *feature, int *have_it)
@@ -119,7 +95,8 @@ static int check_cpu_flag(char *feature, int *have_it)
119 goto out; 95 goto out;
120 96
121 c = token(fd, buf, len - 1, ' '); 97 c = token(fd, buf, len - 1, ' ');
122 if(c < 0) goto out; 98 if(c < 0)
99 goto out;
123 else if(c != ' '){ 100 else if(c != ' '){
124 printk("Failed to find ' ' in /proc/cpuinfo\n"); 101 printk("Failed to find ' ' in /proc/cpuinfo\n");
125 goto out; 102 goto out;
@@ -127,7 +104,8 @@ static int check_cpu_flag(char *feature, int *have_it)
127 104
128 while(1){ 105 while(1){
129 c = token(fd, buf, len - 1, ' '); 106 c = token(fd, buf, len - 1, ' ');
130 if(c < 0) goto out; 107 if(c < 0)
108 goto out;
131 else if(c == '\n') break; 109 else if(c == '\n') break;
132 110
133 if(!strcmp(buf, feature)){ 111 if(!strcmp(buf, feature)){
@@ -136,8 +114,10 @@ static int check_cpu_flag(char *feature, int *have_it)
136 } 114 }
137 } 115 }
138 out: 116 out:
139 if(*have_it == 0) printk("No\n"); 117 if(*have_it == 0)
140 else if(*have_it == 1) printk("Yes\n"); 118 printk("No\n");
119 else if(*have_it == 1)
120 printk("Yes\n");
141 os_close_file(fd); 121 os_close_file(fd);
142 return 1; 122 return 1;
143} 123}
@@ -189,12 +169,13 @@ int arch_handle_signal(int sig, union uml_pt_regs *regs)
189 /* This is testing for a cmov (0x0f 0x4x) instruction causing a 169 /* This is testing for a cmov (0x0f 0x4x) instruction causing a
190 * SIGILL in init. 170 * SIGILL in init.
191 */ 171 */
192 if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0); 172 if((sig != SIGILL) || (TASK_PID(get_current()) != 1))
173 return 0;
193 174
194 if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) 175 if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
195 panic("SIGILL in init, could not read instructions!\n"); 176 panic("SIGILL in init, could not read instructions!\n");
196 if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) 177 if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
197 return(0); 178 return 0;
198 179
199 if(host_has_cmov == 0) 180 if(host_has_cmov == 0)
200 panic("SIGILL caused by cmov, which this processor doesn't " 181 panic("SIGILL caused by cmov, which this processor doesn't "
@@ -208,16 +189,5 @@ int arch_handle_signal(int sig, union uml_pt_regs *regs)
208 "implements it, boot a filesystem compiled for older " 189 "implements it, boot a filesystem compiled for older "
209 "processors"); 190 "processors");
210 else panic("Bad value for host_has_cmov (%d)", host_has_cmov); 191 else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
211 return(0); 192 return 0;
212} 193}
213
214/*
215 * Overrides for Emacs so that we follow Linus's tabbing style.
216 * Emacs will notice this stuff at the end of the file and automatically
217 * adjust the settings for this buffer only. This must remain at the end
218 * of the file.
219 * ---------------------------------------------------------------------------
220 * Local variables:
221 * c-file-style: "linux"
222 * End:
223 */
diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c
index d0bbcdfdb53f..745b4fd49e9f 100644
--- a/arch/um/sys-i386/fault.c
+++ b/arch/um/sys-i386/fault.c
@@ -3,9 +3,7 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h>
7#include "sysdep/ptrace.h" 6#include "sysdep/ptrace.h"
8#include "sysdep/sigcontext.h"
9 7
10/* These two are from asm-um/uaccess.h and linux/module.h, check them. */ 8/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
11struct exception_table_entry 9struct exception_table_entry
@@ -17,26 +15,14 @@ struct exception_table_entry
17const struct exception_table_entry *search_exception_tables(unsigned long add); 15const struct exception_table_entry *search_exception_tables(unsigned long add);
18 16
19/* Compare this to arch/i386/mm/extable.c:fixup_exception() */ 17/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
20int arch_fixup(unsigned long address, void *sc_ptr) 18int arch_fixup(unsigned long address, union uml_pt_regs *regs)
21{ 19{
22 struct sigcontext *sc = sc_ptr;
23 const struct exception_table_entry *fixup; 20 const struct exception_table_entry *fixup;
24 21
25 fixup = search_exception_tables(address); 22 fixup = search_exception_tables(address);
26 if(fixup != 0){ 23 if(fixup != 0){
27 sc->eip = fixup->fixup; 24 UPT_IP(regs) = fixup->fixup;
28 return(1); 25 return(1);
29 } 26 }
30 return(0); 27 return(0);
31} 28}
32
33/*
34 * Overrides for Emacs so that we follow Linus's tabbing style.
35 * Emacs will notice this stuff at the end of the file and automatically
36 * adjust the settings for this buffer only. This must remain at the end
37 * of the file.
38 * ---------------------------------------------------------------------------
39 * Local variables:
40 * c-file-style: "linux"
41 * End:
42 */
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 01212c88fcc4..40ff0c831bd0 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -15,7 +15,6 @@
15#include "user.h" 15#include "user.h"
16#include "os.h" 16#include "os.h"
17#include "uml-config.h" 17#include "uml-config.h"
18#include "user_util.h"
19 18
20int ptrace_getregs(long pid, unsigned long *regs_out) 19int ptrace_getregs(long pid, unsigned long *regs_out)
21{ 20{
@@ -45,7 +44,8 @@ int ptrace_setfpregs(long pid, unsigned long *regs)
45 return 0; 44 return 0;
46} 45}
47 46
48/* All the below stuff is of interest for TT mode only */ 47#ifdef UML_CONFIG_MODE_TT
48
49static void write_debugregs(int pid, unsigned long *regs) 49static void write_debugregs(int pid, unsigned long *regs)
50{ 50{
51 struct user *dummy; 51 struct user *dummy;
@@ -128,13 +128,4 @@ void update_debugregs(int seq)
128} 128}
129#endif 129#endif
130 130
131/* 131#endif
132 * Overrides for Emacs so that we follow Linus's tabbing style.
133 * Emacs will notice this stuff at the end of the file and automatically
134 * adjust the settings for this buffer only. This must remain at the end
135 * of the file.
136 * ---------------------------------------------------------------------------
137 * Local variables:
138 * c-file-style: "linux"
139 * End:
140 */
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 3f6acd667717..1cbf95f6858a 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -18,6 +18,28 @@
18 18
19#include "skas.h" 19#include "skas.h"
20 20
21void copy_sc(union uml_pt_regs *regs, void *from)
22{
23 struct sigcontext *sc = from;
24
25 REGS_GS(regs->skas.regs) = sc->gs;
26 REGS_FS(regs->skas.regs) = sc->fs;
27 REGS_ES(regs->skas.regs) = sc->es;
28 REGS_DS(regs->skas.regs) = sc->ds;
29 REGS_EDI(regs->skas.regs) = sc->edi;
30 REGS_ESI(regs->skas.regs) = sc->esi;
31 REGS_EBP(regs->skas.regs) = sc->ebp;
32 REGS_SP(regs->skas.regs) = sc->esp;
33 REGS_EBX(regs->skas.regs) = sc->ebx;
34 REGS_EDX(regs->skas.regs) = sc->edx;
35 REGS_ECX(regs->skas.regs) = sc->ecx;
36 REGS_EAX(regs->skas.regs) = sc->eax;
37 REGS_IP(regs->skas.regs) = sc->eip;
38 REGS_CS(regs->skas.regs) = sc->cs;
39 REGS_EFLAGS(regs->skas.regs) = sc->eflags;
40 REGS_SS(regs->skas.regs) = sc->ss;
41}
42
21static int copy_sc_from_user_skas(struct pt_regs *regs, 43static int copy_sc_from_user_skas(struct pt_regs *regs,
22 struct sigcontext __user *from) 44 struct sigcontext __user *from)
23{ 45{
@@ -28,33 +50,18 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
28 err = copy_from_user(&sc, from, sizeof(sc)); 50 err = copy_from_user(&sc, from, sizeof(sc));
29 err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs)); 51 err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs));
30 if(err) 52 if(err)
31 return(err); 53 return err;
32 54
33 REGS_GS(regs->regs.skas.regs) = sc.gs; 55 copy_sc(&regs->regs, &sc);
34 REGS_FS(regs->regs.skas.regs) = sc.fs;
35 REGS_ES(regs->regs.skas.regs) = sc.es;
36 REGS_DS(regs->regs.skas.regs) = sc.ds;
37 REGS_EDI(regs->regs.skas.regs) = sc.edi;
38 REGS_ESI(regs->regs.skas.regs) = sc.esi;
39 REGS_EBP(regs->regs.skas.regs) = sc.ebp;
40 REGS_SP(regs->regs.skas.regs) = sc.esp;
41 REGS_EBX(regs->regs.skas.regs) = sc.ebx;
42 REGS_EDX(regs->regs.skas.regs) = sc.edx;
43 REGS_ECX(regs->regs.skas.regs) = sc.ecx;
44 REGS_EAX(regs->regs.skas.regs) = sc.eax;
45 REGS_IP(regs->regs.skas.regs) = sc.eip;
46 REGS_CS(regs->regs.skas.regs) = sc.cs;
47 REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags;
48 REGS_SS(regs->regs.skas.regs) = sc.ss;
49 56
50 err = restore_fp_registers(userspace_pid[0], fpregs); 57 err = restore_fp_registers(userspace_pid[0], fpregs);
51 if(err < 0){ 58 if(err < 0) {
52 printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, " 59 printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
53 "errno = %d\n", err); 60 "errno = %d\n", -err);
54 return(1); 61 return err;
55 } 62 }
56 63
57 return(0); 64 return 0;
58} 65}
59 66
60int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, 67int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
@@ -90,16 +97,16 @@ int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *t
90 if(err < 0){ 97 if(err < 0){
91 printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, " 98 printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
92 "errno = %d\n", err); 99 "errno = %d\n", err);
93 return(1); 100 return 1;
94 } 101 }
95 to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); 102 to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
96 sc.fpstate = to_fp; 103 sc.fpstate = to_fp;
97 104
98 if(err) 105 if(err)
99 return(err); 106 return err;
100 107
101 return(copy_to_user(to, &sc, sizeof(sc)) || 108 return copy_to_user(to, &sc, sizeof(sc)) ||
102 copy_to_user(to_fp, fpregs, sizeof(fpregs))); 109 copy_to_user(to_fp, fpregs, sizeof(fpregs));
103} 110}
104#endif 111#endif
105 112
@@ -129,7 +136,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
129 to->fpstate = to_fp; 136 to->fpstate = to_fp;
130 if(to_fp != NULL) 137 if(to_fp != NULL)
131 err |= copy_from_user(to_fp, from_fp, fpsize); 138 err |= copy_from_user(to_fp, from_fp, fpsize);
132 return(err); 139 return err;
133} 140}
134 141
135int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, 142int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
@@ -164,15 +171,15 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
164 ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, 171 ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from,
165 sizeof(struct _fpstate)), 172 sizeof(struct _fpstate)),
166 copy_sc_from_user_skas(to, from)); 173 copy_sc_from_user_skas(to, from));
167 return(ret); 174 return ret;
168} 175}
169 176
170static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, 177static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
171 struct pt_regs *from, unsigned long sp) 178 struct pt_regs *from, unsigned long sp)
172{ 179{
173 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 180 return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
174 sizeof(*fp), sp), 181 sizeof(*fp), sp),
175 copy_sc_to_user_skas(to, fp, from, sp))); 182 copy_sc_to_user_skas(to, fp, from, sp));
176} 183}
177 184
178static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, 185static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp,
@@ -185,7 +192,7 @@ static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __u
185 err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); 192 err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
186 err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp); 193 err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
187 err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); 194 err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
188 return(err); 195 return err;
189} 196}
190 197
191struct sigframe 198struct sigframe
@@ -359,7 +366,7 @@ long sys_sigreturn(struct pt_regs regs)
359 366
360 /* Avoid ERESTART handling */ 367 /* Avoid ERESTART handling */
361 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1; 368 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
362 return(PT_REGS_SYSCALL_RET(&current->thread.regs)); 369 return PT_REGS_SYSCALL_RET(&current->thread.regs);
363 370
364 segfault: 371 segfault:
365 force_sig(SIGSEGV, current); 372 force_sig(SIGSEGV, current);
@@ -389,20 +396,9 @@ long sys_rt_sigreturn(struct pt_regs regs)
389 396
390 /* Avoid ERESTART handling */ 397 /* Avoid ERESTART handling */
391 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1; 398 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
392 return(PT_REGS_SYSCALL_RET(&current->thread.regs)); 399 return PT_REGS_SYSCALL_RET(&current->thread.regs);
393 400
394 segfault: 401 segfault:
395 force_sig(SIGSEGV, current); 402 force_sig(SIGSEGV, current);
396 return 0; 403 return 0;
397} 404}
398
399/*
400 * Overrides for Emacs so that we follow Linus's tabbing style.
401 * Emacs will notice this stuff at the end of the file and automatically
402 * adjust the settings for this buffer only. This must remain at the end
403 * of the file.
404 * ---------------------------------------------------------------------------
405 * Local variables:
406 * c-file-style: "linux"
407 * End:
408 */
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
index 643dab585727..fea8e5e15cc4 100644
--- a/arch/um/sys-i386/tls.c
+++ b/arch/um/sys-i386/tls.c
@@ -23,9 +23,13 @@
23#include "skas.h" 23#include "skas.h"
24#endif 24#endif
25 25
26/* If needed we can detect when it's uninitialized. */ 26/*
27 * If needed we can detect when it's uninitialized.
28 *
29 * These are initialized in an initcall and unchanged thereafter.
30 */
27static int host_supports_tls = -1; 31static int host_supports_tls = -1;
28int host_gdt_entry_tls_min = -1; 32int host_gdt_entry_tls_min;
29 33
30#ifdef CONFIG_MODE_SKAS 34#ifdef CONFIG_MODE_SKAS
31int do_set_thread_area_skas(struct user_desc *info) 35int do_set_thread_area_skas(struct user_desc *info)
@@ -361,7 +365,8 @@ out:
361 365
362/* XXX: This part is probably common to i386 and x86-64. Don't create a common 366/* XXX: This part is probably common to i386 and x86-64. Don't create a common
363 * file for now, do that when implementing x86-64 support.*/ 367 * file for now, do that when implementing x86-64 support.*/
364static int __init __setup_host_supports_tls(void) { 368static int __init __setup_host_supports_tls(void)
369{
365 check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); 370 check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
366 if (host_supports_tls) { 371 if (host_supports_tls) {
367 printk(KERN_INFO "Host TLS support detected\n"); 372 printk(KERN_INFO "Host TLS support detected\n");
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
index 447306b20aea..29118cf5ff25 100644
--- a/arch/um/sys-i386/user-offsets.c
+++ b/arch/um/sys-i386/user-offsets.c
@@ -1,9 +1,10 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <stddef.h>
2#include <signal.h> 3#include <signal.h>
4#include <sys/poll.h>
5#include <sys/mman.h>
3#include <asm/ptrace.h> 6#include <asm/ptrace.h>
4#include <asm/user.h> 7#include <asm/user.h>
5#include <stddef.h>
6#include <sys/poll.h>
7 8
8#define DEFINE(sym, val) \ 9#define DEFINE(sym, val) \
9 asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 10 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -47,7 +48,6 @@ void foo(void)
47 OFFSET(HOST_SC_FP_ST, _fpstate, _st); 48 OFFSET(HOST_SC_FP_ST, _fpstate, _st);
48 OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); 49 OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env);
49 50
50 DEFINE(HOST_FRAME_SIZE, FRAME_SIZE);
51 DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct)); 51 DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct));
52 DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct)); 52 DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct));
53 53
@@ -73,4 +73,8 @@ void foo(void)
73 DEFINE(UM_POLLIN, POLLIN); 73 DEFINE(UM_POLLIN, POLLIN);
74 DEFINE(UM_POLLPRI, POLLPRI); 74 DEFINE(UM_POLLPRI, POLLPRI);
75 DEFINE(UM_POLLOUT, POLLOUT); 75 DEFINE(UM_POLLOUT, POLLOUT);
76
77 DEFINE(UM_PROT_READ, PROT_READ);
78 DEFINE(UM_PROT_WRITE, PROT_WRITE);
79 DEFINE(UM_PROT_EXEC, PROT_EXEC);
76} 80}
diff --git a/arch/um/sys-ppc/sigcontext.c b/arch/um/sys-ppc/sigcontext.c
index 5d430fc994af..4bdc15c89edd 100644
--- a/arch/um/sys-ppc/sigcontext.c
+++ b/arch/um/sys-ppc/sigcontext.c
@@ -1,7 +1,6 @@
1#include "asm/ptrace.h" 1#include "asm/ptrace.h"
2#include "asm/sigcontext.h" 2#include "asm/sigcontext.h"
3#include "sysdep/ptrace.h" 3#include "sysdep/ptrace.h"
4#include "user_util.h"
5 4
6/* 5/*
7 * Overrides for Emacs so that we follow Linus's tabbing style. 6 * Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
index fdce7ea98ca7..095478890371 100644
--- a/arch/um/sys-x86_64/bugs.c
+++ b/arch/um/sys-x86_64/bugs.c
@@ -4,12 +4,7 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include "linux/sched.h"
8#include "linux/errno.h"
9#include "asm/system.h"
10#include "asm/pda.h"
11#include "sysdep/ptrace.h" 7#include "sysdep/ptrace.h"
12#include "os.h"
13 8
14void arch_init_thread(void) 9void arch_init_thread(void)
15{ 10{
@@ -21,102 +16,5 @@ void arch_check_bugs(void)
21 16
22int arch_handle_signal(int sig, union uml_pt_regs *regs) 17int arch_handle_signal(int sig, union uml_pt_regs *regs)
23{ 18{
24 return(0); 19 return 0;
25} 20}
26
27#define MAXTOKEN 64
28
29/* Set during early boot */
30int host_has_cmov = 1;
31int host_has_xmm = 0;
32
33static char token(int fd, char *buf, int len, char stop)
34{
35 int n;
36 char *ptr, *end, c;
37
38 ptr = buf;
39 end = &buf[len];
40 do {
41 n = os_read_file(fd, ptr, sizeof(*ptr));
42 c = *ptr++;
43 if(n != sizeof(*ptr)){
44 if(n == 0) return(0);
45 printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
46 if(n < 0)
47 return(n);
48 else
49 return(-EIO);
50 }
51 } while((c != '\n') && (c != stop) && (ptr < end));
52
53 if(ptr == end){
54 printk("Failed to find '%c' in /proc/cpuinfo\n", stop);
55 return(-1);
56 }
57 *(ptr - 1) = '\0';
58 return(c);
59}
60
61static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
62{
63 int n;
64 char c;
65
66 scratch[len - 1] = '\0';
67 while(1){
68 c = token(fd, scratch, len - 1, ':');
69 if(c <= 0)
70 return(0);
71 else if(c != ':'){
72 printk("Failed to find ':' in /proc/cpuinfo\n");
73 return(0);
74 }
75
76 if(!strncmp(scratch, key, strlen(key)))
77 return(1);
78
79 do {
80 n = os_read_file(fd, &c, sizeof(c));
81 if(n != sizeof(c)){
82 printk("Failed to find newline in "
83 "/proc/cpuinfo, err = %d\n", -n);
84 return(0);
85 }
86 } while(c != '\n');
87 }
88 return(0);
89}
90
91int cpu_feature(char *what, char *buf, int len)
92{
93 int fd, ret = 0;
94
95 fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
96 if(fd < 0){
97 printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
98 return(0);
99 }
100
101 if(!find_cpuinfo_line(fd, what, buf, len)){
102 printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
103 goto out_close;
104 }
105
106 token(fd, buf, len, '\n');
107 ret = 1;
108
109 out_close:
110 os_close_file(fd);
111 return(ret);
112}
113
114/* Overrides for Emacs so that we follow Linus's tabbing style.
115 * Emacs will notice this stuff at the end of the file and automatically
116 * adjust the settings for this buffer only. This must remain at the end
117 * of the file.
118 * ---------------------------------------------------------------------------
119 * Local variables:
120 * c-file-style: "linux"
121 * End:
122 */
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c
index cee1513c5c31..4636b1465b6c 100644
--- a/arch/um/sys-x86_64/fault.c
+++ b/arch/um/sys-x86_64/fault.c
@@ -4,20 +4,24 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include "user.h" 7#include "sysdep/ptrace.h"
8 8
9int arch_fixup(unsigned long address, void *sc_ptr) 9/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
10struct exception_table_entry
10{ 11{
11 /* XXX search_exception_tables() */ 12 unsigned long insn;
13 unsigned long fixup;
14};
15
16const struct exception_table_entry *search_exception_tables(unsigned long add);
17int arch_fixup(unsigned long address, union uml_pt_regs *regs)
18{
19 const struct exception_table_entry *fixup;
20
21 fixup = search_exception_tables(address);
22 if(fixup != 0){
23 UPT_IP(regs) = fixup->fixup;
24 return(1);
25 }
12 return(0); 26 return(0);
13} 27}
14
15/* Overrides for Emacs so that we follow Linus's tabbing style.
16 * Emacs will notice this stuff at the end of the file and automatically
17 * adjust the settings for this buffer only. This must remain at the end
18 * of the file.
19 * ---------------------------------------------------------------------------
20 * Local variables:
21 * c-file-style: "linux"
22 * End:
23 */
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index af2f017617b4..fe8ec04d35bb 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -20,6 +20,36 @@
20 20
21#include "skas.h" 21#include "skas.h"
22 22
23void copy_sc(union uml_pt_regs *regs, void *from)
24{
25 struct sigcontext *sc = from;
26
27#define GETREG(regs, regno, sc, regname) \
28 (regs)->skas.regs[(regno) / sizeof(unsigned long)] = (sc)->regname
29
30 GETREG(regs, R8, sc, r8);
31 GETREG(regs, R9, sc, r9);
32 GETREG(regs, R10, sc, r10);
33 GETREG(regs, R11, sc, r11);
34 GETREG(regs, R12, sc, r12);
35 GETREG(regs, R13, sc, r13);
36 GETREG(regs, R14, sc, r14);
37 GETREG(regs, R15, sc, r15);
38 GETREG(regs, RDI, sc, rdi);
39 GETREG(regs, RSI, sc, rsi);
40 GETREG(regs, RBP, sc, rbp);
41 GETREG(regs, RBX, sc, rbx);
42 GETREG(regs, RDX, sc, rdx);
43 GETREG(regs, RAX, sc, rax);
44 GETREG(regs, RCX, sc, rcx);
45 GETREG(regs, RSP, sc, rsp);
46 GETREG(regs, RIP, sc, rip);
47 GETREG(regs, EFLAGS, sc, eflags);
48 GETREG(regs, CS, sc, cs);
49
50#undef GETREG
51}
52
23static int copy_sc_from_user_skas(struct pt_regs *regs, 53static int copy_sc_from_user_skas(struct pt_regs *regs,
24 struct sigcontext __user *from) 54 struct sigcontext __user *from)
25{ 55{
@@ -51,7 +81,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
51 81
52#undef GETREG 82#undef GETREG
53 83
54 return(err); 84 return err;
55} 85}
56 86
57int copy_sc_to_user_skas(struct sigcontext __user *to, 87int copy_sc_to_user_skas(struct sigcontext __user *to,
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 899cebb57c3f..0d5fd764c21f 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -2,6 +2,7 @@
2#include <stddef.h> 2#include <stddef.h>
3#include <signal.h> 3#include <signal.h>
4#include <sys/poll.h> 4#include <sys/poll.h>
5#include <sys/mman.h>
5#define __FRAME_OFFSETS 6#define __FRAME_OFFSETS
6#include <asm/ptrace.h> 7#include <asm/ptrace.h>
7#include <asm/types.h> 8#include <asm/types.h>
@@ -57,7 +58,6 @@ void foo(void)
57 OFFSET(HOST_SC_SS, sigcontext, ss); 58 OFFSET(HOST_SC_SS, sigcontext, ss);
58#endif 59#endif
59 60
60 DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE);
61 DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); 61 DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
62 DEFINE(HOST_XFP_SIZE, 0); 62 DEFINE(HOST_XFP_SIZE, 0);
63 DEFINE_LONGS(HOST_RBX, RBX); 63 DEFINE_LONGS(HOST_RBX, RBX);
@@ -94,4 +94,8 @@ void foo(void)
94 DEFINE(UM_POLLIN, POLLIN); 94 DEFINE(UM_POLLIN, POLLIN);
95 DEFINE(UM_POLLPRI, POLLPRI); 95 DEFINE(UM_POLLPRI, POLLPRI);
96 DEFINE(UM_POLLOUT, POLLOUT); 96 DEFINE(UM_POLLOUT, POLLOUT);
97
98 DEFINE(UM_PROT_READ, PROT_READ);
99 DEFINE(UM_PROT_WRITE, PROT_WRITE);
100 DEFINE(UM_PROT_EXEC, PROT_EXEC);
97} 101}