From e03c78ac2d7709b7556a9b8dd584e2969c6fce67 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 May 2017 02:14:57 +0900 Subject: um: Use printk instead of printf in make_uml_dir Since this function will be called after printk buffer initialized, use printk as other functions do. Signed-off-by: Masami Hiramatsu Signed-off-by: Richard Weinberger --- arch/um/os-Linux/umid.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index c1dc89261f67..37cfaba47aa6 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c @@ -35,8 +35,9 @@ static int __init make_uml_dir(void) err = -ENOENT; if (home == NULL) { - printk(UM_KERN_ERR "make_uml_dir : no value in " - "environment for $HOME\n"); + printk(UM_KERN_ERR + "%s: no value in environment for $HOME\n", + __func__); goto err; } strlcpy(dir, home, sizeof(dir)); @@ -50,13 +51,15 @@ static int __init make_uml_dir(void) err = -ENOMEM; uml_dir = malloc(strlen(dir) + 1); if (uml_dir == NULL) { - printf("make_uml_dir : malloc failed, errno = %d\n", errno); + printk(UM_KERN_ERR "%s : malloc failed, errno = %d\n", + __func__, errno); goto err; } strcpy(uml_dir, dir); if ((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)) { - printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); + printk(UM_KERN_ERR "Failed to mkdir '%s': %s\n", + uml_dir, strerror(errno)); err = -errno; goto err_free; } -- cgit v1.2.3 From f7887ee11082b468517f31ae315b474eaa48b843 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 May 2017 02:16:05 +0900 Subject: um: Add os_info() for pre-boot information messages Add os_info() for printing out pre-boot information level messages in stderr. The messages via os_info() are suppressed by "quiet" kernel command line. Signed-off-by: Masami Hiramatsu Signed-off-by: Richard Weinberger --- arch/um/include/shared/os.h | 2 ++ arch/um/os-Linux/util.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index cd1fa97776c3..9e95bcebaf9b 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -242,6 +242,8 @@ 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); extern void os_fix_helper_signals(void); +extern void os_info(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); /* time.c */ extern void os_idle_sleep(unsigned long long nsecs); diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index faee55ef6d2f..c9bad1bca108 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -13,6 +13,7 @@ #include #include #include +#include #include void stack_protections(unsigned long address) @@ -152,3 +153,27 @@ void um_early_printk(const char *s, unsigned int n) { printf("%.*s", n, s); } + +static int quiet_info; + +static int __init quiet_cmd_param(char *str, int *add) +{ + quiet_info = 1; + return 0; +} + +__uml_setup("quiet", quiet_cmd_param, +"quiet\n" +" Turns off information messages during boot.\n\n"); + +void os_info(const char *fmt, ...) +{ + va_list list; + + if (quiet_info) + return; + + va_start(list, fmt); + vfprintf(stderr, fmt, list); + va_end(list); +} -- cgit v1.2.3 From d3878bb8003009d148cd787e1a2d74cff914a7b2 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 May 2017 02:17:14 +0900 Subject: um: Use os_info for the messages on normal path Use os_info() for printing out the messages on the normal execution path. Signed-off-by: Masami Hiramatsu Signed-off-by: Richard Weinberger --- arch/um/kernel/um_arch.c | 8 ++++---- arch/um/os-Linux/main.c | 3 +-- arch/um/os-Linux/mem.c | 18 +++++++++--------- arch/um/os-Linux/start_up.c | 26 ++++++++++++++------------ 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 64a1fd06f3fd..5df91d845a0d 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -289,8 +289,8 @@ int __init linux_main(int argc, char **argv) diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); if (diff > 1024 * 1024) { - printf("Adding %ld bytes to physical memory to account for " - "exec-shield gap\n", diff); + os_info("Adding %ld bytes to physical memory to account for " + "exec-shield gap\n", diff); physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); } @@ -330,8 +330,8 @@ int __init linux_main(int argc, char **argv) end_vm = start_vm + virtmem_size; if (virtmem_size < physmem_size) - printf("Kernel virtual memory size shrunk to %lu bytes\n", - virtmem_size); + os_info("Kernel virtual memory size shrunk to %lu bytes\n", + virtmem_size); os_flush_stdout(); diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index 9d499de87e63..f880dcd6ecc9 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -184,14 +184,13 @@ int __init main(int argc, char **argv, char **envp) */ unblock_signals(); + os_info("\n"); /* Reboot */ if (ret) { - printf("\n"); execvp(new_argv[0], new_argv); perror("Failed to exec kernel"); ret = 1; } - printf("\n"); return uml_exitcode; } diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 8b1767668515..a7f6023301cd 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -25,13 +25,13 @@ static int __init check_tmpfs(const char *dir) { struct statfs st; - printf("Checking if %s is on tmpfs...", dir); + os_info("Checking if %s is on tmpfs...", dir); if (statfs(dir, &st) < 0) { - printf("%s\n", strerror(errno)); + os_info("%s\n", strerror(errno)); } else if (st.f_type != TMPFS_MAGIC) { - printf("no\n"); + os_info("no\n"); } else { - printf("OK\n"); + os_info("OK\n"); return 0; } return -1; @@ -61,18 +61,18 @@ static char * __init choose_tempdir(void) int i; const char *dir; - printf("Checking environment variables for a tempdir..."); + os_info("Checking environment variables for a tempdir..."); for (i = 0; vars[i]; i++) { dir = getenv(vars[i]); if ((dir != NULL) && (*dir != '\0')) { - printf("%s\n", dir); + os_info("%s\n", dir); if (check_tmpfs(dir) >= 0) goto done; else goto warn; } } - printf("none found\n"); + os_info("none found\n"); for (i = 0; tmpfs_dirs[i]; i++) { dir = tmpfs_dirs[i]; @@ -194,7 +194,7 @@ void __init check_tmpexec(void) addr = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); - printf("Checking PROT_EXEC mmap in %s...", tempdir); + os_info("Checking PROT_EXEC mmap in %s...", tempdir); if (addr == MAP_FAILED) { err = errno; printf("%s\n", strerror(err)); @@ -203,7 +203,7 @@ void __init check_tmpexec(void) printf("%s must be not mounted noexec\n", tempdir); exit(1); } - printf("OK\n"); + os_info("OK\n"); munmap(addr, UM_KERN_PAGE_SIZE); close(fd); diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 22a358ef1b0c..f16e001998e5 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -166,7 +166,7 @@ static void __init check_sysemu(void) unsigned long regs[MAX_REG_NR]; int pid, n, status, count=0; - non_fatal("Checking syscall emulation patch for ptrace..."); + os_info("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; pid = start_ptraced_child(); @@ -199,10 +199,10 @@ static void __init check_sysemu(void) goto fail_stopped; sysemu_supported = 1; - non_fatal("OK\n"); + os_info("OK\n"); set_using_sysemu(!force_sysemu_disabled); - non_fatal("Checking advanced syscall emulation patch for ptrace..."); + os_info("Checking advanced syscall emulation patch for ptrace..."); pid = start_ptraced_child(); if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, @@ -244,7 +244,7 @@ static void __init check_sysemu(void) goto fail_stopped; sysemu_supported = 2; - non_fatal("OK\n"); + os_info("OK\n"); if (!force_sysemu_disabled) set_using_sysemu(sysemu_supported); @@ -260,7 +260,7 @@ static void __init check_ptrace(void) { int pid, syscall, n, status; - non_fatal("Checking that ptrace can change system call numbers..."); + os_info("Checking that ptrace can change system call numbers..."); pid = start_ptraced_child(); if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, @@ -292,7 +292,7 @@ static void __init check_ptrace(void) } } stop_ptraced_child(pid, 0, 1); - non_fatal("OK\n"); + os_info("OK\n"); check_sysemu(); } @@ -308,15 +308,17 @@ static void __init check_coredump_limit(void) return; } - printf("Core dump limits :\n\tsoft - "); + os_info("Core dump limits :\n\tsoft - "); if (lim.rlim_cur == RLIM_INFINITY) - printf("NONE\n"); - else printf("%lu\n", lim.rlim_cur); + os_info("NONE\n"); + else + os_info("%llu\n", (unsigned long long)lim.rlim_cur); - printf("\thard - "); + os_info("\thard - "); if (lim.rlim_max == RLIM_INFINITY) - printf("NONE\n"); - else printf("%lu\n", lim.rlim_max); + os_info("NONE\n"); + else + os_info("%llu\n", (unsigned long long)lim.rlim_max); } void __init os_early_checks(void) -- cgit v1.2.3 From 721ccae88d04f7e9334fde4cbb3eecfaa70a31ac Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 May 2017 02:18:22 +0900 Subject: um: Add os_warn() for pre-boot warning/error messages Add os_warn() for printing out pre-boot warning/error messages in stderr. The messages via os_warn() are not suppressed by quiet option. Signed-off-by: Masami Hiramatsu Signed-off-by: Richard Weinberger --- arch/um/include/shared/os.h | 2 ++ arch/um/os-Linux/util.c | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 9e95bcebaf9b..574e03fc7ba2 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -244,6 +244,8 @@ extern void um_early_printk(const char *s, unsigned int n); extern void os_fix_helper_signals(void); extern void os_info(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +extern void os_warn(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); /* time.c */ extern void os_idle_sleep(unsigned long long nsecs); diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index c9bad1bca108..8cc8b2617a67 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -177,3 +177,12 @@ void os_info(const char *fmt, ...) vfprintf(stderr, fmt, list); va_end(list); } + +void os_warn(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + vfprintf(stderr, fmt, list); + va_end(list); +} -- cgit v1.2.3 From 0936d4f3d5a3d5daf453bc341f02ba4e68cfe40e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 May 2017 02:19:31 +0900 Subject: um: Use os_warn to print out pre-boot warning/error messages Use os_warn() instead of printf/fprintf to print out pre-boot warning/error messages to stderr. Note that the help message and version message are kept to print out to stdout, because user explicitly specifies those options to get such information. Signed-off-by: Masami Hiramatsu Signed-off-by: Richard Weinberger --- arch/um/kernel/physmem.c | 10 +++++----- arch/um/kernel/um_arch.c | 8 +++++--- arch/um/kernel/umid.c | 4 ++-- arch/um/os-Linux/execvp.c | 2 +- arch/um/os-Linux/main.c | 6 +++--- arch/um/os-Linux/mem.c | 10 +++++----- arch/um/os-Linux/start_up.c | 2 +- arch/um/os-Linux/umid.c | 8 ++++---- 8 files changed, 26 insertions(+), 24 deletions(-) diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 4c9861b421fd..f02596e9931d 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -89,8 +89,8 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, offset = uml_reserved - uml_physmem; map_size = len - offset; if(map_size <= 0) { - printf("Too few physical memory! Needed=%d, given=%d\n", - offset, len); + os_warn("Too few physical memory! Needed=%lu, given=%lu\n", + offset, len); exit(1); } @@ -99,9 +99,9 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, err = os_map_memory((void *) uml_reserved, physmem_fd, offset, map_size, 1, 1, 1); if (err < 0) { - printf("setup_physmem - mapping %ld bytes of memory at 0x%p " - "failed - errno = %d\n", map_size, - (void *) uml_reserved, err); + os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p " + "failed - errno = %d\n", map_size, + (void *) uml_reserved, err); exit(1); } diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 5df91d845a0d..9c5d111f46be 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -34,7 +34,7 @@ static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; static void __init add_arg(char *arg) { if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { - printf("add_arg: Too many command line arguments!\n"); + os_warn("add_arg: Too many command line arguments!\n"); exit(1); } if (strlen(command_line) > 0) @@ -126,6 +126,7 @@ static const char *usage_string = static int __init uml_version_setup(char *line, int *add) { + /* Explicitly use printf() to show version in stdout */ printf("%s\n", init_utsname()->release); exit(0); @@ -154,8 +155,8 @@ __uml_setup("root=", uml_root_setup, static int __init no_skas_debug_setup(char *line, int *add) { - printf("'debug' is not necessary to gdb UML in skas mode - run \n"); - printf("'gdb linux'\n"); + os_warn("'debug' is not necessary to gdb UML in skas mode - run\n"); + os_warn("'gdb linux'\n"); return 0; } @@ -171,6 +172,7 @@ static int __init Usage(char *line, int *add) printf(usage_string, init_utsname()->release); p = &__uml_help_start; + /* Explicitly use printf() to show help in stdout */ while (p < &__uml_help_end) { printf("%s", *p); p++; diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index f6cc3bd61781..10bf4aca529f 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -16,14 +16,14 @@ static int __init set_umid_arg(char *name, int *add) int err; if (umid_inited) { - printf("umid already set\n"); + os_warn("umid already set\n"); return 0; } *add = 0; err = set_umid(name); if (err == -EEXIST) - printf("umid '%s' already in use\n", name); + os_warn("umid '%s' already in use\n", name); else if (!err) umid_inited = 1; diff --git a/arch/um/os-Linux/execvp.c b/arch/um/os-Linux/execvp.c index 8fb25ca07c46..84a0777c2a45 100644 --- a/arch/um/os-Linux/execvp.c +++ b/arch/um/os-Linux/execvp.c @@ -136,7 +136,7 @@ int main(int argc, char**argv) int ret; argc--; if (!argc) { - fprintf(stderr, "Not enough arguments\n"); + os_warn("Not enough arguments\n"); return 1; } argv++; diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index f880dcd6ecc9..5f970ece5ac3 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -74,8 +74,8 @@ static void install_fatal_handler(int sig) action.sa_restorer = NULL; action.sa_handler = last_ditch_exit; if (sigaction(sig, &action, NULL) < 0) { - printf("failed to install handler for signal %d - errno = %d\n", - sig, errno); + os_warn("failed to install handler for signal %d " + "- errno = %d\n", sig, errno); exit(1); } } @@ -175,7 +175,7 @@ int __init main(int argc, char **argv, char **envp) /* disable SIGIO for the fds and set SIGIO to be ignored */ err = deactivate_all_fds(); if (err) - printf("deactivate_all_fds failed, errno = %d\n", -err); + os_warn("deactivate_all_fds failed, errno = %d\n", -err); /* * Let any pending signals fire now. This ensures diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index a7f6023301cd..e162a95ad7dd 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -82,7 +82,7 @@ static char * __init choose_tempdir(void) dir = fallback_dir; warn: - printf("Warning: tempdir %s is not on tmpfs\n", dir); + os_warn("Warning: tempdir %s is not on tmpfs\n", dir); done: /* Make a copy since getenv results may not remain valid forever. */ return strdup(dir); @@ -100,7 +100,7 @@ static int __init make_tempfile(const char *template) if (tempdir == NULL) { tempdir = choose_tempdir(); if (tempdir == NULL) { - fprintf(stderr, "Failed to choose tempdir: %s\n", + os_warn("Failed to choose tempdir: %s\n", strerror(errno)); return -1; } @@ -125,7 +125,7 @@ static int __init make_tempfile(const char *template) strcat(tempname, template); fd = mkstemp(tempname); if (fd < 0) { - fprintf(stderr, "open - cannot create %s: %s\n", tempname, + os_warn("open - cannot create %s: %s\n", tempname, strerror(errno)); goto out; } @@ -197,10 +197,10 @@ void __init check_tmpexec(void) os_info("Checking PROT_EXEC mmap in %s...", tempdir); if (addr == MAP_FAILED) { err = errno; - printf("%s\n", strerror(err)); + os_warn("%s\n", strerror(err)); close(fd); if (err == EPERM) - printf("%s must be not mounted noexec\n", tempdir); + os_warn("%s must be not mounted noexec\n", tempdir); exit(1); } os_info("OK\n"); diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index f16e001998e5..b1b6b75c5b17 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -351,7 +351,7 @@ int __init parse_iomem(char *str, int *add) driver = str; file = strchr(str,','); if (file == NULL) { - fprintf(stderr, "parse_iomem : failed to parse iomem\n"); + os_warn("parse_iomem : failed to parse iomem\n"); goto out; } *file = '\0'; diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index 37cfaba47aa6..998fbb445458 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c @@ -354,7 +354,7 @@ char *get_umid(void) static int __init set_uml_dir(char *name, int *add) { if (*name == '\0') { - printf("uml_dir can't be an empty string\n"); + os_warn("uml_dir can't be an empty string\n"); return 0; } @@ -365,7 +365,7 @@ static int __init set_uml_dir(char *name, int *add) uml_dir = malloc(strlen(name) + 2); if (uml_dir == NULL) { - printf("Failed to malloc uml_dir - error = %d\n", errno); + os_warn("Failed to malloc uml_dir - error = %d\n", errno); /* * Return 0 here because do_initcalls doesn't look at @@ -390,8 +390,8 @@ static void remove_umid_dir(void) sprintf(dir, "%s%s", uml_dir, umid); err = remove_files_and_dir(dir); if (err) - printf("remove_umid_dir - remove_files_and_dir failed with " - "err = %d\n", err); + os_warn("%s - remove_files_and_dir failed with err = %d\n", + __func__, err); } __uml_exitcall(remove_umid_dir); -- cgit v1.2.3 From 745a600cf1a6230f5e3910c340dcb312b718e114 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 May 2017 02:20:39 +0900 Subject: um: console: Ignore console= option Ignore linux kernel's console= option at uml's console option handler. Since uml's con= option is only for setting up new console, and Linux kernel's console= option specify to which console kernel output its message, we can use both option for different purpose. Signed-off-by: Masami Hiramatsu Signed-off-by: Richard Weinberger --- arch/um/drivers/stdio_console.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 7b361f36ca96..c90817b04da9 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -192,6 +192,9 @@ __uml_exitcall(console_exit); static int console_chan_setup(char *str) { + if (!strncmp(str, "sole=", 5)) /* console= option specifies tty */ + return 0; + line_setup(vt_conf, MAX_TTYS, &def_conf, str, "console"); return 1; } -- cgit v1.2.3 From f44f1e7da7c8e3f4575d5d61c4df978496903fcc Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 23 May 2017 17:32:31 -0700 Subject: um: Avoid longjmp/setjmp symbol clashes with libpthread.a Building a statically linked UML kernel on a Centos 6.9 host resulted in the following linking failure (GCC 4.4, glibc-2.12): /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/libpthread.a(libpthread.o): In function `siglongjmp': (.text+0x8490): multiple definition of `longjmp' arch/x86/um/built-in.o:/local/users/fainelli/openwrt/trunk/build_dir/target-x86_64_musl/linux-uml/linux-4.4.69/arch/x86/um/setjmp_64.S:44: first defined here /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/libpthread.a(libpthread.o): In function `sem_open': (.text+0x77cd): warning: the use of `mktemp' is dangerous, better use `mkstemp' collect2: ld returned 1 exit status make[4]: *** [vmlinux] Error 1 Adopt a solution similar to the one done for vmap where we define longjmp/setjmp to be kernel_longjmp/setjmp. In the process, make sure we do rename the functions in arch/x86/um/setjmp_*.S accordingly. Fixes: a7df4716d195 ("um: link with -lpthread") Signed-off-by: Florian Fainelli Signed-off-by: Richard Weinberger --- arch/um/Makefile | 4 ++++ arch/x86/um/setjmp_32.S | 16 ++++++++-------- arch/x86/um/setjmp_64.S | 16 ++++++++-------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/arch/um/Makefile b/arch/um/Makefile index 0ca46ededfc7..6ca4f66085c1 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -59,10 +59,14 @@ KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um # Same things for in6addr_loopback and mktime - found in libc. For these two we # only get link-time error, luckily. # +# -Dlongjmp=kernel_longjmp prevents anything from referencing the libpthread.a +# embedded copy of longjmp, same thing for setjmp. +# # These apply to USER_CFLAGS to. KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \ $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ + -Dlongjmp=kernel_longjmp -Dsetjmp=kernel_setjmp \ -Din6addr_loopback=kernel_in6addr_loopback \ -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr diff --git a/arch/x86/um/setjmp_32.S b/arch/x86/um/setjmp_32.S index b766792c9933..39053192918d 100644 --- a/arch/x86/um/setjmp_32.S +++ b/arch/x86/um/setjmp_32.S @@ -16,9 +16,9 @@ .text .align 4 - .globl setjmp - .type setjmp, @function -setjmp: + .globl kernel_setjmp + .type kernel_setjmp, @function +kernel_setjmp: #ifdef _REGPARM movl %eax,%edx #else @@ -35,13 +35,13 @@ setjmp: movl %ecx,20(%edx) # Return address ret - .size setjmp,.-setjmp + .size kernel_setjmp,.-kernel_setjmp .text .align 4 - .globl longjmp - .type longjmp, @function -longjmp: + .globl kernel_longjmp + .type kernel_longjmp, @function +kernel_longjmp: #ifdef _REGPARM xchgl %eax,%edx #else @@ -55,4 +55,4 @@ longjmp: movl 16(%edx),%edi jmp *20(%edx) - .size longjmp,.-longjmp + .size kernel_longjmp,.-kernel_longjmp diff --git a/arch/x86/um/setjmp_64.S b/arch/x86/um/setjmp_64.S index 45f547b4043e..c56942e1a38c 100644 --- a/arch/x86/um/setjmp_64.S +++ b/arch/x86/um/setjmp_64.S @@ -18,9 +18,9 @@ .text .align 4 - .globl setjmp - .type setjmp, @function -setjmp: + .globl kernel_setjmp + .type kernel_setjmp, @function +kernel_setjmp: pop %rsi # Return address, and adjust the stack xorl %eax,%eax # Return value movq %rbx,(%rdi) @@ -34,13 +34,13 @@ setjmp: movq %rsi,56(%rdi) # Return address ret - .size setjmp,.-setjmp + .size kernel_setjmp,.-kernel_setjmp .text .align 4 - .globl longjmp - .type longjmp, @function -longjmp: + .globl kernel_longjmp + .type kernel_longjmp, @function +kernel_longjmp: movl %esi,%eax # Return value (int) movq (%rdi),%rbx movq 8(%rdi),%rsp @@ -51,4 +51,4 @@ longjmp: movq 48(%rdi),%r15 jmp *56(%rdi) - .size longjmp,.-longjmp + .size kernel_longjmp,.-kernel_longjmp -- cgit v1.2.3 From 0a987645672ebde7844a9c0732a5a25f3d4bb6c6 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 25 May 2017 11:36:26 -0700 Subject: um: Allow building and running on older hosts Commit a78ff1112263 ("um: add extended processor state save/restore support") and b6024b21fec8 ("um: extend fpstate to _xstate to support YMM registers") forced the use of the x86 FP _xstate and PTRACE_GETREGSET/SETREGSET. On older hosts, we would neither be able to build UML nor run it anymore with these two commits applied because we don't have definitions for struct _xstate nor these two ptrace requests. We can determine at build time which fp context structure to check against, just like we can keep using the old i387 fp save/restore if PTRACE_GETRESET/SETREGSET are not defined. Fixes: a78ff1112263 ("um: add extended processor state save/restore support") Fixes: b6024b21fec8 ("um: extend fpstate to _xstate to support YMM registers") Signed-off-by: Florian Fainelli Signed-off-by: Richard Weinberger --- arch/x86/um/os-Linux/registers.c | 12 ++++++++---- arch/x86/um/user-offsets.c | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c index 00f54a91bb4b..28775f55bde2 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c @@ -26,6 +26,7 @@ int save_i387_registers(int pid, unsigned long *fp_regs) int save_fp_registers(int pid, unsigned long *fp_regs) { +#ifdef PTRACE_GETREGSET struct iovec iov; if (have_xstate_support) { @@ -34,9 +35,9 @@ int save_fp_registers(int pid, unsigned long *fp_regs) if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) return -errno; return 0; - } else { + } else +#endif return save_i387_registers(pid, fp_regs); - } } int restore_i387_registers(int pid, unsigned long *fp_regs) @@ -48,6 +49,7 @@ int restore_i387_registers(int pid, unsigned long *fp_regs) int restore_fp_registers(int pid, unsigned long *fp_regs) { +#ifdef PTRACE_SETREGSET struct iovec iov; if (have_xstate_support) { @@ -56,9 +58,9 @@ int restore_fp_registers(int pid, unsigned long *fp_regs) if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) return -errno; return 0; - } else { + } else +#endif return restore_i387_registers(pid, fp_regs); - } } #ifdef __i386__ @@ -122,6 +124,7 @@ int put_fp_registers(int pid, unsigned long *regs) void arch_init_registers(int pid) { +#ifdef PTRACE_GETREGSET struct _xstate fp_regs; struct iovec iov; @@ -129,6 +132,7 @@ void arch_init_registers(int pid) iov.iov_len = sizeof(struct _xstate); if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) have_xstate_support = 1; +#endif } #endif diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index cb3c22370cf5..8af0fb5d2780 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -50,7 +50,11 @@ void foo(void) DEFINE(HOST_GS, GS); DEFINE(HOST_ORIG_AX, ORIG_EAX); #else +#if defined(PTRACE_GETREGSET) && defined(PTRACE_SETREGSET) DEFINE(HOST_FP_SIZE, sizeof(struct _xstate) / sizeof(unsigned long)); +#else + DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); +#endif DEFINE_LONGS(HOST_BX, RBX); DEFINE_LONGS(HOST_CX, RCX); DEFINE_LONGS(HOST_DI, RDI); -- cgit v1.2.3 From 1bcbfbfdeb0091036db7a32e1cd31b49cce5983a Mon Sep 17 00:00:00 2001 From: Logan Gunthorpe Date: Wed, 24 May 2017 15:42:15 -0600 Subject: um: add dummy ioremap and iounmap functions The user mode architecture does not provide ioremap or iounmap, and because of this, the arch won't build when the functions are used in some core libraries. I have designs to use these functions in scatterlist.c where they'd almost certainly never be called on the um architecture but it does need to compile. Signed-off-by: Logan Gunthorpe Signed-off-by: Stephen Bates Signed-off-by: Richard Weinberger --- arch/um/include/asm/io.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 arch/um/include/asm/io.h diff --git a/arch/um/include/asm/io.h b/arch/um/include/asm/io.h new file mode 100644 index 000000000000..8f35d574f35b --- /dev/null +++ b/arch/um/include/asm/io.h @@ -0,0 +1,17 @@ +#ifndef _ASM_UM_IO_H +#define _ASM_UM_IO_H + +#define ioremap ioremap +static inline void __iomem *ioremap(phys_addr_t offset, size_t size) +{ + return (void __iomem *)(unsigned long)offset; +} + +#define iounmap iounmap +static inline void iounmap(void __iomem *addr) +{ +} + +#include + +#endif -- cgit v1.2.3 From 22e19c8d062cc19832cde13225cbc6e5283cd969 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 6 Jul 2017 00:31:14 +0200 Subject: um: userspace - be more verbose in ptrace set regs error When ptrace fails to set GP/FP regs for the target process, log the error before crashing the UML kernel. Signed-off-by: Thomas Meyer Signed-off-by: Richard Weinberger --- arch/um/os-Linux/skas/process.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 03b3c4cc7735..31c9be2c2bdd 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -323,11 +323,17 @@ void userspace(struct uml_pt_regs *regs) * fail. In this case, there is nothing to do but * just kill the process. */ - if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) + if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) { + printk(UM_KERN_ERR "userspace - ptrace set regs " + "failed, errno = %d\n", errno); fatal_sigsegv(); + } - if (put_fp_registers(pid, regs->fp)) + if (put_fp_registers(pid, regs->fp)) { + printk(UM_KERN_ERR "userspace - ptrace set fp regs " + "failed, errno = %d\n", errno); fatal_sigsegv(); + } /* Now we set local_using_sysemu to be used for one loop */ local_using_sysemu = get_using_sysemu(); -- cgit v1.2.3 From 171fa6928bcdf72372f98884b0abb93ad9b2e673 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 6 Jul 2017 00:32:33 +0200 Subject: um: stub-data.h: remove superfluous include Signed-off-by: Thomas Meyer Signed-off-by: Richard Weinberger --- arch/um/include/shared/skas/stub-data.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/um/include/shared/skas/stub-data.h b/arch/um/include/shared/skas/stub-data.h index a9deece956bf..13f404e1262b 100644 --- a/arch/um/include/shared/skas/stub-data.h +++ b/arch/um/include/shared/skas/stub-data.h @@ -8,8 +8,6 @@ #ifndef __STUB_DATA_H #define __STUB_DATA_H -#include - struct stub_data { unsigned long offset; int fd; -- cgit v1.2.3 From 88af23381ac3a04e35974d9ece422c2b6ebe7775 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 6 Jul 2017 00:34:04 +0200 Subject: um: Add kerneldoc for segv_handler Signed-off-by: Thomas Meyer Signed-off-by: Richard Weinberger --- arch/um/kernel/trap.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 59158871b9fc..4e6fcb32620f 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -183,6 +183,16 @@ void fatal_sigsegv(void) os_dump_core(); } +/** + * segv_handler() - the SIGSEGV handler + * @sig: the signal number + * @unused_si: the signal info struct; unused in this handler + * @regs: the ptrace register information + * + * The handler first extracts the faultinfo from the UML ptrace regs struct. + * If the userfault did not happen in an UML userspace process, bad_segv is called. + * Otherwise the signal did happen in a cloned userspace process, handle it. + */ void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { struct faultinfo * fi = UPT_FAULTINFO(regs); -- cgit v1.2.3 From e90998302682c41df4813da1ae019c8db79775f5 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 6 Jul 2017 00:34:05 +0200 Subject: um: Add kerneldoc for userspace_tramp() and start_userspace() Also use correct function name spelling (stub_segv_handler) for better grepping Signed-off-by: Thomas Meyer Signed-off-by: Richard Weinberger --- arch/um/os-Linux/skas/process.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 31c9be2c2bdd..819d68656673 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -108,7 +108,7 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi) 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)); @@ -175,6 +175,21 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, extern char __syscall_stub_start[]; +/** + * userspace_tramp() - userspace trampoline + * @stack: pointer to the new userspace stack page, can be NULL, if? FIXME: + * + * The userspace trampoline is used to setup a new userspace process in start_userspace() after it was clone()'ed. + * This function will run on a temporary stack page. + * It ptrace()'es itself, then + * Two pages are mapped into the userspace address space: + * - STUB_CODE (with EXEC), which contains the skas stub code + * - STUB_DATA (with R/W), which contains a data page that is used to transfer certain data between the UML userspace process and the UML kernel. + * Also for the userspace process a SIGSEGV handler is installed to catch pagefaults in the userspace process. + * And last the process stops itself to give control to the UML kernel for this userspace process. + * + * Return: Always zero, otherwise the current userspace process is ended with non null exit() call + */ static int userspace_tramp(void *stack) { void *addr; @@ -236,12 +251,24 @@ static int userspace_tramp(void *stack) int userspace_pid[NR_CPUS]; +/** + * start_userspace() - prepare a new userspace process + * @stub_stack: pointer to the stub stack. Can be NULL, if? FIXME: + * + * Setups a new temporary stack page that is used while userspace_tramp() runs + * Clones the kernel process into a new userspace process, with FDs only. + * + * Return: When positive: the process id of the new userspace process, + * when negative: an error number. + * FIXME: can PIDs become negative?! + */ int start_userspace(unsigned long stub_stack) { void *stack; unsigned long sp; int pid, status, n, flags, err; + /* setup a temporary stack page */ stack = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -252,10 +279,12 @@ int start_userspace(unsigned long stub_stack) return err; } + /* set stack pointer to the end of the stack page, so it can grow downwards */ sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); flags = CLONE_FILES | SIGCHLD; + /* clone into new userspace process */ pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); if (pid < 0) { err = -errno; -- cgit v1.2.3 From 94df7fe0d3e6418113783ff646507287c233e1e3 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Fri, 7 Jul 2017 11:17:31 +0200 Subject: um: v2: Use generic NOTES macro Signed-off-by: Thomas Meyer Signed-off-by: Richard Weinberger --- arch/um/include/asm/common.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S index 133055311dce..9e6d5997cfc4 100644 --- a/arch/um/include/asm/common.lds.S +++ b/arch/um/include/asm/common.lds.S @@ -15,7 +15,7 @@ PROVIDE (_unprotected_end = .); . = ALIGN(4096); - .note : { *(.note.*) } + NOTES EXCEPTION_TABLE(0) BUG_TABLE -- cgit v1.2.3 From 61e8d462457f202bf0c6393133425ad387825e22 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Thu, 6 Jul 2017 09:35:27 +0200 Subject: um: Correctly check for PTRACE_GETRESET/SETREGSET When checking for PTRACE_GETRESET/SETREGSET, make sure that the correct header file is included. We need linux/ptrace.h which contains all ptrace UAPI related defines. Otherwise #if defined(PTRACE_GETRESET) is always false. Cc: Florian Fainelli Signed-off-by: Richard Weinberger --- arch/x86/um/user-offsets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index 8af0fb5d2780..ae4cd58c0c7a 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -5,7 +5,7 @@ #include #include #define __FRAME_OFFSETS -#include +#include #include #ifdef __i386__ -- cgit v1.2.3