diff options
Diffstat (limited to 'arch/um')
110 files changed, 1586 insertions, 1890 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 55945db1313..99e51d059a0 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -68,6 +68,10 @@ config IRQ_RELEASE_METHOD bool default y +config HZ + int + default 100 + menu "UML-specific options" config STATIC_LINK @@ -95,23 +99,6 @@ config LD_SCRIPT_DYN default y depends on !LD_SCRIPT_STATIC -config NET - bool "Networking support" - help - Unless you really know what you are doing, you should say Y here. - The reason is that some programs need kernel networking support even - when running on a stand-alone machine that isn't connected to any - other computer. If you are upgrading from an older kernel, you - should consider updating your networking tools too because changes - in the kernel and the tools often go hand in hand. The tools are - contained in the package net-tools, the location and version number - of which are given in <file:Documentation/Changes>. - - For a general introduction to Linux networking, it is highly - recommended to read the NET-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - source "fs/Kconfig.binfmt" config HOSTFS @@ -145,7 +132,7 @@ config HPPFS by removing or changing anything in /proc which gives away the identity of a UML. - See <http://user-mode-linux.sf.net/hppfs.html> for more information. + See <http://user-mode-linux.sf.net/old/hppfs.html> for more information. You only need this if you are setting up a UML honeypot. Otherwise, it is safe to say 'N' here. @@ -189,8 +176,7 @@ config MAGIC_SYSRQ config SMP bool "Symmetric multi-processing support (EXPERIMENTAL)" default n - #SMP_BROKEN is for x86_64. - depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) + depends on BROKEN help This option enables UML SMP support. It is NOT related to having a real SMP box. Not directly, at least. diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index 9a78d354f0b..3a4b396d797 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char @@ -18,7 +18,7 @@ config SSL lines on the UML that are usually made to show up on the host as ttys or ptys. - See <http://user-mode-linux.sourceforge.net/input.html> for more + See <http://user-mode-linux.sourceforge.net/old/input.html> for more information and command line examples of how to use this facility. Unless you have a specific reason for disabling this, say Y. diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index 1f6462ffd3e..8fce5e536b0 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug @@ -4,12 +4,12 @@ source "lib/Kconfig.debug" config GPROF bool "Enable gprof support" - depends on DEBUG_INFO + depends on DEBUG_INFO && FRAME_POINTER help This allows profiling of a User-Mode Linux kernel with the gprof utility. - See <http://user-mode-linux.sourceforge.net/gprof.html> for more + See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more details. If you're involved in UML kernel development and want to use gprof, @@ -22,7 +22,7 @@ config GCOV This option allows developers to retrieve coverage data from a UML session. - See <http://user-mode-linux.sourceforge.net/gprof.html> for more + See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more details. If you're involved in UML kernel development and want to use gcov, diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net index 66e50026ade..9e9a4aaa703 100644 --- a/arch/um/Kconfig.net +++ b/arch/um/Kconfig.net @@ -14,7 +14,7 @@ config UML_NET For more information, including explanations of the networking and sample configurations, see - <http://user-mode-linux.sourceforge.net/networking.html>. + <http://user-mode-linux.sourceforge.net/old/networking.html>. If you'd like to be able to enable networking in the User-Mode linux environment, say Y; otherwise say N. Note that you must @@ -38,7 +38,7 @@ config UML_NET_ETHERTAP CONFIG_NETLINK_DEV configured as Y or M. For more information, see - <http://user-mode-linux.sourceforge.net/networking.html> That site + <http://user-mode-linux.sourceforge.net/old/networking.html> That site has examples of the UML command line to use to enable Ethertap networking. @@ -72,7 +72,7 @@ config UML_NET_SLIP To use this, your host must support slip devices. For more information, see - <http://user-mode-linux.sourceforge.net/networking.html>. That site + <http://user-mode-linux.sourceforge.net/old/networking.html>. has examples of the UML command line to use to enable slip networking, and details of a few quirks with it. @@ -96,7 +96,7 @@ config UML_NET_DAEMON networking daemon on the host. For more information, see - <http://user-mode-linux.sourceforge.net/networking.html> That site + <http://user-mode-linux.sourceforge.net/old/networking.html> That site has examples of the UML command line to use to enable Daemon networking. @@ -144,7 +144,7 @@ config UML_NET_MCAST To use this, your host kernel(s) must support IP Multicasting. For more information, see - <http://user-mode-linux.sourceforge.net/networking.html> That site + <http://user-mode-linux.sourceforge.net/old/networking.html> That site has examples of the UML command line to use to enable Multicast networking, and notes about the security of this approach. @@ -165,7 +165,7 @@ config UML_NET_PCAP installed in order to build the pcap transport into UML. For more information, see - <http://user-mode-linux.sourceforge.net/networking.html> That site + <http://user-mode-linux.sourceforge.net/old/networking.html> That site has examples of the UML command line to use to enable this option. If you intend to use UML as a network monitor for the host, say diff --git a/arch/um/Makefile b/arch/um/Makefile index ba6813a4aa3..cb4af9bf207 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -49,7 +49,7 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) # # These apply to USER_CFLAGS to. -KBUILD_CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ +KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ -Din6addr_loopback=kernel_in6addr_loopback \ -Din6addr_any=kernel_in6addr_any @@ -58,7 +58,7 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE) USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ - -D_FILE_OFFSET_BITS=64 + $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) @@ -130,7 +130,9 @@ CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ # The wrappers will select whether using "malloc" or the kernel allocator. LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc -CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) +LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt)) + +CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE) define cmd_vmlinux__ $(CC) $(CFLAGS_vmlinux) -o $@ \ -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \ @@ -158,7 +160,7 @@ ifneq ($(KBUILD_SRC),) $(Q)mkdir -p $(objtree)/include/asm-um $(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@ else - $(Q)cd $(TOPDIR)/$(dir $@) ; \ + $(Q)cd $(srctree)/$(dir $@) ; \ ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@) endif @@ -168,7 +170,7 @@ ifneq ($(KBUILD_SRC),) $(Q)mkdir -p $(objtree)/include/asm-um $(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch else - $(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch + $(Q)cd $(srctree)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch endif $(objtree)/$(ARCH_DIR)/include: diff --git a/arch/um/Makefile-tt b/arch/um/Makefile-tt deleted file mode 100644 index 03f7b10cfd0..00000000000 --- a/arch/um/Makefile-tt +++ /dev/null @@ -1,5 +0,0 @@ -# -# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -# Licensed under the GPL -# - diff --git a/arch/um/defconfig b/arch/um/defconfig index f609edede06..86db2862f22 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -77,7 +77,7 @@ CONFIG_LD_SCRIPT_DYN=y CONFIG_NET=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m -# CONFIG_HOSTFS is not set +CONFIG_HOSTFS=y # CONFIG_HPPFS is not set CONFIG_MCONSOLE=y CONFIG_MAGIC_SYSRQ=y @@ -188,7 +188,7 @@ CONFIG_CON_CHAN="xterm" CONFIG_SSL_CHAN="pts" CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_LEGACY_PTY_COUNT=32 # CONFIG_WATCHDOG is not set CONFIG_UML_SOUND=m CONFIG_SOUND=m @@ -508,7 +508,7 @@ CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set -CONFIG_DEBUG_SLAB=y +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SLAB_LEAK is not set # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 83bf15a3dda..2c898c4d6b6 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -8,6 +8,7 @@ #include "chan_kern.h" #include "irq_kern.h" #include "irq_user.h" +#include "kern_util.h" #include "os.h" #define LINE_BUFSIZE 4096 @@ -48,7 +49,7 @@ static int write_room(struct line *line) n = line->head - line->tail; if (n <= 0) - n = LINE_BUFSIZE + n; /* The other case */ + n += LINE_BUFSIZE; /* The other case */ return n - 1; } @@ -58,17 +59,10 @@ int line_write_room(struct tty_struct *tty) unsigned long flags; int room; - if (tty->stopped) - return 0; - spin_lock_irqsave(&line->lock, flags); room = write_room(line); spin_unlock_irqrestore(&line->lock, flags); - /*XXX: Warning to remove */ - if (0 == room) - printk(KERN_DEBUG "%s: %s: no room left in buffer\n", - __FUNCTION__,tty->name); return room; } @@ -79,8 +73,7 @@ int line_chars_in_buffer(struct tty_struct *tty) int ret; spin_lock_irqsave(&line->lock, flags); - - /*write_room subtracts 1 for the needed NULL, so we readd it.*/ + /* write_room subtracts 1 for the needed NULL, so we readd it.*/ ret = LINE_BUFSIZE - (write_room(line) + 1); spin_unlock_irqrestore(&line->lock, flags); @@ -184,10 +177,6 @@ void line_flush_buffer(struct tty_struct *tty) unsigned long flags; int err; - /*XXX: copied from line_write, verify if it is correct!*/ - if (tty->stopped) - return; - spin_lock_irqsave(&line->lock, flags); err = flush_buffer(line); spin_unlock_irqrestore(&line->lock, flags); @@ -213,9 +202,6 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) unsigned long flags; int n, ret = 0; - if (tty->stopped) - return 0; - spin_lock_irqsave(&line->lock, flags); if (line->head != line->tail) ret = buffer_data(line, buf, len); @@ -788,9 +774,11 @@ static irqreturn_t winch_interrupt(int irq, void *data) tty = winch->tty; if (tty != NULL) { line = tty->driver_data; - chan_window_size(&line->chan_list, &tty->winsize.ws_row, - &tty->winsize.ws_col); - kill_pgrp(tty->pgrp, SIGWINCH, 1); + if (line != NULL) { + chan_window_size(&line->chan_list, &tty->winsize.ws_row, + &tty->winsize.ws_col); + kill_pgrp(tty->pgrp, SIGWINCH, 1); + } } out: if (winch->fd != -1) diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 0f3c7d14a6e..ebb265c07e4 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -1,23 +1,25 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/console.h" -#include "linux/ctype.h" -#include "linux/interrupt.h" -#include "linux/list.h" -#include "linux/mm.h" -#include "linux/module.h" -#include "linux/notifier.h" -#include "linux/reboot.h" -#include "linux/proc_fs.h" -#include "linux/slab.h" -#include "linux/syscalls.h" -#include "linux/utsname.h" -#include "linux/workqueue.h" -#include "asm/uaccess.h" +#include <linux/console.h> +#include <linux/ctype.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/proc_fs.h> +#include <linux/slab.h> +#include <linux/syscalls.h> +#include <linux/utsname.h> +#include <linux/workqueue.h> +#include <linux/mutex.h> +#include <asm/uaccess.h> + #include "init.h" #include "irq_kern.h" #include "irq_user.h" @@ -305,7 +307,9 @@ void mconsole_stop(struct mc_request *req) deactivate_fd(req->originating_fd, MCONSOLE_IRQ); os_set_fd_block(req->originating_fd, 1); mconsole_reply(req, "stopped", 0, 0); - while (mconsole_get_request(req->originating_fd, req)) { + for (;;) { + if (!mconsole_get_request(req->originating_fd, req)) + continue; if (req->cmd->handler == mconsole_go) break; if (req->cmd->handler == mconsole_stop) { @@ -358,7 +362,7 @@ struct unplugged_pages { void *pages[UNPLUGGED_PER_PAGE]; }; -static DECLARE_MUTEX(plug_mem_mutex); +static DEFINE_MUTEX(plug_mem_mutex); static unsigned long long unplugged_pages_count = 0; static LIST_HEAD(unplugged_pages); static int unplug_index = UNPLUGGED_PER_PAGE; @@ -394,7 +398,7 @@ static int mem_config(char *str, char **error_out) diff /= PAGE_SIZE; - down(&plug_mem_mutex); + mutex_lock(&plug_mem_mutex); for (i = 0; i < diff; i++) { struct unplugged_pages *unplugged; void *addr; @@ -451,7 +455,7 @@ static int mem_config(char *str, char **error_out) err = 0; out_unlock: - up(&plug_mem_mutex); + mutex_unlock(&plug_mem_mutex); out: return err; } @@ -741,7 +745,6 @@ void mconsole_stack(struct mc_request *req) { char *ptr = req->request.data; int pid_requested= -1; - struct task_struct *from = NULL; struct task_struct *to = NULL; /* @@ -763,9 +766,7 @@ void mconsole_stack(struct mc_request *req) return; } - from = current; - - to = find_task_by_pid(pid_requested); + to = find_task_by_pid_ns(pid_requested, &init_pid_ns); if ((to == NULL) || (pid_requested == 0)) { mconsole_reply(req, "Couldn't find that pid", 1, 0); return; @@ -795,6 +796,8 @@ static int __init mconsole_init(void) printk(KERN_ERR "Failed to initialize management console\n"); return 1; } + if (os_set_fd_block(sock, 0)) + goto out; register_reboot_notifier(&reboot_notifier); @@ -803,7 +806,7 @@ static int __init mconsole_init(void) "mconsole", (void *)sock); if (err) { printk(KERN_ERR "Failed to get IRQ for management console\n"); - return 1; + goto out; } if (notify_socket != NULL) { @@ -819,6 +822,10 @@ static int __init mconsole_init(void) printk(KERN_INFO "mconsole (version %d) initialized on %s\n", MCONSOLE_VERSION, mconsole_socket_name); return 0; + + out: + os_close_file(sock); + return 1; } __initcall(mconsole_init); diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 430c024a19b..13af2f03ed8 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -83,9 +83,8 @@ int mconsole_get_request(int fd, struct mc_request *req) int len; req->originlen = sizeof(req->origin); - req->len = recvfrom(fd, &req->request, sizeof(req->request), - MSG_DONTWAIT, (struct sockaddr *) req->origin, - &req->originlen); + req->len = recvfrom(fd, &req->request, sizeof(req->request), 0, + (struct sockaddr *) req->origin, &req->originlen); if (req->len < 0) return 0; diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 3c6c44ca1ff..1e8f41a9951 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -318,7 +318,7 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name) if (str == NULL) goto random; - for (i = 0;i < 6; i++) { + for (i = 0; i < 6; i++) { addr[i] = simple_strtoul(str, &end, 16); if ((end == str) || ((*end != ':') && (*end != ',') && (*end != '\0'))) { @@ -343,14 +343,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name) } if (!is_local_ether_addr(addr)) { printk(KERN_WARNING - "Warning: attempt to assign a globally valid ethernet " + "Warning: Assigning a globally valid ethernet " "address to a device\n"); - printk(KERN_WARNING "You should better enable the 2nd " - "rightmost bit in the first byte of the MAC,\n"); + printk(KERN_WARNING "You should set the 2nd rightmost bit in " + "the first byte of the MAC,\n"); printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n", addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], addr[5]); - goto random; } return; @@ -368,7 +367,6 @@ static struct platform_driver uml_net_driver = { .name = DRIVER_NAME, }, }; -static int driver_registered; static void net_device_release(struct device *dev) { @@ -383,6 +381,12 @@ static void net_device_release(struct device *dev) free_netdev(netdev); } +/* + * Ensures that platform_driver_register is called only once by + * eth_configure. Will be set in an initcall. + */ +static int driver_registered; + static void eth_configure(int n, void *init, char *mac, struct transport *transport) { diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 29185cad9ff..abf2653f551 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -201,7 +201,7 @@ static int change_tramp(char **argv, char *output, int output_len) close(fds[1]); if (pid > 0) - helper_wait(pid, 0, "change_tramp"); + helper_wait(pid); return pid; } diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 330543b3129..19930081d3d 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -6,6 +6,7 @@ #include "linux/completion.h" #include "linux/interrupt.h" #include "linux/list.h" +#include "linux/mutex.h" #include "asm/atomic.h" #include "init.h" #include "irq_kern.h" @@ -120,7 +121,7 @@ static int port_accept(struct port_list *port) return 0; } -static DECLARE_MUTEX(ports_sem); +static DEFINE_MUTEX(ports_mutex); static LIST_HEAD(ports); static void port_work_proc(struct work_struct *unused) @@ -161,7 +162,7 @@ void *port_data(int port_num) struct port_dev *dev = NULL; int fd; - down(&ports_sem); + mutex_lock(&ports_mutex); list_for_each(ele, &ports) { port = list_entry(ele, struct port_list, list); if (port->port == port_num) @@ -216,7 +217,7 @@ void *port_data(int port_num) out_free: kfree(port); out: - up(&ports_sem); + mutex_unlock(&ports_mutex); return dev; } diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index e942e836f99..71f0959c153 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -5,6 +5,7 @@ * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. */ +#include <linux/sched.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/miscdevice.h> diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index b8711e50da8..8b80505a3fb 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -109,7 +109,7 @@ static int slip_tramp(char **argv, int fd) read_output(fds[0], output, output_len); printk("%s", output); - err = helper_wait(pid, 0, argv[0]); + err = helper_wait(pid); close(fds[0]); out_free: diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index 89c1be225fd..a0ada8fec72 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c @@ -98,7 +98,7 @@ static void slirp_close(int fd, void *data) "(%d)\n", pri->pid, errno); } #endif - err = helper_wait(pri->pid, 1, "slirp_close"); + err = helper_wait(pri->pid); if (err < 0) return; diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 875d60d0c6a..f1786e64607 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -15,7 +15,6 @@ #include "line.h" #include "ssl.h" #include "chan_kern.h" -#include "kern_util.h" #include "kern.h" #include "init.h" #include "irq_user.h" diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 656036e90b1..cec0c33cdd3 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -22,7 +22,6 @@ #include "stdio_console.h" #include "line.h" #include "chan_kern.h" -#include "kern_util.h" #include "irq_user.h" #include "mconsole_kern.h" #include "init.h" diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 99f9f9605e9..be3a2797dac 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -49,6 +49,7 @@ #include "irq_user.h" #include "irq_kern.h" #include "ubd_user.h" +#include "kern_util.h" #include "os.h" #include "mem.h" #include "mem_kern.h" @@ -229,7 +230,7 @@ static int proc_ide_read_media(char *page, char **start, off_t off, int count, return len; } -static void make_ide_entries(char *dev_name) +static void make_ide_entries(const char *dev_name) { struct proc_dir_entry *dir, *ent; char name[64]; @@ -244,7 +245,7 @@ static void make_ide_entries(char *dev_name) ent->data = NULL; ent->read_proc = proc_ide_read_media; ent->write_proc = NULL; - sprintf(name,"ide0/%s", dev_name); + snprintf(name, sizeof(name), "ide0/%s", dev_name); proc_symlink(dev_name, proc_ide_root, name); } @@ -437,7 +438,10 @@ __uml_help(ubd_setup, " machine by running 'dd' on the device. <n> must be in the range\n" " 0 to 7. Appending an 'r' to the number will cause that device\n" " to be mounted read-only. For example ubd1r=./ext_fs. Appending\n" -" an 's' will cause data to be written to disk on the host immediately.\n\n" +" an 's' will cause data to be written to disk on the host immediately.\n" +" 'c' will cause the device to be treated as being shared between multiple\n" +" UMLs and file locking will be turned off - this is appropriate for a\n" +" cluster filesystem and inappropriate at almost all other times.\n\n" ); static int udb_setup(char *str) @@ -456,20 +460,6 @@ __uml_help(udb_setup, " in the boot output.\n\n" ); -static int fakehd_set = 0; -static int fakehd(char *str) -{ - printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n"); - fakehd_set = 1; - return 1; -} - -__setup("fakehd", fakehd); -__uml_help(fakehd, -"fakehd\n" -" Change the ubd device name to \"hd\".\n\n" -); - static void do_ubd_request(struct request_queue * q); /* Only changed by ubd_init, which is an initcall. */ @@ -718,8 +708,10 @@ static int ubd_add(int n, char **error_out) ubd_disk_register(fake_major, ubd_dev->size, n, &fake_gendisk[n]); - /* perhaps this should also be under the "if (fake_major)" above */ - /* using the fake_disk->disk_name and also the fakehd_set name */ + /* + * Perhaps this should also be under the "if (fake_major)" above + * using the fake_disk->disk_name + */ if (fake_ide) make_ide_entries(ubd_gendisk[n]->disk_name); diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index 48fc7452bc1..b591bb9c41d 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c @@ -16,7 +16,6 @@ #include <sys/mman.h> #include <sys/param.h> #include "asm/types.h" -#include "kern_util.h" #include "user.h" #include "ubd_user.h" #include "os.h" diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c index d9941fe5f93..56533db2534 100644 --- a/arch/um/drivers/vde_user.c +++ b/arch/um/drivers/vde_user.c @@ -80,7 +80,7 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init) vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL); if (vpri->args == NULL) { - printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args" + printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args " "allocation failed"); return; } diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h index 49c601ff2ba..2de92a08a76 100644 --- a/arch/um/include/arch.h +++ b/arch/um/include/arch.h @@ -10,6 +10,6 @@ extern void arch_check_bugs(void); extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs); -extern int arch_handle_signal(int sig, struct uml_pt_regs *regs); +extern void arch_examine_signal(int sig, struct uml_pt_regs *regs); #endif diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h index a5cdf953e04..606bb5c7fdf 100644 --- a/arch/um/include/as-layout.h +++ b/arch/um/include/as-layout.h @@ -10,23 +10,31 @@ #include "kern_constants.h" /* - * Assembly doesn't want any casting, but C does, so define these - * without casts here, and define new symbols with casts inside the C - * section. + * Stolen from linux/const.h, which can't be directly included since + * this is used in userspace code, which has no access to the kernel + * headers. Changed to be suitable for adding casts to the start, + * rather than "UL" to the end. */ -#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE) -#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE) -#define ASM_STUB_START ASM_STUB_CODE -/* - * This file is included by the assembly stubs, which just want the - * definitions above. +/* Some constant macros are used in both assembler and + * C code. Therefore we cannot annotate them always with + * 'UL' and other type specifiers unilaterally. We + * use the following macros to deal with this. */ -#ifndef __ASSEMBLY__ -#define STUB_CODE ((unsigned long) ASM_STUB_CODE) -#define STUB_DATA ((unsigned long) ASM_STUB_DATA) -#define STUB_START ((unsigned long) ASM_STUB_START) +#ifdef __ASSEMBLY__ +#define _AC(X, Y) (Y) +#else +#define __AC(X, Y) (X (Y)) +#define _AC(X, Y) __AC(X, Y) +#endif + +#define STUB_START _AC(, 0x100000) +#define STUB_CODE _AC((unsigned long), STUB_START) +#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE) +#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE) + +#ifndef __ASSEMBLY__ #include "sysdep/ptrace.h" diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h index 5a2263e05bb..9b9ced85b70 100644 --- a/arch/um/include/chan_user.h +++ b/arch/um/include/chan_user.h @@ -48,7 +48,7 @@ extern void register_winch_irq(int fd, int tty_fd, int pid, #define __channel_help(fn, prefix) \ __uml_help(fn, prefix "[0-9]*=<channel description>\n" \ " Attach a console or serial line to a host channel. See\n" \ -" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \ +" http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \ " description of this switch.\n\n" \ ); diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h index 0edab695ed4..b54bd35585c 100644 --- a/arch/um/include/common-offsets.h +++ b/arch/um/include/common-offsets.h @@ -18,6 +18,7 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING); DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); DEFINE_STR(UM_KERN_INFO, KERN_INFO); DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); +DEFINE_STR(UM_KERN_CONT, KERN_CONT); DEFINE(UM_ELF_CLASS, ELF_CLASS); DEFINE(UM_ELFCLASS32, ELFCLASS32); diff --git a/arch/um/include/init.h b/arch/um/include/init.h index cebc6cae919..b00a95741d4 100644 --- a/arch/um/include/init.h +++ b/arch/um/include/init.h @@ -40,6 +40,20 @@ typedef int (*initcall_t)(void); typedef void (*exitcall_t)(void); +#ifndef __KERNEL__ +#ifndef __section +# define __section(S) __attribute__ ((__section__(#S))) +#endif + +#if __GNUC_MINOR__ >= 3 +# define __used __attribute__((__used__)) +#else +# define __used __attribute__((__unused__)) +#endif + +#else +#include <linux/compiler.h> +#endif /* These are for everybody (although not all archs will actually discard it in modules) */ #define __init __section(.init.text) @@ -127,14 +141,3 @@ extern struct uml_param __uml_setup_start, __uml_setup_end; #endif #endif /* _LINUX_UML_INIT_H */ - -/* - * 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/include/irq_user.h b/arch/um/include/irq_user.h index 884a9c17eea..e60b31873de 100644 --- a/arch/um/include/irq_user.h +++ b/arch/um/include/irq_user.h @@ -14,7 +14,6 @@ struct irq_fd { int fd; int type; int irq; - int pid; int events; int current_events; }; diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 74ce8e5370a..3c341222d25 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -9,107 +9,61 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" -typedef void (*kern_hndl)(int, struct uml_pt_regs *); - -struct kern_handlers { - kern_hndl relay_signal; - kern_hndl winch; - kern_hndl bus_handler; - kern_hndl page_fault; - kern_hndl sigio_handler; - kern_hndl timer_handler; -}; - -extern const struct kern_handlers handlinfo_kern; +extern int uml_exitcode; extern int ncpus; -extern char *gdb_init; extern int kmalloc_ok; -extern int jail; -extern int nsyscalls; -#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK)) #define UML_ROUND_UP(addr) \ - UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) + ((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK) -extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); -extern int kernel_thread_proc(void *data); -extern void syscall_segv(int sig); -extern int current_pid(void); extern unsigned long alloc_stack(int order, int atomic); +extern void free_stack(unsigned long stack, int order); + extern int do_signal(void); -extern int is_stack_fault(unsigned long sp); +extern void copy_sc(struct uml_pt_regs *regs, void *from); +extern void interrupt_end(void); +extern void relay_signal(int sig, struct uml_pt_regs *regs); + extern unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, struct uml_pt_regs *regs); extern int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out); -extern void syscall_ready(void); -extern void set_tracing(void *t, int tracing); -extern int is_tracing(void *task); -extern int segv_syscall(void); -extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); -extern unsigned long page_mask(void); -extern int need_finish_fork(void); -extern void free_stack(unsigned long stack, int order); -extern void add_input_request(int op, void (*proc)(int), void *arg); -extern char *current_cmd(void); -extern void timer_handler(int sig, struct uml_pt_regs *regs); -extern int set_signals(int enable); -extern int pid_to_processor_id(int pid); -extern void deliver_signals(void *t); -extern int next_trap_index(int max); -extern void default_idle(void); -extern void finish_fork(void); -extern void paging_init(void); -extern void init_flush_vm(void); -extern void *syscall_sp(void *t); -extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); + extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs); -extern void interrupt_end(void); -extern void initial_thread_cb(void (*proc)(void *), void *arg); -extern int debugger_signal(int status, int pid); -extern void debugger_parent_signal(int status, int pid); -extern void child_signal(int pid, int status); -extern int init_ptrace_proxy(int idle_pid, int startup, int stop); -extern int init_parent_proxy(int pid); -extern int singlestepping(void *t); -extern void check_stack_overflow(void *ptr); -extern void relay_signal(int sig, struct uml_pt_regs *regs); -extern int user_context(unsigned long sp); -extern void timer_irq(struct uml_pt_regs *regs); -extern void do_uml_exitcalls(void); -extern int attach_debugger(int idle_pid, int pid, int stop); -extern int config_gdb(char *str); -extern int remove_gdb(void); -extern char *uml_strdup(char *string); -extern void unprotect_kernel_mem(void); -extern void protect_kernel_mem(void); -extern void uml_cleanup(void); -extern void lock_signalled_task(void *t); -extern void IPI_handler(int cpu); -extern int jail_setup(char *line, int *add); -extern void *get_init_task(void); -extern int clear_user_proc(void *buf, int size); -extern int copy_to_user_proc(void *to, void *from, int size); -extern int copy_from_user_proc(void *to, void *from, int size); -extern int strlen_user_proc(char *str); -extern long execute_syscall(void *r); extern int smp_sigio_handler(void); -extern void *get_current(void); -extern struct task_struct *get_task(int pid, int require); -extern void machine_halt(void); +extern void initial_thread_cb(void (*proc)(void *), void *arg); extern int is_syscall(unsigned long addr); +extern void timer_handler(int sig, struct uml_pt_regs *regs); -extern void free_irq(unsigned int, void *); -extern int cpu(void); +extern void timer_handler(int sig, struct uml_pt_regs *regs); -extern void time_init_kern(void); +extern int start_uml(void); +extern void paging_init(void); -/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ +extern void uml_cleanup(void); +extern void do_uml_exitcalls(void); + +/* + * Are we disallowed to sleep? Used to choose between GFP_KERNEL and + * GFP_ATOMIC. + */ extern int __cant_sleep(void); -extern void sigio_handler(int sig, struct uml_pt_regs *regs); -extern void copy_sc(struct uml_pt_regs *regs, void *from); +extern void *get_current(void); +extern int copy_from_user_proc(void *to, void *from, int size); +extern int cpu(void); +extern char *uml_strdup(const char *string); + extern unsigned long to_irq_stack(unsigned long *mask_out); -unsigned long from_irq_stack(int nested); -extern int start_uml(void); +extern unsigned long from_irq_stack(int nested); + +extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); +extern int singlestepping(void *t); + +extern void segv_handler(int sig, struct uml_pt_regs *regs); +extern void bus_handler(int sig, struct uml_pt_regs *regs); +extern void winch(int sig, struct uml_pt_regs *regs); +extern void fatal_sigsegv(void) __attribute__ ((noreturn)); + + #endif diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h index a54514d2cc3..46384acd547 100644 --- a/arch/um/include/mem_user.h +++ b/arch/um/include/mem_user.h @@ -46,9 +46,6 @@ extern int iomem_size; #define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) -extern unsigned long host_task_size; -extern unsigned long task_size; - extern int init_mem_user(void); extern void setup_memory(void *entry); extern unsigned long find_iomem(char *driver, unsigned long *len_out); @@ -59,9 +56,7 @@ extern void setup_physmem(unsigned long start, unsigned long usable, unsigned long len, unsigned long long highmem); extern void add_iomem(char *name, int fd, unsigned long size); extern unsigned long phys_offset(unsigned long phys); -extern void unmap_physmem(void); extern void map_memory(unsigned long virt, unsigned long phys, unsigned long len, int r, int w, int x); -extern unsigned long get_kmem_end(void); #endif diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h deleted file mode 100644 index 989bc08de36..00000000000 --- a/arch/um/include/misc_constants.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __MISC_CONSTANT_H_ -#define __MISC_CONSTANT_H_ - -#include <user_constants.h> - -#endif diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 6f0d1c741bc..0b6b6273330 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -8,7 +8,6 @@ #include <stdarg.h> #include "irq_user.h" -#include "kern_util.h" #include "longjmp.h" #include "mm_id.h" #include "sysdep/tls.h" @@ -128,33 +127,31 @@ static inline struct openflags of_cloexec(struct openflags flags) extern int os_stat_file(const char *file_name, struct uml_stat *buf); extern int os_stat_fd(const int fd, struct uml_stat *buf); extern int os_access(const char *file, int mode); -extern int os_get_exec_close(int fd, int *close_on_exec); extern int os_set_exec_close(int fd); extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); extern int os_get_ifname(int fd, char *namebuf); extern int os_set_slip(int fd); -extern int os_set_owner(int fd, int pid); extern int os_mode_fd(int fd, int mode); extern int os_seek_file(int fd, unsigned long long offset); -extern int os_open_file(char *file, struct openflags flags, int mode); +extern int os_open_file(const char *file, struct openflags flags, int mode); extern int os_read_file(int fd, void *buf, int len); extern int os_write_file(int fd, const void *buf, int count); -extern int os_file_size(char *file, unsigned long long *size_out); -extern int os_file_modtime(char *file, unsigned long *modtime); +extern int os_file_size(const char *file, unsigned long long *size_out); +extern int os_file_modtime(const char *file, unsigned long *modtime); extern int os_pipe(int *fd, int stream, int close_on_exec); -extern int os_set_fd_async(int fd, int owner); +extern int os_set_fd_async(int fd); extern int os_clear_fd_async(int fd); extern int os_set_fd_block(int fd, int blocking); extern int os_accept_connection(int fd); -extern int os_create_unix_socket(char *file, int len, int close_on_exec); +extern int os_create_unix_socket(const char *file, int len, int close_on_exec); extern int os_shutdown_socket(int fd, int r, int w); extern void os_close_file(int fd); extern int os_rcv_fd(int fd, int *helper_pid_out); extern int create_unix_socket(char *file, int len, int close_on_exec); -extern int os_connect_socket(char *name); +extern int os_connect_socket(const char *name); extern int os_file_type(char *file); -extern int os_file_mode(char *file, struct openflags *mode_out); +extern int os_file_mode(const char *file, struct openflags *mode_out); extern int os_lock_file(int fd, int excl); extern void os_flush_stdout(void); extern int os_stat_filesystem(char *path, long *bsize_out, @@ -168,14 +165,10 @@ extern int os_fchange_dir(int fd); /* start_up.c */ extern void os_early_checks(void); -extern int can_do_skas(void); +extern void can_do_skas(void); extern void os_check_bugs(void); extern void check_host_supports_tls(int *supports_tls, int *tls_min); -/* Make sure they are clear when running in TT mode. Required by - * SEGV_MAYBE_FIXABLE */ -#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) - /* mem.c */ extern int create_mem_file(unsigned long long len); @@ -214,7 +207,7 @@ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]); extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv); extern int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, unsigned long *stack_out); -extern int helper_wait(int pid, int nohang, char *pname); +extern int helper_wait(int pid); /* tls.c */ @@ -237,16 +230,12 @@ extern void unblock_signals(void); extern int get_signals(void); extern int set_signals(int enable); -/* trap.c */ -extern void os_fill_handlinfo(struct kern_handlers h); - /* util.c */ extern void stack_protections(unsigned long address); extern int raw(int fd); extern void setup_machinename(char *machine_out); extern void setup_hostinfo(char *buf, int len); -extern int setjmp_wrapper(void (*proc)(void *, void *), ...); -extern void os_dump_core(void); +extern void os_dump_core(void) __attribute__ ((noreturn)); /* time.c */ extern void idle_sleep(unsigned long long nsecs); @@ -275,11 +264,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr, extern int is_skas_winch(int pid, int fd, void *data); extern int start_userspace(unsigned long stub_stack); extern int copy_context_skas0(unsigned long stack, int pid); -extern void save_registers(int pid, struct uml_pt_regs *regs); -extern void restore_registers(int pid, struct uml_pt_regs *regs); extern void userspace(struct uml_pt_regs *regs); -extern void map_stub_pages(int fd, unsigned long code, - unsigned long data, unsigned long stack); +extern int map_stub_pages(int fd, unsigned long code, unsigned long data, + unsigned long stack); 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); @@ -298,16 +285,12 @@ extern void os_free_irq_later(struct irq_fd *active_fds, extern int os_get_pollfd(int i); extern void os_set_pollfd(int i, int fd); extern void os_set_ioignore(void); -extern void init_irq_signals(int on_sigstack); /* sigio.c */ extern int add_sigio_fd(int fd); extern int ignore_sigio_fd(int fd); extern void maybe_sigio_broken(int fd, int read); -/* skas/trap */ -extern void sig_handler_common_skas(int sig, void *sc_ptr); - /* sys-x86_64/prctl.c */ extern int os_arch_prctl(int pid, int code, unsigned long *addr); diff --git a/arch/um/include/ptrace_user.h b/arch/um/include/ptrace_user.h index f3450e6bc18..4bce6e01288 100644 --- a/arch/um/include/ptrace_user.h +++ b/arch/um/include/ptrace_user.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -10,12 +10,6 @@ extern int ptrace_getregs(long pid, unsigned long *regs_out); extern int ptrace_setregs(long pid, unsigned long *regs_in); -extern int ptrace_getfpregs(long pid, unsigned long *regs_out); -extern int ptrace_setfpregs(long pid, unsigned long *regs); -extern void arch_enter_kernel(void *task, int pid); -extern void arch_leave_kernel(void *task, int pid); -extern void ptrace_pokeuser(unsigned long addr, unsigned long data); - /* syscall emulation path in ptrace */ @@ -54,7 +48,8 @@ extern int sysemu_supported; (((int[3][3] ) { \ { PTRACE_SYSCALL, PTRACE_SYSCALL, PTRACE_SINGLESTEP }, \ { PTRACE_SYSEMU, PTRACE_SYSEMU, PTRACE_SINGLESTEP }, \ - { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, PTRACE_SYSEMU_SINGLESTEP }}) \ + { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, \ + PTRACE_SYSEMU_SINGLESTEP } }) \ [sysemu_mode][singlestep_mode]) #endif diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index 0e27406a43a..9ea1ae3c8f4 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h @@ -9,14 +9,13 @@ #include "sysdep/ptrace.h" #include "sysdep/archsetjmp.h" -extern void init_thread_registers(struct uml_pt_regs *to); extern int save_fp_registers(int pid, unsigned long *fp_regs); extern int restore_fp_registers(int pid, unsigned long *fp_regs); extern int save_fpx_registers(int pid, unsigned long *fp_regs); extern int restore_fpx_registers(int pid, unsigned long *fp_regs); -extern void save_registers(int pid, struct uml_pt_regs *regs); -extern void restore_registers(int pid, struct uml_pt_regs *regs); -extern void init_registers(int pid); +extern int save_registers(int pid, struct uml_pt_regs *regs); +extern int restore_registers(int pid, struct uml_pt_regs *regs); +extern int init_registers(int pid); extern void get_safe_registers(unsigned long *regs); extern unsigned long get_thread_reg(int reg, jmp_buf *buf); diff --git a/arch/um/include/signal_kern.h b/arch/um/include/signal_kern.h deleted file mode 100644 index aeb5d5ab1df..00000000000 --- a/arch/um/include/signal_kern.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SIGNAL_KERN_H__ -#define __SIGNAL_KERN_H__ - -extern int have_signals(void *t); - -#endif - -/* - * 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/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h deleted file mode 100644 index e065feb000d..00000000000 --- a/arch/um/include/skas/mode-skas.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) - * Licensed under the GPL - */ - -#ifndef __MODE_SKAS_H__ -#define __MODE_SKAS_H__ - -extern void kill_off_processes_skas(void); - -#endif diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h index 57bd79efbee..905698197e3 100644 --- a/arch/um/include/sysdep-i386/syscalls.h +++ b/arch/um/include/sysdep-i386/syscalls.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -18,7 +18,8 @@ extern syscall_handler_t old_mmap_i386; extern syscall_handler_t *sys_call_table[]; #define EXECUTE_SYSCALL(syscall, regs) \ - ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) + ((long (*)(struct syscall_args)) \ + (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) extern long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h index c978b589df4..a307237b796 100644 --- a/arch/um/include/sysdep-x86_64/kernel-offsets.h +++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h @@ -17,16 +17,7 @@ #define OFFSET(sym, str, mem) \ DEFINE(sym, offsetof(struct str, mem)); -#define __NO_STUBS 1 -#undef __SYSCALL -#undef _ASM_X86_64_UNISTD_H_ -#define __SYSCALL(nr, sym) [nr] = 1, -static char syscalls[] = { -#include <asm/arch/unistd.h> -}; - void foo(void) { #include <common-offsets.h> -DEFINE(UM_NR_syscall_max, sizeof(syscalls) - 1); } diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h index cf72256609e..7cfb0b08565 100644 --- a/arch/um/include/sysdep-x86_64/syscalls.h +++ b/arch/um/include/sysdep-x86_64/syscalls.h @@ -30,6 +30,4 @@ extern long old_mmap(unsigned long addr, unsigned long len, extern syscall_handler_t sys_modify_ldt; extern syscall_handler_t sys_arch_prctl; -#define NR_syscalls (UM_NR_syscall_max + 1) - #endif diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h index 8855d8df512..82865fcf687 100644 --- a/arch/um/include/um_mmu.h +++ b/arch/um/include/um_mmu.h @@ -12,10 +12,6 @@ typedef struct mm_context { struct mm_id id; - unsigned long last_page_table; -#ifdef CONFIG_3_LEVEL_PGTABLES - unsigned long last_pmd; -#endif struct uml_ldt ldt; } mm_context_t; diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index fdfc06b8560..2b6fc8e0f07 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h @@ -6,7 +6,9 @@ #ifndef __ARCH_UM_UACCESS_H #define __ARCH_UM_UACCESS_H -#include "asm/fixmap.h" +#include <asm/elf.h> +#include <asm/fixmap.h> +#include "sysdep/archsetjmp.h" #define __under_task_size(addr, size) \ (((unsigned long) (addr) < TASK_SIZE) && \ diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 8196450451c..76a62c0cb2b 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -19,12 +19,13 @@ void flush_thread(void) { void *data = NULL; - unsigned long end = proc_mm ? task_size : STUB_START; int ret; arch_flush_thread(¤t->thread.arch); - ret = unmap(¤t->mm->context.id, 0, end, 1, &data); + ret = unmap(¤t->mm->context.id, 0, STUB_START, 0, &data); + ret = ret || unmap(¤t->mm->context.id, STUB_END, + TASK_SIZE - STUB_END, 1, &data); if (ret) { printk(KERN_ERR "flush_thread - clearing address space failed, " "err = %d\n", ret); diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index c716b5a6db1..984f80e668c 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -1,15 +1,17 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/init.h" -#include "linux/ctype.h" -#include "linux/proc_fs.h" -#include "asm/uaccess.h" +#include <linux/ctype.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/proc_fs.h> +#include <linux/types.h> +#include <asm/uaccess.h> -/* If read and write race, the read will still atomically read a valid +/* + * If read and write race, the read will still atomically read a valid * value. */ int uml_exitcode = 0; @@ -19,18 +21,19 @@ static int read_proc_exitcode(char *page, char **start, off_t off, { int len, val; - /* Save uml_exitcode in a local so that we don't need to guarantee + /* + * Save uml_exitcode in a local so that we don't need to guarantee * that sprintf accesses it atomically. */ val = uml_exitcode; len = sprintf(page, "%d\n", val); len -= off; - if(len <= off+count) + if (len <= off+count) *eof = 1; *start = page + off; - if(len > count) + if (len > count) len = count; - if(len < 0) + if (len < 0) len = 0; return len; } @@ -41,11 +44,11 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer, char *end, buf[sizeof("nnnnn\0")]; int tmp; - if(copy_from_user(buf, buffer, count)) + if (copy_from_user(buf, buffer, count)) return -EFAULT; tmp = simple_strtol(buf, &end, 0); - if((*end != '\0') && !isspace(*end)) + if ((*end != '\0') && !isspace(*end)) return -EINVAL; uml_exitcode = tmp; @@ -57,7 +60,7 @@ static int make_proc_exitcode(void) struct proc_dir_entry *ent; ent = create_proc_entry("exitcode", 0600, &proc_root); - if(ent == NULL){ + if (ent == NULL) { printk(KERN_WARNING "make_proc_exitcode : Failed to register " "/proc/exitcode\n"); return 0; diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c index 734f873cab1..72eccd2a411 100644 --- a/arch/um/kernel/gmon_syms.c +++ b/arch/um/kernel/gmon_syms.c @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -8,12 +8,13 @@ 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 +/* + * This is defined (and referred to in profiling stub code) only by some GCC * versions in libgcov. * * Since SuSE backported the fix, we cannot handle it depending on GCC version. - * So, unconditionally export it. But also give it a weak declaration, which will - * be overridden by any other one. + * So, unconditionally export it. But also give it a weak declaration, which + * will be overridden by any other one. */ extern void __gcov_init(void *) __attribute__((weak)); diff --git a/arch/um/kernel/gprof_syms.c b/arch/um/kernel/gprof_syms.c index 9244f018d44..e2f043d0de6 100644 --- a/arch/um/kernel/gprof_syms.c +++ b/arch/um/kernel/gprof_syms.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -7,14 +7,3 @@ extern void mcount(void); EXPORT_SYMBOL(mcount); - -/* - * 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/initrd.c b/arch/um/kernel/initrd.c index 16dc43e9d94..fa015565001 100644 --- a/arch/um/kernel/initrd.c +++ b/arch/um/kernel/initrd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -7,7 +7,6 @@ #include "linux/bootmem.h" #include "linux/initrd.h" #include "asm/types.h" -#include "kern_util.h" #include "initrd.h" #include "init.h" #include "os.h" @@ -21,18 +20,27 @@ static int __init read_initrd(void) long long size; int err; - if(initrd == NULL) + if (initrd == NULL) return 0; err = os_file_size(initrd, &size); - if(err) + if (err) return 0; + /* + * This is necessary because alloc_bootmem craps out if you + * ask for no memory. + */ + if (size == 0) { + printk(KERN_ERR "\"%\" is a zero-size initrd\n"); + return 0; + } + area = alloc_bootmem(size); - if(area == NULL) + if (area == NULL) return 0; - if(load_initrd(initrd, area, size) == -1) + if (load_initrd(initrd, area, size) == -1) return 0; initrd_start = (unsigned long) area; @@ -59,13 +67,15 @@ int load_initrd(char *filename, void *buf, int size) int fd, n; fd = os_open_file(filename, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("Opening '%s' failed - err = %d\n", filename, -fd); + if (fd < 0) { + printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename, + -fd); return -1; } n = os_read_file(fd, buf, size); - if(n != size){ - printk("Read of %d bytes from '%s' failed, err = %d\n", size, + if (n != size) { + printk(KERN_ERR "Read of %d bytes from '%s' failed, " + "err = %d\n", size, filename, -n); return -1; } diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index ba11ccd6a8a..91587f8db34 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -107,10 +107,9 @@ int activate_fd(int irq, int fd, int type, void *dev_id) struct pollfd *tmp_pfd; struct irq_fd *new_fd, *irq_fd; unsigned long flags; - int pid, events, err, n; + int events, err, n; - pid = os_getpid(); - err = os_set_fd_async(fd, pid); + err = os_set_fd_async(fd); if (err < 0) goto out; @@ -127,7 +126,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id) .fd = fd, .type = type, .irq = irq, - .pid = pid, .events = events, .current_events = 0 } ); diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 7c7142ba3bd..5311ee93ede 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -18,15 +18,11 @@ EXPORT_SYMBOL(set_signals); EXPORT_SYMBOL(get_signals); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(sys_waitpid); -EXPORT_SYMBOL(task_size); EXPORT_SYMBOL(flush_tlb_range); -EXPORT_SYMBOL(host_task_size); EXPORT_SYMBOL(arch_validate); -EXPORT_SYMBOL(get_kmem_end); EXPORT_SYMBOL(high_physmem); EXPORT_SYMBOL(empty_zero_page); -EXPORT_SYMBOL(um_virt_to_phys); EXPORT_SYMBOL(handle_page_fault); EXPORT_SYMBOL(find_iomem); @@ -40,7 +36,6 @@ EXPORT_SYMBOL(uml_strdup); EXPORT_SYMBOL(os_stat_fd); EXPORT_SYMBOL(os_stat_file); EXPORT_SYMBOL(os_access); -EXPORT_SYMBOL(os_get_exec_close); EXPORT_SYMBOL(os_set_exec_close); EXPORT_SYMBOL(os_getpid); EXPORT_SYMBOL(os_open_file); diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 59822dee438..d872fdce1d7 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -1,49 +1,41 @@ /* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/kernel.h" -#include "linux/mm.h" -#include "linux/bootmem.h" -#include "linux/swap.h" -#include "linux/highmem.h" -#include "linux/gfp.h" -#include "asm/page.h" -#include "asm/fixmap.h" -#include "asm/pgalloc.h" -#include "kern_util.h" +#include <linux/stddef.h> +#include <linux/bootmem.h> +#include <linux/gfp.h> +#include <linux/highmem.h> +#include <linux/mm.h> +#include <linux/swap.h> +#include <asm/fixmap.h> +#include <asm/page.h> #include "as-layout.h" +#include "init.h" #include "kern.h" +#include "kern_util.h" #include "mem_user.h" -#include "um_uaccess.h" #include "os.h" -#include "linux/types.h" -#include "linux/string.h" -#include "init.h" -#include "kern_constants.h" /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */ unsigned long *empty_zero_page = NULL; /* allocated in paging_init and unchanged thereafter */ unsigned long *empty_bad_page = NULL; + +/* + * Initialized during boot, and readonly for initializing page tables + * afterwards + */ pgd_t swapper_pg_dir[PTRS_PER_PGD]; + +/* Initialized at boot time, and readonly after that */ unsigned long long highmem; int kmalloc_ok = 0; +/* Used during early boot */ static unsigned long brk_end; -void unmap_physmem(void) -{ - os_unmap_memory((void *) brk_end, uml_reserved - brk_end); -} - -static void map_cb(void *unused) -{ - map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); -} - #ifdef CONFIG_HIGHMEM static void setup_highmem(unsigned long highmem_start, unsigned long highmem_len) @@ -53,7 +45,7 @@ static void setup_highmem(unsigned long highmem_start, int i; highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT; - for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ + for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) { page = &mem_map[highmem_pfn + i]; ClearPageReserved(page); init_page_count(page); @@ -65,14 +57,13 @@ static void setup_highmem(unsigned long highmem_start, void __init mem_init(void) { /* clear the zero-page */ - memset((void *) empty_zero_page, 0, PAGE_SIZE); + memset(empty_zero_page, 0, PAGE_SIZE); /* Map in the area just after the brk now that kmalloc is about * to be turned on. */ brk_end = (unsigned long) UML_ROUND_UP(sbrk(0)); - map_cb(NULL); - initial_thread_cb(map_cb, NULL); + map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); free_bootmem(__pa(brk_end), uml_reserved - brk_end); uml_reserved = brk_end; @@ -85,7 +76,7 @@ void __init mem_init(void) #endif num_physpages = totalram_pages; max_pfn = totalram_pages; - printk(KERN_INFO "Memory: %luk available\n", + printk(KERN_INFO "Memory: %luk available\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10)); kmalloc_ok = 1; @@ -119,7 +110,7 @@ static void __init one_md_table_init(pud_t *pud) #endif } -static void __init fixrange_init(unsigned long start, unsigned long end, +static void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) { pgd_t *pgd; @@ -138,7 +129,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end, if (pud_none(*pud)) one_md_table_init(pud); pmd = pmd_offset(pud, vaddr); - for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { + for (; (j < PTRS_PER_PMD) && (vaddr < end); pmd++, j++) { one_page_table_init(pmd); vaddr += PMD_SIZE; } @@ -152,7 +143,7 @@ pgprot_t kmap_prot; #define kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\ - (vaddr)), (vaddr)) + (vaddr)), (vaddr)) static void __init kmap_init(void) { @@ -197,21 +188,23 @@ static void __init fixaddr_user_init( void) pud_t *pud; pmd_t *pmd; pte_t *pte; - unsigned long paddr, vaddr = FIXADDR_USER_START; + phys_t p; + unsigned long v, vaddr = FIXADDR_USER_START; - if ( ! size ) + if (!size) return; fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir); - paddr = (unsigned long)alloc_bootmem_low_pages( size); - memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size); - paddr = __pa(paddr); - for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){ + v = (unsigned long) alloc_bootmem_low_pages(size); + memcpy((void *) v , (void *) FIXADDR_USER_START, size); + p = __pa(v); + for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE, + p += PAGE_SIZE) { pgd = swapper_pg_dir + pgd_index(vaddr); pud = pud_offset(pgd, vaddr); pmd = pmd_offset(pud, vaddr); pte = pte_offset_kernel(pmd, vaddr); - pte_set_val( (*pte), paddr, PAGE_READONLY); + pte_set_val(*pte, p, PAGE_READONLY); } #endif } @@ -223,7 +216,7 @@ void __init paging_init(void) empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); - for(i = 0; i < ARRAY_SIZE(zones_size); i++) + for (i = 0; i < ARRAY_SIZE(zones_size); i++) zones_size[i] = 0; zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) - @@ -253,32 +246,33 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order) int i; again: - if(page == NULL) + if (page == NULL) return page; - if(PageHighMem(page)) + if (PageHighMem(page)) return page; addr = (unsigned long) page_address(page); - for(i = 0; i < (1 << order); i++){ + for (i = 0; i < (1 << order); i++) { current->thread.fault_addr = (void *) addr; - if(__do_copy_to_user((void __user *) addr, &zero, + if (__do_copy_to_user((void __user *) addr, &zero, sizeof(zero), ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)){ - if(!(mask & __GFP_WAIT)) + ¤t->thread.fault_catcher)) { + if (!(mask & __GFP_WAIT)) return NULL; else break; } addr += PAGE_SIZE; } - if(i == (1 << order)) + if (i == (1 << order)) return page; page = alloc_pages(mask, order); goto again; } -/* This can't do anything because nothing in the kernel image can be freed +/* + * This can't do anything because nothing in the kernel image can be freed * since it's not in kernel physical memory. */ @@ -290,8 +284,8 @@ void free_initmem(void) void free_initrd_mem(unsigned long start, unsigned long end) { if (start < end) - printk ("Freeing initrd memory: %ldk freed\n", - (end - start) >> 10); + printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", + (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); init_page_count(virt_to_page(start)); @@ -308,32 +302,31 @@ void show_mem(void) int highmem = 0; struct page *page; - printk("Mem-info:\n"); + printk(KERN_INFO "Mem-info:\n"); show_free_areas(); - printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); + printk(KERN_INFO "Free swap: %6ldkB\n", + nr_swap_pages<<(PAGE_SHIFT-10)); pfn = max_mapnr; - while(pfn-- > 0) { + while (pfn-- > 0) { page = pfn_to_page(pfn); total++; - if(PageHighMem(page)) + if (PageHighMem(page)) highmem++; - if(PageReserved(page)) + if (PageReserved(page)) reserved++; - else if(PageSwapCache(page)) + else if (PageSwapCache(page)) cached++; - else if(page_count(page)) + else if (page_count(page)) shared += page_count(page) - 1; } - printk("%d pages of RAM\n", total); - printk("%d pages of HIGHMEM\n", highmem); - printk("%d reserved pages\n", reserved); - printk("%d pages shared\n", shared); - printk("%d pages swap cached\n", cached); + printk(KERN_INFO "%d pages of RAM\n", total); + printk(KERN_INFO "%d pages of HIGHMEM\n", highmem); + printk(KERN_INFO "%d reserved pages\n", reserved); + printk(KERN_INFO "%d pages shared\n", shared); + printk(KERN_INFO "%d pages swap cached\n", cached); } -/* - * Allocate and free page tables. - */ +/* Allocate and free page tables. */ pgd_t *pgd_alloc(struct mm_struct *mm) { @@ -341,14 +334,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm) if (pgd) { memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); - memcpy(pgd + USER_PTRS_PER_PGD, - swapper_pg_dir + USER_PTRS_PER_PGD, + memcpy(pgd + USER_PTRS_PER_PGD, + swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); } return pgd; } -void pgd_free(pgd_t *pgd) +void pgd_free(struct mm_struct *mm, pgd_t *pgd) { free_page((unsigned long) pgd); } @@ -368,3 +361,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); return pte; } + +#ifdef CONFIG_3_LEVEL_PGTABLES +pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) +{ + pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL); + + if (pmd) + memset(pmd, 0, PAGE_SIZE); + + return pmd; +} +#endif diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index e66432f4248..9757085a022 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -55,16 +55,6 @@ int __init init_maps(unsigned long physmem, unsigned long iomem, return 0; } -/* Changed during early boot */ -static unsigned long kmem_top = 0; - -unsigned long get_kmem_end(void) -{ - if (kmem_top == 0) - kmem_top = host_task_size - 1024 * 1024; - return kmem_top; -} - void map_memory(unsigned long virt, unsigned long phys, unsigned long len, int r, int w, int x) { @@ -174,10 +164,10 @@ __uml_setup("iomem=", parse_iomem, * setup_iomem, both of which run during early boot. Afterwards, it's * unchanged. */ -struct iomem_region *iomem_regions = NULL; +struct iomem_region *iomem_regions; -/* Initialized in parse_iomem */ -int iomem_size = 0; +/* Initialized in parse_iomem and unchanged thereafter */ +int iomem_size; unsigned long find_iomem(char *driver, unsigned long *len_out) { diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 0eae00b3e58..c07961bedb7 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -4,19 +4,21 @@ * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/err.h" -#include "linux/hardirq.h" -#include "linux/mm.h" -#include "linux/personality.h" -#include "linux/proc_fs.h" -#include "linux/ptrace.h" -#include "linux/random.h" -#include "linux/sched.h" -#include "linux/tick.h" -#include "linux/threads.h" -#include "asm/pgtable.h" -#include "asm/uaccess.h" +#include <linux/stddef.h> +#include <linux/err.h> +#include <linux/hardirq.h> +#include <linux/gfp.h> +#include <linux/mm.h> +#include <linux/personality.h> +#include <linux/proc_fs.h> +#include <linux/ptrace.h> +#include <linux/random.h> +#include <linux/sched.h> +#include <linux/tick.h> +#include <linux/threads.h> +#include <asm/current.h> +#include <asm/pgtable.h> +#include <asm/uaccess.h> #include "as-layout.h" #include "kern_util.h" #include "os.h" @@ -30,7 +32,7 @@ */ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; -static inline int external_pid(struct task_struct *task) +static inline int external_pid(void) { /* FIXME: Need to look up userspace_pid by cpu */ return userspace_pid[0]; @@ -40,7 +42,7 @@ int pid_to_processor_id(int pid) { int i; - for(i = 0; i < ncpus; i++) { + for (i = 0; i < ncpus; i++) { if (cpu_tasks[i].pid == pid) return i; } @@ -60,8 +62,6 @@ unsigned long alloc_stack(int order, int atomic) if (atomic) flags = GFP_ATOMIC; page = __get_free_pages(flags, order); - if (page == 0) - return 0; return page; } @@ -80,15 +80,15 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) static inline void set_current(struct task_struct *task) { cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) - { external_pid(task), task }); + { external_pid(), task }); } -extern void arch_switch_to(struct task_struct *from, struct task_struct *to); +extern void arch_switch_to(struct task_struct *to); void *_switch_to(void *prev, void *next, void *last) { struct task_struct *from = prev; - struct task_struct *to= next; + struct task_struct *to = next; to->thread.prev_sched = from; set_current(to); @@ -99,13 +99,13 @@ void *_switch_to(void *prev, void *next, void *last) switch_threads(&from->thread.switch_buf, &to->thread.switch_buf); - arch_switch_to(current->thread.prev_sched, current); + arch_switch_to(current); if (current->thread.saved_task) show_regs(&(current->thread.regs)); - next= current->thread.saved_task; - prev= current; - } while(current->thread.saved_task); + to = current->thread.saved_task; + from = current; + } while (current->thread.saved_task); return current->thread.prev_sched; @@ -163,8 +163,6 @@ void new_thread_handler(void) void fork_handler(void) { force_flush_all(); - if (current->thread.prev_sched == NULL) - panic("blech"); schedule_tail(current->thread.prev_sched); @@ -173,7 +171,7 @@ void fork_handler(void) * arch_switch_to isn't needed. We could want to apply this to * improve performance. -bb */ - arch_switch_to(current->thread.prev_sched, current); + arch_switch_to(current); current->thread.prev_sched = NULL; @@ -204,7 +202,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, arch_copy_thread(¤t->thread.arch, &p->thread.arch); } else { - init_thread_registers(&p->thread.regs.regs); + get_safe_registers(p->thread.regs.regs.gp); p->thread.request.u.thread = current->thread.request.u.thread; handler = new_thread_handler; } @@ -237,7 +235,7 @@ void default_idle(void) { unsigned long long nsecs; - while(1) { + while (1) { /* endless idle loop with no priority at all */ /* @@ -256,53 +254,10 @@ void default_idle(void) void cpu_idle(void) { - cpu_tasks[current_thread->cpu].pid = os_getpid(); + cpu_tasks[current_thread_info()->cpu].pid = os_getpid(); default_idle(); } -void *um_virt_to_phys(struct task_struct *task, unsigned long addr, - pte_t *pte_out) -{ - 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); -} - -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 -} - void dump_thread(struct pt_regs *regs, struct user *u) { } @@ -317,7 +272,7 @@ int user_context(unsigned long sp) unsigned long stack; stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); - return stack != (unsigned long) current_thread; + return stack != (unsigned long) current_thread_info(); } extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; @@ -331,7 +286,7 @@ void do_uml_exitcalls(void) (*call)(); } -char *uml_strdup(char *string) +char *uml_strdup(const char *string) { return kstrdup(string, GFP_KERNEL); } @@ -359,7 +314,7 @@ int strlen_user_proc(char __user *str) int smp_sigio_handler(void) { #ifdef CONFIG_SMP - int cpu = current_thread->cpu; + int cpu = current_thread_info()->cpu; IPI_handler(cpu); if (cpu != 0) return 1; @@ -369,7 +324,7 @@ int smp_sigio_handler(void) int cpu(void) { - return current_thread->cpu; + return current_thread_info()->cpu; } static atomic_t using_sysemu = ATOMIC_INIT(0); @@ -435,7 +390,7 @@ int singlestepping(void * t) { struct task_struct *task = t ? t : current; - if ( ! (task->ptrace & PT_DTRACE) ) + if (!(task->ptrace & PT_DTRACE)) return 0; if (task->thread.singlestep_syscall) @@ -459,3 +414,46 @@ unsigned long arch_align_stack(unsigned long sp) return sp & ~0xf; } #endif + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long stack_page, sp, ip; + bool seen_sched = 0; + + if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING)) + return 0; + + stack_page = (unsigned long) task_stack_page(p); + /* Bail if the process has no kernel stack for some reason */ + if (stack_page == 0) + return 0; + + sp = p->thread.switch_buf->JB_SP; + /* + * Bail if the stack pointer is below the bottom of the kernel + * stack for some reason + */ + if (sp < stack_page) + return 0; + + while (sp < stack_page + THREAD_SIZE) { + ip = *((unsigned long *) sp); + if (in_sched_functions(ip)) + /* Ignore everything until we're above the scheduler */ + seen_sched = 1; + else if (kernel_text_address(ip) && seen_sched) + return ip; + + sp += sizeof(unsigned long); + } + + return 0; +} + +int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu) +{ + int cpu = current_thread_info()->cpu; + + return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu); +} + diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 04cebcf0679..00197d3d21e 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -4,6 +4,7 @@ */ #include "linux/sched.h" +#include "kern_util.h" #include "os.h" #include "skas.h" @@ -11,7 +12,7 @@ void (*pm_power_off)(void); static void kill_off_processes(void) { - if(proc_mm) + if (proc_mm) /* * FIXME: need to loop over userspace_pids */ @@ -21,8 +22,8 @@ static void kill_off_processes(void) int pid, me; me = os_getpid(); - for_each_process(p){ - if(p->mm == NULL) + for_each_process(p) { + if (p->mm == NULL) continue; pid = p->mm->context.id.u.pid; diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c index 89f9866a135..2b272b63b51 100644 --- a/arch/um/kernel/sigio.c +++ b/arch/um/kernel/sigio.c @@ -1,18 +1,12 @@ /* - * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/list.h" -#include "linux/slab.h" -#include "linux/signal.h" -#include "linux/interrupt.h" -#include "init.h" -#include "sigio.h" -#include "irq_user.h" +#include <linux/interrupt.h> #include "irq_kern.h" #include "os.h" +#include "sigio.h" /* Protected by sigio_lock() called from write_sigio_workaround */ static int sigio_irq_fd = -1; @@ -33,9 +27,9 @@ int write_sigio_irq(int fd) err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio", NULL); - if(err){ - printk("write_sigio_irq : um_request_irq failed, err = %d\n", - err); + if (err) { + printk(KERN_ERR "write_sigio_irq : um_request_irq failed, " + "err = %d\n", err); return -1; } sigio_irq_fd = fd; diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index 19cb9773393..b0fce720c4d 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c @@ -3,12 +3,12 @@ * Licensed under the GPL */ -#include "linux/module.h" -#include "linux/ptrace.h" -#include "linux/sched.h" -#include "asm/siginfo.h" -#include "asm/signal.h" -#include "asm/unistd.h" +#include <linux/module.h> +#include <linux/ptrace.h> +#include <linux/sched.h> +#include <asm/siginfo.h> +#include <asm/signal.h> +#include <asm/unistd.h> #include "frame_kern.h" #include "kern_util.h" #include "sigcontext.h" @@ -36,7 +36,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, /* Did we come from a system call? */ if (PT_REGS_SYSCALL_NR(regs) >= 0) { /* If so, check system call restarting.. */ - switch(PT_REGS_SYSCALL_RET(regs)) { + switch (PT_REGS_SYSCALL_RET(regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: PT_REGS_SYSCALL_RET(regs) = -EINTR; @@ -116,7 +116,7 @@ static int kern_do_signal(struct pt_regs *regs) /* Did we come from a system call? */ if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) { /* Restart the system call - no handlers present */ - switch(PT_REGS_SYSCALL_RET(regs)) { + switch (PT_REGS_SYSCALL_RET(regs)) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 8d07a7acb90..2c8583c1a34 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -1,17 +1,20 @@ -#include <sched.h> +/* + * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + #include <signal.h> -#include <sys/mman.h> -#include <sys/time.h> +#include <sched.h> #include <asm/unistd.h> +#include <sys/time.h> #include "as-layout.h" +#include "kern_constants.h" #include "ptrace_user.h" -#include "skas.h" #include "stub-data.h" -#include "uml-config.h" #include "sysdep/stub.h" -#include "kern_constants.h" -/* This is in a separate file because it needs to be compiled with any +/* + * This is in a separate file because it needs to be compiled with any * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled * * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize @@ -26,25 +29,26 @@ stub_clone_handler(void) err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); - if(err != 0) + if (err != 0) goto out; err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0); - if(err) + if (err) goto out; - err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, + err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, (long) &data->timer, 0); - if(err) + if (err) goto out; remap_stack(data->fd, data->offset); goto done; out: - /* save current result. - * Parent: pid; - * child: retcode of mmap already saved and it jumps around this + /* + * save current result. + * Parent: pid; + * child: retcode of mmap already saved and it jumps around this * assignment */ data->err = err; diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index f859ec306cd..78b3e9f69d5 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -34,33 +34,14 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, if (!pte) goto out_pte; - /* - * There's an interaction between the skas0 stub pages, stack - * randomization, and the BUG at the end of exit_mmap. exit_mmap - * checks that the number of page tables freed is the same as had - * been allocated. If the stack is on the last page table page, - * then the stack pte page will be freed, and if not, it won't. To - * avoid having to know where the stack is, or if the process mapped - * something at the top of its address space for some other reason, - * we set TASK_SIZE to end at the start of the last page table. - * This keeps exit_mmap off the last page, but introduces a leak - * of that page. So, we hang onto it here and free it in - * destroy_context_skas. - */ - - mm->context.last_page_table = pmd_page_vaddr(*pmd); -#ifdef CONFIG_3_LEVEL_PGTABLES - mm->context.last_pmd = (unsigned long) __va(pud_val(*pud)); -#endif - *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); *pte = pte_mkread(*pte); return 0; out_pmd: - pud_free(pud); + pud_free(mm, pud); out_pte: - pmd_free(pmd); + pmd_free(mm, pmd); out: return -ENOMEM; } @@ -76,24 +57,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) stack = get_zeroed_page(GFP_KERNEL); if (stack == 0) goto out; - - /* - * This zeros the entry that pgd_alloc didn't, needed since - * we are about to reinitialize it, and want mm.nr_ptes to - * be accurate. - */ - mm->pgd[USER_PTRS_PER_PGD] = __pgd(0); - - ret = init_stub_pte(mm, STUB_CODE, - (unsigned long) &__syscall_stub_start); - if (ret) - goto out_free; - - ret = init_stub_pte(mm, STUB_DATA, stack); - if (ret) - goto out_free; - - mm->nr_ptes--; } to_mm->id.stack = stack; @@ -114,6 +77,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) to_mm->id.u.pid = copy_context_skas0(stack, from_mm->id.u.pid); else to_mm->id.u.pid = start_userspace(stack); + + if (to_mm->id.u.pid < 0) { + ret = to_mm->id.u.pid; + goto out_free; + } } ret = init_new_ldt(to_mm, from_mm); @@ -132,24 +100,87 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) return ret; } +void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) +{ + struct page **pages; + int err, ret; + + if (!skas_needs_stub) + return; + + ret = init_stub_pte(mm, STUB_CODE, + (unsigned long) &__syscall_stub_start); + if (ret) + goto out; + + ret = init_stub_pte(mm, STUB_DATA, mm->context.id.stack); + if (ret) + goto out; + + pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL); + if (pages == NULL) { + printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page " + "pointers\n"); + goto out; + } + + pages[0] = virt_to_page(&__syscall_stub_start); + pages[1] = virt_to_page(mm->context.id.stack); + + /* dup_mmap already holds mmap_sem */ + err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START, + VM_READ | VM_MAYREAD | VM_EXEC | + VM_MAYEXEC | VM_DONTCOPY, pages); + if (err) { + printk(KERN_ERR "install_special_mapping returned %d\n", err); + goto out_free; + } + return; + +out_free: + kfree(pages); +out: + force_sigsegv(SIGSEGV, current); +} + +void arch_exit_mmap(struct mm_struct *mm) +{ + pte_t *pte; + + pte = virt_to_pte(mm, STUB_CODE); + if (pte != NULL) + pte_clear(mm, STUB_CODE, pte); + + pte = virt_to_pte(mm, STUB_DATA); + if (pte == NULL) + return; + + pte_clear(mm, STUB_DATA, pte); +} + void destroy_context(struct mm_struct *mm) { struct mm_context *mmu = &mm->context; if (proc_mm) os_close_file(mmu->id.u.mm_fd); - else + else { + /* + * If init_new_context wasn't called, this will be + * zero, resulting in a kill(0), which will result in the + * whole UML suddenly dying. Also, cover negative and + * 1 cases, since they shouldn't happen either. + */ + if (mmu->id.u.pid < 2) { + printk(KERN_ERR "corrupt mm_context - pid = %d\n", + mmu->id.u.pid); + return; + } os_kill_ptraced_process(mmu->id.u.pid, 1); + } - if (!proc_mm || !ptrace_faultinfo) { + if (skas_needs_stub) free_page(mmu->id.stack); - pte_lock_deinit(virt_to_page(mmu->last_page_table)); - pte_free_kernel((pte_t *) mmu->last_page_table); - dec_zone_page_state(virt_to_page(mmu->last_page_table), NR_PAGETABLE); -#ifdef CONFIG_3_LEVEL_PGTABLES - pmd_free((pmd_t *) mmu->last_pmd); -#endif - } free_ldt(mmu); } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index fce389c2342..2e9852c0d48 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -6,19 +6,25 @@ #include "linux/init.h" #include "linux/sched.h" #include "as-layout.h" +#include "kern.h" #include "os.h" #include "skas.h" int new_mm(unsigned long stack) { - int fd; + int fd, err; 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, STUB_CODE, STUB_DATA, stack); + if (skas_needs_stub) { + err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack); + if (err) { + os_close_file(fd); + return err; + } + } return fd; } @@ -49,8 +55,14 @@ int __init start_uml(void) { stack_protections((unsigned long) &cpu0_irqstack); set_sigstack(cpu0_irqstack, THREAD_SIZE); - if (proc_mm) + if (proc_mm) { userspace_pid[0] = start_userspace(0); + if (userspace_pid[0] < 0) { + printf("start_uml - start_userspace returned %d\n", + userspace_pid[0]); + exit(1); + } + } init_new_thread_signals(); diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 50b476f2b38..4e3b820bd2b 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -9,6 +9,9 @@ #include "sysdep/ptrace.h" #include "sysdep/syscalls.h" +extern int syscall_table_size; +#define NR_syscalls (syscall_table_size / sizeof(void *)) + void handle_syscall(struct uml_pt_regs *r) { struct pt_regs *regs = container_of(r, struct pt_regs, regs); @@ -17,9 +20,6 @@ void handle_syscall(struct uml_pt_regs *r) syscall_trace(r, 0); - current->thread.nsyscalls++; - nsyscalls++; - /* * This should go in the declaration of syscall, but when I do that, * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 1d8b119f2d0..e22c96993db 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -3,128 +3,130 @@ * Licensed under the GPL */ -#include "linux/err.h" -#include "linux/highmem.h" -#include "linux/mm.h" -#include "asm/current.h" -#include "asm/page.h" -#include "asm/pgtable.h" +#include <linux/err.h> +#include <linux/highmem.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <asm/current.h> +#include <asm/page.h> +#include <asm/pgtable.h> #include "kern_util.h" #include "os.h" -extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, - pte_t *pte_out); - -static unsigned long maybe_map(unsigned long virt, int is_write) +pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr) { - pte_t pte; - int err; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + if (mm == NULL) + return NULL; + + pgd = pgd_offset(mm, addr); + if (!pgd_present(*pgd)) + return NULL; + + pud = pud_offset(pgd, addr); + if (!pud_present(*pud)) + return NULL; - void *phys = um_virt_to_phys(current, virt, &pte); - int dummy_code; + pmd = pmd_offset(pud, addr); + if (!pmd_present(*pmd)) + return NULL; + + return pte_offset_kernel(pmd, addr); +} + +static pte_t *maybe_map(unsigned long virt, int is_write) +{ + pte_t *pte = virt_to_pte(current->mm, virt); + int err, dummy_code; - if (IS_ERR(phys) || (is_write && !pte_write(pte))) { + if ((pte == NULL) || !pte_present(*pte) || + (is_write && !pte_write(*pte))) { err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); if (err) - return -1UL; - phys = um_virt_to_phys(current, virt, NULL); + return NULL; + pte = virt_to_pte(current->mm, virt); } - if (IS_ERR(phys)) - phys = (void *) -1; + if (!pte_present(*pte)) + pte = NULL; - return (unsigned long) phys; + return pte; } static int do_op_one_page(unsigned long addr, int len, int is_write, int (*op)(unsigned long addr, int len, void *arg), void *arg) { + jmp_buf buf; struct page *page; - int n; + pte_t *pte; + int n, faulted; - addr = maybe_map(addr, is_write); - if (addr == -1UL) + pte = maybe_map(addr, is_write); + if (pte == NULL) return -1; - page = phys_to_page(addr); + page = pte_page(*pte); addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK); - n = (*op)(addr, len, arg); + current->thread.fault_catcher = &buf; + + faulted = UML_SETJMP(&buf); + if (faulted == 0) + n = (*op)(addr, len, arg); + else + n = -1; + + current->thread.fault_catcher = NULL; kunmap_atomic(page, KM_UML_USERCOPY); return n; } -static void do_buffer_op(void *jmpbuf, void *arg_ptr) +static int buffer_op(unsigned long addr, int len, int is_write, + int (*op)(unsigned long, int, void *), void *arg) { - va_list args; - unsigned long addr; - int len, is_write, size, remain, n; - int (*op)(unsigned long, int, void *); - void *arg; - int *res; - - va_copy(args, *(va_list *)arg_ptr); - addr = va_arg(args, unsigned long); - len = va_arg(args, int); - is_write = va_arg(args, int); - op = va_arg(args, void *); - arg = va_arg(args, void *); - res = va_arg(args, int *); - va_end(args); + int size, remain, n; + size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); remain = len; - current->thread.fault_catcher = jmpbuf; n = do_op_one_page(addr, size, is_write, op, arg); if (n != 0) { - *res = (n < 0 ? remain : 0); + remain = (n < 0 ? remain : 0); goto out; } addr += size; remain -= size; - if (remain == 0) { - *res = 0; + if (remain == 0) goto out; - } - while(addr < ((addr + remain) & PAGE_MASK)) { + while (addr < ((addr + remain) & PAGE_MASK)) { n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); if (n != 0) { - *res = (n < 0 ? remain : 0); + remain = (n < 0 ? remain : 0); goto out; } addr += PAGE_SIZE; remain -= PAGE_SIZE; } - if (remain == 0) { - *res = 0; + if (remain == 0) goto out; - } n = do_op_one_page(addr, remain, is_write, op, arg); - if (n != 0) - *res = (n < 0 ? remain : 0); - else *res = 0; - out: - current->thread.fault_catcher = NULL; -} - -static int buffer_op(unsigned long addr, int len, int is_write, - int (*op)(unsigned long addr, int len, void *arg), - void *arg) -{ - int faulted, res; - - faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, - &res); - if (!faulted) - return res; + if (n != 0) { + remain = (n < 0 ? remain : 0); + goto out; + } - return addr + len - (unsigned long) current->thread.fault_addr; + return 0; + out: + return remain; } static int copy_chunk_from_user(unsigned long from, int len, void *arg) diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 36d89cf8d20..e1062ec36d4 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); #include "asm/smp.h" #include "asm/processor.h" #include "asm/spinlock.h" -#include "kern_util.h" #include "kern.h" #include "irq_user.h" #include "os.h" @@ -61,7 +60,7 @@ void smp_send_stop(void) continue; os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); } - printk(KERN_INFO "done\n"); + printk(KERN_CONT "done\n"); } static cpumask_t smp_commenced_mask = CPU_MASK_NONE; @@ -75,8 +74,7 @@ static int idle_proc(void *cpup) if (err < 0) panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); - os_set_fd_async(cpu_data[cpu].ipi_pipe[0], - current->thread.mode.tt.extern_pid); + os_set_fd_async(cpu_data[cpu].ipi_pipe[0]); wmb(); if (cpu_test_and_set(cpu, cpu_callin_map)) { @@ -129,8 +127,7 @@ void smp_prepare_cpus(unsigned int maxcpus) if (err < 0) panic("CPU#0 failed to create IPI pipe, errno = %d", -err); - os_set_fd_async(cpu_data[me].ipi_pipe[0], - current->thread.mode.tt.extern_pid); + os_set_fd_async(cpu_data[me].ipi_pipe[0]); for (cpu = 1; cpu < ncpus; cpu++) { printk(KERN_INFO "Booting processor %d...\n", cpu); @@ -143,9 +140,8 @@ void smp_prepare_cpus(unsigned int maxcpus) while (waittime-- && !cpu_isset(cpu, cpu_callin_map)) cpu_relax(); - if (cpu_isset(cpu, cpu_callin_map)) - printk(KERN_INFO "done\n"); - else printk(KERN_INFO "failed\n"); + printk(KERN_INFO "%s\n", + cpu_isset(cpu, cpu_calling_map) ? "done" : "failed"); } } diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index b9d92b2089a..9cffc628a37 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -13,9 +13,6 @@ #include "asm/uaccess.h" #include "asm/unistd.h" -/* Unlocked, I don't care if this is a bit off */ -int nsyscalls = 0; - long sys_fork(void) { long ret; diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 93263571d81..56d43d0a396 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -1,38 +1,37 @@ -/* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "linux/sched.h" -#include "linux/kernel.h" -#include "linux/module.h" -#include "linux/kallsyms.h" -#include "asm/page.h" -#include "asm/processor.h" +#include <linux/kallsyms.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> #include "sysrq.h" /* Catch non-i386 SUBARCH's. */ #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) void show_trace(struct task_struct *task, unsigned long * stack) { - unsigned long addr; + unsigned long addr; - if (!stack) { + if (!stack) { stack = (unsigned long*) &stack; WARN_ON(1); } - printk("Call Trace: \n"); - while (((long) stack & (THREAD_SIZE-1)) != 0) { - addr = *stack; + printk(KERN_INFO "Call Trace: \n"); + while (((long) stack & (THREAD_SIZE-1)) != 0) { + addr = *stack; if (__kernel_text_address(addr)) { - printk("%08lx: [<%08lx>]", (unsigned long) stack, addr); - print_symbol(" %s", addr); - printk("\n"); - } - stack++; - } - printk("\n"); + printk(KERN_INFO "%08lx: [<%08lx>]", + (unsigned long) stack, addr); + print_symbol(KERN_CONT " %s", addr); + printk(KERN_CONT "\n"); + } + stack++; + } + printk(KERN_INFO "\n"); } #endif @@ -67,14 +66,13 @@ void show_stack(struct task_struct *task, unsigned long *esp) } stack = esp; - for(i = 0; i < kstack_depth_to_print; i++) { + for (i = 0; i < kstack_depth_to_print; i++) { if (kstack_end(stack)) break; if (i && ((i % 8) == 0)) - printk("\n "); + printk("\n" KERN_INFO " "); printk("%08lx ", *stack++); } - printk("Call Trace: \n"); show_trace(task, esp); } diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 1ac746a9eae..e066e84493b 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -3,12 +3,12 @@ * Licensed under the GPL */ -#include "linux/clockchips.h" -#include "linux/interrupt.h" -#include "linux/jiffies.h" -#include "linux/threads.h" -#include "asm/irq.h" -#include "asm/param.h" +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/threads.h> +#include <asm/irq.h> +#include <asm/param.h> #include "kern_util.h" #include "os.h" @@ -32,7 +32,7 @@ void timer_handler(int sig, struct uml_pt_regs *regs) static void itimer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - switch(mode) { + switch (mode) { case CLOCK_EVT_MODE_PERIODIC: set_interval(); break; diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index f4a0e407eee..d175d0566af 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -3,9 +3,10 @@ * Licensed under the GPL */ -#include "linux/mm.h" -#include "asm/pgtable.h" -#include "asm/tlbflush.h" +#include <linux/mm.h> +#include <linux/sched.h> +#include <asm/pgtable.h> +#include <asm/tlbflush.h> #include "as-layout.h" #include "mem_user.h" #include "os.h" @@ -56,7 +57,7 @@ static int do_ops(struct host_vm_change *hvc, int end, for (i = 0; i < end && !ret; i++) { op = &hvc->ops[i]; - switch(op->type) { + switch (op->type) { case MMAP: ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len, op->u.mmap.prot, op->u.mmap.fd, @@ -183,27 +184,30 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr, pte = pte_offset_kernel(pmd, addr); do { + if ((addr >= STUB_START) && (addr < STUB_END)) + continue; + r = pte_read(*pte); w = pte_write(*pte); x = pte_exec(*pte); if (!pte_young(*pte)) { r = 0; w = 0; - } else if (!pte_dirty(*pte)) { + } else if (!pte_dirty(*pte)) w = 0; - } + prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | (x ? UM_PROT_EXEC : 0)); if (hvc->force || pte_newpage(*pte)) { if (pte_present(*pte)) ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, PAGE_SIZE, prot, hvc); - else ret = add_munmap(addr, PAGE_SIZE, hvc); - } - else if (pte_newprot(*pte)) + else + ret = add_munmap(addr, PAGE_SIZE, hvc); + } else if (pte_newprot(*pte)) ret = add_mprotect(addr, PAGE_SIZE, prot, hvc); *pte = pte_mkuptodate(*pte); - } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret)); + } while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret)); return ret; } @@ -225,7 +229,7 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr, } } else ret = update_pte_range(pmd, addr, next, hvc); - } while (pmd++, addr = next, ((addr != end) && !ret)); + } while (pmd++, addr = next, ((addr < end) && !ret)); return ret; } @@ -247,7 +251,7 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr, } } else ret = update_pmd_range(pud, addr, next, hvc); - } while (pud++, addr = next, ((addr != end) && !ret)); + } while (pud++, addr = next, ((addr < end) && !ret)); return ret; } @@ -270,7 +274,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, } } else ret = update_pud_range(pgd, addr, next, &hvc); - } while (pgd++, addr = next, ((addr != end_addr) && !ret)); + } while (pgd++, addr = next, ((addr < end_addr) && !ret)); if (!ret) ret = do_ops(&hvc, hvc.index, 1); @@ -485,9 +489,6 @@ void __flush_tlb_one(unsigned long addr) static void fix_range(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr, int force) { - if (!proc_mm && (end_addr > STUB_START)) - end_addr = STUB_START; - fix_range_common(mm, start_addr, end_addr, force); } @@ -499,10 +500,9 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, else fix_range(vma->vm_mm, start, end, 0); } -void flush_tlb_mm(struct mm_struct *mm) +void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, + unsigned long end) { - unsigned long end; - /* * Don't bother flushing if this address space is about to be * destroyed. @@ -510,8 +510,17 @@ void flush_tlb_mm(struct mm_struct *mm) if (atomic_read(&mm->mm_users) == 0) return; - end = proc_mm ? task_size : STUB_START; - fix_range(mm, 0, end, 0); + fix_range(mm, start, end, 0); +} + +void flush_tlb_mm(struct mm_struct *mm) +{ + struct vm_area_struct *vma = mm->mmap; + + while (vma != NULL) { + fix_range(mm, vma->vm_start, vma->vm_end, 0); + vma = vma->vm_next; + } } void force_flush_all(void) diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index cb3321f8e0a..44e49041949 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -13,6 +13,7 @@ #include "as-layout.h" #include "kern_util.h" #include "os.h" +#include "skas.h" #include "sysdep/sigcontext.h" /* @@ -128,7 +129,19 @@ static void bad_segv(struct faultinfo fi, unsigned long ip) force_sig_info(SIGSEGV, &si, current); } -static void segv_handler(int sig, struct uml_pt_regs *regs) +void fatal_sigsegv(void) +{ + force_sigsegv(SIGSEGV, current); + do_signal(); + /* + * This is to tell gcc that we're not returning - do_signal + * can, in general, return, but in this case, it's not, since + * we just got a fatal SIGSEGV queued. + */ + os_dump_core(); +} + +void segv_handler(int sig, struct uml_pt_regs *regs) { struct faultinfo * fi = UPT_FAULTINFO(regs); @@ -216,9 +229,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void relay_signal(int sig, struct uml_pt_regs *regs) { - if (arch_handle_signal(sig, regs)) - return; - if (!UPT_IS_USER(regs)) { if (sig == SIGBUS) printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " @@ -226,31 +236,24 @@ void relay_signal(int sig, struct uml_pt_regs *regs) panic("Kernel mode signal %d", sig); } + arch_examine_signal(sig, regs); + current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); force_sig(sig, current); } -static void bus_handler(int sig, struct uml_pt_regs *regs) +void bus_handler(int sig, struct uml_pt_regs *regs) { if (current->thread.fault_catcher != NULL) UML_LONGJMP(current->thread.fault_catcher, 1); else relay_signal(sig, regs); } -static void winch(int sig, struct uml_pt_regs *regs) +void winch(int sig, struct 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/uaccess.c b/arch/um/kernel/uaccess.c index d7436aacd26..f0f4b040d7c 100644 --- a/arch/um/kernel/uaccess.c +++ b/arch/um/kernel/uaccess.c @@ -1,10 +1,11 @@ /* * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -/* These are here rather than tt/uaccess.c because skas mode needs them in +/* + * These are here rather than tt/uaccess.c because skas mode needs them in * order to do SIGBUS recovery when a tmpfs mount runs out of room. */ @@ -25,6 +26,8 @@ int __do_copy_to_user(void *to, const void *from, int n, fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, __do_copy, &faulted); - if(!faulted) return(0); - else return(n - (fault - (unsigned long) to)); + if (!faulted) + return 0; + else + return n - (fault - (unsigned long) to); } diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index f1c71393f57..468aba990db 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -3,22 +3,23 @@ * Licensed under the GPL */ -#include "linux/delay.h" -#include "linux/mm.h" -#include "linux/module.h" -#include "linux/seq_file.h" -#include "linux/string.h" -#include "linux/utsname.h" -#include "asm/pgtable.h" -#include "asm/processor.h" -#include "asm/setup.h" -#include "arch.h" +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/seq_file.h> +#include <linux/string.h> +#include <linux/utsname.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/setup.h> #include "as-layout.h" +#include "arch.h" #include "init.h" #include "kern.h" +#include "kern_util.h" #include "mem_user.h" #include "os.h" -#include "skas.h" #define DEFAULT_COMMAND_LINE "root=98:0" @@ -100,8 +101,6 @@ const struct seq_operations cpuinfo_op = { }; /* Set in linux_main */ -unsigned long host_task_size; -unsigned long task_size; unsigned long uml_physmem; unsigned long uml_reserved; /* Also modified in mem_init */ unsigned long start_vm; @@ -197,20 +196,19 @@ __uml_setup("--help", Usage, " Prints this message.\n\n" ); -static int __init uml_checksetup(char *line, int *add) +static void __init uml_checksetup(char *line, int *add) { struct uml_param *p; p = &__uml_setup_start; - while(p < &__uml_setup_end) { + while (p < &__uml_setup_end) { int n; n = strlen(p->str); if (!strncmp(line, p->str, n) && p->setup_func(line + n, add)) - return 1; + return; p++; } - return 0; } static void __init uml_postsetup(void) @@ -218,13 +216,30 @@ static void __init uml_postsetup(void) initcall_t *p; p = &__uml_postsetup_start; - while(p < &__uml_postsetup_end) { + while (p < &__uml_postsetup_end) { (*p)(); p++; } return; } +static int panic_exit(struct notifier_block *self, unsigned long unused1, + void *unused2) +{ + bust_spinlocks(1); + show_regs(&(current->thread.regs)); + bust_spinlocks(0); + uml_exitcode = 1; + os_dump_core(); + return 0; +} + +static struct notifier_block panic_exit_notifier = { + .notifier_call = panic_exit, + .next = NULL, + .priority = 0 +}; + /* Set during early boot */ unsigned long brk_start; unsigned long end_iomem; @@ -234,20 +249,6 @@ EXPORT_SYMBOL(end_iomem); extern char __binary_start; -static unsigned long set_task_sizes_skas(unsigned long *task_size_out) -{ - /* Round up to the nearest 4M */ - unsigned long host_task_size = ROUND_4M((unsigned long) - &host_task_size); - - if (!skas_needs_stub) - *task_size_out = host_task_size; - else - *task_size_out = STUB_START & PGDIR_MASK; - - return host_task_size; -} - int __init linux_main(int argc, char **argv) { unsigned long avail, diff; @@ -278,13 +279,6 @@ int __init linux_main(int argc, char **argv) printf("UML running in %s mode\n", mode); - host_task_size = set_task_sizes_skas(&task_size); - - /* - * Setting up handlers to 'sig_info' struct - */ - os_fill_handlinfo(handlinfo_kern); - brk_start = (unsigned long) sbrk(0); /* @@ -309,7 +303,7 @@ int __init linux_main(int argc, char **argv) highmem = 0; iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; - max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; + max_physmem = CONFIG_TOP_ADDR - uml_physmem - iomem_size - MIN_VMALLOC; /* * Zones have to begin on a 1 << MAX_ORDER page boundary, @@ -341,7 +335,7 @@ int __init linux_main(int argc, char **argv) } virtmem_size = physmem_size; - avail = get_kmem_end() - start_vm; + avail = CONFIG_TOP_ADDR - start_vm; if (physmem_size > avail) virtmem_size = avail; end_vm = start_vm + virtmem_size; @@ -350,6 +344,9 @@ int __init linux_main(int argc, char **argv) printf("Kernel virtual memory size shrunk to %lu bytes\n", virtmem_size); + atomic_notifier_chain_register(&panic_notifier_list, + &panic_exit_notifier); + uml_postsetup(); stack_protections((unsigned long) &init_thread_info); @@ -358,29 +355,8 @@ int __init linux_main(int argc, char **argv) return start_uml(); } -extern int uml_exitcode; - -static int panic_exit(struct notifier_block *self, unsigned long unused1, - void *unused2) -{ - bust_spinlocks(1); - show_regs(&(current->thread.regs)); - bust_spinlocks(0); - uml_exitcode = 1; - os_dump_core(); - return 0; -} - -static struct notifier_block panic_exit_notifier = { - .notifier_call = panic_exit, - .next = NULL, - .priority = 0 -}; - void __init setup_arch(char **cmdline_p) { - atomic_notifier_chain_register(&panic_notifier_list, - &panic_exit_notifier); paging_init(); strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 039e16efcd5..81e07e2be3a 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -1,13 +1,12 @@ -/* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include "asm/errno.h" +#include <asm/errno.h> #include "init.h" -#include "os.h" #include "kern.h" -#include "linux/kernel.h" +#include "os.h" /* Changed by set_umid_arg */ static int umid_inited = 0; @@ -16,16 +15,16 @@ static int __init set_umid_arg(char *name, int *add) { int err; - if(umid_inited){ + if (umid_inited) { printf("umid already set\n"); return 0; } *add = 0; err = set_umid(name); - if(err == -EEXIST) + if (err == -EEXIST) printf("umid '%s' already in use\n", name); - else if(!err) + else if (!err) umid_inited = 1; return 0; diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 8e129af8170..8a48d6a3006 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -4,7 +4,7 @@ # obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ - registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \ + registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \ umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ obj-$(CONFIG_TTY_LOG) += tty_log.o @@ -12,7 +12,7 @@ user-objs-$(CONFIG_TTY_LOG) += tty_log.o USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ - trap.o tty.o tls.o uaccess.o umid.o util.o + tty.o tls.o uaccess.o umid.o util.o CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 93dc0c80eba..b8d8c9ca8d4 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -12,6 +12,7 @@ #include "aio.h" #include "init.h" #include "kern_constants.h" +#include "kern_util.h" #include "os.h" #include "user.h" diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 07ca0cb472a..6fb0b174f53 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -131,7 +131,7 @@ static int etap_tramp(char *dev, char *gate, int control_me, } if (c != 1) { printk(UM_KERN_ERR "etap_tramp : uml_net failed\n"); - err = helper_wait(pid, 0, "uml_net"); + err = helper_wait(pid); } return err; } diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 1037a3b6386..2448be03fd7 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -14,6 +14,7 @@ #include <sys/wait.h> #include <sys/uio.h> #include "kern_constants.h" +#include "kern_util.h" #include "os.h" #include "tuntap.h" #include "user.h" @@ -107,7 +108,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, "errno = %d\n", errno); return err; } - helper_wait(pid, 0, "tuntap_open_tramp"); + helper_wait(pid); cmsg = CMSG_FIRSTHDR(&msg); if (cmsg == NULL) { @@ -148,7 +149,7 @@ static int tuntap_open(void *data) memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); - if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) { + if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) { err = -errno; printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n", errno); diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index f8346275862..b5afcfd0f86 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -8,18 +8,16 @@ #include <errno.h> #include <fcntl.h> #include <signal.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> #include <sys/ioctl.h> #include <sys/mount.h> -#include <sys/uio.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> +#include "kern_constants.h" #include "os.h" #include "user.h" -#include "kern_util.h" -static void copy_stat(struct uml_stat *dst, struct stat64 *src) +static void copy_stat(struct uml_stat *dst, const struct stat64 *src) { *dst = ((struct uml_stat) { .ust_dev = src->st_dev, /* device */ @@ -43,10 +41,10 @@ int os_stat_fd(const int fd, struct uml_stat *ubuf) int err; CATCH_EINTR(err = fstat64(fd, &sbuf)); - if(err < 0) + if (err < 0) return -errno; - if(ubuf != NULL) + if (ubuf != NULL) copy_stat(ubuf, &sbuf); return err; } @@ -56,27 +54,26 @@ int os_stat_file(const char *file_name, struct uml_stat *ubuf) struct stat64 sbuf; int err; - do { - err = stat64(file_name, &sbuf); - } while((err < 0) && (errno == EINTR)) ; - - if(err < 0) + CATCH_EINTR(err = stat64(file_name, &sbuf)); + if (err < 0) return -errno; - if(ubuf != NULL) + if (ubuf != NULL) copy_stat(ubuf, &sbuf); return err; } -int os_access(const char* file, int mode) +int os_access(const char *file, int mode) { int amode, err; - amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) | - (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ; + amode = (mode & OS_ACC_R_OK ? R_OK : 0) | + (mode & OS_ACC_W_OK ? W_OK : 0) | + (mode & OS_ACC_X_OK ? X_OK : 0) | + (mode & OS_ACC_F_OK ? F_OK : 0); err = access(file, amode); - if(err < 0) + if (err < 0) return -errno; return 0; @@ -88,7 +85,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) int err; err = ioctl(fd, cmd, arg); - if(err < 0) + if (err < 0) return -errno; return err; @@ -97,7 +94,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) /* FIXME: ensure namebuf in os_get_if_name is big enough */ int os_get_ifname(int fd, char* namebuf) { - if(ioctl(fd, SIOCGIFNAME, namebuf) < 0) + if (ioctl(fd, SIOCGIFNAME, namebuf) < 0) return -errno; return 0; @@ -108,37 +105,22 @@ int os_set_slip(int fd) int disc, sencap; disc = N_SLIP; - if(ioctl(fd, TIOCSETD, &disc) < 0) + if (ioctl(fd, TIOCSETD, &disc) < 0) return -errno; sencap = 0; - if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0) + if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0) return -errno; return 0; } -int os_set_owner(int fd, int pid) -{ - if(fcntl(fd, F_SETOWN, pid) < 0){ - int save_errno = errno; - - if(fcntl(fd, F_GETOWN, 0) != pid) - return -save_errno; - } - - return 0; -} - int os_mode_fd(int fd, int mode) { int err; - do { - err = fchmod(fd, mode); - } while((err < 0) && (errno==EINTR)) ; - - if(err < 0) + CATCH_EINTR(err = fchmod(fd, mode)); + if (err < 0) return -errno; return 0; @@ -150,64 +132,73 @@ int os_file_type(char *file) int err; err = os_stat_file(file, &buf); - if(err < 0) + if (err < 0) return err; - if(S_ISDIR(buf.ust_mode)) + if (S_ISDIR(buf.ust_mode)) return OS_TYPE_DIR; - else if(S_ISLNK(buf.ust_mode)) + else if (S_ISLNK(buf.ust_mode)) return OS_TYPE_SYMLINK; - else if(S_ISCHR(buf.ust_mode)) + else if (S_ISCHR(buf.ust_mode)) return OS_TYPE_CHARDEV; - else if(S_ISBLK(buf.ust_mode)) + else if (S_ISBLK(buf.ust_mode)) return OS_TYPE_BLOCKDEV; - else if(S_ISFIFO(buf.ust_mode)) + else if (S_ISFIFO(buf.ust_mode)) return OS_TYPE_FIFO; - else if(S_ISSOCK(buf.ust_mode)) + else if (S_ISSOCK(buf.ust_mode)) return OS_TYPE_SOCK; else return OS_TYPE_FILE; } -int os_file_mode(char *file, struct openflags *mode_out) +int os_file_mode(const char *file, struct openflags *mode_out) { int err; *mode_out = OPENFLAGS(); err = access(file, W_OK); - if(err && (errno != EACCES)) + if (err && (errno != EACCES)) return -errno; - else if(!err) + else if (!err) *mode_out = of_write(*mode_out); err = access(file, R_OK); - if(err && (errno != EACCES)) + if (err && (errno != EACCES)) return -errno; - else if(!err) + else if (!err) *mode_out = of_read(*mode_out); return err; } -int os_open_file(char *file, struct openflags flags, int mode) +int os_open_file(const char *file, struct openflags flags, int mode) { int fd, err, f = 0; - if(flags.r && flags.w) f = O_RDWR; - else if(flags.r) f = O_RDONLY; - else if(flags.w) f = O_WRONLY; + if (flags.r && flags.w) + f = O_RDWR; + else if (flags.r) + f = O_RDONLY; + else if (flags.w) + f = O_WRONLY; else f = 0; - if(flags.s) f |= O_SYNC; - if(flags.c) f |= O_CREAT; - if(flags.t) f |= O_TRUNC; - if(flags.e) f |= O_EXCL; + if (flags.s) + f |= O_SYNC; + if (flags.c) + f |= O_CREAT; + if (flags.t) + f |= O_TRUNC; + if (flags.e) + f |= O_EXCL; + if (flags.a) + f |= O_APPEND; fd = open64(file, f, mode); - if(fd < 0) + if (fd < 0) return -errno; - if(flags.cl && fcntl(fd, F_SETFD, 1)){ + if (flags.cl && fcntl(fd, F_SETFD, 1)) { err = -errno; close(fd); return err; @@ -216,7 +207,7 @@ int os_open_file(char *file, struct openflags flags, int mode) return fd; } -int os_connect_socket(char *name) +int os_connect_socket(const char *name) { struct sockaddr_un sock; int fd, err; @@ -225,13 +216,13 @@ int os_connect_socket(char *name) snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(fd < 0) { + if (fd < 0) { err = -errno; goto out; } err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); - if(err) { + if (err) { err = -errno; goto out_close; } @@ -254,7 +245,7 @@ int os_seek_file(int fd, unsigned long long offset) unsigned long long actual; actual = lseek64(fd, offset, SEEK_SET); - if(actual != offset) + if (actual != offset) return -errno; return 0; } @@ -263,7 +254,7 @@ int os_read_file(int fd, void *buf, int len) { int n = read(fd, buf, len); - if(n < 0) + if (n < 0) return -errno; return n; } @@ -272,37 +263,38 @@ int os_write_file(int fd, const void *buf, int len) { int n = write(fd, (void *) buf, len); - if(n < 0) + if (n < 0) return -errno; return n; } -int os_file_size(char *file, unsigned long long *size_out) +int os_file_size(const char *file, unsigned long long *size_out) { struct uml_stat buf; int err; err = os_stat_file(file, &buf); - if(err < 0){ - printk("Couldn't stat \"%s\" : err = %d\n", file, -err); + if (err < 0) { + printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file, + -err); return err; } - if(S_ISBLK(buf.ust_mode)){ + if (S_ISBLK(buf.ust_mode)) { int fd; long blocks; fd = open(file, O_RDONLY, 0); - if(fd < 0) { + if (fd < 0) { err = -errno; - printk("Couldn't open \"%s\", errno = %d\n", file, - errno); + printk(UM_KERN_ERR "Couldn't open \"%s\", " + "errno = %d\n", file, errno); return err; } - if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ + if (ioctl(fd, BLKGETSIZE, &blocks) < 0) { err = -errno; - printk("Couldn't get the block size of \"%s\", " - "errno = %d\n", file, errno); + printk(UM_KERN_ERR "Couldn't get the block size of " + "\"%s\", errno = %d\n", file, errno); close(fd); return err; } @@ -314,14 +306,15 @@ int os_file_size(char *file, unsigned long long *size_out) return 0; } -int os_file_modtime(char *file, unsigned long *modtime) +int os_file_modtime(const char *file, unsigned long *modtime) { struct uml_stat buf; int err; err = os_stat_file(file, &buf); - if(err < 0){ - printk("Couldn't stat \"%s\" : err = %d\n", file, -err); + if (err < 0) { + printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file, + -err); return err; } @@ -329,26 +322,13 @@ int os_file_modtime(char *file, unsigned long *modtime) return 0; } -int os_get_exec_close(int fd, int *close_on_exec) -{ - int ret; - - CATCH_EINTR(ret = fcntl(fd, F_GETFD)); - - if(ret < 0) - return -errno; - - *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0; - return ret; -} - int os_set_exec_close(int fd) { int err; CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC)); - if(err < 0) + if (err < 0) return -errno; return err; } @@ -358,53 +338,51 @@ int os_pipe(int *fds, int stream, int close_on_exec) int err, type = stream ? SOCK_STREAM : SOCK_DGRAM; err = socketpair(AF_UNIX, type, 0, fds); - if(err < 0) + if (err < 0) return -errno; - if(!close_on_exec) + if (!close_on_exec) return 0; err = os_set_exec_close(fds[0]); - if(err < 0) + if (err < 0) goto error; err = os_set_exec_close(fds[1]); - if(err < 0) + if (err < 0) goto error; return 0; error: - printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); + printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n", + -err); close(fds[1]); close(fds[0]); return err; } -int os_set_fd_async(int fd, int owner) +int os_set_fd_async(int fd) { - int err; + int err, flags; + + flags = fcntl(fd, F_GETFL); + if (flags < 0) + return -errno; - /* XXX This should do F_GETFL first */ - if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ + flags |= O_ASYNC | O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) < 0) { err = -errno; - printk("os_set_fd_async : failed to set O_ASYNC and " - "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); + printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC " + "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); return err; } -#ifdef notdef - if(fcntl(fd, F_SETFD, 1) < 0){ - printk("os_set_fd_async : Setting FD_CLOEXEC failed, " - "errno = %d\n", errno); - } -#endif - if((fcntl(fd, F_SETSIG, SIGIO) < 0) || - (fcntl(fd, F_SETOWN, owner) < 0)){ + if ((fcntl(fd, F_SETSIG, SIGIO) < 0) || + (fcntl(fd, F_SETOWN, os_getpid()) < 0)) { err = -errno; - printk("os_set_fd_async : Failed to fcntl F_SETOWN " - "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, - owner, errno); + printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN " + "(or F_SETSIG) fd %d, errno = %d\n", fd, errno); return err; } @@ -413,10 +391,14 @@ int os_set_fd_async(int fd, int owner) int os_clear_fd_async(int fd) { - int flags = fcntl(fd, F_GETFL); + int flags; + + flags = fcntl(fd, F_GETFL); + if (flags < 0) + return -errno; flags &= ~(O_ASYNC | O_NONBLOCK); - if(fcntl(fd, F_SETFL, flags) < 0) + if (fcntl(fd, F_SETFL, flags) < 0) return -errno; return 0; } @@ -426,11 +408,15 @@ int os_set_fd_block(int fd, int blocking) int flags; flags = fcntl(fd, F_GETFL); + if (flags < 0) + return -errno; - if(blocking) flags &= ~O_NONBLOCK; - else flags |= O_NONBLOCK; + if (blocking) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; - if(fcntl(fd, F_SETFL, flags) < 0) + if (fcntl(fd, F_SETFL, flags) < 0) return -errno; return 0; @@ -441,7 +427,7 @@ int os_accept_connection(int fd) int new; new = accept(fd, NULL, 0); - if(new < 0) + if (new < 0) return -errno; return new; } @@ -462,15 +448,17 @@ int os_shutdown_socket(int fd, int r, int w) { int what, err; - if(r && w) what = SHUT_RDWR; - else if(r) what = SHUT_RD; - else if(w) what = SHUT_WR; - else { - printk("os_shutdown_socket : neither r or w was set\n"); + if (r && w) + what = SHUT_RDWR; + else if (r) + what = SHUT_RD; + else if (w) + what = SHUT_WR; + else return -EINVAL; - } + err = shutdown(fd, what); - if(err < 0) + if (err < 0) return -errno; return 0; } @@ -494,19 +482,20 @@ int os_rcv_fd(int fd, int *helper_pid_out) msg.msg_flags = 0; n = recvmsg(fd, &msg, 0); - if(n < 0) + if (n < 0) return -errno; - else if(n != iov.iov_len) + else if (n != iov.iov_len) *helper_pid_out = -1; cmsg = CMSG_FIRSTHDR(&msg); - if(cmsg == NULL){ - printk("rcv_fd didn't receive anything, error = %d\n", errno); + if (cmsg == NULL) { + printk(UM_KERN_ERR "rcv_fd didn't receive anything, " + "error = %d\n", errno); return -1; } - if((cmsg->cmsg_level != SOL_SOCKET) || - (cmsg->cmsg_type != SCM_RIGHTS)){ - printk("rcv_fd didn't receive a descriptor\n"); + if ((cmsg->cmsg_level != SOL_SOCKET) || + (cmsg->cmsg_type != SCM_RIGHTS)) { + printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n"); return -1; } @@ -514,29 +503,28 @@ int os_rcv_fd(int fd, int *helper_pid_out) return new; } -int os_create_unix_socket(char *file, int len, int close_on_exec) +int os_create_unix_socket(const char *file, int len, int close_on_exec) { struct sockaddr_un addr; int sock, err; sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if(sock < 0) + if (sock < 0) return -errno; - if(close_on_exec) { + if (close_on_exec) { err = os_set_exec_close(sock); - if(err < 0) - printk("create_unix_socket : close_on_exec failed, " - "err = %d", -err); + if (err < 0) + printk(UM_KERN_ERR "create_unix_socket : " + "close_on_exec failed, err = %d", -err); } addr.sun_family = AF_UNIX; - /* XXX Be more careful about overflow */ snprintf(addr.sun_path, len, "%s", file); err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); - if(err < 0) + if (err < 0) return -errno; return sock; @@ -557,17 +545,18 @@ int os_lock_file(int fd, int excl) int err, save; err = fcntl(fd, F_SETLK, &lock); - if(!err) + if (!err) goto out; save = -errno; err = fcntl(fd, F_GETLK, &lock); - if(err){ + if (err) { err = -errno; goto out; } - printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid); + printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n", + lock.l_pid); err = save; out: return err; diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index fba3f0fefee..f4bd349d441 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -1,22 +1,19 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sched.h> -#include <limits.h> -#include <sys/signal.h> -#include <sys/wait.h> #include <sys/socket.h> -#include "user.h" +#include <sys/wait.h> +#include "kern_constants.h" #include "kern_util.h" #include "os.h" #include "um_malloc.h" -#include "kern_constants.h" +#include "user.h" struct helper_data { void (*pre_exec)(void*); @@ -30,21 +27,19 @@ static int helper_child(void *arg) { struct helper_data *data = arg; char **argv = data->argv; - int errval; + int err; if (data->pre_exec != NULL) (*data->pre_exec)(data->pre_data); - errval = execvp_noalloc(data->buf, argv[0], argv); - printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], - -errval); - write(data->fd, &errval, sizeof(errval)); - kill(os_getpid(), SIGKILL); + err = execvp_noalloc(data->buf, argv[0], argv); + + /* If the exec succeeds, we don't get here */ + write(data->fd, &err, sizeof(err)); + return 0; } -/* Returns either the pid of the child process we run or -E* on failure. - * XXX The alloc_stack here breaks if this is called in the tracing thread, so - * we need to receive a preallocated stack (a local buffer is ok). */ +/* Returns either the pid of the child process we run or -E* on failure. */ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) { struct helper_data data; @@ -58,14 +53,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); if (ret < 0) { ret = -errno; - printk("run_helper : pipe failed, errno = %d\n", errno); + printk(UM_KERN_ERR "run_helper : pipe failed, errno = %d\n", + errno); goto out_free; } ret = os_set_exec_close(fds[1]); if (ret < 0) { - printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", - -ret); + printk(UM_KERN_ERR "run_helper : setting FD_CLOEXEC failed, " + "ret = %d\n", -ret); goto out_close; } @@ -79,7 +75,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) pid = clone(helper_child, (void *) sp, CLONE_VM, &data); if (pid < 0) { ret = -errno; - printk("run_helper : clone failed, errno = %d\n", errno); + printk(UM_KERN_ERR "run_helper : clone failed, errno = %d\n", + errno); goto out_free2; } @@ -96,10 +93,9 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) } else { if (n < 0) { n = -errno; - printk("run_helper : read on pipe failed, ret = %d\n", - -n); + printk(UM_KERN_ERR "run_helper : read on pipe failed, " + "ret = %d\n", -n); ret = n; - kill(pid, SIGKILL); } CATCH_EINTR(waitpid(pid, NULL, __WCLONE)); } @@ -129,50 +125,40 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, pid = clone(proc, (void *) sp, flags, arg); if (pid < 0) { err = -errno; - printk("run_helper_thread : clone failed, errno = %d\n", - errno); + printk(UM_KERN_ERR "run_helper_thread : clone failed, " + "errno = %d\n", errno); return err; } if (stack_out == NULL) { CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE)); if (pid < 0) { err = -errno; - printk("run_helper_thread - wait failed, errno = %d\n", - errno); + printk(UM_KERN_ERR "run_helper_thread - wait failed, " + "errno = %d\n", errno); pid = err; } if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) - printk("run_helper_thread - thread returned status " - "0x%x\n", status); + printk(UM_KERN_ERR "run_helper_thread - thread " + "returned status 0x%x\n", status); free_stack(stack, 0); } else *stack_out = stack; return pid; } -int helper_wait(int pid, int nohang, char *pname) +int helper_wait(int pid) { int ret, status; int wflags = __WCLONE; - if (nohang) - wflags |= WNOHANG; - - if (!pname) - pname = "helper_wait"; - CATCH_EINTR(ret = waitpid(pid, &status, wflags)); if (ret < 0) { - printk(UM_KERN_ERR "%s : waitpid process %d failed, " - "errno = %d\n", pname, pid, errno); + printk(UM_KERN_ERR "helper_wait : waitpid process %d failed, " + "errno = %d\n", pid, errno); return -errno; - } else if (nohang && ret == 0) { - printk(UM_KERN_ERR "%s : process %d has not exited\n", - pname, pid); - return -ECHILD; } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - printk(UM_KERN_ERR "%s : process %d didn't exit with " - "status 0\n", pname, pid); + printk(UM_KERN_ERR "helper_wait : process %d exited with " + "status 0x%x\n", pid, status); return -ECHILD; } else return 0; diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index 6aa6f95d652..0348b975e81 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c @@ -1,23 +1,19 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <stdlib.h> -#include <unistd.h> #include <errno.h> +#include <poll.h> #include <signal.h> #include <string.h> -#include <sys/poll.h> -#include <sys/types.h> -#include <sys/time.h> -#include "kern_util.h" -#include "user.h" -#include "process.h" -#include "sigio.h" #include "irq_user.h" +#include "kern_constants.h" #include "os.h" +#include "process.h" #include "um_malloc.h" +#include "user.h" /* * Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd @@ -36,7 +32,7 @@ int os_waiting_for_events(struct irq_fd *active_fds) if (n < 0) { err = -errno; if (errno != EINTR) - printk("sigio_handler: os_waiting_for_events:" + printk(UM_KERN_ERR "os_waiting_for_events:" " poll returned %d, errno = %d\n", n, errno); return err; } @@ -95,24 +91,26 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg, struct irq_fd *old_fd = *prev; if ((pollfds[i].fd != -1) && (pollfds[i].fd != (*prev)->fd)) { - printk("os_free_irq_by_cb - mismatch between " - "active_fds and pollfds, fd %d vs %d\n", + printk(UM_KERN_ERR "os_free_irq_by_cb - " + "mismatch between active_fds and " + "pollfds, fd %d vs %d\n", (*prev)->fd, pollfds[i].fd); goto out; } pollfds_num--; - /* This moves the *whole* array after pollfds[i] + /* + * This moves the *whole* array after pollfds[i] * (though it doesn't spot as such)! */ memmove(&pollfds[i], &pollfds[i + 1], (pollfds_num - i) * sizeof(pollfds[0])); - if(*last_irq_ptr2 == &old_fd->next) + if (*last_irq_ptr2 == &old_fd->next) *last_irq_ptr2 = prev; *prev = (*prev)->next; - if(old_fd->type == IRQ_WRITE) + if (old_fd->type == IRQ_WRITE) ignore_sigio_fd(old_fd->fd); kfree(old_fd); continue; @@ -138,14 +136,3 @@ void os_set_ioignore(void) { signal(SIGIO, SIG_IGN); } - -void init_irq_signals(int on_sigstack) -{ - int flags; - - flags = on_sigstack ? SA_ONSTACK : 0; - - set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); - signal(SIGWINCH, SIG_IGN); -} diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index 82c3778627b..abb9b0ffd96 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -73,7 +73,7 @@ static void install_fatal_handler(int sig) action.sa_handler = last_ditch_exit; if (sigaction(sig, &action, NULL) < 0) { printf("failed to install handler for signal %d - errno = %d\n", - errno); + sig, errno); exit(1); } } @@ -92,7 +92,8 @@ static void setup_env_path(void) * just use the default + /usr/lib/uml */ if (!old_path || (path_len = strlen(old_path)) == 0) { - putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH); + if (putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH)) + perror("couldn't putenv"); return; } @@ -100,15 +101,16 @@ static void setup_env_path(void) path_len += strlen("PATH=" UML_LIB_PATH) + 1; new_path = malloc(path_len); if (!new_path) { - perror("coudn't malloc to set a new PATH"); + perror("couldn't malloc to set a new PATH"); return; } snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path); - putenv(new_path); + if (putenv(new_path)) { + perror("couldn't putenv to set a new PATH"); + free(new_path); + } } -extern int uml_exitcode; - extern void scan_elf_aux( char **envp); int __init main(int argc, char **argv, char **envp) diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 436f8d20b20..eedc2d88ef8 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -9,7 +9,6 @@ #include <sys/types.h> #include <sys/mman.h> #include <sys/statfs.h> -#include "kern_util.h" #include "user.h" #include "mem_user.h" #include "init.h" @@ -30,7 +29,7 @@ static char *tempdir = NULL; static void __init find_tempdir(void) { - char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; + const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; int i; char *dir = NULL; @@ -59,9 +58,10 @@ static void __init find_tempdir(void) * read the file as needed. If there's an error, -errno is returned; * if the end of the file is reached, 0 is returned. */ -static int next(int fd, char *buf, int size, char c) +static int next(int fd, char *buf, size_t size, char c) { - int n, len; + ssize_t n; + size_t len; char *ptr; while((ptr = strchr(buf, c)) == NULL){ @@ -172,13 +172,15 @@ int __init make_tempfile(const char *template, char **out_tempname, which_tmpdir(); tempname = malloc(MAXPATHLEN); + if (!tempname) + goto out; find_tempdir(); if (template[0] != '/') strcpy(tempname, tempdir); else tempname[0] = '\0'; - strcat(tempname, template); + strncat(tempname, template, MAXPATHLEN-1-strlen(tempname)); fd = mkstemp(tempname); if(fd < 0){ fprintf(stderr, "open - cannot create %s: %s\n", tempname, @@ -268,6 +270,7 @@ void __init check_tmpexec(void) if(addr == MAP_FAILED){ err = errno; perror("failed"); + close(fd); if(err == EPERM) printf("%s must be not mounted noexec\n",tempdir); exit(1); diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index bda5c3150d6..abf6beae3df 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -249,7 +249,10 @@ void init_new_thread_signals(void) SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); signal(SIGHUP, SIG_IGN); - init_irq_signals(1); + set_handler(SIGIO, (__sighandler_t) sig_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, + SIGVTALRM, -1); + signal(SIGWINCH, SIG_IGN); } int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c index a32ba6ab121..830fe6a1518 100644 --- a/arch/um/os-Linux/registers.c +++ b/arch/um/os-Linux/registers.c @@ -8,47 +8,41 @@ #include <string.h> #include <sys/ptrace.h> #include "sysdep/ptrace.h" -#include "user.h" -/* This is set once at boot time and not changed thereafter */ - -static unsigned long exec_regs[MAX_REG_NR]; - -void init_thread_registers(struct uml_pt_regs *to) -{ - memcpy(to->gp, exec_regs, sizeof(to->gp)); -} - -void save_registers(int pid, struct uml_pt_regs *regs) +int save_registers(int pid, struct uml_pt_regs *regs) { int err; err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp); if (err < 0) - panic("save_registers - saving registers failed, errno = %d\n", - errno); + return -errno; + return 0; } -void restore_registers(int pid, struct uml_pt_regs *regs) +int restore_registers(int pid, struct uml_pt_regs *regs) { int err; err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp); if (err < 0) - panic("restore_registers - saving registers failed, " - "errno = %d\n", errno); + return -errno; + return 0; } -void init_registers(int pid) +/* This is set once at boot time and not changed thereafter */ + +static unsigned long exec_regs[MAX_REG_NR]; + +int init_registers(int pid) { int err; err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); - if (err) - panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", - errno); + if (err < 0) + return -errno; arch_init_registers(pid); + return 0; } void get_safe_registers(unsigned long *regs) diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index dc03e9cccb6..abf47a7c4ab 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c @@ -1,34 +1,33 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <unistd.h> -#include <stdlib.h> -#include <termios.h> +#include <errno.h> +#include <fcntl.h> +#include <poll.h> #include <pty.h> +#include <sched.h> #include <signal.h> -#include <fcntl.h> -#include <errno.h> #include <string.h> -#include <sched.h> -#include <sys/socket.h> -#include <sys/poll.h> -#include "init.h" -#include "user.h" +#include "kern_constants.h" #include "kern_util.h" -#include "sigio.h" +#include "init.h" #include "os.h" +#include "sigio.h" #include "um_malloc.h" -#include "init.h" +#include "user.h" -/* Protected by sigio_lock(), also used by sigio_cleanup, which is an +/* + * Protected by sigio_lock(), also used by sigio_cleanup, which is an * exitcall. */ static int write_sigio_pid = -1; static unsigned long write_sigio_stack; -/* These arrays are initialized before the sigio thread is started, and +/* + * These arrays are initialized before the sigio thread is started, and * the descriptors closed after it is killed. So, it can't see them change. * On the UML side, they are changed under the sigio_lock. */ @@ -43,7 +42,8 @@ struct pollfds { int used; }; -/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread +/* + * Protected by sigio_lock(). Used by the sigio thread, but the UML thread * synchronizes with it. */ static struct pollfds current_poll; @@ -57,23 +57,26 @@ static int write_sigio_thread(void *unused) int i, n, respond_fd; char c; - signal(SIGWINCH, SIG_IGN); + signal(SIGWINCH, SIG_IGN); fds = ¤t_poll; - while(1){ + while (1) { n = poll(fds->poll, fds->used, -1); - if(n < 0){ - if(errno == EINTR) continue; - printk("write_sigio_thread : poll returned %d, " - "errno = %d\n", n, errno); + if (n < 0) { + if (errno == EINTR) + continue; + printk(UM_KERN_ERR "write_sigio_thread : poll returned " + "%d, errno = %d\n", n, errno); } - for(i = 0; i < fds->used; i++){ + for (i = 0; i < fds->used; i++) { p = &fds->poll[i]; - if(p->revents == 0) continue; - if(p->fd == sigio_private[1]){ + if (p->revents == 0) + continue; + if (p->fd == sigio_private[1]) { CATCH_EINTR(n = read(sigio_private[1], &c, sizeof(c))); - if(n != sizeof(c)) - printk("write_sigio_thread : " + if (n != sizeof(c)) + printk(UM_KERN_ERR + "write_sigio_thread : " "read on socket failed, " "err = %d\n", errno); tmp = current_poll; @@ -89,9 +92,10 @@ static int write_sigio_thread(void *unused) } CATCH_EINTR(n = write(respond_fd, &c, sizeof(c))); - if(n != sizeof(c)) - printk("write_sigio_thread : write on socket " - "failed, err = %d\n", errno); + if (n != sizeof(c)) + printk(UM_KERN_ERR "write_sigio_thread : " + "write on socket failed, err = %d\n", + errno); } } @@ -102,12 +106,13 @@ static int need_poll(struct pollfds *polls, int n) { struct pollfd *new; - if(n <= polls->size) + if (n <= polls->size) return 0; new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); - if(new == NULL){ - printk("need_poll : failed to allocate new pollfds\n"); + if (new == NULL) { + printk(UM_KERN_ERR "need_poll : failed to allocate new " + "pollfds\n"); return -ENOMEM; } @@ -119,7 +124,8 @@ static int need_poll(struct pollfds *polls, int n) return 0; } -/* Must be called with sigio_lock held, because it's needed by the marked +/* + * Must be called with sigio_lock held, because it's needed by the marked * critical section. */ static void update_thread(void) @@ -129,15 +135,17 @@ static void update_thread(void) char c; flags = set_signals(0); - n = write(sigio_private[0], &c, sizeof(c)); - if(n != sizeof(c)){ - printk("update_thread : write failed, err = %d\n", errno); + CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c))); + if (n != sizeof(c)) { + printk(UM_KERN_ERR "update_thread : write failed, err = %d\n", + errno); goto fail; } CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c))); - if(n != sizeof(c)){ - printk("update_thread : read failed, err = %d\n", errno); + if (n != sizeof(c)) { + printk(UM_KERN_ERR "update_thread : read failed, err = %d\n", + errno); goto fail; } @@ -164,23 +172,23 @@ int add_sigio_fd(int fd) int err = 0, i, n; sigio_lock(); - for(i = 0; i < all_sigio_fds.used; i++){ - if(all_sigio_fds.poll[i].fd == fd) + for (i = 0; i < all_sigio_fds.used; i++) { + if (all_sigio_fds.poll[i].fd == fd) break; } - if(i == all_sigio_fds.used) + if (i == all_sigio_fds.used) goto out; p = &all_sigio_fds.poll[i]; - for(i = 0; i < current_poll.used; i++){ - if(current_poll.poll[i].fd == fd) + for (i = 0; i < current_poll.used; i++) { + if (current_poll.poll[i].fd == fd) goto out; } n = current_poll.used; err = need_poll(&next_poll, n + 1); - if(err) + if (err) goto out; memcpy(next_poll.poll, current_poll.poll, @@ -198,27 +206,29 @@ int ignore_sigio_fd(int fd) struct pollfd *p; int err = 0, i, n = 0; - /* This is called from exitcalls elsewhere in UML - if + /* + * This is called from exitcalls elsewhere in UML - if * sigio_cleanup has already run, then update_thread will hang * or fail because the thread is no longer running. */ - if(write_sigio_pid == -1) + if (write_sigio_pid == -1) return -EIO; sigio_lock(); - for(i = 0; i < current_poll.used; i++){ - if(current_poll.poll[i].fd == fd) break; + for (i = 0; i < current_poll.used; i++) { + if (current_poll.poll[i].fd == fd) + break; } - if(i == current_poll.used) + if (i == current_poll.used) goto out; err = need_poll(&next_poll, current_poll.used - 1); - if(err) + if (err) goto out; - for(i = 0; i < current_poll.used; i++){ + for (i = 0; i < current_poll.used; i++) { p = ¤t_poll.poll[i]; - if(p->fd != fd) + if (p->fd != fd) next_poll.poll[n++] = *p; } next_poll.used = current_poll.used - 1; @@ -235,7 +245,8 @@ static struct pollfd *setup_initial_poll(int fd) p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); if (p == NULL) { - printk("setup_initial_poll : failed to allocate poll\n"); + printk(UM_KERN_ERR "setup_initial_poll : failed to allocate " + "poll\n"); return NULL; } *p = ((struct pollfd) { .fd = fd, @@ -261,27 +272,29 @@ static void write_sigio_workaround(void) return; err = os_pipe(l_write_sigio_fds, 1, 1); - if(err < 0){ - printk("write_sigio_workaround - os_pipe 1 failed, " + if (err < 0) { + printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, " "err = %d\n", -err); return; } err = os_pipe(l_sigio_private, 1, 1); - if(err < 0){ - printk("write_sigio_workaround - os_pipe 2 failed, " + if (err < 0) { + printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, " "err = %d\n", -err); goto out_close1; } p = setup_initial_poll(l_sigio_private[1]); - if(!p) + if (!p) goto out_close2; sigio_lock(); - /* Did we race? Don't try to optimize this, please, it's not so likely - * to happen, and no more than once at the boot. */ - if(write_sigio_pid != -1) + /* + * Did we race? Don't try to optimize this, please, it's not so likely + * to happen, and no more than once at the boot. + */ + if (write_sigio_pid != -1) goto out_free; current_poll = ((struct pollfds) { .poll = p, @@ -333,19 +346,19 @@ void maybe_sigio_broken(int fd, int read) { int err; - if(!isatty(fd)) + if (!isatty(fd)) return; - if((read || pty_output_sigio) && (!read || pty_close_sigio)) + if ((read || pty_output_sigio) && (!read || pty_close_sigio)) return; write_sigio_workaround(); sigio_lock(); err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1); - if(err){ - printk("maybe_sigio_broken - failed to add pollfd for " - "descriptor %d\n", fd); + if (err) { + printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd " + "for descriptor %d\n", fd); goto out; } @@ -388,7 +401,7 @@ static void openpty_cb(void *arg) struct openpty_arg *info = arg; info->err = 0; - if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) + if (openpty(&info->master, &info->slave, NULL, NULL, NULL)) info->err = -errno; } @@ -397,17 +410,17 @@ static int async_pty(int master, int slave) int flags; flags = fcntl(master, F_GETFL); - if(flags < 0) + if (flags < 0) return -errno; - if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || - (fcntl(master, F_SETOWN, os_getpid()) < 0)) + if ((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || + (fcntl(master, F_SETOWN, os_getpid()) < 0)) return -errno; - if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) + if ((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) return -errno; - return(0); + return 0; } static void __init check_one_sigio(void (*proc)(int, int)) @@ -417,34 +430,49 @@ static void __init check_one_sigio(void (*proc)(int, int)) int master, slave, err; initial_thread_cb(openpty_cb, &pty); - if(pty.err){ - printk("openpty failed, errno = %d\n", -pty.err); + if (pty.err) { + printk(UM_KERN_ERR "check_one_sigio failed, errno = %d\n", + -pty.err); return; } master = pty.master; slave = pty.slave; - if((master == -1) || (slave == -1)){ - printk("openpty failed to allocate a pty\n"); + if ((master == -1) || (slave == -1)) { + printk(UM_KERN_ERR "check_one_sigio failed to allocate a " + "pty\n"); return; } /* Not now, but complain so we now where we failed. */ err = raw(master); - if (err < 0) - panic("check_sigio : __raw failed, errno = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "check_one_sigio : raw failed, errno = %d\n", + -err); + return; + } err = async_pty(master, slave); - if(err < 0) - panic("tty_fds : sigio_async failed, err = %d\n", -err); + if (err < 0) { + printk(UM_KERN_ERR "check_one_sigio : sigio_async failed, " + "err = %d\n", -err); + return; + } + + if (sigaction(SIGIO, NULL, &old) < 0) { + printk(UM_KERN_ERR "check_one_sigio : sigaction 1 failed, " + "errno = %d\n", errno); + return; + } - if(sigaction(SIGIO, NULL, &old) < 0) - panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); new = old; new.sa_handler = handler; - if(sigaction(SIGIO, &new, NULL) < 0) - panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); + if (sigaction(SIGIO, &new, NULL) < 0) { + printk(UM_KERN_ERR "check_one_sigio : sigaction 2 failed, " + "errno = %d\n", errno); + return; + } got_sigio = 0; (*proc)(master, slave); @@ -452,8 +480,9 @@ static void __init check_one_sigio(void (*proc)(int, int)) close(master); close(slave); - if(sigaction(SIGIO, &old, NULL) < 0) - panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); + if (sigaction(SIGIO, &old, NULL) < 0) + printk(UM_KERN_ERR "check_one_sigio : sigaction 3 failed, " + "errno = %d\n", errno); } static void tty_output(int master, int slave) @@ -461,42 +490,45 @@ static void tty_output(int master, int slave) int n; char buf[512]; - printk("Checking that host ptys support output SIGIO..."); + printk(UM_KERN_INFO "Checking that host ptys support output SIGIO..."); memset(buf, 0, sizeof(buf)); - while(write(master, buf, sizeof(buf)) > 0) ; - if(errno != EAGAIN) - panic("tty_output : write failed, errno = %d\n", errno); - while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; + while (write(master, buf, sizeof(buf)) > 0) ; + if (errno != EAGAIN) + printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n", + errno); + while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) + ; - if(got_sigio){ - printk("Yes\n"); + if (got_sigio) { + printk(UM_KERN_CONT "Yes\n"); pty_output_sigio = 1; - } - else if(n == -EAGAIN) - printk("No, enabling workaround\n"); - else panic("tty_output : read failed, err = %d\n", n); + } else if (n == -EAGAIN) + printk(UM_KERN_CONT "No, enabling workaround\n"); + else + printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n); } static void tty_close(int master, int slave) { - printk("Checking that host ptys support SIGIO on close..."); + printk(UM_KERN_INFO "Checking that host ptys support SIGIO on " + "close..."); close(slave); - if(got_sigio){ - printk("Yes\n"); + if (got_sigio) { + printk(UM_KERN_CONT "Yes\n"); pty_close_sigio = 1; - } - else printk("No, enabling workaround\n"); + } else + printk(UM_KERN_CONT "No, enabling workaround\n"); } void __init check_sigio(void) { - if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && - (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ - printk("No pseudo-terminals available - skipping pty SIGIO " - "check\n"); + if ((access("/dev/ptmx", R_OK) < 0) && + (access("/dev/ptyp0", R_OK) < 0)) { + printk(UM_KERN_WARNING "No pseudo-terminals available - " + "skipping pty SIGIO check\n"); return; } check_one_sigio(tty_output); diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index e9800b0b568..0fb0cc8d475 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -9,11 +9,47 @@ #include <errno.h> #include <signal.h> #include <strings.h> +#include "as-layout.h" +#include "kern_util.h" #include "os.h" #include "sysdep/barrier.h" #include "sysdep/sigcontext.h" #include "user.h" +/* Copied from linux/compiler-gcc.h since we can't include it directly */ +#define barrier() __asm__ __volatile__("": : :"memory") + +void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { + [SIGTRAP] = relay_signal, + [SIGFPE] = relay_signal, + [SIGILL] = relay_signal, + [SIGWINCH] = winch, + [SIGBUS] = bus_handler, + [SIGSEGV] = segv_handler, + [SIGIO] = sigio_handler, + [SIGVTALRM] = timer_handler }; + +static void sig_handler_common(int sig, struct sigcontext *sc) +{ + struct uml_pt_regs r; + int save_errno = errno; + + r.is_user = 0; + if (sig == SIGSEGV) { + /* For segfaults, we want the data from the sigcontext. */ + copy_sc(&r, sc); + GET_FAULTINFO_FROM_SC(r.faultinfo, sc); + } + + /* enable signals if sig isn't IRQ signal */ + if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) + unblock_signals(); + + (*sig_info[sig])(sig, &r); + + errno = save_errno; +} + /* * These are the asynchronous signals. SIGPROF is excluded because we want to * be able to profile all of UML, not just the non-critical sections. If @@ -26,13 +62,8 @@ #define SIGVTALRM_BIT 1 #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) -/* - * These are used by both the signal handlers and - * block/unblock_signals. I don't want modifications cached in a - * register - they must go straight to memory. - */ -static volatile int signals_enabled = 1; -static volatile int pending = 0; +static int signals_enabled; +static unsigned int signals_pending; void sig_handler(int sig, struct sigcontext *sc) { @@ -40,13 +71,13 @@ void sig_handler(int sig, struct sigcontext *sc) enabled = signals_enabled; if (!enabled && (sig == SIGIO)) { - pending |= SIGIO_MASK; + signals_pending |= SIGIO_MASK; return; } block_signals(); - sig_handler_common_skas(sig, sc); + sig_handler_common(sig, sc); set_signals(enabled); } @@ -68,7 +99,7 @@ void alarm_handler(int sig, struct sigcontext *sc) enabled = signals_enabled; if (!signals_enabled) { - pending |= SIGVTALRM_MASK; + signals_pending |= SIGVTALRM_MASK; return; } @@ -94,16 +125,6 @@ void set_sigstack(void *sig_stack, int size) panic("enabling signal stack failed, errno = %d\n", errno); } -void remove_sigstack(void) -{ - stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, - .ss_sp = NULL, - .ss_size = 0 }); - - if (sigaltstack(&stack, NULL) != 0) - panic("disabling signal stack failed, errno = %d\n", errno); -} - void (*handlers[_NSIG])(int sig, struct sigcontext *sc); void handle_signal(int sig, struct sigcontext *sc) @@ -166,6 +187,9 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) sigaddset(&action.sa_mask, mask); va_end(ap); + if (sig == SIGSEGV) + flags |= SA_NODEFER; + action.sa_flags = flags; action.sa_restorer = NULL; if (sigaction(sig, &action, NULL) < 0) @@ -179,12 +203,14 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) int change_sig(int signal, int on) { - sigset_t sigset, old; + sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, signal); - sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); - return !sigismember(&old, signal); + if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0) + return -errno; + + return 0; } void block_signals(void) @@ -196,7 +222,7 @@ void block_signals(void) * This might matter if gcc figures out how to inline this and * decides to shuffle this code into the caller. */ - mb(); + barrier(); } void unblock_signals(void) @@ -209,36 +235,26 @@ void unblock_signals(void) /* * We loop because the IRQ handler returns with interrupts off. So, * interrupts may have arrived and we need to re-enable them and - * recheck pending. + * recheck signals_pending. */ while(1) { /* * Save and reset save_pending after enabling signals. This - * way, pending won't be changed while we're reading it. + * way, signals_pending won't be changed while we're reading it. */ signals_enabled = 1; /* - * Setting signals_enabled and reading pending must + * Setting signals_enabled and reading signals_pending must * happen in this order. */ - mb(); - - save_pending = pending; - if (save_pending == 0) { - /* - * This must return with signals enabled, so - * this barrier ensures that writes are - * flushed out before the return. This might - * matter if gcc figures out how to inline - * this (unlikely, given its size) and decides - * to shuffle this code into the caller. - */ - mb(); + barrier(); + + save_pending = signals_pending; + if (save_pending == 0) return; - } - pending = 0; + signals_pending = 0; /* * We have pending interrupts, so disable signals, as the @@ -254,7 +270,7 @@ void unblock_signals(void) * back here. */ if (save_pending & SIGIO_MASK) - sig_handler_common_skas(SIGIO, NULL); + sig_handler_common(SIGIO, NULL); if (save_pending & SIGVTALRM_MASK) real_alarm_handler(NULL); diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile index 5fd8d4dad66..d2ea3409e07 100644 --- a/arch/um/os-Linux/skas/Makefile +++ b/arch/um/os-Linux/skas/Makefile @@ -1,10 +1,10 @@ # -# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) +# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) # Licensed under the GPL # -obj-y := mem.o process.o trap.o +obj-y := mem.o process.o -USER_OBJS := mem.o process.o trap.o +USER_OBJS := $(obj-y) include arch/um/scripts/Makefile.rules diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index e8b7a97e83d..d36c89c24a4 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -15,6 +15,7 @@ #include "as-layout.h" #include "chan_user.h" #include "kern_constants.h" +#include "kern_util.h" #include "mem.h" #include "os.h" #include "process.h" @@ -37,27 +38,27 @@ int is_skas_winch(int pid, int fd, void *data) static int ptrace_dump_regs(int pid) { - unsigned long regs[MAX_REG_NR]; - int i; + unsigned long regs[MAX_REG_NR]; + int i; - if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) - return -errno; + if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + return -errno; printk(UM_KERN_ERR "Stub registers -\n"); for (i = 0; i < ARRAY_SIZE(regs); i++) printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]); - return 0; + return 0; } /* * Signals that are OK to receive in the stub - we'll just continue it. * SIGWINCH will happen when UML is inside a detached screen. */ -#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH)) +#define STUB_SIG_MASK (1 << SIGVTALRM) /* Signals that the stub will finish with - anything else is an error */ -#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP)) +#define STUB_DONE_MASK (1 << SIGTRAP) void wait_stub_done(int pid) { @@ -72,9 +73,11 @@ void wait_stub_done(int pid) break; err = ptrace(PTRACE_CONT, pid, 0, 0); - if (err) - panic("wait_stub_done : continue failed, errno = %d\n", - errno); + if (err) { + printk(UM_KERN_ERR "wait_stub_done : continue failed, " + "errno = %d\n", errno); + fatal_sigsegv(); + } } if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) @@ -85,8 +88,10 @@ bad_wait: if (err) printk(UM_KERN_ERR "Failed to get registers from stub, " "errno = %d\n", -err); - panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, " - "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); + printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, " + "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno, + status); + fatal_sigsegv(); } extern unsigned long current_stub_stack(void); @@ -97,9 +102,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) if (ptrace_faultinfo) { err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); - if (err) - panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " - "errno = %d\n", errno); + if (err) { + printk(UM_KERN_ERR "get_skas_faultinfo - " + "PTRACE_FAULTINFO failed, errno = %d\n", errno); + fatal_sigsegv(); + } /* Special handling for i386, which has different structs */ if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) @@ -109,9 +116,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) } else { err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); - if (err) - panic("Failed to continue stub, pid = %d, errno = %d\n", - pid, errno); + if (err) { + printk(UM_KERN_ERR "Failed to continue stub, pid = %d, " + "errno = %d\n", pid, errno); + fatal_sigsegv(); + } wait_stub_done(pid); /* @@ -137,6 +146,9 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, { int err, status; + if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END)) + fatal_sigsegv(); + /* Mark this as a syscall */ UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp); @@ -144,25 +156,31 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, { err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); - if (err < 0) - panic("handle_trap - nullifying syscall failed, " - "errno = %d\n", errno); + if (err < 0) { + printk(UM_KERN_ERR "handle_trap - nullifying syscall " + "failed, errno = %d\n", errno); + fatal_sigsegv(); + } err = ptrace(PTRACE_SYSCALL, pid, 0, 0); - if (err < 0) - panic("handle_trap - continuing to end of syscall " - "failed, errno = %d\n", errno); + if (err < 0) { + printk(UM_KERN_ERR "handle_trap - continuing to end of " + "syscall failed, errno = %d\n", errno); + fatal_sigsegv(); + } CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL)); if ((err < 0) || !WIFSTOPPED(status) || - (WSTOPSIG(status) != SIGTRAP + 0x80)) { - err = ptrace_dump_regs(pid); - if (err) - printk(UM_KERN_ERR "Failed to get registers " + (WSTOPSIG(status) != SIGTRAP + 0x80)) { + err = ptrace_dump_regs(pid); + if (err) + printk(UM_KERN_ERR "Failed to get registers " "from process, errno = %d\n", -err); - panic("handle_trap - failed to wait at end of syscall, " - "errno = %d, status = %d\n", errno, status); - } + printk(UM_KERN_ERR "handle_trap - failed to wait at " + "end of syscall, errno = %d, status = %d\n", + errno, status); + fatal_sigsegv(); + } } handle_syscall(regs); @@ -178,10 +196,13 @@ static int userspace_tramp(void *stack) ptrace(PTRACE_TRACEME, 0, 0, 0); signal(SIGTERM, SIG_DFL); + signal(SIGWINCH, SIG_IGN); err = set_interval(); - if (err) - panic("userspace_tramp - setting timer failed, errno = %d\n", - err); + if (err) { + printk(UM_KERN_ERR "userspace_tramp - setting timer failed, " + "errno = %d\n", err); + exit(1); + } if (!proc_mm) { /* @@ -221,16 +242,14 @@ static int userspace_tramp(void *stack) set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); sigemptyset(&sa.sa_mask); - sigaddset(&sa.sa_mask, SIGIO); - sigaddset(&sa.sa_mask, SIGWINCH); - sigaddset(&sa.sa_mask, SIGVTALRM); - sigaddset(&sa.sa_mask, SIGUSR1); - sa.sa_flags = SA_ONSTACK; + sa.sa_flags = SA_ONSTACK | SA_NODEFER; sa.sa_handler = (void *) v; sa.sa_restorer = NULL; - if (sigaction(SIGSEGV, &sa, NULL) < 0) - panic("userspace_tramp - setting SIGSEGV handler " - "failed - errno = %d\n", errno); + if (sigaction(SIGSEGV, &sa, NULL) < 0) { + printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV " + "handler failed - errno = %d\n", errno); + exit(1); + } } kill(os_getpid(), SIGSTOP); @@ -246,13 +265,18 @@ int start_userspace(unsigned long stub_stack) { void *stack; unsigned long sp; - int pid, status, n, flags; + int pid, status, n, flags, err; stack = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (stack == MAP_FAILED) - panic("start_userspace : mmap failed, errno = %d", errno); + if (stack == MAP_FAILED) { + err = -errno; + printk(UM_KERN_ERR "start_userspace : mmap failed, " + "errno = %d\n", errno); + return err; + } + sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); flags = CLONE_FILES; @@ -262,29 +286,50 @@ int start_userspace(unsigned long stub_stack) flags |= SIGCHLD; pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); - if (pid < 0) - panic("start_userspace : clone failed, errno = %d", errno); + if (pid < 0) { + err = -errno; + printk(UM_KERN_ERR "start_userspace : clone failed, " + "errno = %d\n", errno); + return err; + } do { CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL)); - if (n < 0) - panic("start_userspace : wait failed, errno = %d", - errno); + if (n < 0) { + err = -errno; + printk(UM_KERN_ERR "start_userspace : wait failed, " + "errno = %d\n", errno); + goto out_kill; + } } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); - if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) - panic("start_userspace : expected SIGSTOP, got status = %d", - status); + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) { + err = -EINVAL; + printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got " + "status = %d\n", status); + goto out_kill; + } if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, - (void *) PTRACE_O_TRACESYSGOOD) < 0) - panic("start_userspace : PTRACE_OLDSETOPTIONS failed, " - "errno = %d\n", errno); + (void *) PTRACE_O_TRACESYSGOOD) < 0) { + err = -errno; + printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS " + "failed, errno = %d\n", errno); + goto out_kill; + } - if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) - panic("start_userspace : munmap failed, errno = %d\n", errno); + if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) { + err = -errno; + printk(UM_KERN_ERR "start_userspace : munmap failed, " + "errno = %d\n", errno); + goto out_kill; + } return pid; + + out_kill: + os_kill_ptraced_process(pid, 1); + return err; } void userspace(struct uml_pt_regs *regs) @@ -302,7 +347,16 @@ void userspace(struct uml_pt_regs *regs) nsecs += os_nsecs(); while (1) { - restore_registers(pid, regs); + /* + * This can legitimately fail if the process loads a + * bogus value into a segment register. It will + * segfault and PTRACE_GETREGS will read that value + * out of the process. However, PTRACE_SETREGS will + * fail. In this case, there is nothing to do but + * just kill the process. + */ + if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) + fatal_sigsegv(); /* Now we set local_using_sysemu to be used for one loop */ local_using_sysemu = get_using_sysemu(); @@ -310,19 +364,26 @@ void userspace(struct uml_pt_regs *regs) op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); - err = ptrace(op, pid, 0, 0); - if (err) - panic("userspace - could not resume userspace process, " - "pid=%d, ptrace operation = %d, errno = %d\n", - pid, op, errno); + if (ptrace(op, pid, 0, 0)) { + printk(UM_KERN_ERR "userspace - ptrace continue " + "failed, op = %d, errno = %d\n", op, errno); + fatal_sigsegv(); + } CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL)); - if (err < 0) - panic("userspace - waitpid failed, errno = %d\n", - errno); + if (err < 0) { + printk(UM_KERN_ERR "userspace - wait failed, " + "errno = %d\n", errno); + fatal_sigsegv(); + } regs->is_user = 1; - save_registers(pid, regs); + if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) { + printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, " + "errno = %d\n", errno); + fatal_sigsegv(); + } + UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ if (WIFSTOPPED(status)) { @@ -345,7 +406,7 @@ void userspace(struct uml_pt_regs *regs) break; case SIGVTALRM: now = os_nsecs(); - if(now < nsecs) + if (now < nsecs) break; block_signals(); (*sig_info[sig])(sig, regs); @@ -368,6 +429,7 @@ void userspace(struct uml_pt_regs *regs) default: printk(UM_KERN_ERR "userspace - child stopped " "with signal %d\n", sig); + fatal_sigsegv(); } pid = userspace_pid[0]; interrupt_end(); @@ -419,9 +481,12 @@ int copy_context_skas0(unsigned long new_stack, int pid) .it_interval = tv }) }); err = ptrace_setregs(pid, thread_regs); - if (err < 0) - panic("copy_context_skas0 : PTRACE_SETREGS failed, " - "pid = %d, errno = %d\n", pid, -err); + if (err < 0) { + err = -errno; + printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS " + "failed, pid = %d, errno = %d\n", pid, -err); + return err; + } /* set a well known return code for detection of child write failure */ child_data->err = 12345678; @@ -431,31 +496,47 @@ int copy_context_skas0(unsigned long new_stack, int pid) * parent's stack, and check, if bad result. */ err = ptrace(PTRACE_CONT, pid, 0, 0); - if (err) - panic("Failed to continue new process, pid = %d, " - "errno = %d\n", pid, errno); + if (err) { + err = -errno; + printk(UM_KERN_ERR "Failed to continue new process, pid = %d, " + "errno = %d\n", pid, errno); + return err; + } + wait_stub_done(pid); pid = data->err; - if (pid < 0) - panic("copy_context_skas0 - stub-parent reports error %d\n", - -pid); + if (pid < 0) { + printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports " + "error %d\n", -pid); + return pid; + } /* * Wait, until child has finished too: read child's result from * child's stack and check it. */ wait_stub_done(pid); - if (child_data->err != STUB_DATA) - panic("copy_context_skas0 - stub-child reports error %ld\n", - child_data->err); + if (child_data->err != STUB_DATA) { + printk(UM_KERN_ERR "copy_context_skas0 - stub-child reports " + "error %ld\n", child_data->err); + err = child_data->err; + goto out_kill; + } if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, - (void *)PTRACE_O_TRACESYSGOOD) < 0) - panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, " - "errno = %d\n", errno); + (void *)PTRACE_O_TRACESYSGOOD) < 0) { + err = -errno; + printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS " + "failed, errno = %d\n", errno); + goto out_kill; + } return pid; + + out_kill: + os_kill_ptraced_process(pid, 1); + return err; } /* @@ -463,8 +544,8 @@ int copy_context_skas0(unsigned long new_stack, int pid) * available. Opening /proc/mm creates a new mm_context, which lacks * the stub-pages. Thus, we map them using /proc/mm-fd */ -void map_stub_pages(int fd, unsigned long code, - unsigned long data, unsigned long stack) +int map_stub_pages(int fd, unsigned long code, unsigned long data, + unsigned long stack) { struct proc_mm_op mmop; int n; @@ -488,8 +569,9 @@ void map_stub_pages(int fd, unsigned long code, printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " "offset = %llx\n", code, code_fd, (unsigned long long) code_offset); - panic("map_stub_pages : /proc/mm map for code failed, " - "err = %d\n", n); + printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code " + "failed, err = %d\n", n); + return -n; } if (stack) { @@ -507,10 +589,15 @@ void map_stub_pages(int fd, unsigned long code, .offset = map_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); - if (n != sizeof(mmop)) - panic("map_stub_pages : /proc/mm map for data failed, " - "err = %d\n", errno); + if (n != sizeof(mmop)) { + n = errno; + printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for " + "data failed, err = %d\n", n); + return -n; + } } + + return 0; } void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) @@ -571,7 +658,9 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) kmalloc_ok = 0; return 1; default: - panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); + printk(UM_KERN_ERR "Bad sigsetjmp return in " + "start_idle_thread - %d\n", n); + fatal_sigsegv(); } longjmp(*switch_buf, 1); } @@ -614,9 +703,11 @@ void __switch_mm(struct mm_id *mm_idp) if (proc_mm) { err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); - if (err) - panic("__switch_mm - PTRACE_SWITCH_MM failed, " - "errno = %d\n", errno); + if (err) { + printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM " + "failed, errno = %d\n", errno); + fatal_sigsegv(); + } } else userspace_pid[0] = mm_idp->u.pid; } diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c deleted file mode 100644 index 3b1b9244f46..00000000000 --- a/arch/um/os-Linux/skas/trap.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#if 0 -#include "kern_util.h" -#include "skas.h" -#include "ptrace_user.h" -#include "sysdep/ptrace_user.h" -#endif - -#include <errno.h> -#include <signal.h> -#include "sysdep/ptrace.h" -#include "kern_constants.h" -#include "as-layout.h" -#include "os.h" -#include "sigcontext.h" -#include "task.h" - -static struct uml_pt_regs ksig_regs[UM_NR_CPUS]; - -void sig_handler_common_skas(int sig, void *sc_ptr) -{ - struct sigcontext *sc = sc_ptr; - struct uml_pt_regs *r; - void (*handler)(int, struct uml_pt_regs *); - int save_user, save_errno = errno; - - /* - * This is done because to allow SIGSEGV to be delivered inside a SEGV - * handler. This can happen in copy_user, and if SEGV is disabled, - * the process will die. - * XXX Figure out why this is better than SA_NODEFER - */ - if (sig == SIGSEGV) { - change_sig(SIGSEGV, 1); - /* - * For segfaults, we want the data from the - * sigcontext. In this case, we don't want to mangle - * the process registers, so use a static set of - * registers. For other signals, the process - * registers are OK. - */ - r = &ksig_regs[cpu()]; - copy_sc(r, sc_ptr); - } - else r = TASK_REGS(get_current()); - - save_user = r->is_user; - r->is_user = 0; - if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || - (sig == SIGILL) || (sig == SIGTRAP)) - GET_FAULTINFO_FROM_SC(r->faultinfo, sc); - - change_sig(SIGUSR1, 1); - - handler = sig_info[sig]; - - /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */ - if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) - unblock_signals(); - - handler(sig, r); - - errno = save_errno; - r->is_user = save_user; -} diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 7b81f6c08a5..b616e15638f 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -60,10 +60,11 @@ static int ptrace_child(void) * the UML code itself. */ ret = 2; - _exit(ret); + + exit(ret); } -static void fatal_perror(char *str) +static void fatal_perror(const char *str) { perror(str); exit(1); @@ -341,6 +342,8 @@ static void __init check_coredump_limit(void) void __init os_early_checks(void) { + int pid; + /* Print out the core dump limits early */ check_coredump_limit(); @@ -350,6 +353,11 @@ void __init os_early_checks(void) * kernel is running. */ check_tmpexec(); + + pid = start_ptraced_child(); + if (init_registers(pid)) + fatal("Failed to initialize default registers"); + stop_ptraced_child(pid, 1, 1); } static int __init noprocmm_cmd_param(char *str, int* add) @@ -411,7 +419,6 @@ static inline void check_skas3_ptrace_faultinfo(void) non_fatal("found\n"); } - init_registers(pid); stop_ptraced_child(pid, 1, 1); } @@ -466,7 +473,7 @@ static inline void check_skas3_proc_mm(void) else non_fatal("found\n"); } -int can_do_skas(void) +void can_do_skas(void) { non_fatal("Checking for the skas3 patch in the host:\n"); @@ -476,8 +483,6 @@ int can_do_skas(void) if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) skas_needs_stub = 1; - - return 1; } int __init parse_iomem(char *str, int *add) diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c deleted file mode 100644 index 2a1c9843e32..00000000000 --- a/arch/um/os-Linux/trap.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <signal.h> -#include "os.h" -#include "sysdep/ptrace.h" - -/* Initialized from linux_main() */ -void (*sig_info[NSIG])(int, struct uml_pt_regs *); - -void os_fill_handlinfo(struct kern_handlers h) -{ - sig_info[SIGTRAP] = h.relay_signal; - sig_info[SIGFPE] = h.relay_signal; - sig_info[SIGILL] = h.relay_signal; - sig_info[SIGWINCH] = h.winch; - sig_info[SIGBUS] = h.bus_handler; - sig_info[SIGSEGV] = h.page_fault; - sig_info[SIGIO] = h.sigio_handler; - sig_info[SIGVTALRM] = h.timer_handler; -} diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c index 4cfdd18ea1e..b09ff66a77e 100644 --- a/arch/um/os-Linux/tty.c +++ b/arch/um/os-Linux/tty.c @@ -1,13 +1,16 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +/* + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <stdlib.h> +#include <unistd.h> #include <errno.h> +#include <fcntl.h> +#include "kern_constants.h" +#include "kern_util.h" #include "os.h" #include "user.h" -#include "kern_util.h" struct grantpt_info { int fd; @@ -26,36 +29,34 @@ static void grantpt_cb(void *arg) int get_pty(void) { struct grantpt_info info; - int fd; - - fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0); - if(fd < 0){ - printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd); - return(fd); + int fd, err; + + fd = open("/dev/ptmx", O_RDWR); + if (fd < 0) { + err = -errno; + printk(UM_KERN_ERR "get_pty : Couldn't open /dev/ptmx - " + "err = %d\n", errno); + return err; } info.fd = fd; initial_thread_cb(grantpt_cb, &info); - if(info.res < 0){ - printk("get_pty : Couldn't grant pty - errno = %d\n", - -info.err); - return(-1); + if (info.res < 0) { + err = -info.err; + printk(UM_KERN_ERR "get_pty : Couldn't grant pty - " + "errno = %d\n", -info.err); + goto out; } - if(unlockpt(fd) < 0){ - printk("get_pty : Couldn't unlock pty - errno = %d\n", errno); - return(-1); + + if (unlockpt(fd) < 0) { + err = -errno; + printk(UM_KERN_ERR "get_pty : Couldn't unlock pty - " + "errno = %d\n", errno); + goto out; } - return(fd); + return fd; +out: + close(fd); + return err; } - -/* - * 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/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c index d11a55baa6b..cc648e6fd3a 100644 --- a/arch/um/os-Linux/tty_log.c +++ b/arch/um/os-Linux/tty_log.c @@ -12,7 +12,6 @@ #include <sys/time.h> #include "init.h" #include "user.h" -#include "kern_util.h" #include "os.h" #define TTY_LOG_DIR "./" diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 3e058ce9ffb..a6f31d47699 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -88,21 +88,6 @@ void setup_hostinfo(char *buf, int len) host.release, host.version, host.machine); } -int setjmp_wrapper(void (*proc)(void *, void *), ...) -{ - va_list args; - jmp_buf buf; - int n; - - n = UML_SETJMP(&buf); - if(n == 0){ - va_start(args, proc); - (*proc)(&buf, &args); - } - va_end(args); - return n; -} - void os_dump_core(void) { int pid; diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c index a4360b5207d..8d4f273f121 100644 --- a/arch/um/sys-i386/bug.c +++ b/arch/um/sys-i386/bug.c @@ -4,6 +4,7 @@ */ #include <linux/uaccess.h> +#include <asm/errno.h> /* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because * that's not relevant in skas mode. diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c index 806895d73bc..a74442d1376 100644 --- a/arch/um/sys-i386/bugs.c +++ b/arch/um/sys-i386/bugs.c @@ -3,171 +3,47 @@ * Licensed under the GPL */ -#include <errno.h> #include <signal.h> -#include <string.h> #include "kern_constants.h" -#include "os.h" +#include "kern_util.h" +#include "longjmp.h" #include "task.h" #include "user.h" - -#define MAXTOKEN 64 +#include "sysdep/ptrace.h" /* Set during early boot */ int host_has_cmov = 1; -int host_has_xmm = 0; +static jmp_buf cmov_test_return; -static char token(int fd, char *buf, int len, char stop) +static void cmov_sigill_test_handler(int sig) { - int n; - char *ptr, *end, c; - - ptr = buf; - end = &buf[len]; - do { - n = os_read_file(fd, ptr, sizeof(*ptr)); - c = *ptr++; - if (n != sizeof(*ptr)) { - if (n == 0) - return 0; - printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, " - "err = %d\n", -n); - if (n < 0) - return n; - else return -EIO; - } - } while ((c != '\n') && (c != stop) && (ptr < end)); - - if (ptr == end) { - printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n", - stop); - return -1; - } - *(ptr - 1) = '\0'; - return c; -} - -static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) -{ - int n; - char c; - - scratch[len - 1] = '\0'; - while (1) { - c = token(fd, scratch, len - 1, ':'); - if (c <= 0) - return 0; - else if (c != ':') { - printk(UM_KERN_ERR "Failed to find ':' in " - "/proc/cpuinfo\n"); - return 0; - } - - if (!strncmp(scratch, key, strlen(key))) - return 1; - - do { - n = os_read_file(fd, &c, sizeof(c)); - if (n != sizeof(c)) { - printk(UM_KERN_ERR "Failed to find newline in " - "/proc/cpuinfo, err = %d\n", -n); - return 0; - } - } while (c != '\n'); - } - return 0; + host_has_cmov = 0; + longjmp(cmov_test_return, 1); } -static int check_cpu_flag(char *feature, int *have_it) -{ - char buf[MAXTOKEN], c; - int fd, len = ARRAY_SIZE(buf); - - printk(UM_KERN_INFO "Checking for host processor %s support...", - feature); - fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); - if (fd < 0) { - printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n", - -fd); - return 0; - } - - *have_it = 0; - if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf))) - goto out; - - c = token(fd, buf, len - 1, ' '); - if (c < 0) - goto out; - else if (c != ' ') { - printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n"); - goto out; - } - - while (1) { - c = token(fd, buf, len - 1, ' '); - if (c < 0) - goto out; - else if (c == '\n') - break; - - if (!strcmp(buf, feature)) { - *have_it = 1; - goto out; - } - } - out: - if (*have_it == 0) - printk("No\n"); - else if (*have_it == 1) - printk("Yes\n"); - os_close_file(fd); - return 1; -} - -#if 0 /* - * This doesn't work in tt mode, plus it's causing compilation problems - * for some people. - */ -static void disable_lcall(void) +void arch_check_bugs(void) { - struct modify_ldt_ldt_s ldt; - int err; + struct sigaction old, new; - bzero(&ldt, sizeof(ldt)); - ldt.entry_number = 7; - ldt.base_addr = 0; - ldt.limit = 0; - err = modify_ldt(1, &ldt, sizeof(ldt)); - if (err) - printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n", - errno); -} -#endif + printk(UM_KERN_INFO "Checking for host processor cmov support..."); + new.sa_handler = cmov_sigill_test_handler; -void arch_init_thread(void) -{ -#if 0 - disable_lcall(); -#endif -} + /* Make sure that SIGILL is enabled after the handler longjmps back */ + new.sa_flags = SA_NODEFER; + sigemptyset(&new.sa_mask); + sigaction(SIGILL, &new, &old); -void arch_check_bugs(void) -{ - int have_it; + if (setjmp(cmov_test_return) == 0) { + unsigned long foo = 0; + __asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo)); + printk(UM_KERN_CONT "Yes\n"); + } else + printk(UM_KERN_CONT "No\n"); - if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) { - printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU " - "capability checks\n"); - return; - } - if (check_cpu_flag("cmov", &have_it)) - host_has_cmov = have_it; - if (check_cpu_flag("xmm", &have_it)) - host_has_xmm = have_it; + sigaction(SIGILL, &old, &new); } -int arch_handle_signal(int sig, struct uml_pt_regs *regs) +void arch_examine_signal(int sig, struct uml_pt_regs *regs) { unsigned char tmp[2]; @@ -176,24 +52,25 @@ int arch_handle_signal(int sig, struct uml_pt_regs *regs) * SIGILL in init. */ if ((sig != SIGILL) || (TASK_PID(get_current()) != 1)) - return 0; + return; + + if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) { + printk(UM_KERN_ERR "SIGILL in init, could not read " + "instructions!\n"); + return; + } - if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) - panic("SIGILL in init, could not read instructions!\n"); if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) - return 0; + return; if (host_has_cmov == 0) - panic("SIGILL caused by cmov, which this processor doesn't " - "implement, boot a filesystem compiled for older " - "processors"); + printk(UM_KERN_ERR "SIGILL caused by cmov, which this " + "processor doesn't implement. Boot a filesystem " + "compiled for older processors"); else if (host_has_cmov == 1) - panic("SIGILL caused by cmov, which this processor claims to " - "implement"); - else if (host_has_cmov == -1) - panic("SIGILL caused by cmov, couldn't tell if this processor " - "implements it, boot a filesystem compiled for older " - "processors"); - else panic("Bad value for host_has_cmov (%d)", host_has_cmov); - return 0; + printk(UM_KERN_ERR "SIGILL caused by cmov, which this " + "processor claims to implement"); + else + printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)", + host_has_cmov); } diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 67c0958eb98..a34263e6b08 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -3,8 +3,9 @@ * Licensed under the GPL */ -#include "linux/mm.h" -#include "asm/unistd.h" +#include <linux/mm.h> +#include <linux/sched.h> +#include <asm/unistd.h> #include "os.h" #include "proc_mm.h" #include "skas.h" @@ -146,7 +147,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) if (ptrace_ldt) return read_ldt_from_host(ptr, bytecount); - down(&ldt->semaphore); + mutex_lock(&ldt->lock); if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; if (size > bytecount) @@ -170,7 +171,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) ptr += size; } } - up(&ldt->semaphore); + mutex_unlock(&ldt->lock); if (bytecount == 0 || err == -EFAULT) goto out; @@ -228,7 +229,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) } if (!ptrace_ldt) - down(&ldt->semaphore); + mutex_lock(&ldt->lock); err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); if (err) @@ -288,7 +289,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) err = 0; out_unlock: - up(&ldt->semaphore); + mutex_unlock(&ldt->lock); out: return err; } @@ -395,7 +396,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) if (!ptrace_ldt) - init_MUTEX(&new_mm->ldt.semaphore); + mutex_init(&new_mm->ldt.lock); if (!from_mm) { memset(&desc, 0, sizeof(desc)); @@ -455,7 +456,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) * i.e., we have to use the stub for modify_ldt, which * can't handle the big read buffer of up to 64kB. */ - down(&from_mm->ldt.semaphore); + mutex_lock(&from_mm->ldt.lock); if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES) memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, sizeof(new_mm->ldt.u.entries)); @@ -474,7 +475,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) } } new_mm->ldt.entry_count = from_mm->ldt.entry_count; - up(&from_mm->ldt.semaphore); + mutex_unlock(&from_mm->ldt.lock); } out: diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index bd3da8a61f6..6b4499906a6 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -8,11 +8,11 @@ #include "asm/uaccess.h" #include "skas.h" -extern int arch_switch_tls(struct task_struct *from, struct task_struct *to); +extern int arch_switch_tls(struct task_struct *to); -void arch_switch_to(struct task_struct *from, struct task_struct *to) +void arch_switch_to(struct task_struct *to) { - int err = arch_switch_tls(from, to); + int err = arch_switch_tls(to); if (!err) return; diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c index 5cf97bc229b..0b10c3e7402 100644 --- a/arch/um/sys-i386/ptrace_user.c +++ b/arch/um/sys-i386/ptrace_user.c @@ -19,17 +19,3 @@ int ptrace_setregs(long pid, unsigned long *regs) return -errno; return 0; } - -int ptrace_getfpregs(long pid, unsigned long *regs) -{ - if (ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0) - return -errno; - return 0; -} - -int ptrace_setfpregs(long pid, unsigned long *regs) -{ - if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0) - return -errno; - return 0; -} diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 19053d46cb6..fd0c25ad6af 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c @@ -168,12 +168,13 @@ static int copy_sc_from_user(struct pt_regs *regs, struct sigcontext __user *from) { struct sigcontext sc; - int err; + int err, pid; err = copy_from_user(&sc, from, sizeof(sc)); if (err) return err; + pid = userspace_pid[current_thread_info()->cpu]; copy_sc(®s->regs, &sc); if (have_fpx_regs) { struct user_fxsr_struct fpx; @@ -187,8 +188,7 @@ static int copy_sc_from_user(struct pt_regs *regs, if (err) return 1; - err = restore_fpx_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fpx); + err = restore_fpx_registers(pid, (unsigned long *) &fpx); if (err < 0) { printk(KERN_ERR "copy_sc_from_user - " "restore_fpx_registers failed, errno = %d\n", @@ -204,8 +204,7 @@ static int copy_sc_from_user(struct pt_regs *regs, if (err) return 1; - err = restore_fp_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fp); + err = restore_fp_registers(pid, (unsigned long *) &fp); if (err < 0) { printk(KERN_ERR "copy_sc_from_user - " "restore_fp_registers failed, errno = %d\n", @@ -223,7 +222,7 @@ static int copy_sc_to_user(struct sigcontext __user *to, { struct sigcontext sc; struct faultinfo * fi = ¤t->thread.arch.faultinfo; - int err; + int err, pid; sc.gs = REGS_GS(regs->regs.gp); sc.fs = REGS_FS(regs->regs.gp); @@ -249,11 +248,11 @@ static int copy_sc_to_user(struct sigcontext __user *to, to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); sc.fpstate = to_fp; + pid = userspace_pid[current_thread_info()->cpu]; if (have_fpx_regs) { struct user_fxsr_struct fpx; - err = save_fpx_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fpx); + err = save_fpx_registers(pid, (unsigned long *) &fpx); if (err < 0){ printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " "failed, errno = %d\n", err); @@ -276,8 +275,7 @@ static int copy_sc_to_user(struct sigcontext __user *to, else { struct user_i387_struct fp; - err = save_fp_registers(userspace_pid[current_thread->cpu], - (unsigned long *) &fp); + err = save_fp_registers(pid, (unsigned long *) &fp); if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) return 1; } diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S index e730772c401..7699e89f660 100644 --- a/arch/um/sys-i386/stub.S +++ b/arch/um/sys-i386/stub.S @@ -7,7 +7,7 @@ .globl batch_syscall_stub batch_syscall_stub: /* load pointer to first operation */ - mov $(ASM_STUB_DATA+8), %esp + mov $(STUB_DATA+8), %esp again: /* load length of additional data */ @@ -15,12 +15,12 @@ again: /* if(length == 0) : end of list */ /* write possible 0 to header */ - mov %eax, ASM_STUB_DATA+4 + mov %eax, STUB_DATA+4 cmpl $0, %eax jz done /* save current pointer */ - mov %esp, ASM_STUB_DATA+4 + mov %esp, STUB_DATA+4 /* skip additional data */ add %eax, %esp @@ -46,7 +46,7 @@ again: done: /* save return value */ - mov %eax, ASM_STUB_DATA + mov %eax, STUB_DATA /* stop */ int3 diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c index b3999cb76bf..28ccf737a79 100644 --- a/arch/um/sys-i386/stub_segv.c +++ b/arch/um/sys-i386/stub_segv.c @@ -1,32 +1,17 @@ /* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <signal.h> -#include <sys/select.h> /* The only way I can see to get sigset_t */ -#include <asm/unistd.h> -#include "as-layout.h" -#include "uml-config.h" #include "sysdep/stub.h" #include "sysdep/sigcontext.h" -#include "sysdep/faultinfo.h" void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig) { struct sigcontext *sc = (struct sigcontext *) (&sig + 1); - int pid; GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc); - pid = stub_syscall0(__NR_getpid); - stub_syscall2(__NR_kill, pid, SIGUSR1); - - /* Load pointer to sigcontext into esp, since we need to leave - * the stack in its original form when we do the sigreturn here, by - * hand. - */ - __asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; " - "int $0x80" : : "a" (sc), "g" (__NR_sigreturn)); + trap_myself(); } diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S index 12d4148dba3..00e5f5203ee 100644 --- a/arch/um/sys-i386/sys_call_table.S +++ b/arch/um/sys-i386/sys_call_table.S @@ -9,4 +9,9 @@ #define old_mmap old_mmap_i386 +.section .rodata,"a" + #include "../../x86/kernel/syscall_table_32.S" + +ENTRY(syscall_table_size) +.long .-sys_call_table diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c index fcaff86b000..c6c7131e563 100644 --- a/arch/um/sys-i386/tls.c +++ b/arch/um/sys-i386/tls.c @@ -26,6 +26,11 @@ int do_set_thread_area(struct user_desc *info) cpu = get_cpu(); ret = os_set_thread_area(info, userspace_pid[cpu]); put_cpu(); + + if (ret) + printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, " + "index = %d\n", ret, info->entry_number); + return ret; } @@ -37,6 +42,11 @@ int do_get_thread_area(struct user_desc *info) cpu = get_cpu(); ret = os_get_thread_area(info, userspace_pid[cpu]); put_cpu(); + + if (ret) + printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, " + "index = %d\n", ret, info->entry_number); + return ret; } @@ -172,7 +182,7 @@ void clear_flushed_tls(struct task_struct *task) * SKAS patch. */ -int arch_switch_tls(struct task_struct *from, struct task_struct *to) +int arch_switch_tls(struct task_struct *to) { if (!host_supports_tls) return 0; @@ -225,7 +235,8 @@ out: } /* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */ -static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx) +static int get_tls_entry(struct task_struct *task, struct user_desc *info, + int idx) { struct thread_struct *t = &task->thread; @@ -263,7 +274,7 @@ clear: goto out; } -asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc) +int sys_set_thread_area(struct user_desc __user *user_desc) { struct user_desc info; int idx, ret; @@ -298,7 +309,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc) * i386. However the only possible error are caused by bugs. */ int ptrace_set_thread_area(struct task_struct *child, int idx, - struct user_desc __user *user_desc) + struct user_desc __user *user_desc) { struct user_desc info; @@ -311,7 +322,7 @@ int ptrace_set_thread_area(struct task_struct *child, int idx, return set_tls_entry(child, &info, idx, 0); } -asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc) +int sys_get_thread_area(struct user_desc __user *user_desc) { struct user_desc info; int idx, ret; @@ -355,10 +366,9 @@ out: return ret; } - /* - * XXX: This part is probably common to i386 and x86-64. Don't create a common - * file for now, do that when implementing x86-64 support. + * This code is really i386-only, but it detects and logs x86_64 GDT indexes + * if a 32-bit UML is running on a 64-bit host. */ static int __init __setup_host_supports_tls(void) { @@ -367,13 +377,16 @@ static int __init __setup_host_supports_tls(void) printk(KERN_INFO "Host TLS support detected\n"); printk(KERN_INFO "Detected host type: "); switch (host_gdt_entry_tls_min) { - case GDT_ENTRY_TLS_MIN_I386: - printk("i386\n"); - break; - case GDT_ENTRY_TLS_MIN_X86_64: - printk("x86_64\n"); - break; + case GDT_ENTRY_TLS_MIN_I386: + printk(KERN_CONT "i386"); + break; + case GDT_ENTRY_TLS_MIN_X86_64: + printk(KERN_CONT "x86_64"); + break; } + printk(KERN_CONT " (GDT indexes %d to %d)\n", + host_gdt_entry_tls_min, + host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES); } else printk(KERN_ERR " Host TLS support NOT detected! " "TLS support inside UML will not work\n"); diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile index a9814a7ae60..08901526e89 100644 --- a/arch/um/sys-ppc/Makefile +++ b/arch/um/sys-ppc/Makefile @@ -6,7 +6,7 @@ OBJ = built-in.o OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \ ptrace_user.o sysrq.o -EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(TOPDIR)/arch/ppc/kernel +EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel all: $(OBJ) @@ -22,25 +22,25 @@ sigcontext.o: sigcontext.c semaphore.c: rm -f $@ - ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ + ln -s $(srctree)/arch/ppc/kernel/$@ $@ checksum.S: rm -f $@ - ln -s $(TOPDIR)/arch/ppc/lib/$@ $@ + ln -s $(srctree)/arch/ppc/lib/$@ $@ mk_defs.c: rm -f $@ - ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ + ln -s $(srctree)/arch/ppc/kernel/$@ $@ ppc_defs.head: rm -f $@ - ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ + ln -s $(srctree)/arch/ppc/kernel/$@ $@ ppc_defs.h: mk_defs.c ppc_defs.head \ - $(TOPDIR)/include/asm-ppc/mmu.h \ - $(TOPDIR)/include/asm-ppc/processor.h \ - $(TOPDIR)/include/asm-ppc/pgtable.h \ - $(TOPDIR)/include/asm-ppc/ptrace.h + $(srctree)/include/asm-ppc/mmu.h \ + $(srctree)/include/asm-ppc/processor.h \ + $(srctree)/include/asm-ppc/pgtable.h \ + $(srctree)/include/asm-ppc/ptrace.h # $(CC) $(CFLAGS) -S mk_defs.c cp ppc_defs.head ppc_defs.h # for bk, this way we can write to the file even if it's not checked out @@ -56,13 +56,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \ checksum.o: checksum.S rm -f asm - ln -s $(TOPDIR)/include/asm-ppc asm + ln -s $(srctree)/include/asm-ppc asm $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o rm -f asm misc.o: misc.S ppc_defs.h rm -f asm - ln -s $(TOPDIR)/include/asm-ppc asm + ln -s $(srctree)/include/asm-ppc asm $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o rm -f asm diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c index a4360b5207d..e8034e363d8 100644 --- a/arch/um/sys-x86_64/bug.c +++ b/arch/um/sys-x86_64/bug.c @@ -5,7 +5,8 @@ #include <linux/uaccess.h> -/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because +/* + * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because * that's not relevant in skas mode. */ diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c index 506b6765bbc..44e02ba2a26 100644 --- a/arch/um/sys-x86_64/bugs.c +++ b/arch/um/sys-x86_64/bugs.c @@ -6,15 +6,10 @@ #include "sysdep/ptrace.h" -void arch_init_thread(void) -{ -} - void arch_check_bugs(void) { } -int arch_handle_signal(int sig, struct uml_pt_regs *regs) +void arch_examine_signal(int sig, struct uml_pt_regs *regs) { - return 0; } diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index b7631b0e9dd..f3458d7d1c5 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c @@ -5,13 +5,12 @@ * Licensed under the GPL */ -#define __FRAME_OFFSETS -#include <asm/ptrace.h> +#include <linux/mm.h> #include <linux/sched.h> #include <linux/errno.h> -#include <linux/mm.h> +#define __FRAME_OFFSETS +#include <asm/ptrace.h> #include <asm/uaccess.h> -#include <asm/elf.h> /* * determines which flags the user has access to. @@ -24,12 +23,14 @@ int putreg(struct task_struct *child, int regno, unsigned long value) unsigned long tmp; #ifdef TIF_IA32 - /* Some code in the 64bit emulation may not be 64bit clean. - Don't take any chances. */ + /* + * Some code in the 64bit emulation may not be 64bit clean. + * Don't take any chances. + */ if (test_tsk_thread_flag(child, TIF_IA32)) value &= 0xffffffff; #endif - switch (regno){ + switch (regno) { case FS: case GS: case DS: @@ -66,7 +67,7 @@ int poke_user(struct task_struct *child, long addr, long data) if (addr < MAX_REG_OFFSET) return putreg(child, addr, data); else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))){ + (addr <= offsetof(struct user, u_debugreg[7]))) { addr -= offsetof(struct user, u_debugreg[0]); addr = addr >> 2; if ((addr == 4) || (addr == 5)) @@ -108,11 +109,10 @@ int peek_user(struct task_struct *child, long addr, long data) return -EIO; tmp = 0; /* Default return condition */ - if (addr < MAX_REG_OFFSET){ + if (addr < MAX_REG_OFFSET) tmp = getreg(child, addr); - } else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))){ + (addr <= offsetof(struct user, u_debugreg[7]))) { addr -= offsetof(struct user, u_debugreg[0]); addr = addr >> 2; tmp = child->thread.arch.debugregs[addr]; @@ -127,8 +127,9 @@ int is_syscall(unsigned long addr) int n; n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); - if (n){ - /* access_process_vm() grants access to vsyscall and stub, + if (n) { + /* + * access_process_vm() grants access to vsyscall and stub, * while copy_from_user doesn't. Maybe access_process_vm is * slow, but that doesn't matter, since it will be called only * in case of singlestepping, if copy_from_user failed. @@ -155,7 +156,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) return err; n = copy_to_user(buf, fpregs, sizeof(fpregs)); - if(n > 0) + if (n > 0) return -EFAULT; return n; diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c index b5f9c33e311..c57a496d3f5 100644 --- a/arch/um/sys-x86_64/ptrace_user.c +++ b/arch/um/sys-x86_64/ptrace_user.c @@ -4,55 +4,19 @@ * Licensed under the GPL */ -#include <stddef.h> #include <errno.h> #include "ptrace_user.h" -#include "user.h" -#include "kern_constants.h" int ptrace_getregs(long pid, unsigned long *regs_out) { - if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) - return(-errno); - return(0); -} - -int ptrace_setregs(long pid, unsigned long *regs) -{ - if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0) - return(-errno); + if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) + return -errno; return(0); } -int ptrace_setfpregs(long pid, unsigned long *regs) +int ptrace_setregs(long pid, unsigned long *regs_out) { - if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0) + if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0) return -errno; - return 0; -} - -void ptrace_pokeuser(unsigned long addr, unsigned long data) -{ - panic("ptrace_pokeuser"); -} - -#define DS 184 -#define ES 192 -#define __USER_DS 0x2b - -void arch_enter_kernel(void *task, int pid) -{ -} - -void arch_leave_kernel(void *task, int pid) -{ -#ifdef UM_USER_CS - if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0) - printk("POKEUSR CS failed"); -#endif - - if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0) - printk("POKEUSR DS failed"); - if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0) - printk("POKEUSR ES failed"); + return(0); } diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index 14070181407..1a899a7ed7a 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c @@ -81,7 +81,7 @@ static int copy_sc_from_user(struct pt_regs *regs, if (err) return 1; - err = restore_fp_registers(userspace_pid[current_thread->cpu], + err = restore_fp_registers(userspace_pid[current_thread_info()->cpu], (unsigned long *) &fp); if (err < 0) { printk(KERN_ERR "copy_sc_from_user - " @@ -143,7 +143,7 @@ static int copy_sc_to_user(struct sigcontext __user *to, if (err) return 1; - err = save_fp_registers(userspace_pid[current_thread->cpu], + err = save_fp_registers(userspace_pid[current_thread_info()->cpu], (unsigned long *) &fp); if (err < 0) { printk(KERN_ERR "copy_sc_from_user - restore_fp_registers " diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S index 4afe204a6af..56876876315 100644 --- a/arch/um/sys-x86_64/stub.S +++ b/arch/um/sys-x86_64/stub.S @@ -8,18 +8,18 @@ syscall_stub: /* We don't have 64-bit constants, so this constructs the address * we need. */ - movq $(ASM_STUB_DATA >> 32), %rbx + movq $(STUB_DATA >> 32), %rbx salq $32, %rbx - movq $(ASM_STUB_DATA & 0xffffffff), %rcx + movq $(STUB_DATA & 0xffffffff), %rcx or %rcx, %rbx movq %rax, (%rbx) int3 .globl batch_syscall_stub batch_syscall_stub: - mov $(ASM_STUB_DATA >> 32), %rbx + mov $(STUB_DATA >> 32), %rbx sal $32, %rbx - mov $(ASM_STUB_DATA & 0xffffffff), %rax + mov $(STUB_DATA & 0xffffffff), %rax or %rax, %rbx /* load pointer to first operation */ mov %rbx, %rsp diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index 3afb590f007..ced051afc70 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c @@ -1,51 +1,22 @@ /* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stddef.h> #include <signal.h> -#include <asm/unistd.h> #include "as-layout.h" -#include "uml-config.h" -#include "sysdep/sigcontext.h" -#include "sysdep/faultinfo.h" #include "sysdep/stub.h" - -/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition - * in the libc headers anywhere. - */ -struct rt_sigframe -{ - char *pretcode; - struct ucontext uc; - struct siginfo info; -}; - -/* Copied here from <linux/kernel.h> - we're userspace. */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) +#include "sysdep/faultinfo.h" +#include "sysdep/sigcontext.h" void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig) { struct ucontext *uc; - int pid; __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :); GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), &uc->uc_mcontext); - - pid = stub_syscall0(__NR_getpid); - stub_syscall2(__NR_kill, pid, SIGUSR1); - - /* sys_sigreturn expects that the stack pointer will be 8 bytes into - * the signal frame. So, we use the ucontext pointer, which we know - * already, to get the signal frame pointer, and add 8 to that. - */ - __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": : - "g" ((unsigned long) - container_of(uc, struct rt_sigframe, uc) + 8), - "g" (__NR_rt_sigreturn)); + trap_myself(); } + diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c index 71b2ae4ad5d..c128eb89700 100644 --- a/arch/um/sys-x86_64/syscall_table.c +++ b/arch/um/sys-x86_64/syscall_table.c @@ -1,5 +1,7 @@ -/* System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c - * with some changes for UML. */ +/* + * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c + * with some changes for UML. + */ #include <linux/linkage.h> #include <linux/sys.h> @@ -8,22 +10,26 @@ #define __NO_STUBS -/* Below you can see, in terms of #define's, the differences between the x86-64 - * and the UML syscall table. */ +/* + * Below you can see, in terms of #define's, the differences between the x86-64 + * and the UML syscall table. + */ /* Not going to be implemented by UML, since we have no hardware. */ #define stub_iopl sys_ni_syscall #define sys_ioperm sys_ni_syscall -/* The UML TLS problem. Note that x86_64 does not implement this, so the below - * is needed only for the ia32 compatibility. */ -/*#define sys_set_thread_area sys_ni_syscall -#define sys_get_thread_area sys_ni_syscall*/ +/* + * The UML TLS problem. Note that x86_64 does not implement this, so the below + * is needed only for the ia32 compatibility. + */ /* On UML we call it this way ("old" means it's not mmap2) */ #define sys_mmap old_mmap -/* On x86-64 sys_uname is actually sys_newuname plus a compatibility trick. - * See arch/x86_64/kernel/sys_x86_64.c */ +/* + * On x86-64 sys_uname is actually sys_newuname plus a compatibility trick. + * See arch/x86_64/kernel/sys_x86_64.c + */ #define sys_uname sys_uname64 #define stub_clone sys_clone @@ -46,8 +52,19 @@ typedef void (*sys_call_ptr_t)(void); extern void sys_ni_syscall(void); -sys_call_ptr_t sys_call_table[UM_NR_syscall_max+1] __cacheline_aligned = { - /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */ - [0 ... UM_NR_syscall_max] = &sys_ni_syscall, +/* + * We used to have a trick here which made sure that holes in the + * x86_64 table were filled in with sys_ni_syscall, but a comment in + * unistd_64.h says that holes aren't allowed, so the trick was + * removed. + * The trick looked like this + * [0 ... UM_NR_syscall_max] = &sys_ni_syscall + * before including unistd_64.h - the later initializations overwrote + * the sys_ni_syscall filler. + */ + +sys_call_ptr_t sys_call_table[] __cacheline_aligned = { #include <asm-x86/unistd_64.h> }; + +int syscall_table_size = sizeof(sys_call_table); diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index 86f6b18410e..f1199fd34d3 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -48,7 +48,9 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) switch (code) { case ARCH_SET_FS: case ARCH_SET_GS: - restore_registers(pid, ¤t->thread.regs.regs); + ret = restore_registers(pid, ¤t->thread.regs.regs); + if (ret) + return ret; break; case ARCH_GET_FS: case ARCH_GET_GS: @@ -70,10 +72,10 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) switch (code) { case ARCH_SET_FS: current->thread.arch.fs = (unsigned long) ptr; - save_registers(pid, ¤t->thread.regs.regs); + ret = save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_SET_GS: - save_registers(pid, ¤t->thread.regs.regs); + ret = save_registers(pid, ¤t->thread.regs.regs); break; case ARCH_GET_FS: ret = put_user(tmp, addr); @@ -105,7 +107,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp, return ret; } -void arch_switch_to(struct task_struct *from, struct task_struct *to) +void arch_switch_to(struct task_struct *to) { if ((to->thread.arch.fs == 0) || (to->mm == NULL)) return; diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c index 76544403181..f4f82beb350 100644 --- a/arch/um/sys-x86_64/sysrq.c +++ b/arch/um/sys-x86_64/sysrq.c @@ -4,32 +4,33 @@ * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/utsname.h" -#include "linux/module.h" -#include "asm/current.h" -#include "asm/ptrace.h" +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/utsname.h> +#include <asm/current.h> +#include <asm/ptrace.h> #include "sysrq.h" -void __show_regs(struct pt_regs * regs) +void __show_regs(struct pt_regs *regs) { printk("\n"); print_modules(); - printk("Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current), + printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current), current->comm, print_tainted(), init_utsname()->release); - printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff, + printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff, PT_REGS_RIP(regs)); - printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs), + printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs), PT_REGS_EFLAGS(regs)); - printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", + printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs)); - printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", + printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n", PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs)); - printk("RBP: %016lx R08: %016lx R09: %016lx\n", + printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n", PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs)); - printk("R10: %016lx R11: %016lx R12: %016lx\n", + printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n", PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs)); - printk("R13: %016lx R14: %016lx R15: %016lx\n", + printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n", PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs)); } diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c index 8b8eff1bd97..3dead392a41 100644 --- a/arch/um/sys-x86_64/um_module.c +++ b/arch/um/sys-x86_64/um_module.c @@ -1,7 +1,7 @@ #include <linux/vmalloc.h> #include <linux/moduleloader.h> -/*Copied from i386 arch/i386/kernel/module.c */ +/* Copied from i386 arch/i386/kernel/module.c */ void *module_alloc(unsigned long size) { if (size == 0) @@ -13,7 +13,9 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ + /* + * FIXME: If module_region == mod->init_region, trim exception + * table entries. + */ } |