diff options
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r-- | arch/um/os-Linux/Makefile | 7 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/ethertap_kern.c | 13 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap_kern.c | 13 | ||||
-rw-r--r-- | arch/um/os-Linux/mem.c | 27 | ||||
-rw-r--r-- | arch/um/os-Linux/process.c | 44 | ||||
-rw-r--r-- | arch/um/os-Linux/start_up.c | 20 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/Makefile | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/tls.c | 33 | ||||
-rw-r--r-- | arch/um/os-Linux/tls.c | 76 |
9 files changed, 159 insertions, 76 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 1659386b42b..f4bfc4c7cca 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -4,7 +4,7 @@ # obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ - signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o \ + signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \ user_syms.o util.o drivers/ sys-$(SUBARCH)/ obj-$(CONFIG_MODE_SKAS) += skas/ @@ -12,12 +12,9 @@ obj-$(CONFIG_TTY_LOG) += tty_log.o user-objs-$(CONFIG_TTY_LOG) += tty_log.o USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ - process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o \ + process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \ uaccess.o umid.o util.o -elf_aux.o: $(ARCH_DIR)/kernel-offsets.h -CFLAGS_elf_aux.o += -I$(objtree)/arch/um - CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) HAVE_AIO_ABI := $(shell [ -r /usr/include/linux/aio_abi.h ] && \ diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c index 6ae4b19d9f5..768606bec23 100644 --- a/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/arch/um/os-Linux/drivers/ethertap_kern.c @@ -102,18 +102,7 @@ static struct transport ethertap_transport = { static int register_ethertap(void) { register_transport(ðertap_transport); - return(1); + return 0; } __initcall(register_ethertap); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c index 4202b9ebad4..190009a6f89 100644 --- a/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/arch/um/os-Linux/drivers/tuntap_kern.c @@ -87,18 +87,7 @@ static struct transport tuntap_transport = { static int register_tuntap(void) { register_transport(&tuntap_transport); - return(1); + return 0; } __initcall(register_tuntap); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 9d7d69a523b..6ab372da965 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -121,36 +121,11 @@ int create_tmp_file(unsigned long long len) return(fd); } -static int create_anon_file(unsigned long long len) -{ - void *addr; - int fd; - - fd = open("/dev/anon", O_RDWR); - if(fd < 0) { - perror("opening /dev/anon"); - exit(1); - } - - addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if(addr == MAP_FAILED){ - perror("mapping physmem file"); - exit(1); - } - munmap(addr, len); - - return(fd); -} - -extern int have_devanon; - int create_mem_file(unsigned long long len) { int err, fd; - if(have_devanon) - fd = create_anon_file(len); - else fd = create_tmp_file(len); + fd = create_tmp_file(len); err = os_set_exec_close(fd, 1); if(err < 0){ diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index d261888f39c..8176b0b5204 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -11,6 +11,7 @@ #include <linux/unistd.h> #include <sys/mman.h> #include <sys/wait.h> +#include <sys/mman.h> #include "ptrace_user.h" #include "os.h" #include "user.h" @@ -20,6 +21,7 @@ #include "kern_util.h" #include "longjmp.h" #include "skas_ptrace.h" +#include "kern_constants.h" #define ARBITRARY_ADDR -1 #define FAILURE_PID -1 @@ -187,6 +189,48 @@ int os_unmap_memory(void *addr, int len) return(0); } +#ifndef MADV_REMOVE +#define MADV_REMOVE 0x5 /* remove these pages & resources */ +#endif + +int os_drop_memory(void *addr, int length) +{ + int err; + + err = madvise(addr, length, MADV_REMOVE); + if(err < 0) + err = -errno; + return err; +} + +int can_drop_memory(void) +{ + void *addr; + int fd; + + printk("Checking host MADV_REMOVE support..."); + fd = create_mem_file(UM_KERN_PAGE_SIZE); + if(fd < 0){ + printk("Creating test memory file failed, err = %d\n", -fd); + return 0; + } + + addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE, fd, 0); + if(addr == MAP_FAILED){ + printk("Mapping test memory file failed, err = %d\n", -errno); + return 0; + } + + if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){ + printk("MADV_REMOVE failed, err = %d\n", -errno); + return 0; + } + + printk("OK\n"); + return 1; +} + void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) { int flags = 0, pages; diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 32753131f8d..387e26af301 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -470,25 +470,6 @@ int can_do_skas(void) } #endif -int have_devanon = 0; - -/* Runs on boot kernel stack - already safe to use printk. */ - -void check_devanon(void) -{ - int fd; - - printk("Checking for /dev/anon on the host..."); - fd = open("/dev/anon", O_RDWR); - if(fd < 0){ - printk("Not available (open failed with errno %d)\n", errno); - return; - } - - printk("OK\n"); - have_devanon = 1; -} - int __init parse_iomem(char *str, int *add) { struct iomem_region *new; @@ -664,6 +645,5 @@ void os_check_bugs(void) { check_ptrace(); check_sigio(); - check_devanon(); } diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile index 340ef26f594..b3213613c41 100644 --- a/arch/um/os-Linux/sys-i386/Makefile +++ b/arch/um/os-Linux/sys-i386/Makefile @@ -3,7 +3,7 @@ # Licensed under the GPL # -obj-$(CONFIG_MODE_SKAS) = registers.o +obj-$(CONFIG_MODE_SKAS) = registers.o tls.o USER_OBJS := $(obj-y) diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c new file mode 100644 index 00000000000..ba21f0e04a2 --- /dev/null +++ b/arch/um/os-Linux/sys-i386/tls.c @@ -0,0 +1,33 @@ +#include <linux/unistd.h> +#include "sysdep/tls.h" +#include "user_util.h" + +static _syscall1(int, get_thread_area, user_desc_t *, u_info); + +/* Checks whether host supports TLS, and sets *tls_min according to the value + * valid on the host. + * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */ +void check_host_supports_tls(int *supports_tls, int *tls_min) { + /* Values for x86 and x86_64.*/ + int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64}; + int i; + + for (i = 0; i < ARRAY_SIZE(val); i++) { + user_desc_t info; + info.entry_number = val[i]; + + if (get_thread_area(&info) == 0) { + *tls_min = val[i]; + *supports_tls = 1; + return; + } else { + if (errno == EINVAL) + continue; + else if (errno == ENOSYS) + *supports_tls = 0; + return; + } + } + + *supports_tls = 0; +} diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c new file mode 100644 index 00000000000..9cb09a45546 --- /dev/null +++ b/arch/um/os-Linux/tls.c @@ -0,0 +1,76 @@ +#include <errno.h> +#include <sys/ptrace.h> +#include <asm/ldt.h> +#include "sysdep/tls.h" +#include "uml-config.h" + +/* TLS support - we basically rely on the host's one.*/ + +/* In TT mode, this should be called only by the tracing thread, and makes sense + * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally. + * + */ + +#ifndef PTRACE_GET_THREAD_AREA +#define PTRACE_GET_THREAD_AREA 25 +#endif + +#ifndef PTRACE_SET_THREAD_AREA +#define PTRACE_SET_THREAD_AREA 26 +#endif + +int os_set_thread_area(user_desc_t *info, int pid) +{ + int ret; + + ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number, + (unsigned long) info); + if (ret < 0) + ret = -errno; + return ret; +} + +#ifdef UML_CONFIG_MODE_SKAS + +int os_get_thread_area(user_desc_t *info, int pid) +{ + int ret; + + ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number, + (unsigned long) info); + if (ret < 0) + ret = -errno; + return ret; +} + +#endif + +#ifdef UML_CONFIG_MODE_TT +#include "linux/unistd.h" + +static _syscall1(int, get_thread_area, user_desc_t *, u_info); +static _syscall1(int, set_thread_area, user_desc_t *, u_info); + +int do_set_thread_area_tt(user_desc_t *info) +{ + int ret; + + ret = set_thread_area(info); + if (ret < 0) { + ret = -errno; + } + return ret; +} + +int do_get_thread_area_tt(user_desc_t *info) +{ + int ret; + + ret = get_thread_area(info); + if (ret < 0) { + ret = -errno; + } + return ret; +} + +#endif /* UML_CONFIG_MODE_TT */ |