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 9558a7cf34d..11154b6773e 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -4,10 +4,13 @@ core-y += arch/um/sys-x86_64/ START := 0x60000000 +_extra_flags_ = -fno-builtin -m64 -mcmodel=kernel + #We #undef __x86_64__ for kernelspace, not for userspace where #it's needed for headers to work! -CFLAGS += -U__$(SUBARCH)__ -fno-builtin -m64 -USER_CFLAGS += -fno-builtin -m64 +CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_) +USER_CFLAGS += $(_extra_flags_) + CHECKFLAGS += -m64 AFLAGS += -m64 LDFLAGS += -m elf_x86_64 diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index e82764f75e7..3576b3cc505 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) "UML\n"); } -static struct chan_ops not_configged_ops = { +static const struct chan_ops not_configged_ops = { .init = not_configged_init, .open = not_configged_open, .close = not_configged_close, @@ -373,7 +373,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) } int console_open_chan(struct line *line, struct console *co, - struct chan_opts *opts) + const struct chan_opts *opts) { int err; @@ -494,10 +494,10 @@ int chan_config_string(struct list_head *chans, char *str, int size, struct chan_type { char *key; - struct chan_ops *ops; + const struct chan_ops *ops; }; -static struct chan_type chan_table[] = { +static const struct chan_type chan_table[] = { { "fd", &fd_ops }, #ifdef CONFIG_NULL_CHAN @@ -534,10 +534,10 @@ static struct chan_type chan_table[] = { }; static struct chan *parse_chan(struct line *line, char *str, int device, - struct chan_opts *opts) + const struct chan_opts *opts) { - struct chan_type *entry; - struct chan_ops *ops; + const struct chan_type *entry; + const struct chan_ops *ops; struct chan *chan; void *data; int i; @@ -582,7 +582,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device, } int parse_chan_pair(char *str, struct line *line, int device, - struct chan_opts *opts) + const struct chan_opts *opts) { struct list_head *chans = &line->chan_list; struct chan *new, *chan; diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h index 7326c42f7ef..3bc3cf6b94a 100644 --- a/arch/um/drivers/daemon.h +++ b/arch/um/drivers/daemon.h @@ -18,7 +18,7 @@ struct daemon_data { void *dev; }; -extern struct net_user_info daemon_user_info; +extern const struct net_user_info daemon_user_info; extern int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri); diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index 53d09ed78b4..824386974f8 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, (struct daemon_data *) &lp->user)); } -static struct net_kern_info daemon_kern_info = { +static const struct net_kern_info daemon_kern_info = { .init = daemon_init, .protocol = eth_protocol, .read = daemon_read, diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index c944265955e..77954ea7704 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) return(mtu); } -struct net_user_info daemon_user_info = { +const struct net_user_info daemon_user_info = { .init = daemon_user_init, .open = daemon_open, .close = NULL, diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index c41f75e4acb..108b7dafbd0 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -20,7 +20,7 @@ struct fd_chan { char str[sizeof("1234567890\0")]; }; -static void *fd_init(char *str, int device, struct chan_opts *opts) +static void *fd_init(char *str, int device, const struct chan_opts *opts) { struct fd_chan *data; char *end; @@ -77,7 +77,7 @@ static void fd_close(int fd, void *d) } } -struct chan_ops fd_ops = { +const struct chan_ops fd_ops = { .type = "fd", .init = fd_init, .open = fd_open, diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 37232f908cd..d247ef45c37 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) /* kernel module operations */ -static struct file_operations hostaudio_fops = { +static const struct file_operations hostaudio_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = hostaudio_read, @@ -292,7 +292,7 @@ static struct file_operations hostaudio_fops = { .release = hostaudio_release, }; -static struct file_operations hostmixer_fops = { +static const struct file_operations hostmixer_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .ioctl = hostmixer_ioctl_mixdev, diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index ebebaabb78a..563ce7690a1 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) /* nothing */ } -static struct { +static const struct { int cmd; char *level; char *name; @@ -405,7 +405,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data, int line_setup_irq(int fd, int input, int output, struct line *line, void *data) { - struct line_driver *driver = line->driver; + const struct line_driver *driver = line->driver; int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM; if (input) @@ -558,7 +558,7 @@ int line_setup(struct line *lines, unsigned int num, char *init) } int line_config(struct line *lines, unsigned int num, char *str, - struct chan_opts *opts) + const struct chan_opts *opts) { struct line *line; char *new; diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h index a2c6db24345..bc56af9d3e5 100644 --- a/arch/um/drivers/mcast.h +++ b/arch/um/drivers/mcast.h @@ -13,7 +13,7 @@ struct mcast_data { void *dev; }; -extern struct net_user_info mcast_user_info; +extern const struct net_user_info mcast_user_info; extern int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri); diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c index 3a7af18cf94..c090fbd464e 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, (struct mcast_data *) &lp->user); } -static struct net_kern_info mcast_kern_info = { +static const struct net_kern_info mcast_kern_info = { .init = mcast_init, .protocol = eth_protocol, .read = mcast_read, diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index afe85bfa66e..4d2bd39a85b 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) return(mtu); } -struct net_user_info mcast_user_info = { +const struct net_user_info mcast_user_info = { .init = mcast_user_init, .open = mcast_open, .close = mcast_close, diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 022f67bb687..9a3b5daf625 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) return 0; } -static struct file_operations mmapper_fops = { +static const struct file_operations mmapper_fops = { .owner = THIS_MODULE, .read = mmapper_read, .write = mmapper_write, @@ -95,7 +95,7 @@ static struct file_operations mmapper_fops = { .release = mmapper_release, }; -static struct miscdevice mmapper_dev = { +static const struct miscdevice mmapper_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "mmapper", .fops = &mmapper_fops diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 4a7966b2193..664c2e2fb82 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) struct uml_net_private *lp = dev->priv; int err; - spin_lock(&lp->lock); - if(lp->fd >= 0){ err = -ENXIO; goto out; @@ -149,8 +147,6 @@ static int uml_net_open(struct net_device *dev) */ while((err = uml_net_rx(dev)) > 0) ; - spin_unlock(&lp->lock); - spin_lock(&opened_lock); list_add(&lp->list, &opened); spin_unlock(&opened_lock); @@ -160,7 +156,6 @@ out_close: if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; out: - spin_unlock(&lp->lock); return err; } @@ -169,15 +164,12 @@ static int uml_net_close(struct net_device *dev) struct uml_net_private *lp = dev->priv; netif_stop_queue(dev); - spin_lock(&lp->lock); free_irq(dev->irq, dev); if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; - spin_unlock(&lp->lock); - spin_lock(&opened_lock); list_del(&lp->list); spin_unlock(&opened_lock); @@ -246,9 +238,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr) struct uml_net_private *lp = dev->priv; struct sockaddr *hwaddr = addr; - spin_lock(&lp->lock); + spin_lock_irq(&lp->lock); set_ether_mac(dev, hwaddr->sa_data); - spin_unlock(&lp->lock); + spin_unlock_irq(&lp->lock); return(0); } @@ -258,7 +250,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu) struct uml_net_private *lp = dev->priv; int err = 0; - spin_lock(&lp->lock); + spin_lock_irq(&lp->lock); new_mtu = (*lp->set_mtu)(new_mtu, &lp->user); if(new_mtu < 0){ @@ -269,7 +261,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu) dev->mtu = new_mtu; out: - spin_unlock(&lp->lock); + spin_unlock_irq(&lp->lock); return err; } @@ -569,12 +561,13 @@ static int eth_setup(char *str) int n, err; err = eth_parse(str, &n, &str); - if(err) return(1); + if(err) + return 1; - new = alloc_bootmem(sizeof(new)); + new = alloc_bootmem(sizeof(*new)); if (new == NULL){ printk("eth_init : alloc_bootmem failed\n"); - return(1); + return 1; } INIT_LIST_HEAD(&new->list); @@ -582,7 +575,7 @@ static int eth_setup(char *str) new->init = str; list_add_tail(&new->list, ð_cmd_line); - return(1); + return 1; } __setup("eth", eth_setup); diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c index 14cc5f78398..3683ed44315 100644 --- a/arch/um/drivers/null.c +++ b/arch/um/drivers/null.c @@ -10,7 +10,7 @@ static int null_chan; -static void *null_init(char *str, int device, struct chan_opts *opts) +static void *null_init(char *str, int device, const struct chan_opts *opts) { return(&null_chan); } @@ -31,7 +31,7 @@ static void null_free(void *data) { } -struct chan_ops null_ops = { +const struct chan_ops null_ops = { .type = "null", .init = null_init, .open = null_open, diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c index 4c767c7adb9..6e1ef855828 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) return(-EPERM); } -static struct net_kern_info pcap_kern_info = { +static const struct net_kern_info pcap_kern_info = { .init = pcap_init, .protocol = eth_protocol, .read = pcap_read, diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c index edfcb29273e..2ef641ded96 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) return(hdata.len); } -struct net_user_info pcap_user_info = { +const struct net_user_info pcap_user_info = { .init = pcap_user_init, .open = pcap_open, .close = NULL, diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index c43e8bb3250..f2e8fc42ecc 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -27,7 +27,7 @@ struct port_chan { char dev[sizeof("32768\0")]; }; -static void *port_init(char *str, int device, struct chan_opts *opts) +static void *port_init(char *str, int device, const struct chan_opts *opts) { struct port_chan *data; void *kern_data; @@ -100,7 +100,7 @@ static void port_close(int fd, void *d) os_close_file(fd); } -struct chan_ops port_ops = { +const struct chan_ops port_ops = { .type = "port", .init = port_init, .open = port_open, diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 1c555c38de4..abec620e838 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -22,7 +22,7 @@ struct pty_chan { char dev_name[sizeof("/dev/pts/0123456\0")]; }; -static void *pty_chan_init(char *str, int device, struct chan_opts *opts) +static void *pty_chan_init(char *str, int device, const struct chan_opts *opts) { struct pty_chan *data; @@ -118,7 +118,7 @@ static int pty_open(int input, int output, int primary, void *d, return(fd); } -struct chan_ops pty_ops = { +const struct chan_ops pty_ops = { .type = "pty", .init = pty_chan_init, .open = pty_open, @@ -131,7 +131,7 @@ struct chan_ops pty_ops = { .winch = 0, }; -struct chan_ops pts_ops = { +const struct chan_ops pts_ops = { .type = "pts", .init = pty_chan_init, .open = pts_open, diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index ba471f5864a..ae9909415b9 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, return ret; } -static struct file_operations rng_chrdev_ops = { +static const struct file_operations rng_chrdev_ops = { .owner = THIS_MODULE, .open = rng_dev_open, .read = rng_dev_read, diff --git a/arch/um/drivers/slip.h b/arch/um/drivers/slip.h index bb0dab41c2e..c64f8c61d27 100644 --- a/arch/um/drivers/slip.h +++ b/arch/um/drivers/slip.h @@ -12,7 +12,7 @@ struct slip_data { struct slip_proto slip; }; -extern struct net_user_info slip_user_info; +extern const struct net_user_info slip_user_info; extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri); 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 163ee0d5f75..ccea2d7885e 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, (struct slip_data *) &lp->user)); } -struct net_kern_info slip_kern_info = { +const struct net_kern_info slip_kern_info = { .init = slip_init, .protocol = slip_protocol, .read = slip_read, diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 89fbec185cc..8460285c69a 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, close_addr(addr, netmask, pri->name); } -struct net_user_info slip_user_info = { +const struct net_user_info slip_user_info = { .init = slip_user_init, .open = slip_open, .close = slip_close, diff --git a/arch/um/drivers/slirp.h b/arch/um/drivers/slirp.h index 6cf88ab580c..89ccf83b757 100644 --- a/arch/um/drivers/slirp.h +++ b/arch/um/drivers/slirp.h @@ -24,7 +24,7 @@ struct slirp_data { struct slip_proto slip; }; -extern struct net_user_info slirp_user_info; +extern const struct net_user_info slirp_user_info; extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri); 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 95e50c943e1..ae322e1c8a8 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, (struct slirp_data *) &lp->user)); } -struct net_kern_info slirp_kern_info = { +const struct net_kern_info slirp_kern_info = { .init = slirp_init, .protocol = slirp_protocol, .read = slirp_read, diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index 33c5f6e625e..ce5e85d1de3 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) return(mtu); } -struct net_user_info slirp_user_info = { +const struct net_user_info slirp_user_info = { .init = slirp_user_init, .open = slirp_open, .close = slirp_close, diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 6dafd6fbfda..6f13e7c71a8 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -23,7 +23,7 @@ #include "irq_user.h" #include "mconsole_kern.h" -static int ssl_version = 1; +static const int ssl_version = 1; /* Referenced only by tty_driver below - presumably it's locked correctly * by the tty driver. @@ -123,7 +123,7 @@ void ssl_hangup(struct tty_struct *tty) } #endif -static struct tty_operations ssl_ops = { +static const struct tty_operations ssl_ops = { .open = ssl_open, .close = line_close, .write = line_write, diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 856f568c268..5e44adb0705 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) static int con_init_done = 0; -static struct tty_operations console_ops = { +static const struct tty_operations console_ops = { .open = con_open, .close = line_close, .write = line_write, diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index 9f70edf5d8e..11de3ac1eb5 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c @@ -18,7 +18,7 @@ struct tty_chan { struct termios tt; }; -static void *tty_chan_init(char *str, int device, struct chan_opts *opts) +static void *tty_chan_init(char *str, int device, const struct chan_opts *opts) { struct tty_chan *data; @@ -62,7 +62,7 @@ static int tty_open(int input, int output, int primary, void *d, return fd; } -struct chan_ops tty_ops = { +const struct chan_ops tty_ops = { .type = "tty", .init = tty_chan_init, .open = tty_open, diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index aaa63666104..386f8b95298 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -31,7 +31,7 @@ struct xterm_chan { }; /* Not static because it's called directly by the tt mode gdb code */ -void *xterm_init(char *str, int device, struct chan_opts *opts) +void *xterm_init(char *str, int device, const struct chan_opts *opts) { struct xterm_chan *data; @@ -194,7 +194,7 @@ static void xterm_free(void *d) free(d); } -struct chan_ops xterm_ops = { +const struct chan_ops xterm_ops = { .type = "xterm", .init = xterm_init, .open = xterm_open, diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h index 1bb5e9d9427..572d286ed2c 100644 --- a/arch/um/include/chan_kern.h +++ b/arch/um/include/chan_kern.h @@ -23,21 +23,21 @@ struct chan { unsigned int opened:1; unsigned int enabled:1; int fd; - struct chan_ops *ops; + const struct chan_ops *ops; void *data; }; extern void chan_interrupt(struct list_head *chans, struct work_struct *task, struct tty_struct *tty, int irq); extern int parse_chan_pair(char *str, struct line *line, int device, - struct chan_opts *opts); + const struct chan_opts *opts); extern int open_chan(struct list_head *chans); extern int write_chan(struct list_head *chans, const char *buf, int len, int write_irq); extern int console_write_chan(struct list_head *chans, const char *buf, int len); extern int console_open_chan(struct line *line, struct console *co, - struct chan_opts *opts); + const struct chan_opts *opts); extern void deactivate_chan(struct list_head *chans, int irq); extern void reactivate_chan(struct list_head *chans, int irq); 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 659bb3cac32..a795547a1db 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 }; struct chan_ops { char *type; - void *(*init)(char *, int, struct chan_opts *); + void *(*init)(char *, int, const struct chan_opts *); int (*open)(int, int, int, void *, char **); void (*close)(int, void *); int (*read)(int, char *, void *); @@ -31,8 +31,8 @@ struct chan_ops { int winch; }; -extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, - xterm_ops; +extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, + tty_ops, xterm_ops; extern void generic_close(int fd, void *unused); 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 89e1dc835a5..59cfa9e0cad 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -21,7 +21,7 @@ struct kern_handlers { kern_hndl timer_handler; }; -extern struct kern_handlers handlinfo_kern; +extern const struct kern_handlers handlinfo_kern; extern int ncpus; extern char *linux_prog; diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 27bf2f6fbc0..642c9a0320f 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -52,7 +52,7 @@ struct line { int sigio; struct work_struct task; - struct line_driver *driver; + const struct line_driver *driver; int have_irq; }; @@ -99,7 +99,7 @@ extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); extern void close_lines(struct line *lines, int nlines); extern int line_config(struct line *lines, unsigned int sizeof_lines, - char *str, struct chan_opts *opts); + char *str, const struct chan_opts *opts); extern int line_id(char **str, int *start_out, int *end_out); extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); 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 f7de6df60dd..769fba43ee0 100644 --- a/arch/um/include/net_kern.h +++ b/arch/um/include/net_kern.h @@ -54,8 +54,8 @@ struct transport { struct list_head list; char *name; int (*setup)(char *, char **, void *); - struct net_user_info *user; - struct net_kern_info *kern; + const struct net_user_info *user; + const struct net_kern_info *kern; int private_size; int setup_size; }; diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 24fb6d8680e..120ca21a513 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -14,6 +14,7 @@ #include "skas/mm_id.h" #include "irq_user.h" #include "sysdep/tls.h" +#include "sysdep/archsetjmp.h" #define OS_TYPE_FILE 1 #define OS_TYPE_DIR 2 @@ -198,7 +199,9 @@ extern long os_ptrace_ldt(long pid, long addr, long data); extern int os_getpid(void); extern int os_getpgrp(void); +#ifdef UML_CONFIG_MODE_TT extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); +#endif extern void init_new_thread_signals(void); extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); @@ -216,7 +219,6 @@ extern void os_flush_stdout(void); */ extern void forward_ipi(int fd, int pid); extern void kill_child_dead(int pid); -extern void stop(void); extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); extern int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed); @@ -307,12 +309,9 @@ extern int copy_context_skas0(unsigned long stack, int pid); extern void userspace(union uml_pt_regs *regs); extern void map_stub_pages(int fd, unsigned long code, unsigned long data, unsigned long stack); -extern void new_thread(void *stack, void **switch_buf_ptr, - void **fork_buf_ptr, void (*handler)(int)); -extern void thread_wait(void *sw, void *fb); -extern void switch_threads(void *me, void *next); -extern int start_idle_thread(void *stack, void *switch_buf_ptr, - void **fork_buf_ptr); +extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); +extern void switch_threads(jmp_buf *me, jmp_buf *you); +extern int start_idle_thread(void *stack, jmp_buf *switch_buf); extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); extern void halt_skas(void); diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index 853b26f148c..e88926b1607 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; extern int skas_needs_stub; extern int user_thread(unsigned long stack, int flags); -extern void new_thread_proc(void *stack, void (*handler)(int sig)); -extern void new_thread_handler(int sig); +extern void new_thread_handler(void); extern void handle_syscall(union uml_pt_regs *regs); extern int new_mm(unsigned long stack); 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 ea1ba3d42ae..11bafab669e 100644 --- a/arch/um/include/sysdep-i386/archsetjmp.h +++ b/arch/um/include/sysdep-i386/archsetjmp.h @@ -16,4 +16,7 @@ struct __jmp_buf { typedef struct __jmp_buf jmp_buf[1]; +#define JB_IP __eip +#define JB_SP __esp + #endif /* _SETJMP_H */ diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h index 454fc60aff6..9a5e1a6ec80 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 { typedef struct __jmp_buf jmp_buf[1]; +#define JB_IP __rip +#define JB_SP __rsp + #endif /* _SETJMP_H */ diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h index 8d353f0feec..617bb9efc93 100644 --- a/arch/um/include/sysdep-x86_64/ptrace.h +++ b/arch/um/include/sysdep-x86_64/ptrace.h @@ -50,6 +50,21 @@ #define HOST_FS 25 #define HOST_GS 26 +/* Also defined in asm/ptrace-x86_64.h, but not in libc headers. So, these + * are already defined for kernel code, but not for userspace code. + */ +#ifndef FS_BASE +/* These aren't defined in ptrace.h, but exist in struct user_regs_struct, + * which is what x86_64 ptrace actually uses. + */ +#define FS_BASE (HOST_FS_BASE * sizeof(long)) +#define GS_BASE (HOST_GS_BASE * sizeof(long)) +#define DS (HOST_DS * sizeof(long)) +#define ES (HOST_ES * sizeof(long)) +#define FS (HOST_FS * sizeof(long)) +#define GS (HOST_GS * sizeof(long)) +#endif + #define REGS_FS_BASE(r) ((r)[HOST_FS_BASE]) #define REGS_GS_BASE(r) ((r)[HOST_GS_BASE]) #define REGS_DS(r) ((r)[HOST_DS]) @@ -89,9 +104,12 @@ union uml_pt_regs { #endif #ifdef UML_CONFIG_MODE_SKAS struct skas_regs { - /* XXX */ - unsigned long regs[27]; - unsigned long fp[65]; + /* x86_64 ptrace uses sizeof(user_regs_struct) as its register + * file size, while i386 uses FRAME_SIZE. Therefore, we need + * to use UM_FRAME_SIZE here instead of HOST_FRAME_SIZE. + */ + unsigned long regs[UM_FRAME_SIZE]; + unsigned long fp[HOST_FP_SIZE]; struct faultinfo faultinfo; long syscall; int is_user; @@ -120,11 +138,16 @@ extern int mode_tt; #define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs)) #define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs)) #define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_FS_BASE(r) \ + __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs)) #define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) +#define UPT_GS_BASE(r) \ + __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs)) #define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) #define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) #define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) #define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) #define UPT_ORIG_RAX(r) \ __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs)) @@ -183,6 +206,13 @@ struct syscall_args { case RBP: val = UPT_RBP(regs); break; \ case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ case CS: val = UPT_CS(regs); break; \ + case SS: val = UPT_SS(regs); break; \ + case FS_BASE: val = UPT_FS_BASE(regs); break; \ + case GS_BASE: val = UPT_GS_BASE(regs); break; \ + case DS: val = UPT_DS(regs); break; \ + case ES: val = UPT_ES(regs); break; \ + case FS : val = UPT_FS (regs); break; \ + case GS: val = UPT_GS(regs); break; \ case EFLAGS: val = UPT_EFLAGS(regs); break; \ default : \ panic("Bad register in UPT_REG : %d\n", reg); \ @@ -214,6 +244,13 @@ struct syscall_args { case RBP: UPT_RBP(regs) = __upt_val; break; \ case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ case CS: UPT_CS(regs) = __upt_val; break; \ + case SS: UPT_SS(regs) = __upt_val; break; \ + case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \ + case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \ + case DS: UPT_DS(regs) = __upt_val; break; \ + case ES: UPT_ES(regs) = __upt_val; break; \ + case FS: UPT_FS(regs) = __upt_val; break; \ + case GS: UPT_GS(regs) = __upt_val; break; \ case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ default : \ 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 a160d9fcc59..8aee45b0743 100644 --- a/arch/um/include/sysdep-x86_64/sc.h +++ b/arch/um/include/sysdep-x86_64/sc.h @@ -35,11 +35,11 @@ #define SC_GS(sc) SC_OFFSET(sc, SC_GS) #define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS) #define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK) +#define SC_SS(sc) SC_OFFSET(sc, SC_SS) #if 0 #define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX) #define SC_DS(sc) SC_OFFSET(sc, SC_DS) #define SC_ES(sc) SC_OFFSET(sc, SC_ES) -#define SC_SS(sc) SC_OFFSET(sc, SC_SS) #endif #endif diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index a2d93065b2d..6fa63a2a89e 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := vmlinux.lds clean-files := obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ - physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \ + physmem.o process.o ptrace.o reboot.o resource.o sigio.o \ signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ um_arch.o umid.o diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c index 2c86e7fdb01..13aa115cd1b 100644 --- a/arch/um/kernel/gmon_syms.c +++ b/arch/um/kernel/gmon_syms.c @@ -5,7 +5,7 @@ #include "linux/module.h" -extern void __bb_init_func(void *); +extern void __bb_init_func(void *) __attribute__((weak)); EXPORT_SYMBOL(__bb_init_func); /* This is defined (and referred to in profiling stub code) only by some GCC @@ -21,14 +21,3 @@ EXPORT_SYMBOL(__gcov_init); extern void __gcov_merge_add(void *) __attribute__((weak)); EXPORT_SYMBOL(__gcov_merge_add); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index c97045d6d89..f030e44262b 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -21,7 +21,6 @@ #include "mem_user.h" #include "os.h" -EXPORT_SYMBOL(stop); EXPORT_SYMBOL(uml_physmem); EXPORT_SYMBOL(set_signals); EXPORT_SYMBOL(get_signals); @@ -41,12 +40,14 @@ EXPORT_SYMBOL(handle_page_fault); EXPORT_SYMBOL(find_iomem); #ifdef CONFIG_MODE_TT +EXPORT_SYMBOL(stop); EXPORT_SYMBOL(strncpy_from_user_tt); EXPORT_SYMBOL(copy_from_user_tt); EXPORT_SYMBOL(copy_to_user_tt); #endif #ifdef CONFIG_MODE_SKAS +EXPORT_SYMBOL(strnlen_user_skas); EXPORT_SYMBOL(strncpy_from_user_skas); EXPORT_SYMBOL(copy_to_user_skas); EXPORT_SYMBOL(copy_from_user_skas); diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 93121c6d26e..c95855ba6ab 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -226,7 +226,8 @@ void paging_init(void) for(i = 0; i < ARRAY_SIZE(zones_size); i++) zones_size[i] = 0; - zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); + zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) - + (uml_physmem >> PAGE_SHIFT); #ifdef CONFIG_HIGHMEM zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; #endif diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process.c index 537895d68ad..fe6c64abda5 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process.c @@ -1,10 +1,9 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ -#include "linux/config.h" #include "linux/kernel.h" #include "linux/sched.h" #include "linux/interrupt.h" @@ -113,11 +112,11 @@ void set_current(void *t) void *_switch_to(void *prev, void *next, void *last) { - struct task_struct *from = prev; - struct task_struct *to= next; + struct task_struct *from = prev; + struct task_struct *to= next; - to->thread.prev_sched = from; - set_current(to); + to->thread.prev_sched = from; + set_current(to); do { current->thread.saved_task = NULL ; @@ -128,7 +127,7 @@ void *_switch_to(void *prev, void *next, void *last) prev= current; } while(current->thread.saved_task); - return(current->thread.prev_sched); + return(current->thread.prev_sched); } @@ -142,19 +141,19 @@ void release_thread(struct task_struct *task) { CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); } - + void exit_thread(void) { unprotect_stack((unsigned long) current_thread); } - + void *get_current(void) { return(current); } int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct * p, + unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { int ret; @@ -183,11 +182,11 @@ void initial_thread_cb(void (*proc)(void *), void *arg) int save_kmalloc_ok = kmalloc_ok; kmalloc_ok = 0; - CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, + CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, arg); kmalloc_ok = save_kmalloc_ok; } - + unsigned long stack_sp(unsigned long page) { return(page + PAGE_SIZE - sizeof(void *)); @@ -211,7 +210,7 @@ void default_idle(void) */ if(need_resched()) schedule(); - + idle_sleep(10); } } @@ -226,7 +225,7 @@ int page_size(void) return(PAGE_SIZE); } -void *um_virt_to_phys(struct task_struct *task, unsigned long addr, +void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte_out) { pgd_t *pgd; @@ -235,7 +234,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte; pte_t ptent; - if(task->mm == NULL) + if(task->mm == NULL) return(ERR_PTR(-EINVAL)); pgd = pgd_offset(task->mm, addr); if(!pgd_present(*pgd)) @@ -246,7 +245,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, return(ERR_PTR(-EINVAL)); pmd = pmd_offset(pud, addr); - if(!pmd_present(*pmd)) + if(!pmd_present(*pmd)) return(ERR_PTR(-EINVAL)); pte = pte_offset_kernel(pmd, addr); @@ -271,7 +270,7 @@ char *current_cmd(void) void force_sigbus(void) { - printk(KERN_ERR "Killing pid %d because of a lack of memory\n", + printk(KERN_ERR "Killing pid %d because of a lack of memory\n", current->pid); lock_kernel(); sigaddset(¤t->pending.signal, SIGBUS); diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index ea3a8e409a6..3e3fa7e7e3c 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -3,8 +3,7 @@ # Licensed under the GPL # -obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \ - syscall.o tlb.o uaccess.o +obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o # clone.o is in the stub, so it can't be built with profiling # 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 00000000000..54b79595137 --- /dev/null +++ b/arch/um/kernel/skas/exec.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "asm/current.h" +#include "asm/page.h" +#include "asm/signal.h" +#include "asm/ptrace.h" +#include "asm/uaccess.h" +#include "asm/mmu_context.h" +#include "tlb.h" +#include "skas.h" +#include "um_mmu.h" +#include "os.h" + +void flush_thread_skas(void) +{ + force_flush_all(); + switch_mm_skas(¤t->mm->context.skas.id); +} + +void start_thread_skas(struct pt_regs *regs, unsigned long eip, + unsigned long esp) +{ + set_fs(USER_DS); + PT_REGS_IP(regs) = eip; + PT_REGS_SP(regs) = esp; +} diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c deleted file mode 100644 index 77ed7bbab21..00000000000 --- a/arch/um/kernel/skas/exec_kern.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/kernel.h" -#include "asm/current.h" -#include "asm/page.h" -#include "asm/signal.h" -#include "asm/ptrace.h" -#include "asm/uaccess.h" -#include "asm/mmu_context.h" -#include "tlb.h" -#include "skas.h" -#include "um_mmu.h" -#include "os.h" - -void flush_thread_skas(void) -{ - force_flush_all(); - switch_mm_skas(¤t->mm->context.skas.id); -} - -void start_thread_skas(struct pt_regs *regs, unsigned long eip, - unsigned long esp) -{ - set_fs(USER_DS); - PT_REGS_IP(regs) = eip; - PT_REGS_SP(regs) = esp; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c new file mode 100644 index 00000000000..ae4fa71d3b8 --- /dev/null +++ b/arch/um/kernel/skas/process.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/sched.h" +#include "linux/slab.h" +#include "linux/ptrace.h" +#include "linux/proc_fs.h" +#include "linux/file.h" +#include "linux/errno.h" +#include "linux/init.h" +#include "asm/uaccess.h" +#include "asm/atomic.h" +#include "kern_util.h" +#include "skas.h" +#include "os.h" +#include "user_util.h" +#include "tlb.h" +#include "kern.h" +#include "mode.h" +#include "registers.h" + +void switch_to_skas(void *prev, void *next) +{ + struct task_struct *from, *to; + + from = prev; + to = next; + + /* XXX need to check runqueues[cpu].idle */ + if(current->pid == 0) + switch_timers(0); + + switch_threads(&from->thread.mode.skas.switch_buf, + &to->thread.mode.skas.switch_buf); + + arch_switch_to_skas(current->thread.prev_sched, current); + + if(current->pid == 0) + switch_timers(1); +} + +extern void schedule_tail(struct task_struct *prev); + +/* This is called magically, by its address being stuffed in a jmp_buf + * and being longjmp-d to. + */ +void new_thread_handler(void) +{ + int (*fn)(void *), n; + void *arg; + + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + + fn = current->thread.request.u.thread.proc; + arg = current->thread.request.u.thread.arg; + + /* The return value is 1 if the kernel thread execs a process, + * 0 if it just exits + */ + n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); + if(n == 1){ + /* Handle any immediate reschedules or signals */ + interrupt_end(); + userspace(¤t->thread.regs.regs); + } + else do_exit(0); +} + +void release_thread_skas(struct task_struct *task) +{ +} + +/* Called magically, see new_thread_handler above */ +void fork_handler(void) +{ + force_flush_all(); + if(current->thread.prev_sched == NULL) + panic("blech"); + + schedule_tail(current->thread.prev_sched); + + /* XXX: if interrupt_end() calls schedule, this call to + * arch_switch_to_skas isn't needed. We could want to apply this to + * improve performance. -bb */ + arch_switch_to_skas(current->thread.prev_sched, current); + + current->thread.prev_sched = NULL; + +/* Handle any immediate reschedules or signals */ + interrupt_end(); + + userspace(¤t->thread.regs.regs); +} + +int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, + unsigned long stack_top, struct task_struct * p, + struct pt_regs *regs) +{ + void (*handler)(void); + + if(current->thread.forking){ + memcpy(&p->thread.regs.regs.skas, ®s->regs.skas, + sizeof(p->thread.regs.regs.skas)); + REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); + if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; + + handler = fork_handler; + + arch_copy_thread(¤t->thread.arch, &p->thread.arch); + } + else { + init_thread_registers(&p->thread.regs.regs); + p->thread.request.u.thread = current->thread.request.u.thread; + handler = new_thread_handler; + } + + new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, + handler); + return(0); +} + +int new_mm(unsigned long stack) +{ + int fd; + + fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); + if(fd < 0) + return(fd); + + if(skas_needs_stub) + map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); + + return(fd); +} + +void init_idle_skas(void) +{ + cpu_tasks[current_thread->cpu].pid = os_getpid(); + default_idle(); +} + +extern void start_kernel(void); + +static int start_kernel_proc(void *unused) +{ + int pid; + + block_signals(); + pid = os_getpid(); + + cpu_tasks[0].pid = pid; + cpu_tasks[0].task = current; +#ifdef CONFIG_SMP + cpu_online_map = cpumask_of_cpu(0); +#endif + start_kernel(); + return(0); +} + +extern int userspace_pid[]; + +int start_uml_skas(void) +{ + if(proc_mm) + userspace_pid[0] = start_userspace(0); + + init_new_thread_signals(); + + init_task.thread.request.u.thread.proc = start_kernel_proc; + init_task.thread.request.u.thread.arg = NULL; + return(start_idle_thread(task_stack_page(&init_task), + &init_task.thread.mode.skas.switch_buf)); +} + +int external_pid_skas(struct task_struct *task) +{ +#warning Need to look up userspace_pid by cpu + return(userspace_pid[0]); +} + +int thread_pid_skas(struct task_struct *task) +{ +#warning Need to look up userspace_pid by cpu + return(userspace_pid[0]); +} + +void kill_off_processes_skas(void) +{ + if(proc_mm) +#warning need to loop over userspace_pids in kill_off_processes_skas + os_kill_ptraced_process(userspace_pid[0], 1); + else { + struct task_struct *p; + int pid, me; + + me = os_getpid(); + for_each_process(p){ + if(p->mm == NULL) + continue; + + pid = p->mm->context.skas.id.u.pid; + os_kill_ptraced_process(pid, 1); + } + } +} + +unsigned long current_stub_stack(void) +{ + if(current->mm == NULL) + return(0); + + return(current->mm->context.skas.id.stack); +} diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 55caeec8b25..0f3d5d084dc 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -1,227 +1,484 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ +#include "linux/config.h" +#include "linux/kernel.h" #include "linux/sched.h" +#include "linux/interrupt.h" +#include "linux/string.h" +#include "linux/mm.h" #include "linux/slab.h" -#include "linux/ptrace.h" -#include "linux/proc_fs.h" -#include "linux/file.h" -#include "linux/errno.h" +#include "linux/utsname.h" +#include "linux/fs.h" +#include "linux/utime.h" +#include "linux/smp_lock.h" +#include "linux/module.h" #include "linux/init.h" +#include "linux/capability.h" +#include "linux/vmalloc.h" +#include "linux/spinlock.h" +#include "linux/proc_fs.h" +#include "linux/ptrace.h" +#include "linux/random.h" +#include "linux/personality.h" +#include "asm/unistd.h" +#include "asm/mman.h" +#include "asm/segment.h" +#include "asm/stat.h" +#include "asm/pgtable.h" +#include "asm/processor.h" +#include "asm/tlbflush.h" #include "asm/uaccess.h" -#include "asm/atomic.h" -#include "kern_util.h" -#include "skas.h" -#include "os.h" +#include "asm/user.h" #include "user_util.h" -#include "tlb.h" +#include "kern_util.h" #include "kern.h" +#include "signal_kern.h" +#include "init.h" +#include "irq_user.h" +#include "mem_user.h" +#include "tlb.h" +#include "frame_kern.h" +#include "sigcontext.h" +#include "os.h" #include "mode.h" -#include "registers.h" +#include "mode_kern.h" +#include "choose-mode.h" + +/* This is a per-cpu array. A processor only modifies its entry and it only + * cares about its entry, so it's OK if another processor is modifying its + * entry. + */ +struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; + +int external_pid(void *t) +{ + struct task_struct *task = t ? t : current; + + return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task)); +} + +int pid_to_processor_id(int pid) +{ + int i; + + for(i = 0; i < ncpus; i++){ + if(cpu_tasks[i].pid == pid) return(i); + } + return(-1); +} + +void free_stack(unsigned long stack, int order) +{ + free_pages(stack, order); +} + +unsigned long alloc_stack(int order, int atomic) +{ + unsigned long page; + gfp_t flags = GFP_KERNEL; + + if (atomic) + flags = GFP_ATOMIC; + page = __get_free_pages(flags, order); + if(page == 0) + return(0); + stack_protections(page); + return(page); +} + +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + int pid; + + current->thread.request.u.thread.proc = fn; + current->thread.request.u.thread.arg = arg; + pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, + ¤t->thread.regs, 0, NULL, NULL); + if(pid < 0) + panic("do_fork failed in kernel_thread, errno = %d", pid); + return(pid); +} -void switch_to_skas(void *prev, void *next) +void set_current(void *t) { - struct task_struct *from, *to; + struct task_struct *task = t; - from = prev; - to = next; + cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) + { external_pid(task), task }); +} - /* XXX need to check runqueues[cpu].idle */ - if(current->pid == 0) - switch_timers(0); +void *_switch_to(void *prev, void *next, void *last) +{ + struct task_struct *from = prev; + struct task_struct *to= next; - switch_threads(&from->thread.mode.skas.switch_buf, - to->thread.mode.skas.switch_buf); + to->thread.prev_sched = from; + set_current(to); - arch_switch_to_skas(current->thread.prev_sched, current); + do { + current->thread.saved_task = NULL ; + CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); + if(current->thread.saved_task) + show_regs(&(current->thread.regs)); + next= current->thread.saved_task; + prev= current; + } while(current->thread.saved_task); + + return(current->thread.prev_sched); - if(current->pid == 0) - switch_timers(1); } -extern void schedule_tail(struct task_struct *prev); +void interrupt_end(void) +{ + if(need_resched()) schedule(); + if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); +} -void new_thread_handler(int sig) +void release_thread(struct task_struct *task) { - int (*fn)(void *), n; - void *arg; + CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); +} - fn = current->thread.request.u.thread.proc; - arg = current->thread.request.u.thread.arg; - os_usr1_signal(1); - thread_wait(¤t->thread.mode.skas.switch_buf, - current->thread.mode.skas.fork_buf); +void exit_thread(void) +{ + unprotect_stack((unsigned long) current_thread); +} - if(current->thread.prev_sched != NULL) - schedule_tail(current->thread.prev_sched); - current->thread.prev_sched = NULL; +void *get_current(void) +{ + return(current); +} + +int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, + unsigned long stack_top, struct task_struct * p, + struct pt_regs *regs) +{ + int ret; - /* The return value is 1 if the kernel thread execs a process, - * 0 if it just exits + p->thread = (struct thread_struct) INIT_THREAD; + ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, + clone_flags, sp, stack_top, p, regs); + + if (ret || !current->thread.forking) + goto out; + + clear_flushed_tls(p); + + /* + * Set a new TLS for the child thread? */ - n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); - if(n == 1){ - /* Handle any immediate reschedules or signals */ - interrupt_end(); - userspace(¤t->thread.regs.regs); + if (clone_flags & CLONE_SETTLS) + ret = arch_copy_tls(p); + +out: + return ret; +} + +void initial_thread_cb(void (*proc)(void *), void *arg) +{ + int save_kmalloc_ok = kmalloc_ok; + + kmalloc_ok = 0; + CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, + arg); + kmalloc_ok = save_kmalloc_ok; +} + +unsigned long stack_sp(unsigned long page) +{ + return(page + PAGE_SIZE - sizeof(void *)); +} + +int current_pid(void) +{ + return(current->pid); +} + +void default_idle(void) +{ + CHOOSE_MODE(uml_idle_timer(), (void) 0); + + while(1){ + /* endless idle loop with no priority at all */ + + /* + * although we are an idle CPU, we do not want to + * get into the scheduler unnecessarily. + */ + if(need_resched()) + schedule(); + + idle_sleep(10); } - else do_exit(0); } -void new_thread_proc(void *stack, void (*handler)(int sig)) +void cpu_idle(void) { - init_new_thread_stack(stack, handler); - os_usr1_process(os_getpid()); + CHOOSE_MODE(init_idle_tt(), init_idle_skas()); } -void release_thread_skas(struct task_struct *task) +int page_size(void) { + return(PAGE_SIZE); } -void fork_handler(int sig) +void *um_virt_to_phys(struct task_struct *task, unsigned long addr, + pte_t *pte_out) { - os_usr1_signal(1); - thread_wait(¤t->thread.mode.skas.switch_buf, - current->thread.mode.skas.fork_buf); - - force_flush_all(); - if(current->thread.prev_sched == NULL) - panic("blech"); + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + pte_t ptent; + + if(task->mm == NULL) + return(ERR_PTR(-EINVAL)); + pgd = pgd_offset(task->mm, addr); + if(!pgd_present(*pgd)) + return(ERR_PTR(-EINVAL)); + + pud = pud_offset(pgd, addr); + if(!pud_present(*pud)) + return(ERR_PTR(-EINVAL)); + + pmd = pmd_offset(pud, addr); + if(!pmd_present(*pmd)) + return(ERR_PTR(-EINVAL)); + + pte = pte_offset_kernel(pmd, addr); + ptent = *pte; + if(!pte_present(ptent)) + return(ERR_PTR(-EINVAL)); + + if(pte_out != NULL) + *pte_out = ptent; + return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK)); +} - schedule_tail(current->thread.prev_sched); +char *current_cmd(void) +{ +#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) + return("(Unknown)"); +#else + void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); + return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); +#endif +} - /* XXX: if interrupt_end() calls schedule, this call to - * arch_switch_to_skas isn't needed. We could want to apply this to - * improve performance. -bb */ - arch_switch_to_skas(current->thread.prev_sched, current); +void force_sigbus(void) +{ + printk(KERN_ERR "Killing pid %d because of a lack of memory\n", + current->pid); + lock_kernel(); + sigaddset(¤t->pending.signal, SIGBUS); + recalc_sigpending(); + current->flags |= PF_SIGNALED; + do_exit(SIGBUS | 0x80); +} - current->thread.prev_sched = NULL; +void dump_thread(struct pt_regs *regs, struct user *u) +{ +} -/* Handle any immediate reschedules or signals */ - interrupt_end(); +void enable_hlt(void) +{ + panic("enable_hlt"); +} + +EXPORT_SYMBOL(enable_hlt); - userspace(¤t->thread.regs.regs); +void disable_hlt(void) +{ + panic("disable_hlt"); } -int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct * p, - struct pt_regs *regs) +EXPORT_SYMBOL(disable_hlt); + +void *um_kmalloc(int size) { - void (*handler)(int); + return kmalloc(size, GFP_KERNEL); +} - if(current->thread.forking){ - memcpy(&p->thread.regs.regs.skas, ®s->regs.skas, - sizeof(p->thread.regs.regs.skas)); - REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); - if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; +void *um_kmalloc_atomic(int size) +{ + return kmalloc(size, GFP_ATOMIC); +} - handler = fork_handler; +void *um_vmalloc(int size) +{ + return vmalloc(size); +} - arch_copy_thread(¤t->thread.arch, &p->thread.arch); - } - else { - init_thread_registers(&p->thread.regs.regs); - p->thread.request.u.thread = current->thread.request.u.thread; - handler = new_thread_handler; - } +void *um_vmalloc_atomic(int size) +{ + return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); +} - new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, - &p->thread.mode.skas.fork_buf, handler); - return(0); +int __cant_sleep(void) { + return in_atomic() || irqs_disabled() || in_interrupt(); + /* Is in_interrupt() really needed? */ +} + +unsigned long get_fault_addr(void) +{ + return((unsigned long) current->thread.fault_addr); } -int new_mm(unsigned long stack) +EXPORT_SYMBOL(get_fault_addr); + +void not_implemented(void) { - int fd; + printk(KERN_DEBUG "Something isn't implemented in here\n"); +} - fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); - if(fd < 0) - return(fd); +EXPORT_SYMBOL(not_implemented); - if(skas_needs_stub) - map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); +int user_context(unsigned long sp) +{ + unsigned long stack; - return(fd); + stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); + return(stack != (unsigned long) current_thread); } -void init_idle_skas(void) +extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; + +void do_uml_exitcalls(void) { - cpu_tasks[current_thread->cpu].pid = os_getpid(); - default_idle(); + exitcall_t *call; + + call = &__uml_exitcall_end; + while (--call >= &__uml_exitcall_begin) + (*call)(); } -extern void start_kernel(void); +char *uml_strdup(char *string) +{ + return kstrdup(string, GFP_KERNEL); +} -static int start_kernel_proc(void *unused) +int copy_to_user_proc(void __user *to, void *from, int size) { - int pid; + return(copy_to_user(to, from, size)); +} + +int copy_from_user_proc(void *to, void __user *from, int size) +{ + return(copy_from_user(to, from, size)); +} + +int clear_user_proc(void __user *buf, int size) +{ + return(clear_user(buf, size)); +} - block_signals(); - pid = os_getpid(); +int strlen_user_proc(char __user *str) +{ + return(strlen_user(str)); +} - cpu_tasks[0].pid = pid; - cpu_tasks[0].task = current; +int smp_sigio_handler(void) +{ #ifdef CONFIG_SMP - cpu_online_map = cpumask_of_cpu(0); + int cpu = current_thread->cpu; + IPI_handler(cpu); + if(cpu != 0) + return(1); #endif - start_kernel(); return(0); } -extern int userspace_pid[]; - -int start_uml_skas(void) +int cpu(void) { - if(proc_mm) - userspace_pid[0] = start_userspace(0); + return(current_thread->cpu); +} + +static atomic_t using_sysemu = ATOMIC_INIT(0); +int sysemu_supported; - init_new_thread_signals(); +void set_using_sysemu(int value) +{ + if (value > sysemu_supported) + return; + atomic_set(&using_sysemu, value); +} - init_task.thread.request.u.thread.proc = start_kernel_proc; - init_task.thread.request.u.thread.arg = NULL; - return(start_idle_thread(task_stack_page(&init_task), - &init_task.thread.mode.skas.switch_buf, - &init_task.thread.mode.skas.fork_buf)); +int get_using_sysemu(void) +{ + return atomic_read(&using_sysemu); } -int external_pid_skas(struct task_struct *task) +static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) { -#warning Need to look up userspace_pid by cpu - return(userspace_pid[0]); + if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ + *eof = 1; + + return strlen(buf); } -int thread_pid_skas(struct task_struct *task) +static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data) { -#warning Need to look up userspace_pid by cpu - return(userspace_pid[0]); + char tmp[2]; + + if (copy_from_user(tmp, buf, 1)) + return -EFAULT; + + if (tmp[0] >= '0' && tmp[0] <= '2') + set_using_sysemu(tmp[0] - '0'); + return count; /*We use the first char, but pretend to write everything*/ } -void kill_off_processes_skas(void) +int __init make_proc_sysemu(void) { - if(proc_mm) -#warning need to loop over userspace_pids in kill_off_processes_skas - os_kill_ptraced_process(userspace_pid[0], 1); - else { - struct task_struct *p; - int pid, me; + struct proc_dir_entry *ent; + if (!sysemu_supported) + return 0; - me = os_getpid(); - for_each_process(p){ - if(p->mm == NULL) - continue; + ent = create_proc_entry("sysemu", 0600, &proc_root); - pid = p->mm->context.skas.id.u.pid; - os_kill_ptraced_process(pid, 1); - } + if (ent == NULL) + { + printk(KERN_WARNING "Failed to register /proc/sysemu\n"); + return(0); } + + ent->read_proc = proc_read_sysemu; + ent->write_proc = proc_write_sysemu; + + return 0; } -unsigned long current_stub_stack(void) +late_initcall(make_proc_sysemu); + +int singlestepping(void * t) { - if(current->mm == NULL) + struct task_struct *task = t ? t : current; + + if ( ! (task->ptrace & PT_DTRACE) ) return(0); - return(current->mm->context.skas.id.stack); + if (task->thread.singlestep_syscall) + return(1); + + return 2; +} + +/* + * Only x86 and x86_64 have an arch_align_stack(). + * All other arches have "#define arch_align_stack(x) (x)" + * in their asm/system.h + * As this is included in UML from asm-um/system-generic.h, + * we can use it to behave as the subarch does. + */ +#ifndef arch_align_stack +unsigned long arch_align_stack(unsigned long sp) +{ + if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) + sp -= get_random_int() % 8192; + return sp & ~0xf; } +#endif diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 2454bbd9555..820affbf3e1 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) do_timer(regs); - nsecs = get_time() + local_offset; + nsecs = get_time(); xtime.tv_sec = nsecs / NSEC_PER_SEC; xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index e5eeaf2b6af..61a23fff439 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) segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); } -struct kern_handlers handlinfo_kern = { - .relay_signal = relay_signal, - .winch = winch, - .bus_handler = relay_signal, - .page_fault = segv_handler, - .sigio_handler = sigio_handler, - .timer_handler = timer_handler -}; /* * We give a *copy* of the faultinfo in the regs to segv. * This must be done, since nesting SEGVs could overwrite @@ -253,6 +245,15 @@ void winch(int sig, union uml_pt_regs *regs) do_IRQ(WINCH_IRQ, regs); } +const struct kern_handlers handlinfo_kern = { + .relay_signal = relay_signal, + .winch = winch, + .bus_handler = bus_handler, + .page_fault = segv_handler, + .sigio_handler = sigio_handler, + .timer_handler = timer_handler +}; + void trap_init(void) { } diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 7896cf98232..55005710dcb 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) { } -struct seq_operations cpuinfo_op = { +const struct seq_operations cpuinfo_op = { .start = c_start, .next = c_next, .stop = c_stop, diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index f4bfc4c7cca..b4183929b32 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -4,15 +4,19 @@ # obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ - signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \ + signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ user_syms.o util.o drivers/ sys-$(SUBARCH)/ obj-$(CONFIG_MODE_SKAS) += skas/ + +obj-$(CONFIG_MODE_TT) += tt.o +user-objs-$(CONFIG_MODE_TT) += tt.o + obj-$(CONFIG_TTY_LOG) += tty_log.o user-objs-$(CONFIG_TTY_LOG) += tty_log.o USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ - process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \ + process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \ uaccess.o umid.o util.o 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 b84f6c4740f..57ecdaf2f67 100644 --- a/arch/um/os-Linux/drivers/etap.h +++ b/arch/um/os-Linux/drivers/etap.h @@ -13,7 +13,7 @@ struct ethertap_data { void *dev; }; -extern struct net_user_info ethertap_user_info; +extern const struct net_user_info ethertap_user_info; /* * 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 768606bec23..16385e2ada8 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) return(net_send(fd, (*skb)->data, (*skb)->len)); } -struct net_kern_info ethertap_kern_info = { +const struct net_kern_info ethertap_kern_info = { .init = etap_init, .protocol = eth_protocol, .read = etap_read, diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 8f49507e64e..f559bdf746e 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, etap_close_addr(addr, netmask, &pri->control_fd); } -struct net_user_info ethertap_user_info = { +const struct net_user_info ethertap_user_info = { .init = etap_user_init, .open = etap_open, .close = etap_close, diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h index 25d4a286881..d3e8d3af624 100644 --- a/arch/um/os-Linux/drivers/tuntap.h +++ b/arch/um/os-Linux/drivers/tuntap.h @@ -16,7 +16,7 @@ struct tuntap_data { void *dev; }; -extern struct net_user_info tuntap_user_info; +extern const struct net_user_info tuntap_user_info; #endif diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c index 190009a6f89..0edbac63c52 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, return(net_write(fd, (*skb)->data, (*skb)->len)); } -struct net_kern_info tuntap_kern_info = { +const struct net_kern_info tuntap_kern_info = { .init = tuntap_init, .protocol = eth_protocol, .read = tuntap_read, diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 87c3aa0252d..e846b23f755 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) return(mtu); } -struct net_user_info tuntap_user_info = { +const struct net_user_info tuntap_user_info = { .init = tuntap_user_init, .open = tuntap_open, .close = tuntap_close, diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 42e3d1ed802..cb9ab54146c 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, } } -void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, - void (*handler)(int)) +void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) { - unsigned long flags; - jmp_buf switch_buf, fork_buf; - - *switch_buf_ptr = &switch_buf; - *fork_buf_ptr = &fork_buf; - - /* Somewhat subtle - siglongjmp restores the signal mask before doing - * the longjmp. This means that when jumping from one stack to another - * when the target stack has interrupts enabled, an interrupt may occur - * on the source stack. This is bad when starting up a process because - * it's not supposed to get timer ticks until it has been scheduled. - * So, we disable interrupts around the sigsetjmp to ensure that - * they can't happen until we get back here where they are safe. - */ - flags = get_signals(); - block_signals(); - if(UML_SETJMP(&fork_buf) == 0) - new_thread_proc(stack, handler); - - remove_sigstack(); - - set_signals(flags); + (*buf)[0].JB_IP = (unsigned long) handler; + (*buf)[0].JB_SP = (unsigned long) stack + + (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *); } #define INIT_JMP_NEW_THREAD 0 -#define INIT_JMP_REMOVE_SIGSTACK 1 -#define INIT_JMP_CALLBACK 2 -#define INIT_JMP_HALT 3 -#define INIT_JMP_REBOOT 4 - -void thread_wait(void *sw, void *fb) -{ - jmp_buf buf, **switch_buf = sw, *fork_buf; - - *switch_buf = &buf; - fork_buf = fb; - if(UML_SETJMP(&buf) == 0) - UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK); -} +#define INIT_JMP_CALLBACK 1 +#define INIT_JMP_HALT 2 +#define INIT_JMP_REBOOT 3 -void switch_threads(void *me, void *next) +void switch_threads(jmp_buf *me, jmp_buf *you) { - jmp_buf my_buf, **me_ptr = me, *next_buf = next; - - *me_ptr = &my_buf; - if(UML_SETJMP(&my_buf) == 0) - UML_LONGJMP(next_buf, 1); + if(UML_SETJMP(me) == 0) + UML_LONGJMP(you, 1); } static jmp_buf initial_jmpbuf; @@ -503,23 +469,21 @@ static void (*cb_proc)(void *arg); static void *cb_arg; static jmp_buf *cb_back; -int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) +int start_idle_thread(void *stack, jmp_buf *switch_buf) { - jmp_buf **switch_buf = switch_buf_ptr; int n; set_handler(SIGWINCH, (__sighandler_t) sig_handler, SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, SIGVTALRM, -1); - *fork_buf_ptr = &initial_jmpbuf; n = UML_SETJMP(&initial_jmpbuf); switch(n){ case INIT_JMP_NEW_THREAD: - new_thread_proc((void *) stack, new_thread_handler); - break; - case INIT_JMP_REMOVE_SIGSTACK: - remove_sigstack(); + (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; + (*switch_buf)[0].JB_SP = (unsigned long) stack + + (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - + sizeof(void *); break; case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); @@ -534,7 +498,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) default: panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); } - UML_LONGJMP(*switch_buf, 1); + UML_LONGJMP(switch_buf, 1); } 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 59cc7027575..0e32adf03be 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 \ obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o -subarch-obj-y = lib/bitops.o kernel/semaphore.o +subarch-obj-y = lib/bitops.o lib/semaphore.o subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o subarch-obj-$(CONFIG_MODULES) += kernel/module.o |