summaryrefslogtreecommitdiff
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/Makefile7
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c13
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c13
-rw-r--r--arch/um/os-Linux/helper.c10
-rw-r--r--arch/um/os-Linux/mem.c50
-rw-r--r--arch/um/os-Linux/process.c44
-rw-r--r--arch/um/os-Linux/sigio.c2
-rw-r--r--arch/um/os-Linux/skas/mem.c4
-rw-r--r--arch/um/os-Linux/skas/process.c4
-rw-r--r--arch/um/os-Linux/start_up.c20
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile2
-rw-r--r--arch/um/os-Linux/sys-i386/tls.c34
-rw-r--r--arch/um/os-Linux/tls.c76
-rw-r--r--arch/um/os-Linux/umid.c15
-rw-r--r--arch/um/os-Linux/user_syms.c9
16 files changed, 201 insertions, 104 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 1659386..f4bfc4c 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 6ae4b19..768606b 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(&ethertap_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/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 901b85e..8f49507 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -40,7 +40,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
int fd)
{
struct addr_change change;
- void *output;
+ char *output;
int n;
change.what = op;
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
index 4202b9e..190009a 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/helper.c b/arch/um/os-Linux/helper.c
index 6490a4f..6987d1d 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -43,7 +43,7 @@ static int helper_child(void *arg)
(*data->pre_exec)(data->pre_data);
execvp(argv[0], argv);
errval = errno;
- printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
+ printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
os_write_file(data->fd, &errval, sizeof(errval));
kill(os_getpid(), SIGKILL);
return(0);
@@ -92,15 +92,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
close(fds[1]);
fds[1] = -1;
- /*Read the errno value from the child.*/
+ /* Read the errno value from the child, if the exec failed, or get 0 if
+ * the exec succeeded because the pipe fd was set as close-on-exec. */
n = os_read_file(fds[0], &ret, sizeof(ret));
- if(n < 0){
+ if (n < 0) {
printk("run_helper : read on pipe failed, ret = %d\n", -n);
ret = n;
kill(pid, SIGKILL);
CATCH_EINTR(waitpid(pid, NULL, 0));
- }
- else if(n != 0){
+ } else if(n != 0){
CATCH_EINTR(n = waitpid(pid, NULL, 0));
ret = -errno;
} else {
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 9d7d69a..71bb90a 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -53,33 +53,36 @@ static void __init find_tempdir(void)
*/
int make_tempfile(const char *template, char **out_tempname, int do_unlink)
{
- char tempname[MAXPATHLEN];
+ char *tempname;
int fd;
+ tempname = malloc(MAXPATHLEN);
+
find_tempdir();
- if (*template != '/')
+ if (template[0] != '/')
strcpy(tempname, tempdir);
else
- *tempname = 0;
+ tempname[0] = '\0';
strcat(tempname, template);
fd = mkstemp(tempname);
if(fd < 0){
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
strerror(errno));
- return -1;
+ goto out;
}
if(do_unlink && (unlink(tempname) < 0)){
perror("unlink");
- return -1;
+ goto out;
}
if(out_tempname){
- *out_tempname = strdup(tempname);
- if(*out_tempname == NULL){
- perror("strdup");
- return -1;
- }
+ *out_tempname = tempname;
+ } else {
+ free(tempname);
}
return(fd);
+out:
+ free(tempname);
+ return -1;
}
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
@@ -121,36 +124,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 d261888..8176b0b 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/sigio.c b/arch/um/os-Linux/sigio.c
index 9ba9429..00e9388 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -304,8 +304,8 @@ out_clear_poll:
.size = 0,
.used = 0 });
out_free:
- kfree(p);
sigio_unlock();
+ kfree(p);
out_close2:
close(l_sigio_private[0]);
close(l_sigio_private[1]);
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index fbb080c..b3c11cf 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -82,8 +82,8 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
if (offset) {
data = (unsigned long *)(mm_idp->stack +
offset - UML_CONFIG_STUB_DATA);
- printk("do_syscall_stub : ret = %d, offset = %d, "
- "data = 0x%x\n", ret, offset, data);
+ printk("do_syscall_stub : ret = %ld, offset = %ld, "
+ "data = %p\n", ret, offset, data);
syscall = (unsigned long *)((unsigned long)data + data[0]);
printk("do_syscall_stub: syscall %ld failed, return value = "
"0x%lx, expected return value = 0x%lx\n",
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index bbf34cb..045ae00 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -265,7 +265,7 @@ void userspace(union uml_pt_regs *regs)
if(err)
panic("userspace - could not resume userspace process, "
"pid=%d, ptrace operation = %d, errno = %d\n",
- op, errno);
+ pid, op, errno);
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
if(err < 0)
@@ -369,7 +369,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
*/
wait_stub_done(pid, -1, "copy_context_skas0");
if (child_data->err != UML_CONFIG_STUB_DATA)
- panic("copy_context_skas0 - stub-child reports error %d\n",
+ panic("copy_context_skas0 - stub-child reports error %ld\n",
child_data->err);
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 3275313..387e26a 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 340ef26..b321361 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 0000000..120abbe
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/tls.c
@@ -0,0 +1,34 @@
+#include <errno.h>
+#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 0000000..9cb09a4
--- /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 */
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 198e591..34bfc1b 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -120,7 +120,8 @@ static int not_dead_yet(char *dir)
dead = 0;
fd = open(file, O_RDONLY);
- if(fd < 0){
+ if(fd < 0) {
+ fd = -errno;
if(fd != -ENOENT){
printk("not_dead_yet : couldn't open pid file '%s', "
"err = %d\n", file, -fd);
@@ -130,9 +131,13 @@ static int not_dead_yet(char *dir)
err = 0;
n = read(fd, pid, sizeof(pid));
- if(n <= 0){
+ if(n < 0){
+ printk("not_dead_yet : couldn't read pid file '%s', "
+ "err = %d\n", file, errno);
+ goto out_close;
+ } else if(n == 0){
printk("not_dead_yet : couldn't read pid file '%s', "
- "err = %d\n", file, -n);
+ "0-byte read\n", file);
goto out_close;
}
@@ -155,9 +160,9 @@ static int not_dead_yet(char *dir)
return err;
- out_close:
+out_close:
close(fd);
- out:
+out:
return 0;
}
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 8da6ab3..2598158 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -18,14 +18,19 @@ extern void *memmove(void *, const void *, size_t);
extern void *memset(void *, int, size_t);
extern int printf(const char *, ...);
+/* If they're not defined, the export is included in lib/string.c.*/
+#ifdef __HAVE_ARCH_STRLEN
EXPORT_SYMBOL(strlen);
+#endif
+#ifdef __HAVE_ARCH_STRSTR
+EXPORT_SYMBOL(strstr);
+#endif
+
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(printf);
-EXPORT_SYMBOL(strstr);
-
/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
* However, the modules will use the CRC defined *here*, no matter if it is
* good; so the versions of these symbols will always match