diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/Kconfig | 5 | ||||
-rw-r--r-- | arch/um/Kconfig.i386 | 58 | ||||
-rw-r--r-- | arch/um/drivers/line.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/net_kern.c | 18 | ||||
-rw-r--r-- | arch/um/include/line.h | 2 | ||||
-rw-r--r-- | arch/um/include/net_kern.h | 2 | ||||
-rw-r--r-- | arch/um/kernel/exec.c | 7 | ||||
-rw-r--r-- | arch/um/sys-i386/Makefile | 2 | ||||
-rw-r--r-- | arch/um/sys-i386/bug.c | 20 | ||||
-rw-r--r-- | arch/um/sys-i386/ldt.c | 4 | ||||
-rw-r--r-- | arch/um/sys-i386/signal.c | 3 | ||||
-rw-r--r-- | arch/um/sys-x86_64/Makefile | 2 | ||||
-rw-r--r-- | arch/um/sys-x86_64/bug.c | 20 | ||||
-rw-r--r-- | arch/um/sys-x86_64/signal.c | 5 |
14 files changed, 101 insertions, 49 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 5ac1f2963ae..d32a80e6668 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -47,6 +47,11 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_BUG + bool + default y + depends on BUG + # Used in kernel/irq/manage.c and include/linux/irq.h config IRQ_RELEASE_METHOD bool diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index f191a550a07..d6cffb27fff 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -19,31 +19,31 @@ config SEMAPHORE_SLEEPERS choice prompt "Host memory split" default HOST_VMSPLIT_3G - ---help--- - This is needed when the host kernel on which you run has a non-default - (like 2G/2G) memory split, instead of the customary 3G/1G. If you did - not recompile your own kernel but use the default distro's one, you can - safely accept the "Default split" option. - - It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via - CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck - patchset by Con Kolivas, or other ones) - option names match closely the - host CONFIG_VM_SPLIT_* ones. - - A lower setting (where 1G/3G is lowest and 3G/1G is higher) will - tolerate even more "normal" host kernels, but an higher setting will be - stricter. - - So, if you do not know what to do here, say 'Default split'. - - config HOST_VMSPLIT_3G - bool "Default split (3G/1G user/kernel host split)" - config HOST_VMSPLIT_3G_OPT - bool "3G/1G user/kernel host split (for full 1G low memory)" - config HOST_VMSPLIT_2G - bool "2G/2G user/kernel host split" - config HOST_VMSPLIT_1G - bool "1G/3G user/kernel host split" + help + This is needed when the host kernel on which you run has a non-default + (like 2G/2G) memory split, instead of the customary 3G/1G. If you did + not recompile your own kernel but use the default distro's one, you can + safely accept the "Default split" option. + + It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via + CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck + patchset by Con Kolivas, or other ones) - option names match closely the + host CONFIG_VM_SPLIT_* ones. + + A lower setting (where 1G/3G is lowest and 3G/1G is higher) will + tolerate even more "normal" host kernels, but an higher setting will be + stricter. + + So, if you do not know what to do here, say 'Default split'. + +config HOST_VMSPLIT_3G + bool "Default split (3G/1G user/kernel host split)" +config HOST_VMSPLIT_3G_OPT + bool "3G/1G user/kernel host split (for full 1G low memory)" +config HOST_VMSPLIT_2G + bool "2G/2G user/kernel host split" +config HOST_VMSPLIT_1G + bool "1G/3G user/kernel host split" endchoice config TOP_ADDR @@ -67,13 +67,13 @@ config 3_LEVEL_PGTABLES config STUB_CODE hex - default 0xbfffe000 if !HOST_2G_2G - default 0x7fffe000 if HOST_2G_2G + default 0xbfffe000 if !HOST_VMSPLIT_2G + default 0x7fffe000 if HOST_VMSPLIT_2G config STUB_DATA hex - default 0xbffff000 if !HOST_2G_2G - default 0x7ffff000 if HOST_2G_2G + default 0xbffff000 if !HOST_VMSPLIT_2G + default 0x7ffff000 if HOST_VMSPLIT_2G config STUB_START hex diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index aa3090d05a8..83301e1ef67 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -246,7 +246,7 @@ out_up: return ret; } -void line_set_termios(struct tty_struct *tty, struct termios * old) +void line_set_termios(struct tty_struct *tty, struct ktermios * old) { /* nothing */ } diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 286bc0b3207..afe3d427ddf 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -72,9 +72,11 @@ static int uml_net_rx(struct net_device *dev) return pkt_len; } -static void uml_dev_close(void* dev) +static void uml_dev_close(struct work_struct *work) { - dev_close( (struct net_device *) dev); + struct uml_net_private *lp = + container_of(work, struct uml_net_private, work); + dev_close(lp->dev); } irqreturn_t uml_net_interrupt(int irq, void *dev_id) @@ -89,7 +91,6 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) spin_lock(&lp->lock); while((err = uml_net_rx(dev)) > 0) ; if(err < 0) { - DECLARE_WORK(close_work, uml_dev_close, dev); printk(KERN_ERR "Device '%s' read returned %d, shutting it down\n", dev->name, err); @@ -97,9 +98,10 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) * again lp->lock. * And dev_close() can be safely called multiple times on the * same device, since it tests for (dev->flags & IFF_UP). So - * there's no harm in delaying the device shutdown. */ - schedule_work(&close_work); -#error this is not permitted - close_work will go out of scope + * there's no harm in delaying the device shutdown. + * Furthermore, the workqueue will not re-enqueue an already + * enqueued work item. */ + schedule_work(&lp->work); goto out; } reactivate_fd(lp->fd, UM_ETH_IRQ); @@ -334,13 +336,12 @@ static int eth_configure(int n, void *init, char *mac, size = transport->private_size + sizeof(struct uml_net_private) + sizeof(((struct uml_net_private *) 0)->user); - device = kmalloc(sizeof(*device), GFP_KERNEL); + device = kzalloc(sizeof(*device), GFP_KERNEL); if (device == NULL) { printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); return(1); } - memset(device, 0, sizeof(*device)); INIT_LIST_HEAD(&device->list); device->index = n; @@ -366,6 +367,7 @@ static int eth_configure(int n, void *init, char *mac, /* This points to the transport private data. It's still clear, but we * must memset it to 0 *now*. Let's help the drivers. */ memset(lp, 0, size); + INIT_WORK(&lp->work, uml_dev_close); /* sysfs register */ if (!driver_registered) { diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 214ee76c40d..5f232ae89fb 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -76,7 +76,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines, extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); extern void line_put_char(struct tty_struct *tty, unsigned char ch); -extern void line_set_termios(struct tty_struct *tty, struct termios * old); +extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); extern void line_flush_chars(struct tty_struct *tty); diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h index 280459fb0b2..218f8b47fdc 100644 --- a/arch/um/include/net_kern.h +++ b/arch/um/include/net_kern.h @@ -11,6 +11,7 @@ #include <linux/skbuff.h> #include <linux/socket.h> #include <linux/list.h> +#include <linux/workqueue.h> struct uml_net { struct list_head list; @@ -26,6 +27,7 @@ struct uml_net_private { struct net_device *dev; struct timer_list tl; struct net_device_stats stats; + struct work_struct work; int fd; unsigned char mac[ETH_ALEN]; unsigned short (*protocol)(struct sk_buff *); diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 0561c43b468..8d56ec6cca7 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -39,12 +39,13 @@ static long execve1(char *file, char __user * __user *argv, char __user *__user *env) { long error; + struct tty_struct *tty; #ifdef CONFIG_TTY_LOG mutex_lock(&tty_mutex); - task_lock(current); /* FIXME: is this needed ? */ - log_exec(argv, current->signal->tty); - task_unlock(current); + tty = get_current_tty(); + if (tty) + log_exec(argv, tty); mutex_unlock(&tty_mutex); #endif error = do_execve(file, argv, env, ¤t->thread.regs); diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 0e32adf03be..098720be019 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -1,4 +1,4 @@ -obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ +obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \ sys_call_table.o tls.o diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c new file mode 100644 index 00000000000..200c8ba2879 --- /dev/null +++ b/arch/um/sys-i386/bug.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL V2 + */ + +#include <linux/uaccess.h> + +/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because + * that's not relevent in skas mode. + */ + +int is_valid_bugaddr(unsigned long eip) +{ + unsigned short ud2; + + if (probe_kernel_address((unsigned short __user *)eip, ud2)) + return 0; + + return ud2 == 0x0b0f; +} diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 49057d8bc66..5db7737df0f 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -166,7 +166,7 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) { .func = 0, .bytecount = bytecount, - .ptr = (void *)kmalloc(bytecount, GFP_KERNEL)}; + .ptr = kmalloc(bytecount, GFP_KERNEL)}; u32 cpu; if(ptrace_ldt.ptr == NULL) @@ -426,7 +426,7 @@ void ldt_get_host_info(void) host_ldt_entries = dummy_list; else { size = (size + 1) * sizeof(dummy_list[0]); - host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL); + host_ldt_entries = kmalloc(size, GFP_KERNEL); if(host_ldt_entries == NULL) { printk("ldt_get_host_info: couldn't allocate host ldt list\n"); goto out_free; diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 0709fc6670c..3f6acd66771 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c @@ -219,7 +219,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, unsigned long save_sp = PT_REGS_SP(regs); int err = 0; - stack_top &= -8UL; + /* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */ + stack_top = ((stack_top + 4) & -16UL) - 4; frame = (struct sigframe __user *) stack_top - 1; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return 1; diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index f41768b8e25..4d9e5efa6fb 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -4,7 +4,7 @@ # Licensed under the GPL # -obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ +obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ ksyms.o tls.o diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c new file mode 100644 index 00000000000..200c8ba2879 --- /dev/null +++ b/arch/um/sys-x86_64/bug.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL V2 + */ + +#include <linux/uaccess.h> + +/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because + * that's not relevent in skas mode. + */ + +int is_valid_bugaddr(unsigned long eip) +{ + unsigned short ud2; + + if (probe_kernel_address((unsigned short __user *)eip, ud2)) + return 0; + + return ud2 == 0x0b0f; +} diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index 9edf114faf7..af2f017617b 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c @@ -191,8 +191,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, struct task_struct *me = current; frame = (struct rt_sigframe __user *) - round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8; - frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128); + round_down(stack_top - sizeof(struct rt_sigframe), 16); + /* Subtract 128 for a red zone and 8 for proper alignment */ + frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto out; |