diff options
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r-- | arch/um/os-Linux/Makefile | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86/Makefile | 13 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86/mcontext.c | 31 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86/prctl.c | 12 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86/registers.c | 111 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86/task_size.c | 150 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86/tls.c | 35 |
7 files changed, 1 insertions, 353 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 7879e76e998f..015d00057663 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ | 6 | obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ |
7 | registers.o sigio.o signal.o start_up.o time.o tty.o \ | 7 | registers.o sigio.o signal.o start_up.o time.o tty.o \ |
8 | umid.o tls.o user_syms.o util.o drivers/ sys-$(HEADER_ARCH)/ skas/ | 8 | umid.o tls.o user_syms.o util.o drivers/ skas/ |
9 | 9 | ||
10 | obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o | 10 | obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o |
11 | 11 | ||
diff --git a/arch/um/os-Linux/sys-x86/Makefile b/arch/um/os-Linux/sys-x86/Makefile deleted file mode 100644 index 253bfb8cb702..000000000000 --- a/arch/um/os-Linux/sys-x86/Makefile +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-y = registers.o task_size.o mcontext.o | ||
7 | |||
8 | obj-$(CONFIG_X86_32) += tls.o | ||
9 | obj-$(CONFIG_64BIT) += prctl.o | ||
10 | |||
11 | USER_OBJS := $(obj-y) | ||
12 | |||
13 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/os-Linux/sys-x86/mcontext.c b/arch/um/os-Linux/sys-x86/mcontext.c deleted file mode 100644 index 1d33d72c6284..000000000000 --- a/arch/um/os-Linux/sys-x86/mcontext.c +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | #include <sys/ucontext.h> | ||
2 | #define __FRAME_OFFSETS | ||
3 | #include <asm/ptrace.h> | ||
4 | #include <sysdep/ptrace.h> | ||
5 | |||
6 | void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc) | ||
7 | { | ||
8 | #ifdef __i386__ | ||
9 | #define COPY2(X,Y) regs->gp[X] = mc->gregs[REG_##Y] | ||
10 | #define COPY(X) regs->gp[X] = mc->gregs[REG_##X] | ||
11 | #define COPY_SEG(X) regs->gp[X] = mc->gregs[REG_##X] & 0xffff; | ||
12 | #define COPY_SEG_CPL3(X) regs->gp[X] = (mc->gregs[REG_##X] & 0xffff) | 3; | ||
13 | COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS); | ||
14 | COPY(EDI); COPY(ESI); COPY(EBP); | ||
15 | COPY2(UESP, ESP); /* sic */ | ||
16 | COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX); | ||
17 | COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS); | ||
18 | #else | ||
19 | #define COPY2(X,Y) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##Y] | ||
20 | #define COPY(X) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##X] | ||
21 | COPY(R8); COPY(R9); COPY(R10); COPY(R11); | ||
22 | COPY(R12); COPY(R13); COPY(R14); COPY(R15); | ||
23 | COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX); | ||
24 | COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP); | ||
25 | COPY(RIP); | ||
26 | COPY2(EFLAGS, EFL); | ||
27 | COPY2(CS, CSGSFS); | ||
28 | regs->gp[CS / sizeof(unsigned long)] &= 0xffff; | ||
29 | regs->gp[CS / sizeof(unsigned long)] |= 3; | ||
30 | #endif | ||
31 | } | ||
diff --git a/arch/um/os-Linux/sys-x86/prctl.c b/arch/um/os-Linux/sys-x86/prctl.c deleted file mode 100644 index 9d34eddb517f..000000000000 --- a/arch/um/os-Linux/sys-x86/prctl.c +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com}) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <sys/ptrace.h> | ||
7 | #include <linux/ptrace.h> | ||
8 | |||
9 | int os_arch_prctl(int pid, int code, unsigned long *addr) | ||
10 | { | ||
11 | return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code); | ||
12 | } | ||
diff --git a/arch/um/os-Linux/sys-x86/registers.c b/arch/um/os-Linux/sys-x86/registers.c deleted file mode 100644 index 3a9b6247bbbc..000000000000 --- a/arch/um/os-Linux/sys-x86/registers.c +++ /dev/null | |||
@@ -1,111 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 PathScale, Inc | ||
3 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <errno.h> | ||
8 | #include <sys/ptrace.h> | ||
9 | #include <sys/user.h> | ||
10 | #include "longjmp.h" | ||
11 | #include "sysdep/ptrace_user.h" | ||
12 | |||
13 | int save_fp_registers(int pid, unsigned long *fp_regs) | ||
14 | { | ||
15 | if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) | ||
16 | return -errno; | ||
17 | return 0; | ||
18 | } | ||
19 | |||
20 | int restore_fp_registers(int pid, unsigned long *fp_regs) | ||
21 | { | ||
22 | if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) | ||
23 | return -errno; | ||
24 | return 0; | ||
25 | } | ||
26 | |||
27 | #ifdef __i386__ | ||
28 | int have_fpx_regs = 1; | ||
29 | int save_fpx_registers(int pid, unsigned long *fp_regs) | ||
30 | { | ||
31 | if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) | ||
32 | return -errno; | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | int restore_fpx_registers(int pid, unsigned long *fp_regs) | ||
37 | { | ||
38 | if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) | ||
39 | return -errno; | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | int get_fp_registers(int pid, unsigned long *regs) | ||
44 | { | ||
45 | if (have_fpx_regs) | ||
46 | return save_fpx_registers(pid, regs); | ||
47 | else | ||
48 | return save_fp_registers(pid, regs); | ||
49 | } | ||
50 | |||
51 | int put_fp_registers(int pid, unsigned long *regs) | ||
52 | { | ||
53 | if (have_fpx_regs) | ||
54 | return restore_fpx_registers(pid, regs); | ||
55 | else | ||
56 | return restore_fp_registers(pid, regs); | ||
57 | } | ||
58 | |||
59 | void arch_init_registers(int pid) | ||
60 | { | ||
61 | struct user_fpxregs_struct fpx_regs; | ||
62 | int err; | ||
63 | |||
64 | err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); | ||
65 | if (!err) | ||
66 | return; | ||
67 | |||
68 | if (errno != EIO) | ||
69 | panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", | ||
70 | errno); | ||
71 | |||
72 | have_fpx_regs = 0; | ||
73 | } | ||
74 | #else | ||
75 | |||
76 | int get_fp_registers(int pid, unsigned long *regs) | ||
77 | { | ||
78 | return save_fp_registers(pid, regs); | ||
79 | } | ||
80 | |||
81 | int put_fp_registers(int pid, unsigned long *regs) | ||
82 | { | ||
83 | return restore_fp_registers(pid, regs); | ||
84 | } | ||
85 | |||
86 | #endif | ||
87 | |||
88 | unsigned long get_thread_reg(int reg, jmp_buf *buf) | ||
89 | { | ||
90 | switch (reg) { | ||
91 | #ifdef __i386__ | ||
92 | case EIP: | ||
93 | return buf[0]->__eip; | ||
94 | case UESP: | ||
95 | return buf[0]->__esp; | ||
96 | case EBP: | ||
97 | return buf[0]->__ebp; | ||
98 | #else | ||
99 | case RIP: | ||
100 | return buf[0]->__rip; | ||
101 | case RSP: | ||
102 | return buf[0]->__rsp; | ||
103 | case RBP: | ||
104 | return buf[0]->__rbp; | ||
105 | #endif | ||
106 | default: | ||
107 | printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", | ||
108 | reg); | ||
109 | return 0; | ||
110 | } | ||
111 | } | ||
diff --git a/arch/um/os-Linux/sys-x86/task_size.c b/arch/um/os-Linux/sys-x86/task_size.c deleted file mode 100644 index efb16c5c9bcf..000000000000 --- a/arch/um/os-Linux/sys-x86/task_size.c +++ /dev/null | |||
@@ -1,150 +0,0 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <signal.h> | ||
4 | #include <sys/mman.h> | ||
5 | #include "longjmp.h" | ||
6 | |||
7 | #ifdef __i386__ | ||
8 | |||
9 | static jmp_buf buf; | ||
10 | |||
11 | static void segfault(int sig) | ||
12 | { | ||
13 | longjmp(buf, 1); | ||
14 | } | ||
15 | |||
16 | static int page_ok(unsigned long page) | ||
17 | { | ||
18 | unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT); | ||
19 | unsigned long n = ~0UL; | ||
20 | void *mapped = NULL; | ||
21 | int ok = 0; | ||
22 | |||
23 | /* | ||
24 | * First see if the page is readable. If it is, it may still | ||
25 | * be a VDSO, so we go on to see if it's writable. If not | ||
26 | * then try mapping memory there. If that fails, then we're | ||
27 | * still in the kernel area. As a sanity check, we'll fail if | ||
28 | * the mmap succeeds, but gives us an address different from | ||
29 | * what we wanted. | ||
30 | */ | ||
31 | if (setjmp(buf) == 0) | ||
32 | n = *address; | ||
33 | else { | ||
34 | mapped = mmap(address, UM_KERN_PAGE_SIZE, | ||
35 | PROT_READ | PROT_WRITE, | ||
36 | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
37 | if (mapped == MAP_FAILED) | ||
38 | return 0; | ||
39 | if (mapped != address) | ||
40 | goto out; | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Now, is it writeable? If so, then we're in user address | ||
45 | * space. If not, then try mprotecting it and try the write | ||
46 | * again. | ||
47 | */ | ||
48 | if (setjmp(buf) == 0) { | ||
49 | *address = n; | ||
50 | ok = 1; | ||
51 | goto out; | ||
52 | } else if (mprotect(address, UM_KERN_PAGE_SIZE, | ||
53 | PROT_READ | PROT_WRITE) != 0) | ||
54 | goto out; | ||
55 | |||
56 | if (setjmp(buf) == 0) { | ||
57 | *address = n; | ||
58 | ok = 1; | ||
59 | } | ||
60 | |||
61 | out: | ||
62 | if (mapped != NULL) | ||
63 | munmap(mapped, UM_KERN_PAGE_SIZE); | ||
64 | return ok; | ||
65 | } | ||
66 | |||
67 | unsigned long os_get_top_address(void) | ||
68 | { | ||
69 | struct sigaction sa, old; | ||
70 | unsigned long bottom = 0; | ||
71 | /* | ||
72 | * A 32-bit UML on a 64-bit host gets confused about the VDSO at | ||
73 | * 0xffffe000. It is mapped, is readable, can be reprotected writeable | ||
74 | * and written. However, exec discovers later that it can't be | ||
75 | * unmapped. So, just set the highest address to be checked to just | ||
76 | * below it. This might waste some address space on 4G/4G 32-bit | ||
77 | * hosts, but shouldn't hurt otherwise. | ||
78 | */ | ||
79 | unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT; | ||
80 | unsigned long test, original; | ||
81 | |||
82 | printf("Locating the bottom of the address space ... "); | ||
83 | fflush(stdout); | ||
84 | |||
85 | /* | ||
86 | * We're going to be longjmping out of the signal handler, so | ||
87 | * SA_DEFER needs to be set. | ||
88 | */ | ||
89 | sa.sa_handler = segfault; | ||
90 | sigemptyset(&sa.sa_mask); | ||
91 | sa.sa_flags = SA_NODEFER; | ||
92 | if (sigaction(SIGSEGV, &sa, &old)) { | ||
93 | perror("os_get_top_address"); | ||
94 | exit(1); | ||
95 | } | ||
96 | |||
97 | /* Manually scan the address space, bottom-up, until we find | ||
98 | * the first valid page (or run out of them). | ||
99 | */ | ||
100 | for (bottom = 0; bottom < top; bottom++) { | ||
101 | if (page_ok(bottom)) | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | /* If we've got this far, we ran out of pages. */ | ||
106 | if (bottom == top) { | ||
107 | fprintf(stderr, "Unable to determine bottom of address " | ||
108 | "space.\n"); | ||
109 | exit(1); | ||
110 | } | ||
111 | |||
112 | printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT); | ||
113 | printf("Locating the top of the address space ... "); | ||
114 | fflush(stdout); | ||
115 | |||
116 | original = bottom; | ||
117 | |||
118 | /* This could happen with a 4G/4G split */ | ||
119 | if (page_ok(top)) | ||
120 | goto out; | ||
121 | |||
122 | do { | ||
123 | test = bottom + (top - bottom) / 2; | ||
124 | if (page_ok(test)) | ||
125 | bottom = test; | ||
126 | else | ||
127 | top = test; | ||
128 | } while (top - bottom > 1); | ||
129 | |||
130 | out: | ||
131 | /* Restore the old SIGSEGV handling */ | ||
132 | if (sigaction(SIGSEGV, &old, NULL)) { | ||
133 | perror("os_get_top_address"); | ||
134 | exit(1); | ||
135 | } | ||
136 | top <<= UM_KERN_PAGE_SHIFT; | ||
137 | printf("0x%x\n", top); | ||
138 | |||
139 | return top; | ||
140 | } | ||
141 | |||
142 | #else | ||
143 | |||
144 | unsigned long os_get_top_address(void) | ||
145 | { | ||
146 | /* The old value of CONFIG_TOP_ADDR */ | ||
147 | return 0x7fc0000000; | ||
148 | } | ||
149 | |||
150 | #endif | ||
diff --git a/arch/um/os-Linux/sys-x86/tls.c b/arch/um/os-Linux/sys-x86/tls.c deleted file mode 100644 index 281e83ecce3d..000000000000 --- a/arch/um/os-Linux/sys-x86/tls.c +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | #include <errno.h> | ||
2 | #include <linux/unistd.h> | ||
3 | |||
4 | #include <sys/syscall.h> | ||
5 | #include <unistd.h> | ||
6 | |||
7 | #include "sysdep/tls.h" | ||
8 | |||
9 | /* Checks whether host supports TLS, and sets *tls_min according to the value | ||
10 | * valid on the host. | ||
11 | * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */ | ||
12 | void check_host_supports_tls(int *supports_tls, int *tls_min) { | ||
13 | /* Values for x86 and x86_64.*/ | ||
14 | int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64}; | ||
15 | int i; | ||
16 | |||
17 | for (i = 0; i < ARRAY_SIZE(val); i++) { | ||
18 | user_desc_t info; | ||
19 | info.entry_number = val[i]; | ||
20 | |||
21 | if (syscall(__NR_get_thread_area, &info) == 0) { | ||
22 | *tls_min = val[i]; | ||
23 | *supports_tls = 1; | ||
24 | return; | ||
25 | } else { | ||
26 | if (errno == EINVAL) | ||
27 | continue; | ||
28 | else if (errno == ENOSYS) | ||
29 | *supports_tls = 0; | ||
30 | return; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | *supports_tls = 0; | ||
35 | } | ||