Commit 4ecd4ff5 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML updates from Richard Weinberger:
 "Mostly fixes for UML:

   - First round of fixes for PTRACE_GETRESET/SETREGSET

   - A printf vs printk cleanup

   - Minor improvements"

* 'for-linus-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: Correctly check for PTRACE_GETRESET/SETREGSET
  um: v2: Use generic NOTES macro
  um: Add kerneldoc for userspace_tramp() and start_userspace()
  um: Add kerneldoc for segv_handler
  um: stub-data.h: remove superfluous include
  um: userspace - be more verbose in ptrace set regs error
  um: add dummy ioremap and iounmap functions
  um: Allow building and running on older hosts
  um: Avoid longjmp/setjmp symbol clashes with libpthread.a
  um: console: Ignore console= option
  um: Use os_warn to print out pre-boot warning/error messages
  um: Add os_warn() for pre-boot warning/error messages
  um: Use os_info for the messages on normal path
  um: Add os_info() for pre-boot information messages
  um: Use printk instead of printf in make_uml_dir
parents 966859b9 61e8d462
...@@ -59,10 +59,14 @@ KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um ...@@ -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 # Same things for in6addr_loopback and mktime - found in libc. For these two we
# only get link-time error, luckily. # 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. # These apply to USER_CFLAGS to.
KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \ KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
-Dlongjmp=kernel_longjmp -Dsetjmp=kernel_setjmp \
-Din6addr_loopback=kernel_in6addr_loopback \ -Din6addr_loopback=kernel_in6addr_loopback \
-Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr
......
...@@ -192,6 +192,9 @@ __uml_exitcall(console_exit); ...@@ -192,6 +192,9 @@ __uml_exitcall(console_exit);
static int console_chan_setup(char *str) 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"); line_setup(vt_conf, MAX_TTYS, &def_conf, str, "console");
return 1; return 1;
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
PROVIDE (_unprotected_end = .); PROVIDE (_unprotected_end = .);
. = ALIGN(4096); . = ALIGN(4096);
.note : { *(.note.*) } NOTES
EXCEPTION_TABLE(0) EXCEPTION_TABLE(0)
BUG_TABLE BUG_TABLE
......
#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 <asm-generic/io.h>
#endif
...@@ -242,6 +242,10 @@ extern void setup_hostinfo(char *buf, int len); ...@@ -242,6 +242,10 @@ extern void setup_hostinfo(char *buf, int len);
extern void os_dump_core(void) __attribute__ ((noreturn)); extern void os_dump_core(void) __attribute__ ((noreturn));
extern void um_early_printk(const char *s, unsigned int n); extern void um_early_printk(const char *s, unsigned int n);
extern void os_fix_helper_signals(void); 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 */ /* time.c */
extern void os_idle_sleep(unsigned long long nsecs); extern void os_idle_sleep(unsigned long long nsecs);
......
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#ifndef __STUB_DATA_H #ifndef __STUB_DATA_H
#define __STUB_DATA_H #define __STUB_DATA_H
#include <time.h>
struct stub_data { struct stub_data {
unsigned long offset; unsigned long offset;
int fd; int fd;
......
...@@ -89,8 +89,8 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, ...@@ -89,8 +89,8 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
offset = uml_reserved - uml_physmem; offset = uml_reserved - uml_physmem;
map_size = len - offset; map_size = len - offset;
if(map_size <= 0) { if(map_size <= 0) {
printf("Too few physical memory! Needed=%d, given=%d\n", os_warn("Too few physical memory! Needed=%lu, given=%lu\n",
offset, len); offset, len);
exit(1); exit(1);
} }
...@@ -99,9 +99,9 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, ...@@ -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, err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
map_size, 1, 1, 1); map_size, 1, 1, 1);
if (err < 0) { if (err < 0) {
printf("setup_physmem - mapping %ld bytes of memory at 0x%p " os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p "
"failed - errno = %d\n", map_size, "failed - errno = %d\n", map_size,
(void *) uml_reserved, err); (void *) uml_reserved, err);
exit(1); exit(1);
} }
......
...@@ -183,6 +183,16 @@ void fatal_sigsegv(void) ...@@ -183,6 +183,16 @@ void fatal_sigsegv(void)
os_dump_core(); 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) void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
{ {
struct faultinfo * fi = UPT_FAULTINFO(regs); struct faultinfo * fi = UPT_FAULTINFO(regs);
......
...@@ -34,7 +34,7 @@ static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; ...@@ -34,7 +34,7 @@ static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
static void __init add_arg(char *arg) static void __init add_arg(char *arg)
{ {
if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { 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); exit(1);
} }
if (strlen(command_line) > 0) if (strlen(command_line) > 0)
...@@ -120,6 +120,7 @@ static const char *usage_string = ...@@ -120,6 +120,7 @@ static const char *usage_string =
static int __init uml_version_setup(char *line, int *add) static int __init uml_version_setup(char *line, int *add)
{ {
/* Explicitly use printf() to show version in stdout */
printf("%s\n", init_utsname()->release); printf("%s\n", init_utsname()->release);
exit(0); exit(0);
...@@ -148,8 +149,8 @@ __uml_setup("root=", uml_root_setup, ...@@ -148,8 +149,8 @@ __uml_setup("root=", uml_root_setup,
static int __init no_skas_debug_setup(char *line, int *add) static int __init no_skas_debug_setup(char *line, int *add)
{ {
printf("'debug' is not necessary to gdb UML in skas mode - run \n"); os_warn("'debug' is not necessary to gdb UML in skas mode - run\n");
printf("'gdb linux'\n"); os_warn("'gdb linux'\n");
return 0; return 0;
} }
...@@ -165,6 +166,7 @@ static int __init Usage(char *line, int *add) ...@@ -165,6 +166,7 @@ static int __init Usage(char *line, int *add)
printf(usage_string, init_utsname()->release); printf(usage_string, init_utsname()->release);
p = &__uml_help_start; p = &__uml_help_start;
/* Explicitly use printf() to show help in stdout */
while (p < &__uml_help_end) { while (p < &__uml_help_end) {
printf("%s", *p); printf("%s", *p);
p++; p++;
...@@ -283,8 +285,8 @@ int __init linux_main(int argc, char **argv) ...@@ -283,8 +285,8 @@ int __init linux_main(int argc, char **argv)
diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
if (diff > 1024 * 1024) { if (diff > 1024 * 1024) {
printf("Adding %ld bytes to physical memory to account for " os_info("Adding %ld bytes to physical memory to account for "
"exec-shield gap\n", diff); "exec-shield gap\n", diff);
physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
} }
...@@ -324,8 +326,8 @@ int __init linux_main(int argc, char **argv) ...@@ -324,8 +326,8 @@ int __init linux_main(int argc, char **argv)
end_vm = start_vm + virtmem_size; end_vm = start_vm + virtmem_size;
if (virtmem_size < physmem_size) if (virtmem_size < physmem_size)
printf("Kernel virtual memory size shrunk to %lu bytes\n", os_info("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size); virtmem_size);
os_flush_stdout(); os_flush_stdout();
......
...@@ -16,14 +16,14 @@ static int __init set_umid_arg(char *name, int *add) ...@@ -16,14 +16,14 @@ static int __init set_umid_arg(char *name, int *add)
int err; int err;
if (umid_inited) { if (umid_inited) {
printf("umid already set\n"); os_warn("umid already set\n");
return 0; return 0;
} }
*add = 0; *add = 0;
err = set_umid(name); err = set_umid(name);
if (err == -EEXIST) if (err == -EEXIST)
printf("umid '%s' already in use\n", name); os_warn("umid '%s' already in use\n", name);
else if (!err) else if (!err)
umid_inited = 1; umid_inited = 1;
......
...@@ -136,7 +136,7 @@ int main(int argc, char**argv) ...@@ -136,7 +136,7 @@ int main(int argc, char**argv)
int ret; int ret;
argc--; argc--;
if (!argc) { if (!argc) {
fprintf(stderr, "Not enough arguments\n"); os_warn("Not enough arguments\n");
return 1; return 1;
} }
argv++; argv++;
......
...@@ -74,8 +74,8 @@ static void install_fatal_handler(int sig) ...@@ -74,8 +74,8 @@ static void install_fatal_handler(int sig)
action.sa_restorer = NULL; action.sa_restorer = NULL;
action.sa_handler = last_ditch_exit; 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", os_warn("failed to install handler for signal %d "
sig, errno); "- errno = %d\n", sig, errno);
exit(1); exit(1);
} }
} }
...@@ -175,7 +175,7 @@ int __init main(int argc, char **argv, char **envp) ...@@ -175,7 +175,7 @@ int __init main(int argc, char **argv, char **envp)
/* disable SIGIO for the fds and set SIGIO to be ignored */ /* disable SIGIO for the fds and set SIGIO to be ignored */
err = deactivate_all_fds(); err = deactivate_all_fds();
if (err) 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 * Let any pending signals fire now. This ensures
...@@ -184,14 +184,13 @@ int __init main(int argc, char **argv, char **envp) ...@@ -184,14 +184,13 @@ int __init main(int argc, char **argv, char **envp)
*/ */
unblock_signals(); unblock_signals();
os_info("\n");
/* Reboot */ /* Reboot */
if (ret) { if (ret) {
printf("\n");
execvp(new_argv[0], new_argv); execvp(new_argv[0], new_argv);
perror("Failed to exec kernel"); perror("Failed to exec kernel");
ret = 1; ret = 1;
} }
printf("\n");
return uml_exitcode; return uml_exitcode;
} }
......
...@@ -25,13 +25,13 @@ static int __init check_tmpfs(const char *dir) ...@@ -25,13 +25,13 @@ static int __init check_tmpfs(const char *dir)
{ {
struct statfs st; 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) { if (statfs(dir, &st) < 0) {
printf("%s\n", strerror(errno)); os_info("%s\n", strerror(errno));
} else if (st.f_type != TMPFS_MAGIC) { } else if (st.f_type != TMPFS_MAGIC) {
printf("no\n"); os_info("no\n");
} else { } else {
printf("OK\n"); os_info("OK\n");
return 0; return 0;
} }
return -1; return -1;
...@@ -61,18 +61,18 @@ static char * __init choose_tempdir(void) ...@@ -61,18 +61,18 @@ static char * __init choose_tempdir(void)
int i; int i;
const char *dir; const char *dir;
printf("Checking environment variables for a tempdir..."); os_info("Checking environment variables for a tempdir...");
for (i = 0; vars[i]; i++) { for (i = 0; vars[i]; i++) {
dir = getenv(vars[i]); dir = getenv(vars[i]);
if ((dir != NULL) && (*dir != '\0')) { if ((dir != NULL) && (*dir != '\0')) {
printf("%s\n", dir); os_info("%s\n", dir);
if (check_tmpfs(dir) >= 0) if (check_tmpfs(dir) >= 0)
goto done; goto done;
else else
goto warn; goto warn;
} }
} }
printf("none found\n"); os_info("none found\n");
for (i = 0; tmpfs_dirs[i]; i++) { for (i = 0; tmpfs_dirs[i]; i++) {
dir = tmpfs_dirs[i]; dir = tmpfs_dirs[i];
...@@ -82,7 +82,7 @@ static char * __init choose_tempdir(void) ...@@ -82,7 +82,7 @@ static char * __init choose_tempdir(void)
dir = fallback_dir; dir = fallback_dir;
warn: warn:
printf("Warning: tempdir %s is not on tmpfs\n", dir); os_warn("Warning: tempdir %s is not on tmpfs\n", dir);
done: done:
/* Make a copy since getenv results may not remain valid forever. */ /* Make a copy since getenv results may not remain valid forever. */
return strdup(dir); return strdup(dir);
...@@ -100,7 +100,7 @@ static int __init make_tempfile(const char *template) ...@@ -100,7 +100,7 @@ static int __init make_tempfile(const char *template)
if (tempdir == NULL) { if (tempdir == NULL) {
tempdir = choose_tempdir(); tempdir = choose_tempdir();
if (tempdir == NULL) { if (tempdir == NULL) {
fprintf(stderr, "Failed to choose tempdir: %s\n", os_warn("Failed to choose tempdir: %s\n",
strerror(errno)); strerror(errno));
return -1; return -1;
} }
...@@ -125,7 +125,7 @@ static int __init make_tempfile(const char *template) ...@@ -125,7 +125,7 @@ static int __init make_tempfile(const char *template)
strcat(tempname, template); strcat(tempname, template);
fd = mkstemp(tempname); fd = mkstemp(tempname);
if (fd < 0) { if (fd < 0) {
fprintf(stderr, "open - cannot create %s: %s\n", tempname, os_warn("open - cannot create %s: %s\n", tempname,
strerror(errno)); strerror(errno));
goto out; goto out;
} }
...@@ -194,16 +194,16 @@ void __init check_tmpexec(void) ...@@ -194,16 +194,16 @@ void __init check_tmpexec(void)
addr = mmap(NULL, UM_KERN_PAGE_SIZE, addr = mmap(NULL, UM_KERN_PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); 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) { if (addr == MAP_FAILED) {
err = errno; err = errno;
printf("%s\n", strerror(err)); os_warn("%s\n", strerror(err));
close(fd); close(fd);
if (err == EPERM) if (err == EPERM)
printf("%s must be not mounted noexec\n", tempdir); os_warn("%s must be not mounted noexec\n", tempdir);
exit(1); exit(1);
} }
printf("OK\n"); os_info("OK\n");
munmap(addr, UM_KERN_PAGE_SIZE); munmap(addr, UM_KERN_PAGE_SIZE);
close(fd); close(fd);
......
...@@ -108,7 +108,7 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi) ...@@ -108,7 +108,7 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi)
wait_stub_done(pid); 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. * the stub stack page. We just have to copy it.
*/ */
memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
...@@ -175,6 +175,21 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, ...@@ -175,6 +175,21 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
extern char __syscall_stub_start[]; 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) static int userspace_tramp(void *stack)
{ {
void *addr; void *addr;
...@@ -236,12 +251,24 @@ static int userspace_tramp(void *stack) ...@@ -236,12 +251,24 @@ static int userspace_tramp(void *stack)
int userspace_pid[NR_CPUS]; 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) int start_userspace(unsigned long stub_stack)
{ {
void *stack; void *stack;
unsigned long sp; unsigned long sp;
int pid, status, n, flags, err; int pid, status, n, flags, err;
/* setup a temporary stack page */
stack = mmap(NULL, UM_KERN_PAGE_SIZE, stack = mmap(NULL, UM_KERN_PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
...@@ -252,10 +279,12 @@ int start_userspace(unsigned long stub_stack) ...@@ -252,10 +279,12 @@ int start_userspace(unsigned long stub_stack)
return err; 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 *); sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
flags = CLONE_FILES | SIGCHLD; flags = CLONE_FILES | SIGCHLD;
/* clone into new userspace process */
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
if (pid < 0) { if (pid < 0) {
err = -errno; err = -errno;
...@@ -323,11 +352,17 @@ void userspace(struct uml_pt_regs *regs) ...@@ -323,11 +352,17 @@ void userspace(struct uml_pt_regs *regs)
* fail. In this case, there is nothing to do but * fail. In this case, there is nothing to do but
* just kill the process. * 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(); 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(); fatal_sigsegv();
}
/* Now we set local_using_sysemu to be used for one loop */ /* Now we set local_using_sysemu to be used for one loop */
local_using_sysemu = get_using_sysemu(); local_using_sysemu = get_using_sysemu();
......
...@@ -166,7 +166,7 @@ static void __init check_sysemu(void) ...@@ -166,7 +166,7 @@ static void __init check_sysemu(void)
unsigned long regs[MAX_REG_NR]; unsigned long regs[MAX_REG_NR];
int pid, n, status, count=0; 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; sysemu_supported = 0;
pid = start_ptraced_child(); pid = start_ptraced_child();
...@@ -199,10 +199,10 @@ static void __init check_sysemu(void) ...@@ -199,10 +199,10 @@ static void __init check_sysemu(void)
goto fail_stopped; goto fail_stopped;
sysemu_supported = 1; sysemu_supported = 1;
non_fatal("OK\n"); os_info("OK\n");
set_using_sysemu(!force_sysemu_disabled); 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(); pid = start_ptraced_child();
if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
...@@ -244,7 +244,7 @@ static void __init check_sysemu(void) ...@@ -244,7 +244,7 @@ static void __init check_sysemu(void)
goto fail_stopped; goto fail_stopped;
sysemu_supported = 2; sysemu_supported = 2;
non_fatal("OK\n"); os_info("OK\n");
if (!force_sysemu_disabled) if (!force_sysemu_disabled)
set_using_sysemu(sysemu_supported); set_using_sysemu(sysemu_supported);
...@@ -260,7 +260,7 @@ static void __init check_ptrace(void) ...@@ -260,7 +260,7 @@ static void __init check_ptrace(void)
{ {
int pid, syscall, n, status; 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(); pid = start_ptraced_child();
if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
...@@ -292,7 +292,7 @@ static void __init check_ptrace(void) ...@@ -292,7 +292,7 @@ static void __init check_ptrace(void)
} }
} }
stop_ptraced_child(pid, 0, 1); stop_ptraced_child(pid, 0, 1);
non_fatal("OK\n"); os_info("OK\n");
check_sysemu(); check_sysemu();
} }
...@@ -308,15 +308,17 @@ static void __init check_coredump_limit(void) ...@@ -308,15 +308,17 @@ static void __init check_coredump_limit(void)
return; return;
} }
printf("Core dump limits :\n\tsoft - "); os_info("Core dump limits :\n\tsoft - ");
if (lim.rlim_cur == RLIM_INFINITY) if (lim.rlim_cur == RLIM_INFINITY)
printf("NONE\n"); os_info("NONE\n");
else printf("%lu\n", lim.rlim_cur); else
os_info("%llu\n", (unsigned long long)lim.rlim_cur);
printf("\thard - "); os_info("\thard - ");
if (lim.rlim_max == RLIM_INFINITY) if (lim.rlim_max == RLIM_INFINITY)
printf("NONE\n"); os_info("NONE\n");
else printf("%lu\n", lim.rlim_max); else
os_info("%llu\n", (unsigned long long)lim.rlim_max);
} }
void __init os_early_checks(void) void __init os_early_checks(void)
...@@ -349,7 +351,7 @@ int __init parse_iomem(char *str, int *add) ...@@ -349,7 +351,7 @@ int __init parse_iomem(char *str, int *add)
driver = str; driver = str;
file = strchr(str,','); file = strchr(str,',');
if (file == NULL) { if (file == NULL) {
fprintf(stderr, "parse_iomem : failed to parse iomem\n"); os_warn("parse_iomem : failed to parse iomem\n");
goto out; goto out;
} }
*file = '\0'; *file = '\0';
......
...@@ -35,8 +35,9 @@ static int __init make_uml_dir(void) ...@@ -35,8 +35,9 @@ static int __init make_uml_dir(void)
err = -ENOENT; err = -ENOENT;
if (home == NULL) { if (home == NULL) {
printk(UM_KERN_ERR "make_uml_dir : no value in " printk(UM_KERN_ERR
"environment for $HOME\n"); "%s: no value in environment for $HOME\n",
__func__);
goto err; goto err;
} }
strlcpy(dir, home, sizeof(dir)); strlcpy(dir, home, sizeof(dir));
...@@ -50,13 +51,15 @@ static int __init make_uml_dir(void) ...@@ -50,13 +51,15 @@ static int __init make_uml_dir(void)
err = -ENOMEM; err = -ENOMEM;
uml_dir = malloc(strlen(dir) + 1); uml_dir = malloc(strlen(dir) + 1);
if (uml_dir == NULL) { 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; goto err;
} }
strcpy(uml_dir, dir); 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)); printk(UM_KERN_ERR "Failed to mkdir '%s': %s\n",
uml_dir, strerror(errno));
err = -errno; err = -errno;
goto err_free; goto err_free;
} }
...@@ -351,7 +354,7 @@ char *get_umid(void) ...@@ -351,7 +354,7 @@ char *get_umid(void)
static int __init set_uml_dir(char *name, int *add) 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"); os_warn("uml_dir can't be an empty string\n");
return 0; return 0;
} }
...@@ -362,7 +365,7 @@ static int __init set_uml_dir(char *name, int *add) ...@@ -362,7 +365,7 @@ static int __init set_uml_dir(char *name, int *add)
uml_dir = malloc(strlen(name) + 2); uml_dir = malloc(strlen(name) + 2);
if (uml_dir == NULL) { 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 * Return 0 here because do_initcalls doesn't look at
...@@ -387,8 +390,8 @@ static void remove_umid_dir(void) ...@@ -387,8 +390,8 @@ static void remove_umid_dir(void)
sprintf(dir, "%s%s", uml_dir, umid); sprintf(dir, "%s%s", uml_dir, umid);
err = remove_files_and_dir(dir); err = remove_files_and_dir(dir);
if (err) if (err)
printf("remove_umid_dir - remove_files_and_dir failed with " os_warn("%s - remove_files_and_dir failed with err = %d\n",
"err = %d\n", err); __func__, err);
} }
__uml_exitcall(remove_umid_dir); __uml_exitcall(remove_umid_dir);
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <wait.h> #include <wait.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <init.h>
#include <os.h> #include <os.h>
void stack_protections(unsigned long address) void stack_protections(unsigned long address)
...@@ -152,3 +153,36 @@ void um_early_printk(const char *s, unsigned int n) ...@@ -152,3 +153,36 @@ void um_early_printk(const char *s, unsigned int n)
{ {
printf("%.*s", n, s); 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);
}
void os_warn(const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
vfprintf(stderr, fmt, list);
va_end(list);
}
...@@ -26,6 +26,7 @@ int save_i387_registers(int pid, unsigned long *fp_regs) ...@@ -26,6 +26,7 @@ int save_i387_registers(int pid, unsigned long *fp_regs)
int save_fp_registers(int pid, unsigned long *fp_regs) int save_fp_registers(int pid, unsigned long *fp_regs)
{ {
#ifdef PTRACE_GETREGSET
struct iovec iov; struct iovec iov;
if (have_xstate_support) { if (have_xstate_support) {
...@@ -34,9 +35,9 @@ int save_fp_registers(int pid, unsigned long *fp_regs) ...@@ -34,9 +35,9 @@ int save_fp_registers(int pid, unsigned long *fp_regs)
if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
return -errno; return -errno;
return 0; return 0;
} else { } else
#endif
return save_i387_registers(pid, fp_regs); return save_i387_registers(pid, fp_regs);
}
} }
int restore_i387_registers(int pid, unsigned long *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) ...@@ -48,6 +49,7 @@ int restore_i387_registers(int pid, unsigned long *fp_regs)
int restore_fp_registers(int pid, unsigned long *fp_regs) int restore_fp_registers(int pid, unsigned long *fp_regs)
{ {
#ifdef PTRACE_SETREGSET
struct iovec iov; struct iovec iov;
if (have_xstate_support) { if (have_xstate_support) {
...@@ -56,9 +58,9 @@ int restore_fp_registers(int pid, unsigned long *fp_regs) ...@@ -56,9 +58,9 @@ int restore_fp_registers(int pid, unsigned long *fp_regs)
if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
return -errno; return -errno;
return 0; return 0;
} else { } else
#endif
return restore_i387_registers(pid, fp_regs); return restore_i387_registers(pid, fp_regs);
}
} }
#ifdef __i386__ #ifdef __i386__
...@@ -122,6 +124,7 @@ int put_fp_registers(int pid, unsigned long *regs) ...@@ -122,6 +124,7 @@ int put_fp_registers(int pid, unsigned long *regs)
void arch_init_registers(int pid) void arch_init_registers(int pid)
{ {
#ifdef PTRACE_GETREGSET
struct _xstate fp_regs; struct _xstate fp_regs;
struct iovec iov; struct iovec iov;
...@@ -129,6 +132,7 @@ void arch_init_registers(int pid) ...@@ -129,6 +132,7 @@ void arch_init_registers(int pid)
iov.iov_len = sizeof(struct _xstate); iov.iov_len = sizeof(struct _xstate);
if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
have_xstate_support = 1; have_xstate_support = 1;
#endif
} }
#endif #endif
......
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
.text .text
.align 4 .align 4
.globl setjmp .globl kernel_setjmp
.type setjmp, @function .type kernel_setjmp, @function
setjmp: kernel_setjmp:
#ifdef _REGPARM #ifdef _REGPARM
movl %eax,%edx movl %eax,%edx
#else #else
...@@ -35,13 +35,13 @@ setjmp: ...@@ -35,13 +35,13 @@ setjmp:
movl %ecx,20(%edx) # Return address movl %ecx,20(%edx) # Return address
ret ret
.size setjmp,.-setjmp .size kernel_setjmp,.-kernel_setjmp
.text .text
.align 4 .align 4
.globl longjmp .globl kernel_longjmp
.type longjmp, @function .type kernel_longjmp, @function
longjmp: kernel_longjmp:
#ifdef _REGPARM #ifdef _REGPARM
xchgl %eax,%edx xchgl %eax,%edx
#else #else
...@@ -55,4 +55,4 @@ longjmp: ...@@ -55,4 +55,4 @@ longjmp:
movl 16(%edx),%edi movl 16(%edx),%edi
jmp *20(%edx) jmp *20(%edx)
.size longjmp,.-longjmp .size kernel_longjmp,.-kernel_longjmp
...@@ -18,9 +18,9 @@ ...@@ -18,9 +18,9 @@
.text .text
.align 4 .align 4
.globl setjmp .globl kernel_setjmp
.type setjmp, @function .type kernel_setjmp, @function
setjmp: kernel_setjmp:
pop %rsi # Return address, and adjust the stack pop %rsi # Return address, and adjust the stack
xorl %eax,%eax # Return value xorl %eax,%eax # Return value
movq %rbx,(%rdi) movq %rbx,(%rdi)
...@@ -34,13 +34,13 @@ setjmp: ...@@ -34,13 +34,13 @@ setjmp:
movq %rsi,56(%rdi) # Return address movq %rsi,56(%rdi) # Return address
ret ret
.size setjmp,.-setjmp .size kernel_setjmp,.-kernel_setjmp
.text .text
.align 4 .align 4
.globl longjmp .globl kernel_longjmp
.type longjmp, @function .type kernel_longjmp, @function
longjmp: kernel_longjmp:
movl %esi,%eax # Return value (int) movl %esi,%eax # Return value (int)
movq (%rdi),%rbx movq (%rdi),%rbx
movq 8(%rdi),%rsp movq 8(%rdi),%rsp
...@@ -51,4 +51,4 @@ longjmp: ...@@ -51,4 +51,4 @@ longjmp:
movq 48(%rdi),%r15 movq 48(%rdi),%r15
jmp *56(%rdi) jmp *56(%rdi)
.size longjmp,.-longjmp .size kernel_longjmp,.-kernel_longjmp
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/user.h> #include <sys/user.h>
#define __FRAME_OFFSETS #define __FRAME_OFFSETS
#include <asm/ptrace.h> #include <linux/ptrace.h>
#include <asm/types.h> #include <asm/types.h>
#ifdef __i386__ #ifdef __i386__
...@@ -50,7 +50,11 @@ void foo(void) ...@@ -50,7 +50,11 @@ void foo(void)
DEFINE(HOST_GS, GS); DEFINE(HOST_GS, GS);
DEFINE(HOST_ORIG_AX, ORIG_EAX); DEFINE(HOST_ORIG_AX, ORIG_EAX);
#else #else
#if defined(PTRACE_GETREGSET) && defined(PTRACE_SETREGSET)
DEFINE(HOST_FP_SIZE, sizeof(struct _xstate) / sizeof(unsigned long)); 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_BX, RBX);
DEFINE_LONGS(HOST_CX, RCX); DEFINE_LONGS(HOST_CX, RCX);
DEFINE_LONGS(HOST_DI, RDI); DEFINE_LONGS(HOST_DI, RDI);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment