aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Makefile-x86_647
-rw-r--r--arch/um/drivers/chan_kern.c16
-rw-r--r--arch/um/drivers/daemon.h2
-rw-r--r--arch/um/drivers/daemon_kern.c2
-rw-r--r--arch/um/drivers/daemon_user.c2
-rw-r--r--arch/um/drivers/fd.c4
-rw-r--r--arch/um/drivers/hostaudio_kern.c4
-rw-r--r--arch/um/drivers/line.c6
-rw-r--r--arch/um/drivers/mcast.h2
-rw-r--r--arch/um/drivers/mcast_kern.c2
-rw-r--r--arch/um/drivers/mcast_user.c2
-rw-r--r--arch/um/drivers/mmapper_kern.c4
-rw-r--r--arch/um/drivers/net_kern.c25
-rw-r--r--arch/um/drivers/null.c4
-rw-r--r--arch/um/drivers/pcap_kern.c2
-rw-r--r--arch/um/drivers/pcap_user.c2
-rw-r--r--arch/um/drivers/port_user.c4
-rw-r--r--arch/um/drivers/pty.c6
-rw-r--r--arch/um/drivers/random.c2
-rw-r--r--arch/um/drivers/slip.h2
-rw-r--r--arch/um/drivers/slip_kern.c2
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/slirp.h2
-rw-r--r--arch/um/drivers/slirp_kern.c2
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ssl.c4
-rw-r--r--arch/um/drivers/stdio_console.c2
-rw-r--r--arch/um/drivers/tty.c4
-rw-r--r--arch/um/drivers/xterm.c4
-rw-r--r--arch/um/include/chan_kern.h6
-rw-r--r--arch/um/include/chan_user.h6
-rw-r--r--arch/um/include/kern_util.h2
-rw-r--r--arch/um/include/line.h4
-rw-r--r--arch/um/include/net_kern.h4
-rw-r--r--arch/um/include/os.h13
-rw-r--r--arch/um/include/skas/skas.h3
-rw-r--r--arch/um/include/sysdep-i386/archsetjmp.h3
-rw-r--r--arch/um/include/sysdep-x86_64/archsetjmp.h3
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h43
-rw-r--r--arch/um/include/sysdep-x86_64/sc.h2
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/gmon_syms.c13
-rw-r--r--arch/um/kernel/ksyms.c3
-rw-r--r--arch/um/kernel/mem.c3
-rw-r--r--arch/um/kernel/process.c (renamed from arch/um/kernel/process_kern.c)33
-rw-r--r--arch/um/kernel/skas/Makefile3
-rw-r--r--arch/um/kernel/skas/exec.c30
-rw-r--r--arch/um/kernel/skas/exec_kern.c41
-rw-r--r--arch/um/kernel/skas/process.c217
-rw-r--r--arch/um/kernel/skas/process_kern.c533
-rw-r--r--arch/um/kernel/time.c2
-rw-r--r--arch/um/kernel/trap.c17
-rw-r--r--arch/um/kernel/um_arch.c2
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/drivers/etap.h2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap.h2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c2
-rw-r--r--arch/um/os-Linux/skas/process.c68
-rw-r--r--arch/um/sys-i386/Makefile2
62 files changed, 830 insertions, 372 deletions
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 9558a7cf34d5..11154b6773ec 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -4,10 +4,13 @@
4core-y += arch/um/sys-x86_64/ 4core-y += arch/um/sys-x86_64/
5START := 0x60000000 5START := 0x60000000
6 6
7_extra_flags_ = -fno-builtin -m64 -mcmodel=kernel
8
7#We #undef __x86_64__ for kernelspace, not for userspace where 9#We #undef __x86_64__ for kernelspace, not for userspace where
8#it's needed for headers to work! 10#it's needed for headers to work!
9CFLAGS += -U__$(SUBARCH)__ -fno-builtin -m64 11CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_)
10USER_CFLAGS += -fno-builtin -m64 12USER_CFLAGS += $(_extra_flags_)
13
11CHECKFLAGS += -m64 14CHECKFLAGS += -m64
12AFLAGS += -m64 15AFLAGS += -m64
13LDFLAGS += -m elf_x86_64 16LDFLAGS += -m elf_x86_64
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index e82764f75e7f..3576b3cc505e 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -110,7 +110,7 @@ static void not_configged_free(void *data)
110 "UML\n"); 110 "UML\n");
111} 111}
112 112
113static struct chan_ops not_configged_ops = { 113static const struct chan_ops not_configged_ops = {
114 .init = not_configged_init, 114 .init = not_configged_init,
115 .open = not_configged_open, 115 .open = not_configged_open,
116 .close = not_configged_close, 116 .close = not_configged_close,
@@ -373,7 +373,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
373} 373}
374 374
375int console_open_chan(struct line *line, struct console *co, 375int console_open_chan(struct line *line, struct console *co,
376 struct chan_opts *opts) 376 const struct chan_opts *opts)
377{ 377{
378 int err; 378 int err;
379 379
@@ -494,10 +494,10 @@ int chan_config_string(struct list_head *chans, char *str, int size,
494 494
495struct chan_type { 495struct chan_type {
496 char *key; 496 char *key;
497 struct chan_ops *ops; 497 const struct chan_ops *ops;
498}; 498};
499 499
500static struct chan_type chan_table[] = { 500static const struct chan_type chan_table[] = {
501 { "fd", &fd_ops }, 501 { "fd", &fd_ops },
502 502
503#ifdef CONFIG_NULL_CHAN 503#ifdef CONFIG_NULL_CHAN
@@ -534,10 +534,10 @@ static struct chan_type chan_table[] = {
534}; 534};
535 535
536static struct chan *parse_chan(struct line *line, char *str, int device, 536static struct chan *parse_chan(struct line *line, char *str, int device,
537 struct chan_opts *opts) 537 const struct chan_opts *opts)
538{ 538{
539 struct chan_type *entry; 539 const struct chan_type *entry;
540 struct chan_ops *ops; 540 const struct chan_ops *ops;
541 struct chan *chan; 541 struct chan *chan;
542 void *data; 542 void *data;
543 int i; 543 int i;
@@ -582,7 +582,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
582} 582}
583 583
584int parse_chan_pair(char *str, struct line *line, int device, 584int parse_chan_pair(char *str, struct line *line, int device,
585 struct chan_opts *opts) 585 const struct chan_opts *opts)
586{ 586{
587 struct list_head *chans = &line->chan_list; 587 struct list_head *chans = &line->chan_list;
588 struct chan *new, *chan; 588 struct chan *new, *chan;
diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h
index 7326c42f7ef9..3bc3cf6b94aa 100644
--- a/arch/um/drivers/daemon.h
+++ b/arch/um/drivers/daemon.h
@@ -18,7 +18,7 @@ struct daemon_data {
18 void *dev; 18 void *dev;
19}; 19};
20 20
21extern struct net_user_info daemon_user_info; 21extern const struct net_user_info daemon_user_info;
22 22
23extern int daemon_user_write(int fd, void *buf, int len, 23extern int daemon_user_write(int fd, void *buf, int len,
24 struct daemon_data *pri); 24 struct daemon_data *pri);
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index 53d09ed78b42..824386974f88 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -57,7 +57,7 @@ static int daemon_write(int fd, struct sk_buff **skb,
57 (struct daemon_data *) &lp->user)); 57 (struct daemon_data *) &lp->user));
58} 58}
59 59
60static struct net_kern_info daemon_kern_info = { 60static const struct net_kern_info daemon_kern_info = {
61 .init = daemon_init, 61 .init = daemon_init,
62 .protocol = eth_protocol, 62 .protocol = eth_protocol,
63 .read = daemon_read, 63 .read = daemon_read,
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index c944265955e2..77954ea77043 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -182,7 +182,7 @@ static int daemon_set_mtu(int mtu, void *data)
182 return(mtu); 182 return(mtu);
183} 183}
184 184
185struct net_user_info daemon_user_info = { 185const struct net_user_info daemon_user_info = {
186 .init = daemon_user_init, 186 .init = daemon_user_init,
187 .open = daemon_open, 187 .open = daemon_open,
188 .close = NULL, 188 .close = NULL,
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index c41f75e4acb5..108b7dafbd0e 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -20,7 +20,7 @@ struct fd_chan {
20 char str[sizeof("1234567890\0")]; 20 char str[sizeof("1234567890\0")];
21}; 21};
22 22
23static void *fd_init(char *str, int device, struct chan_opts *opts) 23static void *fd_init(char *str, int device, const struct chan_opts *opts)
24{ 24{
25 struct fd_chan *data; 25 struct fd_chan *data;
26 char *end; 26 char *end;
@@ -77,7 +77,7 @@ static void fd_close(int fd, void *d)
77 } 77 }
78} 78}
79 79
80struct chan_ops fd_ops = { 80const struct chan_ops fd_ops = {
81 .type = "fd", 81 .type = "fd",
82 .init = fd_init, 82 .init = fd_init,
83 .open = fd_open, 83 .open = fd_open,
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 37232f908cd7..d247ef45c374 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -280,7 +280,7 @@ static int hostmixer_release(struct inode *inode, struct file *file)
280 280
281/* kernel module operations */ 281/* kernel module operations */
282 282
283static struct file_operations hostaudio_fops = { 283static const struct file_operations hostaudio_fops = {
284 .owner = THIS_MODULE, 284 .owner = THIS_MODULE,
285 .llseek = no_llseek, 285 .llseek = no_llseek,
286 .read = hostaudio_read, 286 .read = hostaudio_read,
@@ -292,7 +292,7 @@ static struct file_operations hostaudio_fops = {
292 .release = hostaudio_release, 292 .release = hostaudio_release,
293}; 293};
294 294
295static struct file_operations hostmixer_fops = { 295static const struct file_operations hostmixer_fops = {
296 .owner = THIS_MODULE, 296 .owner = THIS_MODULE,
297 .llseek = no_llseek, 297 .llseek = no_llseek,
298 .ioctl = hostmixer_ioctl_mixdev, 298 .ioctl = hostmixer_ioctl_mixdev,
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index ebebaabb78ad..563ce7690a1e 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -251,7 +251,7 @@ void line_set_termios(struct tty_struct *tty, struct termios * old)
251 /* nothing */ 251 /* nothing */
252} 252}
253 253
254static struct { 254static const struct {
255 int cmd; 255 int cmd;
256 char *level; 256 char *level;
257 char *name; 257 char *name;
@@ -405,7 +405,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
405 405
406int line_setup_irq(int fd, int input, int output, struct line *line, void *data) 406int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
407{ 407{
408 struct line_driver *driver = line->driver; 408 const struct line_driver *driver = line->driver;
409 int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM; 409 int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
410 410
411 if (input) 411 if (input)
@@ -558,7 +558,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
558} 558}
559 559
560int line_config(struct line *lines, unsigned int num, char *str, 560int line_config(struct line *lines, unsigned int num, char *str,
561 struct chan_opts *opts) 561 const struct chan_opts *opts)
562{ 562{
563 struct line *line; 563 struct line *line;
564 char *new; 564 char *new;
diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h
index a2c6db243458..bc56af9d3e53 100644
--- a/arch/um/drivers/mcast.h
+++ b/arch/um/drivers/mcast.h
@@ -13,7 +13,7 @@ struct mcast_data {
13 void *dev; 13 void *dev;
14}; 14};
15 15
16extern struct net_user_info mcast_user_info; 16extern const struct net_user_info mcast_user_info;
17 17
18extern int mcast_user_write(int fd, void *buf, int len, 18extern int mcast_user_write(int fd, void *buf, int len,
19 struct mcast_data *pri); 19 struct mcast_data *pri);
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index 3a7af18cf944..c090fbd464e7 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -61,7 +61,7 @@ static int mcast_write(int fd, struct sk_buff **skb,
61 (struct mcast_data *) &lp->user); 61 (struct mcast_data *) &lp->user);
62} 62}
63 63
64static struct net_kern_info mcast_kern_info = { 64static const struct net_kern_info mcast_kern_info = {
65 .init = mcast_init, 65 .init = mcast_init,
66 .protocol = eth_protocol, 66 .protocol = eth_protocol,
67 .read = mcast_read, 67 .read = mcast_read,
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index afe85bfa66e0..4d2bd39a85bc 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -152,7 +152,7 @@ static int mcast_set_mtu(int mtu, void *data)
152 return(mtu); 152 return(mtu);
153} 153}
154 154
155struct net_user_info mcast_user_info = { 155const struct net_user_info mcast_user_info = {
156 .init = mcast_user_init, 156 .init = mcast_user_init,
157 .open = mcast_open, 157 .open = mcast_open,
158 .close = mcast_close, 158 .close = mcast_close,
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 022f67bb6873..9a3b5daf6250 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -85,7 +85,7 @@ mmapper_release(struct inode *inode, struct file *file)
85 return 0; 85 return 0;
86} 86}
87 87
88static struct file_operations mmapper_fops = { 88static const struct file_operations mmapper_fops = {
89 .owner = THIS_MODULE, 89 .owner = THIS_MODULE,
90 .read = mmapper_read, 90 .read = mmapper_read,
91 .write = mmapper_write, 91 .write = mmapper_write,
@@ -95,7 +95,7 @@ static struct file_operations mmapper_fops = {
95 .release = mmapper_release, 95 .release = mmapper_release,
96}; 96};
97 97
98static struct miscdevice mmapper_dev = { 98static const struct miscdevice mmapper_dev = {
99 .minor = MISC_DYNAMIC_MINOR, 99 .minor = MISC_DYNAMIC_MINOR,
100 .name = "mmapper", 100 .name = "mmapper",
101 .fops = &mmapper_fops 101 .fops = &mmapper_fops
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 4a7966b21931..664c2e2fb820 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -114,8 +114,6 @@ static int uml_net_open(struct net_device *dev)
114 struct uml_net_private *lp = dev->priv; 114 struct uml_net_private *lp = dev->priv;
115 int err; 115 int err;
116 116
117 spin_lock(&lp->lock);
118
119 if(lp->fd >= 0){ 117 if(lp->fd >= 0){
120 err = -ENXIO; 118 err = -ENXIO;
121 goto out; 119 goto out;
@@ -149,8 +147,6 @@ static int uml_net_open(struct net_device *dev)
149 */ 147 */
150 while((err = uml_net_rx(dev)) > 0) ; 148 while((err = uml_net_rx(dev)) > 0) ;
151 149
152 spin_unlock(&lp->lock);
153
154 spin_lock(&opened_lock); 150 spin_lock(&opened_lock);
155 list_add(&lp->list, &opened); 151 list_add(&lp->list, &opened);
156 spin_unlock(&opened_lock); 152 spin_unlock(&opened_lock);
@@ -160,7 +156,6 @@ out_close:
160 if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); 156 if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
161 lp->fd = -1; 157 lp->fd = -1;
162out: 158out:
163 spin_unlock(&lp->lock);
164 return err; 159 return err;
165} 160}
166 161
@@ -169,15 +164,12 @@ static int uml_net_close(struct net_device *dev)
169 struct uml_net_private *lp = dev->priv; 164 struct uml_net_private *lp = dev->priv;
170 165
171 netif_stop_queue(dev); 166 netif_stop_queue(dev);
172 spin_lock(&lp->lock);
173 167
174 free_irq(dev->irq, dev); 168 free_irq(dev->irq, dev);
175 if(lp->close != NULL) 169 if(lp->close != NULL)
176 (*lp->close)(lp->fd, &lp->user); 170 (*lp->close)(lp->fd, &lp->user);
177 lp->fd = -1; 171 lp->fd = -1;
178 172
179 spin_unlock(&lp->lock);
180
181 spin_lock(&opened_lock); 173 spin_lock(&opened_lock);
182 list_del(&lp->list); 174 list_del(&lp->list);
183 spin_unlock(&opened_lock); 175 spin_unlock(&opened_lock);
@@ -246,9 +238,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
246 struct uml_net_private *lp = dev->priv; 238 struct uml_net_private *lp = dev->priv;
247 struct sockaddr *hwaddr = addr; 239 struct sockaddr *hwaddr = addr;
248 240
249 spin_lock(&lp->lock); 241 spin_lock_irq(&lp->lock);
250 set_ether_mac(dev, hwaddr->sa_data); 242 set_ether_mac(dev, hwaddr->sa_data);
251 spin_unlock(&lp->lock); 243 spin_unlock_irq(&lp->lock);
252 244
253 return(0); 245 return(0);
254} 246}
@@ -258,7 +250,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
258 struct uml_net_private *lp = dev->priv; 250 struct uml_net_private *lp = dev->priv;
259 int err = 0; 251 int err = 0;
260 252
261 spin_lock(&lp->lock); 253 spin_lock_irq(&lp->lock);
262 254
263 new_mtu = (*lp->set_mtu)(new_mtu, &lp->user); 255 new_mtu = (*lp->set_mtu)(new_mtu, &lp->user);
264 if(new_mtu < 0){ 256 if(new_mtu < 0){
@@ -269,7 +261,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
269 dev->mtu = new_mtu; 261 dev->mtu = new_mtu;
270 262
271 out: 263 out:
272 spin_unlock(&lp->lock); 264 spin_unlock_irq(&lp->lock);
273 return err; 265 return err;
274} 266}
275 267
@@ -569,12 +561,13 @@ static int eth_setup(char *str)
569 int n, err; 561 int n, err;
570 562
571 err = eth_parse(str, &n, &str); 563 err = eth_parse(str, &n, &str);
572 if(err) return(1); 564 if(err)
565 return 1;
573 566
574 new = alloc_bootmem(sizeof(new)); 567 new = alloc_bootmem(sizeof(*new));
575 if (new == NULL){ 568 if (new == NULL){
576 printk("eth_init : alloc_bootmem failed\n"); 569 printk("eth_init : alloc_bootmem failed\n");
577 return(1); 570 return 1;
578 } 571 }
579 572
580 INIT_LIST_HEAD(&new->list); 573 INIT_LIST_HEAD(&new->list);
@@ -582,7 +575,7 @@ static int eth_setup(char *str)
582 new->init = str; 575 new->init = str;
583 576
584 list_add_tail(&new->list, &eth_cmd_line); 577 list_add_tail(&new->list, &eth_cmd_line);
585 return(1); 578 return 1;
586} 579}
587 580
588__setup("eth", eth_setup); 581__setup("eth", eth_setup);
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c
index 14cc5f78398a..3683ed44315d 100644
--- a/arch/um/drivers/null.c
+++ b/arch/um/drivers/null.c
@@ -10,7 +10,7 @@
10 10
11static int null_chan; 11static int null_chan;
12 12
13static void *null_init(char *str, int device, struct chan_opts *opts) 13static void *null_init(char *str, int device, const struct chan_opts *opts)
14{ 14{
15 return(&null_chan); 15 return(&null_chan);
16} 16}
@@ -31,7 +31,7 @@ static void null_free(void *data)
31{ 31{
32} 32}
33 33
34struct chan_ops null_ops = { 34const struct chan_ops null_ops = {
35 .type = "null", 35 .type = "null",
36 .init = null_init, 36 .init = null_init,
37 .open = null_open, 37 .open = null_open,
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c
index 4c767c7adb96..6e1ef8558283 100644
--- a/arch/um/drivers/pcap_kern.c
+++ b/arch/um/drivers/pcap_kern.c
@@ -46,7 +46,7 @@ static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
46 return(-EPERM); 46 return(-EPERM);
47} 47}
48 48
49static struct net_kern_info pcap_kern_info = { 49static const struct net_kern_info pcap_kern_info = {
50 .init = pcap_init, 50 .init = pcap_init,
51 .protocol = eth_protocol, 51 .protocol = eth_protocol,
52 .read = pcap_read, 52 .read = pcap_read,
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index edfcb29273e1..2ef641ded960 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -120,7 +120,7 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
120 return(hdata.len); 120 return(hdata.len);
121} 121}
122 122
123struct net_user_info pcap_user_info = { 123const struct net_user_info pcap_user_info = {
124 .init = pcap_user_init, 124 .init = pcap_user_init,
125 .open = pcap_open, 125 .open = pcap_open,
126 .close = NULL, 126 .close = NULL,
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index c43e8bb32502..f2e8fc42ecc2 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -27,7 +27,7 @@ struct port_chan {
27 char dev[sizeof("32768\0")]; 27 char dev[sizeof("32768\0")];
28}; 28};
29 29
30static void *port_init(char *str, int device, struct chan_opts *opts) 30static void *port_init(char *str, int device, const struct chan_opts *opts)
31{ 31{
32 struct port_chan *data; 32 struct port_chan *data;
33 void *kern_data; 33 void *kern_data;
@@ -100,7 +100,7 @@ static void port_close(int fd, void *d)
100 os_close_file(fd); 100 os_close_file(fd);
101} 101}
102 102
103struct chan_ops port_ops = { 103const struct chan_ops port_ops = {
104 .type = "port", 104 .type = "port",
105 .init = port_init, 105 .init = port_init,
106 .open = port_open, 106 .open = port_open,
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 1c555c38de4d..abec620e8380 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -22,7 +22,7 @@ struct pty_chan {
22 char dev_name[sizeof("/dev/pts/0123456\0")]; 22 char dev_name[sizeof("/dev/pts/0123456\0")];
23}; 23};
24 24
25static void *pty_chan_init(char *str, int device, struct chan_opts *opts) 25static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
26{ 26{
27 struct pty_chan *data; 27 struct pty_chan *data;
28 28
@@ -118,7 +118,7 @@ static int pty_open(int input, int output, int primary, void *d,
118 return(fd); 118 return(fd);
119} 119}
120 120
121struct chan_ops pty_ops = { 121const struct chan_ops pty_ops = {
122 .type = "pty", 122 .type = "pty",
123 .init = pty_chan_init, 123 .init = pty_chan_init,
124 .open = pty_open, 124 .open = pty_open,
@@ -131,7 +131,7 @@ struct chan_ops pty_ops = {
131 .winch = 0, 131 .winch = 0,
132}; 132};
133 133
134struct chan_ops pts_ops = { 134const struct chan_ops pts_ops = {
135 .type = "pts", 135 .type = "pts",
136 .init = pty_chan_init, 136 .init = pty_chan_init,
137 .open = pts_open, 137 .open = pts_open,
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index ba471f5864a6..ae9909415b9c 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -68,7 +68,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
68 return ret; 68 return ret;
69} 69}
70 70
71static struct file_operations rng_chrdev_ops = { 71static const struct file_operations rng_chrdev_ops = {
72 .owner = THIS_MODULE, 72 .owner = THIS_MODULE,
73 .open = rng_dev_open, 73 .open = rng_dev_open,
74 .read = rng_dev_read, 74 .read = rng_dev_read,
diff --git a/arch/um/drivers/slip.h b/arch/um/drivers/slip.h
index bb0dab41c2e4..c64f8c61d274 100644
--- a/arch/um/drivers/slip.h
+++ b/arch/um/drivers/slip.h
@@ -12,7 +12,7 @@ struct slip_data {
12 struct slip_proto slip; 12 struct slip_proto slip;
13}; 13};
14 14
15extern struct net_user_info slip_user_info; 15extern const struct net_user_info slip_user_info;
16 16
17extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri); 17extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri);
18extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri); 18extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri);
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
index 163ee0d5f75e..ccea2d7885e5 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -61,7 +61,7 @@ static int slip_write(int fd, struct sk_buff **skb,
61 (struct slip_data *) &lp->user)); 61 (struct slip_data *) &lp->user));
62} 62}
63 63
64struct net_kern_info slip_kern_info = { 64const struct net_kern_info slip_kern_info = {
65 .init = slip_init, 65 .init = slip_init,
66 .protocol = slip_protocol, 66 .protocol = slip_protocol,
67 .read = slip_read, 67 .read = slip_read,
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 89fbec185cc1..8460285c69a5 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -241,7 +241,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
241 close_addr(addr, netmask, pri->name); 241 close_addr(addr, netmask, pri->name);
242} 242}
243 243
244struct net_user_info slip_user_info = { 244const struct net_user_info slip_user_info = {
245 .init = slip_user_init, 245 .init = slip_user_init,
246 .open = slip_open, 246 .open = slip_open,
247 .close = slip_close, 247 .close = slip_close,
diff --git a/arch/um/drivers/slirp.h b/arch/um/drivers/slirp.h
index 6cf88ab580c9..89ccf83b7577 100644
--- a/arch/um/drivers/slirp.h
+++ b/arch/um/drivers/slirp.h
@@ -24,7 +24,7 @@ struct slirp_data {
24 struct slip_proto slip; 24 struct slip_proto slip;
25}; 25};
26 26
27extern struct net_user_info slirp_user_info; 27extern const struct net_user_info slirp_user_info;
28 28
29extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri); 29extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
30extern int slirp_user_write(int fd, void *buf, int len, 30extern int slirp_user_write(int fd, void *buf, int len,
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index 95e50c943e14..ae322e1c8a87 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -64,7 +64,7 @@ static int slirp_write(int fd, struct sk_buff **skb,
64 (struct slirp_data *) &lp->user)); 64 (struct slirp_data *) &lp->user));
65} 65}
66 66
67struct net_kern_info slirp_kern_info = { 67const struct net_kern_info slirp_kern_info = {
68 .init = slirp_init, 68 .init = slirp_init,
69 .protocol = slirp_protocol, 69 .protocol = slirp_protocol,
70 .read = slirp_read, 70 .read = slirp_read,
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 33c5f6e625e8..ce5e85d1de3d 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -126,7 +126,7 @@ static int slirp_set_mtu(int mtu, void *data)
126 return(mtu); 126 return(mtu);
127} 127}
128 128
129struct net_user_info slirp_user_info = { 129const struct net_user_info slirp_user_info = {
130 .init = slirp_user_init, 130 .init = slirp_user_init,
131 .open = slirp_open, 131 .open = slirp_open,
132 .close = slirp_close, 132 .close = slirp_close,
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 6dafd6fbfdae..6f13e7c71a82 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -23,7 +23,7 @@
23#include "irq_user.h" 23#include "irq_user.h"
24#include "mconsole_kern.h" 24#include "mconsole_kern.h"
25 25
26static int ssl_version = 1; 26static const int ssl_version = 1;
27 27
28/* Referenced only by tty_driver below - presumably it's locked correctly 28/* Referenced only by tty_driver below - presumably it's locked correctly
29 * by the tty driver. 29 * by the tty driver.
@@ -123,7 +123,7 @@ void ssl_hangup(struct tty_struct *tty)
123} 123}
124#endif 124#endif
125 125
126static struct tty_operations ssl_ops = { 126static const struct tty_operations ssl_ops = {
127 .open = ssl_open, 127 .open = ssl_open,
128 .close = line_close, 128 .close = line_close,
129 .write = line_write, 129 .write = line_write,
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 856f568c2687..5e44adb07051 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -110,7 +110,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
110 110
111static int con_init_done = 0; 111static int con_init_done = 0;
112 112
113static struct tty_operations console_ops = { 113static const struct tty_operations console_ops = {
114 .open = con_open, 114 .open = con_open,
115 .close = line_close, 115 .close = line_close,
116 .write = line_write, 116 .write = line_write,
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index 9f70edf5d8ef..11de3ac1eb5c 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -18,7 +18,7 @@ struct tty_chan {
18 struct termios tt; 18 struct termios tt;
19}; 19};
20 20
21static void *tty_chan_init(char *str, int device, struct chan_opts *opts) 21static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
22{ 22{
23 struct tty_chan *data; 23 struct tty_chan *data;
24 24
@@ -62,7 +62,7 @@ static int tty_open(int input, int output, int primary, void *d,
62 return fd; 62 return fd;
63} 63}
64 64
65struct chan_ops tty_ops = { 65const struct chan_ops tty_ops = {
66 .type = "tty", 66 .type = "tty",
67 .init = tty_chan_init, 67 .init = tty_chan_init,
68 .open = tty_open, 68 .open = tty_open,
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index aaa636661043..386f8b952982 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -31,7 +31,7 @@ struct xterm_chan {
31}; 31};
32 32
33/* Not static because it's called directly by the tt mode gdb code */ 33/* Not static because it's called directly by the tt mode gdb code */
34void *xterm_init(char *str, int device, struct chan_opts *opts) 34void *xterm_init(char *str, int device, const struct chan_opts *opts)
35{ 35{
36 struct xterm_chan *data; 36 struct xterm_chan *data;
37 37
@@ -194,7 +194,7 @@ static void xterm_free(void *d)
194 free(d); 194 free(d);
195} 195}
196 196
197struct chan_ops xterm_ops = { 197const struct chan_ops xterm_ops = {
198 .type = "xterm", 198 .type = "xterm",
199 .init = xterm_init, 199 .init = xterm_init,
200 .open = xterm_open, 200 .open = xterm_open,
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index 1bb5e9d94270..572d286ed2c6 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -23,21 +23,21 @@ struct chan {
23 unsigned int opened:1; 23 unsigned int opened:1;
24 unsigned int enabled:1; 24 unsigned int enabled:1;
25 int fd; 25 int fd;
26 struct chan_ops *ops; 26 const struct chan_ops *ops;
27 void *data; 27 void *data;
28}; 28};
29 29
30extern void chan_interrupt(struct list_head *chans, struct work_struct *task, 30extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
31 struct tty_struct *tty, int irq); 31 struct tty_struct *tty, int irq);
32extern int parse_chan_pair(char *str, struct line *line, int device, 32extern int parse_chan_pair(char *str, struct line *line, int device,
33 struct chan_opts *opts); 33 const struct chan_opts *opts);
34extern int open_chan(struct list_head *chans); 34extern int open_chan(struct list_head *chans);
35extern int write_chan(struct list_head *chans, const char *buf, int len, 35extern int write_chan(struct list_head *chans, const char *buf, int len,
36 int write_irq); 36 int write_irq);
37extern int console_write_chan(struct list_head *chans, const char *buf, 37extern int console_write_chan(struct list_head *chans, const char *buf,
38 int len); 38 int len);
39extern int console_open_chan(struct line *line, struct console *co, 39extern int console_open_chan(struct line *line, struct console *co,
40 struct chan_opts *opts); 40 const struct chan_opts *opts);
41extern void deactivate_chan(struct list_head *chans, int irq); 41extern void deactivate_chan(struct list_head *chans, int irq);
42extern void reactivate_chan(struct list_head *chans, int irq); 42extern void reactivate_chan(struct list_head *chans, int irq);
43extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); 43extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 659bb3cac32f..a795547a1dbd 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -20,7 +20,7 @@ enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
20 20
21struct chan_ops { 21struct chan_ops {
22 char *type; 22 char *type;
23 void *(*init)(char *, int, struct chan_opts *); 23 void *(*init)(char *, int, const struct chan_opts *);
24 int (*open)(int, int, int, void *, char **); 24 int (*open)(int, int, int, void *, char **);
25 void (*close)(int, void *); 25 void (*close)(int, void *);
26 int (*read)(int, char *, void *); 26 int (*read)(int, char *, void *);
@@ -31,8 +31,8 @@ struct chan_ops {
31 int winch; 31 int winch;
32}; 32};
33 33
34extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, 34extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
35 xterm_ops; 35 tty_ops, xterm_ops;
36 36
37extern void generic_close(int fd, void *unused); 37extern void generic_close(int fd, void *unused);
38extern int generic_read(int fd, char *c_out, void *unused); 38extern int generic_read(int fd, char *c_out, void *unused);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 89e1dc835a5b..59cfa9e0cad0 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -21,7 +21,7 @@ struct kern_handlers {
21 kern_hndl timer_handler; 21 kern_hndl timer_handler;
22}; 22};
23 23
24extern struct kern_handlers handlinfo_kern; 24extern const struct kern_handlers handlinfo_kern;
25 25
26extern int ncpus; 26extern int ncpus;
27extern char *linux_prog; 27extern char *linux_prog;
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 27bf2f6fbc05..642c9a0320f9 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -52,7 +52,7 @@ struct line {
52 52
53 int sigio; 53 int sigio;
54 struct work_struct task; 54 struct work_struct task;
55 struct line_driver *driver; 55 const struct line_driver *driver;
56 int have_irq; 56 int have_irq;
57}; 57};
58 58
@@ -99,7 +99,7 @@ extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
99extern void close_lines(struct line *lines, int nlines); 99extern void close_lines(struct line *lines, int nlines);
100 100
101extern int line_config(struct line *lines, unsigned int sizeof_lines, 101extern int line_config(struct line *lines, unsigned int sizeof_lines,
102 char *str, struct chan_opts *opts); 102 char *str, const struct chan_opts *opts);
103extern int line_id(char **str, int *start_out, int *end_out); 103extern int line_id(char **str, int *start_out, int *end_out);
104extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); 104extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
105extern int line_get_config(char *dev, struct line *lines, 105extern int line_get_config(char *dev, struct line *lines,
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index f7de6df60dd7..769fba43ee03 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -54,8 +54,8 @@ struct transport {
54 struct list_head list; 54 struct list_head list;
55 char *name; 55 char *name;
56 int (*setup)(char *, char **, void *); 56 int (*setup)(char *, char **, void *);
57 struct net_user_info *user; 57 const struct net_user_info *user;
58 struct net_kern_info *kern; 58 const struct net_kern_info *kern;
59 int private_size; 59 int private_size;
60 int setup_size; 60 int setup_size;
61}; 61};
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 24fb6d8680e1..120ca21a513a 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -14,6 +14,7 @@
14#include "skas/mm_id.h" 14#include "skas/mm_id.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "sysdep/tls.h" 16#include "sysdep/tls.h"
17#include "sysdep/archsetjmp.h"
17 18
18#define OS_TYPE_FILE 1 19#define OS_TYPE_FILE 1
19#define OS_TYPE_DIR 2 20#define OS_TYPE_DIR 2
@@ -198,7 +199,9 @@ extern long os_ptrace_ldt(long pid, long addr, long data);
198extern int os_getpid(void); 199extern int os_getpid(void);
199extern int os_getpgrp(void); 200extern int os_getpgrp(void);
200 201
202#ifdef UML_CONFIG_MODE_TT
201extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); 203extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
204#endif
202extern void init_new_thread_signals(void); 205extern void init_new_thread_signals(void);
203extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); 206extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
204 207
@@ -216,7 +219,6 @@ extern void os_flush_stdout(void);
216 */ 219 */
217extern void forward_ipi(int fd, int pid); 220extern void forward_ipi(int fd, int pid);
218extern void kill_child_dead(int pid); 221extern void kill_child_dead(int pid);
219extern void stop(void);
220extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); 222extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
221extern int protect_memory(unsigned long addr, unsigned long len, 223extern int protect_memory(unsigned long addr, unsigned long len,
222 int r, int w, int x, int must_succeed); 224 int r, int w, int x, int must_succeed);
@@ -307,12 +309,9 @@ extern int copy_context_skas0(unsigned long stack, int pid);
307extern void userspace(union uml_pt_regs *regs); 309extern void userspace(union uml_pt_regs *regs);
308extern void map_stub_pages(int fd, unsigned long code, 310extern void map_stub_pages(int fd, unsigned long code,
309 unsigned long data, unsigned long stack); 311 unsigned long data, unsigned long stack);
310extern void new_thread(void *stack, void **switch_buf_ptr, 312extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
311 void **fork_buf_ptr, void (*handler)(int)); 313extern void switch_threads(jmp_buf *me, jmp_buf *you);
312extern void thread_wait(void *sw, void *fb); 314extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
313extern void switch_threads(void *me, void *next);
314extern int start_idle_thread(void *stack, void *switch_buf_ptr,
315 void **fork_buf_ptr);
316extern void initial_thread_cb_skas(void (*proc)(void *), 315extern void initial_thread_cb_skas(void (*proc)(void *),
317 void *arg); 316 void *arg);
318extern void halt_skas(void); 317extern void halt_skas(void);
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
index 853b26f148c5..e88926b16072 100644
--- a/arch/um/include/skas/skas.h
+++ b/arch/um/include/skas/skas.h
@@ -14,8 +14,7 @@ extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
14extern int skas_needs_stub; 14extern int skas_needs_stub;
15 15
16extern int user_thread(unsigned long stack, int flags); 16extern int user_thread(unsigned long stack, int flags);
17extern void new_thread_proc(void *stack, void (*handler)(int sig)); 17extern void new_thread_handler(void);
18extern void new_thread_handler(int sig);
19extern void handle_syscall(union uml_pt_regs *regs); 18extern void handle_syscall(union uml_pt_regs *regs);
20extern int new_mm(unsigned long stack); 19extern int new_mm(unsigned long stack);
21extern void get_skas_faultinfo(int pid, struct faultinfo * fi); 20extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h
index ea1ba3d42aee..11bafab669e9 100644
--- a/arch/um/include/sysdep-i386/archsetjmp.h
+++ b/arch/um/include/sysdep-i386/archsetjmp.h
@@ -16,4 +16,7 @@ struct __jmp_buf {
16 16
17typedef struct __jmp_buf jmp_buf[1]; 17typedef struct __jmp_buf jmp_buf[1];
18 18
19#define JB_IP __eip
20#define JB_SP __esp
21
19#endif /* _SETJMP_H */ 22#endif /* _SETJMP_H */
diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h
index 454fc60aff6d..9a5e1a6ec800 100644
--- a/arch/um/include/sysdep-x86_64/archsetjmp.h
+++ b/arch/um/include/sysdep-x86_64/archsetjmp.h
@@ -18,4 +18,7 @@ struct __jmp_buf {
18 18
19typedef struct __jmp_buf jmp_buf[1]; 19typedef struct __jmp_buf jmp_buf[1];
20 20
21#define JB_IP __rip
22#define JB_SP __rsp
23
21#endif /* _SETJMP_H */ 24#endif /* _SETJMP_H */
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 8d353f0feec1..617bb9efc934 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -50,6 +50,21 @@
50#define HOST_FS 25 50#define HOST_FS 25
51#define HOST_GS 26 51#define HOST_GS 26
52 52
53/* Also defined in asm/ptrace-x86_64.h, but not in libc headers. So, these
54 * are already defined for kernel code, but not for userspace code.
55 */
56#ifndef FS_BASE
57/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
58 * which is what x86_64 ptrace actually uses.
59 */
60#define FS_BASE (HOST_FS_BASE * sizeof(long))
61#define GS_BASE (HOST_GS_BASE * sizeof(long))
62#define DS (HOST_DS * sizeof(long))
63#define ES (HOST_ES * sizeof(long))
64#define FS (HOST_FS * sizeof(long))
65#define GS (HOST_GS * sizeof(long))
66#endif
67
53#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE]) 68#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
54#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE]) 69#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
55#define REGS_DS(r) ((r)[HOST_DS]) 70#define REGS_DS(r) ((r)[HOST_DS])
@@ -89,9 +104,12 @@ union uml_pt_regs {
89#endif 104#endif
90#ifdef UML_CONFIG_MODE_SKAS 105#ifdef UML_CONFIG_MODE_SKAS
91 struct skas_regs { 106 struct skas_regs {
92 /* XXX */ 107 /* x86_64 ptrace uses sizeof(user_regs_struct) as its register
93 unsigned long regs[27]; 108 * file size, while i386 uses FRAME_SIZE. Therefore, we need
94 unsigned long fp[65]; 109 * to use UM_FRAME_SIZE here instead of HOST_FRAME_SIZE.
110 */
111 unsigned long regs[UM_FRAME_SIZE];
112 unsigned long fp[HOST_FP_SIZE];
95 struct faultinfo faultinfo; 113 struct faultinfo faultinfo;
96 long syscall; 114 long syscall;
97 int is_user; 115 int is_user;
@@ -120,11 +138,16 @@ extern int mode_tt;
120#define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs)) 138#define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs))
121#define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs)) 139#define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs))
122#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) 140#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
141#define UPT_FS_BASE(r) \
142 __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs))
123#define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) 143#define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
144#define UPT_GS_BASE(r) \
145 __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs))
124#define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) 146#define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
125#define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) 147#define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
126#define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) 148#define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
127#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) 149#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
150#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
128#define UPT_ORIG_RAX(r) \ 151#define UPT_ORIG_RAX(r) \
129 __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs)) 152 __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs))
130 153
@@ -183,6 +206,13 @@ struct syscall_args {
183 case RBP: val = UPT_RBP(regs); break; \ 206 case RBP: val = UPT_RBP(regs); break; \
184 case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ 207 case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \
185 case CS: val = UPT_CS(regs); break; \ 208 case CS: val = UPT_CS(regs); break; \
209 case SS: val = UPT_SS(regs); break; \
210 case FS_BASE: val = UPT_FS_BASE(regs); break; \
211 case GS_BASE: val = UPT_GS_BASE(regs); break; \
212 case DS: val = UPT_DS(regs); break; \
213 case ES: val = UPT_ES(regs); break; \
214 case FS : val = UPT_FS (regs); break; \
215 case GS: val = UPT_GS(regs); break; \
186 case EFLAGS: val = UPT_EFLAGS(regs); break; \ 216 case EFLAGS: val = UPT_EFLAGS(regs); break; \
187 default : \ 217 default : \
188 panic("Bad register in UPT_REG : %d\n", reg); \ 218 panic("Bad register in UPT_REG : %d\n", reg); \
@@ -214,6 +244,13 @@ struct syscall_args {
214 case RBP: UPT_RBP(regs) = __upt_val; break; \ 244 case RBP: UPT_RBP(regs) = __upt_val; break; \
215 case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ 245 case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
216 case CS: UPT_CS(regs) = __upt_val; break; \ 246 case CS: UPT_CS(regs) = __upt_val; break; \
247 case SS: UPT_SS(regs) = __upt_val; break; \
248 case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \
249 case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \
250 case DS: UPT_DS(regs) = __upt_val; break; \
251 case ES: UPT_ES(regs) = __upt_val; break; \
252 case FS: UPT_FS(regs) = __upt_val; break; \
253 case GS: UPT_GS(regs) = __upt_val; break; \
217 case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ 254 case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
218 default : \ 255 default : \
219 panic("Bad register in UPT_SET : %d\n", reg); \ 256 panic("Bad register in UPT_SET : %d\n", reg); \
diff --git a/arch/um/include/sysdep-x86_64/sc.h b/arch/um/include/sysdep-x86_64/sc.h
index a160d9fcc596..8aee45b07434 100644
--- a/arch/um/include/sysdep-x86_64/sc.h
+++ b/arch/um/include/sysdep-x86_64/sc.h
@@ -35,11 +35,11 @@
35#define SC_GS(sc) SC_OFFSET(sc, SC_GS) 35#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
36#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS) 36#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
37#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK) 37#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
38#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
38#if 0 39#if 0
39#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX) 40#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
40#define SC_DS(sc) SC_OFFSET(sc, SC_DS) 41#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
41#define SC_ES(sc) SC_OFFSET(sc, SC_ES) 42#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
42#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
43#endif 43#endif
44 44
45#endif 45#endif
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index a2d93065b2d0..6fa63a2a89e3 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
7clean-files := 7clean-files :=
8 8
9obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ 9obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
10 physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \ 10 physmem.o process.o ptrace.o reboot.o resource.o sigio.o \
11 signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ 11 signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
12 um_arch.o umid.o 12 um_arch.o umid.o
13 13
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 2c86e7fdb014..13aa115cd1b4 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -5,7 +5,7 @@
5 5
6#include "linux/module.h" 6#include "linux/module.h"
7 7
8extern void __bb_init_func(void *); 8extern void __bb_init_func(void *) __attribute__((weak));
9EXPORT_SYMBOL(__bb_init_func); 9EXPORT_SYMBOL(__bb_init_func);
10 10
11/* This is defined (and referred to in profiling stub code) only by some GCC 11/* This is defined (and referred to in profiling stub code) only by some GCC
@@ -21,14 +21,3 @@ EXPORT_SYMBOL(__gcov_init);
21 21
22extern void __gcov_merge_add(void *) __attribute__((weak)); 22extern void __gcov_merge_add(void *) __attribute__((weak));
23EXPORT_SYMBOL(__gcov_merge_add); 23EXPORT_SYMBOL(__gcov_merge_add);
24
25/*
26 * Overrides for Emacs so that we follow Linus's tabbing style.
27 * Emacs will notice this stuff at the end of the file and automatically
28 * adjust the settings for this buffer only. This must remain at the end
29 * of the file.
30 * ---------------------------------------------------------------------------
31 * Local variables:
32 * c-file-style: "linux"
33 * End:
34 */
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index c97045d6d89f..f030e44262ba 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -21,7 +21,6 @@
21#include "mem_user.h" 21#include "mem_user.h"
22#include "os.h" 22#include "os.h"
23 23
24EXPORT_SYMBOL(stop);
25EXPORT_SYMBOL(uml_physmem); 24EXPORT_SYMBOL(uml_physmem);
26EXPORT_SYMBOL(set_signals); 25EXPORT_SYMBOL(set_signals);
27EXPORT_SYMBOL(get_signals); 26EXPORT_SYMBOL(get_signals);
@@ -41,12 +40,14 @@ EXPORT_SYMBOL(handle_page_fault);
41EXPORT_SYMBOL(find_iomem); 40EXPORT_SYMBOL(find_iomem);
42 41
43#ifdef CONFIG_MODE_TT 42#ifdef CONFIG_MODE_TT
43EXPORT_SYMBOL(stop);
44EXPORT_SYMBOL(strncpy_from_user_tt); 44EXPORT_SYMBOL(strncpy_from_user_tt);
45EXPORT_SYMBOL(copy_from_user_tt); 45EXPORT_SYMBOL(copy_from_user_tt);
46EXPORT_SYMBOL(copy_to_user_tt); 46EXPORT_SYMBOL(copy_to_user_tt);
47#endif 47#endif
48 48
49#ifdef CONFIG_MODE_SKAS 49#ifdef CONFIG_MODE_SKAS
50EXPORT_SYMBOL(strnlen_user_skas);
50EXPORT_SYMBOL(strncpy_from_user_skas); 51EXPORT_SYMBOL(strncpy_from_user_skas);
51EXPORT_SYMBOL(copy_to_user_skas); 52EXPORT_SYMBOL(copy_to_user_skas);
52EXPORT_SYMBOL(copy_from_user_skas); 53EXPORT_SYMBOL(copy_from_user_skas);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 93121c6d26e5..c95855ba6ab5 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -226,7 +226,8 @@ void paging_init(void)
226 for(i = 0; i < ARRAY_SIZE(zones_size); i++) 226 for(i = 0; i < ARRAY_SIZE(zones_size); i++)
227 zones_size[i] = 0; 227 zones_size[i] = 0;
228 228
229 zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); 229 zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
230 (uml_physmem >> PAGE_SHIFT);
230#ifdef CONFIG_HIGHMEM 231#ifdef CONFIG_HIGHMEM
231 zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; 232 zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
232#endif 233#endif
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process.c
index 537895d68ad1..fe6c64abda5b 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process.c
@@ -1,10 +1,9 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Copyright 2003 PathScale, Inc. 3 * Copyright 2003 PathScale, Inc.
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include "linux/config.h"
8#include "linux/kernel.h" 7#include "linux/kernel.h"
9#include "linux/sched.h" 8#include "linux/sched.h"
10#include "linux/interrupt.h" 9#include "linux/interrupt.h"
@@ -113,11 +112,11 @@ void set_current(void *t)
113 112
114void *_switch_to(void *prev, void *next, void *last) 113void *_switch_to(void *prev, void *next, void *last)
115{ 114{
116 struct task_struct *from = prev; 115 struct task_struct *from = prev;
117 struct task_struct *to= next; 116 struct task_struct *to= next;
118 117
119 to->thread.prev_sched = from; 118 to->thread.prev_sched = from;
120 set_current(to); 119 set_current(to);
121 120
122 do { 121 do {
123 current->thread.saved_task = NULL ; 122 current->thread.saved_task = NULL ;
@@ -128,7 +127,7 @@ void *_switch_to(void *prev, void *next, void *last)
128 prev= current; 127 prev= current;
129 } while(current->thread.saved_task); 128 } while(current->thread.saved_task);
130 129
131 return(current->thread.prev_sched); 130 return(current->thread.prev_sched);
132 131
133} 132}
134 133
@@ -142,19 +141,19 @@ void release_thread(struct task_struct *task)
142{ 141{
143 CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); 142 CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
144} 143}
145 144
146void exit_thread(void) 145void exit_thread(void)
147{ 146{
148 unprotect_stack((unsigned long) current_thread); 147 unprotect_stack((unsigned long) current_thread);
149} 148}
150 149
151void *get_current(void) 150void *get_current(void)
152{ 151{
153 return(current); 152 return(current);
154} 153}
155 154
156int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, 155int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
157 unsigned long stack_top, struct task_struct * p, 156 unsigned long stack_top, struct task_struct * p,
158 struct pt_regs *regs) 157 struct pt_regs *regs)
159{ 158{
160 int ret; 159 int ret;
@@ -183,11 +182,11 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
183 int save_kmalloc_ok = kmalloc_ok; 182 int save_kmalloc_ok = kmalloc_ok;
184 183
185 kmalloc_ok = 0; 184 kmalloc_ok = 0;
186 CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, 185 CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
187 arg); 186 arg);
188 kmalloc_ok = save_kmalloc_ok; 187 kmalloc_ok = save_kmalloc_ok;
189} 188}
190 189
191unsigned long stack_sp(unsigned long page) 190unsigned long stack_sp(unsigned long page)
192{ 191{
193 return(page + PAGE_SIZE - sizeof(void *)); 192 return(page + PAGE_SIZE - sizeof(void *));
@@ -211,7 +210,7 @@ void default_idle(void)
211 */ 210 */
212 if(need_resched()) 211 if(need_resched())
213 schedule(); 212 schedule();
214 213
215 idle_sleep(10); 214 idle_sleep(10);
216 } 215 }
217} 216}
@@ -226,7 +225,7 @@ int page_size(void)
226 return(PAGE_SIZE); 225 return(PAGE_SIZE);
227} 226}
228 227
229void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 228void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
230 pte_t *pte_out) 229 pte_t *pte_out)
231{ 230{
232 pgd_t *pgd; 231 pgd_t *pgd;
@@ -235,7 +234,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
235 pte_t *pte; 234 pte_t *pte;
236 pte_t ptent; 235 pte_t ptent;
237 236
238 if(task->mm == NULL) 237 if(task->mm == NULL)
239 return(ERR_PTR(-EINVAL)); 238 return(ERR_PTR(-EINVAL));
240 pgd = pgd_offset(task->mm, addr); 239 pgd = pgd_offset(task->mm, addr);
241 if(!pgd_present(*pgd)) 240 if(!pgd_present(*pgd))
@@ -246,7 +245,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
246 return(ERR_PTR(-EINVAL)); 245 return(ERR_PTR(-EINVAL));
247 246
248 pmd = pmd_offset(pud, addr); 247 pmd = pmd_offset(pud, addr);
249 if(!pmd_present(*pmd)) 248 if(!pmd_present(*pmd))
250 return(ERR_PTR(-EINVAL)); 249 return(ERR_PTR(-EINVAL));
251 250
252 pte = pte_offset_kernel(pmd, addr); 251 pte = pte_offset_kernel(pmd, addr);
@@ -271,7 +270,7 @@ char *current_cmd(void)
271 270
272void force_sigbus(void) 271void force_sigbus(void)
273{ 272{
274 printk(KERN_ERR "Killing pid %d because of a lack of memory\n", 273 printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
275 current->pid); 274 current->pid);
276 lock_kernel(); 275 lock_kernel();
277 sigaddset(&current->pending.signal, SIGBUS); 276 sigaddset(&current->pending.signal, SIGBUS);
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index ea3a8e409a6e..3e3fa7e7e3cf 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,8 +3,7 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \ 6obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o
7 syscall.o tlb.o uaccess.o
8 7
9# clone.o is in the stub, so it can't be built with profiling 8# clone.o is in the stub, so it can't be built with profiling
10# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> 9# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
new file mode 100644
index 000000000000..54b795951372
--- /dev/null
+++ b/arch/um/kernel/skas/exec.c
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/kernel.h"
7#include "asm/current.h"
8#include "asm/page.h"
9#include "asm/signal.h"
10#include "asm/ptrace.h"
11#include "asm/uaccess.h"
12#include "asm/mmu_context.h"
13#include "tlb.h"
14#include "skas.h"
15#include "um_mmu.h"
16#include "os.h"
17
18void flush_thread_skas(void)
19{
20 force_flush_all();
21 switch_mm_skas(&current->mm->context.skas.id);
22}
23
24void start_thread_skas(struct pt_regs *regs, unsigned long eip,
25 unsigned long esp)
26{
27 set_fs(USER_DS);
28 PT_REGS_IP(regs) = eip;
29 PT_REGS_SP(regs) = esp;
30}
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
deleted file mode 100644
index 77ed7bbab219..000000000000
--- a/arch/um/kernel/skas/exec_kern.c
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/kernel.h"
7#include "asm/current.h"
8#include "asm/page.h"
9#include "asm/signal.h"
10#include "asm/ptrace.h"
11#include "asm/uaccess.h"
12#include "asm/mmu_context.h"
13#include "tlb.h"
14#include "skas.h"
15#include "um_mmu.h"
16#include "os.h"
17
18void flush_thread_skas(void)
19{
20 force_flush_all();
21 switch_mm_skas(&current->mm->context.skas.id);
22}
23
24void start_thread_skas(struct pt_regs *regs, unsigned long eip,
25 unsigned long esp)
26{
27 set_fs(USER_DS);
28 PT_REGS_IP(regs) = eip;
29 PT_REGS_SP(regs) = esp;
30}
31
32/*
33 * Overrides for Emacs so that we follow Linus's tabbing style.
34 * Emacs will notice this stuff at the end of the file and automatically
35 * adjust the settings for this buffer only. This must remain at the end
36 * of the file.
37 * ---------------------------------------------------------------------------
38 * Local variables:
39 * c-file-style: "linux"
40 * End:
41 */
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
new file mode 100644
index 000000000000..ae4fa71d3b8b
--- /dev/null
+++ b/arch/um/kernel/skas/process.c
@@ -0,0 +1,217 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/sched.h"
7#include "linux/slab.h"
8#include "linux/ptrace.h"
9#include "linux/proc_fs.h"
10#include "linux/file.h"
11#include "linux/errno.h"
12#include "linux/init.h"
13#include "asm/uaccess.h"
14#include "asm/atomic.h"
15#include "kern_util.h"
16#include "skas.h"
17#include "os.h"
18#include "user_util.h"
19#include "tlb.h"
20#include "kern.h"
21#include "mode.h"
22#include "registers.h"
23
24void switch_to_skas(void *prev, void *next)
25{
26 struct task_struct *from, *to;
27
28 from = prev;
29 to = next;
30
31 /* XXX need to check runqueues[cpu].idle */
32 if(current->pid == 0)
33 switch_timers(0);
34
35 switch_threads(&from->thread.mode.skas.switch_buf,
36 &to->thread.mode.skas.switch_buf);
37
38 arch_switch_to_skas(current->thread.prev_sched, current);
39
40 if(current->pid == 0)
41 switch_timers(1);
42}
43
44extern void schedule_tail(struct task_struct *prev);
45
46/* This is called magically, by its address being stuffed in a jmp_buf
47 * and being longjmp-d to.
48 */
49void new_thread_handler(void)
50{
51 int (*fn)(void *), n;
52 void *arg;
53
54 if(current->thread.prev_sched != NULL)
55 schedule_tail(current->thread.prev_sched);
56 current->thread.prev_sched = NULL;
57
58 fn = current->thread.request.u.thread.proc;
59 arg = current->thread.request.u.thread.arg;
60
61 /* The return value is 1 if the kernel thread execs a process,
62 * 0 if it just exits
63 */
64 n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
65 if(n == 1){
66 /* Handle any immediate reschedules or signals */
67 interrupt_end();
68 userspace(&current->thread.regs.regs);
69 }
70 else do_exit(0);
71}
72
73void release_thread_skas(struct task_struct *task)
74{
75}
76
77/* Called magically, see new_thread_handler above */
78void fork_handler(void)
79{
80 force_flush_all();
81 if(current->thread.prev_sched == NULL)
82 panic("blech");
83
84 schedule_tail(current->thread.prev_sched);
85
86 /* XXX: if interrupt_end() calls schedule, this call to
87 * arch_switch_to_skas isn't needed. We could want to apply this to
88 * improve performance. -bb */
89 arch_switch_to_skas(current->thread.prev_sched, current);
90
91 current->thread.prev_sched = NULL;
92
93/* Handle any immediate reschedules or signals */
94 interrupt_end();
95
96 userspace(&current->thread.regs.regs);
97}
98
99int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
100 unsigned long stack_top, struct task_struct * p,
101 struct pt_regs *regs)
102{
103 void (*handler)(void);
104
105 if(current->thread.forking){
106 memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
107 sizeof(p->thread.regs.regs.skas));
108 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
109 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
110
111 handler = fork_handler;
112
113 arch_copy_thread(&current->thread.arch, &p->thread.arch);
114 }
115 else {
116 init_thread_registers(&p->thread.regs.regs);
117 p->thread.request.u.thread = current->thread.request.u.thread;
118 handler = new_thread_handler;
119 }
120
121 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
122 handler);
123 return(0);
124}
125
126int new_mm(unsigned long stack)
127{
128 int fd;
129
130 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
131 if(fd < 0)
132 return(fd);
133
134 if(skas_needs_stub)
135 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
136
137 return(fd);
138}
139
140void init_idle_skas(void)
141{
142 cpu_tasks[current_thread->cpu].pid = os_getpid();
143 default_idle();
144}
145
146extern void start_kernel(void);
147
148static int start_kernel_proc(void *unused)
149{
150 int pid;
151
152 block_signals();
153 pid = os_getpid();
154
155 cpu_tasks[0].pid = pid;
156 cpu_tasks[0].task = current;
157#ifdef CONFIG_SMP
158 cpu_online_map = cpumask_of_cpu(0);
159#endif
160 start_kernel();
161 return(0);
162}
163
164extern int userspace_pid[];
165
166int start_uml_skas(void)
167{
168 if(proc_mm)
169 userspace_pid[0] = start_userspace(0);
170
171 init_new_thread_signals();
172
173 init_task.thread.request.u.thread.proc = start_kernel_proc;
174 init_task.thread.request.u.thread.arg = NULL;
175 return(start_idle_thread(task_stack_page(&init_task),
176 &init_task.thread.mode.skas.switch_buf));
177}
178
179int external_pid_skas(struct task_struct *task)
180{
181#warning Need to look up userspace_pid by cpu
182 return(userspace_pid[0]);
183}
184
185int thread_pid_skas(struct task_struct *task)
186{
187#warning Need to look up userspace_pid by cpu
188 return(userspace_pid[0]);
189}
190
191void kill_off_processes_skas(void)
192{
193 if(proc_mm)
194#warning need to loop over userspace_pids in kill_off_processes_skas
195 os_kill_ptraced_process(userspace_pid[0], 1);
196 else {
197 struct task_struct *p;
198 int pid, me;
199
200 me = os_getpid();
201 for_each_process(p){
202 if(p->mm == NULL)
203 continue;
204
205 pid = p->mm->context.skas.id.u.pid;
206 os_kill_ptraced_process(pid, 1);
207 }
208 }
209}
210
211unsigned long current_stub_stack(void)
212{
213 if(current->mm == NULL)
214 return(0);
215
216 return(current->mm->context.skas.id.stack);
217}
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 55caeec8b257..0f3d5d084dc7 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -1,227 +1,484 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Copyright 2003 PathScale, Inc.
3 * Licensed under the GPL 4 * Licensed under the GPL
4 */ 5 */
5 6
7#include "linux/config.h"
8#include "linux/kernel.h"
6#include "linux/sched.h" 9#include "linux/sched.h"
10#include "linux/interrupt.h"
11#include "linux/string.h"
12#include "linux/mm.h"
7#include "linux/slab.h" 13#include "linux/slab.h"
8#include "linux/ptrace.h" 14#include "linux/utsname.h"
9#include "linux/proc_fs.h" 15#include "linux/fs.h"
10#include "linux/file.h" 16#include "linux/utime.h"
11#include "linux/errno.h" 17#include "linux/smp_lock.h"
18#include "linux/module.h"
12#include "linux/init.h" 19#include "linux/init.h"
20#include "linux/capability.h"
21#include "linux/vmalloc.h"
22#include "linux/spinlock.h"
23#include "linux/proc_fs.h"
24#include "linux/ptrace.h"
25#include "linux/random.h"
26#include "linux/personality.h"
27#include "asm/unistd.h"
28#include "asm/mman.h"
29#include "asm/segment.h"
30#include "asm/stat.h"
31#include "asm/pgtable.h"
32#include "asm/processor.h"
33#include "asm/tlbflush.h"
13#include "asm/uaccess.h" 34#include "asm/uaccess.h"
14#include "asm/atomic.h" 35#include "asm/user.h"
15#include "kern_util.h"
16#include "skas.h"
17#include "os.h"
18#include "user_util.h" 36#include "user_util.h"
19#include "tlb.h" 37#include "kern_util.h"
20#include "kern.h" 38#include "kern.h"
39#include "signal_kern.h"
40#include "init.h"
41#include "irq_user.h"
42#include "mem_user.h"
43#include "tlb.h"
44#include "frame_kern.h"
45#include "sigcontext.h"
46#include "os.h"
21#include "mode.h" 47#include "mode.h"
22#include "registers.h" 48#include "mode_kern.h"
49#include "choose-mode.h"
50
51/* This is a per-cpu array. A processor only modifies its entry and it only
52 * cares about its entry, so it's OK if another processor is modifying its
53 * entry.
54 */
55struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
56
57int external_pid(void *t)
58{
59 struct task_struct *task = t ? t : current;
60
61 return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
62}
63
64int pid_to_processor_id(int pid)
65{
66 int i;
67
68 for(i = 0; i < ncpus; i++){
69 if(cpu_tasks[i].pid == pid) return(i);
70 }
71 return(-1);
72}
73
74void free_stack(unsigned long stack, int order)
75{
76 free_pages(stack, order);
77}
78
79unsigned long alloc_stack(int order, int atomic)
80{
81 unsigned long page;
82 gfp_t flags = GFP_KERNEL;
83
84 if (atomic)
85 flags = GFP_ATOMIC;
86 page = __get_free_pages(flags, order);
87 if(page == 0)
88 return(0);
89 stack_protections(page);
90 return(page);
91}
92
93int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
94{
95 int pid;
96
97 current->thread.request.u.thread.proc = fn;
98 current->thread.request.u.thread.arg = arg;
99 pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
100 &current->thread.regs, 0, NULL, NULL);
101 if(pid < 0)
102 panic("do_fork failed in kernel_thread, errno = %d", pid);
103 return(pid);
104}
23 105
24void switch_to_skas(void *prev, void *next) 106void set_current(void *t)
25{ 107{
26 struct task_struct *from, *to; 108 struct task_struct *task = t;
27 109
28 from = prev; 110 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
29 to = next; 111 { external_pid(task), task });
112}
30 113
31 /* XXX need to check runqueues[cpu].idle */ 114void *_switch_to(void *prev, void *next, void *last)
32 if(current->pid == 0) 115{
33 switch_timers(0); 116 struct task_struct *from = prev;
117 struct task_struct *to= next;
34 118
35 switch_threads(&from->thread.mode.skas.switch_buf, 119 to->thread.prev_sched = from;
36 to->thread.mode.skas.switch_buf); 120 set_current(to);
37 121
38 arch_switch_to_skas(current->thread.prev_sched, current); 122 do {
123 current->thread.saved_task = NULL ;
124 CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
125 if(current->thread.saved_task)
126 show_regs(&(current->thread.regs));
127 next= current->thread.saved_task;
128 prev= current;
129 } while(current->thread.saved_task);
130
131 return(current->thread.prev_sched);
39 132
40 if(current->pid == 0)
41 switch_timers(1);
42} 133}
43 134
44extern void schedule_tail(struct task_struct *prev); 135void interrupt_end(void)
136{
137 if(need_resched()) schedule();
138 if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
139}
45 140
46void new_thread_handler(int sig) 141void release_thread(struct task_struct *task)
47{ 142{
48 int (*fn)(void *), n; 143 CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
49 void *arg; 144}
50 145
51 fn = current->thread.request.u.thread.proc; 146void exit_thread(void)
52 arg = current->thread.request.u.thread.arg; 147{
53 os_usr1_signal(1); 148 unprotect_stack((unsigned long) current_thread);
54 thread_wait(&current->thread.mode.skas.switch_buf, 149}
55 current->thread.mode.skas.fork_buf);
56 150
57 if(current->thread.prev_sched != NULL) 151void *get_current(void)
58 schedule_tail(current->thread.prev_sched); 152{
59 current->thread.prev_sched = NULL; 153 return(current);
154}
155
156int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
157 unsigned long stack_top, struct task_struct * p,
158 struct pt_regs *regs)
159{
160 int ret;
60 161
61 /* The return value is 1 if the kernel thread execs a process, 162 p->thread = (struct thread_struct) INIT_THREAD;
62 * 0 if it just exits 163 ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
164 clone_flags, sp, stack_top, p, regs);
165
166 if (ret || !current->thread.forking)
167 goto out;
168
169 clear_flushed_tls(p);
170
171 /*
172 * Set a new TLS for the child thread?
63 */ 173 */
64 n = run_kernel_thread(fn, arg, &current->thread.exec_buf); 174 if (clone_flags & CLONE_SETTLS)
65 if(n == 1){ 175 ret = arch_copy_tls(p);
66 /* Handle any immediate reschedules or signals */ 176
67 interrupt_end(); 177out:
68 userspace(&current->thread.regs.regs); 178 return ret;
179}
180
181void initial_thread_cb(void (*proc)(void *), void *arg)
182{
183 int save_kmalloc_ok = kmalloc_ok;
184
185 kmalloc_ok = 0;
186 CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
187 arg);
188 kmalloc_ok = save_kmalloc_ok;
189}
190
191unsigned long stack_sp(unsigned long page)
192{
193 return(page + PAGE_SIZE - sizeof(void *));
194}
195
196int current_pid(void)
197{
198 return(current->pid);
199}
200
201void default_idle(void)
202{
203 CHOOSE_MODE(uml_idle_timer(), (void) 0);
204
205 while(1){
206 /* endless idle loop with no priority at all */
207
208 /*
209 * although we are an idle CPU, we do not want to
210 * get into the scheduler unnecessarily.
211 */
212 if(need_resched())
213 schedule();
214
215 idle_sleep(10);
69 } 216 }
70 else do_exit(0);
71} 217}
72 218
73void new_thread_proc(void *stack, void (*handler)(int sig)) 219void cpu_idle(void)
74{ 220{
75 init_new_thread_stack(stack, handler); 221 CHOOSE_MODE(init_idle_tt(), init_idle_skas());
76 os_usr1_process(os_getpid());
77} 222}
78 223
79void release_thread_skas(struct task_struct *task) 224int page_size(void)
80{ 225{
226 return(PAGE_SIZE);
81} 227}
82 228
83void fork_handler(int sig) 229void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
230 pte_t *pte_out)
84{ 231{
85 os_usr1_signal(1); 232 pgd_t *pgd;
86 thread_wait(&current->thread.mode.skas.switch_buf, 233 pud_t *pud;
87 current->thread.mode.skas.fork_buf); 234 pmd_t *pmd;
88 235 pte_t *pte;
89 force_flush_all(); 236 pte_t ptent;
90 if(current->thread.prev_sched == NULL) 237
91 panic("blech"); 238 if(task->mm == NULL)
239 return(ERR_PTR(-EINVAL));
240 pgd = pgd_offset(task->mm, addr);
241 if(!pgd_present(*pgd))
242 return(ERR_PTR(-EINVAL));
243
244 pud = pud_offset(pgd, addr);
245 if(!pud_present(*pud))
246 return(ERR_PTR(-EINVAL));
247
248 pmd = pmd_offset(pud, addr);
249 if(!pmd_present(*pmd))
250 return(ERR_PTR(-EINVAL));
251
252 pte = pte_offset_kernel(pmd, addr);
253 ptent = *pte;
254 if(!pte_present(ptent))
255 return(ERR_PTR(-EINVAL));
256
257 if(pte_out != NULL)
258 *pte_out = ptent;
259 return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
260}
92 261
93 schedule_tail(current->thread.prev_sched); 262char *current_cmd(void)
263{
264#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
265 return("(Unknown)");
266#else
267 void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
268 return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
269#endif
270}
94 271
95 /* XXX: if interrupt_end() calls schedule, this call to 272void force_sigbus(void)
96 * arch_switch_to_skas isn't needed. We could want to apply this to 273{
97 * improve performance. -bb */ 274 printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
98 arch_switch_to_skas(current->thread.prev_sched, current); 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}
99 282
100 current->thread.prev_sched = NULL; 283void dump_thread(struct pt_regs *regs, struct user *u)
284{
285}
101 286
102/* Handle any immediate reschedules or signals */ 287void enable_hlt(void)
103 interrupt_end(); 288{
289 panic("enable_hlt");
290}
291
292EXPORT_SYMBOL(enable_hlt);
104 293
105 userspace(&current->thread.regs.regs); 294void disable_hlt(void)
295{
296 panic("disable_hlt");
106} 297}
107 298
108int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, 299EXPORT_SYMBOL(disable_hlt);
109 unsigned long stack_top, struct task_struct * p, 300
110 struct pt_regs *regs) 301void *um_kmalloc(int size)
111{ 302{
112 void (*handler)(int); 303 return kmalloc(size, GFP_KERNEL);
304}
113 305
114 if(current->thread.forking){ 306void *um_kmalloc_atomic(int size)
115 memcpy(&p->thread.regs.regs.skas, &regs->regs.skas, 307{
116 sizeof(p->thread.regs.regs.skas)); 308 return kmalloc(size, GFP_ATOMIC);
117 REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); 309}
118 if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
119 310
120 handler = fork_handler; 311void *um_vmalloc(int size)
312{
313 return vmalloc(size);
314}
121 315
122 arch_copy_thread(&current->thread.arch, &p->thread.arch); 316void *um_vmalloc_atomic(int size)
123 } 317{
124 else { 318 return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
125 init_thread_registers(&p->thread.regs.regs); 319}
126 p->thread.request.u.thread = current->thread.request.u.thread;
127 handler = new_thread_handler;
128 }
129 320
130 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, 321int __cant_sleep(void) {
131 &p->thread.mode.skas.fork_buf, handler); 322 return in_atomic() || irqs_disabled() || in_interrupt();
132 return(0); 323 /* Is in_interrupt() really needed? */
324}
325
326unsigned long get_fault_addr(void)
327{
328 return((unsigned long) current->thread.fault_addr);
133} 329}
134 330
135int new_mm(unsigned long stack) 331EXPORT_SYMBOL(get_fault_addr);
332
333void not_implemented(void)
136{ 334{
137 int fd; 335 printk(KERN_DEBUG "Something isn't implemented in here\n");
336}
138 337
139 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 338EXPORT_SYMBOL(not_implemented);
140 if(fd < 0)
141 return(fd);
142 339
143 if(skas_needs_stub) 340int user_context(unsigned long sp)
144 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); 341{
342 unsigned long stack;
145 343
146 return(fd); 344 stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
345 return(stack != (unsigned long) current_thread);
147} 346}
148 347
149void init_idle_skas(void) 348extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
349
350void do_uml_exitcalls(void)
150{ 351{
151 cpu_tasks[current_thread->cpu].pid = os_getpid(); 352 exitcall_t *call;
152 default_idle(); 353
354 call = &__uml_exitcall_end;
355 while (--call >= &__uml_exitcall_begin)
356 (*call)();
153} 357}
154 358
155extern void start_kernel(void); 359char *uml_strdup(char *string)
360{
361 return kstrdup(string, GFP_KERNEL);
362}
156 363
157static int start_kernel_proc(void *unused) 364int copy_to_user_proc(void __user *to, void *from, int size)
158{ 365{
159 int pid; 366 return(copy_to_user(to, from, size));
367}
368
369int copy_from_user_proc(void *to, void __user *from, int size)
370{
371 return(copy_from_user(to, from, size));
372}
373
374int clear_user_proc(void __user *buf, int size)
375{
376 return(clear_user(buf, size));
377}
160 378
161 block_signals(); 379int strlen_user_proc(char __user *str)
162 pid = os_getpid(); 380{
381 return(strlen_user(str));
382}
163 383
164 cpu_tasks[0].pid = pid; 384int smp_sigio_handler(void)
165 cpu_tasks[0].task = current; 385{
166#ifdef CONFIG_SMP 386#ifdef CONFIG_SMP
167 cpu_online_map = cpumask_of_cpu(0); 387 int cpu = current_thread->cpu;
388 IPI_handler(cpu);
389 if(cpu != 0)
390 return(1);
168#endif 391#endif
169 start_kernel();
170 return(0); 392 return(0);
171} 393}
172 394
173extern int userspace_pid[]; 395int cpu(void)
174
175int start_uml_skas(void)
176{ 396{
177 if(proc_mm) 397 return(current_thread->cpu);
178 userspace_pid[0] = start_userspace(0); 398}
399
400static atomic_t using_sysemu = ATOMIC_INIT(0);
401int sysemu_supported;
179 402
180 init_new_thread_signals(); 403void set_using_sysemu(int value)
404{
405 if (value > sysemu_supported)
406 return;
407 atomic_set(&using_sysemu, value);
408}
181 409
182 init_task.thread.request.u.thread.proc = start_kernel_proc; 410int get_using_sysemu(void)
183 init_task.thread.request.u.thread.arg = NULL; 411{
184 return(start_idle_thread(task_stack_page(&init_task), 412 return atomic_read(&using_sysemu);
185 &init_task.thread.mode.skas.switch_buf,
186 &init_task.thread.mode.skas.fork_buf));
187} 413}
188 414
189int external_pid_skas(struct task_struct *task) 415static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
190{ 416{
191#warning Need to look up userspace_pid by cpu 417 if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
192 return(userspace_pid[0]); 418 *eof = 1;
419
420 return strlen(buf);
193} 421}
194 422
195int thread_pid_skas(struct task_struct *task) 423static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
196{ 424{
197#warning Need to look up userspace_pid by cpu 425 char tmp[2];
198 return(userspace_pid[0]); 426
427 if (copy_from_user(tmp, buf, 1))
428 return -EFAULT;
429
430 if (tmp[0] >= '0' && tmp[0] <= '2')
431 set_using_sysemu(tmp[0] - '0');
432 return count; /*We use the first char, but pretend to write everything*/
199} 433}
200 434
201void kill_off_processes_skas(void) 435int __init make_proc_sysemu(void)
202{ 436{
203 if(proc_mm) 437 struct proc_dir_entry *ent;
204#warning need to loop over userspace_pids in kill_off_processes_skas 438 if (!sysemu_supported)
205 os_kill_ptraced_process(userspace_pid[0], 1); 439 return 0;
206 else {
207 struct task_struct *p;
208 int pid, me;
209 440
210 me = os_getpid(); 441 ent = create_proc_entry("sysemu", 0600, &proc_root);
211 for_each_process(p){
212 if(p->mm == NULL)
213 continue;
214 442
215 pid = p->mm->context.skas.id.u.pid; 443 if (ent == NULL)
216 os_kill_ptraced_process(pid, 1); 444 {
217 } 445 printk(KERN_WARNING "Failed to register /proc/sysemu\n");
446 return(0);
218 } 447 }
448
449 ent->read_proc = proc_read_sysemu;
450 ent->write_proc = proc_write_sysemu;
451
452 return 0;
219} 453}
220 454
221unsigned long current_stub_stack(void) 455late_initcall(make_proc_sysemu);
456
457int singlestepping(void * t)
222{ 458{
223 if(current->mm == NULL) 459 struct task_struct *task = t ? t : current;
460
461 if ( ! (task->ptrace & PT_DTRACE) )
224 return(0); 462 return(0);
225 463
226 return(current->mm->context.skas.id.stack); 464 if (task->thread.singlestep_syscall)
465 return(1);
466
467 return 2;
468}
469
470/*
471 * Only x86 and x86_64 have an arch_align_stack().
472 * All other arches have "#define arch_align_stack(x) (x)"
473 * in their asm/system.h
474 * As this is included in UML from asm-um/system-generic.h,
475 * we can use it to behave as the subarch does.
476 */
477#ifndef arch_align_stack
478unsigned long arch_align_stack(unsigned long sp)
479{
480 if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
481 sp -= get_random_int() % 8192;
482 return sp & ~0xf;
227} 483}
484#endif
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 2454bbd9555d..820affbf3e16 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -95,7 +95,7 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
95 95
96 do_timer(regs); 96 do_timer(regs);
97 97
98 nsecs = get_time() + local_offset; 98 nsecs = get_time();
99 xtime.tv_sec = nsecs / NSEC_PER_SEC; 99 xtime.tv_sec = nsecs / NSEC_PER_SEC;
100 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; 100 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
101 101
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index e5eeaf2b6af1..61a23fff4395 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -140,14 +140,6 @@ void segv_handler(int sig, union uml_pt_regs *regs)
140 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); 140 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
141} 141}
142 142
143struct kern_handlers handlinfo_kern = {
144 .relay_signal = relay_signal,
145 .winch = winch,
146 .bus_handler = relay_signal,
147 .page_fault = segv_handler,
148 .sigio_handler = sigio_handler,
149 .timer_handler = timer_handler
150};
151/* 143/*
152 * We give a *copy* of the faultinfo in the regs to segv. 144 * We give a *copy* of the faultinfo in the regs to segv.
153 * This must be done, since nesting SEGVs could overwrite 145 * This must be done, since nesting SEGVs could overwrite
@@ -253,6 +245,15 @@ void winch(int sig, union uml_pt_regs *regs)
253 do_IRQ(WINCH_IRQ, regs); 245 do_IRQ(WINCH_IRQ, regs);
254} 246}
255 247
248const struct kern_handlers handlinfo_kern = {
249 .relay_signal = relay_signal,
250 .winch = winch,
251 .bus_handler = bus_handler,
252 .page_fault = segv_handler,
253 .sigio_handler = sigio_handler,
254 .timer_handler = timer_handler
255};
256
256void trap_init(void) 257void trap_init(void)
257{ 258{
258} 259}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 7896cf98232d..55005710dcbb 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -106,7 +106,7 @@ static void c_stop(struct seq_file *m, void *v)
106{ 106{
107} 107}
108 108
109struct seq_operations cpuinfo_op = { 109const struct seq_operations cpuinfo_op = {
110 .start = c_start, 110 .start = c_start,
111 .next = c_next, 111 .next = c_next,
112 .stop = c_stop, 112 .stop = c_stop,
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index f4bfc4c7ccac..b4183929b32c 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,15 +4,19 @@
4# 4#
5 5
6obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ 6obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
7 signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \ 7 signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
8 user_syms.o util.o drivers/ sys-$(SUBARCH)/ 8 user_syms.o util.o drivers/ sys-$(SUBARCH)/
9 9
10obj-$(CONFIG_MODE_SKAS) += skas/ 10obj-$(CONFIG_MODE_SKAS) += skas/
11
12obj-$(CONFIG_MODE_TT) += tt.o
13user-objs-$(CONFIG_MODE_TT) += tt.o
14
11obj-$(CONFIG_TTY_LOG) += tty_log.o 15obj-$(CONFIG_TTY_LOG) += tty_log.o
12user-objs-$(CONFIG_TTY_LOG) += tty_log.o 16user-objs-$(CONFIG_TTY_LOG) += tty_log.o
13 17
14USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ 18USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
15 process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \ 19 process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \
16 uaccess.o umid.o util.o 20 uaccess.o umid.o util.o
17 21
18CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) 22CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h
index b84f6c4740f7..57ecdaf2f67e 100644
--- a/arch/um/os-Linux/drivers/etap.h
+++ b/arch/um/os-Linux/drivers/etap.h
@@ -13,7 +13,7 @@ struct ethertap_data {
13 void *dev; 13 void *dev;
14}; 14};
15 15
16extern struct net_user_info ethertap_user_info; 16extern const struct net_user_info ethertap_user_info;
17 17
18/* 18/*
19 * Overrides for Emacs so that we follow Linus's tabbing style. 19 * Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
index 768606bec233..16385e2ada85 100644
--- a/arch/um/os-Linux/drivers/ethertap_kern.c
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -65,7 +65,7 @@ static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
65 return(net_send(fd, (*skb)->data, (*skb)->len)); 65 return(net_send(fd, (*skb)->data, (*skb)->len));
66} 66}
67 67
68struct net_kern_info ethertap_kern_info = { 68const struct net_kern_info ethertap_kern_info = {
69 .init = etap_init, 69 .init = etap_init,
70 .protocol = eth_protocol, 70 .protocol = eth_protocol,
71 .read = etap_read, 71 .read = etap_read,
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 8f49507e64ef..f559bdf746e6 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -216,7 +216,7 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
216 etap_close_addr(addr, netmask, &pri->control_fd); 216 etap_close_addr(addr, netmask, &pri->control_fd);
217} 217}
218 218
219struct net_user_info ethertap_user_info = { 219const struct net_user_info ethertap_user_info = {
220 .init = etap_user_init, 220 .init = etap_user_init,
221 .open = etap_open, 221 .open = etap_open,
222 .close = etap_close, 222 .close = etap_close,
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h
index 25d4a2868814..d3e8d3af6245 100644
--- a/arch/um/os-Linux/drivers/tuntap.h
+++ b/arch/um/os-Linux/drivers/tuntap.h
@@ -16,7 +16,7 @@ struct tuntap_data {
16 void *dev; 16 void *dev;
17}; 17};
18 18
19extern struct net_user_info tuntap_user_info; 19extern const struct net_user_info tuntap_user_info;
20 20
21#endif 21#endif
22 22
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
index 190009a6f89c..0edbac63c527 100644
--- a/arch/um/os-Linux/drivers/tuntap_kern.c
+++ b/arch/um/os-Linux/drivers/tuntap_kern.c
@@ -53,7 +53,7 @@ static int tuntap_write(int fd, struct sk_buff **skb,
53 return(net_write(fd, (*skb)->data, (*skb)->len)); 53 return(net_write(fd, (*skb)->data, (*skb)->len));
54} 54}
55 55
56struct net_kern_info tuntap_kern_info = { 56const struct net_kern_info tuntap_kern_info = {
57 .init = tuntap_init, 57 .init = tuntap_init,
58 .protocol = eth_protocol, 58 .protocol = eth_protocol,
59 .read = tuntap_read, 59 .read = tuntap_read,
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 87c3aa0252db..e846b23f7558 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -205,7 +205,7 @@ static int tuntap_set_mtu(int mtu, void *data)
205 return(mtu); 205 return(mtu);
206} 206}
207 207
208struct net_user_info tuntap_user_info = { 208const struct net_user_info tuntap_user_info = {
209 .init = tuntap_user_init, 209 .init = tuntap_user_init,
210 .open = tuntap_open, 210 .open = tuntap_open,
211 .close = tuntap_close, 211 .close = tuntap_close,
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 42e3d1ed802c..cb9ab54146cc 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -444,56 +444,22 @@ void map_stub_pages(int fd, unsigned long code,
444 } 444 }
445} 445}
446 446
447void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, 447void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
448 void (*handler)(int))
449{ 448{
450 unsigned long flags; 449 (*buf)[0].JB_IP = (unsigned long) handler;
451 jmp_buf switch_buf, fork_buf; 450 (*buf)[0].JB_SP = (unsigned long) stack +
452 451 (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
453 *switch_buf_ptr = &switch_buf;
454 *fork_buf_ptr = &fork_buf;
455
456 /* Somewhat subtle - siglongjmp restores the signal mask before doing
457 * the longjmp. This means that when jumping from one stack to another
458 * when the target stack has interrupts enabled, an interrupt may occur
459 * on the source stack. This is bad when starting up a process because
460 * it's not supposed to get timer ticks until it has been scheduled.
461 * So, we disable interrupts around the sigsetjmp to ensure that
462 * they can't happen until we get back here where they are safe.
463 */
464 flags = get_signals();
465 block_signals();
466 if(UML_SETJMP(&fork_buf) == 0)
467 new_thread_proc(stack, handler);
468
469 remove_sigstack();
470
471 set_signals(flags);
472} 452}
473 453
474#define INIT_JMP_NEW_THREAD 0 454#define INIT_JMP_NEW_THREAD 0
475#define INIT_JMP_REMOVE_SIGSTACK 1 455#define INIT_JMP_CALLBACK 1
476#define INIT_JMP_CALLBACK 2 456#define INIT_JMP_HALT 2
477#define INIT_JMP_HALT 3 457#define INIT_JMP_REBOOT 3
478#define INIT_JMP_REBOOT 4
479
480void thread_wait(void *sw, void *fb)
481{
482 jmp_buf buf, **switch_buf = sw, *fork_buf;
483
484 *switch_buf = &buf;
485 fork_buf = fb;
486 if(UML_SETJMP(&buf) == 0)
487 UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK);
488}
489 458
490void switch_threads(void *me, void *next) 459void switch_threads(jmp_buf *me, jmp_buf *you)
491{ 460{
492 jmp_buf my_buf, **me_ptr = me, *next_buf = next; 461 if(UML_SETJMP(me) == 0)
493 462 UML_LONGJMP(you, 1);
494 *me_ptr = &my_buf;
495 if(UML_SETJMP(&my_buf) == 0)
496 UML_LONGJMP(next_buf, 1);
497} 463}
498 464
499static jmp_buf initial_jmpbuf; 465static jmp_buf initial_jmpbuf;
@@ -503,23 +469,21 @@ static void (*cb_proc)(void *arg);
503static void *cb_arg; 469static void *cb_arg;
504static jmp_buf *cb_back; 470static jmp_buf *cb_back;
505 471
506int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) 472int start_idle_thread(void *stack, jmp_buf *switch_buf)
507{ 473{
508 jmp_buf **switch_buf = switch_buf_ptr;
509 int n; 474 int n;
510 475
511 set_handler(SIGWINCH, (__sighandler_t) sig_handler, 476 set_handler(SIGWINCH, (__sighandler_t) sig_handler,
512 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, 477 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
513 SIGVTALRM, -1); 478 SIGVTALRM, -1);
514 479
515 *fork_buf_ptr = &initial_jmpbuf;
516 n = UML_SETJMP(&initial_jmpbuf); 480 n = UML_SETJMP(&initial_jmpbuf);
517 switch(n){ 481 switch(n){
518 case INIT_JMP_NEW_THREAD: 482 case INIT_JMP_NEW_THREAD:
519 new_thread_proc((void *) stack, new_thread_handler); 483 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
520 break; 484 (*switch_buf)[0].JB_SP = (unsigned long) stack +
521 case INIT_JMP_REMOVE_SIGSTACK: 485 (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
522 remove_sigstack(); 486 sizeof(void *);
523 break; 487 break;
524 case INIT_JMP_CALLBACK: 488 case INIT_JMP_CALLBACK:
525 (*cb_proc)(cb_arg); 489 (*cb_proc)(cb_arg);
@@ -534,7 +498,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
534 default: 498 default:
535 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 499 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
536 } 500 }
537 UML_LONGJMP(*switch_buf, 1); 501 UML_LONGJMP(switch_buf, 1);
538} 502}
539 503
540void initial_thread_cb_skas(void (*proc)(void *), void *arg) 504void initial_thread_cb_skas(void (*proc)(void *), void *arg)
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 59cc70275754..0e32adf03be1 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -4,7 +4,7 @@ obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
4 4
5obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o 5obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
6 6
7subarch-obj-y = lib/bitops.o kernel/semaphore.o 7subarch-obj-y = lib/bitops.o lib/semaphore.o
8subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o 8subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o
9subarch-obj-$(CONFIG_MODULES) += kernel/module.o 9subarch-obj-$(CONFIG_MODULES) += kernel/module.o
10 10