diff options
Diffstat (limited to 'arch/um/sys-i386')
-rw-r--r-- | arch/um/sys-i386/Makefile | 5 | ||||
-rw-r--r-- | arch/um/sys-i386/asm/elf.h | 2 | ||||
-rw-r--r-- | arch/um/sys-i386/asm/ptrace.h | 5 | ||||
-rw-r--r-- | arch/um/sys-i386/delay.c | 59 | ||||
-rw-r--r-- | arch/um/sys-i386/mem.c | 62 | ||||
-rw-r--r-- | arch/um/sys-i386/ptrace.c | 28 | ||||
-rw-r--r-- | arch/um/sys-i386/shared/sysdep/ptrace.h | 1 | ||||
-rw-r--r-- | arch/um/sys-i386/signal.c | 2 |
8 files changed, 137 insertions, 27 deletions
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index b1da91c1b20..3923cfb8764 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile | |||
@@ -4,11 +4,12 @@ | |||
4 | 4 | ||
5 | obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | 5 | obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ |
6 | ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ | 6 | ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ |
7 | sys_call_table.o tls.o atomic64_cx8_32.o | 7 | sys_call_table.o tls.o atomic64_cx8_32.o mem.o |
8 | 8 | ||
9 | obj-$(CONFIG_BINFMT_ELF) += elfcore.o | 9 | obj-$(CONFIG_BINFMT_ELF) += elfcore.o |
10 | 10 | ||
11 | subarch-obj-y = lib/semaphore_32.o lib/string_32.o | 11 | subarch-obj-y = lib/string_32.o |
12 | subarch-obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += lib/rwsem.o | ||
12 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o | 13 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o |
13 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o | 14 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
14 | 15 | ||
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h index d964a4111ac..42305551d20 100644 --- a/arch/um/sys-i386/asm/elf.h +++ b/arch/um/sys-i386/asm/elf.h | |||
@@ -105,6 +105,8 @@ extern unsigned long __kernel_vsyscall; | |||
105 | #define FIXADDR_USER_START VSYSCALL_BASE | 105 | #define FIXADDR_USER_START VSYSCALL_BASE |
106 | #define FIXADDR_USER_END VSYSCALL_END | 106 | #define FIXADDR_USER_END VSYSCALL_END |
107 | 107 | ||
108 | #define __HAVE_ARCH_GATE_AREA 1 | ||
109 | |||
108 | /* | 110 | /* |
109 | * Architecture-neutral AT_ values in 0-17, leave some room | 111 | * Architecture-neutral AT_ values in 0-17, leave some room |
110 | * for more of them, start the x86-specific ones at 32. | 112 | * for more of them, start the x86-specific ones at 32. |
diff --git a/arch/um/sys-i386/asm/ptrace.h b/arch/um/sys-i386/asm/ptrace.h index 0273e4d09af..5d2a5911253 100644 --- a/arch/um/sys-i386/asm/ptrace.h +++ b/arch/um/sys-i386/asm/ptrace.h | |||
@@ -42,11 +42,6 @@ | |||
42 | */ | 42 | */ |
43 | struct user_desc; | 43 | struct user_desc; |
44 | 44 | ||
45 | extern int get_fpxregs(struct user_fxsr_struct __user *buf, | ||
46 | struct task_struct *child); | ||
47 | extern int set_fpxregs(struct user_fxsr_struct __user *buf, | ||
48 | struct task_struct *tsk); | ||
49 | |||
50 | extern int ptrace_get_thread_area(struct task_struct *child, int idx, | 45 | extern int ptrace_get_thread_area(struct task_struct *child, int idx, |
51 | struct user_desc __user *user_desc); | 46 | struct user_desc __user *user_desc); |
52 | 47 | ||
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c index d623e074f41..f3fe1a688f7 100644 --- a/arch/um/sys-i386/delay.c +++ b/arch/um/sys-i386/delay.c | |||
@@ -1,29 +1,60 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> | ||
3 | * Mostly copied from arch/x86/lib/delay.c | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
1 | #include <linux/module.h> | 10 | #include <linux/module.h> |
2 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
3 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
4 | #include <asm/param.h> | 13 | #include <asm/param.h> |
5 | 14 | ||
6 | void __delay(unsigned long time) | 15 | void __delay(unsigned long loops) |
7 | { | 16 | { |
8 | /* Stolen from the i386 __loop_delay */ | 17 | asm volatile( |
9 | int d0; | 18 | "test %0,%0\n" |
10 | __asm__ __volatile__( | 19 | "jz 3f\n" |
11 | "\tjmp 1f\n" | 20 | "jmp 1f\n" |
21 | |||
12 | ".align 16\n" | 22 | ".align 16\n" |
13 | "1:\tjmp 2f\n" | 23 | "1: jmp 2f\n" |
24 | |||
14 | ".align 16\n" | 25 | ".align 16\n" |
15 | "2:\tdecl %0\n\tjns 2b" | 26 | "2: dec %0\n" |
16 | :"=&a" (d0) | 27 | " jnz 2b\n" |
17 | :"0" (time)); | 28 | "3: dec %0\n" |
29 | |||
30 | : /* we don't need output */ | ||
31 | : "a" (loops) | ||
32 | ); | ||
18 | } | 33 | } |
34 | EXPORT_SYMBOL(__delay); | ||
19 | 35 | ||
20 | void __udelay(unsigned long usecs) | 36 | inline void __const_udelay(unsigned long xloops) |
21 | { | 37 | { |
22 | int i, n; | 38 | int d0; |
23 | 39 | ||
24 | n = (loops_per_jiffy * HZ * usecs) / MILLION; | 40 | xloops *= 4; |
25 | for(i=0;i<n;i++) | 41 | asm("mull %%edx" |
26 | cpu_relax(); | 42 | : "=d" (xloops), "=&a" (d0) |
43 | : "1" (xloops), "0" | ||
44 | (loops_per_jiffy * (HZ/4))); | ||
45 | |||
46 | __delay(++xloops); | ||
27 | } | 47 | } |
48 | EXPORT_SYMBOL(__const_udelay); | ||
28 | 49 | ||
50 | void __udelay(unsigned long usecs) | ||
51 | { | ||
52 | __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ | ||
53 | } | ||
29 | EXPORT_SYMBOL(__udelay); | 54 | EXPORT_SYMBOL(__udelay); |
55 | |||
56 | void __ndelay(unsigned long nsecs) | ||
57 | { | ||
58 | __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ | ||
59 | } | ||
60 | EXPORT_SYMBOL(__ndelay); | ||
diff --git a/arch/um/sys-i386/mem.c b/arch/um/sys-i386/mem.c new file mode 100644 index 00000000000..639900a6fde --- /dev/null +++ b/arch/um/sys-i386/mem.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/mm.h> | ||
10 | #include <asm/page.h> | ||
11 | #include <asm/mman.h> | ||
12 | |||
13 | static struct vm_area_struct gate_vma; | ||
14 | |||
15 | static int __init gate_vma_init(void) | ||
16 | { | ||
17 | if (!FIXADDR_USER_START) | ||
18 | return 0; | ||
19 | |||
20 | gate_vma.vm_mm = NULL; | ||
21 | gate_vma.vm_start = FIXADDR_USER_START; | ||
22 | gate_vma.vm_end = FIXADDR_USER_END; | ||
23 | gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; | ||
24 | gate_vma.vm_page_prot = __P101; | ||
25 | |||
26 | /* | ||
27 | * Make sure the vDSO gets into every core dump. | ||
28 | * Dumping its contents makes post-mortem fully interpretable later | ||
29 | * without matching up the same kernel and hardware config to see | ||
30 | * what PC values meant. | ||
31 | */ | ||
32 | gate_vma.vm_flags |= VM_ALWAYSDUMP; | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | __initcall(gate_vma_init); | ||
37 | |||
38 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
39 | { | ||
40 | return FIXADDR_USER_START ? &gate_vma : NULL; | ||
41 | } | ||
42 | |||
43 | int in_gate_area_no_mm(unsigned long addr) | ||
44 | { | ||
45 | if (!FIXADDR_USER_START) | ||
46 | return 0; | ||
47 | |||
48 | if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) | ||
49 | return 1; | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
55 | { | ||
56 | struct vm_area_struct *vma = get_gate_vma(mm); | ||
57 | |||
58 | if (!vma) | ||
59 | return 0; | ||
60 | |||
61 | return (addr >= vma->vm_start) && (addr < vma->vm_end); | ||
62 | } | ||
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index d23b2d3ea38..3375c271785 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c | |||
@@ -145,7 +145,7 @@ int peek_user(struct task_struct *child, long addr, long data) | |||
145 | return put_user(tmp, (unsigned long __user *) data); | 145 | return put_user(tmp, (unsigned long __user *) data); |
146 | } | 146 | } |
147 | 147 | ||
148 | int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) | 148 | static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) |
149 | { | 149 | { |
150 | int err, n, cpu = ((struct thread_info *) child->stack)->cpu; | 150 | int err, n, cpu = ((struct thread_info *) child->stack)->cpu; |
151 | struct user_i387_struct fpregs; | 151 | struct user_i387_struct fpregs; |
@@ -161,7 +161,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) | |||
161 | return n; | 161 | return n; |
162 | } | 162 | } |
163 | 163 | ||
164 | int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) | 164 | static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) |
165 | { | 165 | { |
166 | int n, cpu = ((struct thread_info *) child->stack)->cpu; | 166 | int n, cpu = ((struct thread_info *) child->stack)->cpu; |
167 | struct user_i387_struct fpregs; | 167 | struct user_i387_struct fpregs; |
@@ -174,7 +174,7 @@ int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) | |||
174 | (unsigned long *) &fpregs); | 174 | (unsigned long *) &fpregs); |
175 | } | 175 | } |
176 | 176 | ||
177 | int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) | 177 | static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) |
178 | { | 178 | { |
179 | int err, n, cpu = ((struct thread_info *) child->stack)->cpu; | 179 | int err, n, cpu = ((struct thread_info *) child->stack)->cpu; |
180 | struct user_fxsr_struct fpregs; | 180 | struct user_fxsr_struct fpregs; |
@@ -190,7 +190,7 @@ int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) | |||
190 | return n; | 190 | return n; |
191 | } | 191 | } |
192 | 192 | ||
193 | int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) | 193 | static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) |
194 | { | 194 | { |
195 | int n, cpu = ((struct thread_info *) child->stack)->cpu; | 195 | int n, cpu = ((struct thread_info *) child->stack)->cpu; |
196 | struct user_fxsr_struct fpregs; | 196 | struct user_fxsr_struct fpregs; |
@@ -206,5 +206,23 @@ int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) | |||
206 | long subarch_ptrace(struct task_struct *child, long request, | 206 | long subarch_ptrace(struct task_struct *child, long request, |
207 | unsigned long addr, unsigned long data) | 207 | unsigned long addr, unsigned long data) |
208 | { | 208 | { |
209 | return -EIO; | 209 | int ret = -EIO; |
210 | void __user *datap = (void __user *) data; | ||
211 | switch (request) { | ||
212 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ | ||
213 | ret = get_fpregs(datap, child); | ||
214 | break; | ||
215 | case PTRACE_SETFPREGS: /* Set the child FPU state. */ | ||
216 | ret = set_fpregs(datap, child); | ||
217 | break; | ||
218 | case PTRACE_GETFPXREGS: /* Get the child FPU state. */ | ||
219 | ret = get_fpxregs(datap, child); | ||
220 | break; | ||
221 | case PTRACE_SETFPXREGS: /* Set the child FPU state. */ | ||
222 | ret = set_fpxregs(datap, child); | ||
223 | break; | ||
224 | default: | ||
225 | ret = -EIO; | ||
226 | } | ||
227 | return ret; | ||
210 | } | 228 | } |
diff --git a/arch/um/sys-i386/shared/sysdep/ptrace.h b/arch/um/sys-i386/shared/sysdep/ptrace.h index d50e62e0707..c398a507611 100644 --- a/arch/um/sys-i386/shared/sysdep/ptrace.h +++ b/arch/um/sys-i386/shared/sysdep/ptrace.h | |||
@@ -53,6 +53,7 @@ extern int sysemu_supported; | |||
53 | 53 | ||
54 | struct uml_pt_regs { | 54 | struct uml_pt_regs { |
55 | unsigned long gp[MAX_REG_NR]; | 55 | unsigned long gp[MAX_REG_NR]; |
56 | unsigned long fp[HOST_FPX_SIZE]; | ||
56 | struct faultinfo faultinfo; | 57 | struct faultinfo faultinfo; |
57 | long syscall; | 58 | long syscall; |
58 | int is_user; | 59 | int is_user; |
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 129647375a6..89a46626bfd 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c | |||
@@ -58,7 +58,7 @@ static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) | |||
58 | unsigned long ret = 0xffff0000; | 58 | unsigned long ret = 0xffff0000; |
59 | int i; | 59 | int i; |
60 | 60 | ||
61 | #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); | 61 | #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16) |
62 | 62 | ||
63 | for (i = 0; i < 8; i++) { | 63 | for (i = 0; i < 8; i++) { |
64 | if (twd & 0x1) { | 64 | if (twd & 0x1) { |