diff options
Diffstat (limited to 'arch/um')
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 @@ | |||
4 | core-y += arch/um/sys-x86_64/ | 4 | core-y += arch/um/sys-x86_64/ |
5 | START := 0x60000000 | 5 | START := 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! |
9 | CFLAGS += -U__$(SUBARCH)__ -fno-builtin -m64 | 11 | CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_) |
10 | USER_CFLAGS += -fno-builtin -m64 | 12 | USER_CFLAGS += $(_extra_flags_) |
13 | |||
11 | CHECKFLAGS += -m64 | 14 | CHECKFLAGS += -m64 |
12 | AFLAGS += -m64 | 15 | AFLAGS += -m64 |
13 | LDFLAGS += -m elf_x86_64 | 16 | LDFLAGS += -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 | ||
113 | static struct chan_ops not_configged_ops = { | 113 | static 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 | ||
375 | int console_open_chan(struct line *line, struct console *co, | 375 | int 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 | ||
495 | struct chan_type { | 495 | struct chan_type { |
496 | char *key; | 496 | char *key; |
497 | struct chan_ops *ops; | 497 | const struct chan_ops *ops; |
498 | }; | 498 | }; |
499 | 499 | ||
500 | static struct chan_type chan_table[] = { | 500 | static 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 | ||
536 | static struct chan *parse_chan(struct line *line, char *str, int device, | 536 | static 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 | ||
584 | int parse_chan_pair(char *str, struct line *line, int device, | 584 | int 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 | ||
21 | extern struct net_user_info daemon_user_info; | 21 | extern const struct net_user_info daemon_user_info; |
22 | 22 | ||
23 | extern int daemon_user_write(int fd, void *buf, int len, | 23 | extern 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 | ||
60 | static struct net_kern_info daemon_kern_info = { | 60 | static 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 | ||
185 | struct net_user_info daemon_user_info = { | 185 | const 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 | ||
23 | static void *fd_init(char *str, int device, struct chan_opts *opts) | 23 | static 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 | ||
80 | struct chan_ops fd_ops = { | 80 | const 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 | ||
283 | static struct file_operations hostaudio_fops = { | 283 | static 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 | ||
295 | static struct file_operations hostmixer_fops = { | 295 | static 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 | ||
254 | static struct { | 254 | static 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 | ||
406 | int line_setup_irq(int fd, int input, int output, struct line *line, void *data) | 406 | int 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 | ||
560 | int line_config(struct line *lines, unsigned int num, char *str, | 560 | int 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 | ||
16 | extern struct net_user_info mcast_user_info; | 16 | extern const struct net_user_info mcast_user_info; |
17 | 17 | ||
18 | extern int mcast_user_write(int fd, void *buf, int len, | 18 | extern 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 | ||
64 | static struct net_kern_info mcast_kern_info = { | 64 | static 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 | ||
155 | struct net_user_info mcast_user_info = { | 155 | const 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 | ||
88 | static struct file_operations mmapper_fops = { | 88 | static 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 | ||
98 | static struct miscdevice mmapper_dev = { | 98 | static 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; |
162 | out: | 158 | out: |
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, ð_cmd_line); | 577 | list_add_tail(&new->list, ð_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 | ||
11 | static int null_chan; | 11 | static int null_chan; |
12 | 12 | ||
13 | static void *null_init(char *str, int device, struct chan_opts *opts) | 13 | static 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 | ||
34 | struct chan_ops null_ops = { | 34 | const 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 | ||
49 | static struct net_kern_info pcap_kern_info = { | 49 | static 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 | ||
123 | struct net_user_info pcap_user_info = { | 123 | const 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 | ||
30 | static void *port_init(char *str, int device, struct chan_opts *opts) | 30 | static 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 | ||
103 | struct chan_ops port_ops = { | 103 | const 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 | ||
25 | static void *pty_chan_init(char *str, int device, struct chan_opts *opts) | 25 | static 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 | ||
121 | struct chan_ops pty_ops = { | 121 | const 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 | ||
134 | struct chan_ops pts_ops = { | 134 | const 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 | ||
71 | static struct file_operations rng_chrdev_ops = { | 71 | static 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 | ||
15 | extern struct net_user_info slip_user_info; | 15 | extern const struct net_user_info slip_user_info; |
16 | 16 | ||
17 | extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri); | 17 | extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri); |
18 | extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri); | 18 | extern 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 | ||
64 | struct net_kern_info slip_kern_info = { | 64 | const 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 | ||
244 | struct net_user_info slip_user_info = { | 244 | const 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 | ||
27 | extern struct net_user_info slirp_user_info; | 27 | extern const struct net_user_info slirp_user_info; |
28 | 28 | ||
29 | extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri); | 29 | extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri); |
30 | extern int slirp_user_write(int fd, void *buf, int len, | 30 | extern 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 | ||
67 | struct net_kern_info slirp_kern_info = { | 67 | const 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 | ||
129 | struct net_user_info slirp_user_info = { | 129 | const 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 | ||
26 | static int ssl_version = 1; | 26 | static 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 | ||
126 | static struct tty_operations ssl_ops = { | 126 | static 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 | ||
111 | static int con_init_done = 0; | 111 | static int con_init_done = 0; |
112 | 112 | ||
113 | static struct tty_operations console_ops = { | 113 | static 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 | ||
21 | static void *tty_chan_init(char *str, int device, struct chan_opts *opts) | 21 | static 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 | ||
65 | struct chan_ops tty_ops = { | 65 | const 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 */ |
34 | void *xterm_init(char *str, int device, struct chan_opts *opts) | 34 | void *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 | ||
197 | struct chan_ops xterm_ops = { | 197 | const 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 | ||
30 | extern void chan_interrupt(struct list_head *chans, struct work_struct *task, | 30 | extern 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); |
32 | extern int parse_chan_pair(char *str, struct line *line, int device, | 32 | extern int parse_chan_pair(char *str, struct line *line, int device, |
33 | struct chan_opts *opts); | 33 | const struct chan_opts *opts); |
34 | extern int open_chan(struct list_head *chans); | 34 | extern int open_chan(struct list_head *chans); |
35 | extern int write_chan(struct list_head *chans, const char *buf, int len, | 35 | extern int write_chan(struct list_head *chans, const char *buf, int len, |
36 | int write_irq); | 36 | int write_irq); |
37 | extern int console_write_chan(struct list_head *chans, const char *buf, | 37 | extern int console_write_chan(struct list_head *chans, const char *buf, |
38 | int len); | 38 | int len); |
39 | extern int console_open_chan(struct line *line, struct console *co, | 39 | extern int console_open_chan(struct line *line, struct console *co, |
40 | struct chan_opts *opts); | 40 | const struct chan_opts *opts); |
41 | extern void deactivate_chan(struct list_head *chans, int irq); | 41 | extern void deactivate_chan(struct list_head *chans, int irq); |
42 | extern void reactivate_chan(struct list_head *chans, int irq); | 42 | extern void reactivate_chan(struct list_head *chans, int irq); |
43 | extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); | 43 | extern 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 | ||
21 | struct chan_ops { | 21 | struct 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 | ||
34 | extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, | 34 | extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, |
35 | xterm_ops; | 35 | tty_ops, xterm_ops; |
36 | 36 | ||
37 | extern void generic_close(int fd, void *unused); | 37 | extern void generic_close(int fd, void *unused); |
38 | extern int generic_read(int fd, char *c_out, void *unused); | 38 | extern 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 | ||
24 | extern struct kern_handlers handlinfo_kern; | 24 | extern const struct kern_handlers handlinfo_kern; |
25 | 25 | ||
26 | extern int ncpus; | 26 | extern int ncpus; |
27 | extern char *linux_prog; | 27 | extern 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); | |||
99 | extern void close_lines(struct line *lines, int nlines); | 99 | extern void close_lines(struct line *lines, int nlines); |
100 | 100 | ||
101 | extern int line_config(struct line *lines, unsigned int sizeof_lines, | 101 | extern 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); |
103 | extern int line_id(char **str, int *start_out, int *end_out); | 103 | extern int line_id(char **str, int *start_out, int *end_out); |
104 | extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); | 104 | extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); |
105 | extern int line_get_config(char *dev, struct line *lines, | 105 | extern 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); | |||
198 | extern int os_getpid(void); | 199 | extern int os_getpid(void); |
199 | extern int os_getpgrp(void); | 200 | extern int os_getpgrp(void); |
200 | 201 | ||
202 | #ifdef UML_CONFIG_MODE_TT | ||
201 | extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); | 203 | extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); |
204 | #endif | ||
202 | extern void init_new_thread_signals(void); | 205 | extern void init_new_thread_signals(void); |
203 | extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); | 206 | extern 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 | */ |
217 | extern void forward_ipi(int fd, int pid); | 220 | extern void forward_ipi(int fd, int pid); |
218 | extern void kill_child_dead(int pid); | 221 | extern void kill_child_dead(int pid); |
219 | extern void stop(void); | ||
220 | extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); | 222 | extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); |
221 | extern int protect_memory(unsigned long addr, unsigned long len, | 223 | extern 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); | |||
307 | extern void userspace(union uml_pt_regs *regs); | 309 | extern void userspace(union uml_pt_regs *regs); |
308 | extern void map_stub_pages(int fd, unsigned long code, | 310 | extern void map_stub_pages(int fd, unsigned long code, |
309 | unsigned long data, unsigned long stack); | 311 | unsigned long data, unsigned long stack); |
310 | extern void new_thread(void *stack, void **switch_buf_ptr, | 312 | extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); |
311 | void **fork_buf_ptr, void (*handler)(int)); | 313 | extern void switch_threads(jmp_buf *me, jmp_buf *you); |
312 | extern void thread_wait(void *sw, void *fb); | 314 | extern int start_idle_thread(void *stack, jmp_buf *switch_buf); |
313 | extern void switch_threads(void *me, void *next); | ||
314 | extern int start_idle_thread(void *stack, void *switch_buf_ptr, | ||
315 | void **fork_buf_ptr); | ||
316 | extern void initial_thread_cb_skas(void (*proc)(void *), | 315 | extern void initial_thread_cb_skas(void (*proc)(void *), |
317 | void *arg); | 316 | void *arg); |
318 | extern void halt_skas(void); | 317 | extern 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; | |||
14 | extern int skas_needs_stub; | 14 | extern int skas_needs_stub; |
15 | 15 | ||
16 | extern int user_thread(unsigned long stack, int flags); | 16 | extern int user_thread(unsigned long stack, int flags); |
17 | extern void new_thread_proc(void *stack, void (*handler)(int sig)); | 17 | extern void new_thread_handler(void); |
18 | extern void new_thread_handler(int sig); | ||
19 | extern void handle_syscall(union uml_pt_regs *regs); | 18 | extern void handle_syscall(union uml_pt_regs *regs); |
20 | extern int new_mm(unsigned long stack); | 19 | extern int new_mm(unsigned long stack); |
21 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); | 20 | extern 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 | ||
17 | typedef struct __jmp_buf jmp_buf[1]; | 17 | typedef 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 | ||
19 | typedef struct __jmp_buf jmp_buf[1]; | 19 | typedef 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 | |||
7 | clean-files := | 7 | clean-files := |
8 | 8 | ||
9 | obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ | 9 | obj-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 | ||
8 | extern void __bb_init_func(void *); | 8 | extern void __bb_init_func(void *) __attribute__((weak)); |
9 | EXPORT_SYMBOL(__bb_init_func); | 9 | EXPORT_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 | ||
22 | extern void __gcov_merge_add(void *) __attribute__((weak)); | 22 | extern void __gcov_merge_add(void *) __attribute__((weak)); |
23 | EXPORT_SYMBOL(__gcov_merge_add); | 23 | EXPORT_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 | ||
24 | EXPORT_SYMBOL(stop); | ||
25 | EXPORT_SYMBOL(uml_physmem); | 24 | EXPORT_SYMBOL(uml_physmem); |
26 | EXPORT_SYMBOL(set_signals); | 25 | EXPORT_SYMBOL(set_signals); |
27 | EXPORT_SYMBOL(get_signals); | 26 | EXPORT_SYMBOL(get_signals); |
@@ -41,12 +40,14 @@ EXPORT_SYMBOL(handle_page_fault); | |||
41 | EXPORT_SYMBOL(find_iomem); | 40 | EXPORT_SYMBOL(find_iomem); |
42 | 41 | ||
43 | #ifdef CONFIG_MODE_TT | 42 | #ifdef CONFIG_MODE_TT |
43 | EXPORT_SYMBOL(stop); | ||
44 | EXPORT_SYMBOL(strncpy_from_user_tt); | 44 | EXPORT_SYMBOL(strncpy_from_user_tt); |
45 | EXPORT_SYMBOL(copy_from_user_tt); | 45 | EXPORT_SYMBOL(copy_from_user_tt); |
46 | EXPORT_SYMBOL(copy_to_user_tt); | 46 | EXPORT_SYMBOL(copy_to_user_tt); |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #ifdef CONFIG_MODE_SKAS | 49 | #ifdef CONFIG_MODE_SKAS |
50 | EXPORT_SYMBOL(strnlen_user_skas); | ||
50 | EXPORT_SYMBOL(strncpy_from_user_skas); | 51 | EXPORT_SYMBOL(strncpy_from_user_skas); |
51 | EXPORT_SYMBOL(copy_to_user_skas); | 52 | EXPORT_SYMBOL(copy_to_user_skas); |
52 | EXPORT_SYMBOL(copy_from_user_skas); | 53 | EXPORT_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 | ||
114 | void *_switch_to(void *prev, void *next, void *last) | 113 | void *_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 | ||
146 | void exit_thread(void) | 145 | void exit_thread(void) |
147 | { | 146 | { |
148 | unprotect_stack((unsigned long) current_thread); | 147 | unprotect_stack((unsigned long) current_thread); |
149 | } | 148 | } |
150 | 149 | ||
151 | void *get_current(void) | 150 | void *get_current(void) |
152 | { | 151 | { |
153 | return(current); | 152 | return(current); |
154 | } | 153 | } |
155 | 154 | ||
156 | int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | 155 | int 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 | ||
191 | unsigned long stack_sp(unsigned long page) | 190 | unsigned 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 | ||
229 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | 228 | void *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 | ||
272 | void force_sigbus(void) | 271 | void 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(¤t->pending.signal, SIGBUS); | 276 | sigaddset(¤t->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 | ||
6 | obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \ | 6 | obj-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 | |||
18 | void flush_thread_skas(void) | ||
19 | { | ||
20 | force_flush_all(); | ||
21 | switch_mm_skas(¤t->mm->context.skas.id); | ||
22 | } | ||
23 | |||
24 | void 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 | |||
18 | void flush_thread_skas(void) | ||
19 | { | ||
20 | force_flush_all(); | ||
21 | switch_mm_skas(¤t->mm->context.skas.id); | ||
22 | } | ||
23 | |||
24 | void 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 | |||
24 | void 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 | |||
44 | extern 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 | */ | ||
49 | void 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, ¤t->thread.exec_buf); | ||
65 | if(n == 1){ | ||
66 | /* Handle any immediate reschedules or signals */ | ||
67 | interrupt_end(); | ||
68 | userspace(¤t->thread.regs.regs); | ||
69 | } | ||
70 | else do_exit(0); | ||
71 | } | ||
72 | |||
73 | void release_thread_skas(struct task_struct *task) | ||
74 | { | ||
75 | } | ||
76 | |||
77 | /* Called magically, see new_thread_handler above */ | ||
78 | void 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(¤t->thread.regs.regs); | ||
97 | } | ||
98 | |||
99 | int 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, ®s->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(¤t->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 | |||
126 | int 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 | |||
140 | void init_idle_skas(void) | ||
141 | { | ||
142 | cpu_tasks[current_thread->cpu].pid = os_getpid(); | ||
143 | default_idle(); | ||
144 | } | ||
145 | |||
146 | extern void start_kernel(void); | ||
147 | |||
148 | static 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 | |||
164 | extern int userspace_pid[]; | ||
165 | |||
166 | int 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 | |||
179 | int 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 | |||
185 | int 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 | |||
191 | void 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 | |||
211 | unsigned 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 | */ | ||
55 | struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; | ||
56 | |||
57 | int 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 | |||
64 | int 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 | |||
74 | void free_stack(unsigned long stack, int order) | ||
75 | { | ||
76 | free_pages(stack, order); | ||
77 | } | ||
78 | |||
79 | unsigned 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 | |||
93 | int 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 | ¤t->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 | ||
24 | void switch_to_skas(void *prev, void *next) | 106 | void 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 */ | 114 | void *_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 | ||
44 | extern void schedule_tail(struct task_struct *prev); | 135 | void interrupt_end(void) |
136 | { | ||
137 | if(need_resched()) schedule(); | ||
138 | if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); | ||
139 | } | ||
45 | 140 | ||
46 | void new_thread_handler(int sig) | 141 | void 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; | 146 | void 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(¤t->thread.mode.skas.switch_buf, | 149 | } |
55 | current->thread.mode.skas.fork_buf); | ||
56 | 150 | ||
57 | if(current->thread.prev_sched != NULL) | 151 | void *get_current(void) |
58 | schedule_tail(current->thread.prev_sched); | 152 | { |
59 | current->thread.prev_sched = NULL; | 153 | return(current); |
154 | } | ||
155 | |||
156 | int 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, ¤t->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(); | 177 | out: |
68 | userspace(¤t->thread.regs.regs); | 178 | return ret; |
179 | } | ||
180 | |||
181 | void 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 | |||
191 | unsigned long stack_sp(unsigned long page) | ||
192 | { | ||
193 | return(page + PAGE_SIZE - sizeof(void *)); | ||
194 | } | ||
195 | |||
196 | int current_pid(void) | ||
197 | { | ||
198 | return(current->pid); | ||
199 | } | ||
200 | |||
201 | void 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 | ||
73 | void new_thread_proc(void *stack, void (*handler)(int sig)) | 219 | void 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 | ||
79 | void release_thread_skas(struct task_struct *task) | 224 | int page_size(void) |
80 | { | 225 | { |
226 | return(PAGE_SIZE); | ||
81 | } | 227 | } |
82 | 228 | ||
83 | void fork_handler(int sig) | 229 | void *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(¤t->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); | 262 | char *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 | 272 | void 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(¤t->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; | 283 | void dump_thread(struct pt_regs *regs, struct user *u) |
284 | { | ||
285 | } | ||
101 | 286 | ||
102 | /* Handle any immediate reschedules or signals */ | 287 | void enable_hlt(void) |
103 | interrupt_end(); | 288 | { |
289 | panic("enable_hlt"); | ||
290 | } | ||
291 | |||
292 | EXPORT_SYMBOL(enable_hlt); | ||
104 | 293 | ||
105 | userspace(¤t->thread.regs.regs); | 294 | void disable_hlt(void) |
295 | { | ||
296 | panic("disable_hlt"); | ||
106 | } | 297 | } |
107 | 298 | ||
108 | int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, | 299 | EXPORT_SYMBOL(disable_hlt); |
109 | unsigned long stack_top, struct task_struct * p, | 300 | |
110 | struct pt_regs *regs) | 301 | void *um_kmalloc(int size) |
111 | { | 302 | { |
112 | void (*handler)(int); | 303 | return kmalloc(size, GFP_KERNEL); |
304 | } | ||
113 | 305 | ||
114 | if(current->thread.forking){ | 306 | void *um_kmalloc_atomic(int size) |
115 | memcpy(&p->thread.regs.regs.skas, ®s->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; | 311 | void *um_vmalloc(int size) |
312 | { | ||
313 | return vmalloc(size); | ||
314 | } | ||
121 | 315 | ||
122 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | 316 | void *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, | 321 | int __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 | |||
326 | unsigned long get_fault_addr(void) | ||
327 | { | ||
328 | return((unsigned long) current->thread.fault_addr); | ||
133 | } | 329 | } |
134 | 330 | ||
135 | int new_mm(unsigned long stack) | 331 | EXPORT_SYMBOL(get_fault_addr); |
332 | |||
333 | void 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); | 338 | EXPORT_SYMBOL(not_implemented); |
140 | if(fd < 0) | ||
141 | return(fd); | ||
142 | 339 | ||
143 | if(skas_needs_stub) | 340 | int 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 | ||
149 | void init_idle_skas(void) | 348 | extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; |
349 | |||
350 | void 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 | ||
155 | extern void start_kernel(void); | 359 | char *uml_strdup(char *string) |
360 | { | ||
361 | return kstrdup(string, GFP_KERNEL); | ||
362 | } | ||
156 | 363 | ||
157 | static int start_kernel_proc(void *unused) | 364 | int 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 | |||
369 | int copy_from_user_proc(void *to, void __user *from, int size) | ||
370 | { | ||
371 | return(copy_from_user(to, from, size)); | ||
372 | } | ||
373 | |||
374 | int clear_user_proc(void __user *buf, int size) | ||
375 | { | ||
376 | return(clear_user(buf, size)); | ||
377 | } | ||
160 | 378 | ||
161 | block_signals(); | 379 | int 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; | 384 | int 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 | ||
173 | extern int userspace_pid[]; | 395 | int cpu(void) |
174 | |||
175 | int start_uml_skas(void) | ||
176 | { | 396 | { |
177 | if(proc_mm) | 397 | return(current_thread->cpu); |
178 | userspace_pid[0] = start_userspace(0); | 398 | } |
399 | |||
400 | static atomic_t using_sysemu = ATOMIC_INIT(0); | ||
401 | int sysemu_supported; | ||
179 | 402 | ||
180 | init_new_thread_signals(); | 403 | void 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; | 410 | int 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 | ||
189 | int external_pid_skas(struct task_struct *task) | 415 | static 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 | ||
195 | int thread_pid_skas(struct task_struct *task) | 423 | static 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 | ||
201 | void kill_off_processes_skas(void) | 435 | int __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 | ||
221 | unsigned long current_stub_stack(void) | 455 | late_initcall(make_proc_sysemu); |
456 | |||
457 | int 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 | ||
478 | unsigned 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 | ||
143 | struct 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 | ||
248 | const 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 | |||
256 | void trap_init(void) | 257 | void 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 | ||
109 | struct seq_operations cpuinfo_op = { | 109 | const 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 | ||
6 | obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ | 6 | obj-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 | ||
10 | obj-$(CONFIG_MODE_SKAS) += skas/ | 10 | obj-$(CONFIG_MODE_SKAS) += skas/ |
11 | |||
12 | obj-$(CONFIG_MODE_TT) += tt.o | ||
13 | user-objs-$(CONFIG_MODE_TT) += tt.o | ||
14 | |||
11 | obj-$(CONFIG_TTY_LOG) += tty_log.o | 15 | obj-$(CONFIG_TTY_LOG) += tty_log.o |
12 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o | 16 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o |
13 | 17 | ||
14 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ | 18 | USER_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 | ||
18 | CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) | 22 | CFLAGS_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 | ||
16 | extern struct net_user_info ethertap_user_info; | 16 | extern 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 | ||
68 | struct net_kern_info ethertap_kern_info = { | 68 | const 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 | ||
219 | struct net_user_info ethertap_user_info = { | 219 | const 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 | ||
19 | extern struct net_user_info tuntap_user_info; | 19 | extern 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 | ||
56 | struct net_kern_info tuntap_kern_info = { | 56 | const 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 | ||
208 | struct net_user_info tuntap_user_info = { | 208 | const 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 | ||
447 | void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | 447 | void 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 | |||
480 | void 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 | ||
490 | void switch_threads(void *me, void *next) | 459 | void 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 | ||
499 | static jmp_buf initial_jmpbuf; | 465 | static jmp_buf initial_jmpbuf; |
@@ -503,23 +469,21 @@ static void (*cb_proc)(void *arg); | |||
503 | static void *cb_arg; | 469 | static void *cb_arg; |
504 | static jmp_buf *cb_back; | 470 | static jmp_buf *cb_back; |
505 | 471 | ||
506 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | 472 | int 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 | ||
540 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | 504 | void 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 | ||
5 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o | 5 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o |
6 | 6 | ||
7 | subarch-obj-y = lib/bitops.o kernel/semaphore.o | 7 | subarch-obj-y = lib/bitops.o lib/semaphore.o |
8 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o | 8 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o |
9 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o | 9 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
10 | 10 | ||