diff options
Diffstat (limited to 'arch/um/os-Linux')
31 files changed, 1061 insertions, 1512 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 2f8c7946401..8e129af8170 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -1,23 +1,18 @@ # -# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ - sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ - user_syms.o util.o drivers/ sys-$(SUBARCH)/ - -obj-$(CONFIG_MODE_SKAS) += skas/ - -obj-$(CONFIG_MODE_TT) += tt.o -user-objs-$(CONFIG_MODE_TT) += tt.o + registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \ + umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ obj-$(CONFIG_TTY_LOG) += tty_log.o user-objs-$(CONFIG_TTY_LOG) += tty_log.o USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ - main.o mem.o process.o sigio.o signal.o start_up.o time.o trap.o tty.o \ - tls.o uaccess.o umid.o util.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 CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 59348359f9a..4158118c4a5 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -1,20 +1,19 @@ /* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <stdlib.h> #include <unistd.h> +#include <sched.h> #include <signal.h> #include <errno.h> -#include <sched.h> -#include <sys/syscall.h> -#include "os.h" +#include <sys/time.h> +#include <asm/unistd.h> #include "aio.h" #include "init.h" -#include "user.h" -#include "mode.h" #include "kern_constants.h" +#include "os.h" +#include "user.h" struct aio_thread_req { enum aio_type type; @@ -28,7 +27,8 @@ struct aio_thread_req { #if defined(HAVE_AIO_ABI) #include <linux/aio_abi.h> -/* If we have the headers, we are going to build with AIO enabled. +/* + * If we have the headers, we are going to build with AIO enabled. * If we don't have aio in libc, we define the necessary stubs here. */ @@ -52,7 +52,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, #endif -/* The AIO_MMAP cases force the mmapped page into memory here +/* + * The AIO_MMAP cases force the mmapped page into memory here * rather than in whatever place first touches the data. I used * to do this by touching the page, but that's delicate because * gcc is prone to optimizing that away. So, what's done here @@ -106,12 +107,12 @@ static int aio_thread(void *arg) signal(SIGWINCH, SIG_IGN); - while(1){ + while (1) { n = io_getevents(ctx, 1, 1, &event, NULL); - if(n < 0){ - if(errno == EINTR) + if (n < 0) { + if (errno == EINTR) continue; - printk("aio_thread - io_getevents failed, " + printk(UM_KERN_ERR "aio_thread - io_getevents failed, " "errno = %d\n", errno); } else { @@ -120,9 +121,9 @@ static int aio_thread(void *arg) .err = event.res }); reply_fd = ((struct aio_context *) reply.data)->reply_fd; err = write(reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("aio_thread - write failed, fd = %d, " - "err = %d\n", reply_fd, errno); + if (err != sizeof(reply)) + printk(UM_KERN_ERR "aio_thread - write failed, " + "fd = %d, err = %d\n", reply_fd, errno); } } return 0; @@ -137,10 +138,10 @@ static int do_not_aio(struct aio_thread_req *req) int n; actual = lseek64(req->io_fd, req->offset, SEEK_SET); - if(actual != req->offset) + if (actual != req->offset) return -errno; - switch(req->type){ + switch(req->type) { case AIO_READ: n = read(req->io_fd, req->buf, req->len); break; @@ -151,11 +152,12 @@ static int do_not_aio(struct aio_thread_req *req) n = read(req->io_fd, &c, sizeof(c)); break; default: - printk("do_not_aio - bad request type : %d\n", req->type); + printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n", + req->type); return -EINVAL; } - if(n < 0) + if (n < 0) return -errno; return 0; } @@ -173,16 +175,18 @@ static int not_aio_thread(void *arg) int err; signal(SIGWINCH, SIG_IGN); - while(1){ + while (1) { err = read(aio_req_fd_r, &req, sizeof(req)); - if(err != sizeof(req)){ - if(err < 0) - printk("not_aio_thread - read failed, " - "fd = %d, err = %d\n", aio_req_fd_r, + if (err != sizeof(req)) { + if (err < 0) + printk(UM_KERN_ERR "not_aio_thread - " + "read failed, fd = %d, err = %d\n", + aio_req_fd_r, errno); else { - printk("not_aio_thread - short read, fd = %d, " - "length = %d\n", aio_req_fd_r, err); + printk(UM_KERN_ERR "not_aio_thread - short " + "read, fd = %d, length = %d\n", + aio_req_fd_r, err); } continue; } @@ -190,9 +194,9 @@ static int not_aio_thread(void *arg) reply = ((struct aio_thread_reply) { .data = req.aio, .err = err }); err = write(req.aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("not_aio_thread - write failed, fd = %d, " - "err = %d\n", req.aio->reply_fd, errno); + if (err != sizeof(reply)) + printk(UM_KERN_ERR "not_aio_thread - write failed, " + "fd = %d, err = %d\n", req.aio->reply_fd, errno); } return 0; @@ -203,35 +207,36 @@ static int init_aio_24(void) int fds[2], err; err = os_pipe(fds, 1, 1); - if(err) + if (err) goto out; aio_req_fd_w = fds[0]; aio_req_fd_r = fds[1]; err = os_set_fd_block(aio_req_fd_w, 0); - if(err) + if (err) goto out_close_pipe; err = run_helper_thread(not_aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); - if(err < 0) + if (err < 0) goto out_close_pipe; aio_pid = err; goto out; out_close_pipe: - os_close_file(fds[0]); - os_close_file(fds[1]); + close(fds[0]); + close(fds[1]); aio_req_fd_w = -1; aio_req_fd_r = -1; out: #ifndef HAVE_AIO_ABI - printk("/usr/include/linux/aio_abi.h not present during build\n"); + printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during " + "build\n"); #endif - printk("2.6 host AIO support not used - falling back to I/O " - "thread\n"); + printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to " + "I/O thread\n"); return 0; } @@ -241,21 +246,21 @@ static int init_aio_26(void) { int err; - if(io_setup(256, &ctx)){ + if (io_setup(256, &ctx)) { err = -errno; - printk("aio_thread failed to initialize context, err = %d\n", - errno); + printk(UM_KERN_ERR "aio_thread failed to initialize context, " + "err = %d\n", errno); return err; } err = run_helper_thread(aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); - if(err < 0) + if (err < 0) return err; aio_pid = err; - printk("Using 2.6 host AIO\n"); + printk(UM_KERN_INFO "Using 2.6 host AIO\n"); return 0; } @@ -266,13 +271,13 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, int err; err = do_aio(ctx, type, io_fd, buf, len, offset, aio); - if(err){ + if (err) { reply = ((struct aio_thread_reply) { .data = aio, .err = err }); err = write(aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)){ + if (err != sizeof(reply)) { err = -errno; - printk("submit_aio_26 - write failed, " + printk(UM_KERN_ERR "submit_aio_26 - write failed, " "fd = %d, err = %d\n", aio->reply_fd, -err); } else err = 0; @@ -320,28 +325,24 @@ static int init_aio(void) { int err; - CHOOSE_MODE(({ if(!aio_24){ - printk("Disabling 2.6 AIO in tt mode\n"); - aio_24 = 1; - } }), (void) 0); - - if(!aio_24){ + if (!aio_24) { err = init_aio_26(); - if(err && (errno == ENOSYS)){ - printk("2.6 AIO not supported on the host - " - "reverting to 2.4 AIO\n"); + if (err && (errno == ENOSYS)) { + printk(UM_KERN_INFO "2.6 AIO not supported on the " + "host - reverting to 2.4 AIO\n"); aio_24 = 1; } else return err; } - if(aio_24) + if (aio_24) return init_aio_24(); return 0; } -/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio +/* + * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio * needs to be called when the kernel is running because it calls run_helper, * which needs get_free_page. exit_aio is a __uml_exitcall because the generic * kernel does not run __exitcalls on shutdown, and can't because many of them @@ -372,7 +373,7 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, int err; err = write(aio_req_fd_w, &req, sizeof(req)); - if(err == sizeof(req)) + if (err == sizeof(req)) err = 0; else err = -errno; @@ -384,9 +385,8 @@ int submit_aio(enum aio_type type, int io_fd, char *buf, int len, struct aio_context *aio) { aio->reply_fd = reply_fd; - if(aio_24) + if (aio_24) return submit_aio_24(type, io_fd, buf, len, offset, aio); - else { + else return submit_aio_26(type, io_fd, buf, len, offset, aio); - } } diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h index 57ecdaf2f67..ddffd41c3f3 100644 --- a/arch/um/os-Linux/drivers/etap.h +++ b/arch/um/os-Linux/drivers/etap.h @@ -1,8 +1,11 @@ /* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ +#ifndef __DRIVERS_ETAP_H +#define __DRIVERS_ETAP_H + #include "net_user.h" struct ethertap_data { @@ -15,13 +18,4 @@ struct ethertap_data { extern const struct net_user_info ethertap_user_info; -/* - * 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: - */ +#endif diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c index 12689141414..04f11b9f1ac 100644 --- a/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/arch/um/os-Linux/drivers/ethertap_kern.c @@ -1,16 +1,15 @@ /* - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. */ #include "linux/init.h" -#include "linux/netdevice.h" -#include "linux/etherdevice.h" -#include "net_kern.h" -#include "net_user.h" +#include <linux/netdevice.h> #include "etap.h" +#include "net_kern.h" struct ethertap_init { char *dev_name; @@ -37,32 +36,24 @@ static void etap_init(struct net_device *dev, void *data) printk("\n"); } -static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) +static int etap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { int len; - *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); - if(*skb == NULL) return(-ENOMEM); - len = net_recvfrom(fd, skb_mac_header(*skb), - (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); - if(len <= 0) return(len); - skb_pull(*skb, 2); + len = net_recvfrom(fd, skb_mac_header(skb), + skb->dev->mtu + 2 + ETH_HEADER_ETHERTAP); + if (len <= 0) + return(len); + + skb_pull(skb, 2); len -= 2; - return(len); + return len; } -static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) +static int etap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - if(skb_headroom(*skb) < 2){ - struct sk_buff *skb2; - - skb2 = skb_realloc_headroom(*skb, 2); - dev_kfree_skb(*skb); - if (skb2 == NULL) return(-ENOMEM); - *skb = skb2; - } - skb_push(*skb, 2); - return(net_send(fd, (*skb)->data, (*skb)->len)); + skb_push(skb, 2); + return net_send(fd, skb->data, skb->len); } const struct net_kern_info ethertap_kern_info = { @@ -79,15 +70,15 @@ int ethertap_setup(char *str, char **mac_out, void *data) *init = ((struct ethertap_init) { .dev_name = NULL, .gate_addr = NULL }); - if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, + if (tap_setup_common(str, "ethertap", &init->dev_name, mac_out, &init->gate_addr)) - return(0); - if(init->dev_name == NULL){ - printk("ethertap_setup : Missing tap device name\n"); - return(0); + return 0; + if (init->dev_name == NULL) { + printk(KERN_ERR "ethertap_setup : Missing tap device name\n"); + return 0; } - return(1); + return 1; } static struct transport ethertap_transport = { @@ -97,6 +88,7 @@ static struct transport ethertap_transport = { .user = ðertap_user_info, .kern = ðertap_kern_info, .private_size = sizeof(struct ethertap_data), + .setup_size = sizeof(struct ethertap_init), }; static int register_ethertap(void) diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 61d3953c7ac..4ff55360344 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. @@ -7,20 +8,16 @@ #include <stdio.h> #include <unistd.h> -#include <stddef.h> -#include <stdlib.h> -#include <sys/errno.h> +#include <errno.h> +#include <string.h> #include <sys/socket.h> #include <sys/wait.h> -#include <sys/un.h> -#include <net/if.h> -#include "user.h" -#include "kern_util.h" -#include "net_user.h" #include "etap.h" +#include "kern_constants.h" #include "os.h" +#include "net_user.h" #include "um_malloc.h" -#include "kern_constants.h" +#include "user.h" #define MAX_PACKET ETH_MAX_PACKET @@ -49,16 +46,18 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, memcpy(change.addr, addr, sizeof(change.addr)); memcpy(change.netmask, netmask, sizeof(change.netmask)); CATCH_EINTR(n = write(fd, &change, sizeof(change))); - if(n != sizeof(change)){ - printk("etap_change - request failed, err = %d\n", errno); + if (n != sizeof(change)) { + printk(UM_KERN_ERR "etap_change - request failed, err = %d\n", + errno); return; } output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); - if(output == NULL) - printk("etap_change : Failed to allocate output buffer\n"); + if (output == NULL) + printk(UM_KERN_ERR "etap_change : Failed to allocate output " + "buffer\n"); read_output(fd, output, UM_KERN_PAGE_SIZE); - if(output != NULL){ + if (output != NULL) { printk("%s", output); kfree(output); } @@ -87,11 +86,11 @@ static void etap_pre_exec(void *arg) struct etap_pre_exec_data *data = arg; dup2(data->control_remote, 1); - os_close_file(data->data_me); - os_close_file(data->control_me); + close(data->data_me); + close(data->control_me); } -static int etap_tramp(char *dev, char *gate, int control_me, +static int etap_tramp(char *dev, char *gate, int control_me, int control_remote, int data_me, int data_remote) { struct etap_pre_exec_data pe_data; @@ -101,13 +100,13 @@ static int etap_tramp(char *dev, char *gate, int control_me, char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, gate_buf, NULL }; - char *nosetup_args[] = { "uml_net", version_buf, "ethertap", + char *nosetup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, NULL }; char **args, c; sprintf(data_fd_buf, "%d", data_remote); sprintf(version_buf, "%d", UML_NET_VERSION); - if(gate != NULL){ + if (gate != NULL) { strcpy(gate_buf, gate); args = setup_args; } @@ -119,24 +118,26 @@ static int etap_tramp(char *dev, char *gate, int control_me, pe_data.data_me = data_me; pid = run_helper(etap_pre_exec, &pe_data, args); - if(pid < 0) + if (pid < 0) err = pid; - os_close_file(data_remote); - os_close_file(control_remote); + close(data_remote); + close(control_remote); CATCH_EINTR(n = read(control_me, &c, sizeof(c))); - if(n != sizeof(c)){ + if (n != sizeof(c)) { err = -errno; - printk("etap_tramp : read of status failed, err = %d\n", -err); + printk(UM_KERN_ERR "etap_tramp : read of status failed, " + "err = %d\n", -err); return err; } - if(c != 1){ - printk("etap_tramp : uml_net failed\n"); + if (c != 1) { + printk(UM_KERN_ERR "etap_tramp : uml_net failed\n"); err = -EINVAL; CATCH_EINTR(n = waitpid(pid, &status, 0)); - if(n < 0) + if (n < 0) err = -errno; - else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) - printk("uml_net didn't exit with status 1\n"); + else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) + printk(UM_KERN_ERR "uml_net didn't exit with " + "status 1\n"); } return err; } @@ -148,43 +149,56 @@ static int etap_open(void *data) int data_fds[2], control_fds[2], err, output_len; err = tap_open_common(pri->dev, pri->gate_addr); - if(err) + if (err) return err; - err = os_pipe(data_fds, 0, 0); - if(err < 0){ - printk("data os_pipe failed - err = %d\n", -err); + err = socketpair(AF_UNIX, SOCK_DGRAM, 0, data_fds); + if (err) { + err = -errno; + printk(UM_KERN_ERR "etap_open - data socketpair failed - " + "err = %d\n", errno); return err; } - err = os_pipe(control_fds, 1, 0); - if(err < 0){ - printk("control os_pipe failed - err = %d\n", -err); - return err; + err = socketpair(AF_UNIX, SOCK_STREAM, 0, control_fds); + if (err) { + err = -errno; + printk(UM_KERN_ERR "etap_open - control socketpair failed - " + "err = %d\n", errno); + goto out_close_data; } - err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], + err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], control_fds[1], data_fds[0], data_fds[1]); output_len = UM_KERN_PAGE_SIZE; output = kmalloc(output_len, UM_GFP_KERNEL); read_output(control_fds[0], output, output_len); - if(output == NULL) - printk("etap_open : failed to allocate output buffer\n"); + if (output == NULL) + printk(UM_KERN_ERR "etap_open : failed to allocate output " + "buffer\n"); else { printk("%s", output); kfree(output); } - if(err < 0){ - printk("etap_tramp failed - err = %d\n", -err); - return err; + if (err < 0) { + printk(UM_KERN_ERR "etap_tramp failed - err = %d\n", -err); + goto out_close_control; } pri->data_fd = data_fds[0]; pri->control_fd = control_fds[0]; iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); return data_fds[0]; + +out_close_control: + close(control_fds[0]); + close(control_fds[1]); +out_close_data: + close(data_fds[0]); + close(data_fds[1]); + return err; } static void etap_close(int fd, void *data) @@ -192,37 +206,41 @@ static void etap_close(int fd, void *data) struct ethertap_data *pri = data; iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); - os_close_file(fd); - os_shutdown_socket(pri->data_fd, 1, 1); - os_close_file(pri->data_fd); + close(fd); + + if (shutdown(pri->data_fd, SHUT_RDWR) < 0) + printk(UM_KERN_ERR "etap_close - shutdown data socket failed, " + "errno = %d\n", errno); + + if (shutdown(pri->control_fd, SHUT_RDWR) < 0) + printk(UM_KERN_ERR "etap_close - shutdown control socket " + "failed, errno = %d\n", errno); + + close(pri->data_fd); pri->data_fd = -1; - os_close_file(pri->control_fd); + close(pri->control_fd); pri->control_fd = -1; } -static int etap_set_mtu(int mtu, void *data) -{ - return mtu; -} - static void etap_add_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct ethertap_data *pri = data; tap_check_ips(pri->gate_addr, addr); - if(pri->control_fd == -1) + if (pri->control_fd == -1) return; etap_open_addr(addr, netmask, &pri->control_fd); } -static void etap_del_addr(unsigned char *addr, unsigned char *netmask, +static void etap_del_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct ethertap_data *pri = data; - if(pri->control_fd == -1) + if (pri->control_fd == -1) return; + etap_close_addr(addr, netmask, &pri->control_fd); } @@ -231,8 +249,8 @@ const struct net_user_info ethertap_user_info = { .open = etap_open, .close = etap_close, .remove = NULL, - .set_mtu = etap_set_mtu, .add_address = etap_add_addr, .delete_address = etap_del_addr, - .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_ETHERTAP, }; diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h index d3e8d3af624..f17c31586c8 100644 --- a/arch/um/os-Linux/drivers/tuntap.h +++ b/arch/um/os-Linux/drivers/tuntap.h @@ -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 */ @@ -19,14 +19,3 @@ struct tuntap_data { extern const struct net_user_info tuntap_user_info; #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/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c index f1714e7fb1d..9d384807b07 100644 --- a/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/arch/um/os-Linux/drivers/tuntap_kern.c @@ -1,16 +1,13 @@ -/* - * 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/stddef.h" -#include "linux/netdevice.h" -#include "linux/etherdevice.h" -#include "linux/skbuff.h" -#include "linux/init.h" -#include "asm/errno.h" +#include <linux/netdevice.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <asm/errno.h> #include "net_kern.h" -#include "net_user.h" #include "tuntap.h" struct tuntap_init { @@ -38,19 +35,15 @@ static void tuntap_init(struct net_device *dev, void *data) printk("\n"); } -static int tuntap_read(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int tuntap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); - if(*skb == NULL) return(-ENOMEM); - return(net_read(fd, skb_mac_header(*skb), - (*skb)->dev->mtu + ETH_HEADER_OTHER)); + return net_read(fd, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER); } -static int tuntap_write(int fd, struct sk_buff **skb, - struct uml_net_private *lp) +static int tuntap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) { - return(net_write(fd, (*skb)->data, (*skb)->len)); + return net_write(fd, skb->data, skb->len); } const struct net_kern_info tuntap_kern_info = { @@ -67,11 +60,11 @@ int tuntap_setup(char *str, char **mac_out, void *data) *init = ((struct tuntap_init) { .dev_name = NULL, .gate_addr = NULL }); - if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, + if (tap_setup_common(str, "tuntap", &init->dev_name, mac_out, &init->gate_addr)) - return(0); + return 0; - return(1); + return 1; } static struct transport tuntap_transport = { diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index f848b4ea934..6c55d3c8ead 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -1,27 +1,22 @@ /* - * 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 <stdio.h> -#include <stddef.h> -#include <stdlib.h> #include <unistd.h> #include <errno.h> -#include <sys/wait.h> +#include <string.h> +#include <linux/if_tun.h> +#include <net/if.h> +#include <sys/ioctl.h> #include <sys/socket.h> -#include <sys/un.h> +#include <sys/wait.h> #include <sys/uio.h> -#include <sys/ioctl.h> -#include <net/if.h> -#include <linux/if_tun.h> -#include "net_user.h" +#include "kern_constants.h" +#include "os.h" #include "tuntap.h" -#include "kern_util.h" #include "user.h" -#include "os.h" - -#define MAX_PACKET ETH_MAX_PACKET static int tuntap_user_init(void *data, void *dev) { @@ -37,7 +32,7 @@ static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, struct tuntap_data *pri = data; tap_check_ips(pri->gate_addr, addr); - if((pri->fd == -1) || pri->fixed_config) + if ((pri->fd == -1) || pri->fixed_config) return; open_addr(addr, netmask, pri->dev_name); } @@ -47,7 +42,7 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, { struct tuntap_data *pri = data; - if((pri->fd == -1) || pri->fixed_config) + if ((pri->fd == -1) || pri->fixed_config) return; close_addr(addr, netmask, pri->dev_name); } @@ -62,7 +57,7 @@ static void tuntap_pre_exec(void *arg) struct tuntap_pre_exec_data *data = arg; dup2(data->stdout, 1); - os_close_file(data->close_me); + close(data->close_me); } static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, @@ -85,14 +80,14 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, pid = run_helper(tuntap_pre_exec, &data, argv); - if(pid < 0) + if (pid < 0) return -pid; - os_close_file(remote); + close(remote); msg.msg_name = NULL; msg.msg_namelen = 0; - if(buffer != NULL){ + if (buffer != NULL) { iov = ((struct iovec) { buffer, buffer_len }); msg.msg_iov = &iov; msg.msg_iovlen = 1; @@ -106,26 +101,28 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, msg.msg_flags = 0; n = recvmsg(me, &msg, 0); *used_out = n; - if(n < 0){ + if (n < 0) { err = -errno; - printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", - errno); + printk(UM_KERN_ERR "tuntap_open_tramp : recvmsg failed - " + "errno = %d\n", errno); return err; } CATCH_EINTR(waitpid(pid, NULL, 0)); cmsg = CMSG_FIRSTHDR(&msg); - if(cmsg == NULL){ - printk("tuntap_open_tramp : didn't receive a message\n"); + if (cmsg == NULL) { + printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a " + "message\n"); return -EINVAL; } - if((cmsg->cmsg_level != SOL_SOCKET) || - (cmsg->cmsg_type != SCM_RIGHTS)){ - printk("tuntap_open_tramp : didn't receive a descriptor\n"); + if ((cmsg->cmsg_level != SOL_SOCKET) || + (cmsg->cmsg_type != SCM_RIGHTS)) { + printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a " + "descriptor\n"); return -EINVAL; } *fd_out = ((int *) CMSG_DATA(cmsg))[0]; - os_set_exec_close(*fd_out, 1); + os_set_exec_close(*fd_out); return 0; } @@ -137,47 +134,51 @@ static int tuntap_open(void *data) int err, fds[2], len, used; err = tap_open_common(pri->dev, pri->gate_addr); - if(err < 0) + if (err < 0) return err; - if(pri->fixed_config){ + if (pri->fixed_config) { pri->fd = os_open_file("/dev/net/tun", of_cloexec(of_rdwr(OPENFLAGS())), 0); - if(pri->fd < 0){ - printk("Failed to open /dev/net/tun, err = %d\n", - -pri->fd); + if (pri->fd < 0) { + printk(UM_KERN_ERR "Failed to open /dev/net/tun, " + "err = %d\n", -pri->fd); return pri->fd; } 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, (void *) &ifr) < 0) { err = -errno; - printk("TUNSETIFF failed, errno = %d\n", errno); - os_close_file(pri->fd); + printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n", + errno); + close(pri->fd); return err; } } else { - err = os_pipe(fds, 0, 0); - if(err < 0){ - printk("tuntap_open : os_pipe failed - err = %d\n", - -err); + err = socketpair(AF_UNIX, SOCK_DGRAM, 0, fds); + if (err) { + err = -errno; + printk(UM_KERN_ERR "tuntap_open : socketpair failed - " + "errno = %d\n", errno); return err; } buffer = get_output_buffer(&len); - if(buffer != NULL) len--; + if (buffer != NULL) + len--; used = 0; err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], fds[1], buffer, len, &used); output = buffer; - if(err < 0) { + if (err < 0) { printk("%s", output); free_output_buffer(buffer); - printk("tuntap_open_tramp failed - err = %d\n", -err); + printk(UM_KERN_ERR "tuntap_open_tramp failed - " + "err = %d\n", -err); return err; } @@ -186,7 +187,7 @@ static int tuntap_open(void *data) printk("%s", output); free_output_buffer(buffer); - os_close_file(fds[0]); + close(fds[0]); iter_addresses(pri->dev, open_addr, pri->dev_name); } @@ -197,24 +198,19 @@ static void tuntap_close(int fd, void *data) { struct tuntap_data *pri = data; - if(!pri->fixed_config) + if (!pri->fixed_config) iter_addresses(pri->dev, close_addr, pri->dev_name); - os_close_file(fd); + close(fd); pri->fd = -1; } -static int tuntap_set_mtu(int mtu, void *data) -{ - return mtu; -} - const struct net_user_info tuntap_user_info = { .init = tuntap_user_init, .open = tuntap_open, .close = tuntap_close, .remove = NULL, - .set_mtu = tuntap_set_mtu, .add_address = tuntap_add_addr, .delete_address = tuntap_del_addr, - .max_packet = MAX_PACKET + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, }; diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index c3ecc2a84e0..b542a3a021b 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -82,13 +82,6 @@ int os_access(const char* file, int mode) return 0; } -void os_print_error(int error, const char* str) -{ - errno = error < 0 ? -error : error; - - perror(str); -} - /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) { @@ -101,30 +94,6 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) return err; } -int os_window_size(int fd, int *rows, int *cols) -{ - struct winsize size; - - if(ioctl(fd, TIOCGWINSZ, &size) < 0) - return -errno; - - *rows = size.ws_row; - *cols = size.ws_col; - - return 0; -} - -int os_new_tty_pgrp(int fd, int pid) -{ - if(ioctl(fd, TIOCSCTTY, 0) < 0) - return -errno; - - if(tcsetpgrp(fd, pid) < 0) - return -errno; - - return 0; -} - /* FIXME: ensure namebuf in os_get_if_name is big enough */ int os_get_ifname(int fd, char* namebuf) { @@ -205,19 +174,19 @@ int os_file_mode(char *file, struct openflags *mode_out) *mode_out = OPENFLAGS(); - err = os_access(file, OS_ACC_W_OK); - if((err < 0) && (err != -EACCES)) - return(err); - - *mode_out = of_write(*mode_out); - - err = os_access(file, OS_ACC_R_OK); - if((err < 0) && (err != -EACCES)) - return(err); + err = access(file, W_OK); + if(err && (errno != EACCES)) + return -errno; + else if(!err) + *mode_out = of_write(*mode_out); - *mode_out = of_read(*mode_out); + err = access(file, R_OK); + if(err && (errno != EACCES)) + return -errno; + else if(!err) + *mode_out = of_read(*mode_out); - return(0); + return err; } int os_open_file(char *file, struct openflags flags, int mode) @@ -236,15 +205,15 @@ int os_open_file(char *file, struct openflags flags, int mode) fd = open64(file, f, mode); if(fd < 0) - return(-errno); + return -errno; if(flags.cl && fcntl(fd, F_SETFD, 1)){ err = -errno; - os_close_file(fd); + close(fd); return err; } - return(fd); + return fd; } int os_connect_socket(char *name) @@ -280,9 +249,9 @@ void os_close_file(int fd) close(fd); } -int os_seek_file(int fd, __u64 offset) +int os_seek_file(int fd, unsigned long long offset) { - __u64 actual; + unsigned long long actual; actual = lseek64(fd, offset, SEEK_SET); if(actual != offset) @@ -316,31 +285,33 @@ int os_file_size(char *file, unsigned long long *size_out) err = os_stat_file(file, &buf); if(err < 0){ printk("Couldn't stat \"%s\" : err = %d\n", file, -err); - return(err); + return err; } if(S_ISBLK(buf.ust_mode)){ int fd; long blocks; - fd = os_open_file(file, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("Couldn't open \"%s\", errno = %d\n", file, -fd); - return(fd); + fd = open(file, O_RDONLY, 0); + if(fd < 0) { + err = -errno; + printk("Couldn't open \"%s\", errno = %d\n", file, + errno); + return err; } if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ err = -errno; printk("Couldn't get the block size of \"%s\", " "errno = %d\n", file, errno); - os_close_file(fd); - return(err); + close(fd); + return err; } *size_out = ((long long) blocks) * 512; - os_close_file(fd); - return(0); + close(fd); } - *size_out = buf.ust_size; - return(0); + else *size_out = buf.ust_size; + + return 0; } int os_file_modtime(char *file, unsigned long *modtime) @@ -358,35 +329,28 @@ int os_file_modtime(char *file, unsigned long *modtime) return 0; } -int os_get_exec_close(int fd, int* close_on_exec) +int os_get_exec_close(int fd, int *close_on_exec) { int ret; - do { - ret = fcntl(fd, F_GETFD); - } while((ret < 0) && (errno == EINTR)) ; + CATCH_EINTR(ret = fcntl(fd, F_GETFD)); if(ret < 0) - return(-errno); + return -errno; - *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; - return(ret); + *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0; + return ret; } -int os_set_exec_close(int fd, int close_on_exec) +int os_set_exec_close(int fd) { - int flag, err; - - if(close_on_exec) flag = FD_CLOEXEC; - else flag = 0; + int err; - do { - err = fcntl(fd, F_SETFD, flag); - } while((err < 0) && (errno == EINTR)) ; + CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC)); if(err < 0) - return(-errno); - return(err); + return -errno; + return err; } int os_pipe(int *fds, int stream, int close_on_exec) @@ -395,16 +359,16 @@ int os_pipe(int *fds, int stream, int close_on_exec) err = socketpair(AF_UNIX, type, 0, fds); if(err < 0) - return(-errno); + return -errno; if(!close_on_exec) - return(0); + return 0; - err = os_set_exec_close(fds[0], 1); + err = os_set_exec_close(fds[0]); if(err < 0) goto error; - err = os_set_exec_close(fds[1], 1); + err = os_set_exec_close(fds[1]); if(err < 0) goto error; @@ -412,9 +376,9 @@ int os_pipe(int *fds, int stream, int close_on_exec) error: printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); - os_close_file(fds[1]); - os_close_file(fds[0]); - return(err); + close(fds[1]); + close(fds[0]); + return err; } int os_set_fd_async(int fd, int owner) @@ -561,7 +525,7 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) return -errno; if(close_on_exec) { - err = os_set_exec_close(sock, 1); + err = os_set_exec_close(sock); if(err < 0) printk("create_unix_socket : close_on_exec failed, " "err = %d", -err); diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index d81af7b8587..7a72dbb61b0 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -11,6 +11,7 @@ #include <limits.h> #include <sys/signal.h> #include <sys/wait.h> +#include <sys/socket.h> #include "user.h" #include "kern_util.h" #include "os.h" @@ -54,13 +55,14 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) if (stack == 0) return -ENOMEM; - ret = os_pipe(fds, 1, 0); + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); if (ret < 0) { - printk("run_helper : pipe failed, ret = %d\n", -ret); + ret = -errno; + printk("run_helper : pipe failed, errno = %d\n", errno); goto out_free; } - ret = os_set_exec_close(fds[1], 1); + ret = os_set_exec_close(fds[1]); if (ret < 0) { printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", -ret); diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index a633fa8e0a9..6aa6f95d652 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c @@ -145,11 +145,7 @@ void init_irq_signals(int on_sigstack) flags = on_sigstack ? SA_ONSTACK : 0; - set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, - flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); - set_handler(SIGALRM, (__sighandler_t) alarm_handler, - flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + 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 e85f4995a01..82c3778627b 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -1,33 +1,21 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <unistd.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <signal.h> +#include <unistd.h> #include <errno.h> +#include <signal.h> +#include <string.h> #include <sys/resource.h> -#include <sys/mman.h> -#include <sys/user.h> -#include <asm/page.h> -#include "kern_util.h" #include "as-layout.h" -#include "mem_user.h" -#include "irq_user.h" -#include "user.h" #include "init.h" -#include "mode.h" -#include "choose-mode.h" -#include "uml-config.h" +#include "kern_constants.h" +#include "kern_util.h" #include "os.h" #include "um_malloc.h" -#include "kern_constants.h" - -/* Set in main, unchanged thereafter */ -char *linux_prog; #define PGD_BOUND (4 * 1024 * 1024) #define STACKSIZE (8 * 1024 * 1024) @@ -37,13 +25,13 @@ static void set_stklim(void) { struct rlimit lim; - if(getrlimit(RLIMIT_STACK, &lim) < 0){ + if (getrlimit(RLIMIT_STACK, &lim) < 0) { perror("getrlimit"); exit(1); } - if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ + if ((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)) { lim.rlim_cur = STACKSIZE; - if(setrlimit(RLIMIT_STACK, &lim) < 0){ + if (setrlimit(RLIMIT_STACK, &lim) < 0) { perror("setrlimit"); exit(1); } @@ -55,7 +43,7 @@ static __init void do_uml_initcalls(void) initcall_t *call; call = &__uml_initcall_start; - while (call < &__uml_initcall_end){ + while (call < &__uml_initcall_end) { (*call)(); call++; } @@ -74,7 +62,8 @@ static void install_fatal_handler(int sig) /* All signals are enabled in this handler ... */ sigemptyset(&action.sa_mask); - /* ... including the signal being handled, plus we want the + /* + * ... including the signal being handled, plus we want the * handler reset to the default behavior, so that if an exit * handler is hanging for some reason, the UML will just die * after this signal is sent a second time. @@ -82,7 +71,7 @@ static void install_fatal_handler(int sig) action.sa_flags = SA_RESETHAND | SA_NODEFER; action.sa_restorer = NULL; action.sa_handler = last_ditch_exit; - if(sigaction(sig, &action, NULL) < 0){ + if (sigaction(sig, &action, NULL) < 0) { printf("failed to install handler for signal %d - errno = %d\n", errno); exit(1); @@ -98,7 +87,8 @@ static void setup_env_path(void) int path_len = 0; old_path = getenv("PATH"); - /* if no PATH variable is set or it has an empty value + /* + * if no PATH variable is set or it has an empty value * just use the default + /usr/lib/uml */ if (!old_path || (path_len = strlen(old_path)) == 0) { @@ -126,93 +116,68 @@ int __init main(int argc, char **argv, char **envp) char **new_argv; int ret, i, err; -#ifdef UML_CONFIG_CMDLINE_ON_HOST - /* Allocate memory for thread command lines */ - if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ - - char padding[THREAD_NAME_LEN] = { - [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' - }; - - new_argv = malloc((argc + 2) * sizeof(char*)); - if(!new_argv) { - perror("Allocating extended argv"); - exit(1); - } - - new_argv[0] = argv[0]; - new_argv[1] = padding; - - for(i = 2; i <= argc; i++) - new_argv[i] = argv[i - 1]; - new_argv[argc + 1] = NULL; - - execvp(new_argv[0], new_argv); - perror("execing with extended args"); - exit(1); - } -#endif - - linux_prog = argv[0]; - set_stklim(); setup_env_path(); new_argv = malloc((argc + 1) * sizeof(char *)); - if(new_argv == NULL){ + if (new_argv == NULL) { perror("Mallocing argv"); exit(1); } - for(i=0;i<argc;i++){ + for (i = 0; i < argc; i++) { new_argv[i] = strdup(argv[i]); - if(new_argv[i] == NULL){ + if (new_argv[i] == NULL) { perror("Mallocing an arg"); exit(1); } } new_argv[argc] = NULL; - /* Allow these signals to bring down a UML if all other + /* + * Allow these signals to bring down a UML if all other * methods of control fail. */ install_fatal_handler(SIGINT); install_fatal_handler(SIGTERM); install_fatal_handler(SIGHUP); - scan_elf_aux( envp); + scan_elf_aux(envp); do_uml_initcalls(); ret = linux_main(argc, argv); - /* Disable SIGPROF - I have no idea why libc doesn't do this or turn + /* + * Disable SIGPROF - I have no idea why libc doesn't do this or turn * off the profiling time, but UML dies with a SIGPROF just before * exiting when profiling is active. */ change_sig(SIGPROF, 0); - /* This signal stuff used to be in the reboot case. However, + /* + * This signal stuff used to be in the reboot case. However, * sometimes a SIGVTALRM can come in when we're halting (reproducably * when writing out gcov information, presumably because that takes * some time) and cause a segfault. */ - /* stop timers and set SIG*ALRM to be ignored */ + /* stop timers and set SIGVTALRM to be ignored */ disable_timer(); /* disable SIGIO for the fds and set SIGIO to be ignored */ err = deactivate_all_fds(); - if(err) + if (err) printf("deactivate_all_fds failed, errno = %d\n", -err); - /* Let any pending signals fire now. This ensures + /* + * Let any pending signals fire now. This ensures * that they won't be delivered after the exec, when * they are definitely not expected. */ unblock_signals(); /* Reboot */ - if(ret){ + if (ret) { printf("\n"); execvp(new_argv[0], new_argv); perror("Failed to exec kernel"); @@ -222,26 +187,24 @@ int __init main(int argc, char **argv, char **envp) return uml_exitcode; } -#define CAN_KMALLOC() \ - (kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1)) - extern void *__real_malloc(int); void *__wrap_malloc(int size) { void *ret; - if(!CAN_KMALLOC()) + if (!kmalloc_ok) return __real_malloc(size); - else if(size <= UM_KERN_PAGE_SIZE) + else if (size <= UM_KERN_PAGE_SIZE) /* finding contiguous pages can be hard*/ ret = kmalloc(size, UM_GFP_KERNEL); else ret = vmalloc(size); - /* glibc people insist that if malloc fails, errno should be + /* + * glibc people insist that if malloc fails, errno should be * set by malloc as well. So we do. */ - if(ret == NULL) + if (ret == NULL) errno = ENOMEM; return ret; @@ -251,7 +214,7 @@ void *__wrap_calloc(int n, int size) { void *ptr = __wrap_malloc(n * size); - if(ptr == NULL) + if (ptr == NULL) return NULL; memset(ptr, 0, n * size); return ptr; @@ -265,7 +228,8 @@ void __wrap_free(void *ptr) { unsigned long addr = (unsigned long) ptr; - /* We need to know how the allocation happened, so it can be correctly + /* + * We need to know how the allocation happened, so it can be correctly * freed. This is done by seeing what region of memory the pointer is * in - * physical memory - kmalloc/kfree @@ -283,12 +247,12 @@ void __wrap_free(void *ptr) * there is a possibility for memory leaks. */ - if((addr >= uml_physmem) && (addr < high_physmem)){ - if(CAN_KMALLOC()) + if ((addr >= uml_physmem) && (addr < high_physmem)) { + if (kmalloc_ok) kfree(ptr); } - else if((addr >= start_vm) && (addr < end_vm)){ - if(CAN_KMALLOC()) + else if ((addr >= start_vm) && (addr < end_vm)) { + if (kmalloc_ok) vfree(ptr); } else __real_free(ptr); diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index c6378c6d10d..436f8d20b20 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -218,7 +218,7 @@ int __init create_tmp_file(unsigned long long len) err = fchmod(fd, 0777); if(err < 0){ - perror("os_mode_fd"); + perror("fchmod"); exit(1); } @@ -226,7 +226,7 @@ int __init create_tmp_file(unsigned long long len) * increase the file size by one byte, to the desired length. */ if (lseek64(fd, len - 1, SEEK_SET) < 0) { - perror("os_seek_file"); + perror("lseek64"); exit(1); } @@ -247,7 +247,7 @@ int __init create_mem_file(unsigned long long len) fd = create_tmp_file(len); - err = os_set_exec_close(fd, 1); + err = os_set_exec_close(fd); if(err < 0){ errno = -err; perror("exec_close"); diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index e9c14329751..37781db4cec 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -1,27 +1,24 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) +/* + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <unistd.h> #include <stdio.h> +#include <unistd.h> #include <errno.h> #include <signal.h> +#include <fcntl.h> #include <sys/mman.h> +#include <sys/ptrace.h> #include <sys/wait.h> -#include <sys/mman.h> -#include <sys/syscall.h> -#include "ptrace_user.h" +#include <asm/unistd.h> +#include "init.h" +#include "kern_constants.h" +#include "longjmp.h" #include "os.h" -#include "user.h" #include "process.h" -#include "irq_user.h" -#include "kern_util.h" -#include "longjmp.h" #include "skas_ptrace.h" -#include "kern_constants.h" -#include "uml-config.h" -#include "init.h" +#include "user.h" #define ARBITRARY_ADDR -1 #define FAILURE_PID -1 @@ -32,30 +29,32 @@ unsigned long os_process_pc(int pid) { char proc_stat[STAT_PATH_LEN], buf[256]; - unsigned long pc; + unsigned long pc = ARBITRARY_ADDR; int fd, err; sprintf(proc_stat, "/proc/%d/stat", pid); - fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("os_process_pc - couldn't open '%s', err = %d\n", - proc_stat, -fd); - return ARBITRARY_ADDR; + fd = open(proc_stat, O_RDONLY, 0); + if (fd < 0) { + printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', " + "errno = %d\n", proc_stat, errno); + goto out; } CATCH_EINTR(err = read(fd, buf, sizeof(buf))); - if(err < 0){ - printk("os_process_pc - couldn't read '%s', err = %d\n", - proc_stat, errno); - os_close_file(fd); - return ARBITRARY_ADDR; + if (err < 0) { + printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', " + "err = %d\n", proc_stat, errno); + goto out_close; } os_close_file(fd); pc = ARBITRARY_ADDR; - if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " - "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " - "%*d %*d %*d %*d %*d %lu", &pc) != 1){ - printk("os_process_pc - couldn't find pc in '%s'\n", buf); - } + if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " + "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " + "%*d %*d %*d %*d %*d %lu", &pc) != 1) + printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n", + buf); + out_close: + close(fd); + out: return pc; } @@ -63,30 +62,32 @@ int os_process_parent(int pid) { char stat[STAT_PATH_LEN]; char data[256]; - int parent, n, fd; + int parent = FAILURE_PID, n, fd; - if(pid == -1) - return -1; + if (pid == -1) + return parent; snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); - fd = os_open_file(stat, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("Couldn't open '%s', err = %d\n", stat, -fd); - return FAILURE_PID; + fd = open(stat, O_RDONLY, 0); + if (fd < 0) { + printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat, + errno); + return parent; } CATCH_EINTR(n = read(fd, data, sizeof(data))); - os_close_file(fd); + close(fd); - if(n < 0){ - printk("Couldn't read '%s', err = %d\n", stat, errno); - return FAILURE_PID; + if (n < 0) { + printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat, + errno); + return parent; } parent = FAILURE_PID; n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); - if(n != 1) - printk("Failed to scan '%s'\n", data); + if (n != 1) + printk(UM_KERN_ERR "Failed to scan '%s'\n", data); return parent; } @@ -99,9 +100,8 @@ void os_stop_process(int pid) void os_kill_process(int pid, int reap_child) { kill(pid, SIGKILL); - if(reap_child) + if (reap_child) CATCH_EINTR(waitpid(pid, NULL, 0)); - } /* This is here uniquely to have access to the userspace errno, i.e. the one @@ -129,17 +129,10 @@ void os_kill_ptraced_process(int pid, int reap_child) kill(pid, SIGKILL); ptrace(PTRACE_KILL, pid); ptrace(PTRACE_CONT, pid); - if(reap_child) + if (reap_child) CATCH_EINTR(waitpid(pid, NULL, 0)); } -#ifdef UML_CONFIG_MODE_TT -void os_usr1_process(int pid) -{ - kill(pid, SIGUSR1); -} -#endif - /* Don't use the glibc version, which caches the result in TLS. It misses some * syscalls, and also breaks with clone(), which does not unshare the TLS. */ @@ -160,34 +153,35 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, void *loc; int prot; - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, fd, off); - if(loc == MAP_FAILED) + if (loc == MAP_FAILED) return -errno; return 0; } int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) { - int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0)); - if(mprotect(addr, len, prot) < 0) + if (mprotect(addr, len, prot) < 0) return -errno; - return 0; + + return 0; } int os_unmap_memory(void *addr, int len) { - int err; + int err; - err = munmap(addr, len); - if(err < 0) + err = munmap(addr, len); + if (err < 0) return -errno; - return 0; + return 0; } #ifndef MADV_REMOVE @@ -199,7 +193,7 @@ int os_drop_memory(void *addr, int length) int err; err = madvise(addr, length, MADV_REMOVE); - if(err < 0) + if (err < 0) err = -errno; return err; } @@ -209,22 +203,24 @@ int __init can_drop_memory(void) void *addr; int fd, ok = 0; - printk("Checking host MADV_REMOVE support..."); + printk(UM_KERN_INFO "Checking host MADV_REMOVE support..."); fd = create_mem_file(UM_KERN_PAGE_SIZE); - if(fd < 0){ - printk("Creating test memory file failed, err = %d\n", -fd); + if (fd < 0) { + printk(UM_KERN_ERR "Creating test memory file failed, " + "err = %d\n", -fd); goto out; } addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if(addr == MAP_FAILED){ - printk("Mapping test memory file failed, err = %d\n", -errno); + if (addr == MAP_FAILED) { + printk(UM_KERN_ERR "Mapping test memory file failed, " + "err = %d\n", -errno); goto out_close; } - if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){ - printk("MADV_REMOVE failed, err = %d\n", -errno); + if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) { + printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno); goto out_unmap; } @@ -239,58 +235,31 @@ out: return ok; } -#ifdef UML_CONFIG_MODE_TT -void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) -{ - int flags = 0, pages; - - if(sig_stack != NULL){ - pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); - set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE); - flags = SA_ONSTACK; - } - if(usr1_handler){ - struct sigaction sa; - - sa.sa_handler = usr1_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = flags; - sa.sa_restorer = NULL; - if(sigaction(SIGUSR1, &sa, NULL) < 0) - panic("init_new_thread_stack - sigaction failed - " - "errno = %d\n", errno); - } -} -#endif - void init_new_thread_signals(void) { set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); - set_handler(SIGUSR2, (__sighandler_t) sig_handler, - SA_ONSTACK, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, - -1); + SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); signal(SIGHUP, SIG_IGN); init_irq_signals(1); } -int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) +int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) { jmp_buf buf; int n; *jmp_ptr = &buf; n = UML_SETJMP(&buf); - if(n != 0) + if (n != 0) return n; (*fn)(arg); return 0; diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c new file mode 100644 index 00000000000..a32ba6ab121 --- /dev/null +++ b/arch/um/os-Linux/registers.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2004 PathScale, Inc + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + +#include <errno.h> +#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 err; + + err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp); + if (err < 0) + panic("save_registers - saving registers failed, errno = %d\n", + errno); +} + +void 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); +} + +void 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); + + arch_init_registers(pid); +} + +void get_safe_registers(unsigned long *regs) +{ + memcpy(regs, exec_regs, sizeof(exec_regs)); +} diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index b98f7ea2d2f..e9800b0b568 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -1,26 +1,21 @@ /* * Copyright (C) 2004 PathScale, Inc + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <signal.h> -#include <stdio.h> -#include <unistd.h> #include <stdlib.h> -#include <errno.h> #include <stdarg.h> -#include <string.h> -#include <sys/mman.h> -#include "user.h" -#include "signal_kern.h" -#include "sysdep/sigcontext.h" -#include "sysdep/barrier.h" -#include "sigcontext.h" -#include "mode.h" +#include <errno.h> +#include <signal.h> +#include <strings.h> #include "os.h" +#include "sysdep/barrier.h" +#include "sysdep/sigcontext.h" +#include "user.h" -/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled - * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to +/* + * 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 * profiling is not thread-safe, then that is not my problem. We can disable * profiling when SMP is enabled in that case. @@ -31,10 +26,8 @@ #define SIGVTALRM_BIT 1 #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) -#define SIGALRM_BIT 2 -#define SIGALRM_MASK (1 << SIGALRM_BIT) - -/* These are used by both the signal handlers and +/* + * 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. */ @@ -46,34 +39,27 @@ void sig_handler(int sig, struct sigcontext *sc) int enabled; enabled = signals_enabled; - if(!enabled && (sig == SIGIO)){ + if (!enabled && (sig == SIGIO)) { pending |= SIGIO_MASK; return; } block_signals(); - CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, - sig, sc); + sig_handler_common_skas(sig, sc); set_signals(enabled); } -static void real_alarm_handler(int sig, struct sigcontext *sc) +static void real_alarm_handler(struct sigcontext *sc) { - union uml_pt_regs regs; + struct uml_pt_regs regs; - if(sig == SIGALRM) - switch_timers(0); - - if(sc != NULL) + if (sc != NULL) copy_sc(®s, sc); - regs.skas.is_user = 0; + regs.is_user = 0; unblock_signals(); - timer_handler(sig, ®s); - - if(sig == SIGALRM) - switch_timers(1); + timer_handler(SIGVTALRM, ®s); } void alarm_handler(int sig, struct sigcontext *sc) @@ -81,27 +67,30 @@ void alarm_handler(int sig, struct sigcontext *sc) int enabled; enabled = signals_enabled; - if(!signals_enabled){ - if(sig == SIGVTALRM) - pending |= SIGVTALRM_MASK; - else pending |= SIGALRM_MASK; - + if (!signals_enabled) { + pending |= SIGVTALRM_MASK; return; } block_signals(); - real_alarm_handler(sig, sc); + real_alarm_handler(sc); set_signals(enabled); } +void timer_init(void) +{ + set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1); +} + void set_sigstack(void *sig_stack, int size) { stack_t stack = ((stack_t) { .ss_flags = 0, .ss_sp = (__ptr_t) sig_stack, .ss_size = size - sizeof(void *) }); - if(sigaltstack(&stack, NULL) != 0) + if (sigaltstack(&stack, NULL) != 0) panic("enabling signal stack failed, errno = %d\n", errno); } @@ -111,7 +100,7 @@ void remove_sigstack(void) .ss_sp = NULL, .ss_size = 0 }); - if(sigaltstack(&stack, NULL) != 0) + if (sigaltstack(&stack, NULL) != 0) panic("disabling signal stack failed, errno = %d\n", errno); } @@ -135,26 +124,27 @@ void handle_signal(int sig, struct sigcontext *sc) * with this interrupt. */ bail = to_irq_stack(&pending); - if(bail) + if (bail) return; nested = pending & 1; pending &= ~1; - while((sig = ffs(pending)) != 0){ + while ((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); (*handlers[sig])(sig, sc); } - /* Again, pending comes back with a mask of signals + /* + * Again, pending comes back with a mask of signals * that arrived while tearing down the stack. If this * is non-zero, we just go back, set up the stack * again, and handle the new interrupts. */ - if(!nested) + if (!nested) pending = from_irq_stack(nested); - } while(pending); + } while (pending); } extern void hard_handler(int sig); @@ -172,18 +162,18 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) sigemptyset(&action.sa_mask); va_start(ap, flags); - while((mask = va_arg(ap, int)) != -1) + while ((mask = va_arg(ap, int)) != -1) sigaddset(&action.sa_mask, mask); va_end(ap); action.sa_flags = flags; action.sa_restorer = NULL; - if(sigaction(sig, &action, NULL) < 0) + if (sigaction(sig, &action, NULL) < 0) panic("sigaction failed - errno = %d\n", errno); sigemptyset(&sig_mask); sigaddset(&sig_mask, sig); - if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) + if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) panic("sigprocmask failed - errno = %d\n", errno); } @@ -194,13 +184,14 @@ int change_sig(int signal, int on) sigemptyset(&sigset); sigaddset(&sigset, signal); sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); - return(!sigismember(&old, signal)); + return !sigismember(&old, signal); } void block_signals(void) { signals_enabled = 0; - /* This must return with signals disabled, so this barrier + /* + * This must return with signals disabled, so this barrier * ensures that writes are flushed out before the return. * This might matter if gcc figures out how to inline this and * decides to shuffle this code into the caller. @@ -212,27 +203,31 @@ void unblock_signals(void) { int save_pending; - if(signals_enabled == 1) + if (signals_enabled == 1) return; - /* We loop because the IRQ handler returns with interrupts off. So, + /* + * 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. */ - while(1){ - /* Save and reset save_pending after enabling signals. This + while(1) { + /* + * Save and reset save_pending after enabling signals. This * way, 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 pending must * happen in this order. */ mb(); save_pending = pending; - if(save_pending == 0){ - /* This must return with signals enabled, so + 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 @@ -245,26 +240,24 @@ void unblock_signals(void) pending = 0; - /* We have pending interrupts, so disable signals, as the + /* + * We have pending interrupts, so disable signals, as the * handlers expect them off when they are called. They will * be enabled again above. */ signals_enabled = 0; - /* Deal with SIGIO first because the alarm handler might + /* + * Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. */ - if(save_pending & SIGIO_MASK) - CHOOSE_MODE_PROC(sig_handler_common_tt, - sig_handler_common_skas, SIGIO, NULL); - - if(save_pending & SIGALRM_MASK) - real_alarm_handler(SIGALRM, NULL); + if (save_pending & SIGIO_MASK) + sig_handler_common_skas(SIGIO, NULL); - if(save_pending & SIGVTALRM_MASK) - real_alarm_handler(SIGVTALRM, NULL); + if (save_pending & SIGVTALRM_MASK) + real_alarm_handler(NULL); } } @@ -276,11 +269,11 @@ int get_signals(void) int set_signals(int enable) { int ret; - if(signals_enabled == enable) + if (signals_enabled == enable) return enable; ret = signals_enabled; - if(enable) + if (enable) unblock_signals(); else block_signals(); diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 0f7df4eb903..484e68f9f7a 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -1,31 +1,26 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <signal.h> +#include <stddef.h> +#include <unistd.h> #include <errno.h> #include <string.h> -#include <unistd.h> #include <sys/mman.h> -#include <sys/wait.h> -#include <asm/page.h> -#include <asm/unistd.h> -#include "mem_user.h" -#include "mem.h" -#include "skas.h" -#include "user.h" +#include "init.h" +#include "kern_constants.h" +#include "as-layout.h" +#include "mm_id.h" #include "os.h" #include "proc_mm.h" #include "ptrace_user.h" -#include "kern_util.h" -#include "task.h" #include "registers.h" -#include "uml-config.h" +#include "skas.h" +#include "user.h" #include "sysdep/ptrace.h" #include "sysdep/stub.h" -#include "init.h" -#include "kern_constants.h" +#include "uml-config.h" extern unsigned long batch_syscall_stub, __syscall_stub_start; @@ -34,7 +29,7 @@ extern void wait_stub_done(int pid); static inline unsigned long *check_init_stack(struct mm_id * mm_idp, unsigned long *stack) { - if(stack == NULL) { + if (stack == NULL) { stack = (unsigned long *) mm_idp->stack + 2; *stack = 0; } @@ -45,8 +40,8 @@ static unsigned long syscall_regs[MAX_REG_NR]; static int __init init_syscall_regs(void) { - get_safe_registers(syscall_regs, NULL); - syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + + get_safe_registers(syscall_regs); + syscall_regs[REGS_IP_INDEX] = STUB_CODE + ((unsigned long) &batch_syscall_stub - (unsigned long) &__syscall_stub_start); return 0; @@ -68,29 +63,30 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) unsigned long * syscall; int err, pid = mm_idp->u.pid; - if(proc_mm) + if (proc_mm) /* FIXME: Need to look up userspace_pid by cpu */ pid = userspace_pid[0]; multi_count++; n = ptrace_setregs(pid, syscall_regs); - if(n < 0){ - printk("Registers - \n"); - for(i = 0; i < MAX_REG_NR; i++) - printk("\t%d\t0x%lx\n", i, syscall_regs[i]); + if (n < 0) { + printk(UM_KERN_ERR "Registers - \n"); + for (i = 0; i < MAX_REG_NR; i++) + printk(UM_KERN_ERR "\t%d\t0x%lx\n", i, syscall_regs[i]); panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", -n); } err = ptrace(PTRACE_CONT, pid, 0, 0); - if(err) + if (err) panic("Failed to continue stub, pid = %d, errno = %d\n", pid, errno); wait_stub_done(pid); - /* When the stub stops, we find the following values on the + /* + * When the stub stops, we find the following values on the * beginning of the stack: * (long )return_value * (long )offset to failed sycall-data (0, if no error) @@ -98,26 +94,26 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) ret = *((unsigned long *) mm_idp->stack); offset = *((unsigned long *) mm_idp->stack + 1); if (offset) { - data = (unsigned long *)(mm_idp->stack + - offset - UML_CONFIG_STUB_DATA); - printk("do_syscall_stub : ret = %ld, offset = %ld, " + data = (unsigned long *)(mm_idp->stack + offset - STUB_DATA); + printk(UM_KERN_ERR "do_syscall_stub : ret = %ld, offset = %ld, " "data = %p\n", ret, offset, data); syscall = (unsigned long *)((unsigned long)data + data[0]); - printk("do_syscall_stub: syscall %ld failed, return value = " - "0x%lx, expected return value = 0x%lx\n", + printk(UM_KERN_ERR "do_syscall_stub: syscall %ld failed, " + "return value = 0x%lx, expected return value = 0x%lx\n", syscall[0], ret, syscall[7]); - printk(" syscall parameters: " + printk(UM_KERN_ERR " syscall parameters: " "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", syscall[1], syscall[2], syscall[3], syscall[4], syscall[5], syscall[6]); - for(n = 1; n < data[0]/sizeof(long); n++) { - if(n == 1) - printk(" additional syscall data:"); - if(n % 4 == 1) - printk("\n "); + for (n = 1; n < data[0]/sizeof(long); n++) { + if (n == 1) + printk(UM_KERN_ERR " additional syscall " + "data:"); + if (n % 4 == 1) + printk("\n" UM_KERN_ERR " "); printk(" 0x%lx", data[n]); } - if(n > 1) + if (n > 1) printk("\n"); } else ret = 0; @@ -133,7 +129,7 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, { unsigned long *stack = check_init_stack(mm_idp, *addr); - if(done && *addr == NULL) + if (done && *addr == NULL) single_count++; *stack += sizeof(long); @@ -150,8 +146,8 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, *stack = 0; multi_op_count++; - if(!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < - UM_KERN_PAGE_SIZE - 10 * sizeof(long))){ + if (!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < + UM_KERN_PAGE_SIZE - 10 * sizeof(long))) { *addr = stack; return 0; } @@ -166,14 +162,15 @@ long syscall_stub_data(struct mm_id * mm_idp, unsigned long *stack; int ret = 0; - /* If *addr still is uninitialized, it *must* contain NULL. + /* + * If *addr still is uninitialized, it *must* contain NULL. * Thus in this case do_syscall_stub correctly won't be called. */ - if((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >= + if ((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >= UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) { ret = do_syscall_stub(mm_idp, addr); /* in case of error, don't overwrite data on stack */ - if(ret) + if (ret) return ret; } @@ -185,7 +182,7 @@ long syscall_stub_data(struct mm_id * mm_idp, memcpy(stack + 1, data, data_count * sizeof(long)); *stub_addr = (void *)(((unsigned long)(stack + 1) & - ~UM_KERN_PAGE_MASK) + UML_CONFIG_STUB_DATA); + ~UM_KERN_PAGE_MASK) + STUB_DATA); return 0; } @@ -195,7 +192,7 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, { int ret; - if(proc_mm){ + if (proc_mm) { struct proc_mm_op map; int fd = mm_idp->u.mm_fd; @@ -211,9 +208,10 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, .offset= offset } } } ); CATCH_EINTR(ret = write(fd, &map, sizeof(map))); - if(ret != sizeof(map)){ + if (ret != sizeof(map)) { ret = -errno; - printk("map : /proc/mm map failed, err = %d\n", -ret); + printk(UM_KERN_ERR "map : /proc/mm map failed, " + "err = %d\n", -ret); } else ret = 0; } @@ -234,7 +232,7 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, { int ret; - if(proc_mm){ + if (proc_mm) { struct proc_mm_op unmap; int fd = mm_idp->u.mm_fd; @@ -245,9 +243,10 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, (unsigned long) addr, .len = len } } } ); CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); - if(ret != sizeof(unmap)){ + if (ret != sizeof(unmap)) { ret = -errno; - printk("unmap - proc_mm write returned %d\n", ret); + printk(UM_KERN_ERR "unmap - proc_mm write returned " + "%d\n", ret); } else ret = 0; } @@ -268,7 +267,7 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, struct proc_mm_op protect; int ret; - if(proc_mm){ + if (proc_mm) { int fd = mm_idp->u.mm_fd; protect = ((struct proc_mm_op) { .op = MM_MPROTECT, @@ -280,9 +279,9 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, .prot = prot } } } ); CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); - if(ret != sizeof(protect)){ + if (ret != sizeof(protect)) { ret = -errno; - printk("protect failed, err = %d", -ret); + printk(UM_KERN_ERR "protect failed, err = %d", -ret); } else ret = 0; } @@ -295,7 +294,3 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, return ret; } - -void before_mem_skas(unsigned long unused) -{ -} diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index ba9af8d6205..d77c81d7068 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -1,48 +1,38 @@ /* - * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <stdlib.h> -#include <string.h> #include <unistd.h> -#include <errno.h> -#include <signal.h> #include <sched.h> -#include "ptrace_user.h" -#include <sys/wait.h> +#include <errno.h> +#include <string.h> #include <sys/mman.h> -#include <sys/user.h> -#include <sys/time.h> -#include <sys/syscall.h> -#include <asm/types.h> -#include "user.h" -#include "sysdep/ptrace.h" -#include "kern_util.h" -#include "skas.h" -#include "stub-data.h" -#include "mm_id.h" -#include "sysdep/sigcontext.h" -#include "sysdep/stub.h" -#include "os.h" -#include "proc_mm.h" -#include "skas_ptrace.h" +#include <sys/ptrace.h> +#include <sys/wait.h> +#include <asm/unistd.h> +#include "as-layout.h" #include "chan_user.h" -#include "registers.h" +#include "kern_constants.h" #include "mem.h" -#include "uml-config.h" +#include "os.h" #include "process.h" -#include "longjmp.h" -#include "kern_constants.h" -#include "as-layout.h" +#include "proc_mm.h" +#include "ptrace_user.h" +#include "registers.h" +#include "skas.h" +#include "skas_ptrace.h" +#include "user.h" +#include "sysdep/stub.h" int is_skas_winch(int pid, int fd, void *data) { - if(pid != os_getpgrp()) - return(0); + if (pid != getpgrp()) + return 0; register_winch_irq(-1, fd, -1, data, 0); - return(1); + return 1; } static int ptrace_dump_regs(int pid) @@ -50,13 +40,12 @@ static int ptrace_dump_regs(int pid) unsigned long regs[MAX_REG_NR]; int i; - if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) return -errno; - else { - printk("Stub registers -\n"); - for(i = 0; i < ARRAY_SIZE(regs); i++) - printk("\t%d - %lx\n", i, regs[i]); - } + + 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; } @@ -74,27 +63,28 @@ void wait_stub_done(int pid) { int n, status, err; - while(1){ + while (1) { CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if((n < 0) || !WIFSTOPPED(status)) + if ((n < 0) || !WIFSTOPPED(status)) goto bad_wait; - if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) + if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) break; err = ptrace(PTRACE_CONT, pid, 0, 0); - if(err) + if (err) panic("wait_stub_done : continue failed, errno = %d\n", errno); } - if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) + if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) return; bad_wait: err = ptrace_dump_regs(pid); - if(err) - printk("Failed to get registers from stub, errno = %d\n", -err); + 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); } @@ -105,9 +95,9 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) { int err; - if(ptrace_faultinfo){ + if (ptrace_faultinfo) { err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); - if(err) + if (err) panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " "errno = %d\n", errno); @@ -119,52 +109,57 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) } else { err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); - if(err) + if (err) panic("Failed to continue stub, pid = %d, errno = %d\n", pid, errno); wait_stub_done(pid); - /* faultinfo is prepared by the stub-segv-handler at start of + /* + * faultinfo is prepared by the stub-segv-handler at start of * the stub stack page. We just have to copy it. */ memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); } } -static void handle_segv(int pid, union uml_pt_regs * regs) +static void handle_segv(int pid, struct uml_pt_regs * regs) { - get_skas_faultinfo(pid, ®s->skas.faultinfo); - segv(regs->skas.faultinfo, 0, 1, NULL); + get_skas_faultinfo(pid, ®s->faultinfo); + segv(regs->faultinfo, 0, 1, NULL); } -/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ -static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) +/* + * To use the same value of using_sysemu as the caller, ask it that value + * (in local_using_sysemu + */ +static void handle_trap(int pid, struct uml_pt_regs *regs, + int local_using_sysemu) { int err, status; /* Mark this as a syscall */ - UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); + UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp); if (!local_using_sysemu) { 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) + panic("handle_trap - nullifying syscall failed, " + "errno = %d\n", errno); 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) + panic("handle_trap - continuing to end of syscall " + "failed, errno = %d\n", errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); - if((err < 0) || !WIFSTOPPED(status) || - (WSTOPSIG(status) != SIGTRAP + 0x80)){ + if ((err < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGTRAP + 0x80)) { err = ptrace_dump_regs(pid); - if(err) - printk("Failed to get registers from process, " - "errno = %d\n", -err); + 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); } @@ -182,63 +177,64 @@ static int userspace_tramp(void *stack) ptrace(PTRACE_TRACEME, 0, 0, 0); - init_new_thread_signals(); - err = set_interval(1); - if(err) + signal(SIGTERM, SIG_DFL); + err = set_interval(); + if (err) panic("userspace_tramp - setting timer failed, errno = %d\n", err); - if(!proc_mm){ - /* This has a pte, but it can't be mapped in with the usual + if (!proc_mm) { + /* + * This has a pte, but it can't be mapped in with the usual * tlb_flush mechanism because this is part of that mechanism */ int fd; - __u64 offset; + unsigned long long offset; fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); - addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE, + addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); - if(addr == MAP_FAILED){ - printk("mapping mmap stub failed, errno = %d\n", - errno); + if (addr == MAP_FAILED) { + printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, " + "errno = %d\n", STUB_CODE, errno); exit(1); } - if(stack != NULL){ + if (stack != NULL) { fd = phys_mapping(to_phys(stack), &offset); - addr = mmap((void *) UML_CONFIG_STUB_DATA, + addr = mmap((void *) STUB_DATA, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, offset); - if(addr == MAP_FAILED){ - printk("mapping segfault stack failed, " - "errno = %d\n", errno); + if (addr == MAP_FAILED) { + printk(UM_KERN_ERR "mapping segfault stack " + "at 0x%lx failed, errno = %d\n", + STUB_DATA, errno); exit(1); } } } - if(!ptrace_faultinfo && (stack != NULL)){ + if (!ptrace_faultinfo && (stack != NULL)) { struct sigaction sa; - unsigned long v = UML_CONFIG_STUB_CODE + + unsigned long v = STUB_CODE + (unsigned long) stub_segv_handler - (unsigned long) &__syscall_stub_start; - set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE); + 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, SIGALRM); sigaddset(&sa.sa_mask, SIGVTALRM); sigaddset(&sa.sa_mask, SIGUSR1); sa.sa_flags = SA_ONSTACK; sa.sa_handler = (void *) v; sa.sa_restorer = NULL; - if(sigaction(SIGSEGV, &sa, NULL) < 0) + if (sigaction(SIGSEGV, &sa, NULL) < 0) panic("userspace_tramp - setting SIGSEGV handler " "failed - errno = %d\n", errno); } - os_stop_process(os_getpid()); - return(0); + kill(os_getpid(), SIGSTOP); + return 0; } /* Each element set once, and only accessed by a single processor anyway */ @@ -255,44 +251,55 @@ int start_userspace(unsigned long stub_stack) stack = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if(stack == MAP_FAILED) + if (stack == MAP_FAILED) panic("start_userspace : mmap failed, errno = %d", errno); sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); flags = CLONE_FILES | SIGCHLD; - if(proc_mm) flags |= CLONE_VM; + if (proc_mm) + flags |= CLONE_VM; + pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); - if(pid < 0) + if (pid < 0) panic("start_userspace : clone failed, errno = %d", errno); do { CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) + if (n < 0) panic("start_userspace : wait failed, errno = %d", errno); - } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); + } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) panic("start_userspace : expected SIGSTOP, got status = %d", status); - if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) - panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n", - errno); + if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, + (void *) PTRACE_O_TRACESYSGOOD) < 0) + panic("start_userspace : PTRACE_OLDSETOPTIONS failed, " + "errno = %d\n", errno); - if(munmap(stack, UM_KERN_PAGE_SIZE) < 0) + if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) panic("start_userspace : munmap failed, errno = %d\n", errno); - return(pid); + return pid; } -void userspace(union uml_pt_regs *regs) +void userspace(struct uml_pt_regs *regs) { + struct itimerval timer; + unsigned long long nsecs, now; int err, status, op, pid = userspace_pid[0]; /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; - while(1){ + if (getitimer(ITIMER_VIRTUAL, &timer)) + printk("Failed to get itimer, errno = %d\n", errno); + nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + + timer.it_value.tv_usec * UM_NSEC_PER_USEC; + nsecs += os_nsecs(); + + while (1) { restore_registers(pid, regs); /* Now we set local_using_sysemu to be used for one loop */ @@ -302,26 +309,28 @@ void userspace(union uml_pt_regs *regs) singlestepping(NULL)); err = ptrace(op, pid, 0, 0); - if(err) + if (err) panic("userspace - could not resume userspace process, " "pid=%d, ptrace operation = %d, errno = %d\n", pid, op, errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); - if(err < 0) + if (err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); - regs->skas.is_user = 1; + regs->is_user = 1; save_registers(pid, regs); UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ - if(WIFSTOPPED(status)){ + if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); - switch(sig){ + switch(sig) { case SIGSEGV: - if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){ - get_skas_faultinfo(pid, ®s->skas.faultinfo); + if (PTRACE_FULL_FAULTINFO || + !ptrace_faultinfo) { + get_skas_faultinfo(pid, + ®s->faultinfo); (*sig_info[SIGSEGV])(SIGSEGV, regs); } else handle_segv(pid, regs); @@ -332,8 +341,20 @@ void userspace(union uml_pt_regs *regs) case SIGTRAP: relay_signal(SIGTRAP, regs); break; - case SIGIO: case SIGVTALRM: + now = os_nsecs(); + if(now < nsecs) + break; + block_signals(); + (*sig_info[sig])(sig, regs); + unblock_signals(); + nsecs = timer.it_value.tv_sec * + UM_NSEC_PER_SEC + + timer.it_value.tv_usec * + UM_NSEC_PER_USEC; + nsecs += os_nsecs(); + break; + case SIGIO: case SIGILL: case SIGBUS: case SIGFPE: @@ -343,30 +364,29 @@ void userspace(union uml_pt_regs *regs) unblock_signals(); break; default: - printk("userspace - child stopped with signal " - "%d\n", sig); + printk(UM_KERN_ERR "userspace - child stopped " + "with signal %d\n", sig); } pid = userspace_pid[0]; interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ - if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) - PT_SYSCALL_NR(regs->skas.regs) = -1; + if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) + PT_SYSCALL_NR(regs->gp) = -1; } } } static unsigned long thread_regs[MAX_REG_NR]; -static unsigned long thread_fp_regs[HOST_FP_SIZE]; static int __init init_thread_regs(void) { - get_safe_registers(thread_regs, thread_fp_regs); + get_safe_registers(thread_regs); /* Set parent's instruction pointer to start of clone-stub */ - thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + + thread_regs[REGS_IP_INDEX] = STUB_CODE + (unsigned long) stub_clone_handler - (unsigned long) &__syscall_stub_start; - thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE - + thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - sizeof(void *); #ifdef __SIGNAL_FRAMESIZE thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; @@ -378,53 +398,53 @@ __initcall(init_thread_regs); int copy_context_skas0(unsigned long new_stack, int pid) { + struct timeval tv = { .tv_sec = 0, .tv_usec = UM_USEC_PER_SEC / UM_HZ }; int err; unsigned long current_stack = current_stub_stack(); struct stub_data *data = (struct stub_data *) current_stack; struct stub_data *child_data = (struct stub_data *) new_stack; - __u64 new_offset; + unsigned long long new_offset; int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); - /* prepare offset and fd of child's stack as argument for parent's + /* + * prepare offset and fd of child's stack as argument for parent's * and child's mmap2 calls */ *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), .fd = new_fd, .timer = ((struct itimerval) - { { 0, 1000000 / hz() }, - { 0, 1000000 / hz() }})}); + { .it_value = tv, + .it_interval = tv }) }); + err = ptrace_setregs(pid, thread_regs); - if(err < 0) + if (err < 0) panic("copy_context_skas0 : PTRACE_SETREGS failed, " "pid = %d, errno = %d\n", pid, -err); - err = ptrace_setfpregs(pid, thread_fp_regs); - if(err < 0) - panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " - "pid = %d, errno = %d\n", pid, -err); - /* set a well known return code for detection of child write failure */ child_data->err = 12345678; - /* Wait, until parent has finished its work: read child's pid from + /* + * Wait, until parent has finished its work: read child's pid from * parent's stack, and check, if bad result. */ err = ptrace(PTRACE_CONT, pid, 0, 0); - if(err) + if (err) panic("Failed to continue new process, pid = %d, " "errno = %d\n", pid, errno); wait_stub_done(pid); pid = data->err; - if(pid < 0) + if (pid < 0) panic("copy_context_skas0 - stub-parent reports error %d\n", -pid); - /* Wait, until child has finished too: read child's result from + /* + * 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 != UML_CONFIG_STUB_DATA) + if (child_data->err != STUB_DATA) panic("copy_context_skas0 - stub-child reports error %ld\n", child_data->err); @@ -446,7 +466,7 @@ void map_stub_pages(int fd, unsigned long code, { struct proc_mm_op mmop; int n; - __u64 code_offset; + unsigned long long code_offset; int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), &code_offset); @@ -461,16 +481,17 @@ void map_stub_pages(int fd, unsigned long code, .offset = code_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); - if(n != sizeof(mmop)){ + if (n != sizeof(mmop)) { n = errno; - printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", - code, code_fd, (unsigned long long) code_offset); + 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); } - if ( stack ) { - __u64 map_offset; + if (stack) { + unsigned long long map_offset; int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); mmop = ((struct proc_mm_op) { .op = MM_MMAP, @@ -484,7 +505,7 @@ void map_stub_pages(int fd, unsigned long code, .offset = map_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); - if(n != sizeof(mmop)) + if (n != sizeof(mmop)) panic("map_stub_pages : /proc/mm map for data failed, " "err = %d\n", errno); } @@ -504,7 +525,7 @@ void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) void switch_threads(jmp_buf *me, jmp_buf *you) { - if(UML_SETJMP(me) == 0) + if (UML_SETJMP(me) == 0) UML_LONGJMP(you, 1); } @@ -520,8 +541,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) int n; set_handler(SIGWINCH, (__sighandler_t) sig_handler, - SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, - SIGVTALRM, -1); + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1); /* * Can't use UML_SETJMP or UML_LONGJMP here because they save @@ -532,7 +552,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) * after returning to the jumper. */ n = setjmp(initial_jmpbuf); - switch(n){ + switch(n) { case INIT_JMP_NEW_THREAD: (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; (*switch_buf)[0].JB_SP = (unsigned long) stack + @@ -544,10 +564,10 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) break; case INIT_JMP_HALT: kmalloc_ok = 0; - return(0); + return 0; case INIT_JMP_REBOOT: kmalloc_ok = 0; - return(1); + return 1; default: panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); } @@ -563,7 +583,7 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg) cb_back = &here; block_signals(); - if(UML_SETJMP(&here) == 0) + if (UML_SETJMP(&here) == 0) UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); unblock_signals(); @@ -584,16 +604,16 @@ void reboot_skas(void) UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); } -void switch_mm_skas(struct mm_id *mm_idp) +void __switch_mm(struct mm_id *mm_idp) { int err; - /* FIXME: need cpu pid in switch_mm_skas */ - if(proc_mm){ + /* FIXME: need cpu pid in __switch_mm */ + if (proc_mm) { err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); - if(err) - panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " + if (err) + panic("__switch_mm - PTRACE_SWITCH_MM failed, " "errno = %d\n", errno); } 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 index 3b600c2e63b..3b1b9244f46 100644 --- a/arch/um/os-Linux/skas/trap.c +++ b/arch/um/os-Linux/skas/trap.c @@ -1,37 +1,43 @@ /* - * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#include <signal.h> -#include <errno.h> +#if 0 #include "kern_util.h" -#include "as-layout.h" -#include "task.h" -#include "sigcontext.h" #include "skas.h" #include "ptrace_user.h" -#include "sysdep/ptrace.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 union uml_pt_regs ksig_regs[UM_NR_CPUS]; +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; - union uml_pt_regs *r; - void (*handler)(int, union uml_pt_regs *); + 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 + /* + * 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) { + if (sig == SIGSEGV) { change_sig(SIGSEGV, 1); - /* For segfaults, we want the data from the + /* + * 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 @@ -42,25 +48,22 @@ void sig_handler_common_skas(int sig, void *sc_ptr) } else r = TASK_REGS(get_current()); - save_user = r->skas.is_user; - r->skas.is_user = 0; - if ( sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGILL || - sig == SIGTRAP ) { - GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc); - } + 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 SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ - if (sig != SIGIO && sig != SIGWINCH && - sig != SIGVTALRM && sig != SIGALRM) + /* 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->skas.is_user = save_user; + r->is_user = save_user; } diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 46f613975c1..7b81f6c08a5 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -1,75 +1,65 @@ /* - * 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 <pty.h> #include <stdio.h> -#include <stddef.h> -#include <stdarg.h> #include <stdlib.h> -#include <string.h> +#include <stdarg.h> #include <unistd.h> -#include <signal.h> -#include <sched.h> -#include <fcntl.h> #include <errno.h> -#include <sys/time.h> -#include <sys/wait.h> +#include <fcntl.h> +#include <sched.h> +#include <signal.h> +#include <string.h> #include <sys/mman.h> -#include <sys/resource.h> +#include <sys/ptrace.h> +#include <sys/stat.h> +#include <sys/wait.h> #include <asm/unistd.h> -#include <asm/page.h> -#include <sys/types.h> -#include "kern_util.h" -#include "user.h" -#include "signal_kern.h" -#include "sysdep/ptrace.h" -#include "sysdep/sigcontext.h" -#include "irq_user.h" -#include "ptrace_user.h" -#include "mem_user.h" #include "init.h" -#include "os.h" -#include "uml-config.h" -#include "choose-mode.h" -#include "mode.h" -#include "tempfile.h" #include "kern_constants.h" - -#ifdef UML_CONFIG_MODE_SKAS -#include "skas.h" -#include "skas_ptrace.h" +#include "os.h" +#include "mem_user.h" +#include "ptrace_user.h" #include "registers.h" -#endif +#include "skas_ptrace.h" -static int ptrace_child(void *arg) +static int ptrace_child(void) { int ret; + /* Calling os_getpid because some libcs cached getpid incorrectly */ int pid = os_getpid(), ppid = getppid(); int sc_result; change_sig(SIGWINCH, 0); - if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ + if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { perror("ptrace"); - os_kill_process(pid, 0); + kill(pid, SIGKILL); } kill(pid, SIGSTOP); - /*This syscall will be intercepted by the parent. Don't call more than - * once, please.*/ + /* + * This syscall will be intercepted by the parent. Don't call more than + * once, please. + */ sc_result = os_getpid(); if (sc_result == pid) - ret = 1; /*Nothing modified by the parent, we are running - normally.*/ + /* Nothing modified by the parent, we are running normally. */ + ret = 1; else if (sc_result == ppid) - ret = 0; /*Expected in check_ptrace and check_sysemu when they - succeed in modifying the stack frame*/ + /* + * Expected in check_ptrace and check_sysemu when they succeed + * in modifying the stack frame + */ + ret = 0; else - ret = 2; /*Serious trouble! This could be caused by a bug in - host 2.6 SKAS3/2.6 patch before release -V6, together - with a bug in the UML code itself.*/ + /* Serious trouble! This could be caused by a bug in host 2.6 + * SKAS3/2.6 patch before release -V6, together with a bug in + * the UML code itself. + */ + ret = 2; _exit(ret); } @@ -101,29 +91,23 @@ static void non_fatal(char *fmt, ...) fflush(stdout); } -static int start_ptraced_child(void **stack_out) +static int start_ptraced_child(void) { - void *stack; - unsigned long sp; int pid, n, status; - stack = mmap(NULL, UM_KERN_PAGE_SIZE, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if(stack == MAP_FAILED) - fatal_perror("check_ptrace : mmap failed"); - sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); - pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); - if(pid < 0) - fatal_perror("start_ptraced_child : clone failed"); + pid = fork(); + if (pid == 0) + ptrace_child(); + else if (pid < 0) + fatal_perror("start_ptraced_child : fork failed"); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) - fatal_perror("check_ptrace : clone failed"); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) + if (n < 0) + fatal_perror("check_ptrace : waitpid failed"); + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) fatal("check_ptrace : expected SIGSTOP, got status = %d", status); - *stack_out = stack; return pid; } @@ -133,15 +117,14 @@ static int start_ptraced_child(void **stack_out) * So only for SYSEMU features we test mustpanic, while normal host features * must work anyway! */ -static int stop_ptraced_child(int pid, void *stack, int exitcode, - int mustexit) +static int stop_ptraced_child(int pid, int exitcode, int mustexit) { int status, n, ret = 0; - if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) + if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) fatal_perror("stop_ptraced_child : ptrace failed"); CATCH_EINTR(n = waitpid(pid, &status, 0)); - if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { + if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); if (exit_with == 2) non_fatal("check_ptrace : child exited with status 2. " @@ -154,8 +137,6 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, ret = -1; } - if(munmap(stack, UM_KERN_PAGE_SIZE) < 0) - fatal_perror("check_ptrace : munmap failed"); return ret; } @@ -207,40 +188,39 @@ __uml_setup("nosysemu", nosysemu_cmd_param, static void __init check_sysemu(void) { - void *stack; unsigned long regs[MAX_REG_NR]; int pid, n, status, count=0; non_fatal("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); - if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) + if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) goto fail; CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if (n < 0) fatal_perror("check_sysemu : wait failed"); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) fatal("check_sysemu : expected SIGTRAP, got status = %d", status); - if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) fatal_perror("check_sysemu : PTRACE_GETREGS failed"); - if(PT_SYSCALL_NR(regs) != __NR_getpid){ + if (PT_SYSCALL_NR(regs) != __NR_getpid) { non_fatal("check_sysemu got system call number %d, " "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid); goto fail; } n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); - if(n < 0){ + if (n < 0) { non_fatal("check_sysemu : failed to modify system call " "return"); goto fail; } - if (stop_ptraced_child(pid, stack, 0, 0) < 0) + if (stop_ptraced_child(pid, 0, 0) < 0) goto fail_stopped; sysemu_supported = 1; @@ -248,90 +228,90 @@ static void __init check_sysemu(void) set_using_sysemu(!force_sysemu_disabled); non_fatal("Checking advanced syscall emulation patch for ptrace..."); - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); - if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, + if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *) PTRACE_O_TRACESYSGOOD) < 0)) fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); - while(1){ + while (1) { count++; - if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) + if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) goto fail; CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) + if (n < 0) fatal_perror("check_ptrace : wait failed"); - if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){ + if (WIFSTOPPED(status) && + (WSTOPSIG(status) == (SIGTRAP|0x80))) { if (!count) fatal("check_ptrace : SYSEMU_SINGLESTEP " "doesn't singlestep"); n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); - if(n < 0) + if (n < 0) fatal_perror("check_sysemu : failed to modify " "system call return"); break; } - else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) + else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) count++; else fatal("check_ptrace : expected SIGTRAP or " "(SIGTRAP | 0x80), got status = %d", status); } - if (stop_ptraced_child(pid, stack, 0, 0) < 0) + if (stop_ptraced_child(pid, 0, 0) < 0) goto fail_stopped; sysemu_supported = 2; non_fatal("OK\n"); - if ( !force_sysemu_disabled ) + if (!force_sysemu_disabled) set_using_sysemu(sysemu_supported); return; fail: - stop_ptraced_child(pid, stack, 1, 0); + stop_ptraced_child(pid, 1, 0); fail_stopped: non_fatal("missing\n"); } static void __init check_ptrace(void) { - void *stack; int pid, syscall, n, status; non_fatal("Checking that ptrace can change system call numbers..."); - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); - if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, + if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *) PTRACE_O_TRACESYSGOOD) < 0)) fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); - while(1){ - if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) + while (1) { + if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) fatal_perror("check_ptrace : ptrace failed"); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) + if (n < 0) fatal_perror("check_ptrace : wait failed"); - if(!WIFSTOPPED(status) || + if (!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP | 0x80))) fatal("check_ptrace : expected (SIGTRAP|0x80), " "got status = %d", status); syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0); - if(syscall == __NR_getpid){ + if (syscall == __NR_getpid) { n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getppid); - if(n < 0) + if (n < 0) fatal_perror("check_ptrace : failed to modify " "system call"); break; } } - stop_ptraced_child(pid, stack, 0, 1); + stop_ptraced_child(pid, 0, 1); non_fatal("OK\n"); check_sysemu(); } @@ -343,18 +323,18 @@ static void __init check_coredump_limit(void) struct rlimit lim; int err = getrlimit(RLIMIT_CORE, &lim); - if(err){ + if (err) { perror("Getting core dump limit"); return; } printf("Core dump limits :\n\tsoft - "); - if(lim.rlim_cur == RLIM_INFINITY) + if (lim.rlim_cur == RLIM_INFINITY) printf("NONE\n"); else printf("%lu\n", lim.rlim_cur); printf("\thard - "); - if(lim.rlim_max == RLIM_INFINITY) + if (lim.rlim_max == RLIM_INFINITY) printf("NONE\n"); else printf("%lu\n", lim.rlim_max); } @@ -408,20 +388,18 @@ __uml_setup("noptraceldt", noptraceldt_cmd_param, " To support PTRACE_LDT, the host needs to be patched using\n" " the current skas3 patch.\n\n"); -#ifdef UML_CONFIG_MODE_SKAS static inline void check_skas3_ptrace_faultinfo(void) { struct ptrace_faultinfo fi; - void *stack; int pid, n; non_fatal(" - PTRACE_FAULTINFO..."); - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); if (n < 0) { ptrace_faultinfo = 0; - if(errno == EIO) + if (errno == EIO) non_fatal("not found\n"); else perror("not found"); @@ -434,13 +412,12 @@ static inline void check_skas3_ptrace_faultinfo(void) } init_registers(pid); - stop_ptraced_child(pid, stack, 1, 1); + stop_ptraced_child(pid, 1, 1); } static inline void check_skas3_ptrace_ldt(void) { #ifdef PTRACE_LDT - void *stack; int pid, n; unsigned char ldtbuf[40]; struct ptrace_ldt ldt_op = (struct ptrace_ldt) { @@ -449,11 +426,11 @@ static inline void check_skas3_ptrace_ldt(void) .bytecount = sizeof(ldtbuf)}; non_fatal(" - PTRACE_LDT..."); - pid = start_ptraced_child(&stack); + pid = start_ptraced_child(); n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); if (n < 0) { - if(errno == EIO) + if (errno == EIO) non_fatal("not found\n"); else { perror("not found"); @@ -461,13 +438,13 @@ static inline void check_skas3_ptrace_ldt(void) ptrace_ldt = 0; } else { - if(ptrace_ldt) + if (ptrace_ldt) non_fatal("found\n"); else non_fatal("found, but use is disabled\n"); } - stop_ptraced_child(pid, stack, 1, 1); + stop_ptraced_child(pid, 1, 1); #else /* PTRACE_LDT might be disabled via cmdline option. * We want to override this, else we might use the stub @@ -484,12 +461,9 @@ static inline void check_skas3_proc_mm(void) proc_mm = 0; perror("not found"); } - else { - if (!proc_mm) - non_fatal("found but disabled on command line\n"); - else - non_fatal("found\n"); - } + else if (!proc_mm) + non_fatal("found but disabled on command line\n"); + else non_fatal("found\n"); } int can_do_skas(void) @@ -500,17 +474,11 @@ int can_do_skas(void) check_skas3_ptrace_faultinfo(); check_skas3_ptrace_ldt(); - if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt) + if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) skas_needs_stub = 1; return 1; } -#else -int can_do_skas(void) -{ - return 0; -} -#endif int __init parse_iomem(char *str, int *add) { @@ -521,25 +489,25 @@ int __init parse_iomem(char *str, int *add) driver = str; file = strchr(str,','); - if(file == NULL){ + if (file == NULL) { printf("parse_iomem : failed to parse iomem\n"); goto out; } *file = '\0'; file++; fd = open(file, O_RDWR, 0); - if(fd < 0){ - os_print_error(fd, "parse_iomem - Couldn't open io file"); + if (fd < 0) { + perror("parse_iomem - Couldn't open io file"); goto out; } - if(fstat64(fd, &buf) < 0){ + if (fstat64(fd, &buf) < 0) { perror("parse_iomem - cannot stat_fd file"); goto out_close; } new = malloc(sizeof(*new)); - if(new == NULL){ + if (new == NULL) { perror("Couldn't allocate iomem_region struct"); goto out_close; } diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile index 37806621b25..a841262c594 100644 --- a/arch/um/os-Linux/sys-i386/Makefile +++ b/arch/um/os-Linux/sys-i386/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # -obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o +obj-y = registers.o signal.o tls.o USER_OBJS := $(obj-y) diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 84b44f9cd42..d1997ca76e5 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -1,144 +1,73 @@ /* * Copyright (C) 2004 PathScale, Inc + * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <errno.h> -#include <string.h> -#include "sysdep/ptrace_user.h" -#include "sysdep/ptrace.h" -#include "uml-config.h" -#include "skas_ptregs.h" -#include "registers.h" +#include "kern_constants.h" #include "longjmp.h" #include "user.h" +#include "sysdep/ptrace_user.h" -/* These are set once at boot time and not changed thereafter */ - -static unsigned long exec_regs[MAX_REG_NR]; -static unsigned long exec_fp_regs[HOST_FP_SIZE]; -static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; -static int have_fpx_regs = 1; - -void init_thread_registers(union uml_pt_regs *to) -{ - memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); - memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); - if(have_fpx_regs) - memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp)); -} - -/* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs - * to pass in a sufficiently large buffer - */ int save_fp_registers(int pid, unsigned long *fp_regs) { - if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) + if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) return -errno; return 0; } int restore_fp_registers(int pid, unsigned long *fp_regs) { - if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) + if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) return -errno; return 0; } -static int move_registers(int pid, int int_op, union uml_pt_regs *regs, - int fp_op, unsigned long *fp_regs) +int save_fpx_registers(int pid, unsigned long *fp_regs) { - if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) - return -errno; - - if(ptrace(fp_op, pid, 0, fp_regs) < 0) + if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) return -errno; - return 0; } -void save_registers(int pid, union uml_pt_regs *regs) +int restore_fpx_registers(int pid, unsigned long *fp_regs) { - unsigned long *fp_regs; - int err, fp_op; - - if(have_fpx_regs){ - fp_op = PTRACE_GETFPXREGS; - fp_regs = regs->skas.xfp; - } - else { - fp_op = PTRACE_GETFPREGS; - fp_regs = regs->skas.fp; - } - - err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs); - if(err) - panic("save_registers - saving registers failed, errno = %d\n", - -err); + if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) + return -errno; + return 0; } -void restore_registers(int pid, union uml_pt_regs *regs) +unsigned long get_thread_reg(int reg, jmp_buf *buf) { - unsigned long *fp_regs; - int err, fp_op; - - if(have_fpx_regs){ - fp_op = PTRACE_SETFPXREGS; - fp_regs = regs->skas.xfp; - } - else { - fp_op = PTRACE_SETFPREGS; - fp_regs = regs->skas.fp; + switch (reg) { + case EIP: + return buf[0]->__eip; + case UESP: + return buf[0]->__esp; + case EBP: + return buf[0]->__ebp; + default: + printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", + reg); + return 0; } - - err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs); - if(err) - panic("restore_registers - saving registers failed, " - "errno = %d\n", -err); } -void init_registers(int pid) +int have_fpx_regs = 1; + +void arch_init_registers(int pid) { + unsigned long fpx_regs[HOST_XFP_SIZE]; int err; - memset(exec_regs, 0, sizeof(exec_regs)); - err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); - if(err) - panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", - errno); - - errno = 0; - err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); + err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs); if(!err) return; + if(errno != EIO) panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", errno); have_fpx_regs = 0; - - err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); - if(err) - panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", - errno); -} - -void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) -{ - memcpy(regs, exec_regs, sizeof(exec_regs)); - if(fp_regs != NULL) - memcpy(fp_regs, exec_fp_regs, - HOST_FP_SIZE * sizeof(unsigned long)); -} - -unsigned long get_thread_reg(int reg, jmp_buf *buf) -{ - switch(reg){ - case EIP: return buf[0]->__eip; - case UESP: return buf[0]->__esp; - case EBP: return buf[0]->__ebp; - default: - printk("get_thread_regs - unknown register %d\n", reg); - return 0; - } } diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile index 7955e061a67..a42a4ef02e1 100644 --- a/arch/um/os-Linux/sys-x86_64/Makefile +++ b/arch/um/os-Linux/sys-x86_64/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # -obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o +obj-y = registers.o prctl.o signal.o USER_OBJS := $(obj-y) diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index 9467315b805..9bfa789992d 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -1,23 +1,15 @@ /* - * Copyright (C) 2004 PathScale, Inc + * Copyright (C) 2006-2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <errno.h> #include <sys/ptrace.h> -#include <string.h> -#include "ptrace_user.h" -#include "uml-config.h" -#include "skas_ptregs.h" -#include "registers.h" +#define __FRAME_OFFSETS +#include <asm/ptrace.h> #include "longjmp.h" #include "user.h" -/* These are set once at boot time and not changed thereafter */ - -static unsigned long exec_regs[MAX_REG_NR]; -static unsigned long exec_fp_regs[HOST_FP_SIZE]; - int save_fp_registers(int pid, unsigned long *fp_regs) { if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) @@ -32,67 +24,6 @@ int restore_fp_registers(int pid, unsigned long *fp_regs) return 0; } -void init_thread_registers(union uml_pt_regs *to) -{ - memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); - memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); -} - -static int move_registers(int pid, int int_op, int fp_op, - union uml_pt_regs *regs) -{ - if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) - return -errno; - - if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) - return -errno; - - return 0; -} - -void save_registers(int pid, union uml_pt_regs *regs) -{ - int err; - - err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs); - if(err) - panic("save_registers - saving registers failed, errno = %d\n", - -err); -} - -void restore_registers(int pid, union uml_pt_regs *regs) -{ - int err; - - err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs); - if(err) - panic("restore_registers - saving registers failed, " - "errno = %d\n", -err); -} - -void 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); - - err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); - if(err) - panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", - errno); -} - -void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) -{ - memcpy(regs, exec_regs, sizeof(exec_regs)); - if(fp_regs != NULL) - memcpy(fp_regs, exec_fp_regs, - HOST_FP_SIZE * sizeof(unsigned long)); -} - unsigned long get_thread_reg(int reg, jmp_buf *buf) { switch(reg){ diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 5de169b168f..e34e1effe0f 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -1,101 +1,86 @@ /* - * 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 <stdio.h> -#include <stdlib.h> -#include <unistd.h> +#include <stddef.h> +#include <errno.h> +#include <signal.h> #include <time.h> #include <sys/time.h> -#include <signal.h> -#include <errno.h> -#include "kern_util.h" -#include "user.h" -#include "process.h" #include "kern_constants.h" #include "os.h" -#include "uml-config.h" +#include "user.h" -int set_interval(int is_virtual) +int set_interval(void) { - int usec = 1000000/hz(); - int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL; + int usec = UM_USEC_PER_SEC / UM_HZ; struct itimerval interval = ((struct itimerval) { { 0, usec }, { 0, usec } }); - if(setitimer(timer_type, &interval, NULL) == -1) + if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) return -errno; return 0; } -#ifdef UML_CONFIG_MODE_TT -void enable_timer(void) +int timer_one_shot(int ticks) { - set_interval(1); -} -#endif + unsigned long usec = ticks * UM_USEC_PER_SEC / UM_HZ; + unsigned long sec = usec / UM_USEC_PER_SEC; + struct itimerval interval; -void disable_timer(void) -{ - struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); - if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || - (setitimer(ITIMER_REAL, &disable, NULL) < 0)) - printk("disnable_timer - setitimer failed, errno = %d\n", - errno); - /* If there are signals already queued, after unblocking ignore them */ - signal(SIGALRM, SIG_IGN); - signal(SIGVTALRM, SIG_IGN); + usec %= UM_USEC_PER_SEC; + interval = ((struct itimerval) { { 0, 0 }, { sec, usec } }); + + if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) + return -errno; + + return 0; } -void switch_timers(int to_real) +/** + * timeval_to_ns - Convert timeval to nanoseconds + * @ts: pointer to the timeval variable to be converted + * + * Returns the scalar nanosecond representation of the timeval + * parameter. + * + * Ripped from linux/time.h because it's a kernel header, and thus + * unusable from here. + */ +static inline long long timeval_to_ns(const struct timeval *tv) { - struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); - struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, - { 0, 1000000/hz() }}); - int old, new; - - if(to_real){ - old = ITIMER_VIRTUAL; - new = ITIMER_REAL; - } - else { - old = ITIMER_REAL; - new = ITIMER_VIRTUAL; - } - - if((setitimer(old, &disable, NULL) < 0) || - (setitimer(new, &enable, NULL))) - printk("switch_timers - setitimer failed, errno = %d\n", - errno); + return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) + + tv->tv_usec * UM_NSEC_PER_USEC; } -#ifdef UML_CONFIG_MODE_TT -void uml_idle_timer(void) +long long disable_timer(void) { - if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) - panic("Couldn't unset SIGVTALRM handler"); + struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); + + if(setitimer(ITIMER_VIRTUAL, &time, &time) < 0) + printk(UM_KERN_ERR "disable_timer - setitimer failed, " + "errno = %d\n", errno); - set_handler(SIGALRM, (__sighandler_t) alarm_handler, - SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); - set_interval(0); + return timeval_to_ns(&time.it_value); } -#endif -unsigned long long os_nsecs(void) +long long os_nsecs(void) { struct timeval tv; gettimeofday(&tv, NULL); - return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000); + return timeval_to_ns(&tv); } -void idle_sleep(int secs) +extern void alarm_handler(int sig, struct sigcontext *sc); + +void idle_sleep(unsigned long long nsecs) { - struct timespec ts; + struct timespec ts = { .tv_sec = nsecs / UM_NSEC_PER_SEC, + .tv_nsec = nsecs % UM_NSEC_PER_SEC }; - ts.tv_sec = secs; - ts.tv_nsec = 0; - nanosleep(&ts, NULL); + if (nanosleep(&ts, &ts) == 0) + alarm_handler(SIGVTALRM, NULL); } diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c index 16215b99080..73277801ef1 100644 --- a/arch/um/os-Linux/tls.c +++ b/arch/um/os-Linux/tls.c @@ -1,18 +1,9 @@ #include <errno.h> -#include <unistd.h> #include <sys/ptrace.h> -#include <sys/syscall.h> -#include <asm/ldt.h> #include "sysdep/tls.h" -#include "uml-config.h" /* TLS support - we basically rely on the host's one.*/ -/* In TT mode, this should be called only by the tracing thread, and makes sense - * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally. - * - */ - #ifndef PTRACE_GET_THREAD_AREA #define PTRACE_GET_THREAD_AREA 25 #endif @@ -32,8 +23,6 @@ int os_set_thread_area(user_desc_t *info, int pid) return ret; } -#ifdef UML_CONFIG_MODE_SKAS - int os_get_thread_area(user_desc_t *info, int pid) { int ret; @@ -44,32 +33,3 @@ int os_get_thread_area(user_desc_t *info, int pid) ret = -errno; return ret; } - -#endif - -#ifdef UML_CONFIG_MODE_TT -#include "linux/unistd.h" - -int do_set_thread_area_tt(user_desc_t *info) -{ - int ret; - - ret = syscall(__NR_set_thread_area,info); - if (ret < 0) { - ret = -errno; - } - return ret; -} - -int do_get_thread_area_tt(user_desc_t *info) -{ - int ret; - - ret = syscall(__NR_get_thread_area,info); - if (ret < 0) { - ret = -errno; - } - return ret; -} - -#endif /* UML_CONFIG_MODE_TT */ diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index 295da657931..2a1c9843e32 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c @@ -1,22 +1,14 @@ /* - * 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 <signal.h> -#include "kern_util.h" #include "os.h" -#include "mode.h" -#include "longjmp.h" - -void usr2_handler(int sig, union uml_pt_regs *regs) -{ - CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); -} +#include "sysdep/ptrace.h" /* Initialized from linux_main() */ -void (*sig_info[NSIG])(int, union uml_pt_regs *); +void (*sig_info[NSIG])(int, struct uml_pt_regs *); void os_fill_handlinfo(struct kern_handlers h) { @@ -28,13 +20,4 @@ void os_fill_handlinfo(struct kern_handlers h) sig_info[SIGSEGV] = h.page_fault; sig_info[SIGIO] = h.sigio_handler; sig_info[SIGVTALRM] = h.timer_handler; - sig_info[SIGALRM] = h.timer_handler; - sig_info[SIGUSR2] = usr2_handler; -} - -void do_longjmp(void *b, int val) -{ - jmp_buf *buf = b; - - UML_LONGJMP(buf, val); } diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c deleted file mode 100644 index bcf9359c4e9..00000000000 --- a/arch/um/os-Linux/tt.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <unistd.h> -#include <signal.h> -#include <sched.h> -#include <errno.h> -#include <stdarg.h> -#include <stdlib.h> -#include <sys/time.h> -#include <sys/ptrace.h> -#include <linux/ptrace.h> -#include <sys/wait.h> -#include <sys/mman.h> -#include <asm/ptrace.h> -#include <asm/unistd.h> -#include <asm/page.h> -#include "kern_util.h" -#include "user.h" -#include "signal_kern.h" -#include "sysdep/ptrace.h" -#include "sysdep/sigcontext.h" -#include "irq_user.h" -#include "ptrace_user.h" -#include "init.h" -#include "os.h" -#include "uml-config.h" -#include "choose-mode.h" -#include "mode.h" -#include "tempfile.h" -#include "kern_constants.h" - -int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, - int must_succeed) -{ - int err; - - err = os_protect_memory((void *) addr, len, r, w, x); - if(err < 0){ - if(must_succeed) - panic("protect failed, err = %d", -err); - else return(err); - } - return(0); -} - -void kill_child_dead(int pid) -{ - kill(pid, SIGKILL); - kill(pid, SIGCONT); - do { - int n; - CATCH_EINTR(n = waitpid(pid, NULL, 0)); - if (n > 0) - kill(pid, SIGCONT); - else - break; - } while(1); -} - -void stop(void) -{ - while(1) sleep(1000000); -} - -int wait_for_stop(int pid, int sig, int cont_type, void *relay) -{ - sigset_t *relay_signals = relay; - int status, ret; - - while(1){ - CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); - if((ret < 0) || - !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ - if(ret < 0){ - printk("wait failed, errno = %d\n", - errno); - } - else if(WIFEXITED(status)) - printk("process %d exited with status %d\n", - pid, WEXITSTATUS(status)); - else if(WIFSIGNALED(status)) - printk("process %d exited with signal %d\n", - pid, WTERMSIG(status)); - else if((WSTOPSIG(status) == SIGVTALRM) || - (WSTOPSIG(status) == SIGALRM) || - (WSTOPSIG(status) == SIGIO) || - (WSTOPSIG(status) == SIGPROF) || - (WSTOPSIG(status) == SIGCHLD) || - (WSTOPSIG(status) == SIGWINCH) || - (WSTOPSIG(status) == SIGINT)){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else if((relay_signals != NULL) && - sigismember(relay_signals, WSTOPSIG(status))){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else printk("process %d stopped with signal %d\n", - pid, WSTOPSIG(status)); - panic("wait_for_stop failed to wait for %d to stop " - "with %d\n", pid, sig); - } - return(status); - } -} - -void forward_ipi(int fd, int pid) -{ - int err; - - err = os_set_owner(fd, pid); - if(err < 0) - printk("forward_ipi: set_owner failed, fd = %d, me = %d, " - "target = %d, err = %d\n", fd, os_getpid(), pid, -err); -} - -/* - *------------------------- - * only for tt mode (will be deleted in future...) - *------------------------- - */ - -struct tramp { - int (*tramp)(void *); - void *tramp_data; - unsigned long temp_stack; - int flags; - int pid; -}; - -/* See above for why sigkill is here */ - -int sigkill = SIGKILL; - -int outer_tramp(void *arg) -{ - struct tramp *t; - int sig = sigkill; - - t = arg; - t->pid = clone(t->tramp, (void *) t->temp_stack + UM_KERN_PAGE_SIZE/2, - t->flags, t->tramp_data); - if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); - kill(os_getpid(), sig); - _exit(0); -} - -int start_fork_tramp(void *thread_arg, unsigned long temp_stack, - int clone_flags, int (*tramp)(void *)) -{ - struct tramp arg; - unsigned long sp; - int new_pid, status, err; - - /* The trampoline will run on the temporary stack */ - sp = stack_sp(temp_stack); - - clone_flags |= CLONE_FILES | SIGCHLD; - - arg.tramp = tramp; - arg.tramp_data = thread_arg; - arg.temp_stack = temp_stack; - arg.flags = clone_flags; - - /* Start the process and wait for it to kill itself */ - new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); - if(new_pid < 0) - return(new_pid); - - CATCH_EINTR(err = waitpid(new_pid, &status, 0)); - if(err < 0) - panic("Waiting for outer trampoline failed - errno = %d", - errno); - - if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) - panic("outer trampoline didn't exit with SIGKILL, " - "status = %d", status); - - return(arg.pid); -} - -void forward_pending_sigio(int target) -{ - sigset_t sigs; - - if(sigpending(&sigs)) - panic("forward_pending_sigio : sigpending failed"); - if(sigismember(&sigs, SIGIO)) - kill(target, SIGIO); -} - diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index bbb73a65037..8d27b6d1df9 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c @@ -8,7 +8,7 @@ #include "longjmp.h" unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher, + void **fault_addr, jmp_buf **fault_catcher, void (*op)(void *to, const void *from, int n), int *faulted_out) { diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index b462863f717..106fa864155 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c @@ -1,17 +1,21 @@ +/* + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + #include <stdio.h> -#include <unistd.h> #include <stdlib.h> -#include <string.h> +#include <dirent.h> #include <errno.h> +#include <fcntl.h> #include <signal.h> -#include <dirent.h> -#include <sys/fcntl.h> +#include <string.h> +#include <unistd.h> #include <sys/stat.h> -#include <sys/param.h> #include "init.h" +#include "kern_constants.h" #include "os.h" #include "user.h" -#include "mode.h" #define UML_DIR "~/.uml/" @@ -28,13 +32,13 @@ static int __init make_uml_dir(void) char dir[512] = { '\0' }; int len, err; - if(*uml_dir == '~'){ + if (*uml_dir == '~') { char *home = getenv("HOME"); err = -ENOENT; - if(home == NULL){ - printk("make_uml_dir : no value in environment for " - "$HOME\n"); + if (home == NULL) { + printk(UM_KERN_ERR "make_uml_dir : no value in " + "environment for $HOME\n"); goto err; } strlcpy(dir, home, sizeof(dir)); @@ -53,7 +57,7 @@ static int __init make_uml_dir(void) } strcpy(uml_dir, dir); - if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ + if ((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)) { printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); err = -errno; goto err_free; @@ -70,8 +74,8 @@ err: /* * Unlinks the files contained in @dir and then removes @dir. * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We - * ignore ENOENT errors for anything (they happen, strangely enough - possibly due - * to races between multiple dying UML threads). + * ignore ENOENT errors for anything (they happen, strangely enough - possibly + * due to races between multiple dying UML threads). */ static int remove_files_and_dir(char *dir) { @@ -116,7 +120,8 @@ out: return ret; } -/* This says that there isn't already a user of the specified directory even if +/* + * This says that there isn't already a user of the specified directory even if * there are errors during the checking. This is because if these errors * happen, the directory is unusable by the pre-existing UML, so we might as * well take it over. This could happen either by @@ -134,44 +139,45 @@ static inline int is_umdir_used(char *dir) int dead, fd, p, n, err; n = snprintf(file, sizeof(file), "%s/pid", dir); - if(n >= sizeof(file)){ - printk("is_umdir_used - pid filename too long\n"); + if (n >= sizeof(file)) { + printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n"); err = -E2BIG; goto out; } dead = 0; fd = open(file, O_RDONLY); - if(fd < 0) { + if (fd < 0) { fd = -errno; - if(fd != -ENOENT){ - printk("is_umdir_used : couldn't open pid file '%s', " - "err = %d\n", file, -fd); + if (fd != -ENOENT) { + printk(UM_KERN_ERR "is_umdir_used : couldn't open pid " + "file '%s', err = %d\n", file, -fd); } goto out; } err = 0; n = read(fd, pid, sizeof(pid)); - if(n < 0){ - printk("is_umdir_used : couldn't read pid file '%s', " - "err = %d\n", file, errno); + if (n < 0) { + printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " + "'%s', err = %d\n", file, errno); goto out_close; - } else if(n == 0){ - printk("is_umdir_used : couldn't read pid file '%s', " - "0-byte read\n", file); + } else if (n == 0) { + printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " + "'%s', 0-byte read\n", file); goto out_close; } p = strtoul(pid, &end, 0); - if(end == pid){ - printk("is_umdir_used : couldn't parse pid file '%s', " - "errno = %d\n", file, errno); + if (end == pid) { + printk(UM_KERN_ERR "is_umdir_used : couldn't parse pid file " + "'%s', errno = %d\n", file, errno); goto out_close; } - if((kill(p, 0) == 0) || (errno != ESRCH)){ - printk("umid \"%s\" is already in use by pid %d\n", umid, p); + if ((kill(p, 0) == 0) || (errno != ESRCH)) { + printk(UM_KERN_ERR "umid \"%s\" is already in use by pid %d\n", + umid, p); return 1; } @@ -195,8 +201,8 @@ static int umdir_take_if_dead(char *dir) ret = remove_files_and_dir(dir); if (ret) { - printk("is_umdir_used - remove_files_and_dir failed with " - "err = %d\n", ret); + printk(UM_KERN_ERR "is_umdir_used - remove_files_and_dir " + "failed with err = %d\n", ret); } return ret; } @@ -207,27 +213,28 @@ static void __init create_pid_file(void) char pid[sizeof("nnnnn\0")]; int fd, n; - if(umid_file_name("pid", file, sizeof(file))) + if (umid_file_name("pid", file, sizeof(file))) return; fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); - if(fd < 0){ - printk("Open of machine pid file \"%s\" failed: %s\n", - file, strerror(errno)); + if (fd < 0) { + printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: " + "%s\n", file, strerror(errno)); return; } snprintf(pid, sizeof(pid), "%d\n", getpid()); n = write(fd, pid, strlen(pid)); - if(n != strlen(pid)) - printk("Write of pid file failed - err = %d\n", errno); + if (n != strlen(pid)) + printk(UM_KERN_ERR "Write of pid file failed - err = %d\n", + errno); close(fd); } int __init set_umid(char *name) { - if(strlen(name) > UMID_LEN - 1) + if (strlen(name) > UMID_LEN - 1) return -E2BIG; strlcpy(umid, name, sizeof(umid)); @@ -243,18 +250,18 @@ int __init make_umid(void) int fd, err; char tmp[256]; - if(umid_setup) + if (umid_setup) return 0; make_uml_dir(); - if(*umid == '\0'){ + if (*umid == '\0') { strlcpy(tmp, uml_dir, sizeof(tmp)); strlcat(tmp, "XXXXXX", sizeof(tmp)); fd = mkstemp(tmp); - if(fd < 0){ - printk("make_umid - mkstemp(%s) failed: %s\n", - tmp, strerror(errno)); + if (fd < 0) { + printk(UM_KERN_ERR "make_umid - mkstemp(%s) failed: " + "%s\n", tmp, strerror(errno)); err = -errno; goto err; } @@ -263,11 +270,12 @@ int __init make_umid(void) set_umid(&tmp[strlen(uml_dir)]); - /* There's a nice tiny little race between this unlink and + /* + * There's a nice tiny little race between this unlink and * the mkdir below. It'd be nice if there were a mkstemp * for directories. */ - if(unlink(tmp)){ + if (unlink(tmp)) { err = -errno; goto err; } @@ -275,9 +283,9 @@ int __init make_umid(void) snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid); err = mkdir(tmp, 0777); - if(err < 0){ + if (err < 0) { err = -errno; - if(err != -EEXIST) + if (err != -EEXIST) goto err; if (umdir_take_if_dead(tmp) < 0) @@ -285,9 +293,10 @@ int __init make_umid(void) err = mkdir(tmp, 0777); } - if(err){ + if (err) { err = -errno; - printk("Failed to create '%s' - err = %d\n", umid, -errno); + printk(UM_KERN_ERR "Failed to create '%s' - err = %d\n", umid, + errno); goto err; } @@ -302,14 +311,15 @@ int __init make_umid(void) static int __init make_umid_init(void) { - if(!make_umid()) + if (!make_umid()) return 0; - /* If initializing with the given umid failed, then try again with + /* + * If initializing with the given umid failed, then try again with * a random one. */ - printk("Failed to initialize umid \"%s\", trying with a random umid\n", - umid); + printk(UM_KERN_ERR "Failed to initialize umid \"%s\", trying with a " + "random umid\n", umid); *umid = '\0'; make_umid(); @@ -323,12 +333,12 @@ int __init umid_file_name(char *name, char *buf, int len) int n, err; err = make_umid(); - if(err) + if (err) return err; n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name); - if(n >= len){ - printk("umid_file_name : buffer too short\n"); + if (n >= len) { + printk(UM_KERN_ERR "umid_file_name : buffer too short\n"); return -E2BIG; } @@ -342,21 +352,22 @@ char *get_umid(void) static int __init set_uml_dir(char *name, int *add) { - if(*name == '\0'){ + if (*name == '\0') { printf("uml_dir can't be an empty string\n"); return 0; } - if(name[strlen(name) - 1] == '/'){ + if (name[strlen(name) - 1] == '/') { uml_dir = name; return 0; } uml_dir = malloc(strlen(name) + 2); - if(uml_dir == NULL){ + if (uml_dir == NULL) { printf("Failed to malloc uml_dir - error = %d\n", errno); - /* Return 0 here because do_initcalls doesn't look at + /* + * Return 0 here because do_initcalls doesn't look at * the return value. */ return 0; @@ -377,7 +388,7 @@ static void remove_umid_dir(void) sprintf(dir, "%s%s", uml_dir, umid); err = remove_files_and_dir(dir); - if(err) + if (err) printf("remove_umid_dir - remove_files_and_dir failed with " "err = %d\n", err); } diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 7cbcf484e13..ef095436a78 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -105,6 +105,44 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) void os_dump_core(void) { + int pid; + signal(SIGSEGV, SIG_DFL); + + /* + * We are about to SIGTERM this entire process group to ensure that + * nothing is around to run after the kernel exits. The + * kernel wants to abort, not die through SIGTERM, so we + * ignore it here. + */ + + signal(SIGTERM, SIG_IGN); + kill(0, SIGTERM); + /* + * Most of the other processes associated with this UML are + * likely sTopped, so give them a SIGCONT so they see the + * SIGTERM. + */ + kill(0, SIGCONT); + + /* + * Now, having sent signals to everyone but us, make sure they + * die by ptrace. Processes can survive what's been done to + * them so far - the mechanism I understand is receiving a + * SIGSEGV and segfaulting immediately upon return. There is + * always a SIGSEGV pending, and (I'm guessing) signals are + * processed in numeric order so the SIGTERM (signal 15 vs + * SIGSEGV being signal 11) is never handled. + * + * Run a waitpid loop until we get some kind of error. + * Hopefully, it's ECHILD, but there's not a lot we can do if + * it's something else. Tell os_kill_ptraced_process not to + * wait for the child to report its death because there's + * nothing reasonable to do if that fails. + */ + + while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) + os_kill_ptraced_process(pid, 0); + abort(); } |