um: take arch/um/sys-x86 to arch/x86/um
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:

committed by
Richard Weinberger

parent
7bbe7204e9
commit
5c48b108ec
@@ -5,7 +5,7 @@
|
||||
|
||||
obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
|
||||
registers.o sigio.o signal.o start_up.o time.o tty.o \
|
||||
umid.o tls.o user_syms.o util.o drivers/ sys-$(HEADER_ARCH)/ skas/
|
||||
umid.o tls.o user_syms.o util.o drivers/ skas/
|
||||
|
||||
obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
|
||||
|
||||
|
@@ -1,13 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||
# Licensed under the GPL
|
||||
#
|
||||
|
||||
obj-y = registers.o task_size.o mcontext.o
|
||||
|
||||
obj-$(CONFIG_X86_32) += tls.o
|
||||
obj-$(CONFIG_64BIT) += prctl.o
|
||||
|
||||
USER_OBJS := $(obj-y)
|
||||
|
||||
include arch/um/scripts/Makefile.rules
|
@@ -1,31 +0,0 @@
|
||||
#include <sys/ucontext.h>
|
||||
#define __FRAME_OFFSETS
|
||||
#include <asm/ptrace.h>
|
||||
#include <sysdep/ptrace.h>
|
||||
|
||||
void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
|
||||
{
|
||||
#ifdef __i386__
|
||||
#define COPY2(X,Y) regs->gp[X] = mc->gregs[REG_##Y]
|
||||
#define COPY(X) regs->gp[X] = mc->gregs[REG_##X]
|
||||
#define COPY_SEG(X) regs->gp[X] = mc->gregs[REG_##X] & 0xffff;
|
||||
#define COPY_SEG_CPL3(X) regs->gp[X] = (mc->gregs[REG_##X] & 0xffff) | 3;
|
||||
COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS);
|
||||
COPY(EDI); COPY(ESI); COPY(EBP);
|
||||
COPY2(UESP, ESP); /* sic */
|
||||
COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX);
|
||||
COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS);
|
||||
#else
|
||||
#define COPY2(X,Y) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##Y]
|
||||
#define COPY(X) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##X]
|
||||
COPY(R8); COPY(R9); COPY(R10); COPY(R11);
|
||||
COPY(R12); COPY(R13); COPY(R14); COPY(R15);
|
||||
COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX);
|
||||
COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP);
|
||||
COPY(RIP);
|
||||
COPY2(EFLAGS, EFL);
|
||||
COPY2(CS, CSGSFS);
|
||||
regs->gp[CS / sizeof(unsigned long)] &= 0xffff;
|
||||
regs->gp[CS / sizeof(unsigned long)] |= 3;
|
||||
#endif
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <linux/ptrace.h>
|
||||
|
||||
int os_arch_prctl(int pid, int code, unsigned long *addr)
|
||||
{
|
||||
return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
|
||||
}
|
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2004 PathScale, Inc
|
||||
* Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
#include "longjmp.h"
|
||||
#include "sysdep/ptrace_user.h"
|
||||
|
||||
int save_fp_registers(int pid, unsigned long *fp_regs)
|
||||
{
|
||||
if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int restore_fp_registers(int pid, unsigned long *fp_regs)
|
||||
{
|
||||
if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __i386__
|
||||
int have_fpx_regs = 1;
|
||||
int save_fpx_registers(int pid, unsigned long *fp_regs)
|
||||
{
|
||||
if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int restore_fpx_registers(int pid, unsigned long *fp_regs)
|
||||
{
|
||||
if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_fp_registers(int pid, unsigned long *regs)
|
||||
{
|
||||
if (have_fpx_regs)
|
||||
return save_fpx_registers(pid, regs);
|
||||
else
|
||||
return save_fp_registers(pid, regs);
|
||||
}
|
||||
|
||||
int put_fp_registers(int pid, unsigned long *regs)
|
||||
{
|
||||
if (have_fpx_regs)
|
||||
return restore_fpx_registers(pid, regs);
|
||||
else
|
||||
return restore_fp_registers(pid, regs);
|
||||
}
|
||||
|
||||
void arch_init_registers(int pid)
|
||||
{
|
||||
struct user_fpxregs_struct fpx_regs;
|
||||
int err;
|
||||
|
||||
err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
|
||||
if (!err)
|
||||
return;
|
||||
|
||||
if (errno != EIO)
|
||||
panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
|
||||
errno);
|
||||
|
||||
have_fpx_regs = 0;
|
||||
}
|
||||
#else
|
||||
|
||||
int get_fp_registers(int pid, unsigned long *regs)
|
||||
{
|
||||
return save_fp_registers(pid, regs);
|
||||
}
|
||||
|
||||
int put_fp_registers(int pid, unsigned long *regs)
|
||||
{
|
||||
return restore_fp_registers(pid, regs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned long get_thread_reg(int reg, jmp_buf *buf)
|
||||
{
|
||||
switch (reg) {
|
||||
#ifdef __i386__
|
||||
case EIP:
|
||||
return buf[0]->__eip;
|
||||
case UESP:
|
||||
return buf[0]->__esp;
|
||||
case EBP:
|
||||
return buf[0]->__ebp;
|
||||
#else
|
||||
case RIP:
|
||||
return buf[0]->__rip;
|
||||
case RSP:
|
||||
return buf[0]->__rsp;
|
||||
case RBP:
|
||||
return buf[0]->__rbp;
|
||||
#endif
|
||||
default:
|
||||
printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
|
||||
reg);
|
||||
return 0;
|
||||
}
|
||||
}
|
@@ -1,150 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include "longjmp.h"
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
static jmp_buf buf;
|
||||
|
||||
static void segfault(int sig)
|
||||
{
|
||||
longjmp(buf, 1);
|
||||
}
|
||||
|
||||
static int page_ok(unsigned long page)
|
||||
{
|
||||
unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
|
||||
unsigned long n = ~0UL;
|
||||
void *mapped = NULL;
|
||||
int ok = 0;
|
||||
|
||||
/*
|
||||
* First see if the page is readable. If it is, it may still
|
||||
* be a VDSO, so we go on to see if it's writable. If not
|
||||
* then try mapping memory there. If that fails, then we're
|
||||
* still in the kernel area. As a sanity check, we'll fail if
|
||||
* the mmap succeeds, but gives us an address different from
|
||||
* what we wanted.
|
||||
*/
|
||||
if (setjmp(buf) == 0)
|
||||
n = *address;
|
||||
else {
|
||||
mapped = mmap(address, UM_KERN_PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (mapped == MAP_FAILED)
|
||||
return 0;
|
||||
if (mapped != address)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, is it writeable? If so, then we're in user address
|
||||
* space. If not, then try mprotecting it and try the write
|
||||
* again.
|
||||
*/
|
||||
if (setjmp(buf) == 0) {
|
||||
*address = n;
|
||||
ok = 1;
|
||||
goto out;
|
||||
} else if (mprotect(address, UM_KERN_PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE) != 0)
|
||||
goto out;
|
||||
|
||||
if (setjmp(buf) == 0) {
|
||||
*address = n;
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
if (mapped != NULL)
|
||||
munmap(mapped, UM_KERN_PAGE_SIZE);
|
||||
return ok;
|
||||
}
|
||||
|
||||
unsigned long os_get_top_address(void)
|
||||
{
|
||||
struct sigaction sa, old;
|
||||
unsigned long bottom = 0;
|
||||
/*
|
||||
* A 32-bit UML on a 64-bit host gets confused about the VDSO at
|
||||
* 0xffffe000. It is mapped, is readable, can be reprotected writeable
|
||||
* and written. However, exec discovers later that it can't be
|
||||
* unmapped. So, just set the highest address to be checked to just
|
||||
* below it. This might waste some address space on 4G/4G 32-bit
|
||||
* hosts, but shouldn't hurt otherwise.
|
||||
*/
|
||||
unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
|
||||
unsigned long test, original;
|
||||
|
||||
printf("Locating the bottom of the address space ... ");
|
||||
fflush(stdout);
|
||||
|
||||
/*
|
||||
* We're going to be longjmping out of the signal handler, so
|
||||
* SA_DEFER needs to be set.
|
||||
*/
|
||||
sa.sa_handler = segfault;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_NODEFER;
|
||||
if (sigaction(SIGSEGV, &sa, &old)) {
|
||||
perror("os_get_top_address");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Manually scan the address space, bottom-up, until we find
|
||||
* the first valid page (or run out of them).
|
||||
*/
|
||||
for (bottom = 0; bottom < top; bottom++) {
|
||||
if (page_ok(bottom))
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we've got this far, we ran out of pages. */
|
||||
if (bottom == top) {
|
||||
fprintf(stderr, "Unable to determine bottom of address "
|
||||
"space.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
|
||||
printf("Locating the top of the address space ... ");
|
||||
fflush(stdout);
|
||||
|
||||
original = bottom;
|
||||
|
||||
/* This could happen with a 4G/4G split */
|
||||
if (page_ok(top))
|
||||
goto out;
|
||||
|
||||
do {
|
||||
test = bottom + (top - bottom) / 2;
|
||||
if (page_ok(test))
|
||||
bottom = test;
|
||||
else
|
||||
top = test;
|
||||
} while (top - bottom > 1);
|
||||
|
||||
out:
|
||||
/* Restore the old SIGSEGV handling */
|
||||
if (sigaction(SIGSEGV, &old, NULL)) {
|
||||
perror("os_get_top_address");
|
||||
exit(1);
|
||||
}
|
||||
top <<= UM_KERN_PAGE_SHIFT;
|
||||
printf("0x%x\n", top);
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
unsigned long os_get_top_address(void)
|
||||
{
|
||||
/* The old value of CONFIG_TOP_ADDR */
|
||||
return 0x7fc0000000;
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,35 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sysdep/tls.h"
|
||||
|
||||
/* 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 (syscall(__NR_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;
|
||||
}
|
Reference in New Issue
Block a user