aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/defconfig1
-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.c162
-rw-r--r--arch/um/drivers/net_user.c4
-rw-r--r--arch/um/drivers/pcap_user.c38
-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.h2
-rw-r--r--arch/um/include/kern_util.h13
-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.h17
-rw-r--r--arch/um/include/skas/mode_kern_skas.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/exec.c2
-rw-r--r--arch/um/kernel/init_task.c1
-rw-r--r--arch/um/kernel/initrd.c33
-rw-r--r--arch/um/kernel/irq.c16
-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.c2
-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.c15
-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.c1
-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.c4
-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.c84
-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.c45
-rw-r--r--arch/um/os-Linux/sigio.c164
-rw-r--r--arch/um/os-Linux/signal.c1
-rw-r--r--arch/um/os-Linux/skas/mem.c75
-rw-r--r--arch/um/os-Linux/skas/process.c190
-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/tls.c2
-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.c26
-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
106 files changed, 1498 insertions, 1819 deletions
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 780cc0a4a128..f938fa822146 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
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..baac4ad5e68e 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,32 @@ 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 address to a "
320 "device\n");
321 printk(KERN_WARNING "You should better enable the 2nd rightmost bit "
322 "in the first byte of the MAC, i.e. "
323 "%02x:%02x:%02x:%02x:%02x:%02x\n",
324 addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], addr[5]);
325 }
312 return; 326 return;
313 327
314random: 328random:
329 printk(KERN_INFO
330 "Choosing a random ethernet address for device %s\n", name);
315 random_ether_addr(addr); 331 random_ether_addr(addr);
316} 332}
317 333
@@ -325,31 +341,53 @@ static struct platform_driver uml_net_driver = {
325}; 341};
326static int driver_registered; 342static int driver_registered;
327 343
328static int eth_configure(int n, void *init, char *mac, 344static void net_device_release(struct device *dev)
329 struct transport *transport) 345{
346 struct uml_net *device = dev->driver_data;
347 struct net_device *netdev = device->dev;
348 struct uml_net_private *lp = netdev->priv;
349
350 if(lp->remove != NULL)
351 (*lp->remove)(&lp->user);
352 list_del(&device->list);
353 kfree(device);
354 free_netdev(netdev);
355}
356
357static void eth_configure(int n, void *init, char *mac,
358 struct transport *transport)
330{ 359{
331 struct uml_net *device; 360 struct uml_net *device;
332 struct net_device *dev; 361 struct net_device *dev;
333 struct uml_net_private *lp; 362 struct uml_net_private *lp;
334 int save, err, size; 363 int err, size;
335 364
336 size = transport->private_size + sizeof(struct uml_net_private) + 365 size = transport->private_size + sizeof(struct uml_net_private);
337 sizeof(((struct uml_net_private *) 0)->user);
338 366
339 device = kzalloc(sizeof(*device), GFP_KERNEL); 367 device = kzalloc(sizeof(*device), GFP_KERNEL);
340 if (device == NULL) { 368 if (device == NULL) {
341 printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); 369 printk(KERN_ERR "eth_configure failed to allocate struct "
342 return(1); 370 "uml_net\n");
371 return;
372 }
373
374 dev = alloc_etherdev(size);
375 if (dev == NULL) {
376 printk(KERN_ERR "eth_configure: failed to allocate struct "
377 "net_device for eth%d\n", n);
378 goto out_free_device;
343 } 379 }
344 380
345 INIT_LIST_HEAD(&device->list); 381 INIT_LIST_HEAD(&device->list);
346 device->index = n; 382 device->index = n;
347 383
348 spin_lock(&devices_lock); 384 /* If this name ends up conflicting with an existing registered
349 list_add(&device->list, &devices); 385 * netdevice, that is OK, register_netdev{,ice}() will notice this
350 spin_unlock(&devices_lock); 386 * and fail.
387 */
388 snprintf(dev->name, sizeof(dev->name), "eth%d", n);
351 389
352 setup_etheraddr(mac, device->mac); 390 setup_etheraddr(mac, device->mac, dev->name);
353 391
354 printk(KERN_INFO "Netdevice %d ", n); 392 printk(KERN_INFO "Netdevice %d ", n);
355 printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", 393 printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
@@ -357,11 +395,6 @@ static int eth_configure(int n, void *init, char *mac,
357 device->mac[2], device->mac[3], 395 device->mac[2], device->mac[3],
358 device->mac[4], device->mac[5]); 396 device->mac[4], device->mac[5]);
359 printk(": "); 397 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 398
366 lp = dev->priv; 399 lp = dev->priv;
367 /* This points to the transport private data. It's still clear, but we 400 /* This points to the transport private data. It's still clear, but we
@@ -376,47 +409,20 @@ static int eth_configure(int n, void *init, char *mac,
376 } 409 }
377 device->pdev.id = n; 410 device->pdev.id = n;
378 device->pdev.name = DRIVER_NAME; 411 device->pdev.name = DRIVER_NAME;
379 platform_device_register(&device->pdev); 412 device->pdev.dev.release = net_device_release;
413 device->pdev.dev.driver_data = device;
414 if(platform_device_register(&device->pdev))
415 goto out_free_netdev;
380 SET_NETDEV_DEV(dev,&device->pdev.dev); 416 SET_NETDEV_DEV(dev,&device->pdev.dev);
381 417
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; 418 device->dev = dev;
388 419
420 /*
421 * These just fill in a data structure, so there's no failure
422 * to be worried about.
423 */
389 (*transport->kern->init)(dev, init); 424 (*transport->kern->init)(dev, init);
390 425
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) 426 *lp = ((struct uml_net_private)
421 { .list = LIST_HEAD_INIT(lp->list), 427 { .list = LIST_HEAD_INIT(lp->list),
422 .dev = dev, 428 .dev = dev,
@@ -430,20 +436,52 @@ static int eth_configure(int n, void *init, char *mac,
430 .write = transport->kern->write, 436 .write = transport->kern->write,
431 .add_address = transport->user->add_address, 437 .add_address = transport->user->add_address,
432 .delete_address = transport->user->delete_address, 438 .delete_address = transport->user->delete_address,
433 .set_mtu = transport->user->set_mtu, 439 .set_mtu = transport->user->set_mtu });
434 .user = { save } });
435 440
436 init_timer(&lp->tl); 441 init_timer(&lp->tl);
437 spin_lock_init(&lp->lock); 442 spin_lock_init(&lp->lock);
438 lp->tl.function = uml_net_user_timer_expire; 443 lp->tl.function = uml_net_user_timer_expire;
439 memcpy(lp->mac, device->mac, sizeof(lp->mac)); 444 memcpy(lp->mac, device->mac, sizeof(lp->mac));
440 445
441 if (transport->user->init) 446 if ((transport->user->init != NULL) &&
442 (*transport->user->init)(&lp->user, dev); 447 ((*transport->user->init)(&lp->user, dev) != 0))
448 goto out_unregister;
443 449
444 set_ether_mac(dev, device->mac); 450 set_ether_mac(dev, device->mac);
451 dev->mtu = transport->user->max_packet;
452 dev->open = uml_net_open;
453 dev->hard_start_xmit = uml_net_start_xmit;
454 dev->stop = uml_net_close;
455 dev->get_stats = uml_net_get_stats;
456 dev->set_multicast_list = uml_net_set_multicast_list;
457 dev->tx_timeout = uml_net_tx_timeout;
458 dev->set_mac_address = uml_net_set_mac;
459 dev->change_mtu = uml_net_change_mtu;
460 dev->ethtool_ops = &uml_net_ethtool_ops;
461 dev->watchdog_timeo = (HZ >> 1);
462 dev->irq = UM_ETH_IRQ;
445 463
446 return 0; 464 rtnl_lock();
465 err = register_netdevice(dev);
466 rtnl_unlock();
467 if (err)
468 goto out_undo_user_init;
469
470 spin_lock(&devices_lock);
471 list_add(&device->list, &devices);
472 spin_unlock(&devices_lock);
473
474 return;
475
476out_undo_user_init:
477 if (transport->user->remove != NULL)
478 (*transport->user->remove)(&lp->user);
479out_unregister:
480 platform_device_unregister(&device->pdev);
481out_free_netdev:
482 free_netdev(dev);
483out_free_device:
484 kfree(device);
447} 485}
448 486
449static struct uml_net *find_device(int n) 487static struct uml_net *find_device(int n)
@@ -666,13 +704,9 @@ static int net_remove(int n, char **error_out)
666 lp = dev->priv; 704 lp = dev->priv;
667 if(lp->fd > 0) 705 if(lp->fd > 0)
668 return -EBUSY; 706 return -EBUSY;
669 if(lp->remove != NULL) (*lp->remove)(&lp->user);
670 unregister_netdev(dev); 707 unregister_netdev(dev);
671 platform_device_unregister(&device->pdev); 708 platform_device_unregister(&device->pdev);
672 709
673 list_del(&device->list);
674 kfree(device);
675 free_netdev(dev);
676 return 0; 710 return 0;
677} 711}
678 712
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_user.c b/arch/um/drivers/pcap_user.c
index 11921a7baa7b..dc0a903ef9a6 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -18,7 +18,7 @@
18 18
19#define PCAP_FD(p) (*(int *)(p)) 19#define PCAP_FD(p) (*(int *)(p))
20 20
21static void pcap_user_init(void *data, void *dev) 21static int pcap_user_init(void *data, void *dev)
22{ 22{
23 struct pcap_data *pri = data; 23 struct pcap_data *pri = data;
24 pcap_t *p; 24 pcap_t *p;
@@ -28,11 +28,12 @@ static void pcap_user_init(void *data, void *dev)
28 if(p == NULL){ 28 if(p == NULL){
29 printk("pcap_user_init : pcap_open_live failed - '%s'\n", 29 printk("pcap_user_init : pcap_open_live failed - '%s'\n",
30 errors); 30 errors);
31 return; 31 return -EINVAL;
32 } 32 }
33 33
34 pri->dev = dev; 34 pri->dev = dev;
35 pri->pcap = p; 35 pri->pcap = p;
36 return 0;
36} 37}
37 38
38static int pcap_open(void *data) 39static int pcap_open(void *data)
@@ -42,39 +43,39 @@ static int pcap_open(void *data)
42 int err; 43 int err;
43 44
44 if(pri->pcap == NULL) 45 if(pri->pcap == NULL)
45 return(-ENODEV); 46 return -ENODEV;
46 47
47 if(pri->filter != NULL){ 48 if(pri->filter != NULL){
48 err = dev_netmask(pri->dev, &netmask); 49 err = dev_netmask(pri->dev, &netmask);
49 if(err < 0){ 50 if(err < 0){
50 printk("pcap_open : dev_netmask failed\n"); 51 printk("pcap_open : dev_netmask failed\n");
51 return(-EIO); 52 return -EIO;
52 } 53 }
53 54
54 pri->compiled = um_kmalloc(sizeof(struct bpf_program)); 55 pri->compiled = um_kmalloc(sizeof(struct bpf_program));
55 if(pri->compiled == NULL){ 56 if(pri->compiled == NULL){
56 printk("pcap_open : kmalloc failed\n"); 57 printk("pcap_open : kmalloc failed\n");
57 return(-ENOMEM); 58 return -ENOMEM;
58 } 59 }
59 60
60 err = pcap_compile(pri->pcap, 61 err = pcap_compile(pri->pcap,
61 (struct bpf_program *) pri->compiled, 62 (struct bpf_program *) pri->compiled,
62 pri->filter, pri->optimize, netmask); 63 pri->filter, pri->optimize, netmask);
63 if(err < 0){ 64 if(err < 0){
64 printk("pcap_open : pcap_compile failed - '%s'\n", 65 printk("pcap_open : pcap_compile failed - '%s'\n",
65 pcap_geterr(pri->pcap)); 66 pcap_geterr(pri->pcap));
66 return(-EIO); 67 return -EIO;
67 } 68 }
68 69
69 err = pcap_setfilter(pri->pcap, pri->compiled); 70 err = pcap_setfilter(pri->pcap, pri->compiled);
70 if(err < 0){ 71 if(err < 0){
71 printk("pcap_open : pcap_setfilter failed - '%s'\n", 72 printk("pcap_open : pcap_setfilter failed - '%s'\n",
72 pcap_geterr(pri->pcap)); 73 pcap_geterr(pri->pcap));
73 return(-EIO); 74 return -EIO;
74 } 75 }
75 } 76 }
76 77
77 return(PCAP_FD(pri->pcap)); 78 return PCAP_FD(pri->pcap);
78} 79}
79 80
80static void pcap_remove(void *data) 81static void pcap_remove(void *data)
@@ -114,11 +115,11 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
114 n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); 115 n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
115 if(n < 0){ 116 if(n < 0){
116 printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); 117 printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap));
117 return(-EIO); 118 return -EIO;
118 } 119 }
119 else if(n == 0) 120 else if(n == 0)
120 return(0); 121 return 0;
121 return(hdata.len); 122 return hdata.len;
122} 123}
123 124
124const struct net_user_info pcap_user_info = { 125const struct net_user_info pcap_user_info = {
@@ -131,14 +132,3 @@ const struct net_user_info pcap_user_info = {
131 .delete_address = NULL, 132 .delete_address = NULL,
132 .max_packet = MAX_PACKET - ETH_HEADER_OTHER 133 .max_packet = MAX_PACKET - ETH_HEADER_OTHER
133}; 134};
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..5593a8027083 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -24,5 +24,7 @@ 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));
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 173af029d12b..50a49691e0e6 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,6 @@ 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
121#endif 120#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..688d181b5f8a 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
@@ -273,8 +275,9 @@ extern void stack_protections(unsigned long address);
273extern void task_protections(unsigned long address); 275extern void task_protections(unsigned long address);
274extern int raw(int fd); 276extern int raw(int fd);
275extern void setup_machinename(char *machine_out); 277extern void setup_machinename(char *machine_out);
276extern void setup_hostinfo(void); 278extern void setup_hostinfo(char *buf, int len);
277extern int setjmp_wrapper(void (*proc)(void *, void *), ...); 279extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
280extern void os_dump_core(void);
278 281
279/* time.c */ 282/* time.c */
280#define BILLION (1000 * 1000 * 1000) 283#define BILLION (1000 * 1000 * 1000)
@@ -297,13 +300,12 @@ extern long syscall_stub_data(struct mm_id * mm_idp,
297 unsigned long *data, int data_count, 300 unsigned long *data, int data_count,
298 void **addr, void **stub_addr); 301 void **addr, void **stub_addr);
299extern int map(struct mm_id * mm_idp, unsigned long virt, 302extern int map(struct mm_id * mm_idp, unsigned long virt,
300 unsigned long len, int r, int w, int x, int phys_fd, 303 unsigned long len, int prot, int phys_fd,
301 unsigned long long offset, int done, void **data); 304 unsigned long long offset, int done, void **data);
302extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, 305extern int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
303 int done, void **data); 306 int done, void **data);
304extern int protect(struct mm_id * mm_idp, unsigned long addr, 307extern int protect(struct mm_id * mm_idp, unsigned long addr,
305 unsigned long len, int r, int w, int x, int done, 308 unsigned long len, unsigned int prot, int done, void **data);
306 void **data);
307 309
308/* skas/process.c */ 310/* skas/process.c */
309extern int is_skas_winch(int pid, int fd, void *data); 311extern int is_skas_winch(int pid, int fd, void *data);
@@ -339,8 +341,11 @@ extern void maybe_sigio_broken(int fd, int read);
339 341
340/* skas/trap */ 342/* skas/trap */
341extern void sig_handler_common_skas(int sig, void *sc_ptr); 343extern void sig_handler_common_skas(int sig, void *sc_ptr);
342extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
343 344
345/* sys-x86_64/prctl.c */
344extern int os_arch_prctl(int pid, int code, unsigned long *addr); 346extern int os_arch_prctl(int pid, int code, unsigned long *addr);
345 347
348/* tty.c */
349int get_pty(void);
350
346#endif 351#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/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/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..cda91aa8e703 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -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
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..8f2ed3690315 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/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"
@@ -79,6 +78,14 @@ skip:
79 return 0; 78 return 0;
80} 79}
81 80
81/*
82 * This list is accessed under irq_lock, except in sigio_handler,
83 * where it is safe from being modified. IRQ handlers won't change it -
84 * if an IRQ source has vanished, it will be freed by free_irqs just
85 * before returning from sigio_handler. That will process a separate
86 * list of irqs to free, with its own locking, coming back here to
87 * remove list elements, taking the irq_lock to do so.
88 */
82static struct irq_fd *active_fds = NULL; 89static struct irq_fd *active_fds = NULL;
83static struct irq_fd **last_irq_ptr = &active_fds; 90static struct irq_fd **last_irq_ptr = &active_fds;
84 91
@@ -244,6 +251,7 @@ void free_irq_by_fd(int fd)
244 free_irq_by_cb(same_fd, &fd); 251 free_irq_by_cb(same_fd, &fd);
245} 252}
246 253
254/* Must be called with irq_lock held */
247static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) 255static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
248{ 256{
249 struct irq_fd *irq; 257 struct irq_fd *irq;
@@ -309,6 +317,12 @@ void deactivate_fd(int fd, int irqnum)
309 ignore_sigio_fd(fd); 317 ignore_sigio_fd(fd);
310} 318}
311 319
320/*
321 * Called just before shutdown in order to provide a clean exec
322 * environment in case the system is rebooting. No locking because
323 * that would cause a pointless shutdown hang if something hadn't
324 * released the lock.
325 */
312int deactivate_all_fds(void) 326int deactivate_all_fds(void)
313{ 327{
314 struct irq_fd *irq; 328 struct irq_fd *irq;
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..ef36facd8fe9 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"
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..cd7349de8ca6 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
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..98e21743e604 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"
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..c631303cb800 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
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..1cf954a47fd7 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 task_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/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..92a7b59120d6 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;
@@ -244,7 +245,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
244 245
245 if(sig_stack != NULL){ 246 if(sig_stack != NULL){
246 pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); 247 pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
247 set_sigstack(sig_stack, pages * page_size()); 248 set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE);
248 flags = SA_ONSTACK; 249 flags = SA_ONSTACK;
249 } 250 }
250 if(usr1_handler){ 251 if(usr1_handler){
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..48d493415301 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"
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 9383e8751ae7..8e490fff3d47 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,12 +61,11 @@ 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#warning Need to look up userspace_pid by cpu
@@ -60,21 +73,21 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
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..5c088a55396c 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); 69
57 } 70/* Signals that the stub will finish with - anything else is an error */
58 sig = 0; 71#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
72
73void wait_stub_done(int pid)
74{
75 int n, status, err;
59 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);
@@ -291,10 +314,13 @@ void userspace(union uml_pt_regs *regs)
291 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ 314 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
292 315
293 if(WIFSTOPPED(status)){ 316 if(WIFSTOPPED(status)){
294 switch(WSTOPSIG(status)){ 317 int sig = WSTOPSIG(status);
318 switch(sig){
295 case SIGSEGV: 319 case SIGSEGV:
296 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) 320 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){
297 user_signal(SIGSEGV, regs, pid); 321 get_skas_faultinfo(pid, &regs->skas.faultinfo);
322 (*sig_info[SIGSEGV])(SIGSEGV, regs);
323 }
298 else handle_segv(pid, regs); 324 else handle_segv(pid, regs);
299 break; 325 break;
300 case SIGTRAP + 0x80: 326 case SIGTRAP + 0x80:
@@ -309,11 +335,13 @@ void userspace(union uml_pt_regs *regs)
309 case SIGBUS: 335 case SIGBUS:
310 case SIGFPE: 336 case SIGFPE:
311 case SIGWINCH: 337 case SIGWINCH:
312 user_signal(WSTOPSIG(status), regs, pid); 338 block_signals();
339 (*sig_info[sig])(sig, regs);
340 unblock_signals();
313 break; 341 break;
314 default: 342 default:
315 printk("userspace - child stopped with signal " 343 printk("userspace - child stopped with signal "
316 "%d\n", WSTOPSIG(status)); 344 "%d\n", sig);
317 } 345 }
318 pid = userspace_pid[0]; 346 pid = userspace_pid[0];
319 interrupt_end(); 347 interrupt_end();
@@ -325,11 +353,29 @@ void userspace(union uml_pt_regs *regs)
325 } 353 }
326} 354}
327 355
356static unsigned long thread_regs[MAX_REG_NR];
357static unsigned long thread_fp_regs[HOST_FP_SIZE];
358
359static int __init init_thread_regs(void)
360{
361 get_safe_registers(thread_regs, thread_fp_regs);
362 /* Set parent's instruction pointer to start of clone-stub */
363 thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
364 (unsigned long) stub_clone_handler -
365 (unsigned long) &__syscall_stub_start;
366 thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
367 sizeof(void *);
368#ifdef __SIGNAL_FRAMESIZE
369 thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
370#endif
371 return 0;
372}
373
374__initcall(init_thread_regs);
375
328int copy_context_skas0(unsigned long new_stack, int pid) 376int copy_context_skas0(unsigned long new_stack, int pid)
329{ 377{
330 int err; 378 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(); 379 unsigned long current_stack = current_stub_stack();
334 struct stub_data *data = (struct stub_data *) current_stack; 380 struct stub_data *data = (struct stub_data *) current_stack;
335 struct stub_data *child_data = (struct stub_data *) new_stack; 381 struct stub_data *child_data = (struct stub_data *) new_stack;
@@ -344,23 +390,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
344 .timer = ((struct itimerval) 390 .timer = ((struct itimerval)
345 { { 0, 1000000 / hz() }, 391 { { 0, 1000000 / hz() },
346 { 0, 1000000 / hz() }})}); 392 { 0, 1000000 / hz() }})});
347 get_safe_registers(regs, fp_regs); 393 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) 394 if(err < 0)
360 panic("copy_context_skas0 : PTRACE_SETREGS failed, " 395 panic("copy_context_skas0 : PTRACE_SETREGS failed, "
361 "pid = %d, errno = %d\n", pid, -err); 396 "pid = %d, errno = %d\n", pid, -err);
362 397
363 err = ptrace_setfpregs(pid, fp_regs); 398 err = ptrace_setfpregs(pid, thread_fp_regs);
364 if(err < 0) 399 if(err < 0)
365 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " 400 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
366 "pid = %d, errno = %d\n", pid, -err); 401 "pid = %d, errno = %d\n", pid, -err);
@@ -371,7 +406,11 @@ int copy_context_skas0(unsigned long new_stack, int pid)
371 /* Wait, until parent has finished its work: read child's pid from 406 /* Wait, until parent has finished its work: read child's pid from
372 * parent's stack, and check, if bad result. 407 * parent's stack, and check, if bad result.
373 */ 408 */
374 wait_stub_done(pid, 0, "copy_context_skas0"); 409 err = ptrace(PTRACE_CONT, pid, 0, 0);
410 if(err)
411 panic("Failed to continue new process, pid = %d, "
412 "errno = %d\n", pid, errno);
413 wait_stub_done(pid);
375 414
376 pid = data->err; 415 pid = data->err;
377 if(pid < 0) 416 if(pid < 0)
@@ -381,7 +420,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
381 /* Wait, until child has finished too: read child's result from 420 /* Wait, until child has finished too: read child's result from
382 * child's stack and check it. 421 * child's stack and check it.
383 */ 422 */
384 wait_stub_done(pid, -1, "copy_context_skas0"); 423 wait_stub_done(pid);
385 if (child_data->err != UML_CONFIG_STUB_DATA) 424 if (child_data->err != UML_CONFIG_STUB_DATA)
386 panic("copy_context_skas0 - stub-child reports error %ld\n", 425 panic("copy_context_skas0 - stub-child reports error %ld\n",
387 child_data->err); 426 child_data->err);
@@ -396,7 +435,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
396 435
397/* 436/*
398 * This is used only, if stub pages are needed, while proc_mm is 437 * 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 438 * available. Opening /proc/mm creates a new mm_context, which lacks
400 * the stub-pages. Thus, we map them using /proc/mm-fd 439 * the stub-pages. Thus, we map them using /proc/mm-fd
401 */ 440 */
402void map_stub_pages(int fd, unsigned long code, 441void map_stub_pages(int fd, unsigned long code,
@@ -418,12 +457,13 @@ void map_stub_pages(int fd, unsigned long code,
418 .fd = code_fd, 457 .fd = code_fd,
419 .offset = code_offset 458 .offset = code_offset
420 } } }); 459 } } });
421 n = os_write_file(fd, &mmop, sizeof(mmop)); 460 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
422 if(n != sizeof(mmop)){ 461 if(n != sizeof(mmop)){
462 n = errno;
423 printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", 463 printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n",
424 code, code_fd, (unsigned long long) code_offset); 464 code, code_fd, (unsigned long long) code_offset);
425 panic("map_stub_pages : /proc/mm map for code failed, " 465 panic("map_stub_pages : /proc/mm map for code failed, "
426 "err = %d\n", -n); 466 "err = %d\n", n);
427 } 467 }
428 468
429 if ( stack ) { 469 if ( stack ) {
@@ -440,10 +480,10 @@ void map_stub_pages(int fd, unsigned long code,
440 .fd = map_fd, 480 .fd = map_fd,
441 .offset = map_offset 481 .offset = map_offset
442 } } }); 482 } } });
443 n = os_write_file(fd, &mmop, sizeof(mmop)); 483 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
444 if(n != sizeof(mmop)) 484 if(n != sizeof(mmop))
445 panic("map_stub_pages : /proc/mm map for data failed, " 485 panic("map_stub_pages : /proc/mm map for data failed, "
446 "err = %d\n", -n); 486 "err = %d\n", errno);
447 } 487 }
448} 488}
449 489
@@ -480,7 +520,15 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
480 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, 520 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
481 SIGVTALRM, -1); 521 SIGVTALRM, -1);
482 522
483 n = UML_SETJMP(&initial_jmpbuf); 523 /*
524 * Can't use UML_SETJMP or UML_LONGJMP here because they save
525 * and restore signals, with the possible side-effect of
526 * trying to handle any signals which came when they were
527 * blocked, which can't be done on this stack.
528 * Signals must be blocked when jumping back here and restored
529 * after returning to the jumper.
530 */
531 n = setjmp(initial_jmpbuf);
484 switch(n){ 532 switch(n){
485 case INIT_JMP_NEW_THREAD: 533 case INIT_JMP_NEW_THREAD:
486 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; 534 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
@@ -490,7 +538,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
490 break; 538 break;
491 case INIT_JMP_CALLBACK: 539 case INIT_JMP_CALLBACK:
492 (*cb_proc)(cb_arg); 540 (*cb_proc)(cb_arg);
493 UML_LONGJMP(cb_back, 1); 541 longjmp(*cb_back, 1);
494 break; 542 break;
495 case INIT_JMP_HALT: 543 case INIT_JMP_HALT:
496 kmalloc_ok = 0; 544 kmalloc_ok = 0;
@@ -501,7 +549,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
501 default: 549 default:
502 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 550 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
503 } 551 }
504 UML_LONGJMP(switch_buf, 1); 552 longjmp(*switch_buf, 1);
505} 553}
506 554
507void initial_thread_cb_skas(void (*proc)(void *), void *arg) 555void initial_thread_cb_skas(void (*proc)(void *), void *arg)
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/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/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..c307a89ed259 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,29 @@
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 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
37 37
38 if(mprotect((void *) address, page_size(), prot) < 0) 38 if(mprotect((void *) address, UM_KERN_PAGE_SIZE, prot) < 0)
39 panic("protecting stack failed, errno = %d", errno); 39 panic("protecting stack failed, errno = %d", errno);
40} 40}
41 41
42void task_protections(unsigned long address) 42void task_protections(unsigned long address)
43{ 43{
44 unsigned long guard = address + page_size(); 44 unsigned long guard = address + UM_KERN_PAGE_SIZE;
45 unsigned long stack = guard + page_size(); 45 unsigned long stack = guard + UM_KERN_PAGE_SIZE;
46 int prot = 0, pages; 46 int prot = 0, pages;
47 47
48#ifdef notdef 48#ifdef notdef
49 if(mprotect((void *) stack, page_size(), prot) < 0) 49 if(mprotect((void *) stack, UM_KERN_PAGE_SIZE, prot) < 0)
50 panic("protecting guard page failed, errno = %d", errno); 50 panic("protecting guard page failed, errno = %d", errno);
51#endif 51#endif
52 pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; 52 pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
53 prot = PROT_READ | PROT_WRITE | PROT_EXEC; 53 prot = PROT_READ | PROT_WRITE | PROT_EXEC;
54 if(mprotect((void *) stack, pages * page_size(), prot) < 0) 54 if(mprotect((void *) stack, pages * UM_KERN_PAGE_SIZE, prot) < 0)
55 panic("protecting stack failed, errno = %d", errno); 55 panic("protecting stack failed, errno = %d", errno);
56} 56}
57 57
@@ -96,15 +96,13 @@ void setup_machinename(char *machine_out)
96 strcpy(machine_out, host.machine); 96 strcpy(machine_out, host.machine);
97} 97}
98 98
99char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1]; 99void setup_hostinfo(char *buf, int len)
100
101void setup_hostinfo(void)
102{ 100{
103 struct utsname host; 101 struct utsname host;
104 102
105 uname(&host); 103 uname(&host);
106 sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename, 104 snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename,
107 host.release, host.version, host.machine); 105 host.release, host.version, host.machine);
108} 106}
109 107
110int setjmp_wrapper(void (*proc)(void *, void *), ...) 108int setjmp_wrapper(void (*proc)(void *, void *), ...)
@@ -121,3 +119,9 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
121 va_end(args); 119 va_end(args);
122 return n; 120 return n;
123} 121}
122
123void os_dump_core(void)
124{
125 signal(SIGSEGV, SIG_DFL);
126 abort();
127}
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}