diff options
Diffstat (limited to 'arch/um/sys-x86_64')
-rw-r--r-- | arch/um/sys-x86_64/Makefile | 37 | ||||
-rw-r--r-- | arch/um/sys-x86_64/bugs.c | 122 | ||||
-rw-r--r-- | arch/um/sys-x86_64/delay.c | 26 | ||||
-rw-r--r-- | arch/um/sys-x86_64/fault.c | 23 | ||||
-rw-r--r-- | arch/um/sys-x86_64/mem.c | 25 | ||||
-rw-r--r-- | arch/um/sys-x86_64/ptrace.c | 138 | ||||
-rw-r--r-- | arch/um/sys-x86_64/ptrace_user.c | 51 | ||||
-rw-r--r-- | arch/um/sys-x86_64/sigcontext.c | 39 | ||||
-rw-r--r-- | arch/um/sys-x86_64/signal.c | 276 | ||||
-rw-r--r-- | arch/um/sys-x86_64/syscalls.c | 186 | ||||
-rw-r--r-- | arch/um/sys-x86_64/sysrq.c | 49 | ||||
-rw-r--r-- | arch/um/sys-x86_64/util/Makefile | 10 | ||||
-rw-r--r-- | arch/um/sys-x86_64/util/mk_sc.c | 58 | ||||
-rw-r--r-- | arch/um/sys-x86_64/util/mk_thread_kern.c | 21 | ||||
-rw-r--r-- | arch/um/sys-x86_64/util/mk_thread_user.c | 30 |
15 files changed, 1091 insertions, 0 deletions
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile new file mode 100644 index 000000000000..2129e3143559 --- /dev/null +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -0,0 +1,37 @@ | |||
1 | # | ||
2 | # Copyright 2003 PathScale, Inc. | ||
3 | # | ||
4 | # Licensed under the GPL | ||
5 | # | ||
6 | |||
7 | lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \ | ||
8 | ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \ | ||
9 | syscalls.o sysrq.o thunk.o | ||
10 | |||
11 | USER_OBJS := ptrace_user.o sigcontext.o | ||
12 | |||
13 | include arch/um/scripts/Makefile.rules | ||
14 | |||
15 | SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ | ||
16 | semaphore.c thunk.S | ||
17 | |||
18 | # this needs to be before the foreach, because clean-files does not accept | ||
19 | # complete paths like $(src)/$f. | ||
20 | clean-files := $(SYMLINKS) | ||
21 | |||
22 | targets += $(SYMLINKS) | ||
23 | |||
24 | SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$f) | ||
25 | |||
26 | bitops.c-dir = lib | ||
27 | csum-copy.S-dir = lib | ||
28 | csum-partial.c-dir = lib | ||
29 | csum-wrappers.c-dir = lib | ||
30 | memcpy.S-dir = lib | ||
31 | semaphore.c-dir = kernel | ||
32 | thunk.S-dir = lib | ||
33 | |||
34 | $(SYMLINKS): FORCE | ||
35 | $(call if_changed,make_link) | ||
36 | |||
37 | CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial | ||
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c new file mode 100644 index 000000000000..fdce7ea98ca7 --- /dev/null +++ b/arch/um/sys-x86_64/bugs.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/sched.h" | ||
8 | #include "linux/errno.h" | ||
9 | #include "asm/system.h" | ||
10 | #include "asm/pda.h" | ||
11 | #include "sysdep/ptrace.h" | ||
12 | #include "os.h" | ||
13 | |||
14 | void arch_init_thread(void) | ||
15 | { | ||
16 | } | ||
17 | |||
18 | void arch_check_bugs(void) | ||
19 | { | ||
20 | } | ||
21 | |||
22 | int arch_handle_signal(int sig, union uml_pt_regs *regs) | ||
23 | { | ||
24 | return(0); | ||
25 | } | ||
26 | |||
27 | #define MAXTOKEN 64 | ||
28 | |||
29 | /* Set during early boot */ | ||
30 | int host_has_cmov = 1; | ||
31 | int host_has_xmm = 0; | ||
32 | |||
33 | static char token(int fd, char *buf, int len, char stop) | ||
34 | { | ||
35 | int n; | ||
36 | char *ptr, *end, c; | ||
37 | |||
38 | ptr = buf; | ||
39 | end = &buf[len]; | ||
40 | do { | ||
41 | n = os_read_file(fd, ptr, sizeof(*ptr)); | ||
42 | c = *ptr++; | ||
43 | if(n != sizeof(*ptr)){ | ||
44 | if(n == 0) return(0); | ||
45 | printk("Reading /proc/cpuinfo failed, err = %d\n", -n); | ||
46 | if(n < 0) | ||
47 | return(n); | ||
48 | else | ||
49 | return(-EIO); | ||
50 | } | ||
51 | } while((c != '\n') && (c != stop) && (ptr < end)); | ||
52 | |||
53 | if(ptr == end){ | ||
54 | printk("Failed to find '%c' in /proc/cpuinfo\n", stop); | ||
55 | return(-1); | ||
56 | } | ||
57 | *(ptr - 1) = '\0'; | ||
58 | return(c); | ||
59 | } | ||
60 | |||
61 | static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) | ||
62 | { | ||
63 | int n; | ||
64 | char c; | ||
65 | |||
66 | scratch[len - 1] = '\0'; | ||
67 | while(1){ | ||
68 | c = token(fd, scratch, len - 1, ':'); | ||
69 | if(c <= 0) | ||
70 | return(0); | ||
71 | else if(c != ':'){ | ||
72 | printk("Failed to find ':' in /proc/cpuinfo\n"); | ||
73 | return(0); | ||
74 | } | ||
75 | |||
76 | if(!strncmp(scratch, key, strlen(key))) | ||
77 | return(1); | ||
78 | |||
79 | do { | ||
80 | n = os_read_file(fd, &c, sizeof(c)); | ||
81 | if(n != sizeof(c)){ | ||
82 | printk("Failed to find newline in " | ||
83 | "/proc/cpuinfo, err = %d\n", -n); | ||
84 | return(0); | ||
85 | } | ||
86 | } while(c != '\n'); | ||
87 | } | ||
88 | return(0); | ||
89 | } | ||
90 | |||
91 | int cpu_feature(char *what, char *buf, int len) | ||
92 | { | ||
93 | int fd, ret = 0; | ||
94 | |||
95 | fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); | ||
96 | if(fd < 0){ | ||
97 | printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); | ||
98 | return(0); | ||
99 | } | ||
100 | |||
101 | if(!find_cpuinfo_line(fd, what, buf, len)){ | ||
102 | printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); | ||
103 | goto out_close; | ||
104 | } | ||
105 | |||
106 | token(fd, buf, len, '\n'); | ||
107 | ret = 1; | ||
108 | |||
109 | out_close: | ||
110 | os_close_file(fd); | ||
111 | return(ret); | ||
112 | } | ||
113 | |||
114 | /* Overrides for Emacs so that we follow Linus's tabbing style. | ||
115 | * Emacs will notice this stuff at the end of the file and automatically | ||
116 | * adjust the settings for this buffer only. This must remain at the end | ||
117 | * of the file. | ||
118 | * --------------------------------------------------------------------------- | ||
119 | * Local variables: | ||
120 | * c-file-style: "linux" | ||
121 | * End: | ||
122 | */ | ||
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c new file mode 100644 index 000000000000..f3b5187942b4 --- /dev/null +++ b/arch/um/sys-x86_64/delay.c | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * Copied from arch/x86_64 | ||
4 | * | ||
5 | * Licensed under the GPL | ||
6 | */ | ||
7 | |||
8 | #include "asm/processor.h" | ||
9 | |||
10 | void __delay(unsigned long loops) | ||
11 | { | ||
12 | unsigned long i; | ||
13 | |||
14 | for(i = 0; i < loops; i++) ; | ||
15 | } | ||
16 | |||
17 | /* | ||
18 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
19 | * Emacs will notice this stuff at the end of the file and automatically | ||
20 | * adjust the settings for this buffer only. This must remain at the end | ||
21 | * of the file. | ||
22 | * --------------------------------------------------------------------------- | ||
23 | * Local variables: | ||
24 | * c-file-style: "linux" | ||
25 | * End: | ||
26 | */ | ||
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c new file mode 100644 index 000000000000..cee1513c5c31 --- /dev/null +++ b/arch/um/sys-x86_64/fault.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "user.h" | ||
8 | |||
9 | int arch_fixup(unsigned long address, void *sc_ptr) | ||
10 | { | ||
11 | /* XXX search_exception_tables() */ | ||
12 | return(0); | ||
13 | } | ||
14 | |||
15 | /* Overrides for Emacs so that we follow Linus's tabbing style. | ||
16 | * Emacs will notice this stuff at the end of the file and automatically | ||
17 | * adjust the settings for this buffer only. This must remain at the end | ||
18 | * of the file. | ||
19 | * --------------------------------------------------------------------------- | ||
20 | * Local variables: | ||
21 | * c-file-style: "linux" | ||
22 | * End: | ||
23 | */ | ||
diff --git a/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c new file mode 100644 index 000000000000..3f59a0a4f156 --- /dev/null +++ b/arch/um/sys-x86_64/mem.c | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/mm.h" | ||
8 | #include "asm/page.h" | ||
9 | #include "asm/mman.h" | ||
10 | |||
11 | unsigned long vm_stack_flags = __VM_STACK_FLAGS; | ||
12 | unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; | ||
13 | unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; | ||
14 | unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; | ||
15 | unsigned long vm_force_exec32 = PROT_EXEC; | ||
16 | |||
17 | /* Overrides for Emacs so that we follow Linus's tabbing style. | ||
18 | * Emacs will notice this stuff at the end of the file and automatically | ||
19 | * adjust the settings for this buffer only. This must remain at the end | ||
20 | * of the file. | ||
21 | * --------------------------------------------------------------------------- | ||
22 | * Local variables: | ||
23 | * c-file-style: "linux" | ||
24 | * End: | ||
25 | */ | ||
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c new file mode 100644 index 000000000000..8c146b2a1e00 --- /dev/null +++ b/arch/um/sys-x86_64/ptrace.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #define __FRAME_OFFSETS | ||
8 | #include "asm/ptrace.h" | ||
9 | #include "linux/sched.h" | ||
10 | #include "linux/errno.h" | ||
11 | #include "asm/elf.h" | ||
12 | |||
13 | /* XXX x86_64 */ | ||
14 | unsigned long not_ss; | ||
15 | unsigned long not_ds; | ||
16 | unsigned long not_es; | ||
17 | |||
18 | #define SC_SS(r) (not_ss) | ||
19 | #define SC_DS(r) (not_ds) | ||
20 | #define SC_ES(r) (not_es) | ||
21 | |||
22 | /* determines which flags the user has access to. */ | ||
23 | /* 1 = access 0 = no access */ | ||
24 | #define FLAG_MASK 0x44dd5UL | ||
25 | |||
26 | int putreg(struct task_struct *child, int regno, unsigned long value) | ||
27 | { | ||
28 | unsigned long tmp; | ||
29 | |||
30 | #ifdef TIF_IA32 | ||
31 | /* Some code in the 64bit emulation may not be 64bit clean. | ||
32 | Don't take any chances. */ | ||
33 | if (test_tsk_thread_flag(child, TIF_IA32)) | ||
34 | value &= 0xffffffff; | ||
35 | #endif | ||
36 | switch (regno){ | ||
37 | case FS: | ||
38 | case GS: | ||
39 | case DS: | ||
40 | case ES: | ||
41 | case SS: | ||
42 | case CS: | ||
43 | if (value && (value & 3) != 3) | ||
44 | return -EIO; | ||
45 | value &= 0xffff; | ||
46 | break; | ||
47 | |||
48 | case FS_BASE: | ||
49 | case GS_BASE: | ||
50 | if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) | ||
51 | return -EIO; | ||
52 | break; | ||
53 | |||
54 | case EFLAGS: | ||
55 | value &= FLAG_MASK; | ||
56 | tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK; | ||
57 | value |= tmp; | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | PT_REGS_SET(&child->thread.regs, regno, value); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | unsigned long getreg(struct task_struct *child, int regno) | ||
66 | { | ||
67 | unsigned long retval = ~0UL; | ||
68 | switch (regno) { | ||
69 | case FS: | ||
70 | case GS: | ||
71 | case DS: | ||
72 | case ES: | ||
73 | case SS: | ||
74 | case CS: | ||
75 | retval = 0xffff; | ||
76 | /* fall through */ | ||
77 | default: | ||
78 | retval &= PT_REG(&child->thread.regs, regno); | ||
79 | #ifdef TIF_IA32 | ||
80 | if (test_tsk_thread_flag(child, TIF_IA32)) | ||
81 | retval &= 0xffffffff; | ||
82 | #endif | ||
83 | } | ||
84 | return retval; | ||
85 | } | ||
86 | |||
87 | void arch_switch(void) | ||
88 | { | ||
89 | /* XXX | ||
90 | printk("arch_switch\n"); | ||
91 | */ | ||
92 | } | ||
93 | |||
94 | int is_syscall(unsigned long addr) | ||
95 | { | ||
96 | panic("is_syscall"); | ||
97 | } | ||
98 | |||
99 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) | ||
100 | { | ||
101 | panic("dump_fpu"); | ||
102 | return(1); | ||
103 | } | ||
104 | |||
105 | int get_fpregs(unsigned long buf, struct task_struct *child) | ||
106 | { | ||
107 | panic("get_fpregs"); | ||
108 | return(0); | ||
109 | } | ||
110 | |||
111 | int set_fpregs(unsigned long buf, struct task_struct *child) | ||
112 | { | ||
113 | panic("set_fpregs"); | ||
114 | return(0); | ||
115 | } | ||
116 | |||
117 | int get_fpxregs(unsigned long buf, struct task_struct *tsk) | ||
118 | { | ||
119 | panic("get_fpxregs"); | ||
120 | return(0); | ||
121 | } | ||
122 | |||
123 | int set_fpxregs(unsigned long buf, struct task_struct *tsk) | ||
124 | { | ||
125 | panic("set_fxpregs"); | ||
126 | return(0); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
131 | * Emacs will notice this stuff at the end of the file and automatically | ||
132 | * adjust the settings for this buffer only. This must remain at the end | ||
133 | * of the file. | ||
134 | * --------------------------------------------------------------------------- | ||
135 | * Local variables: | ||
136 | * c-file-style: "linux" | ||
137 | * End: | ||
138 | */ | ||
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c new file mode 100644 index 000000000000..12e404c6fa46 --- /dev/null +++ b/arch/um/sys-x86_64/ptrace_user.c | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <stddef.h> | ||
8 | #include <errno.h> | ||
9 | #include "ptrace_user.h" | ||
10 | #include "user.h" | ||
11 | #include "kern_constants.h" | ||
12 | |||
13 | int ptrace_getregs(long pid, unsigned long *regs_out) | ||
14 | { | ||
15 | if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) | ||
16 | return(-errno); | ||
17 | return(0); | ||
18 | } | ||
19 | |||
20 | int ptrace_setregs(long pid, unsigned long *regs) | ||
21 | { | ||
22 | if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0) | ||
23 | return(-errno); | ||
24 | return(0); | ||
25 | } | ||
26 | |||
27 | void ptrace_pokeuser(unsigned long addr, unsigned long data) | ||
28 | { | ||
29 | panic("ptrace_pokeuser"); | ||
30 | } | ||
31 | |||
32 | #define DS 184 | ||
33 | #define ES 192 | ||
34 | #define __USER_DS 0x2b | ||
35 | |||
36 | void arch_enter_kernel(void *task, int pid) | ||
37 | { | ||
38 | } | ||
39 | |||
40 | void arch_leave_kernel(void *task, int pid) | ||
41 | { | ||
42 | #ifdef UM_USER_CS | ||
43 | if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0) | ||
44 | printk("POKEUSR CS failed"); | ||
45 | #endif | ||
46 | |||
47 | if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0) | ||
48 | printk("POKEUSR DS failed"); | ||
49 | if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0) | ||
50 | printk("POKEUSR ES failed"); | ||
51 | } | ||
diff --git a/arch/um/sys-x86_64/sigcontext.c b/arch/um/sys-x86_64/sigcontext.c new file mode 100644 index 000000000000..c88e64def6f2 --- /dev/null +++ b/arch/um/sys-x86_64/sigcontext.c | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <stdio.h> | ||
8 | #include <string.h> | ||
9 | #include <signal.h> | ||
10 | #include "user.h" | ||
11 | |||
12 | void sc_to_sc(void *to_ptr, void *from_ptr) | ||
13 | { | ||
14 | struct sigcontext *to = to_ptr, *from = from_ptr; | ||
15 | int size = sizeof(*to); /* + sizeof(struct _fpstate); */ | ||
16 | |||
17 | memcpy(to, from, size); | ||
18 | if(from->fpstate != NULL) | ||
19 | to->fpstate = (struct _fpstate *) (to + 1); | ||
20 | |||
21 | to->fpstate = NULL; | ||
22 | } | ||
23 | |||
24 | unsigned long *sc_sigmask(void *sc_ptr) | ||
25 | { | ||
26 | struct sigcontext *sc = sc_ptr; | ||
27 | |||
28 | return(&sc->oldmask); | ||
29 | } | ||
30 | |||
31 | /* Overrides for Emacs so that we follow Linus's tabbing style. | ||
32 | * Emacs will notice this stuff at the end of the file and automatically | ||
33 | * adjust the settings for this buffer only. This must remain at the end | ||
34 | * of the file. | ||
35 | * --------------------------------------------------------------------------- | ||
36 | * Local variables: | ||
37 | * c-file-style: "linux" | ||
38 | * End: | ||
39 | */ | ||
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c new file mode 100644 index 000000000000..5bc5a0d796e5 --- /dev/null +++ b/arch/um/sys-x86_64/signal.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003 PathScale, Inc. | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/stddef.h" | ||
7 | #include "linux/errno.h" | ||
8 | #include "linux/personality.h" | ||
9 | #include "linux/ptrace.h" | ||
10 | #include "asm/current.h" | ||
11 | #include "asm/uaccess.h" | ||
12 | #include "asm/sigcontext.h" | ||
13 | #include "asm/ptrace.h" | ||
14 | #include "asm/arch/ucontext.h" | ||
15 | #include "choose-mode.h" | ||
16 | #include "sysdep/ptrace.h" | ||
17 | #include "frame_kern.h" | ||
18 | |||
19 | #ifdef CONFIG_MODE_SKAS | ||
20 | |||
21 | #include "skas.h" | ||
22 | |||
23 | static int copy_sc_from_user_skas(struct pt_regs *regs, | ||
24 | struct sigcontext *from) | ||
25 | { | ||
26 | int err = 0; | ||
27 | |||
28 | #define GETREG(regs, regno, sc, regname) \ | ||
29 | __get_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ | ||
30 | &(sc)->regname) | ||
31 | |||
32 | err |= GETREG(regs, R8, from, r8); | ||
33 | err |= GETREG(regs, R9, from, r9); | ||
34 | err |= GETREG(regs, R10, from, r10); | ||
35 | err |= GETREG(regs, R11, from, r11); | ||
36 | err |= GETREG(regs, R12, from, r12); | ||
37 | err |= GETREG(regs, R13, from, r13); | ||
38 | err |= GETREG(regs, R14, from, r14); | ||
39 | err |= GETREG(regs, R15, from, r15); | ||
40 | err |= GETREG(regs, RDI, from, rdi); | ||
41 | err |= GETREG(regs, RSI, from, rsi); | ||
42 | err |= GETREG(regs, RBP, from, rbp); | ||
43 | err |= GETREG(regs, RBX, from, rbx); | ||
44 | err |= GETREG(regs, RDX, from, rdx); | ||
45 | err |= GETREG(regs, RAX, from, rax); | ||
46 | err |= GETREG(regs, RCX, from, rcx); | ||
47 | err |= GETREG(regs, RSP, from, rsp); | ||
48 | err |= GETREG(regs, RIP, from, rip); | ||
49 | err |= GETREG(regs, EFLAGS, from, eflags); | ||
50 | err |= GETREG(regs, CS, from, cs); | ||
51 | |||
52 | #undef GETREG | ||
53 | |||
54 | return(err); | ||
55 | } | ||
56 | |||
57 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | ||
58 | struct pt_regs *regs, unsigned long mask) | ||
59 | { | ||
60 | unsigned long eflags; | ||
61 | int err = 0; | ||
62 | |||
63 | err |= __put_user(0, &to->gs); | ||
64 | err |= __put_user(0, &to->fs); | ||
65 | |||
66 | #define PUTREG(regs, regno, sc, regname) \ | ||
67 | __put_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ | ||
68 | &(sc)->regname) | ||
69 | |||
70 | err |= PUTREG(regs, RDI, to, rdi); | ||
71 | err |= PUTREG(regs, RSI, to, rsi); | ||
72 | err |= PUTREG(regs, RBP, to, rbp); | ||
73 | err |= PUTREG(regs, RSP, to, rsp); | ||
74 | err |= PUTREG(regs, RBX, to, rbx); | ||
75 | err |= PUTREG(regs, RDX, to, rdx); | ||
76 | err |= PUTREG(regs, RCX, to, rcx); | ||
77 | err |= PUTREG(regs, RAX, to, rax); | ||
78 | err |= PUTREG(regs, R8, to, r8); | ||
79 | err |= PUTREG(regs, R9, to, r9); | ||
80 | err |= PUTREG(regs, R10, to, r10); | ||
81 | err |= PUTREG(regs, R11, to, r11); | ||
82 | err |= PUTREG(regs, R12, to, r12); | ||
83 | err |= PUTREG(regs, R13, to, r13); | ||
84 | err |= PUTREG(regs, R14, to, r14); | ||
85 | err |= PUTREG(regs, R15, to, r15); | ||
86 | err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ | ||
87 | err |= __put_user(current->thread.err, &to->err); | ||
88 | err |= __put_user(current->thread.trap_no, &to->trapno); | ||
89 | err |= PUTREG(regs, RIP, to, rip); | ||
90 | err |= PUTREG(regs, EFLAGS, to, eflags); | ||
91 | #undef PUTREG | ||
92 | |||
93 | err |= __put_user(mask, &to->oldmask); | ||
94 | err |= __put_user(current->thread.cr2, &to->cr2); | ||
95 | |||
96 | return(err); | ||
97 | } | ||
98 | |||
99 | #endif | ||
100 | |||
101 | #ifdef CONFIG_MODE_TT | ||
102 | int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, | ||
103 | int fpsize) | ||
104 | { | ||
105 | struct _fpstate *to_fp, *from_fp; | ||
106 | unsigned long sigs; | ||
107 | int err; | ||
108 | |||
109 | to_fp = to->fpstate; | ||
110 | from_fp = from->fpstate; | ||
111 | sigs = to->oldmask; | ||
112 | err = copy_from_user(to, from, sizeof(*to)); | ||
113 | to->oldmask = sigs; | ||
114 | return(err); | ||
115 | } | ||
116 | |||
117 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | ||
118 | struct sigcontext *from, int fpsize) | ||
119 | { | ||
120 | struct _fpstate *to_fp, *from_fp; | ||
121 | int err; | ||
122 | |||
123 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); | ||
124 | from_fp = from->fpstate; | ||
125 | err = copy_to_user(to, from, sizeof(*to)); | ||
126 | return(err); | ||
127 | } | ||
128 | |||
129 | #endif | ||
130 | |||
131 | static int copy_sc_from_user(struct pt_regs *to, void __user *from) | ||
132 | { | ||
133 | int ret; | ||
134 | |||
135 | ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, | ||
136 | sizeof(struct _fpstate)), | ||
137 | copy_sc_from_user_skas(to, from)); | ||
138 | return(ret); | ||
139 | } | ||
140 | |||
141 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, | ||
142 | struct pt_regs *from, unsigned long mask) | ||
143 | { | ||
144 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | ||
145 | sizeof(*fp)), | ||
146 | copy_sc_to_user_skas(to, fp, from, mask))); | ||
147 | } | ||
148 | |||
149 | struct rt_sigframe | ||
150 | { | ||
151 | char *pretcode; | ||
152 | struct ucontext uc; | ||
153 | struct siginfo info; | ||
154 | }; | ||
155 | |||
156 | #define round_down(m, n) (((m) / (n)) * (n)) | ||
157 | |||
158 | int setup_signal_stack_si(unsigned long stack_top, int sig, | ||
159 | struct k_sigaction *ka, struct pt_regs * regs, | ||
160 | siginfo_t *info, sigset_t *set) | ||
161 | { | ||
162 | struct rt_sigframe __user *frame; | ||
163 | struct _fpstate __user *fp = NULL; | ||
164 | int err = 0; | ||
165 | struct task_struct *me = current; | ||
166 | |||
167 | frame = (struct rt_sigframe __user *) | ||
168 | round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8; | ||
169 | frame -= 128; | ||
170 | |||
171 | if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) | ||
172 | goto out; | ||
173 | |||
174 | #if 0 /* XXX */ | ||
175 | if (save_i387(fp) < 0) | ||
176 | err |= -1; | ||
177 | #endif | ||
178 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
179 | goto out; | ||
180 | |||
181 | if (ka->sa.sa_flags & SA_SIGINFO) { | ||
182 | err |= copy_siginfo_to_user(&frame->info, info); | ||
183 | if (err) | ||
184 | goto out; | ||
185 | } | ||
186 | |||
187 | /* Create the ucontext. */ | ||
188 | err |= __put_user(0, &frame->uc.uc_flags); | ||
189 | err |= __put_user(0, &frame->uc.uc_link); | ||
190 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
191 | err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)), | ||
192 | &frame->uc.uc_stack.ss_flags); | ||
193 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
194 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); | ||
195 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); | ||
196 | if (sizeof(*set) == 16) { | ||
197 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | ||
198 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); | ||
199 | } | ||
200 | else | ||
201 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, | ||
202 | sizeof(*set)); | ||
203 | |||
204 | /* Set up to return from userspace. If provided, use a stub | ||
205 | already in userspace. */ | ||
206 | /* x86-64 should always use SA_RESTORER. */ | ||
207 | if (ka->sa.sa_flags & SA_RESTORER) | ||
208 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | ||
209 | else | ||
210 | /* could use a vstub here */ | ||
211 | goto out; | ||
212 | |||
213 | if (err) | ||
214 | goto out; | ||
215 | |||
216 | /* Set up registers for signal handler */ | ||
217 | { | ||
218 | struct exec_domain *ed = current_thread_info()->exec_domain; | ||
219 | if (unlikely(ed && ed->signal_invmap && sig < 32)) | ||
220 | sig = ed->signal_invmap[sig]; | ||
221 | } | ||
222 | |||
223 | PT_REGS_RDI(regs) = sig; | ||
224 | /* In case the signal handler was declared without prototypes */ | ||
225 | PT_REGS_RAX(regs) = 0; | ||
226 | |||
227 | /* This also works for non SA_SIGINFO handlers because they expect the | ||
228 | next argument after the signal number on the stack. */ | ||
229 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; | ||
230 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; | ||
231 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; | ||
232 | |||
233 | PT_REGS_RSP(regs) = (unsigned long) frame; | ||
234 | out: | ||
235 | return(err); | ||
236 | } | ||
237 | |||
238 | long sys_rt_sigreturn(struct pt_regs *regs) | ||
239 | { | ||
240 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); | ||
241 | struct rt_sigframe __user *frame = | ||
242 | (struct rt_sigframe __user *)(sp - 8); | ||
243 | struct ucontext __user *uc = &frame->uc; | ||
244 | sigset_t set; | ||
245 | |||
246 | if(copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) | ||
247 | goto segfault; | ||
248 | |||
249 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
250 | |||
251 | spin_lock_irq(¤t->sighand->siglock); | ||
252 | current->blocked = set; | ||
253 | recalc_sigpending(); | ||
254 | spin_unlock_irq(¤t->sighand->siglock); | ||
255 | |||
256 | if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) | ||
257 | goto segfault; | ||
258 | |||
259 | /* Avoid ERESTART handling */ | ||
260 | PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; | ||
261 | return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); | ||
262 | |||
263 | segfault: | ||
264 | force_sig(SIGSEGV, current); | ||
265 | return 0; | ||
266 | } | ||
267 | /* | ||
268 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
269 | * Emacs will notice this stuff at the end of the file and automatically | ||
270 | * adjust the settings for this buffer only. This must remain at the end | ||
271 | * of the file. | ||
272 | * --------------------------------------------------------------------------- | ||
273 | * Local variables: | ||
274 | * c-file-style: "linux" | ||
275 | * End: | ||
276 | */ | ||
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c new file mode 100644 index 000000000000..68205a03364c --- /dev/null +++ b/arch/um/sys-x86_64/syscalls.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/linkage.h" | ||
8 | #include "linux/slab.h" | ||
9 | #include "linux/shm.h" | ||
10 | #include "asm/uaccess.h" | ||
11 | #define __FRAME_OFFSETS | ||
12 | #include "asm/ptrace.h" | ||
13 | #include "asm/unistd.h" | ||
14 | #include "asm/prctl.h" /* XXX This should get the constants from libc */ | ||
15 | #include "choose-mode.h" | ||
16 | |||
17 | asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg) | ||
18 | { | ||
19 | unsigned long raddr; | ||
20 | |||
21 | return do_shmat(shmid, shmaddr, shmflg, &raddr) ?: (long) raddr; | ||
22 | } | ||
23 | |||
24 | #ifdef CONFIG_MODE_TT | ||
25 | extern int modify_ldt(int func, void *ptr, unsigned long bytecount); | ||
26 | |||
27 | long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) | ||
28 | { | ||
29 | /* XXX This should check VERIFY_WRITE depending on func, check this | ||
30 | * in i386 as well. | ||
31 | */ | ||
32 | if (!access_ok(VERIFY_READ, ptr, bytecount)) | ||
33 | return -EFAULT; | ||
34 | return(modify_ldt(func, ptr, bytecount)); | ||
35 | } | ||
36 | #endif | ||
37 | |||
38 | #ifdef CONFIG_MODE_SKAS | ||
39 | extern int userspace_pid[]; | ||
40 | |||
41 | long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) | ||
42 | { | ||
43 | struct ptrace_ldt ldt; | ||
44 | void *buf; | ||
45 | int res, n; | ||
46 | |||
47 | buf = kmalloc(bytecount, GFP_KERNEL); | ||
48 | if(buf == NULL) | ||
49 | return(-ENOMEM); | ||
50 | |||
51 | res = 0; | ||
52 | |||
53 | switch(func){ | ||
54 | case 1: | ||
55 | case 0x11: | ||
56 | res = copy_from_user(buf, ptr, bytecount); | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | if(res != 0){ | ||
61 | res = -EFAULT; | ||
62 | goto out; | ||
63 | } | ||
64 | |||
65 | ldt = ((struct ptrace_ldt) { .func = func, | ||
66 | .ptr = buf, | ||
67 | .bytecount = bytecount }); | ||
68 | #warning Need to look up userspace_pid by cpu | ||
69 | res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt); | ||
70 | if(res < 0) | ||
71 | goto out; | ||
72 | |||
73 | switch(func){ | ||
74 | case 0: | ||
75 | case 2: | ||
76 | n = res; | ||
77 | res = copy_to_user(ptr, buf, n); | ||
78 | if(res != 0) | ||
79 | res = -EFAULT; | ||
80 | else | ||
81 | res = n; | ||
82 | break; | ||
83 | } | ||
84 | |||
85 | out: | ||
86 | kfree(buf); | ||
87 | return(res); | ||
88 | } | ||
89 | #endif | ||
90 | |||
91 | long sys_modify_ldt(int func, void *ptr, unsigned long bytecount) | ||
92 | { | ||
93 | return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, | ||
94 | ptr, bytecount)); | ||
95 | } | ||
96 | |||
97 | #ifdef CONFIG_MODE_TT | ||
98 | extern long arch_prctl(int code, unsigned long addr); | ||
99 | |||
100 | static long arch_prctl_tt(int code, unsigned long addr) | ||
101 | { | ||
102 | unsigned long tmp; | ||
103 | long ret; | ||
104 | |||
105 | switch(code){ | ||
106 | case ARCH_SET_GS: | ||
107 | case ARCH_SET_FS: | ||
108 | ret = arch_prctl(code, addr); | ||
109 | break; | ||
110 | case ARCH_GET_FS: | ||
111 | case ARCH_GET_GS: | ||
112 | ret = arch_prctl(code, (unsigned long) &tmp); | ||
113 | if(!ret) | ||
114 | ret = put_user(tmp, &addr); | ||
115 | break; | ||
116 | default: | ||
117 | ret = -EINVAL; | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | return(ret); | ||
122 | } | ||
123 | #endif | ||
124 | |||
125 | #ifdef CONFIG_MODE_SKAS | ||
126 | |||
127 | static long arch_prctl_skas(int code, unsigned long addr) | ||
128 | { | ||
129 | long ret = 0; | ||
130 | |||
131 | switch(code){ | ||
132 | case ARCH_SET_GS: | ||
133 | current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr; | ||
134 | break; | ||
135 | case ARCH_SET_FS: | ||
136 | current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr; | ||
137 | break; | ||
138 | case ARCH_GET_FS: | ||
139 | ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr); | ||
140 | break; | ||
141 | case ARCH_GET_GS: | ||
142 | ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \ | ||
143 | long)], &addr); | ||
144 | break; | ||
145 | default: | ||
146 | ret = -EINVAL; | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | return(ret); | ||
151 | } | ||
152 | #endif | ||
153 | |||
154 | long sys_arch_prctl(int code, unsigned long addr) | ||
155 | { | ||
156 | return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr)); | ||
157 | } | ||
158 | |||
159 | long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
160 | void __user *parent_tid, void __user *child_tid) | ||
161 | { | ||
162 | long ret; | ||
163 | |||
164 | /* XXX: normal arch do here this pass, and also pass the regs to | ||
165 | * do_fork, instead of NULL. Currently the arch-independent code | ||
166 | * ignores these values, while the UML code (actually it's | ||
167 | * copy_thread) does the right thing. But this should change, | ||
168 | probably. */ | ||
169 | /*if (!newsp) | ||
170 | newsp = UPT_SP(current->thread.regs);*/ | ||
171 | current->thread.forking = 1; | ||
172 | ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid); | ||
173 | current->thread.forking = 0; | ||
174 | return(ret); | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
179 | * Emacs will notice this stuff at the end of the file and automatically | ||
180 | * adjust the settings for this buffer only. This must remain at the end | ||
181 | * of the file. | ||
182 | * --------------------------------------------------------------------------- | ||
183 | * Local variables: | ||
184 | * c-file-style: "linux" | ||
185 | * End: | ||
186 | */ | ||
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c new file mode 100644 index 000000000000..ddf74691a610 --- /dev/null +++ b/arch/um/sys-x86_64/sysrq.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/kernel.h" | ||
8 | #include "linux/utsname.h" | ||
9 | #include "linux/module.h" | ||
10 | #include "asm/current.h" | ||
11 | #include "asm/ptrace.h" | ||
12 | #include "sysrq.h" | ||
13 | |||
14 | void __show_regs(struct pt_regs * regs) | ||
15 | { | ||
16 | printk("\n"); | ||
17 | print_modules(); | ||
18 | printk("Pid: %d, comm: %.20s %s %s\n", | ||
19 | current->pid, current->comm, print_tainted(), system_utsname.release); | ||
20 | printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff, | ||
21 | PT_REGS_RIP(regs)); | ||
22 | printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs), | ||
23 | PT_REGS_EFLAGS(regs)); | ||
24 | printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", | ||
25 | PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs)); | ||
26 | printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", | ||
27 | PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs)); | ||
28 | printk("RBP: %016lx R08: %016lx R09: %016lx\n", | ||
29 | PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs)); | ||
30 | printk("R10: %016lx R11: %016lx R12: %016lx\n", | ||
31 | PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs)); | ||
32 | printk("R13: %016lx R14: %016lx R15: %016lx\n", | ||
33 | PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs)); | ||
34 | } | ||
35 | |||
36 | void show_regs(struct pt_regs *regs) | ||
37 | { | ||
38 | __show_regs(regs); | ||
39 | show_trace((unsigned long *) ®s); | ||
40 | } | ||
41 | |||
42 | /* Emacs will notice this stuff at the end of the file and automatically | ||
43 | * adjust the settings for this buffer only. This must remain at the end | ||
44 | * of the file. | ||
45 | * --------------------------------------------------------------------------- | ||
46 | * Local variables: | ||
47 | * c-file-style: "linux" | ||
48 | * End: | ||
49 | */ | ||
diff --git a/arch/um/sys-x86_64/util/Makefile b/arch/um/sys-x86_64/util/Makefile new file mode 100644 index 000000000000..002607980864 --- /dev/null +++ b/arch/um/sys-x86_64/util/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # Copyright 2003 - 2004 Pathscale, Inc | ||
2 | # Released under the GPL | ||
3 | |||
4 | hostprogs-y := mk_sc mk_thread | ||
5 | always := $(hostprogs-y) | ||
6 | |||
7 | mk_thread-objs := mk_thread_kern.o mk_thread_user.o | ||
8 | |||
9 | HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS) | ||
10 | HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS) | ||
diff --git a/arch/um/sys-x86_64/util/mk_sc.c b/arch/um/sys-x86_64/util/mk_sc.c new file mode 100644 index 000000000000..c236e213918d --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_sc.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* Copyright (C) 2003 - 2004 PathScale, Inc | ||
2 | * Released under the GPL | ||
3 | */ | ||
4 | |||
5 | #include <stdio.h> | ||
6 | #include <signal.h> | ||
7 | #include <linux/stddef.h> | ||
8 | |||
9 | #define SC_OFFSET(name, field) \ | ||
10 | printf("#define " name \ | ||
11 | "(sc) *((unsigned long *) &(((char *) (sc))[%ld]))\n",\ | ||
12 | offsetof(struct sigcontext, field)) | ||
13 | |||
14 | #define SC_FP_OFFSET(name, field) \ | ||
15 | printf("#define " name \ | ||
16 | "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%ld]))\n",\ | ||
17 | offsetof(struct _fpstate, field)) | ||
18 | |||
19 | #define SC_FP_OFFSET_PTR(name, field, type) \ | ||
20 | printf("#define " name \ | ||
21 | "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ | ||
22 | offsetof(struct _fpstate, field)) | ||
23 | |||
24 | int main(int argc, char **argv) | ||
25 | { | ||
26 | SC_OFFSET("SC_RBX", rbx); | ||
27 | SC_OFFSET("SC_RCX", rcx); | ||
28 | SC_OFFSET("SC_RDX", rdx); | ||
29 | SC_OFFSET("SC_RSI", rsi); | ||
30 | SC_OFFSET("SC_RDI", rdi); | ||
31 | SC_OFFSET("SC_RBP", rbp); | ||
32 | SC_OFFSET("SC_RAX", rax); | ||
33 | SC_OFFSET("SC_R8", r8); | ||
34 | SC_OFFSET("SC_R9", r9); | ||
35 | SC_OFFSET("SC_R10", r10); | ||
36 | SC_OFFSET("SC_R11", r11); | ||
37 | SC_OFFSET("SC_R12", r12); | ||
38 | SC_OFFSET("SC_R13", r13); | ||
39 | SC_OFFSET("SC_R14", r14); | ||
40 | SC_OFFSET("SC_R15", r15); | ||
41 | SC_OFFSET("SC_IP", rip); | ||
42 | SC_OFFSET("SC_SP", rsp); | ||
43 | SC_OFFSET("SC_CR2", cr2); | ||
44 | SC_OFFSET("SC_ERR", err); | ||
45 | SC_OFFSET("SC_TRAPNO", trapno); | ||
46 | SC_OFFSET("SC_CS", cs); | ||
47 | SC_OFFSET("SC_FS", fs); | ||
48 | SC_OFFSET("SC_GS", gs); | ||
49 | SC_OFFSET("SC_EFLAGS", eflags); | ||
50 | SC_OFFSET("SC_SIGMASK", oldmask); | ||
51 | #if 0 | ||
52 | SC_OFFSET("SC_ORIG_RAX", orig_rax); | ||
53 | SC_OFFSET("SC_DS", ds); | ||
54 | SC_OFFSET("SC_ES", es); | ||
55 | SC_OFFSET("SC_SS", ss); | ||
56 | #endif | ||
57 | return(0); | ||
58 | } | ||
diff --git a/arch/um/sys-x86_64/util/mk_thread_kern.c b/arch/um/sys-x86_64/util/mk_thread_kern.c new file mode 100644 index 000000000000..a281673f02b2 --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_thread_kern.c | |||
@@ -0,0 +1,21 @@ | |||
1 | #include "linux/config.h" | ||
2 | #include "linux/stddef.h" | ||
3 | #include "linux/sched.h" | ||
4 | |||
5 | extern void print_head(void); | ||
6 | extern void print_constant_ptr(char *name, int value); | ||
7 | extern void print_constant(char *name, char *type, int value); | ||
8 | extern void print_tail(void); | ||
9 | |||
10 | #define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field) | ||
11 | |||
12 | int main(int argc, char **argv) | ||
13 | { | ||
14 | print_head(); | ||
15 | #ifdef CONFIG_MODE_TT | ||
16 | print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid)); | ||
17 | #endif | ||
18 | print_tail(); | ||
19 | return(0); | ||
20 | } | ||
21 | |||
diff --git a/arch/um/sys-x86_64/util/mk_thread_user.c b/arch/um/sys-x86_64/util/mk_thread_user.c new file mode 100644 index 000000000000..7989725568b8 --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_thread_user.c | |||
@@ -0,0 +1,30 @@ | |||
1 | #include <stdio.h> | ||
2 | |||
3 | void print_head(void) | ||
4 | { | ||
5 | printf("/*\n"); | ||
6 | printf(" * Generated by mk_thread\n"); | ||
7 | printf(" */\n"); | ||
8 | printf("\n"); | ||
9 | printf("#ifndef __UM_THREAD_H\n"); | ||
10 | printf("#define __UM_THREAD_H\n"); | ||
11 | printf("\n"); | ||
12 | } | ||
13 | |||
14 | void print_constant_ptr(char *name, int value) | ||
15 | { | ||
16 | printf("#define %s(task) ((unsigned long *) " | ||
17 | "&(((char *) (task))[%d]))\n", name, value); | ||
18 | } | ||
19 | |||
20 | void print_constant(char *name, char *type, int value) | ||
21 | { | ||
22 | printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, | ||
23 | value); | ||
24 | } | ||
25 | |||
26 | void print_tail(void) | ||
27 | { | ||
28 | printf("\n"); | ||
29 | printf("#endif\n"); | ||
30 | } | ||