From ff075d605511784c79cbf0ae73d90e07238267b3 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 24 May 2011 17:11:57 -0700 Subject: um: mmu_gather rework Fix up the um mmu_gather code to conform to the new API. Signed-off-by: Peter Zijlstra Cc: Jeff Dike Cc: Richard Weinberger Cc: Benjamin Herrenschmidt Cc: David Miller Cc: Martin Schwidefsky Cc: Russell King Cc: Paul Mundt Cc: Tony Luck Cc: KAMEZAWA Hiroyuki Cc: Hugh Dickins Cc: Mel Gorman Cc: KOSAKI Motohiro Cc: Nick Piggin Cc: Namhyung Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/asm/tlb.h | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/asm/tlb.h b/arch/um/include/asm/tlb.h index 660caedac9eb..4febacd1a8a1 100644 --- a/arch/um/include/asm/tlb.h +++ b/arch/um/include/asm/tlb.h @@ -22,9 +22,6 @@ struct mmu_gather { unsigned int fullmm; /* non-zero means full mm flush */ }; -/* Users of the generic TLB shootdown code must declare this storage space. */ -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); - static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long address) { @@ -47,27 +44,20 @@ static inline void init_tlb_gather(struct mmu_gather *tlb) } } -/* tlb_gather_mmu - * Return a pointer to an initialized struct mmu_gather. - */ -static inline struct mmu_gather * -tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) +static inline void +tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) { - struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); - tlb->mm = mm; tlb->fullmm = full_mm_flush; init_tlb_gather(tlb); - - return tlb; } extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, unsigned long end); static inline void -tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) +tlb_flush_mmu(struct mmu_gather *tlb) { if (!tlb->need_flush) return; @@ -83,12 +73,10 @@ tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) static inline void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) { - tlb_flush_mmu(tlb, start, end); + tlb_flush_mmu(tlb); /* keep the page table cache within bounds */ check_pgt_cache(); - - put_cpu_var(mmu_gathers); } /* tlb_remove_page @@ -96,11 +84,16 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) * while handling the additional races in SMP caused by other CPUs * caching valid mappings in their TLBs. */ -static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) { tlb->need_flush = 1; free_page_and_swap_cache(page); - return; + return 1; /* avoid calling tlb_flush_mmu */ +} + +static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + __tlb_remove_page(tlb, page); } /** -- cgit v1.2.1 From 1c395176962176660bb108f90e97e1686cfe0d85 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 24 May 2011 17:11:58 -0700 Subject: mm: now that all old mmu_gather code is gone, remove the storage Fold all the mmu_gather rework patches into one for submission Signed-off-by: Peter Zijlstra Reported-by: Hugh Dickins Cc: Benjamin Herrenschmidt Cc: David Miller Cc: Martin Schwidefsky Cc: Russell King Cc: Paul Mundt Cc: Jeff Dike Cc: Richard Weinberger Cc: Tony Luck Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Cc: KOSAKI Motohiro Cc: Nick Piggin Cc: Namhyung Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/smp.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/um') diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index eefb107d2d73..155206a66908 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -7,9 +7,6 @@ #include "asm/pgalloc.h" #include "asm/tlb.h" -/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - #ifdef CONFIG_SMP #include "linux/sched.h" -- cgit v1.2.1 From 0ce451acb1872eab0fcf22753f93f51567e812fa Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 24 May 2011 17:13:00 -0700 Subject: um: fix UML_LIB_PATH UML_LIB_PATH is hardcoded to /usr/lib/uml/, on 64bit systems UML_LIB_PATH needs to be /usr/lib64/uml/. Signed-off-by: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/xterm.c | 2 +- arch/um/include/shared/os.h | 6 ++++++ arch/um/os-Linux/main.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index da2caa5a21ef..8ac7146c237f 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -90,7 +90,7 @@ static int xterm_open(int input, int output, int primary, void *d, int pid, fd, new, err; char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; char *argv[] = { terminal_emulator, title_switch, title, exec_switch, - "/usr/lib/uml/port-helper", "-uml-socket", + OS_LIB_PATH "/uml/port-helper", "-uml-socket", file, NULL }; if (access(argv[4], X_OK) < 0) diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index c4617baaa4f2..f06a5da71a8f 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -29,6 +29,12 @@ #define OS_ACC_R_OK 4 /* Test for read permission. */ #define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ +#ifdef CONFIG_64BIT +#define OS_LIB_PATH "/usr/lib64/" +#else +#define OS_LIB_PATH "/usr/lib/" +#endif + /* * types taken from stat_file() in hostfs_user.c * (if they are wrong here, they are wrong there...). diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index eee69b9f52c9..39613ea42196 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -78,7 +78,7 @@ static void install_fatal_handler(int sig) } } -#define UML_LIB_PATH ":/usr/lib/uml" +#define UML_LIB_PATH ":" OS_LIB_PATH "/uml" static void setup_env_path(void) { -- cgit v1.2.1 From 2525e70d492f8c7bbe1292db8fcd973607a56ac6 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 24 May 2011 17:13:00 -0700 Subject: um: remove SIGHUP handler The UML kernel ignores SIGHUP anyway. This handler is in vain. Signed-off-by: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index 39613ea42196..fb2a97a75fb1 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -142,7 +142,6 @@ int __init main(int argc, char **argv, char **envp) */ install_fatal_handler(SIGINT); install_fatal_handler(SIGTERM); - install_fatal_handler(SIGHUP); scan_elf_aux(envp); -- cgit v1.2.1 From d634f194d4e2e58d57927c812aca097e67a2287d Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 24 May 2011 17:13:01 -0700 Subject: um: add earlyprintk support User Mode Linux can also benefit from earlyprintk. UML's earlyprintk writes kernel messages directly to stdout. Signed-off-by: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig.debug | 10 ++++++++++ arch/um/include/shared/os.h | 1 + arch/um/kernel/Makefile | 1 + arch/um/kernel/early_printk.c | 33 +++++++++++++++++++++++++++++++++ arch/um/os-Linux/util.c | 5 +++++ 5 files changed, 50 insertions(+) create mode 100644 arch/um/kernel/early_printk.c (limited to 'arch/um') diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index 8fce5e536b0f..85c86edd1e67 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug @@ -37,4 +37,14 @@ config DEBUG_STACK_USAGE stack seen so far. This option will slow down process creation and destruction somewhat. + +config EARLY_PRINTK + bool "Early printk" + default y + ---help--- + Write kernel log output directly to stdout. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. + endmenu diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index f06a5da71a8f..83c7c2ecd614 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -244,6 +244,7 @@ extern int raw(int fd); extern void setup_machinename(char *machine_out); extern void setup_hostinfo(char *buf, int len); extern void os_dump_core(void) __attribute__ ((noreturn)); +extern void um_early_printk(const char *s, unsigned int n); /* time.c */ extern void idle_sleep(unsigned long long nsecs); diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 1119233597a1..c4491c15afb2 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -17,6 +17,7 @@ obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o obj-$(CONFIG_GCOV) += gmon_syms.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o USER_OBJS := config.o diff --git a/arch/um/kernel/early_printk.c b/arch/um/kernel/early_printk.c new file mode 100644 index 000000000000..ec649bf72f68 --- /dev/null +++ b/arch/um/kernel/early_printk.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2011 Richard Weinberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include "os.h" + +static void early_console_write(struct console *con, const char *s, unsigned int n) +{ + um_early_printk(s, n); +} + +static struct console early_console = { + .name = "earlycon", + .write = early_console_write, + .flags = CON_BOOT, + .index = -1, +}; + +static int __init setup_early_printk(char *buf) +{ + register_console(&early_console); + + return 0; +} + +early_param("earlyprintk", setup_early_printk); diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 42827cafa6af..5803b1887672 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -139,3 +139,8 @@ void os_dump_core(void) uml_abort(); } + +void um_early_printk(const char *s, unsigned int n) +{ + printf("%.*s", n, s); +} -- cgit v1.2.1 From 4ff4d8d342fe25c4d1106fb0ffdd310a43d0ace0 Mon Sep 17 00:00:00 2001 From: Nolan Leake Date: Tue, 24 May 2011 17:13:02 -0700 Subject: um: add ucast ethernet transport The ucast transport is similar to the mcast transport (and, in fact, shares most of its code), only it uses UDP unicast to move packets. Obviously this is only useful for point-to-point connections between virtual ethernet devices. Signed-off-by: Nolan Leake Signed-off-by: Richard Weinberger Cc: David Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/Makefile | 4 +- arch/um/drivers/mcast.h | 24 ------ arch/um/drivers/mcast_kern.c | 120 --------------------------- arch/um/drivers/mcast_user.c | 165 ------------------------------------ arch/um/drivers/umcast.h | 27 ++++++ arch/um/drivers/umcast_kern.c | 188 ++++++++++++++++++++++++++++++++++++++++++ arch/um/drivers/umcast_user.c | 186 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 403 insertions(+), 311 deletions(-) delete mode 100644 arch/um/drivers/mcast.h delete mode 100644 arch/um/drivers/mcast_kern.c delete mode 100644 arch/um/drivers/mcast_user.c create mode 100644 arch/um/drivers/umcast.h create mode 100644 arch/um/drivers/umcast_kern.c create mode 100644 arch/um/drivers/umcast_user.c (limited to 'arch/um') diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 1d9b6ae967b0..e7582e1d248c 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -9,7 +9,7 @@ slip-objs := slip_kern.o slip_user.o slirp-objs := slirp_kern.o slirp_user.o daemon-objs := daemon_kern.o daemon_user.o -mcast-objs := mcast_kern.o mcast_user.o +umcast-objs := umcast_kern.o umcast_user.o net-objs := net_kern.o net_user.o mconsole-objs := mconsole_kern.o mconsole_user.o hostaudio-objs := hostaudio_kern.o @@ -44,7 +44,7 @@ obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o obj-$(CONFIG_UML_NET_DAEMON) += daemon.o obj-$(CONFIG_UML_NET_VDE) += vde.o -obj-$(CONFIG_UML_NET_MCAST) += mcast.o +obj-$(CONFIG_UML_NET_MCAST) += umcast.o obj-$(CONFIG_UML_NET_PCAP) += pcap.o obj-$(CONFIG_UML_NET) += net.o obj-$(CONFIG_MCONSOLE) += mconsole.o diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h deleted file mode 100644 index 6fa282e896be..000000000000 --- a/arch/um/drivers/mcast.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __DRIVERS_MCAST_H -#define __DRIVERS_MCAST_H - -#include "net_user.h" - -struct mcast_data { - char *addr; - unsigned short port; - void *mcast_addr; - int ttl; - void *dev; -}; - -extern const struct net_user_info mcast_user_info; - -extern int mcast_user_write(int fd, void *buf, int len, - struct mcast_data *pri); - -#endif diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c deleted file mode 100644 index ffc6416d5ed7..000000000000 --- a/arch/um/drivers/mcast_kern.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * user-mode-linux networking multicast transport - * Copyright (C) 2001 by Harald Welte - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * - * based on the existing uml-networking code, which is - * 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. - * - * Licensed under the GPL. - */ - -#include "linux/init.h" -#include -#include "mcast.h" -#include "net_kern.h" - -struct mcast_init { - char *addr; - int port; - int ttl; -}; - -static void mcast_init(struct net_device *dev, void *data) -{ - struct uml_net_private *pri; - struct mcast_data *dpri; - struct mcast_init *init = data; - - pri = netdev_priv(dev); - dpri = (struct mcast_data *) pri->user; - dpri->addr = init->addr; - dpri->port = init->port; - dpri->ttl = init->ttl; - dpri->dev = dev; - - printk("mcast backend multicast address: %s:%u, TTL:%u\n", - dpri->addr, dpri->port, dpri->ttl); -} - -static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) -{ - return net_recvfrom(fd, skb_mac_header(skb), - skb->dev->mtu + ETH_HEADER_OTHER); -} - -static int mcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) -{ - return mcast_user_write(fd, skb->data, skb->len, - (struct mcast_data *) &lp->user); -} - -static const struct net_kern_info mcast_kern_info = { - .init = mcast_init, - .protocol = eth_protocol, - .read = mcast_read, - .write = mcast_write, -}; - -static int mcast_setup(char *str, char **mac_out, void *data) -{ - struct mcast_init *init = data; - char *port_str = NULL, *ttl_str = NULL, *remain; - char *last; - - *init = ((struct mcast_init) - { .addr = "239.192.168.1", - .port = 1102, - .ttl = 1 }); - - remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, - NULL); - if (remain != NULL) { - printk(KERN_ERR "mcast_setup - Extra garbage on " - "specification : '%s'\n", remain); - return 0; - } - - if (port_str != NULL) { - init->port = simple_strtoul(port_str, &last, 10); - if ((*last != '\0') || (last == port_str)) { - printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", - port_str); - return 0; - } - } - - if (ttl_str != NULL) { - init->ttl = simple_strtoul(ttl_str, &last, 10); - if ((*last != '\0') || (last == ttl_str)) { - printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", - ttl_str); - return 0; - } - } - - printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, - init->port, init->ttl); - - return 1; -} - -static struct transport mcast_transport = { - .list = LIST_HEAD_INIT(mcast_transport.list), - .name = "mcast", - .setup = mcast_setup, - .user = &mcast_user_info, - .kern = &mcast_kern_info, - .private_size = sizeof(struct mcast_data), - .setup_size = sizeof(struct mcast_init), -}; - -static int register_mcast(void) -{ - register_transport(&mcast_transport); - return 0; -} - -late_initcall(register_mcast); diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c deleted file mode 100644 index ee19e91568a2..000000000000 --- a/arch/um/drivers/mcast_user.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * user-mode-linux networking multicast transport - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Copyright (C) 2001 by Harald Welte - * - * based on the existing uml-networking code, which is - * 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. - * - * Licensed under the GPL. - * - */ - -#include -#include -#include -#include "kern_constants.h" -#include "mcast.h" -#include "net_user.h" -#include "um_malloc.h" -#include "user.h" - -static struct sockaddr_in *new_addr(char *addr, unsigned short port) -{ - struct sockaddr_in *sin; - - sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); - if (sin == NULL) { - printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " - "failed\n"); - return NULL; - } - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = in_aton(addr); - sin->sin_port = htons(port); - return sin; -} - -static int mcast_user_init(void *data, void *dev) -{ - struct mcast_data *pri = data; - - pri->mcast_addr = new_addr(pri->addr, pri->port); - pri->dev = dev; - return 0; -} - -static void mcast_remove(void *data) -{ - struct mcast_data *pri = data; - - kfree(pri->mcast_addr); - pri->mcast_addr = NULL; -} - -static int mcast_open(void *data) -{ - struct mcast_data *pri = data; - struct sockaddr_in *sin = pri->mcast_addr; - struct ip_mreq mreq; - int fd, yes = 1, err = -EINVAL; - - - if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) - goto out; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - - if (fd < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open : data socket failed, " - "errno = %d\n", errno); - goto out; - } - - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, " - "errno = %d\n", errno); - goto out_close; - } - - /* set ttl according to config */ - if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, - sizeof(pri->ttl)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, " - "error = %d\n", errno); - goto out_close; - } - - /* set LOOP, so data does get fed back to local sockets */ - if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, " - "error = %d\n", errno); - goto out_close; - } - - /* bind socket to mcast address */ - if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open : data bind failed, " - "errno = %d\n", errno); - goto out_close; - } - - /* subscribe to the multicast group */ - mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; - mreq.imr_interface.s_addr = 0; - if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, " - "error = %d\n", errno); - printk(UM_KERN_ERR "There appears not to be a multicast-" - "capable network interface on the host.\n"); - printk(UM_KERN_ERR "eth0 should be configured in order to use " - "the multicast transport.\n"); - goto out_close; - } - - return fd; - - out_close: - close(fd); - out: - return err; -} - -static void mcast_close(int fd, void *data) -{ - struct ip_mreq mreq; - struct mcast_data *pri = data; - struct sockaddr_in *sin = pri->mcast_addr; - - mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; - mreq.imr_interface.s_addr = 0; - if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, " - "error = %d\n", errno); - } - - close(fd); -} - -int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) -{ - struct sockaddr_in *data_addr = pri->mcast_addr; - - return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); -} - -const struct net_user_info mcast_user_info = { - .init = mcast_user_init, - .open = mcast_open, - .close = mcast_close, - .remove = mcast_remove, - .add_address = NULL, - .delete_address = NULL, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, -}; diff --git a/arch/um/drivers/umcast.h b/arch/um/drivers/umcast.h new file mode 100644 index 000000000000..6f8c0fe890fb --- /dev/null +++ b/arch/um/drivers/umcast.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + +#ifndef __DRIVERS_UMCAST_H +#define __DRIVERS_UMCAST_H + +#include "net_user.h" + +struct umcast_data { + char *addr; + unsigned short lport; + unsigned short rport; + void *listen_addr; + void *remote_addr; + int ttl; + int unicast; + void *dev; +}; + +extern const struct net_user_info umcast_user_info; + +extern int umcast_user_write(int fd, void *buf, int len, + struct umcast_data *pri); + +#endif diff --git a/arch/um/drivers/umcast_kern.c b/arch/um/drivers/umcast_kern.c new file mode 100644 index 000000000000..42dab11d2ecf --- /dev/null +++ b/arch/um/drivers/umcast_kern.c @@ -0,0 +1,188 @@ +/* + * user-mode-linux networking multicast transport + * Copyright (C) 2001 by Harald Welte + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * + * based on the existing uml-networking code, which is + * 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. + * + * Licensed under the GPL. + */ + +#include "linux/init.h" +#include +#include "umcast.h" +#include "net_kern.h" + +struct umcast_init { + char *addr; + int lport; + int rport; + int ttl; + bool unicast; +}; + +static void umcast_init(struct net_device *dev, void *data) +{ + struct uml_net_private *pri; + struct umcast_data *dpri; + struct umcast_init *init = data; + + pri = netdev_priv(dev); + dpri = (struct umcast_data *) pri->user; + dpri->addr = init->addr; + dpri->lport = init->lport; + dpri->rport = init->rport; + dpri->unicast = init->unicast; + dpri->ttl = init->ttl; + dpri->dev = dev; + + if (dpri->unicast) { + printk(KERN_INFO "ucast backend address: %s:%u listen port: " + "%u\n", dpri->addr, dpri->rport, dpri->lport); + } else { + printk(KERN_INFO "mcast backend multicast address: %s:%u, " + "TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl); + } +} + +static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +{ + return net_recvfrom(fd, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER); +} + +static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +{ + return umcast_user_write(fd, skb->data, skb->len, + (struct umcast_data *) &lp->user); +} + +static const struct net_kern_info umcast_kern_info = { + .init = umcast_init, + .protocol = eth_protocol, + .read = umcast_read, + .write = umcast_write, +}; + +static int mcast_setup(char *str, char **mac_out, void *data) +{ + struct umcast_init *init = data; + char *port_str = NULL, *ttl_str = NULL, *remain; + char *last; + + *init = ((struct umcast_init) + { .addr = "239.192.168.1", + .lport = 1102, + .ttl = 1 }); + + remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, + NULL); + if (remain != NULL) { + printk(KERN_ERR "mcast_setup - Extra garbage on " + "specification : '%s'\n", remain); + return 0; + } + + if (port_str != NULL) { + init->lport = simple_strtoul(port_str, &last, 10); + if ((*last != '\0') || (last == port_str)) { + printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", + port_str); + return 0; + } + } + + if (ttl_str != NULL) { + init->ttl = simple_strtoul(ttl_str, &last, 10); + if ((*last != '\0') || (last == ttl_str)) { + printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", + ttl_str); + return 0; + } + } + + init->unicast = false; + init->rport = init->lport; + + printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, + init->lport, init->ttl); + + return 1; +} + +static int ucast_setup(char *str, char **mac_out, void *data) +{ + struct umcast_init *init = data; + char *lport_str = NULL, *rport_str = NULL, *remain; + char *last; + + *init = ((struct umcast_init) + { .addr = "", + .lport = 1102, + .rport = 1102 }); + + remain = split_if_spec(str, mac_out, &init->addr, + &lport_str, &rport_str, NULL); + if (remain != NULL) { + printk(KERN_ERR "ucast_setup - Extra garbage on " + "specification : '%s'\n", remain); + return 0; + } + + if (lport_str != NULL) { + init->lport = simple_strtoul(lport_str, &last, 10); + if ((*last != '\0') || (last == lport_str)) { + printk(KERN_ERR "ucast_setup - Bad listen port : " + "'%s'\n", lport_str); + return 0; + } + } + + if (rport_str != NULL) { + init->rport = simple_strtoul(rport_str, &last, 10); + if ((*last != '\0') || (last == rport_str)) { + printk(KERN_ERR "ucast_setup - Bad remote port : " + "'%s'\n", rport_str); + return 0; + } + } + + init->unicast = true; + + printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n", + init->lport, init->addr, init->rport); + + return 1; +} + +static struct transport mcast_transport = { + .list = LIST_HEAD_INIT(mcast_transport.list), + .name = "mcast", + .setup = mcast_setup, + .user = &umcast_user_info, + .kern = &umcast_kern_info, + .private_size = sizeof(struct umcast_data), + .setup_size = sizeof(struct umcast_init), +}; + +static struct transport ucast_transport = { + .list = LIST_HEAD_INIT(ucast_transport.list), + .name = "ucast", + .setup = ucast_setup, + .user = &umcast_user_info, + .kern = &umcast_kern_info, + .private_size = sizeof(struct umcast_data), + .setup_size = sizeof(struct umcast_init), +}; + +static int register_umcast(void) +{ + register_transport(&mcast_transport); + register_transport(&ucast_transport); + return 0; +} + +late_initcall(register_umcast); diff --git a/arch/um/drivers/umcast_user.c b/arch/um/drivers/umcast_user.c new file mode 100644 index 000000000000..59c56fd6f52a --- /dev/null +++ b/arch/um/drivers/umcast_user.c @@ -0,0 +1,186 @@ +/* + * user-mode-linux networking multicast transport + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 by Harald Welte + * + * based on the existing uml-networking code, which is + * 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. + * + * Licensed under the GPL. + * + */ + +#include +#include +#include +#include "kern_constants.h" +#include "umcast.h" +#include "net_user.h" +#include "um_malloc.h" +#include "user.h" + +static struct sockaddr_in *new_addr(char *addr, unsigned short port) +{ + struct sockaddr_in *sin; + + sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); + if (sin == NULL) { + printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " + "failed\n"); + return NULL; + } + sin->sin_family = AF_INET; + if (addr) + sin->sin_addr.s_addr = in_aton(addr); + else + sin->sin_addr.s_addr = INADDR_ANY; + sin->sin_port = htons(port); + return sin; +} + +static int umcast_user_init(void *data, void *dev) +{ + struct umcast_data *pri = data; + + pri->remote_addr = new_addr(pri->addr, pri->rport); + if (pri->unicast) + pri->listen_addr = new_addr(NULL, pri->lport); + else + pri->listen_addr = pri->remote_addr; + pri->dev = dev; + return 0; +} + +static void umcast_remove(void *data) +{ + struct umcast_data *pri = data; + + kfree(pri->listen_addr); + if (pri->unicast) + kfree(pri->remote_addr); + pri->listen_addr = pri->remote_addr = NULL; +} + +static int umcast_open(void *data) +{ + struct umcast_data *pri = data; + struct sockaddr_in *lsin = pri->listen_addr; + struct sockaddr_in *rsin = pri->remote_addr; + struct ip_mreq mreq; + int fd, yes = 1, err = -EINVAL; + + + if ((!pri->unicast && lsin->sin_addr.s_addr == 0) || + (rsin->sin_addr.s_addr == 0) || + (lsin->sin_port == 0) || (rsin->sin_port == 0)) + goto out; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + + if (fd < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open : data socket failed, " + "errno = %d\n", errno); + goto out; + } + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: SO_REUSEADDR failed, " + "errno = %d\n", errno); + goto out_close; + } + + if (!pri->unicast) { + /* set ttl according to config */ + if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, + sizeof(pri->ttl)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_TTL " + "failed, error = %d\n", errno); + goto out_close; + } + + /* set LOOP, so data does get fed back to local sockets */ + if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, + &yes, sizeof(yes)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_LOOP " + "failed, error = %d\n", errno); + goto out_close; + } + } + + /* bind socket to the address */ + if (bind(fd, (struct sockaddr *) lsin, sizeof(*lsin)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open : data bind failed, " + "errno = %d\n", errno); + goto out_close; + } + + if (!pri->unicast) { + /* subscribe to the multicast group */ + mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr; + mreq.imr_interface.s_addr = 0; + if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, + &mreq, sizeof(mreq)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: IP_ADD_MEMBERSHIP " + "failed, error = %d\n", errno); + printk(UM_KERN_ERR "There appears not to be a " + "multicast-capable network interface on the " + "host.\n"); + printk(UM_KERN_ERR "eth0 should be configured in order " + "to use the multicast transport.\n"); + goto out_close; + } + } + + return fd; + + out_close: + close(fd); + out: + return err; +} + +static void umcast_close(int fd, void *data) +{ + struct umcast_data *pri = data; + + if (!pri->unicast) { + struct ip_mreq mreq; + struct sockaddr_in *lsin = pri->listen_addr; + + mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr; + mreq.imr_interface.s_addr = 0; + if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, + &mreq, sizeof(mreq)) < 0) { + printk(UM_KERN_ERR "umcast_close: IP_DROP_MEMBERSHIP " + "failed, error = %d\n", errno); + } + } + + close(fd); +} + +int umcast_user_write(int fd, void *buf, int len, struct umcast_data *pri) +{ + struct sockaddr_in *data_addr = pri->remote_addr; + + return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); +} + +const struct net_user_info umcast_user_info = { + .init = umcast_user_init, + .open = umcast_open, + .close = umcast_close, + .remove = umcast_remove, + .add_address = NULL, + .delete_address = NULL, + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, +}; -- cgit v1.2.1 From 3ef6130ab25a9db6627212d2f6859cc7fc0427ed Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 24 May 2011 17:13:03 -0700 Subject: um: print info about fatal segfaults Print a short info about fatal segfaults like other archs do. Signed-off-by: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/trap.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch/um') diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 637c6505dc00..8c7b8823d1f0 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -113,6 +113,27 @@ out_of_memory: return 0; } +static void show_segv_info(struct uml_pt_regs *regs) +{ + struct task_struct *tsk = current; + struct faultinfo *fi = UPT_FAULTINFO(regs); + + if (!unhandled_signal(tsk, SIGSEGV)) + return; + + if (!printk_ratelimit()) + return; + + printk("%s%s[%d]: segfault at %lx ip %p sp %p error %x", + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, + tsk->comm, task_pid_nr(tsk), FAULT_ADDRESS(*fi), + (void *)UPT_IP(regs), (void *)UPT_SP(regs), + fi->error_code); + + print_vma_addr(KERN_CONT " in ", UPT_IP(regs)); + printk(KERN_CONT "\n"); +} + static void bad_segv(struct faultinfo fi, unsigned long ip) { struct siginfo si; @@ -141,6 +162,7 @@ void segv_handler(int sig, struct uml_pt_regs *regs) struct faultinfo * fi = UPT_FAULTINFO(regs); if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) { + show_segv_info(regs); bad_segv(*fi, UPT_IP(regs)); return; } @@ -202,6 +224,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, address, ip); } + show_segv_info(regs); + if (err == -EACCES) { si.si_signo = SIGBUS; si.si_errno = 0; -- cgit v1.2.1 From 607647ab04cb7c23616fb5c5dc8bad86f410226d Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 24 May 2011 17:13:03 -0700 Subject: um: include linux/prefetch.h Fix build failures on UML. Signed-off-by: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/asm/processor-generic.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/um') diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index d1d1b0d8a0cd..98d01bc4fa92 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h @@ -14,6 +14,8 @@ struct task_struct; #include "registers.h" #include "sysdep/archsetjmp.h" +#include + struct mm_struct; struct thread_struct { -- cgit v1.2.1 From db271cf03f5fe39feab8e1b1818c0880c7290c5c Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 24 May 2011 17:13:04 -0700 Subject: um: fix crash while os_dump_core() os_dump_core() emits SIGTERM to terminate all UML processes. Kernel threads have to exit on SIGTERM instead of calling last_ditch_exit(). Multiple calls to last_ditch_exit() can cause a crash. Signed-off-by: Richard Weinberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/process.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um') diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index e0477c3ee894..0c45dc8efb05 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -253,6 +253,7 @@ void init_new_thread_signals(void) SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); signal(SIGWINCH, SIG_IGN); + signal(SIGTERM, SIG_DFL); } int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) -- cgit v1.2.1 From 818b667ba57f68bf1e7240fa441dda0b11e6b944 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 24 May 2011 17:13:08 -0700 Subject: Remove unused PROC_CHANGE_PENALTY constant This constant hasn't been used since before the git era (2.6.12) and thus can be dropped. Signed-off-by: Stephen Boyd Cc: Russell King Cc: Richard Weinberger Cc: Hirokazu Takata Cc: Kyle McMartin Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/asm/smp.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/include/asm/smp.h b/arch/um/include/asm/smp.h index f27a96313174..4a4b09d4f366 100644 --- a/arch/um/include/asm/smp.h +++ b/arch/um/include/asm/smp.h @@ -11,7 +11,6 @@ #define cpu_logical_map(n) (n) #define cpu_number_map(n) (n) -#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */ extern int hard_smp_processor_id(void); #define NO_PROC_ID -1 -- cgit v1.2.1 From 5ca43f6c3b365024d889bc77064bb331f5a72a45 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 24 May 2011 17:13:36 -0700 Subject: lib: consolidate DEBUG_STACK_USAGE option Most arches define CONFIG_DEBUG_STACK_USAGE exactly the same way. Move it to lib/Kconfig.debug so each arch doesn't have to define it. This obviously makes the option generic, but that's fine because the config is already used in generic code. It's not obvious to me that sysrq-P actually does anything caution by keeping the most inclusive wording. Signed-off-by: Stephen Boyd Cc: Chris Metcalf Acked-by: David S. Miller Acked-by: Richard Weinberger Acked-by: Mike Frysinger Cc: Russell King Cc: Hirokazu Takata Acked-by: Ralf Baechle Cc: Paul Mackerras Acked-by: Benjamin Herrenschmidt Cc: Chen Liqin Cc: Lennox Wu Cc: Ingo Molnar Cc: Thomas Gleixner Cc: "H. Peter Anvin" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig.debug | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch/um') diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index 85c86edd1e67..68205fd3b08c 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug @@ -28,16 +28,6 @@ config GCOV If you're involved in UML kernel development and want to use gcov, say Y. If you're unsure, say N. -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - default N - help - Track the maximum kernel stack usage - this will look at each - kernel stack at process exit and log it if it's the deepest - stack seen so far. - - This option will slow down process creation and destruction somewhat. - config EARLY_PRINTK bool "Early printk" default y -- cgit v1.2.1