diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/drivers/mconsole_kern.c | 15 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_user.c | 4 | ||||
-rw-r--r-- | arch/um/drivers/net_kern.c | 98 | ||||
-rw-r--r-- | arch/um/drivers/net_user.c | 1 | ||||
-rw-r--r-- | arch/um/drivers/null.c | 1 | ||||
-rw-r--r-- | arch/um/drivers/random.c | 4 | ||||
-rw-r--r-- | arch/um/drivers/stderr_console.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/stdio_console.c | 1 | ||||
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 11 | ||||
-rw-r--r-- | arch/um/include/net_kern.h | 14 | ||||
-rw-r--r-- | arch/um/include/net_user.h | 18 | ||||
-rw-r--r-- | arch/um/kernel/exitcode.c | 8 | ||||
-rw-r--r-- | arch/um/kernel/skas/mmu.c | 6 | ||||
-rw-r--r-- | arch/um/kernel/skas/process_kern.c | 484 | ||||
-rw-r--r-- | arch/um/kernel/time.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/trap.c | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/mem.c | 6 |
17 files changed, 84 insertions, 593 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 79610b5ce6..773a134e7f 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -598,6 +598,11 @@ out: | |||
598 | mconsole_reply(req, err_msg, err, 0); | 598 | mconsole_reply(req, err_msg, err, 0); |
599 | } | 599 | } |
600 | 600 | ||
601 | struct mconsole_output { | ||
602 | struct list_head list; | ||
603 | struct mc_request *req; | ||
604 | }; | ||
605 | |||
601 | static DEFINE_SPINLOCK(console_lock); | 606 | static DEFINE_SPINLOCK(console_lock); |
602 | static LIST_HEAD(clients); | 607 | static LIST_HEAD(clients); |
603 | static char console_buf[MCONSOLE_MAX_DATA]; | 608 | static char console_buf[MCONSOLE_MAX_DATA]; |
@@ -622,10 +627,10 @@ static void console_write(struct console *console, const char *string, | |||
622 | return; | 627 | return; |
623 | 628 | ||
624 | list_for_each(ele, &clients){ | 629 | list_for_each(ele, &clients){ |
625 | struct mconsole_entry *entry; | 630 | struct mconsole_output *entry; |
626 | 631 | ||
627 | entry = list_entry(ele, struct mconsole_entry, list); | 632 | entry = list_entry(ele, struct mconsole_output, list); |
628 | mconsole_reply_len(&entry->request, console_buf, | 633 | mconsole_reply_len(entry->req, console_buf, |
629 | console_index, 0, 1); | 634 | console_index, 0, 1); |
630 | } | 635 | } |
631 | 636 | ||
@@ -649,10 +654,10 @@ late_initcall(mc_add_console); | |||
649 | static void with_console(struct mc_request *req, void (*proc)(void *), | 654 | static void with_console(struct mc_request *req, void (*proc)(void *), |
650 | void *arg) | 655 | void *arg) |
651 | { | 656 | { |
652 | struct mconsole_entry entry; | 657 | struct mconsole_output entry; |
653 | unsigned long flags; | 658 | unsigned long flags; |
654 | 659 | ||
655 | entry.request = *req; | 660 | entry.req = req; |
656 | list_add(&entry.list, &clients); | 661 | list_add(&entry.list, &clients); |
657 | spin_lock_irqsave(&console_lock, flags); | 662 | spin_lock_irqsave(&console_lock, flags); |
658 | 663 | ||
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 5b2f5fe9e4..17068eb746 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c | |||
@@ -131,6 +131,10 @@ int mconsole_get_request(int fd, struct mc_request *req) | |||
131 | int mconsole_reply_len(struct mc_request *req, const char *str, int total, | 131 | int mconsole_reply_len(struct mc_request *req, const char *str, int total, |
132 | int err, int more) | 132 | int err, int more) |
133 | { | 133 | { |
134 | /* XXX This is a stack consumption problem. It'd be nice to | ||
135 | * make it global and serialize access to it, but there are a | ||
136 | * ton of callers to this function. | ||
137 | */ | ||
134 | struct mconsole_reply reply; | 138 | struct mconsole_reply reply; |
135 | int len, n; | 139 | int len, n; |
136 | 140 | ||
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 664c2e2fb8..300a54a652 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
@@ -119,11 +119,6 @@ static int uml_net_open(struct net_device *dev) | |||
119 | goto out; | 119 | goto out; |
120 | } | 120 | } |
121 | 121 | ||
122 | if(!lp->have_mac){ | ||
123 | dev_ip_addr(dev, &lp->mac[2]); | ||
124 | set_ether_mac(dev, lp->mac); | ||
125 | } | ||
126 | |||
127 | lp->fd = (*lp->open)(&lp->user); | 122 | lp->fd = (*lp->open)(&lp->user); |
128 | if(lp->fd < 0){ | 123 | if(lp->fd < 0){ |
129 | err = lp->fd; | 124 | err = lp->fd; |
@@ -287,6 +282,37 @@ void uml_net_user_timer_expire(unsigned long _conn) | |||
287 | #endif | 282 | #endif |
288 | } | 283 | } |
289 | 284 | ||
285 | static void setup_etheraddr(char *str, unsigned char *addr) | ||
286 | { | ||
287 | char *end; | ||
288 | int i; | ||
289 | |||
290 | if(str == NULL) | ||
291 | goto random; | ||
292 | |||
293 | for(i=0;i<6;i++){ | ||
294 | addr[i] = simple_strtoul(str, &end, 16); | ||
295 | if((end == str) || | ||
296 | ((*end != ':') && (*end != ',') && (*end != '\0'))){ | ||
297 | printk(KERN_ERR | ||
298 | "setup_etheraddr: failed to parse '%s' " | ||
299 | "as an ethernet address\n", str); | ||
300 | goto random; | ||
301 | } | ||
302 | str = end + 1; | ||
303 | } | ||
304 | if(addr[0] & 1){ | ||
305 | printk(KERN_ERR | ||
306 | "Attempt to assign a broadcast ethernet address to a " | ||
307 | "device disallowed\n"); | ||
308 | goto random; | ||
309 | } | ||
310 | return; | ||
311 | |||
312 | random: | ||
313 | random_ether_addr(addr); | ||
314 | } | ||
315 | |||
290 | static DEFINE_SPINLOCK(devices_lock); | 316 | static DEFINE_SPINLOCK(devices_lock); |
291 | static LIST_HEAD(devices); | 317 | static LIST_HEAD(devices); |
292 | 318 | ||
@@ -322,15 +348,13 @@ static int eth_configure(int n, void *init, char *mac, | |||
322 | list_add(&device->list, &devices); | 348 | list_add(&device->list, &devices); |
323 | spin_unlock(&devices_lock); | 349 | spin_unlock(&devices_lock); |
324 | 350 | ||
325 | if (setup_etheraddr(mac, device->mac)) | 351 | setup_etheraddr(mac, device->mac); |
326 | device->have_mac = 1; | ||
327 | 352 | ||
328 | printk(KERN_INFO "Netdevice %d ", n); | 353 | printk(KERN_INFO "Netdevice %d ", n); |
329 | if (device->have_mac) | 354 | printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", |
330 | printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", | 355 | device->mac[0], device->mac[1], |
331 | device->mac[0], device->mac[1], | 356 | device->mac[2], device->mac[3], |
332 | device->mac[2], device->mac[3], | 357 | device->mac[4], device->mac[5]); |
333 | device->mac[4], device->mac[5]); | ||
334 | printk(": "); | 358 | printk(": "); |
335 | dev = alloc_etherdev(size); | 359 | dev = alloc_etherdev(size); |
336 | if (dev == NULL) { | 360 | if (dev == NULL) { |
@@ -396,7 +420,6 @@ static int eth_configure(int n, void *init, char *mac, | |||
396 | .dev = dev, | 420 | .dev = dev, |
397 | .fd = -1, | 421 | .fd = -1, |
398 | .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, | 422 | .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, |
399 | .have_mac = device->have_mac, | ||
400 | .protocol = transport->kern->protocol, | 423 | .protocol = transport->kern->protocol, |
401 | .open = transport->user->open, | 424 | .open = transport->user->open, |
402 | .close = transport->user->close, | 425 | .close = transport->user->close, |
@@ -411,14 +434,12 @@ static int eth_configure(int n, void *init, char *mac, | |||
411 | init_timer(&lp->tl); | 434 | init_timer(&lp->tl); |
412 | spin_lock_init(&lp->lock); | 435 | spin_lock_init(&lp->lock); |
413 | lp->tl.function = uml_net_user_timer_expire; | 436 | lp->tl.function = uml_net_user_timer_expire; |
414 | if (lp->have_mac) | 437 | memcpy(lp->mac, device->mac, sizeof(lp->mac)); |
415 | memcpy(lp->mac, device->mac, sizeof(lp->mac)); | ||
416 | 438 | ||
417 | if (transport->user->init) | 439 | if (transport->user->init) |
418 | (*transport->user->init)(&lp->user, dev); | 440 | (*transport->user->init)(&lp->user, dev); |
419 | 441 | ||
420 | if (device->have_mac) | 442 | set_ether_mac(dev, device->mac); |
421 | set_ether_mac(dev, device->mac); | ||
422 | 443 | ||
423 | return 0; | 444 | return 0; |
424 | } | 445 | } |
@@ -747,47 +768,6 @@ static void close_devices(void) | |||
747 | 768 | ||
748 | __uml_exitcall(close_devices); | 769 | __uml_exitcall(close_devices); |
749 | 770 | ||
750 | int setup_etheraddr(char *str, unsigned char *addr) | ||
751 | { | ||
752 | char *end; | ||
753 | int i; | ||
754 | |||
755 | if(str == NULL) | ||
756 | return(0); | ||
757 | for(i=0;i<6;i++){ | ||
758 | addr[i] = simple_strtoul(str, &end, 16); | ||
759 | if((end == str) || | ||
760 | ((*end != ':') && (*end != ',') && (*end != '\0'))){ | ||
761 | printk(KERN_ERR | ||
762 | "setup_etheraddr: failed to parse '%s' " | ||
763 | "as an ethernet address\n", str); | ||
764 | return(0); | ||
765 | } | ||
766 | str = end + 1; | ||
767 | } | ||
768 | if(addr[0] & 1){ | ||
769 | printk(KERN_ERR | ||
770 | "Attempt to assign a broadcast ethernet address to a " | ||
771 | "device disallowed\n"); | ||
772 | return(0); | ||
773 | } | ||
774 | return(1); | ||
775 | } | ||
776 | |||
777 | void dev_ip_addr(void *d, unsigned char *bin_buf) | ||
778 | { | ||
779 | struct net_device *dev = d; | ||
780 | struct in_device *ip = dev->ip_ptr; | ||
781 | struct in_ifaddr *in; | ||
782 | |||
783 | if((ip == NULL) || ((in = ip->ifa_list) == NULL)){ | ||
784 | printk(KERN_WARNING "dev_ip_addr - device not assigned an " | ||
785 | "IP address\n"); | ||
786 | return; | ||
787 | } | ||
788 | memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address)); | ||
789 | } | ||
790 | |||
791 | struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) | 771 | struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) |
792 | { | 772 | { |
793 | if((skb != NULL) && (skb_tailroom(skb) < extra)){ | 773 | if((skb != NULL) && (skb_tailroom(skb) < extra)){ |
@@ -825,7 +805,7 @@ int dev_netmask(void *d, void *m) | |||
825 | struct net_device *dev = d; | 805 | struct net_device *dev = d; |
826 | struct in_device *ip = dev->ip_ptr; | 806 | struct in_device *ip = dev->ip_ptr; |
827 | struct in_ifaddr *in; | 807 | struct in_ifaddr *in; |
828 | __u32 *mask_out = m; | 808 | __be32 *mask_out = m; |
829 | 809 | ||
830 | if(ip == NULL) | 810 | if(ip == NULL) |
831 | return(1); | 811 | return(1); |
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 107c5e43fa..f3a3f8a29c 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <string.h> | 12 | #include <string.h> |
13 | #include <sys/socket.h> | 13 | #include <sys/socket.h> |
14 | #include <sys/wait.h> | 14 | #include <sys/wait.h> |
15 | #include <sys/time.h> | ||
15 | #include "user.h" | 16 | #include "user.h" |
16 | #include "user_util.h" | 17 | #include "user_util.h" |
17 | #include "kern_util.h" | 18 | #include "kern_util.h" |
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c index 3683ed4431..9016c68bee 100644 --- a/arch/um/drivers/null.c +++ b/arch/um/drivers/null.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "chan_user.h" | 8 | #include "chan_user.h" |
9 | #include "os.h" | 9 | #include "os.h" |
10 | 10 | ||
11 | /* This address is used only as a unique identifer */ | ||
11 | static int null_chan; | 12 | static int null_chan; |
12 | 13 | ||
13 | static void *null_init(char *str, int device, const struct chan_opts *opts) | 14 | static void *null_init(char *str, int device, const struct chan_opts *opts) |
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index ae9909415b..73b2bdd6d2 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c | |||
@@ -20,6 +20,10 @@ | |||
20 | 20 | ||
21 | #define RNG_MISCDEV_MINOR 183 /* official */ | 21 | #define RNG_MISCDEV_MINOR 183 /* official */ |
22 | 22 | ||
23 | /* Changed at init time, in the non-modular case, and at module load | ||
24 | * time, in the module case. Presumably, the module subsystem | ||
25 | * protects against a module being loaded twice at the same time. | ||
26 | */ | ||
23 | static int random_fd = -1; | 27 | static int random_fd = -1; |
24 | 28 | ||
25 | static int rng_dev_open (struct inode *inode, struct file *filp) | 29 | static int rng_dev_open (struct inode *inode, struct file *filp) |
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c index 6d2cf32a9e..9115392938 100644 --- a/arch/um/drivers/stderr_console.c +++ b/arch/um/drivers/stderr_console.c | |||
@@ -9,6 +9,8 @@ | |||
9 | /* | 9 | /* |
10 | * Don't register by default -- as this registeres very early in the | 10 | * Don't register by default -- as this registeres very early in the |
11 | * boot process it becomes the default console. | 11 | * boot process it becomes the default console. |
12 | * | ||
13 | * Initialized at init time. | ||
12 | */ | 14 | */ |
13 | static int use_stderr_console = 0; | 15 | static int use_stderr_console = 0; |
14 | 16 | ||
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 5e44adb070..e4bfcfe855 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c | |||
@@ -108,6 +108,7 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
108 | return line_open(vts, tty); | 108 | return line_open(vts, tty); |
109 | } | 109 | } |
110 | 110 | ||
111 | /* Set in an initcall, checked in an exitcall */ | ||
111 | static int con_init_done = 0; | 112 | static int con_init_done = 0; |
112 | 113 | ||
113 | static const struct tty_operations console_ops = { | 114 | static const struct tty_operations console_ops = { |
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 34085315aa..fda4a39406 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -668,18 +668,15 @@ static int ubd_add(int n) | |||
668 | if(dev->file == NULL) | 668 | if(dev->file == NULL) |
669 | goto out; | 669 | goto out; |
670 | 670 | ||
671 | if (ubd_open_dev(dev)) | ||
672 | goto out; | ||
673 | |||
674 | err = ubd_file_size(dev, &dev->size); | 671 | err = ubd_file_size(dev, &dev->size); |
675 | if(err < 0) | 672 | if(err < 0) |
676 | goto out_close; | 673 | goto out; |
677 | 674 | ||
678 | dev->size = ROUND_BLOCK(dev->size); | 675 | dev->size = ROUND_BLOCK(dev->size); |
679 | 676 | ||
680 | err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); | 677 | err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); |
681 | if(err) | 678 | if(err) |
682 | goto out_close; | 679 | goto out; |
683 | 680 | ||
684 | if(fake_major != MAJOR_NR) | 681 | if(fake_major != MAJOR_NR) |
685 | ubd_new_disk(fake_major, dev->size, n, | 682 | ubd_new_disk(fake_major, dev->size, n, |
@@ -691,8 +688,6 @@ static int ubd_add(int n) | |||
691 | make_ide_entries(ubd_gendisk[n]->disk_name); | 688 | make_ide_entries(ubd_gendisk[n]->disk_name); |
692 | 689 | ||
693 | err = 0; | 690 | err = 0; |
694 | out_close: | ||
695 | ubd_close(dev); | ||
696 | out: | 691 | out: |
697 | return err; | 692 | return err; |
698 | } | 693 | } |
@@ -986,8 +981,6 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) | |||
986 | __u64 offset; | 981 | __u64 offset; |
987 | int len; | 982 | int len; |
988 | 983 | ||
989 | if(req->rq_status == RQ_INACTIVE) return(1); | ||
990 | |||
991 | /* This should be impossible now */ | 984 | /* This should be impossible now */ |
992 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ | 985 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ |
993 | printk("Write attempted on readonly ubd device %s\n", | 986 | printk("Write attempted on readonly ubd device %s\n", |
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h index 769fba43ee..280459fb0b 100644 --- a/arch/um/include/net_kern.h +++ b/arch/um/include/net_kern.h | |||
@@ -18,7 +18,6 @@ struct uml_net { | |||
18 | struct platform_device pdev; | 18 | struct platform_device pdev; |
19 | int index; | 19 | int index; |
20 | unsigned char mac[ETH_ALEN]; | 20 | unsigned char mac[ETH_ALEN]; |
21 | int have_mac; | ||
22 | }; | 21 | }; |
23 | 22 | ||
24 | struct uml_net_private { | 23 | struct uml_net_private { |
@@ -29,7 +28,6 @@ struct uml_net_private { | |||
29 | struct net_device_stats stats; | 28 | struct net_device_stats stats; |
30 | int fd; | 29 | int fd; |
31 | unsigned char mac[ETH_ALEN]; | 30 | unsigned char mac[ETH_ALEN]; |
32 | int have_mac; | ||
33 | unsigned short (*protocol)(struct sk_buff *); | 31 | unsigned short (*protocol)(struct sk_buff *); |
34 | int (*open)(void *); | 32 | int (*open)(void *); |
35 | void (*close)(int, void *); | 33 | void (*close)(int, void *); |
@@ -62,7 +60,6 @@ struct transport { | |||
62 | 60 | ||
63 | extern struct net_device *ether_init(int); | 61 | extern struct net_device *ether_init(int); |
64 | extern unsigned short ether_protocol(struct sk_buff *); | 62 | extern unsigned short ether_protocol(struct sk_buff *); |
65 | extern int setup_etheraddr(char *str, unsigned char *addr); | ||
66 | extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); | 63 | extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); |
67 | extern int tap_setup_common(char *str, char *type, char **dev_name, | 64 | extern int tap_setup_common(char *str, char *type, char **dev_name, |
68 | char **mac_out, char **gate_addr); | 65 | char **mac_out, char **gate_addr); |
@@ -70,14 +67,3 @@ extern void register_transport(struct transport *new); | |||
70 | extern unsigned short eth_protocol(struct sk_buff *skb); | 67 | extern unsigned short eth_protocol(struct sk_buff *skb); |
71 | 68 | ||
72 | #endif | 69 | #endif |
73 | |||
74 | /* | ||
75 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
76 | * Emacs will notice this stuff at the end of the file and automatically | ||
77 | * adjust the settings for this buffer only. This must remain at the end | ||
78 | * of the file. | ||
79 | * --------------------------------------------------------------------------- | ||
80 | * Local variables: | ||
81 | * c-file-style: "linux" | ||
82 | * End: | ||
83 | */ | ||
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h index 47ef7cb49a..19f207cd70 100644 --- a/arch/um/include/net_user.h +++ b/arch/um/include/net_user.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -25,9 +25,8 @@ struct net_user_info { | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | extern void ether_user_init(void *data, void *dev); | 27 | extern void ether_user_init(void *data, void *dev); |
28 | extern void dev_ip_addr(void *d, unsigned char *bin_buf); | 28 | extern void iter_addresses(void *d, void (*cb)(unsigned char *, |
29 | extern void iter_addresses(void *d, void (*cb)(unsigned char *, | 29 | unsigned char *, void *), |
30 | unsigned char *, void *), | ||
31 | void *arg); | 30 | void *arg); |
32 | 31 | ||
33 | extern void *get_output_buffer(int *len_out); | 32 | extern void *get_output_buffer(int *len_out); |
@@ -52,14 +51,3 @@ extern char *split_if_spec(char *str, ...); | |||
52 | extern int dev_netmask(void *d, void *m); | 51 | extern int dev_netmask(void *d, void *m); |
53 | 52 | ||
54 | #endif | 53 | #endif |
55 | |||
56 | /* | ||
57 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
58 | * Emacs will notice this stuff at the end of the file and automatically | ||
59 | * adjust the settings for this buffer only. This must remain at the end | ||
60 | * of the file. | ||
61 | * --------------------------------------------------------------------------- | ||
62 | * Local variables: | ||
63 | * c-file-style: "linux" | ||
64 | * End: | ||
65 | */ | ||
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index d21ebad666..8b7f2cdedf 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c | |||
@@ -16,9 +16,13 @@ int uml_exitcode = 0; | |||
16 | static int read_proc_exitcode(char *page, char **start, off_t off, | 16 | static int read_proc_exitcode(char *page, char **start, off_t off, |
17 | int count, int *eof, void *data) | 17 | int count, int *eof, void *data) |
18 | { | 18 | { |
19 | int len; | 19 | int len, val; |
20 | 20 | ||
21 | len = sprintf(page, "%d\n", uml_exitcode); | 21 | /* Save uml_exitcode in a local so that we don't need to guarantee |
22 | * that sprintf accesses it atomically. | ||
23 | */ | ||
24 | val = uml_exitcode; | ||
25 | len = sprintf(page, "%d\n", val); | ||
22 | len -= off; | 26 | len -= off; |
23 | if(len <= off+count) *eof = 1; | 27 | if(len <= off+count) *eof = 1; |
24 | *start = page + off; | 28 | *start = page + off; |
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 79c22707a6..4cd2ff546e 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c | |||
@@ -61,8 +61,10 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, | |||
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); | 63 | *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); |
64 | *pte = pte_mkexec(*pte); | 64 | /* This is wrong for the code page, but it doesn't matter since the |
65 | *pte = pte_wrprotect(*pte); | 65 | * stub is mapped by hand with the correct permissions. |
66 | */ | ||
67 | *pte = pte_mkwrite(*pte); | ||
66 | return(0); | 68 | return(0); |
67 | 69 | ||
68 | out_pmd: | 70 | out_pmd: |
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c deleted file mode 100644 index 0f3d5d084d..0000000000 --- a/arch/um/kernel/skas/process_kern.c +++ /dev/null | |||
@@ -1,484 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Copyright 2003 PathScale, Inc. | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/config.h" | ||
8 | #include "linux/kernel.h" | ||
9 | #include "linux/sched.h" | ||
10 | #include "linux/interrupt.h" | ||
11 | #include "linux/string.h" | ||
12 | #include "linux/mm.h" | ||
13 | #include "linux/slab.h" | ||
14 | #include "linux/utsname.h" | ||
15 | #include "linux/fs.h" | ||
16 | #include "linux/utime.h" | ||
17 | #include "linux/smp_lock.h" | ||
18 | #include "linux/module.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" | ||
34 | #include "asm/uaccess.h" | ||
35 | #include "asm/user.h" | ||
36 | #include "user_util.h" | ||
37 | #include "kern_util.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" | ||
47 | #include "mode.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 | } | ||
105 | |||
106 | void set_current(void *t) | ||
107 | { | ||
108 | struct task_struct *task = t; | ||
109 | |||
110 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) | ||
111 | { external_pid(task), task }); | ||
112 | } | ||
113 | |||
114 | void *_switch_to(void *prev, void *next, void *last) | ||
115 | { | ||
116 | struct task_struct *from = prev; | ||
117 | struct task_struct *to= next; | ||
118 | |||
119 | to->thread.prev_sched = from; | ||
120 | set_current(to); | ||
121 | |||
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); | ||
132 | |||
133 | } | ||
134 | |||
135 | void interrupt_end(void) | ||
136 | { | ||
137 | if(need_resched()) schedule(); | ||
138 | if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); | ||
139 | } | ||
140 | |||
141 | void release_thread(struct task_struct *task) | ||
142 | { | ||
143 | CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); | ||
144 | } | ||
145 | |||
146 | void exit_thread(void) | ||
147 | { | ||
148 | unprotect_stack((unsigned long) current_thread); | ||
149 | } | ||
150 | |||
151 | void *get_current(void) | ||
152 | { | ||
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; | ||
161 | |||
162 | p->thread = (struct thread_struct) INIT_THREAD; | ||
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? | ||
173 | */ | ||
174 | if (clone_flags & CLONE_SETTLS) | ||
175 | ret = arch_copy_tls(p); | ||
176 | |||
177 | out: | ||
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); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | void cpu_idle(void) | ||
220 | { | ||
221 | CHOOSE_MODE(init_idle_tt(), init_idle_skas()); | ||
222 | } | ||
223 | |||
224 | int page_size(void) | ||
225 | { | ||
226 | return(PAGE_SIZE); | ||
227 | } | ||
228 | |||
229 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | ||
230 | pte_t *pte_out) | ||
231 | { | ||
232 | pgd_t *pgd; | ||
233 | pud_t *pud; | ||
234 | pmd_t *pmd; | ||
235 | pte_t *pte; | ||
236 | pte_t ptent; | ||
237 | |||
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 | } | ||
261 | |||
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 | } | ||
271 | |||
272 | void force_sigbus(void) | ||
273 | { | ||
274 | printk(KERN_ERR "Killing pid %d because of a lack of memory\n", | ||
275 | current->pid); | ||
276 | lock_kernel(); | ||
277 | sigaddset(¤t->pending.signal, SIGBUS); | ||
278 | recalc_sigpending(); | ||
279 | current->flags |= PF_SIGNALED; | ||
280 | do_exit(SIGBUS | 0x80); | ||
281 | } | ||
282 | |||
283 | void dump_thread(struct pt_regs *regs, struct user *u) | ||
284 | { | ||
285 | } | ||
286 | |||
287 | void enable_hlt(void) | ||
288 | { | ||
289 | panic("enable_hlt"); | ||
290 | } | ||
291 | |||
292 | EXPORT_SYMBOL(enable_hlt); | ||
293 | |||
294 | void disable_hlt(void) | ||
295 | { | ||
296 | panic("disable_hlt"); | ||
297 | } | ||
298 | |||
299 | EXPORT_SYMBOL(disable_hlt); | ||
300 | |||
301 | void *um_kmalloc(int size) | ||
302 | { | ||
303 | return kmalloc(size, GFP_KERNEL); | ||
304 | } | ||
305 | |||
306 | void *um_kmalloc_atomic(int size) | ||
307 | { | ||
308 | return kmalloc(size, GFP_ATOMIC); | ||
309 | } | ||
310 | |||
311 | void *um_vmalloc(int size) | ||
312 | { | ||
313 | return vmalloc(size); | ||
314 | } | ||
315 | |||
316 | void *um_vmalloc_atomic(int size) | ||
317 | { | ||
318 | return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); | ||
319 | } | ||
320 | |||
321 | int __cant_sleep(void) { | ||
322 | return in_atomic() || irqs_disabled() || in_interrupt(); | ||
323 | /* Is in_interrupt() really needed? */ | ||
324 | } | ||
325 | |||
326 | unsigned long get_fault_addr(void) | ||
327 | { | ||
328 | return((unsigned long) current->thread.fault_addr); | ||
329 | } | ||
330 | |||
331 | EXPORT_SYMBOL(get_fault_addr); | ||
332 | |||
333 | void not_implemented(void) | ||
334 | { | ||
335 | printk(KERN_DEBUG "Something isn't implemented in here\n"); | ||
336 | } | ||
337 | |||
338 | EXPORT_SYMBOL(not_implemented); | ||
339 | |||
340 | int user_context(unsigned long sp) | ||
341 | { | ||
342 | unsigned long stack; | ||
343 | |||
344 | stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); | ||
345 | return(stack != (unsigned long) current_thread); | ||
346 | } | ||
347 | |||
348 | extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; | ||
349 | |||
350 | void do_uml_exitcalls(void) | ||
351 | { | ||
352 | exitcall_t *call; | ||
353 | |||
354 | call = &__uml_exitcall_end; | ||
355 | while (--call >= &__uml_exitcall_begin) | ||
356 | (*call)(); | ||
357 | } | ||
358 | |||
359 | char *uml_strdup(char *string) | ||
360 | { | ||
361 | return kstrdup(string, GFP_KERNEL); | ||
362 | } | ||
363 | |||
364 | int copy_to_user_proc(void __user *to, void *from, int size) | ||
365 | { | ||
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 | } | ||
378 | |||
379 | int strlen_user_proc(char __user *str) | ||
380 | { | ||
381 | return(strlen_user(str)); | ||
382 | } | ||
383 | |||
384 | int smp_sigio_handler(void) | ||
385 | { | ||
386 | #ifdef CONFIG_SMP | ||
387 | int cpu = current_thread->cpu; | ||
388 | IPI_handler(cpu); | ||
389 | if(cpu != 0) | ||
390 | return(1); | ||
391 | #endif | ||
392 | return(0); | ||
393 | } | ||
394 | |||
395 | int cpu(void) | ||
396 | { | ||
397 | return(current_thread->cpu); | ||
398 | } | ||
399 | |||
400 | static atomic_t using_sysemu = ATOMIC_INIT(0); | ||
401 | int sysemu_supported; | ||
402 | |||
403 | void set_using_sysemu(int value) | ||
404 | { | ||
405 | if (value > sysemu_supported) | ||
406 | return; | ||
407 | atomic_set(&using_sysemu, value); | ||
408 | } | ||
409 | |||
410 | int get_using_sysemu(void) | ||
411 | { | ||
412 | return atomic_read(&using_sysemu); | ||
413 | } | ||
414 | |||
415 | static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) | ||
416 | { | ||
417 | if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ | ||
418 | *eof = 1; | ||
419 | |||
420 | return strlen(buf); | ||
421 | } | ||
422 | |||
423 | static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data) | ||
424 | { | ||
425 | char tmp[2]; | ||
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*/ | ||
433 | } | ||
434 | |||
435 | int __init make_proc_sysemu(void) | ||
436 | { | ||
437 | struct proc_dir_entry *ent; | ||
438 | if (!sysemu_supported) | ||
439 | return 0; | ||
440 | |||
441 | ent = create_proc_entry("sysemu", 0600, &proc_root); | ||
442 | |||
443 | if (ent == NULL) | ||
444 | { | ||
445 | printk(KERN_WARNING "Failed to register /proc/sysemu\n"); | ||
446 | return(0); | ||
447 | } | ||
448 | |||
449 | ent->read_proc = proc_read_sysemu; | ||
450 | ent->write_proc = proc_write_sysemu; | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | late_initcall(make_proc_sysemu); | ||
456 | |||
457 | int singlestepping(void * t) | ||
458 | { | ||
459 | struct task_struct *task = t ? t : current; | ||
460 | |||
461 | if ( ! (task->ptrace & PT_DTRACE) ) | ||
462 | return(0); | ||
463 | |||
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; | ||
483 | } | ||
484 | #endif | ||
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 820affbf3e..a92965f8f9 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c | |||
@@ -93,7 +93,7 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) | |||
93 | 93 | ||
94 | write_seqlock_irqsave(&xtime_lock, flags); | 94 | write_seqlock_irqsave(&xtime_lock, flags); |
95 | 95 | ||
96 | do_timer(regs); | 96 | do_timer(1); |
97 | 97 | ||
98 | nsecs = get_time(); | 98 | nsecs = get_time(); |
99 | xtime.tv_sec = nsecs / NSEC_PER_SEC; | 99 | xtime.tv_sec = nsecs / NSEC_PER_SEC; |
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 61a23fff43..c7b195c7e5 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -120,7 +120,7 @@ out_nosemaphore: | |||
120 | * us unable to handle the page fault gracefully. | 120 | * us unable to handle the page fault gracefully. |
121 | */ | 121 | */ |
122 | out_of_memory: | 122 | out_of_memory: |
123 | if (current->pid == 1) { | 123 | if (is_init(current)) { |
124 | up_read(&mm->mmap_sem); | 124 | up_read(&mm->mmap_sem); |
125 | yield(); | 125 | yield(); |
126 | down_read(&mm->mmap_sem); | 126 | down_read(&mm->mmap_sem); |
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index b170b4704d..4203681e50 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c | |||
@@ -132,6 +132,9 @@ err: | |||
132 | else if(found < 0) | 132 | else if(found < 0) |
133 | printf("read returned errno %d\n", -found); | 133 | printf("read returned errno %d\n", -found); |
134 | 134 | ||
135 | out: | ||
136 | close(fd); | ||
137 | |||
135 | return; | 138 | return; |
136 | 139 | ||
137 | found: | 140 | found: |
@@ -141,11 +144,12 @@ found: | |||
141 | 144 | ||
142 | if(strncmp(buf, "tmpfs", strlen("tmpfs"))){ | 145 | if(strncmp(buf, "tmpfs", strlen("tmpfs"))){ |
143 | printf("not tmpfs\n"); | 146 | printf("not tmpfs\n"); |
144 | return; | 147 | goto out; |
145 | } | 148 | } |
146 | 149 | ||
147 | printf("OK\n"); | 150 | printf("OK\n"); |
148 | default_tmpdir = "/dev/shm"; | 151 | default_tmpdir = "/dev/shm"; |
152 | goto out; | ||
149 | } | 153 | } |
150 | 154 | ||
151 | /* | 155 | /* |