diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 15:02:37 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 15:02:37 -0500 |
commit | 61ecdb84c1f05ad445db4584ae375a15c0e8ae47 (patch) | |
tree | 2ecdc462785be5b96c6dcc14c517a8abb5ed16e8 /arch | |
parent | da184a8064efe2a78d8542877970f7c6bb62775a (diff) | |
parent | 23637568ad0c9b5ab0ad27d2f2f26d1e9282c527 (diff) |
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86: Fix kprobes build with non-gawk awk
x86: Split swiotlb initialization into two stages
x86: Regex support and known-movable symbols for relocs, fix _end
x86, msr: Remove incorrect, duplicated code in the MSR driver
x86: Merge kernel_thread()
x86: Sync 32/64-bit kernel_thread
x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper
x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread()
x86, 64-bit: Move kernel_thread to C
x86-64, paravirt: Call set_iopl_mask() on 64 bits
x86-32: Avoid pipeline serialization in PTREGSCALL1 and 2
x86: Merge sys_clone
x86, 32-bit: Convert sys_vm86 & sys_vm86old
x86: Merge sys_sigaltstack
x86: Merge sys_execve
x86: Merge sys_iopl
x86-32: Add new pt_regs stubs
cpumask: Use modern cpumask style in arch/x86/kernel/cpu/mcheck/mce-inject.c
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/boot/compressed/relocs.c | 87 | ||||
-rw-r--r-- | arch/x86/include/asm/swiotlb.h | 8 | ||||
-rw-r--r-- | arch/x86/include/asm/syscalls.h | 32 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-inject.c | 22 | ||||
-rw-r--r-- | arch/x86/kernel/entry_32.S | 69 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 49 | ||||
-rw-r--r-- | arch/x86/kernel/ioport.c | 28 | ||||
-rw-r--r-- | arch/x86/kernel/msr.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/pci-swiotlb.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/process.c | 70 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 73 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 35 | ||||
-rw-r--r-- | arch/x86/kernel/signal.c | 12 | ||||
-rw-r--r-- | arch/x86/kernel/vm86_32.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/vmlinux.lds.S | 4 | ||||
-rw-r--r-- | arch/x86/kernel/x8664_ksyms_64.c | 2 | ||||
-rw-r--r-- | arch/x86/tools/gen-insn-attr-x86.awk | 10 |
18 files changed, 244 insertions, 293 deletions
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c index bbeb0c3fbd90..89bbf4e4d05d 100644 --- a/arch/x86/boot/compressed/relocs.c +++ b/arch/x86/boot/compressed/relocs.c | |||
@@ -9,6 +9,9 @@ | |||
9 | #include <byteswap.h> | 9 | #include <byteswap.h> |
10 | #define USE_BSD | 10 | #define USE_BSD |
11 | #include <endian.h> | 11 | #include <endian.h> |
12 | #include <regex.h> | ||
13 | |||
14 | static void die(char *fmt, ...); | ||
12 | 15 | ||
13 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | 16 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
14 | static Elf32_Ehdr ehdr; | 17 | static Elf32_Ehdr ehdr; |
@@ -30,25 +33,47 @@ static struct section *secs; | |||
30 | * the address for which it has been compiled. Don't warn user about | 33 | * the address for which it has been compiled. Don't warn user about |
31 | * absolute relocations present w.r.t these symbols. | 34 | * absolute relocations present w.r.t these symbols. |
32 | */ | 35 | */ |
33 | static const char* safe_abs_relocs[] = { | 36 | static const char abs_sym_regex[] = |
34 | "xen_irq_disable_direct_reloc", | 37 | "^(xen_irq_disable_direct_reloc$|" |
35 | "xen_save_fl_direct_reloc", | 38 | "xen_save_fl_direct_reloc$|" |
36 | }; | 39 | "VDSO|" |
40 | "__crc_)"; | ||
41 | static regex_t abs_sym_regex_c; | ||
42 | static int is_abs_reloc(const char *sym_name) | ||
43 | { | ||
44 | return !regexec(&abs_sym_regex_c, sym_name, 0, NULL, 0); | ||
45 | } | ||
37 | 46 | ||
38 | static int is_safe_abs_reloc(const char* sym_name) | 47 | /* |
48 | * These symbols are known to be relative, even if the linker marks them | ||
49 | * as absolute (typically defined outside any section in the linker script.) | ||
50 | */ | ||
51 | static const char rel_sym_regex[] = | ||
52 | "^_end$"; | ||
53 | static regex_t rel_sym_regex_c; | ||
54 | static int is_rel_reloc(const char *sym_name) | ||
39 | { | 55 | { |
40 | int i; | 56 | return !regexec(&rel_sym_regex_c, sym_name, 0, NULL, 0); |
57 | } | ||
41 | 58 | ||
42 | for (i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) { | 59 | static void regex_init(void) |
43 | if (!strcmp(sym_name, safe_abs_relocs[i])) | 60 | { |
44 | /* Match found */ | 61 | char errbuf[128]; |
45 | return 1; | 62 | int err; |
46 | } | 63 | |
47 | if (strncmp(sym_name, "VDSO", 4) == 0) | 64 | err = regcomp(&abs_sym_regex_c, abs_sym_regex, |
48 | return 1; | 65 | REG_EXTENDED|REG_NOSUB); |
49 | if (strncmp(sym_name, "__crc_", 6) == 0) | 66 | if (err) { |
50 | return 1; | 67 | regerror(err, &abs_sym_regex_c, errbuf, sizeof errbuf); |
51 | return 0; | 68 | die("%s", errbuf); |
69 | } | ||
70 | |||
71 | err = regcomp(&rel_sym_regex_c, rel_sym_regex, | ||
72 | REG_EXTENDED|REG_NOSUB); | ||
73 | if (err) { | ||
74 | regerror(err, &rel_sym_regex_c, errbuf, sizeof errbuf); | ||
75 | die("%s", errbuf); | ||
76 | } | ||
52 | } | 77 | } |
53 | 78 | ||
54 | static void die(char *fmt, ...) | 79 | static void die(char *fmt, ...) |
@@ -131,7 +156,7 @@ static const char *rel_type(unsigned type) | |||
131 | #undef REL_TYPE | 156 | #undef REL_TYPE |
132 | }; | 157 | }; |
133 | const char *name = "unknown type rel type name"; | 158 | const char *name = "unknown type rel type name"; |
134 | if (type < ARRAY_SIZE(type_name)) { | 159 | if (type < ARRAY_SIZE(type_name) && type_name[type]) { |
135 | name = type_name[type]; | 160 | name = type_name[type]; |
136 | } | 161 | } |
137 | return name; | 162 | return name; |
@@ -448,7 +473,7 @@ static void print_absolute_relocs(void) | |||
448 | * Before warning check if this absolute symbol | 473 | * Before warning check if this absolute symbol |
449 | * relocation is harmless. | 474 | * relocation is harmless. |
450 | */ | 475 | */ |
451 | if (is_safe_abs_reloc(name)) | 476 | if (is_abs_reloc(name) || is_rel_reloc(name)) |
452 | continue; | 477 | continue; |
453 | 478 | ||
454 | if (!printed) { | 479 | if (!printed) { |
@@ -501,21 +526,26 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | |||
501 | sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; | 526 | sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; |
502 | r_type = ELF32_R_TYPE(rel->r_info); | 527 | r_type = ELF32_R_TYPE(rel->r_info); |
503 | /* Don't visit relocations to absolute symbols */ | 528 | /* Don't visit relocations to absolute symbols */ |
504 | if (sym->st_shndx == SHN_ABS) { | 529 | if (sym->st_shndx == SHN_ABS && |
530 | !is_rel_reloc(sym_name(sym_strtab, sym))) { | ||
505 | continue; | 531 | continue; |
506 | } | 532 | } |
507 | if (r_type == R_386_NONE || r_type == R_386_PC32) { | 533 | switch (r_type) { |
534 | case R_386_NONE: | ||
535 | case R_386_PC32: | ||
508 | /* | 536 | /* |
509 | * NONE can be ignored and and PC relative | 537 | * NONE can be ignored and and PC relative |
510 | * relocations don't need to be adjusted. | 538 | * relocations don't need to be adjusted. |
511 | */ | 539 | */ |
512 | } | 540 | break; |
513 | else if (r_type == R_386_32) { | 541 | case R_386_32: |
514 | /* Visit relocations that need to be adjusted */ | 542 | /* Visit relocations that need to be adjusted */ |
515 | visit(rel, sym); | 543 | visit(rel, sym); |
516 | } | 544 | break; |
517 | else { | 545 | default: |
518 | die("Unsupported relocation type: %d\n", r_type); | 546 | die("Unsupported relocation type: %s (%d)\n", |
547 | rel_type(r_type), r_type); | ||
548 | break; | ||
519 | } | 549 | } |
520 | } | 550 | } |
521 | } | 551 | } |
@@ -571,16 +601,15 @@ static void emit_relocs(int as_text) | |||
571 | } | 601 | } |
572 | else { | 602 | else { |
573 | unsigned char buf[4]; | 603 | unsigned char buf[4]; |
574 | buf[0] = buf[1] = buf[2] = buf[3] = 0; | ||
575 | /* Print a stop */ | 604 | /* Print a stop */ |
576 | printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]); | 605 | fwrite("\0\0\0\0", 4, 1, stdout); |
577 | /* Now print each relocation */ | 606 | /* Now print each relocation */ |
578 | for (i = 0; i < reloc_count; i++) { | 607 | for (i = 0; i < reloc_count; i++) { |
579 | buf[0] = (relocs[i] >> 0) & 0xff; | 608 | buf[0] = (relocs[i] >> 0) & 0xff; |
580 | buf[1] = (relocs[i] >> 8) & 0xff; | 609 | buf[1] = (relocs[i] >> 8) & 0xff; |
581 | buf[2] = (relocs[i] >> 16) & 0xff; | 610 | buf[2] = (relocs[i] >> 16) & 0xff; |
582 | buf[3] = (relocs[i] >> 24) & 0xff; | 611 | buf[3] = (relocs[i] >> 24) & 0xff; |
583 | printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]); | 612 | fwrite(buf, 4, 1, stdout); |
584 | } | 613 | } |
585 | } | 614 | } |
586 | } | 615 | } |
@@ -598,6 +627,8 @@ int main(int argc, char **argv) | |||
598 | FILE *fp; | 627 | FILE *fp; |
599 | int i; | 628 | int i; |
600 | 629 | ||
630 | regex_init(); | ||
631 | |||
601 | show_absolute_syms = 0; | 632 | show_absolute_syms = 0; |
602 | show_absolute_relocs = 0; | 633 | show_absolute_relocs = 0; |
603 | as_text = 0; | 634 | as_text = 0; |
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h index 87ffcb12a1b8..8085277e1b8b 100644 --- a/arch/x86/include/asm/swiotlb.h +++ b/arch/x86/include/asm/swiotlb.h | |||
@@ -5,13 +5,17 @@ | |||
5 | 5 | ||
6 | #ifdef CONFIG_SWIOTLB | 6 | #ifdef CONFIG_SWIOTLB |
7 | extern int swiotlb; | 7 | extern int swiotlb; |
8 | extern int pci_swiotlb_init(void); | 8 | extern int __init pci_swiotlb_detect(void); |
9 | extern void __init pci_swiotlb_init(void); | ||
9 | #else | 10 | #else |
10 | #define swiotlb 0 | 11 | #define swiotlb 0 |
11 | static inline int pci_swiotlb_init(void) | 12 | static inline int pci_swiotlb_detect(void) |
12 | { | 13 | { |
13 | return 0; | 14 | return 0; |
14 | } | 15 | } |
16 | static inline void pci_swiotlb_init(void) | ||
17 | { | ||
18 | } | ||
15 | #endif | 19 | #endif |
16 | 20 | ||
17 | static inline void dma_mark_clean(void *addr, size_t size) {} | 21 | static inline void dma_mark_clean(void *addr, size_t size) {} |
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index 1bb6e395881c..8868b9420b0e 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h | |||
@@ -18,16 +18,24 @@ | |||
18 | /* Common in X86_32 and X86_64 */ | 18 | /* Common in X86_32 and X86_64 */ |
19 | /* kernel/ioport.c */ | 19 | /* kernel/ioport.c */ |
20 | asmlinkage long sys_ioperm(unsigned long, unsigned long, int); | 20 | asmlinkage long sys_ioperm(unsigned long, unsigned long, int); |
21 | long sys_iopl(unsigned int, struct pt_regs *); | ||
21 | 22 | ||
22 | /* kernel/process.c */ | 23 | /* kernel/process.c */ |
23 | int sys_fork(struct pt_regs *); | 24 | int sys_fork(struct pt_regs *); |
24 | int sys_vfork(struct pt_regs *); | 25 | int sys_vfork(struct pt_regs *); |
26 | long sys_execve(char __user *, char __user * __user *, | ||
27 | char __user * __user *, struct pt_regs *); | ||
28 | long sys_clone(unsigned long, unsigned long, void __user *, | ||
29 | void __user *, struct pt_regs *); | ||
25 | 30 | ||
26 | /* kernel/ldt.c */ | 31 | /* kernel/ldt.c */ |
27 | asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); | 32 | asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); |
28 | 33 | ||
29 | /* kernel/signal.c */ | 34 | /* kernel/signal.c */ |
30 | long sys_rt_sigreturn(struct pt_regs *); | 35 | long sys_rt_sigreturn(struct pt_regs *); |
36 | long sys_sigaltstack(const stack_t __user *, stack_t __user *, | ||
37 | struct pt_regs *); | ||
38 | |||
31 | 39 | ||
32 | /* kernel/tls.c */ | 40 | /* kernel/tls.c */ |
33 | asmlinkage int sys_set_thread_area(struct user_desc __user *); | 41 | asmlinkage int sys_set_thread_area(struct user_desc __user *); |
@@ -35,18 +43,11 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *); | |||
35 | 43 | ||
36 | /* X86_32 only */ | 44 | /* X86_32 only */ |
37 | #ifdef CONFIG_X86_32 | 45 | #ifdef CONFIG_X86_32 |
38 | /* kernel/ioport.c */ | ||
39 | long sys_iopl(struct pt_regs *); | ||
40 | |||
41 | /* kernel/process_32.c */ | ||
42 | int sys_clone(struct pt_regs *); | ||
43 | int sys_execve(struct pt_regs *); | ||
44 | 46 | ||
45 | /* kernel/signal.c */ | 47 | /* kernel/signal.c */ |
46 | asmlinkage int sys_sigsuspend(int, int, old_sigset_t); | 48 | asmlinkage int sys_sigsuspend(int, int, old_sigset_t); |
47 | asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, | 49 | asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, |
48 | struct old_sigaction __user *); | 50 | struct old_sigaction __user *); |
49 | int sys_sigaltstack(struct pt_regs *); | ||
50 | unsigned long sys_sigreturn(struct pt_regs *); | 51 | unsigned long sys_sigreturn(struct pt_regs *); |
51 | 52 | ||
52 | /* kernel/sys_i386_32.c */ | 53 | /* kernel/sys_i386_32.c */ |
@@ -62,28 +63,15 @@ asmlinkage int sys_uname(struct old_utsname __user *); | |||
62 | asmlinkage int sys_olduname(struct oldold_utsname __user *); | 63 | asmlinkage int sys_olduname(struct oldold_utsname __user *); |
63 | 64 | ||
64 | /* kernel/vm86_32.c */ | 65 | /* kernel/vm86_32.c */ |
65 | int sys_vm86old(struct pt_regs *); | 66 | int sys_vm86old(struct vm86_struct __user *, struct pt_regs *); |
66 | int sys_vm86(struct pt_regs *); | 67 | int sys_vm86(unsigned long, unsigned long, struct pt_regs *); |
67 | 68 | ||
68 | #else /* CONFIG_X86_32 */ | 69 | #else /* CONFIG_X86_32 */ |
69 | 70 | ||
70 | /* X86_64 only */ | 71 | /* X86_64 only */ |
71 | /* kernel/ioport.c */ | ||
72 | asmlinkage long sys_iopl(unsigned int, struct pt_regs *); | ||
73 | |||
74 | /* kernel/process_64.c */ | 72 | /* kernel/process_64.c */ |
75 | asmlinkage long sys_clone(unsigned long, unsigned long, | ||
76 | void __user *, void __user *, | ||
77 | struct pt_regs *); | ||
78 | asmlinkage long sys_execve(char __user *, char __user * __user *, | ||
79 | char __user * __user *, | ||
80 | struct pt_regs *); | ||
81 | long sys_arch_prctl(int, unsigned long); | 73 | long sys_arch_prctl(int, unsigned long); |
82 | 74 | ||
83 | /* kernel/signal.c */ | ||
84 | asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *, | ||
85 | struct pt_regs *); | ||
86 | |||
87 | /* kernel/sys_x86_64.c */ | 75 | /* kernel/sys_x86_64.c */ |
88 | struct new_utsname; | 76 | struct new_utsname; |
89 | 77 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index 472763d92098..73734baa50f2 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c | |||
@@ -74,7 +74,7 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs) | |||
74 | m->finished = 0; | 74 | m->finished = 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | static cpumask_t mce_inject_cpumask; | 77 | static cpumask_var_t mce_inject_cpumask; |
78 | 78 | ||
79 | static int mce_raise_notify(struct notifier_block *self, | 79 | static int mce_raise_notify(struct notifier_block *self, |
80 | unsigned long val, void *data) | 80 | unsigned long val, void *data) |
@@ -82,9 +82,9 @@ static int mce_raise_notify(struct notifier_block *self, | |||
82 | struct die_args *args = (struct die_args *)data; | 82 | struct die_args *args = (struct die_args *)data; |
83 | int cpu = smp_processor_id(); | 83 | int cpu = smp_processor_id(); |
84 | struct mce *m = &__get_cpu_var(injectm); | 84 | struct mce *m = &__get_cpu_var(injectm); |
85 | if (val != DIE_NMI_IPI || !cpu_isset(cpu, mce_inject_cpumask)) | 85 | if (val != DIE_NMI_IPI || !cpumask_test_cpu(cpu, mce_inject_cpumask)) |
86 | return NOTIFY_DONE; | 86 | return NOTIFY_DONE; |
87 | cpu_clear(cpu, mce_inject_cpumask); | 87 | cpumask_clear_cpu(cpu, mce_inject_cpumask); |
88 | if (m->inject_flags & MCJ_EXCEPTION) | 88 | if (m->inject_flags & MCJ_EXCEPTION) |
89 | raise_exception(m, args->regs); | 89 | raise_exception(m, args->regs); |
90 | else if (m->status) | 90 | else if (m->status) |
@@ -148,22 +148,22 @@ static void raise_mce(struct mce *m) | |||
148 | unsigned long start; | 148 | unsigned long start; |
149 | int cpu; | 149 | int cpu; |
150 | get_online_cpus(); | 150 | get_online_cpus(); |
151 | mce_inject_cpumask = cpu_online_map; | 151 | cpumask_copy(mce_inject_cpumask, cpu_online_mask); |
152 | cpu_clear(get_cpu(), mce_inject_cpumask); | 152 | cpumask_clear_cpu(get_cpu(), mce_inject_cpumask); |
153 | for_each_online_cpu(cpu) { | 153 | for_each_online_cpu(cpu) { |
154 | struct mce *mcpu = &per_cpu(injectm, cpu); | 154 | struct mce *mcpu = &per_cpu(injectm, cpu); |
155 | if (!mcpu->finished || | 155 | if (!mcpu->finished || |
156 | MCJ_CTX(mcpu->inject_flags) != MCJ_CTX_RANDOM) | 156 | MCJ_CTX(mcpu->inject_flags) != MCJ_CTX_RANDOM) |
157 | cpu_clear(cpu, mce_inject_cpumask); | 157 | cpumask_clear_cpu(cpu, mce_inject_cpumask); |
158 | } | 158 | } |
159 | if (!cpus_empty(mce_inject_cpumask)) | 159 | if (!cpumask_empty(mce_inject_cpumask)) |
160 | apic->send_IPI_mask(&mce_inject_cpumask, NMI_VECTOR); | 160 | apic->send_IPI_mask(mce_inject_cpumask, NMI_VECTOR); |
161 | start = jiffies; | 161 | start = jiffies; |
162 | while (!cpus_empty(mce_inject_cpumask)) { | 162 | while (!cpumask_empty(mce_inject_cpumask)) { |
163 | if (!time_before(jiffies, start + 2*HZ)) { | 163 | if (!time_before(jiffies, start + 2*HZ)) { |
164 | printk(KERN_ERR | 164 | printk(KERN_ERR |
165 | "Timeout waiting for mce inject NMI %lx\n", | 165 | "Timeout waiting for mce inject NMI %lx\n", |
166 | *cpus_addr(mce_inject_cpumask)); | 166 | *cpumask_bits(mce_inject_cpumask)); |
167 | break; | 167 | break; |
168 | } | 168 | } |
169 | cpu_relax(); | 169 | cpu_relax(); |
@@ -210,6 +210,8 @@ static ssize_t mce_write(struct file *filp, const char __user *ubuf, | |||
210 | 210 | ||
211 | static int inject_init(void) | 211 | static int inject_init(void) |
212 | { | 212 | { |
213 | if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL)) | ||
214 | return -ENOMEM; | ||
213 | printk(KERN_INFO "Machine check injector initialized\n"); | 215 | printk(KERN_INFO "Machine check injector initialized\n"); |
214 | mce_chrdev_ops.write = mce_write; | 216 | mce_chrdev_ops.write = mce_write; |
215 | register_die_notifier(&mce_raise_nb); | 217 | register_die_notifier(&mce_raise_nb); |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 50b9c220e121..44a8e0dc6737 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -725,22 +725,61 @@ END(syscall_badsys) | |||
725 | /* | 725 | /* |
726 | * System calls that need a pt_regs pointer. | 726 | * System calls that need a pt_regs pointer. |
727 | */ | 727 | */ |
728 | #define PTREGSCALL(name) \ | 728 | #define PTREGSCALL0(name) \ |
729 | ALIGN; \ | 729 | ALIGN; \ |
730 | ptregs_##name: \ | 730 | ptregs_##name: \ |
731 | leal 4(%esp),%eax; \ | 731 | leal 4(%esp),%eax; \ |
732 | jmp sys_##name; | 732 | jmp sys_##name; |
733 | 733 | ||
734 | PTREGSCALL(iopl) | 734 | #define PTREGSCALL1(name) \ |
735 | PTREGSCALL(fork) | 735 | ALIGN; \ |
736 | PTREGSCALL(clone) | 736 | ptregs_##name: \ |
737 | PTREGSCALL(vfork) | 737 | leal 4(%esp),%edx; \ |
738 | PTREGSCALL(execve) | 738 | movl (PT_EBX+4)(%esp),%eax; \ |
739 | PTREGSCALL(sigaltstack) | 739 | jmp sys_##name; |
740 | PTREGSCALL(sigreturn) | 740 | |
741 | PTREGSCALL(rt_sigreturn) | 741 | #define PTREGSCALL2(name) \ |
742 | PTREGSCALL(vm86) | 742 | ALIGN; \ |
743 | PTREGSCALL(vm86old) | 743 | ptregs_##name: \ |
744 | leal 4(%esp),%ecx; \ | ||
745 | movl (PT_ECX+4)(%esp),%edx; \ | ||
746 | movl (PT_EBX+4)(%esp),%eax; \ | ||
747 | jmp sys_##name; | ||
748 | |||
749 | #define PTREGSCALL3(name) \ | ||
750 | ALIGN; \ | ||
751 | ptregs_##name: \ | ||
752 | leal 4(%esp),%eax; \ | ||
753 | pushl %eax; \ | ||
754 | movl PT_EDX(%eax),%ecx; \ | ||
755 | movl PT_ECX(%eax),%edx; \ | ||
756 | movl PT_EBX(%eax),%eax; \ | ||
757 | call sys_##name; \ | ||
758 | addl $4,%esp; \ | ||
759 | ret | ||
760 | |||
761 | PTREGSCALL1(iopl) | ||
762 | PTREGSCALL0(fork) | ||
763 | PTREGSCALL0(vfork) | ||
764 | PTREGSCALL3(execve) | ||
765 | PTREGSCALL2(sigaltstack) | ||
766 | PTREGSCALL0(sigreturn) | ||
767 | PTREGSCALL0(rt_sigreturn) | ||
768 | PTREGSCALL2(vm86) | ||
769 | PTREGSCALL1(vm86old) | ||
770 | |||
771 | /* Clone is an oddball. The 4th arg is in %edi */ | ||
772 | ALIGN; | ||
773 | ptregs_clone: | ||
774 | leal 4(%esp),%eax | ||
775 | pushl %eax | ||
776 | pushl PT_EDI(%eax) | ||
777 | movl PT_EDX(%eax),%ecx | ||
778 | movl PT_ECX(%eax),%edx | ||
779 | movl PT_EBX(%eax),%eax | ||
780 | call sys_clone | ||
781 | addl $8,%esp | ||
782 | ret | ||
744 | 783 | ||
745 | .macro FIXUP_ESPFIX_STACK | 784 | .macro FIXUP_ESPFIX_STACK |
746 | /* | 785 | /* |
@@ -1008,12 +1047,8 @@ END(spurious_interrupt_bug) | |||
1008 | ENTRY(kernel_thread_helper) | 1047 | ENTRY(kernel_thread_helper) |
1009 | pushl $0 # fake return address for unwinder | 1048 | pushl $0 # fake return address for unwinder |
1010 | CFI_STARTPROC | 1049 | CFI_STARTPROC |
1011 | movl %edx,%eax | 1050 | movl %edi,%eax |
1012 | push %edx | 1051 | call *%esi |
1013 | CFI_ADJUST_CFA_OFFSET 4 | ||
1014 | call *%ebx | ||
1015 | push %eax | ||
1016 | CFI_ADJUST_CFA_OFFSET 4 | ||
1017 | call do_exit | 1052 | call do_exit |
1018 | ud2 # padding for call trace | 1053 | ud2 # padding for call trace |
1019 | CFI_ENDPROC | 1054 | CFI_ENDPROC |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 673f693fb451..0697ff139837 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -1166,63 +1166,20 @@ bad_gs: | |||
1166 | jmp 2b | 1166 | jmp 2b |
1167 | .previous | 1167 | .previous |
1168 | 1168 | ||
1169 | /* | 1169 | ENTRY(kernel_thread_helper) |
1170 | * Create a kernel thread. | ||
1171 | * | ||
1172 | * C extern interface: | ||
1173 | * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
1174 | * | ||
1175 | * asm input arguments: | ||
1176 | * rdi: fn, rsi: arg, rdx: flags | ||
1177 | */ | ||
1178 | ENTRY(kernel_thread) | ||
1179 | CFI_STARTPROC | ||
1180 | FAKE_STACK_FRAME $child_rip | ||
1181 | SAVE_ALL | ||
1182 | |||
1183 | # rdi: flags, rsi: usp, rdx: will be &pt_regs | ||
1184 | movq %rdx,%rdi | ||
1185 | orq kernel_thread_flags(%rip),%rdi | ||
1186 | movq $-1, %rsi | ||
1187 | movq %rsp, %rdx | ||
1188 | |||
1189 | xorl %r8d,%r8d | ||
1190 | xorl %r9d,%r9d | ||
1191 | |||
1192 | # clone now | ||
1193 | call do_fork | ||
1194 | movq %rax,RAX(%rsp) | ||
1195 | xorl %edi,%edi | ||
1196 | |||
1197 | /* | ||
1198 | * It isn't worth to check for reschedule here, | ||
1199 | * so internally to the x86_64 port you can rely on kernel_thread() | ||
1200 | * not to reschedule the child before returning, this avoids the need | ||
1201 | * of hacks for example to fork off the per-CPU idle tasks. | ||
1202 | * [Hopefully no generic code relies on the reschedule -AK] | ||
1203 | */ | ||
1204 | RESTORE_ALL | ||
1205 | UNFAKE_STACK_FRAME | ||
1206 | ret | ||
1207 | CFI_ENDPROC | ||
1208 | END(kernel_thread) | ||
1209 | |||
1210 | ENTRY(child_rip) | ||
1211 | pushq $0 # fake return address | 1170 | pushq $0 # fake return address |
1212 | CFI_STARTPROC | 1171 | CFI_STARTPROC |
1213 | /* | 1172 | /* |
1214 | * Here we are in the child and the registers are set as they were | 1173 | * Here we are in the child and the registers are set as they were |
1215 | * at kernel_thread() invocation in the parent. | 1174 | * at kernel_thread() invocation in the parent. |
1216 | */ | 1175 | */ |
1217 | movq %rdi, %rax | 1176 | call *%rsi |
1218 | movq %rsi, %rdi | ||
1219 | call *%rax | ||
1220 | # exit | 1177 | # exit |
1221 | mov %eax, %edi | 1178 | mov %eax, %edi |
1222 | call do_exit | 1179 | call do_exit |
1223 | ud2 # padding for call trace | 1180 | ud2 # padding for call trace |
1224 | CFI_ENDPROC | 1181 | CFI_ENDPROC |
1225 | END(child_rip) | 1182 | END(kernel_thread_helper) |
1226 | 1183 | ||
1227 | /* | 1184 | /* |
1228 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. | 1185 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. |
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index 99c4d308f16b..8eec0ec59af2 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c | |||
@@ -103,9 +103,10 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
103 | * on system-call entry - see also fork() and the signal handling | 103 | * on system-call entry - see also fork() and the signal handling |
104 | * code. | 104 | * code. |
105 | */ | 105 | */ |
106 | static int do_iopl(unsigned int level, struct pt_regs *regs) | 106 | long sys_iopl(unsigned int level, struct pt_regs *regs) |
107 | { | 107 | { |
108 | unsigned int old = (regs->flags >> 12) & 3; | 108 | unsigned int old = (regs->flags >> 12) & 3; |
109 | struct thread_struct *t = ¤t->thread; | ||
109 | 110 | ||
110 | if (level > 3) | 111 | if (level > 3) |
111 | return -EINVAL; | 112 | return -EINVAL; |
@@ -115,29 +116,8 @@ static int do_iopl(unsigned int level, struct pt_regs *regs) | |||
115 | return -EPERM; | 116 | return -EPERM; |
116 | } | 117 | } |
117 | regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); | 118 | regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); |
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | #ifdef CONFIG_X86_32 | ||
123 | long sys_iopl(struct pt_regs *regs) | ||
124 | { | ||
125 | unsigned int level = regs->bx; | ||
126 | struct thread_struct *t = ¤t->thread; | ||
127 | int rc; | ||
128 | |||
129 | rc = do_iopl(level, regs); | ||
130 | if (rc < 0) | ||
131 | goto out; | ||
132 | |||
133 | t->iopl = level << 12; | 119 | t->iopl = level << 12; |
134 | set_iopl_mask(t->iopl); | 120 | set_iopl_mask(t->iopl); |
135 | out: | 121 | |
136 | return rc; | 122 | return 0; |
137 | } | ||
138 | #else | ||
139 | asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs) | ||
140 | { | ||
141 | return do_iopl(level, regs); | ||
142 | } | 123 | } |
143 | #endif | ||
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 553449951b84..572b07eee3f4 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c | |||
@@ -172,11 +172,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg) | |||
172 | 172 | ||
173 | static int msr_open(struct inode *inode, struct file *file) | 173 | static int msr_open(struct inode *inode, struct file *file) |
174 | { | 174 | { |
175 | unsigned int cpu = iminor(file->f_path.dentry->d_inode); | 175 | unsigned int cpu; |
176 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 176 | struct cpuinfo_x86 *c; |
177 | 177 | ||
178 | cpu = iminor(file->f_path.dentry->d_inode); | 178 | cpu = iminor(file->f_path.dentry->d_inode); |
179 | |||
180 | if (cpu >= nr_cpu_ids || !cpu_online(cpu)) | 179 | if (cpu >= nr_cpu_ids || !cpu_online(cpu)) |
181 | return -ENXIO; /* No such CPU */ | 180 | return -ENXIO; /* No such CPU */ |
182 | 181 | ||
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index fcc2f2bfa39c..75e14e21f61a 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -120,15 +120,12 @@ static void __init dma32_free_bootmem(void) | |||
120 | 120 | ||
121 | void __init pci_iommu_alloc(void) | 121 | void __init pci_iommu_alloc(void) |
122 | { | 122 | { |
123 | int use_swiotlb; | ||
124 | |||
125 | use_swiotlb = pci_swiotlb_init(); | ||
126 | #ifdef CONFIG_X86_64 | 123 | #ifdef CONFIG_X86_64 |
127 | /* free the range so iommu could get some range less than 4G */ | 124 | /* free the range so iommu could get some range less than 4G */ |
128 | dma32_free_bootmem(); | 125 | dma32_free_bootmem(); |
129 | #endif | 126 | #endif |
130 | if (use_swiotlb) | 127 | if (pci_swiotlb_detect()) |
131 | return; | 128 | goto out; |
132 | 129 | ||
133 | gart_iommu_hole_init(); | 130 | gart_iommu_hole_init(); |
134 | 131 | ||
@@ -138,6 +135,8 @@ void __init pci_iommu_alloc(void) | |||
138 | 135 | ||
139 | /* needs to be called after gart_iommu_hole_init */ | 136 | /* needs to be called after gart_iommu_hole_init */ |
140 | amd_iommu_detect(); | 137 | amd_iommu_detect(); |
138 | out: | ||
139 | pci_swiotlb_init(); | ||
141 | } | 140 | } |
142 | 141 | ||
143 | void *dma_generic_alloc_coherent(struct device *dev, size_t size, | 142 | void *dma_generic_alloc_coherent(struct device *dev, size_t size, |
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c index e3c0a66b9e77..7d2829dde20e 100644 --- a/arch/x86/kernel/pci-swiotlb.c +++ b/arch/x86/kernel/pci-swiotlb.c | |||
@@ -43,12 +43,12 @@ static struct dma_map_ops swiotlb_dma_ops = { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * pci_swiotlb_init - initialize swiotlb if necessary | 46 | * pci_swiotlb_detect - set swiotlb to 1 if necessary |
47 | * | 47 | * |
48 | * This returns non-zero if we are forced to use swiotlb (by the boot | 48 | * This returns non-zero if we are forced to use swiotlb (by the boot |
49 | * option). | 49 | * option). |
50 | */ | 50 | */ |
51 | int __init pci_swiotlb_init(void) | 51 | int __init pci_swiotlb_detect(void) |
52 | { | 52 | { |
53 | int use_swiotlb = swiotlb | swiotlb_force; | 53 | int use_swiotlb = swiotlb | swiotlb_force; |
54 | 54 | ||
@@ -60,10 +60,13 @@ int __init pci_swiotlb_init(void) | |||
60 | if (swiotlb_force) | 60 | if (swiotlb_force) |
61 | swiotlb = 1; | 61 | swiotlb = 1; |
62 | 62 | ||
63 | return use_swiotlb; | ||
64 | } | ||
65 | |||
66 | void __init pci_swiotlb_init(void) | ||
67 | { | ||
63 | if (swiotlb) { | 68 | if (swiotlb) { |
64 | swiotlb_init(0); | 69 | swiotlb_init(0); |
65 | dma_ops = &swiotlb_dma_ops; | 70 | dma_ops = &swiotlb_dma_ops; |
66 | } | 71 | } |
67 | |||
68 | return use_swiotlb; | ||
69 | } | 72 | } |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 7a7bd4e3ec49..98c2cdeb599e 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -255,6 +255,76 @@ int sys_vfork(struct pt_regs *regs) | |||
255 | NULL, NULL); | 255 | NULL, NULL); |
256 | } | 256 | } |
257 | 257 | ||
258 | long | ||
259 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
260 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
261 | { | ||
262 | if (!newsp) | ||
263 | newsp = regs->sp; | ||
264 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * This gets run with %si containing the | ||
269 | * function to call, and %di containing | ||
270 | * the "args". | ||
271 | */ | ||
272 | extern void kernel_thread_helper(void); | ||
273 | |||
274 | /* | ||
275 | * Create a kernel thread | ||
276 | */ | ||
277 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
278 | { | ||
279 | struct pt_regs regs; | ||
280 | |||
281 | memset(®s, 0, sizeof(regs)); | ||
282 | |||
283 | regs.si = (unsigned long) fn; | ||
284 | regs.di = (unsigned long) arg; | ||
285 | |||
286 | #ifdef CONFIG_X86_32 | ||
287 | regs.ds = __USER_DS; | ||
288 | regs.es = __USER_DS; | ||
289 | regs.fs = __KERNEL_PERCPU; | ||
290 | regs.gs = __KERNEL_STACK_CANARY; | ||
291 | #endif | ||
292 | |||
293 | regs.orig_ax = -1; | ||
294 | regs.ip = (unsigned long) kernel_thread_helper; | ||
295 | regs.cs = __KERNEL_CS | get_kernel_rpl(); | ||
296 | regs.flags = X86_EFLAGS_IF | 0x2; | ||
297 | |||
298 | /* Ok, create the new process.. */ | ||
299 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
300 | } | ||
301 | EXPORT_SYMBOL(kernel_thread); | ||
302 | |||
303 | /* | ||
304 | * sys_execve() executes a new program. | ||
305 | */ | ||
306 | long sys_execve(char __user *name, char __user * __user *argv, | ||
307 | char __user * __user *envp, struct pt_regs *regs) | ||
308 | { | ||
309 | long error; | ||
310 | char *filename; | ||
311 | |||
312 | filename = getname(name); | ||
313 | error = PTR_ERR(filename); | ||
314 | if (IS_ERR(filename)) | ||
315 | return error; | ||
316 | error = do_execve(filename, argv, envp, regs); | ||
317 | |||
318 | #ifdef CONFIG_X86_32 | ||
319 | if (error == 0) { | ||
320 | /* Make sure we don't return using sysenter.. */ | ||
321 | set_thread_flag(TIF_IRET); | ||
322 | } | ||
323 | #endif | ||
324 | |||
325 | putname(filename); | ||
326 | return error; | ||
327 | } | ||
258 | 328 | ||
259 | /* | 329 | /* |
260 | * Idle related variables and functions | 330 | * Idle related variables and functions |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 120b88797a75..9c517b5858f0 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -180,39 +180,6 @@ void show_regs(struct pt_regs *regs) | |||
180 | show_trace(NULL, regs, ®s->sp, regs->bp); | 180 | show_trace(NULL, regs, ®s->sp, regs->bp); |
181 | } | 181 | } |
182 | 182 | ||
183 | /* | ||
184 | * This gets run with %bx containing the | ||
185 | * function to call, and %dx containing | ||
186 | * the "args". | ||
187 | */ | ||
188 | extern void kernel_thread_helper(void); | ||
189 | |||
190 | /* | ||
191 | * Create a kernel thread | ||
192 | */ | ||
193 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
194 | { | ||
195 | struct pt_regs regs; | ||
196 | |||
197 | memset(®s, 0, sizeof(regs)); | ||
198 | |||
199 | regs.bx = (unsigned long) fn; | ||
200 | regs.dx = (unsigned long) arg; | ||
201 | |||
202 | regs.ds = __USER_DS; | ||
203 | regs.es = __USER_DS; | ||
204 | regs.fs = __KERNEL_PERCPU; | ||
205 | regs.gs = __KERNEL_STACK_CANARY; | ||
206 | regs.orig_ax = -1; | ||
207 | regs.ip = (unsigned long) kernel_thread_helper; | ||
208 | regs.cs = __KERNEL_CS | get_kernel_rpl(); | ||
209 | regs.flags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; | ||
210 | |||
211 | /* Ok, create the new process.. */ | ||
212 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
213 | } | ||
214 | EXPORT_SYMBOL(kernel_thread); | ||
215 | |||
216 | void release_thread(struct task_struct *dead_task) | 183 | void release_thread(struct task_struct *dead_task) |
217 | { | 184 | { |
218 | BUG_ON(dead_task->mm); | 185 | BUG_ON(dead_task->mm); |
@@ -424,46 +391,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
424 | return prev_p; | 391 | return prev_p; |
425 | } | 392 | } |
426 | 393 | ||
427 | int sys_clone(struct pt_regs *regs) | ||
428 | { | ||
429 | unsigned long clone_flags; | ||
430 | unsigned long newsp; | ||
431 | int __user *parent_tidptr, *child_tidptr; | ||
432 | |||
433 | clone_flags = regs->bx; | ||
434 | newsp = regs->cx; | ||
435 | parent_tidptr = (int __user *)regs->dx; | ||
436 | child_tidptr = (int __user *)regs->di; | ||
437 | if (!newsp) | ||
438 | newsp = regs->sp; | ||
439 | return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * sys_execve() executes a new program. | ||
444 | */ | ||
445 | int sys_execve(struct pt_regs *regs) | ||
446 | { | ||
447 | int error; | ||
448 | char *filename; | ||
449 | |||
450 | filename = getname((char __user *) regs->bx); | ||
451 | error = PTR_ERR(filename); | ||
452 | if (IS_ERR(filename)) | ||
453 | goto out; | ||
454 | error = do_execve(filename, | ||
455 | (char __user * __user *) regs->cx, | ||
456 | (char __user * __user *) regs->dx, | ||
457 | regs); | ||
458 | if (error == 0) { | ||
459 | /* Make sure we don't return using sysenter.. */ | ||
460 | set_thread_flag(TIF_IRET); | ||
461 | } | ||
462 | putname(filename); | ||
463 | out: | ||
464 | return error; | ||
465 | } | ||
466 | |||
467 | #define top_esp (THREAD_SIZE - sizeof(unsigned long)) | 394 | #define top_esp (THREAD_SIZE - sizeof(unsigned long)) |
468 | #define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) | 395 | #define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) |
469 | 396 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e5ab0cd0ef36..52fbd0c60198 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -57,8 +57,6 @@ asmlinkage extern void ret_from_fork(void); | |||
57 | DEFINE_PER_CPU(unsigned long, old_rsp); | 57 | DEFINE_PER_CPU(unsigned long, old_rsp); |
58 | static DEFINE_PER_CPU(unsigned char, is_idle); | 58 | static DEFINE_PER_CPU(unsigned char, is_idle); |
59 | 59 | ||
60 | unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; | ||
61 | |||
62 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); | 60 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); |
63 | 61 | ||
64 | void idle_notifier_register(struct notifier_block *n) | 62 | void idle_notifier_register(struct notifier_block *n) |
@@ -273,8 +271,9 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
273 | *childregs = *regs; | 271 | *childregs = *regs; |
274 | 272 | ||
275 | childregs->ax = 0; | 273 | childregs->ax = 0; |
276 | childregs->sp = sp; | 274 | if (user_mode(regs)) |
277 | if (sp == ~0UL) | 275 | childregs->sp = sp; |
276 | else | ||
278 | childregs->sp = (unsigned long)childregs; | 277 | childregs->sp = (unsigned long)childregs; |
279 | 278 | ||
280 | p->thread.sp = (unsigned long) childregs; | 279 | p->thread.sp = (unsigned long) childregs; |
@@ -508,25 +507,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
508 | return prev_p; | 507 | return prev_p; |
509 | } | 508 | } |
510 | 509 | ||
511 | /* | ||
512 | * sys_execve() executes a new program. | ||
513 | */ | ||
514 | asmlinkage | ||
515 | long sys_execve(char __user *name, char __user * __user *argv, | ||
516 | char __user * __user *envp, struct pt_regs *regs) | ||
517 | { | ||
518 | long error; | ||
519 | char *filename; | ||
520 | |||
521 | filename = getname(name); | ||
522 | error = PTR_ERR(filename); | ||
523 | if (IS_ERR(filename)) | ||
524 | return error; | ||
525 | error = do_execve(filename, argv, envp, regs); | ||
526 | putname(filename); | ||
527 | return error; | ||
528 | } | ||
529 | |||
530 | void set_personality_64bit(void) | 510 | void set_personality_64bit(void) |
531 | { | 511 | { |
532 | /* inherit personality from parent */ | 512 | /* inherit personality from parent */ |
@@ -541,15 +521,6 @@ void set_personality_64bit(void) | |||
541 | current->personality &= ~READ_IMPLIES_EXEC; | 521 | current->personality &= ~READ_IMPLIES_EXEC; |
542 | } | 522 | } |
543 | 523 | ||
544 | asmlinkage long | ||
545 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
546 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
547 | { | ||
548 | if (!newsp) | ||
549 | newsp = regs->sp; | ||
550 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
551 | } | ||
552 | |||
553 | unsigned long get_wchan(struct task_struct *p) | 524 | unsigned long get_wchan(struct task_struct *p) |
554 | { | 525 | { |
555 | unsigned long stack; | 526 | unsigned long stack; |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 74fe6d86dc5d..4fd173cd8e57 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -545,22 +545,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
545 | } | 545 | } |
546 | #endif /* CONFIG_X86_32 */ | 546 | #endif /* CONFIG_X86_32 */ |
547 | 547 | ||
548 | #ifdef CONFIG_X86_32 | 548 | long |
549 | int sys_sigaltstack(struct pt_regs *regs) | ||
550 | { | ||
551 | const stack_t __user *uss = (const stack_t __user *)regs->bx; | ||
552 | stack_t __user *uoss = (stack_t __user *)regs->cx; | ||
553 | |||
554 | return do_sigaltstack(uss, uoss, regs->sp); | ||
555 | } | ||
556 | #else /* !CONFIG_X86_32 */ | ||
557 | asmlinkage long | ||
558 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 549 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
559 | struct pt_regs *regs) | 550 | struct pt_regs *regs) |
560 | { | 551 | { |
561 | return do_sigaltstack(uss, uoss, regs->sp); | 552 | return do_sigaltstack(uss, uoss, regs->sp); |
562 | } | 553 | } |
563 | #endif /* CONFIG_X86_32 */ | ||
564 | 554 | ||
565 | /* | 555 | /* |
566 | * Do a signal return; undo the signal stack. | 556 | * Do a signal return; undo the signal stack. |
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 9c4e62539058..5ffb5622f793 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c | |||
@@ -197,9 +197,8 @@ out: | |||
197 | static int do_vm86_irq_handling(int subfunction, int irqnumber); | 197 | static int do_vm86_irq_handling(int subfunction, int irqnumber); |
198 | static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); | 198 | static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); |
199 | 199 | ||
200 | int sys_vm86old(struct pt_regs *regs) | 200 | int sys_vm86old(struct vm86_struct __user *v86, struct pt_regs *regs) |
201 | { | 201 | { |
202 | struct vm86_struct __user *v86 = (struct vm86_struct __user *)regs->bx; | ||
203 | struct kernel_vm86_struct info; /* declare this _on top_, | 202 | struct kernel_vm86_struct info; /* declare this _on top_, |
204 | * this avoids wasting of stack space. | 203 | * this avoids wasting of stack space. |
205 | * This remains on the stack until we | 204 | * This remains on the stack until we |
@@ -227,7 +226,7 @@ out: | |||
227 | } | 226 | } |
228 | 227 | ||
229 | 228 | ||
230 | int sys_vm86(struct pt_regs *regs) | 229 | int sys_vm86(unsigned long cmd, unsigned long arg, struct pt_regs *regs) |
231 | { | 230 | { |
232 | struct kernel_vm86_struct info; /* declare this _on top_, | 231 | struct kernel_vm86_struct info; /* declare this _on top_, |
233 | * this avoids wasting of stack space. | 232 | * this avoids wasting of stack space. |
@@ -239,12 +238,12 @@ int sys_vm86(struct pt_regs *regs) | |||
239 | struct vm86plus_struct __user *v86; | 238 | struct vm86plus_struct __user *v86; |
240 | 239 | ||
241 | tsk = current; | 240 | tsk = current; |
242 | switch (regs->bx) { | 241 | switch (cmd) { |
243 | case VM86_REQUEST_IRQ: | 242 | case VM86_REQUEST_IRQ: |
244 | case VM86_FREE_IRQ: | 243 | case VM86_FREE_IRQ: |
245 | case VM86_GET_IRQ_BITS: | 244 | case VM86_GET_IRQ_BITS: |
246 | case VM86_GET_AND_RESET_IRQ: | 245 | case VM86_GET_AND_RESET_IRQ: |
247 | ret = do_vm86_irq_handling(regs->bx, (int)regs->cx); | 246 | ret = do_vm86_irq_handling(cmd, (int)arg); |
248 | goto out; | 247 | goto out; |
249 | case VM86_PLUS_INSTALL_CHECK: | 248 | case VM86_PLUS_INSTALL_CHECK: |
250 | /* | 249 | /* |
@@ -261,7 +260,7 @@ int sys_vm86(struct pt_regs *regs) | |||
261 | ret = -EPERM; | 260 | ret = -EPERM; |
262 | if (tsk->thread.saved_sp0) | 261 | if (tsk->thread.saved_sp0) |
263 | goto out; | 262 | goto out; |
264 | v86 = (struct vm86plus_struct __user *)regs->cx; | 263 | v86 = (struct vm86plus_struct __user *)arg; |
265 | tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, | 264 | tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, |
266 | offsetof(struct kernel_vm86_struct, regs32) - | 265 | offsetof(struct kernel_vm86_struct, regs32) - |
267 | sizeof(info.regs)); | 266 | sizeof(info.regs)); |
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index f3f2104408d9..f92a0da608cb 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S | |||
@@ -319,9 +319,7 @@ SECTIONS | |||
319 | __brk_limit = .; | 319 | __brk_limit = .; |
320 | } | 320 | } |
321 | 321 | ||
322 | .end : AT(ADDR(.end) - LOAD_OFFSET) { | 322 | _end = .; |
323 | _end = .; | ||
324 | } | ||
325 | 323 | ||
326 | STABS_DEBUG | 324 | STABS_DEBUG |
327 | DWARF_DEBUG | 325 | DWARF_DEBUG |
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index 084c1adc45f5..619f7f88b8cc 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c | |||
@@ -17,8 +17,6 @@ | |||
17 | EXPORT_SYMBOL(mcount); | 17 | EXPORT_SYMBOL(mcount); |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | EXPORT_SYMBOL(kernel_thread); | ||
21 | |||
22 | EXPORT_SYMBOL(__get_user_1); | 20 | EXPORT_SYMBOL(__get_user_1); |
23 | EXPORT_SYMBOL(__get_user_2); | 21 | EXPORT_SYMBOL(__get_user_2); |
24 | EXPORT_SYMBOL(__get_user_4); | 22 | EXPORT_SYMBOL(__get_user_4); |
diff --git a/arch/x86/tools/gen-insn-attr-x86.awk b/arch/x86/tools/gen-insn-attr-x86.awk index e34e92a28eb6..7a6850683c34 100644 --- a/arch/x86/tools/gen-insn-attr-x86.awk +++ b/arch/x86/tools/gen-insn-attr-x86.awk | |||
@@ -226,12 +226,12 @@ function add_flags(old,new) { | |||
226 | } | 226 | } |
227 | 227 | ||
228 | # convert operands to flags. | 228 | # convert operands to flags. |
229 | function convert_operands(opnd, i,imm,mod) | 229 | function convert_operands(count,opnd, i,j,imm,mod) |
230 | { | 230 | { |
231 | imm = null | 231 | imm = null |
232 | mod = null | 232 | mod = null |
233 | for (i in opnd) { | 233 | for (j = 1; j <= count; j++) { |
234 | i = opnd[i] | 234 | i = opnd[j] |
235 | if (match(i, imm_expr) == 1) { | 235 | if (match(i, imm_expr) == 1) { |
236 | if (!imm_flag[i]) | 236 | if (!imm_flag[i]) |
237 | semantic_error("Unknown imm opnd: " i) | 237 | semantic_error("Unknown imm opnd: " i) |
@@ -282,8 +282,8 @@ function convert_operands(opnd, i,imm,mod) | |||
282 | # parse one opcode | 282 | # parse one opcode |
283 | if (match($i, opnd_expr)) { | 283 | if (match($i, opnd_expr)) { |
284 | opnd = $i | 284 | opnd = $i |
285 | split($(i++), opnds, ",") | 285 | count = split($(i++), opnds, ",") |
286 | flags = convert_operands(opnds) | 286 | flags = convert_operands(count, opnds) |
287 | } | 287 | } |
288 | if (match($i, ext_expr)) | 288 | if (match($i, ext_expr)) |
289 | ext = $(i++) | 289 | ext = $(i++) |