diff options
author | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2009-02-11 14:52:22 -0500 |
---|---|---|
committer | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2009-02-11 14:52:22 -0500 |
commit | 9049a11de73d3ecc623f1903100d099f82ede56c (patch) | |
tree | c03d130d58168e337a66fe999682452b7a02b42b /arch/x86/include | |
parent | c47c1b1f3a9d6973108020df1dcab7604f7774dd (diff) | |
parent | e4d0407185cdbdcfd99fc23bde2e5454bbc46329 (diff) |
Merge commit 'remotes/tip/x86/paravirt' into x86/untangle2
* commit 'remotes/tip/x86/paravirt': (175 commits)
xen: use direct ops on 64-bit
xen: make direct versions of irq_enable/disable/save/restore to common code
xen: setup percpu data pointers
xen: fix 32-bit build resulting from mmu move
x86/paravirt: return full 64-bit result
x86, percpu: fix kexec with vmlinux
x86/vmi: fix interrupt enable/disable/save/restore calling convention.
x86/paravirt: don't restore second return reg
xen: setup percpu data pointers
x86: split loading percpu segments from loading gdt
x86: pass in cpu number to switch_to_new_gdt()
x86: UV fix uv_flush_send_and_wait()
x86/paravirt: fix missing callee-save call on pud_val
x86/paravirt: use callee-saved convention for pte_val/make_pte/etc
x86/paravirt: implement PVOP_CALL macros for callee-save functions
x86/paravirt: add register-saving thunks to reduce caller register pressure
x86/paravirt: selectively save/restore regs around pvops calls
x86: fix paravirt clobber in entry_64.S
x86/pvops: add a paravirt_ident functions to allow special patching
xen: move remaining mmu-related stuff into mmu.c
...
Conflicts:
arch/x86/mach-voyager/voyager_smp.c
arch/x86/mm/fault.c
Diffstat (limited to 'arch/x86/include')
37 files changed, 807 insertions, 787 deletions
diff --git a/arch/x86/include/asm/apicnum.h b/arch/x86/include/asm/apicnum.h new file mode 100644 index 000000000000..82f613c607ce --- /dev/null +++ b/arch/x86/include/asm/apicnum.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _ASM_X86_APICNUM_H | ||
2 | #define _ASM_X86_APICNUM_H | ||
3 | |||
4 | /* define MAX_IO_APICS */ | ||
5 | #ifdef CONFIG_X86_32 | ||
6 | # define MAX_IO_APICS 64 | ||
7 | #else | ||
8 | # define MAX_IO_APICS 128 | ||
9 | # define MAX_LOCAL_APIC 32768 | ||
10 | #endif | ||
11 | |||
12 | #endif /* _ASM_X86_APICNUM_H */ | ||
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index bae482df6039..f03b23e32864 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h | |||
@@ -7,6 +7,20 @@ | |||
7 | #include <linux/nodemask.h> | 7 | #include <linux/nodemask.h> |
8 | #include <linux/percpu.h> | 8 | #include <linux/percpu.h> |
9 | 9 | ||
10 | #ifdef CONFIG_SMP | ||
11 | |||
12 | extern void prefill_possible_map(void); | ||
13 | |||
14 | #else /* CONFIG_SMP */ | ||
15 | |||
16 | static inline void prefill_possible_map(void) {} | ||
17 | |||
18 | #define cpu_physical_id(cpu) boot_cpu_physical_apicid | ||
19 | #define safe_smp_processor_id() 0 | ||
20 | #define stack_smp_processor_id() 0 | ||
21 | |||
22 | #endif /* CONFIG_SMP */ | ||
23 | |||
10 | struct x86_cpu { | 24 | struct x86_cpu { |
11 | struct cpu cpu; | 25 | struct cpu cpu; |
12 | }; | 26 | }; |
@@ -17,4 +31,11 @@ extern void arch_unregister_cpu(int); | |||
17 | #endif | 31 | #endif |
18 | 32 | ||
19 | DECLARE_PER_CPU(int, cpu_state); | 33 | DECLARE_PER_CPU(int, cpu_state); |
34 | |||
35 | #ifdef CONFIG_X86_HAS_BOOT_CPU_ID | ||
36 | extern unsigned char boot_cpu_id; | ||
37 | #else | ||
38 | #define boot_cpu_id 0 | ||
39 | #endif | ||
40 | |||
20 | #endif /* _ASM_X86_CPU_H */ | 41 | #endif /* _ASM_X86_CPU_H */ |
diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h new file mode 100644 index 000000000000..a7f3c75f8ad7 --- /dev/null +++ b/arch/x86/include/asm/cpumask.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef _ASM_X86_CPUMASK_H | ||
2 | #define _ASM_X86_CPUMASK_H | ||
3 | #ifndef __ASSEMBLY__ | ||
4 | #include <linux/cpumask.h> | ||
5 | |||
6 | #ifdef CONFIG_X86_64 | ||
7 | |||
8 | extern cpumask_var_t cpu_callin_mask; | ||
9 | extern cpumask_var_t cpu_callout_mask; | ||
10 | extern cpumask_var_t cpu_initialized_mask; | ||
11 | extern cpumask_var_t cpu_sibling_setup_mask; | ||
12 | |||
13 | extern void setup_cpu_local_masks(void); | ||
14 | |||
15 | #else /* CONFIG_X86_32 */ | ||
16 | |||
17 | extern cpumask_t cpu_callin_map; | ||
18 | extern cpumask_t cpu_callout_map; | ||
19 | extern cpumask_t cpu_initialized; | ||
20 | extern cpumask_t cpu_sibling_setup_map; | ||
21 | |||
22 | #define cpu_callin_mask ((struct cpumask *)&cpu_callin_map) | ||
23 | #define cpu_callout_mask ((struct cpumask *)&cpu_callout_map) | ||
24 | #define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) | ||
25 | #define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) | ||
26 | |||
27 | static inline void setup_cpu_local_masks(void) { } | ||
28 | |||
29 | #endif /* CONFIG_X86_32 */ | ||
30 | |||
31 | #endif /* __ASSEMBLY__ */ | ||
32 | #endif /* _ASM_X86_CPUMASK_H */ | ||
diff --git a/arch/x86/include/asm/current.h b/arch/x86/include/asm/current.h index 0930b4f8d672..c68c361697e1 100644 --- a/arch/x86/include/asm/current.h +++ b/arch/x86/include/asm/current.h | |||
@@ -1,39 +1,21 @@ | |||
1 | #ifndef _ASM_X86_CURRENT_H | 1 | #ifndef _ASM_X86_CURRENT_H |
2 | #define _ASM_X86_CURRENT_H | 2 | #define _ASM_X86_CURRENT_H |
3 | 3 | ||
4 | #ifdef CONFIG_X86_32 | ||
5 | #include <linux/compiler.h> | 4 | #include <linux/compiler.h> |
6 | #include <asm/percpu.h> | 5 | #include <asm/percpu.h> |
7 | 6 | ||
7 | #ifndef __ASSEMBLY__ | ||
8 | struct task_struct; | 8 | struct task_struct; |
9 | 9 | ||
10 | DECLARE_PER_CPU(struct task_struct *, current_task); | 10 | DECLARE_PER_CPU(struct task_struct *, current_task); |
11 | static __always_inline struct task_struct *get_current(void) | ||
12 | { | ||
13 | return x86_read_percpu(current_task); | ||
14 | } | ||
15 | |||
16 | #else /* X86_32 */ | ||
17 | |||
18 | #ifndef __ASSEMBLY__ | ||
19 | #include <asm/pda.h> | ||
20 | |||
21 | struct task_struct; | ||
22 | 11 | ||
23 | static __always_inline struct task_struct *get_current(void) | 12 | static __always_inline struct task_struct *get_current(void) |
24 | { | 13 | { |
25 | return read_pda(pcurrent); | 14 | return percpu_read(current_task); |
26 | } | 15 | } |
27 | 16 | ||
28 | #else /* __ASSEMBLY__ */ | 17 | #define current get_current() |
29 | |||
30 | #include <asm/asm-offsets.h> | ||
31 | #define GET_CURRENT(reg) movq %gs:(pda_pcurrent),reg | ||
32 | 18 | ||
33 | #endif /* __ASSEMBLY__ */ | 19 | #endif /* __ASSEMBLY__ */ |
34 | 20 | ||
35 | #endif /* X86_32 */ | ||
36 | |||
37 | #define current get_current() | ||
38 | |||
39 | #endif /* _ASM_X86_CURRENT_H */ | 21 | #endif /* _ASM_X86_CURRENT_H */ |
diff --git a/arch/x86/include/asm/genapic_32.h b/arch/x86/include/asm/genapic_32.h index 2c05b737ee22..4334502d3664 100644 --- a/arch/x86/include/asm/genapic_32.h +++ b/arch/x86/include/asm/genapic_32.h | |||
@@ -138,11 +138,4 @@ struct genapic { | |||
138 | extern struct genapic *genapic; | 138 | extern struct genapic *genapic; |
139 | extern void es7000_update_genapic_to_cluster(void); | 139 | extern void es7000_update_genapic_to_cluster(void); |
140 | 140 | ||
141 | enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; | ||
142 | #define get_uv_system_type() UV_NONE | ||
143 | #define is_uv_system() 0 | ||
144 | #define uv_wakeup_secondary(a, b) 1 | ||
145 | #define uv_system_init() do {} while (0) | ||
146 | |||
147 | |||
148 | #endif /* _ASM_X86_GENAPIC_32_H */ | 141 | #endif /* _ASM_X86_GENAPIC_32_H */ |
diff --git a/arch/x86/include/asm/genapic_64.h b/arch/x86/include/asm/genapic_64.h index adf32fb56aa6..7bb092c59055 100644 --- a/arch/x86/include/asm/genapic_64.h +++ b/arch/x86/include/asm/genapic_64.h | |||
@@ -51,15 +51,9 @@ extern struct genapic apic_x2apic_phys; | |||
51 | extern int acpi_madt_oem_check(char *, char *); | 51 | extern int acpi_madt_oem_check(char *, char *); |
52 | 52 | ||
53 | extern void apic_send_IPI_self(int vector); | 53 | extern void apic_send_IPI_self(int vector); |
54 | enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; | ||
55 | extern enum uv_system_type get_uv_system_type(void); | ||
56 | extern int is_uv_system(void); | ||
57 | 54 | ||
58 | extern struct genapic apic_x2apic_uv_x; | 55 | extern struct genapic apic_x2apic_uv_x; |
59 | DECLARE_PER_CPU(int, x2apic_extra_bits); | 56 | DECLARE_PER_CPU(int, x2apic_extra_bits); |
60 | extern void uv_cpu_init(void); | ||
61 | extern void uv_system_init(void); | ||
62 | extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); | ||
63 | 57 | ||
64 | extern void setup_apic_routing(void); | 58 | extern void setup_apic_routing(void); |
65 | 59 | ||
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 000787df66e6..176f058e7159 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
@@ -1,11 +1,52 @@ | |||
1 | #ifdef CONFIG_X86_32 | 1 | #ifndef _ASM_X86_HARDIRQ_H |
2 | # include "hardirq_32.h" | 2 | #define _ASM_X86_HARDIRQ_H |
3 | #else | 3 | |
4 | # include "hardirq_64.h" | 4 | #include <linux/threads.h> |
5 | #include <linux/irq.h> | ||
6 | |||
7 | typedef struct { | ||
8 | unsigned int __softirq_pending; | ||
9 | unsigned int __nmi_count; /* arch dependent */ | ||
10 | unsigned int irq0_irqs; | ||
11 | #ifdef CONFIG_X86_LOCAL_APIC | ||
12 | unsigned int apic_timer_irqs; /* arch dependent */ | ||
13 | unsigned int irq_spurious_count; | ||
14 | #endif | ||
15 | #ifdef CONFIG_SMP | ||
16 | unsigned int irq_resched_count; | ||
17 | unsigned int irq_call_count; | ||
18 | unsigned int irq_tlb_count; | ||
19 | #endif | ||
20 | #ifdef CONFIG_X86_MCE | ||
21 | unsigned int irq_thermal_count; | ||
22 | # ifdef CONFIG_X86_64 | ||
23 | unsigned int irq_threshold_count; | ||
24 | # endif | ||
5 | #endif | 25 | #endif |
26 | } ____cacheline_aligned irq_cpustat_t; | ||
27 | |||
28 | DECLARE_PER_CPU(irq_cpustat_t, irq_stat); | ||
29 | |||
30 | /* We can have at most NR_VECTORS irqs routed to a cpu at a time */ | ||
31 | #define MAX_HARDIRQS_PER_CPU NR_VECTORS | ||
32 | |||
33 | #define __ARCH_IRQ_STAT | ||
34 | |||
35 | #define inc_irq_stat(member) percpu_add(irq_stat.member, 1) | ||
36 | |||
37 | #define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) | ||
38 | |||
39 | #define __ARCH_SET_SOFTIRQ_PENDING | ||
40 | |||
41 | #define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x)) | ||
42 | #define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) | ||
43 | |||
44 | extern void ack_bad_irq(unsigned int irq); | ||
6 | 45 | ||
7 | extern u64 arch_irq_stat_cpu(unsigned int cpu); | 46 | extern u64 arch_irq_stat_cpu(unsigned int cpu); |
8 | #define arch_irq_stat_cpu arch_irq_stat_cpu | 47 | #define arch_irq_stat_cpu arch_irq_stat_cpu |
9 | 48 | ||
10 | extern u64 arch_irq_stat(void); | 49 | extern u64 arch_irq_stat(void); |
11 | #define arch_irq_stat arch_irq_stat | 50 | #define arch_irq_stat arch_irq_stat |
51 | |||
52 | #endif /* _ASM_X86_HARDIRQ_H */ | ||
diff --git a/arch/x86/include/asm/hardirq_32.h b/arch/x86/include/asm/hardirq_32.h deleted file mode 100644 index cf7954d1405f..000000000000 --- a/arch/x86/include/asm/hardirq_32.h +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | #ifndef _ASM_X86_HARDIRQ_32_H | ||
2 | #define _ASM_X86_HARDIRQ_32_H | ||
3 | |||
4 | #include <linux/threads.h> | ||
5 | #include <linux/irq.h> | ||
6 | |||
7 | typedef struct { | ||
8 | unsigned int __softirq_pending; | ||
9 | unsigned long idle_timestamp; | ||
10 | unsigned int __nmi_count; /* arch dependent */ | ||
11 | unsigned int apic_timer_irqs; /* arch dependent */ | ||
12 | unsigned int irq0_irqs; | ||
13 | unsigned int irq_resched_count; | ||
14 | unsigned int irq_call_count; | ||
15 | unsigned int irq_tlb_count; | ||
16 | unsigned int irq_thermal_count; | ||
17 | unsigned int irq_spurious_count; | ||
18 | } ____cacheline_aligned irq_cpustat_t; | ||
19 | |||
20 | DECLARE_PER_CPU(irq_cpustat_t, irq_stat); | ||
21 | |||
22 | #define __ARCH_IRQ_STAT | ||
23 | #define __IRQ_STAT(cpu, member) (per_cpu(irq_stat, cpu).member) | ||
24 | |||
25 | #define inc_irq_stat(member) (__get_cpu_var(irq_stat).member++) | ||
26 | |||
27 | void ack_bad_irq(unsigned int irq); | ||
28 | #include <linux/irq_cpustat.h> | ||
29 | |||
30 | #endif /* _ASM_X86_HARDIRQ_32_H */ | ||
diff --git a/arch/x86/include/asm/hardirq_64.h b/arch/x86/include/asm/hardirq_64.h deleted file mode 100644 index b5a6b5d56704..000000000000 --- a/arch/x86/include/asm/hardirq_64.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | #ifndef _ASM_X86_HARDIRQ_64_H | ||
2 | #define _ASM_X86_HARDIRQ_64_H | ||
3 | |||
4 | #include <linux/threads.h> | ||
5 | #include <linux/irq.h> | ||
6 | #include <asm/pda.h> | ||
7 | #include <asm/apic.h> | ||
8 | |||
9 | /* We can have at most NR_VECTORS irqs routed to a cpu at a time */ | ||
10 | #define MAX_HARDIRQS_PER_CPU NR_VECTORS | ||
11 | |||
12 | #define __ARCH_IRQ_STAT 1 | ||
13 | |||
14 | #define inc_irq_stat(member) add_pda(member, 1) | ||
15 | |||
16 | #define local_softirq_pending() read_pda(__softirq_pending) | ||
17 | |||
18 | #define __ARCH_SET_SOFTIRQ_PENDING 1 | ||
19 | |||
20 | #define set_softirq_pending(x) write_pda(__softirq_pending, (x)) | ||
21 | #define or_softirq_pending(x) or_pda(__softirq_pending, (x)) | ||
22 | |||
23 | extern void ack_bad_irq(unsigned int irq); | ||
24 | |||
25 | #endif /* _ASM_X86_HARDIRQ_64_H */ | ||
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 7a1f44ac1f17..08ec793aa043 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -114,38 +114,16 @@ struct IR_IO_APIC_route_entry { | |||
114 | extern int nr_ioapics; | 114 | extern int nr_ioapics; |
115 | extern int nr_ioapic_registers[MAX_IO_APICS]; | 115 | extern int nr_ioapic_registers[MAX_IO_APICS]; |
116 | 116 | ||
117 | /* | ||
118 | * MP-BIOS irq configuration table structures: | ||
119 | */ | ||
120 | |||
121 | #define MP_MAX_IOAPIC_PIN 127 | 117 | #define MP_MAX_IOAPIC_PIN 127 |
122 | 118 | ||
123 | struct mp_config_ioapic { | ||
124 | unsigned long mp_apicaddr; | ||
125 | unsigned int mp_apicid; | ||
126 | unsigned char mp_type; | ||
127 | unsigned char mp_apicver; | ||
128 | unsigned char mp_flags; | ||
129 | }; | ||
130 | |||
131 | struct mp_config_intsrc { | ||
132 | unsigned int mp_dstapic; | ||
133 | unsigned char mp_type; | ||
134 | unsigned char mp_irqtype; | ||
135 | unsigned short mp_irqflag; | ||
136 | unsigned char mp_srcbus; | ||
137 | unsigned char mp_srcbusirq; | ||
138 | unsigned char mp_dstirq; | ||
139 | }; | ||
140 | |||
141 | /* I/O APIC entries */ | 119 | /* I/O APIC entries */ |
142 | extern struct mp_config_ioapic mp_ioapics[MAX_IO_APICS]; | 120 | extern struct mpc_ioapic mp_ioapics[MAX_IO_APICS]; |
143 | 121 | ||
144 | /* # of MP IRQ source entries */ | 122 | /* # of MP IRQ source entries */ |
145 | extern int mp_irq_entries; | 123 | extern int mp_irq_entries; |
146 | 124 | ||
147 | /* MP IRQ source entries */ | 125 | /* MP IRQ source entries */ |
148 | extern struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; | 126 | extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; |
149 | 127 | ||
150 | /* non-0 if default (table-less) MP configuration */ | 128 | /* non-0 if default (table-less) MP configuration */ |
151 | extern int mpc_default_type; | 129 | extern int mpc_default_type; |
diff --git a/arch/x86/include/asm/irq_regs.h b/arch/x86/include/asm/irq_regs.h index 89c898ab298b..77843225b7ea 100644 --- a/arch/x86/include/asm/irq_regs.h +++ b/arch/x86/include/asm/irq_regs.h | |||
@@ -1,5 +1,31 @@ | |||
1 | #ifdef CONFIG_X86_32 | 1 | /* |
2 | # include "irq_regs_32.h" | 2 | * Per-cpu current frame pointer - the location of the last exception frame on |
3 | #else | 3 | * the stack, stored in the per-cpu area. |
4 | # include "irq_regs_64.h" | 4 | * |
5 | #endif | 5 | * Jeremy Fitzhardinge <jeremy@goop.org> |
6 | */ | ||
7 | #ifndef _ASM_X86_IRQ_REGS_H | ||
8 | #define _ASM_X86_IRQ_REGS_H | ||
9 | |||
10 | #include <asm/percpu.h> | ||
11 | |||
12 | #define ARCH_HAS_OWN_IRQ_REGS | ||
13 | |||
14 | DECLARE_PER_CPU(struct pt_regs *, irq_regs); | ||
15 | |||
16 | static inline struct pt_regs *get_irq_regs(void) | ||
17 | { | ||
18 | return percpu_read(irq_regs); | ||
19 | } | ||
20 | |||
21 | static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) | ||
22 | { | ||
23 | struct pt_regs *old_regs; | ||
24 | |||
25 | old_regs = get_irq_regs(); | ||
26 | percpu_write(irq_regs, new_regs); | ||
27 | |||
28 | return old_regs; | ||
29 | } | ||
30 | |||
31 | #endif /* _ASM_X86_IRQ_REGS_32_H */ | ||
diff --git a/arch/x86/include/asm/irq_regs_32.h b/arch/x86/include/asm/irq_regs_32.h deleted file mode 100644 index 86afd7473457..000000000000 --- a/arch/x86/include/asm/irq_regs_32.h +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | /* | ||
2 | * Per-cpu current frame pointer - the location of the last exception frame on | ||
3 | * the stack, stored in the per-cpu area. | ||
4 | * | ||
5 | * Jeremy Fitzhardinge <jeremy@goop.org> | ||
6 | */ | ||
7 | #ifndef _ASM_X86_IRQ_REGS_32_H | ||
8 | #define _ASM_X86_IRQ_REGS_32_H | ||
9 | |||
10 | #include <asm/percpu.h> | ||
11 | |||
12 | #define ARCH_HAS_OWN_IRQ_REGS | ||
13 | |||
14 | DECLARE_PER_CPU(struct pt_regs *, irq_regs); | ||
15 | |||
16 | static inline struct pt_regs *get_irq_regs(void) | ||
17 | { | ||
18 | return x86_read_percpu(irq_regs); | ||
19 | } | ||
20 | |||
21 | static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) | ||
22 | { | ||
23 | struct pt_regs *old_regs; | ||
24 | |||
25 | old_regs = get_irq_regs(); | ||
26 | x86_write_percpu(irq_regs, new_regs); | ||
27 | |||
28 | return old_regs; | ||
29 | } | ||
30 | |||
31 | #endif /* _ASM_X86_IRQ_REGS_32_H */ | ||
diff --git a/arch/x86/include/asm/irq_regs_64.h b/arch/x86/include/asm/irq_regs_64.h deleted file mode 100644 index 3dd9c0b70270..000000000000 --- a/arch/x86/include/asm/irq_regs_64.h +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | #include <asm-generic/irq_regs.h> | ||
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index f7ff65032b9d..9a83a10a5d51 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
@@ -49,31 +49,33 @@ | |||
49 | * some of the following vectors are 'rare', they are merged | 49 | * some of the following vectors are 'rare', they are merged |
50 | * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. | 50 | * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. |
51 | * TLB, reschedule and local APIC vectors are performance-critical. | 51 | * TLB, reschedule and local APIC vectors are performance-critical. |
52 | * | ||
53 | * Vectors 0xf0-0xfa are free (reserved for future Linux use). | ||
54 | */ | 52 | */ |
55 | #ifdef CONFIG_X86_32 | 53 | #ifdef CONFIG_X86_32 |
56 | 54 | ||
57 | # define SPURIOUS_APIC_VECTOR 0xff | 55 | # define SPURIOUS_APIC_VECTOR 0xff |
58 | # define ERROR_APIC_VECTOR 0xfe | 56 | # define ERROR_APIC_VECTOR 0xfe |
59 | # define INVALIDATE_TLB_VECTOR 0xfd | 57 | # define RESCHEDULE_VECTOR 0xfd |
60 | # define RESCHEDULE_VECTOR 0xfc | 58 | # define CALL_FUNCTION_VECTOR 0xfc |
61 | # define CALL_FUNCTION_VECTOR 0xfb | 59 | # define CALL_FUNCTION_SINGLE_VECTOR 0xfb |
62 | # define CALL_FUNCTION_SINGLE_VECTOR 0xfa | 60 | # define THERMAL_APIC_VECTOR 0xfa |
63 | # define THERMAL_APIC_VECTOR 0xf0 | 61 | /* 0xf8 - 0xf9 : free */ |
62 | # define INVALIDATE_TLB_VECTOR_END 0xf7 | ||
63 | # define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */ | ||
64 | |||
65 | # define NUM_INVALIDATE_TLB_VECTORS 8 | ||
64 | 66 | ||
65 | #else | 67 | #else |
66 | 68 | ||
67 | #define SPURIOUS_APIC_VECTOR 0xff | 69 | # define SPURIOUS_APIC_VECTOR 0xff |
68 | #define ERROR_APIC_VECTOR 0xfe | 70 | # define ERROR_APIC_VECTOR 0xfe |
69 | #define RESCHEDULE_VECTOR 0xfd | 71 | # define RESCHEDULE_VECTOR 0xfd |
70 | #define CALL_FUNCTION_VECTOR 0xfc | 72 | # define CALL_FUNCTION_VECTOR 0xfc |
71 | #define CALL_FUNCTION_SINGLE_VECTOR 0xfb | 73 | # define CALL_FUNCTION_SINGLE_VECTOR 0xfb |
72 | #define THERMAL_APIC_VECTOR 0xfa | 74 | # define THERMAL_APIC_VECTOR 0xfa |
73 | #define THRESHOLD_APIC_VECTOR 0xf9 | 75 | # define THRESHOLD_APIC_VECTOR 0xf9 |
74 | #define UV_BAU_MESSAGE 0xf8 | 76 | # define UV_BAU_MESSAGE 0xf8 |
75 | #define INVALIDATE_TLB_VECTOR_END 0xf7 | 77 | # define INVALIDATE_TLB_VECTOR_END 0xf7 |
76 | #define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */ | 78 | # define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */ |
77 | 79 | ||
78 | #define NUM_INVALIDATE_TLB_VECTORS 8 | 80 | #define NUM_INVALIDATE_TLB_VECTORS 8 |
79 | 81 | ||
@@ -105,6 +107,8 @@ | |||
105 | 107 | ||
106 | #if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_VOYAGER) | 108 | #if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_VOYAGER) |
107 | 109 | ||
110 | #include <asm/apicnum.h> /* need MAX_IO_APICS */ | ||
111 | |||
108 | #ifndef CONFIG_SPARSE_IRQ | 112 | #ifndef CONFIG_SPARSE_IRQ |
109 | # if NR_CPUS < MAX_IO_APICS | 113 | # if NR_CPUS < MAX_IO_APICS |
110 | # define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) | 114 | # define NR_IRQS (NR_VECTORS + (32 * NR_CPUS)) |
@@ -112,11 +116,12 @@ | |||
112 | # define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) | 116 | # define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) |
113 | # endif | 117 | # endif |
114 | #else | 118 | #else |
115 | # if (8 * NR_CPUS) > (32 * MAX_IO_APICS) | 119 | |
116 | # define NR_IRQS (NR_VECTORS + (8 * NR_CPUS)) | 120 | # define NR_IRQS \ |
117 | # else | 121 | ((8 * NR_CPUS) > (32 * MAX_IO_APICS) ? \ |
118 | # define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS)) | 122 | (NR_VECTORS + (8 * NR_CPUS)) : \ |
119 | # endif | 123 | (NR_VECTORS + (32 * MAX_IO_APICS))) \ |
124 | |||
120 | #endif | 125 | #endif |
121 | 126 | ||
122 | #elif defined(CONFIG_X86_VOYAGER) | 127 | #elif defined(CONFIG_X86_VOYAGER) |
diff --git a/arch/x86/include/asm/mach-default/entry_arch.h b/arch/x86/include/asm/mach-default/entry_arch.h index 6b1add8e31dd..6fa399ad1de2 100644 --- a/arch/x86/include/asm/mach-default/entry_arch.h +++ b/arch/x86/include/asm/mach-default/entry_arch.h | |||
@@ -11,10 +11,26 @@ | |||
11 | */ | 11 | */ |
12 | #ifdef CONFIG_X86_SMP | 12 | #ifdef CONFIG_X86_SMP |
13 | BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) | 13 | BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) |
14 | BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR) | ||
15 | BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) | 14 | BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) |
16 | BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) | 15 | BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) |
17 | BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR) | 16 | BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR) |
17 | |||
18 | BUILD_INTERRUPT3(invalidate_interrupt0,INVALIDATE_TLB_VECTOR_START+0, | ||
19 | smp_invalidate_interrupt) | ||
20 | BUILD_INTERRUPT3(invalidate_interrupt1,INVALIDATE_TLB_VECTOR_START+1, | ||
21 | smp_invalidate_interrupt) | ||
22 | BUILD_INTERRUPT3(invalidate_interrupt2,INVALIDATE_TLB_VECTOR_START+2, | ||
23 | smp_invalidate_interrupt) | ||
24 | BUILD_INTERRUPT3(invalidate_interrupt3,INVALIDATE_TLB_VECTOR_START+3, | ||
25 | smp_invalidate_interrupt) | ||
26 | BUILD_INTERRUPT3(invalidate_interrupt4,INVALIDATE_TLB_VECTOR_START+4, | ||
27 | smp_invalidate_interrupt) | ||
28 | BUILD_INTERRUPT3(invalidate_interrupt5,INVALIDATE_TLB_VECTOR_START+5, | ||
29 | smp_invalidate_interrupt) | ||
30 | BUILD_INTERRUPT3(invalidate_interrupt6,INVALIDATE_TLB_VECTOR_START+6, | ||
31 | smp_invalidate_interrupt) | ||
32 | BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7, | ||
33 | smp_invalidate_interrupt) | ||
18 | #endif | 34 | #endif |
19 | 35 | ||
20 | /* | 36 | /* |
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 8aeeb3fd73db..52948df9cd1d 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h | |||
@@ -21,11 +21,54 @@ static inline void paravirt_activate_mm(struct mm_struct *prev, | |||
21 | int init_new_context(struct task_struct *tsk, struct mm_struct *mm); | 21 | int init_new_context(struct task_struct *tsk, struct mm_struct *mm); |
22 | void destroy_context(struct mm_struct *mm); | 22 | void destroy_context(struct mm_struct *mm); |
23 | 23 | ||
24 | #ifdef CONFIG_X86_32 | 24 | |
25 | # include "mmu_context_32.h" | 25 | static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) |
26 | #else | 26 | { |
27 | # include "mmu_context_64.h" | 27 | #ifdef CONFIG_SMP |
28 | if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) | ||
29 | percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); | ||
30 | #endif | ||
31 | } | ||
32 | |||
33 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | ||
34 | struct task_struct *tsk) | ||
35 | { | ||
36 | unsigned cpu = smp_processor_id(); | ||
37 | |||
38 | if (likely(prev != next)) { | ||
39 | /* stop flush ipis for the previous mm */ | ||
40 | cpu_clear(cpu, prev->cpu_vm_mask); | ||
41 | #ifdef CONFIG_SMP | ||
42 | percpu_write(cpu_tlbstate.state, TLBSTATE_OK); | ||
43 | percpu_write(cpu_tlbstate.active_mm, next); | ||
28 | #endif | 44 | #endif |
45 | cpu_set(cpu, next->cpu_vm_mask); | ||
46 | |||
47 | /* Re-load page tables */ | ||
48 | load_cr3(next->pgd); | ||
49 | |||
50 | /* | ||
51 | * load the LDT, if the LDT is different: | ||
52 | */ | ||
53 | if (unlikely(prev->context.ldt != next->context.ldt)) | ||
54 | load_LDT_nolock(&next->context); | ||
55 | } | ||
56 | #ifdef CONFIG_SMP | ||
57 | else { | ||
58 | percpu_write(cpu_tlbstate.state, TLBSTATE_OK); | ||
59 | BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next); | ||
60 | |||
61 | if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { | ||
62 | /* We were in lazy tlb mode and leave_mm disabled | ||
63 | * tlb flush IPI delivery. We must reload CR3 | ||
64 | * to make sure to use no freed page tables. | ||
65 | */ | ||
66 | load_cr3(next->pgd); | ||
67 | load_LDT_nolock(&next->context); | ||
68 | } | ||
69 | } | ||
70 | #endif | ||
71 | } | ||
29 | 72 | ||
30 | #define activate_mm(prev, next) \ | 73 | #define activate_mm(prev, next) \ |
31 | do { \ | 74 | do { \ |
@@ -33,5 +76,17 @@ do { \ | |||
33 | switch_mm((prev), (next), NULL); \ | 76 | switch_mm((prev), (next), NULL); \ |
34 | } while (0); | 77 | } while (0); |
35 | 78 | ||
79 | #ifdef CONFIG_X86_32 | ||
80 | #define deactivate_mm(tsk, mm) \ | ||
81 | do { \ | ||
82 | loadsegment(gs, 0); \ | ||
83 | } while (0) | ||
84 | #else | ||
85 | #define deactivate_mm(tsk, mm) \ | ||
86 | do { \ | ||
87 | load_gs_index(0); \ | ||
88 | loadsegment(fs, 0); \ | ||
89 | } while (0) | ||
90 | #endif | ||
36 | 91 | ||
37 | #endif /* _ASM_X86_MMU_CONTEXT_H */ | 92 | #endif /* _ASM_X86_MMU_CONTEXT_H */ |
diff --git a/arch/x86/include/asm/mmu_context_32.h b/arch/x86/include/asm/mmu_context_32.h deleted file mode 100644 index 7e98ce1d2c0e..000000000000 --- a/arch/x86/include/asm/mmu_context_32.h +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | #ifndef _ASM_X86_MMU_CONTEXT_32_H | ||
2 | #define _ASM_X86_MMU_CONTEXT_32_H | ||
3 | |||
4 | static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | ||
5 | { | ||
6 | #ifdef CONFIG_SMP | ||
7 | if (x86_read_percpu(cpu_tlbstate.state) == TLBSTATE_OK) | ||
8 | x86_write_percpu(cpu_tlbstate.state, TLBSTATE_LAZY); | ||
9 | #endif | ||
10 | } | ||
11 | |||
12 | static inline void switch_mm(struct mm_struct *prev, | ||
13 | struct mm_struct *next, | ||
14 | struct task_struct *tsk) | ||
15 | { | ||
16 | int cpu = smp_processor_id(); | ||
17 | |||
18 | if (likely(prev != next)) { | ||
19 | /* stop flush ipis for the previous mm */ | ||
20 | cpu_clear(cpu, prev->cpu_vm_mask); | ||
21 | #ifdef CONFIG_SMP | ||
22 | x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK); | ||
23 | x86_write_percpu(cpu_tlbstate.active_mm, next); | ||
24 | #endif | ||
25 | cpu_set(cpu, next->cpu_vm_mask); | ||
26 | |||
27 | /* Re-load page tables */ | ||
28 | load_cr3(next->pgd); | ||
29 | |||
30 | /* | ||
31 | * load the LDT, if the LDT is different: | ||
32 | */ | ||
33 | if (unlikely(prev->context.ldt != next->context.ldt)) | ||
34 | load_LDT_nolock(&next->context); | ||
35 | } | ||
36 | #ifdef CONFIG_SMP | ||
37 | else { | ||
38 | x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK); | ||
39 | BUG_ON(x86_read_percpu(cpu_tlbstate.active_mm) != next); | ||
40 | |||
41 | if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { | ||
42 | /* We were in lazy tlb mode and leave_mm disabled | ||
43 | * tlb flush IPI delivery. We must reload %cr3. | ||
44 | */ | ||
45 | load_cr3(next->pgd); | ||
46 | load_LDT_nolock(&next->context); | ||
47 | } | ||
48 | } | ||
49 | #endif | ||
50 | } | ||
51 | |||
52 | #define deactivate_mm(tsk, mm) \ | ||
53 | asm("movl %0,%%gs": :"r" (0)); | ||
54 | |||
55 | #endif /* _ASM_X86_MMU_CONTEXT_32_H */ | ||
diff --git a/arch/x86/include/asm/mmu_context_64.h b/arch/x86/include/asm/mmu_context_64.h deleted file mode 100644 index 677d36e9540a..000000000000 --- a/arch/x86/include/asm/mmu_context_64.h +++ /dev/null | |||
@@ -1,54 +0,0 @@ | |||
1 | #ifndef _ASM_X86_MMU_CONTEXT_64_H | ||
2 | #define _ASM_X86_MMU_CONTEXT_64_H | ||
3 | |||
4 | #include <asm/pda.h> | ||
5 | |||
6 | static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | ||
7 | { | ||
8 | #ifdef CONFIG_SMP | ||
9 | if (read_pda(mmu_state) == TLBSTATE_OK) | ||
10 | write_pda(mmu_state, TLBSTATE_LAZY); | ||
11 | #endif | ||
12 | } | ||
13 | |||
14 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | ||
15 | struct task_struct *tsk) | ||
16 | { | ||
17 | unsigned cpu = smp_processor_id(); | ||
18 | if (likely(prev != next)) { | ||
19 | /* stop flush ipis for the previous mm */ | ||
20 | cpu_clear(cpu, prev->cpu_vm_mask); | ||
21 | #ifdef CONFIG_SMP | ||
22 | write_pda(mmu_state, TLBSTATE_OK); | ||
23 | write_pda(active_mm, next); | ||
24 | #endif | ||
25 | cpu_set(cpu, next->cpu_vm_mask); | ||
26 | load_cr3(next->pgd); | ||
27 | |||
28 | if (unlikely(next->context.ldt != prev->context.ldt)) | ||
29 | load_LDT_nolock(&next->context); | ||
30 | } | ||
31 | #ifdef CONFIG_SMP | ||
32 | else { | ||
33 | write_pda(mmu_state, TLBSTATE_OK); | ||
34 | if (read_pda(active_mm) != next) | ||
35 | BUG(); | ||
36 | if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { | ||
37 | /* We were in lazy tlb mode and leave_mm disabled | ||
38 | * tlb flush IPI delivery. We must reload CR3 | ||
39 | * to make sure to use no freed page tables. | ||
40 | */ | ||
41 | load_cr3(next->pgd); | ||
42 | load_LDT_nolock(&next->context); | ||
43 | } | ||
44 | } | ||
45 | #endif | ||
46 | } | ||
47 | |||
48 | #define deactivate_mm(tsk, mm) \ | ||
49 | do { \ | ||
50 | load_gs_index(0); \ | ||
51 | asm volatile("movl %0,%%fs"::"r"(0)); \ | ||
52 | } while (0) | ||
53 | |||
54 | #endif /* _ASM_X86_MMU_CONTEXT_64_H */ | ||
diff --git a/arch/x86/include/asm/mpspec_def.h b/arch/x86/include/asm/mpspec_def.h index 59568bc4767f..4a7f96d7c188 100644 --- a/arch/x86/include/asm/mpspec_def.h +++ b/arch/x86/include/asm/mpspec_def.h | |||
@@ -24,17 +24,18 @@ | |||
24 | # endif | 24 | # endif |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | struct intel_mp_floating { | 27 | /* Intel MP Floating Pointer Structure */ |
28 | char mpf_signature[4]; /* "_MP_" */ | 28 | struct mpf_intel { |
29 | unsigned int mpf_physptr; /* Configuration table address */ | 29 | char signature[4]; /* "_MP_" */ |
30 | unsigned char mpf_length; /* Our length (paragraphs) */ | 30 | unsigned int physptr; /* Configuration table address */ |
31 | unsigned char mpf_specification;/* Specification version */ | 31 | unsigned char length; /* Our length (paragraphs) */ |
32 | unsigned char mpf_checksum; /* Checksum (makes sum 0) */ | 32 | unsigned char specification; /* Specification version */ |
33 | unsigned char mpf_feature1; /* Standard or configuration ? */ | 33 | unsigned char checksum; /* Checksum (makes sum 0) */ |
34 | unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */ | 34 | unsigned char feature1; /* Standard or configuration ? */ |
35 | unsigned char mpf_feature3; /* Unused (0) */ | 35 | unsigned char feature2; /* Bit7 set for IMCR|PIC */ |
36 | unsigned char mpf_feature4; /* Unused (0) */ | 36 | unsigned char feature3; /* Unused (0) */ |
37 | unsigned char mpf_feature5; /* Unused (0) */ | 37 | unsigned char feature4; /* Unused (0) */ |
38 | unsigned char feature5; /* Unused (0) */ | ||
38 | }; | 39 | }; |
39 | 40 | ||
40 | #define MPC_SIGNATURE "PCMP" | 41 | #define MPC_SIGNATURE "PCMP" |
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index 823cc931363f..40226999cbf8 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h | |||
@@ -163,7 +163,7 @@ static inline pteval_t native_pte_val(pte_t pte) | |||
163 | return pte.pte; | 163 | return pte.pte; |
164 | } | 164 | } |
165 | 165 | ||
166 | static inline pteval_t native_pte_flags(pte_t pte) | 166 | static inline pteval_t pte_flags(pte_t pte) |
167 | { | 167 | { |
168 | return native_pte_val(pte) & PTE_FLAGS_MASK; | 168 | return native_pte_val(pte) & PTE_FLAGS_MASK; |
169 | } | 169 | } |
@@ -189,7 +189,6 @@ static inline pteval_t native_pte_flags(pte_t pte) | |||
189 | #endif | 189 | #endif |
190 | 190 | ||
191 | #define pte_val(x) native_pte_val(x) | 191 | #define pte_val(x) native_pte_val(x) |
192 | #define pte_flags(x) native_pte_flags(x) | ||
193 | #define __pte(x) native_make_pte(x) | 192 | #define __pte(x) native_make_pte(x) |
194 | 193 | ||
195 | #endif /* CONFIG_PARAVIRT */ | 194 | #endif /* CONFIG_PARAVIRT */ |
diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h index 5ebca29f44f0..e27fdbe5f9e4 100644 --- a/arch/x86/include/asm/page_64.h +++ b/arch/x86/include/asm/page_64.h | |||
@@ -13,8 +13,8 @@ | |||
13 | #define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1) | 13 | #define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1) |
14 | #define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER) | 14 | #define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER) |
15 | 15 | ||
16 | #define IRQSTACK_ORDER 2 | 16 | #define IRQ_STACK_ORDER 2 |
17 | #define IRQSTACKSIZE (PAGE_SIZE << IRQSTACK_ORDER) | 17 | #define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER) |
18 | 18 | ||
19 | #define STACKFAULT_STACK 1 | 19 | #define STACKFAULT_STACK 1 |
20 | #define DOUBLEFAULT_STACK 2 | 20 | #define DOUBLEFAULT_STACK 2 |
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index ba3e2ff6aedc..c85e7475e171 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h | |||
@@ -12,21 +12,38 @@ | |||
12 | #define CLBR_EAX (1 << 0) | 12 | #define CLBR_EAX (1 << 0) |
13 | #define CLBR_ECX (1 << 1) | 13 | #define CLBR_ECX (1 << 1) |
14 | #define CLBR_EDX (1 << 2) | 14 | #define CLBR_EDX (1 << 2) |
15 | #define CLBR_EDI (1 << 3) | ||
15 | 16 | ||
16 | #ifdef CONFIG_X86_64 | 17 | #ifdef CONFIG_X86_32 |
17 | #define CLBR_RSI (1 << 3) | 18 | /* CLBR_ANY should match all regs platform has. For i386, that's just it */ |
18 | #define CLBR_RDI (1 << 4) | 19 | #define CLBR_ANY ((1 << 4) - 1) |
20 | |||
21 | #define CLBR_ARG_REGS (CLBR_EAX | CLBR_EDX | CLBR_ECX) | ||
22 | #define CLBR_RET_REG (CLBR_EAX | CLBR_EDX) | ||
23 | #define CLBR_SCRATCH (0) | ||
24 | #else | ||
25 | #define CLBR_RAX CLBR_EAX | ||
26 | #define CLBR_RCX CLBR_ECX | ||
27 | #define CLBR_RDX CLBR_EDX | ||
28 | #define CLBR_RDI CLBR_EDI | ||
29 | #define CLBR_RSI (1 << 4) | ||
19 | #define CLBR_R8 (1 << 5) | 30 | #define CLBR_R8 (1 << 5) |
20 | #define CLBR_R9 (1 << 6) | 31 | #define CLBR_R9 (1 << 6) |
21 | #define CLBR_R10 (1 << 7) | 32 | #define CLBR_R10 (1 << 7) |
22 | #define CLBR_R11 (1 << 8) | 33 | #define CLBR_R11 (1 << 8) |
34 | |||
23 | #define CLBR_ANY ((1 << 9) - 1) | 35 | #define CLBR_ANY ((1 << 9) - 1) |
36 | |||
37 | #define CLBR_ARG_REGS (CLBR_RDI | CLBR_RSI | CLBR_RDX | \ | ||
38 | CLBR_RCX | CLBR_R8 | CLBR_R9) | ||
39 | #define CLBR_RET_REG (CLBR_RAX) | ||
40 | #define CLBR_SCRATCH (CLBR_R10 | CLBR_R11) | ||
41 | |||
24 | #include <asm/desc_defs.h> | 42 | #include <asm/desc_defs.h> |
25 | #else | ||
26 | /* CLBR_ANY should match all regs platform has. For i386, that's just it */ | ||
27 | #define CLBR_ANY ((1 << 3) - 1) | ||
28 | #endif /* X86_64 */ | 43 | #endif /* X86_64 */ |
29 | 44 | ||
45 | #define CLBR_CALLEE_SAVE ((CLBR_ARG_REGS | CLBR_SCRATCH) & ~CLBR_RET_REG) | ||
46 | |||
30 | #ifndef __ASSEMBLY__ | 47 | #ifndef __ASSEMBLY__ |
31 | #include <linux/types.h> | 48 | #include <linux/types.h> |
32 | #include <linux/cpumask.h> | 49 | #include <linux/cpumask.h> |
@@ -40,6 +57,14 @@ struct tss_struct; | |||
40 | struct mm_struct; | 57 | struct mm_struct; |
41 | struct desc_struct; | 58 | struct desc_struct; |
42 | 59 | ||
60 | /* | ||
61 | * Wrapper type for pointers to code which uses the non-standard | ||
62 | * calling convention. See PV_CALL_SAVE_REGS_THUNK below. | ||
63 | */ | ||
64 | struct paravirt_callee_save { | ||
65 | void *func; | ||
66 | }; | ||
67 | |||
43 | /* general info */ | 68 | /* general info */ |
44 | struct pv_info { | 69 | struct pv_info { |
45 | unsigned int kernel_rpl; | 70 | unsigned int kernel_rpl; |
@@ -189,11 +214,15 @@ struct pv_irq_ops { | |||
189 | * expected to use X86_EFLAGS_IF; all other bits | 214 | * expected to use X86_EFLAGS_IF; all other bits |
190 | * returned from save_fl are undefined, and may be ignored by | 215 | * returned from save_fl are undefined, and may be ignored by |
191 | * restore_fl. | 216 | * restore_fl. |
217 | * | ||
218 | * NOTE: These functions callers expect the callee to preserve | ||
219 | * more registers than the standard C calling convention. | ||
192 | */ | 220 | */ |
193 | unsigned long (*save_fl)(void); | 221 | struct paravirt_callee_save save_fl; |
194 | void (*restore_fl)(unsigned long); | 222 | struct paravirt_callee_save restore_fl; |
195 | void (*irq_disable)(void); | 223 | struct paravirt_callee_save irq_disable; |
196 | void (*irq_enable)(void); | 224 | struct paravirt_callee_save irq_enable; |
225 | |||
197 | void (*safe_halt)(void); | 226 | void (*safe_halt)(void); |
198 | void (*halt)(void); | 227 | void (*halt)(void); |
199 | 228 | ||
@@ -244,7 +273,8 @@ struct pv_mmu_ops { | |||
244 | void (*flush_tlb_user)(void); | 273 | void (*flush_tlb_user)(void); |
245 | void (*flush_tlb_kernel)(void); | 274 | void (*flush_tlb_kernel)(void); |
246 | void (*flush_tlb_single)(unsigned long addr); | 275 | void (*flush_tlb_single)(unsigned long addr); |
247 | void (*flush_tlb_others)(const cpumask_t *cpus, struct mm_struct *mm, | 276 | void (*flush_tlb_others)(const struct cpumask *cpus, |
277 | struct mm_struct *mm, | ||
248 | unsigned long va); | 278 | unsigned long va); |
249 | 279 | ||
250 | /* Hooks for allocating and freeing a pagetable top-level */ | 280 | /* Hooks for allocating and freeing a pagetable top-level */ |
@@ -278,12 +308,11 @@ struct pv_mmu_ops { | |||
278 | void (*ptep_modify_prot_commit)(struct mm_struct *mm, unsigned long addr, | 308 | void (*ptep_modify_prot_commit)(struct mm_struct *mm, unsigned long addr, |
279 | pte_t *ptep, pte_t pte); | 309 | pte_t *ptep, pte_t pte); |
280 | 310 | ||
281 | pteval_t (*pte_val)(pte_t); | 311 | struct paravirt_callee_save pte_val; |
282 | pteval_t (*pte_flags)(pte_t); | 312 | struct paravirt_callee_save make_pte; |
283 | pte_t (*make_pte)(pteval_t pte); | ||
284 | 313 | ||
285 | pgdval_t (*pgd_val)(pgd_t); | 314 | struct paravirt_callee_save pgd_val; |
286 | pgd_t (*make_pgd)(pgdval_t pgd); | 315 | struct paravirt_callee_save make_pgd; |
287 | 316 | ||
288 | #if PAGETABLE_LEVELS >= 3 | 317 | #if PAGETABLE_LEVELS >= 3 |
289 | #ifdef CONFIG_X86_PAE | 318 | #ifdef CONFIG_X86_PAE |
@@ -298,12 +327,12 @@ struct pv_mmu_ops { | |||
298 | 327 | ||
299 | void (*set_pud)(pud_t *pudp, pud_t pudval); | 328 | void (*set_pud)(pud_t *pudp, pud_t pudval); |
300 | 329 | ||
301 | pmdval_t (*pmd_val)(pmd_t); | 330 | struct paravirt_callee_save pmd_val; |
302 | pmd_t (*make_pmd)(pmdval_t pmd); | 331 | struct paravirt_callee_save make_pmd; |
303 | 332 | ||
304 | #if PAGETABLE_LEVELS == 4 | 333 | #if PAGETABLE_LEVELS == 4 |
305 | pudval_t (*pud_val)(pud_t); | 334 | struct paravirt_callee_save pud_val; |
306 | pud_t (*make_pud)(pudval_t pud); | 335 | struct paravirt_callee_save make_pud; |
307 | 336 | ||
308 | void (*set_pgd)(pgd_t *pudp, pgd_t pgdval); | 337 | void (*set_pgd)(pgd_t *pudp, pgd_t pgdval); |
309 | #endif /* PAGETABLE_LEVELS == 4 */ | 338 | #endif /* PAGETABLE_LEVELS == 4 */ |
@@ -388,6 +417,8 @@ extern struct pv_lock_ops pv_lock_ops; | |||
388 | asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":") | 417 | asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":") |
389 | 418 | ||
390 | unsigned paravirt_patch_nop(void); | 419 | unsigned paravirt_patch_nop(void); |
420 | unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len); | ||
421 | unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len); | ||
391 | unsigned paravirt_patch_ignore(unsigned len); | 422 | unsigned paravirt_patch_ignore(unsigned len); |
392 | unsigned paravirt_patch_call(void *insnbuf, | 423 | unsigned paravirt_patch_call(void *insnbuf, |
393 | const void *target, u16 tgt_clobbers, | 424 | const void *target, u16 tgt_clobbers, |
@@ -479,25 +510,45 @@ int paravirt_disable_iospace(void); | |||
479 | * makes sure the incoming and outgoing types are always correct. | 510 | * makes sure the incoming and outgoing types are always correct. |
480 | */ | 511 | */ |
481 | #ifdef CONFIG_X86_32 | 512 | #ifdef CONFIG_X86_32 |
482 | #define PVOP_VCALL_ARGS unsigned long __eax, __edx, __ecx | 513 | #define PVOP_VCALL_ARGS \ |
514 | unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx | ||
483 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS | 515 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS |
516 | |||
517 | #define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x)) | ||
518 | #define PVOP_CALL_ARG2(x) "d" ((unsigned long)(x)) | ||
519 | #define PVOP_CALL_ARG3(x) "c" ((unsigned long)(x)) | ||
520 | |||
484 | #define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \ | 521 | #define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \ |
485 | "=c" (__ecx) | 522 | "=c" (__ecx) |
486 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS | 523 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS |
524 | |||
525 | #define PVOP_VCALLEE_CLOBBERS "=a" (__eax), "=d" (__edx) | ||
526 | #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS | ||
527 | |||
487 | #define EXTRA_CLOBBERS | 528 | #define EXTRA_CLOBBERS |
488 | #define VEXTRA_CLOBBERS | 529 | #define VEXTRA_CLOBBERS |
489 | #else | 530 | #else /* CONFIG_X86_64 */ |
490 | #define PVOP_VCALL_ARGS unsigned long __edi, __esi, __edx, __ecx | 531 | #define PVOP_VCALL_ARGS \ |
532 | unsigned long __edi = __edi, __esi = __esi, \ | ||
533 | __edx = __edx, __ecx = __ecx | ||
491 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS, __eax | 534 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS, __eax |
535 | |||
536 | #define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x)) | ||
537 | #define PVOP_CALL_ARG2(x) "S" ((unsigned long)(x)) | ||
538 | #define PVOP_CALL_ARG3(x) "d" ((unsigned long)(x)) | ||
539 | #define PVOP_CALL_ARG4(x) "c" ((unsigned long)(x)) | ||
540 | |||
492 | #define PVOP_VCALL_CLOBBERS "=D" (__edi), \ | 541 | #define PVOP_VCALL_CLOBBERS "=D" (__edi), \ |
493 | "=S" (__esi), "=d" (__edx), \ | 542 | "=S" (__esi), "=d" (__edx), \ |
494 | "=c" (__ecx) | 543 | "=c" (__ecx) |
495 | |||
496 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) | 544 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) |
497 | 545 | ||
546 | #define PVOP_VCALLEE_CLOBBERS "=a" (__eax) | ||
547 | #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS | ||
548 | |||
498 | #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" | 549 | #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" |
499 | #define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11" | 550 | #define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11" |
500 | #endif | 551 | #endif /* CONFIG_X86_32 */ |
501 | 552 | ||
502 | #ifdef CONFIG_PARAVIRT_DEBUG | 553 | #ifdef CONFIG_PARAVIRT_DEBUG |
503 | #define PVOP_TEST_NULL(op) BUG_ON(op == NULL) | 554 | #define PVOP_TEST_NULL(op) BUG_ON(op == NULL) |
@@ -505,10 +556,11 @@ int paravirt_disable_iospace(void); | |||
505 | #define PVOP_TEST_NULL(op) ((void)op) | 556 | #define PVOP_TEST_NULL(op) ((void)op) |
506 | #endif | 557 | #endif |
507 | 558 | ||
508 | #define __PVOP_CALL(rettype, op, pre, post, ...) \ | 559 | #define ____PVOP_CALL(rettype, op, clbr, call_clbr, extra_clbr, \ |
560 | pre, post, ...) \ | ||
509 | ({ \ | 561 | ({ \ |
510 | rettype __ret; \ | 562 | rettype __ret; \ |
511 | PVOP_CALL_ARGS; \ | 563 | PVOP_CALL_ARGS; \ |
512 | PVOP_TEST_NULL(op); \ | 564 | PVOP_TEST_NULL(op); \ |
513 | /* This is 32-bit specific, but is okay in 64-bit */ \ | 565 | /* This is 32-bit specific, but is okay in 64-bit */ \ |
514 | /* since this condition will never hold */ \ | 566 | /* since this condition will never hold */ \ |
@@ -516,70 +568,113 @@ int paravirt_disable_iospace(void); | |||
516 | asm volatile(pre \ | 568 | asm volatile(pre \ |
517 | paravirt_alt(PARAVIRT_CALL) \ | 569 | paravirt_alt(PARAVIRT_CALL) \ |
518 | post \ | 570 | post \ |
519 | : PVOP_CALL_CLOBBERS \ | 571 | : call_clbr \ |
520 | : paravirt_type(op), \ | 572 | : paravirt_type(op), \ |
521 | paravirt_clobber(CLBR_ANY), \ | 573 | paravirt_clobber(clbr), \ |
522 | ##__VA_ARGS__ \ | 574 | ##__VA_ARGS__ \ |
523 | : "memory", "cc" EXTRA_CLOBBERS); \ | 575 | : "memory", "cc" extra_clbr); \ |
524 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ | 576 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ |
525 | } else { \ | 577 | } else { \ |
526 | asm volatile(pre \ | 578 | asm volatile(pre \ |
527 | paravirt_alt(PARAVIRT_CALL) \ | 579 | paravirt_alt(PARAVIRT_CALL) \ |
528 | post \ | 580 | post \ |
529 | : PVOP_CALL_CLOBBERS \ | 581 | : call_clbr \ |
530 | : paravirt_type(op), \ | 582 | : paravirt_type(op), \ |
531 | paravirt_clobber(CLBR_ANY), \ | 583 | paravirt_clobber(clbr), \ |
532 | ##__VA_ARGS__ \ | 584 | ##__VA_ARGS__ \ |
533 | : "memory", "cc" EXTRA_CLOBBERS); \ | 585 | : "memory", "cc" extra_clbr); \ |
534 | __ret = (rettype)__eax; \ | 586 | __ret = (rettype)__eax; \ |
535 | } \ | 587 | } \ |
536 | __ret; \ | 588 | __ret; \ |
537 | }) | 589 | }) |
538 | #define __PVOP_VCALL(op, pre, post, ...) \ | 590 | |
591 | #define __PVOP_CALL(rettype, op, pre, post, ...) \ | ||
592 | ____PVOP_CALL(rettype, op, CLBR_ANY, PVOP_CALL_CLOBBERS, \ | ||
593 | EXTRA_CLOBBERS, pre, post, ##__VA_ARGS__) | ||
594 | |||
595 | #define __PVOP_CALLEESAVE(rettype, op, pre, post, ...) \ | ||
596 | ____PVOP_CALL(rettype, op.func, CLBR_RET_REG, \ | ||
597 | PVOP_CALLEE_CLOBBERS, , \ | ||
598 | pre, post, ##__VA_ARGS__) | ||
599 | |||
600 | |||
601 | #define ____PVOP_VCALL(op, clbr, call_clbr, extra_clbr, pre, post, ...) \ | ||
539 | ({ \ | 602 | ({ \ |
540 | PVOP_VCALL_ARGS; \ | 603 | PVOP_VCALL_ARGS; \ |
541 | PVOP_TEST_NULL(op); \ | 604 | PVOP_TEST_NULL(op); \ |
542 | asm volatile(pre \ | 605 | asm volatile(pre \ |
543 | paravirt_alt(PARAVIRT_CALL) \ | 606 | paravirt_alt(PARAVIRT_CALL) \ |
544 | post \ | 607 | post \ |
545 | : PVOP_VCALL_CLOBBERS \ | 608 | : call_clbr \ |
546 | : paravirt_type(op), \ | 609 | : paravirt_type(op), \ |
547 | paravirt_clobber(CLBR_ANY), \ | 610 | paravirt_clobber(clbr), \ |
548 | ##__VA_ARGS__ \ | 611 | ##__VA_ARGS__ \ |
549 | : "memory", "cc" VEXTRA_CLOBBERS); \ | 612 | : "memory", "cc" extra_clbr); \ |
550 | }) | 613 | }) |
551 | 614 | ||
615 | #define __PVOP_VCALL(op, pre, post, ...) \ | ||
616 | ____PVOP_VCALL(op, CLBR_ANY, PVOP_VCALL_CLOBBERS, \ | ||
617 | VEXTRA_CLOBBERS, \ | ||
618 | pre, post, ##__VA_ARGS__) | ||
619 | |||
620 | #define __PVOP_VCALLEESAVE(rettype, op, pre, post, ...) \ | ||
621 | ____PVOP_CALL(rettype, op.func, CLBR_RET_REG, \ | ||
622 | PVOP_VCALLEE_CLOBBERS, , \ | ||
623 | pre, post, ##__VA_ARGS__) | ||
624 | |||
625 | |||
626 | |||
552 | #define PVOP_CALL0(rettype, op) \ | 627 | #define PVOP_CALL0(rettype, op) \ |
553 | __PVOP_CALL(rettype, op, "", "") | 628 | __PVOP_CALL(rettype, op, "", "") |
554 | #define PVOP_VCALL0(op) \ | 629 | #define PVOP_VCALL0(op) \ |
555 | __PVOP_VCALL(op, "", "") | 630 | __PVOP_VCALL(op, "", "") |
556 | 631 | ||
632 | #define PVOP_CALLEE0(rettype, op) \ | ||
633 | __PVOP_CALLEESAVE(rettype, op, "", "") | ||
634 | #define PVOP_VCALLEE0(op) \ | ||
635 | __PVOP_VCALLEESAVE(op, "", "") | ||
636 | |||
637 | |||
557 | #define PVOP_CALL1(rettype, op, arg1) \ | 638 | #define PVOP_CALL1(rettype, op, arg1) \ |
558 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1))) | 639 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) |
559 | #define PVOP_VCALL1(op, arg1) \ | 640 | #define PVOP_VCALL1(op, arg1) \ |
560 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1))) | 641 | __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1)) |
642 | |||
643 | #define PVOP_CALLEE1(rettype, op, arg1) \ | ||
644 | __PVOP_CALLEESAVE(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) | ||
645 | #define PVOP_VCALLEE1(op, arg1) \ | ||
646 | __PVOP_VCALLEESAVE(op, "", "", PVOP_CALL_ARG1(arg1)) | ||
647 | |||
561 | 648 | ||
562 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ | 649 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ |
563 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 650 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ |
564 | "1" ((unsigned long)(arg2))) | 651 | PVOP_CALL_ARG2(arg2)) |
565 | #define PVOP_VCALL2(op, arg1, arg2) \ | 652 | #define PVOP_VCALL2(op, arg1, arg2) \ |
566 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 653 | __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ |
567 | "1" ((unsigned long)(arg2))) | 654 | PVOP_CALL_ARG2(arg2)) |
655 | |||
656 | #define PVOP_CALLEE2(rettype, op, arg1, arg2) \ | ||
657 | __PVOP_CALLEESAVE(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ | ||
658 | PVOP_CALL_ARG2(arg2)) | ||
659 | #define PVOP_VCALLEE2(op, arg1, arg2) \ | ||
660 | __PVOP_VCALLEESAVE(op, "", "", PVOP_CALL_ARG1(arg1), \ | ||
661 | PVOP_CALL_ARG2(arg2)) | ||
662 | |||
568 | 663 | ||
569 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ | 664 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ |
570 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 665 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ |
571 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) | 666 | PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) |
572 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ | 667 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ |
573 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 668 | __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ |
574 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) | 669 | PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) |
575 | 670 | ||
576 | /* This is the only difference in x86_64. We can make it much simpler */ | 671 | /* This is the only difference in x86_64. We can make it much simpler */ |
577 | #ifdef CONFIG_X86_32 | 672 | #ifdef CONFIG_X86_32 |
578 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | 673 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ |
579 | __PVOP_CALL(rettype, op, \ | 674 | __PVOP_CALL(rettype, op, \ |
580 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | 675 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ |
581 | "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ | 676 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
582 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | 677 | PVOP_CALL_ARG3(arg3), [_arg4] "mr" ((u32)(arg4))) |
583 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ | 678 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ |
584 | __PVOP_VCALL(op, \ | 679 | __PVOP_VCALL(op, \ |
585 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | 680 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ |
@@ -587,13 +682,13 @@ int paravirt_disable_iospace(void); | |||
587 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | 682 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) |
588 | #else | 683 | #else |
589 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | 684 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ |
590 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 685 | __PVOP_CALL(rettype, op, "", "", \ |
591 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ | 686 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
592 | "3"((unsigned long)(arg4))) | 687 | PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) |
593 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ | 688 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ |
594 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 689 | __PVOP_VCALL(op, "", "", \ |
595 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ | 690 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
596 | "3"((unsigned long)(arg4))) | 691 | PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) |
597 | #endif | 692 | #endif |
598 | 693 | ||
599 | static inline int paravirt_enabled(void) | 694 | static inline int paravirt_enabled(void) |
@@ -984,10 +1079,11 @@ static inline void __flush_tlb_single(unsigned long addr) | |||
984 | PVOP_VCALL1(pv_mmu_ops.flush_tlb_single, addr); | 1079 | PVOP_VCALL1(pv_mmu_ops.flush_tlb_single, addr); |
985 | } | 1080 | } |
986 | 1081 | ||
987 | static inline void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, | 1082 | static inline void flush_tlb_others(const struct cpumask *cpumask, |
1083 | struct mm_struct *mm, | ||
988 | unsigned long va) | 1084 | unsigned long va) |
989 | { | 1085 | { |
990 | PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, &cpumask, mm, va); | 1086 | PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, cpumask, mm, va); |
991 | } | 1087 | } |
992 | 1088 | ||
993 | static inline int paravirt_pgd_alloc(struct mm_struct *mm) | 1089 | static inline int paravirt_pgd_alloc(struct mm_struct *mm) |
@@ -1059,13 +1155,13 @@ static inline pte_t __pte(pteval_t val) | |||
1059 | pteval_t ret; | 1155 | pteval_t ret; |
1060 | 1156 | ||
1061 | if (sizeof(pteval_t) > sizeof(long)) | 1157 | if (sizeof(pteval_t) > sizeof(long)) |
1062 | ret = PVOP_CALL2(pteval_t, | 1158 | ret = PVOP_CALLEE2(pteval_t, |
1063 | pv_mmu_ops.make_pte, | 1159 | pv_mmu_ops.make_pte, |
1064 | val, (u64)val >> 32); | 1160 | val, (u64)val >> 32); |
1065 | else | 1161 | else |
1066 | ret = PVOP_CALL1(pteval_t, | 1162 | ret = PVOP_CALLEE1(pteval_t, |
1067 | pv_mmu_ops.make_pte, | 1163 | pv_mmu_ops.make_pte, |
1068 | val); | 1164 | val); |
1069 | 1165 | ||
1070 | return (pte_t) { .pte = ret }; | 1166 | return (pte_t) { .pte = ret }; |
1071 | } | 1167 | } |
@@ -1075,29 +1171,12 @@ static inline pteval_t pte_val(pte_t pte) | |||
1075 | pteval_t ret; | 1171 | pteval_t ret; |
1076 | 1172 | ||
1077 | if (sizeof(pteval_t) > sizeof(long)) | 1173 | if (sizeof(pteval_t) > sizeof(long)) |
1078 | ret = PVOP_CALL2(pteval_t, pv_mmu_ops.pte_val, | 1174 | ret = PVOP_CALLEE2(pteval_t, pv_mmu_ops.pte_val, |
1079 | pte.pte, (u64)pte.pte >> 32); | 1175 | pte.pte, (u64)pte.pte >> 32); |
1080 | else | ||
1081 | ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_val, | ||
1082 | pte.pte); | ||
1083 | |||
1084 | return ret; | ||
1085 | } | ||
1086 | |||
1087 | static inline pteval_t pte_flags(pte_t pte) | ||
1088 | { | ||
1089 | pteval_t ret; | ||
1090 | |||
1091 | if (sizeof(pteval_t) > sizeof(long)) | ||
1092 | ret = PVOP_CALL2(pteval_t, pv_mmu_ops.pte_flags, | ||
1093 | pte.pte, (u64)pte.pte >> 32); | ||
1094 | else | 1176 | else |
1095 | ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_flags, | 1177 | ret = PVOP_CALLEE1(pteval_t, pv_mmu_ops.pte_val, |
1096 | pte.pte); | 1178 | pte.pte); |
1097 | 1179 | ||
1098 | #ifdef CONFIG_PARAVIRT_DEBUG | ||
1099 | BUG_ON(ret & PTE_PFN_MASK); | ||
1100 | #endif | ||
1101 | return ret; | 1180 | return ret; |
1102 | } | 1181 | } |
1103 | 1182 | ||
@@ -1106,11 +1185,11 @@ static inline pgd_t __pgd(pgdval_t val) | |||
1106 | pgdval_t ret; | 1185 | pgdval_t ret; |
1107 | 1186 | ||
1108 | if (sizeof(pgdval_t) > sizeof(long)) | 1187 | if (sizeof(pgdval_t) > sizeof(long)) |
1109 | ret = PVOP_CALL2(pgdval_t, pv_mmu_ops.make_pgd, | 1188 | ret = PVOP_CALLEE2(pgdval_t, pv_mmu_ops.make_pgd, |
1110 | val, (u64)val >> 32); | 1189 | val, (u64)val >> 32); |
1111 | else | 1190 | else |
1112 | ret = PVOP_CALL1(pgdval_t, pv_mmu_ops.make_pgd, | 1191 | ret = PVOP_CALLEE1(pgdval_t, pv_mmu_ops.make_pgd, |
1113 | val); | 1192 | val); |
1114 | 1193 | ||
1115 | return (pgd_t) { ret }; | 1194 | return (pgd_t) { ret }; |
1116 | } | 1195 | } |
@@ -1120,11 +1199,11 @@ static inline pgdval_t pgd_val(pgd_t pgd) | |||
1120 | pgdval_t ret; | 1199 | pgdval_t ret; |
1121 | 1200 | ||
1122 | if (sizeof(pgdval_t) > sizeof(long)) | 1201 | if (sizeof(pgdval_t) > sizeof(long)) |
1123 | ret = PVOP_CALL2(pgdval_t, pv_mmu_ops.pgd_val, | 1202 | ret = PVOP_CALLEE2(pgdval_t, pv_mmu_ops.pgd_val, |
1124 | pgd.pgd, (u64)pgd.pgd >> 32); | 1203 | pgd.pgd, (u64)pgd.pgd >> 32); |
1125 | else | 1204 | else |
1126 | ret = PVOP_CALL1(pgdval_t, pv_mmu_ops.pgd_val, | 1205 | ret = PVOP_CALLEE1(pgdval_t, pv_mmu_ops.pgd_val, |
1127 | pgd.pgd); | 1206 | pgd.pgd); |
1128 | 1207 | ||
1129 | return ret; | 1208 | return ret; |
1130 | } | 1209 | } |
@@ -1188,11 +1267,11 @@ static inline pmd_t __pmd(pmdval_t val) | |||
1188 | pmdval_t ret; | 1267 | pmdval_t ret; |
1189 | 1268 | ||
1190 | if (sizeof(pmdval_t) > sizeof(long)) | 1269 | if (sizeof(pmdval_t) > sizeof(long)) |
1191 | ret = PVOP_CALL2(pmdval_t, pv_mmu_ops.make_pmd, | 1270 | ret = PVOP_CALLEE2(pmdval_t, pv_mmu_ops.make_pmd, |
1192 | val, (u64)val >> 32); | 1271 | val, (u64)val >> 32); |
1193 | else | 1272 | else |
1194 | ret = PVOP_CALL1(pmdval_t, pv_mmu_ops.make_pmd, | 1273 | ret = PVOP_CALLEE1(pmdval_t, pv_mmu_ops.make_pmd, |
1195 | val); | 1274 | val); |
1196 | 1275 | ||
1197 | return (pmd_t) { ret }; | 1276 | return (pmd_t) { ret }; |
1198 | } | 1277 | } |
@@ -1202,11 +1281,11 @@ static inline pmdval_t pmd_val(pmd_t pmd) | |||
1202 | pmdval_t ret; | 1281 | pmdval_t ret; |
1203 | 1282 | ||
1204 | if (sizeof(pmdval_t) > sizeof(long)) | 1283 | if (sizeof(pmdval_t) > sizeof(long)) |
1205 | ret = PVOP_CALL2(pmdval_t, pv_mmu_ops.pmd_val, | 1284 | ret = PVOP_CALLEE2(pmdval_t, pv_mmu_ops.pmd_val, |
1206 | pmd.pmd, (u64)pmd.pmd >> 32); | 1285 | pmd.pmd, (u64)pmd.pmd >> 32); |
1207 | else | 1286 | else |
1208 | ret = PVOP_CALL1(pmdval_t, pv_mmu_ops.pmd_val, | 1287 | ret = PVOP_CALLEE1(pmdval_t, pv_mmu_ops.pmd_val, |
1209 | pmd.pmd); | 1288 | pmd.pmd); |
1210 | 1289 | ||
1211 | return ret; | 1290 | return ret; |
1212 | } | 1291 | } |
@@ -1228,11 +1307,11 @@ static inline pud_t __pud(pudval_t val) | |||
1228 | pudval_t ret; | 1307 | pudval_t ret; |
1229 | 1308 | ||
1230 | if (sizeof(pudval_t) > sizeof(long)) | 1309 | if (sizeof(pudval_t) > sizeof(long)) |
1231 | ret = PVOP_CALL2(pudval_t, pv_mmu_ops.make_pud, | 1310 | ret = PVOP_CALLEE2(pudval_t, pv_mmu_ops.make_pud, |
1232 | val, (u64)val >> 32); | 1311 | val, (u64)val >> 32); |
1233 | else | 1312 | else |
1234 | ret = PVOP_CALL1(pudval_t, pv_mmu_ops.make_pud, | 1313 | ret = PVOP_CALLEE1(pudval_t, pv_mmu_ops.make_pud, |
1235 | val); | 1314 | val); |
1236 | 1315 | ||
1237 | return (pud_t) { ret }; | 1316 | return (pud_t) { ret }; |
1238 | } | 1317 | } |
@@ -1242,11 +1321,11 @@ static inline pudval_t pud_val(pud_t pud) | |||
1242 | pudval_t ret; | 1321 | pudval_t ret; |
1243 | 1322 | ||
1244 | if (sizeof(pudval_t) > sizeof(long)) | 1323 | if (sizeof(pudval_t) > sizeof(long)) |
1245 | ret = PVOP_CALL2(pudval_t, pv_mmu_ops.pud_val, | 1324 | ret = PVOP_CALLEE2(pudval_t, pv_mmu_ops.pud_val, |
1246 | pud.pud, (u64)pud.pud >> 32); | 1325 | pud.pud, (u64)pud.pud >> 32); |
1247 | else | 1326 | else |
1248 | ret = PVOP_CALL1(pudval_t, pv_mmu_ops.pud_val, | 1327 | ret = PVOP_CALLEE1(pudval_t, pv_mmu_ops.pud_val, |
1249 | pud.pud); | 1328 | pud.pud); |
1250 | 1329 | ||
1251 | return ret; | 1330 | return ret; |
1252 | } | 1331 | } |
@@ -1387,6 +1466,9 @@ static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, | |||
1387 | } | 1466 | } |
1388 | 1467 | ||
1389 | void _paravirt_nop(void); | 1468 | void _paravirt_nop(void); |
1469 | u32 _paravirt_ident_32(u32); | ||
1470 | u64 _paravirt_ident_64(u64); | ||
1471 | |||
1390 | #define paravirt_nop ((void *)_paravirt_nop) | 1472 | #define paravirt_nop ((void *)_paravirt_nop) |
1391 | 1473 | ||
1392 | void paravirt_use_bytelocks(void); | 1474 | void paravirt_use_bytelocks(void); |
@@ -1438,12 +1520,37 @@ extern struct paravirt_patch_site __parainstructions[], | |||
1438 | __parainstructions_end[]; | 1520 | __parainstructions_end[]; |
1439 | 1521 | ||
1440 | #ifdef CONFIG_X86_32 | 1522 | #ifdef CONFIG_X86_32 |
1441 | #define PV_SAVE_REGS "pushl %%ecx; pushl %%edx;" | 1523 | #define PV_SAVE_REGS "pushl %ecx; pushl %edx;" |
1442 | #define PV_RESTORE_REGS "popl %%edx; popl %%ecx" | 1524 | #define PV_RESTORE_REGS "popl %edx; popl %ecx;" |
1525 | |||
1526 | /* save and restore all caller-save registers, except return value */ | ||
1527 | #define PV_SAVE_ALL_CALLER_REGS "pushl %ecx;" | ||
1528 | #define PV_RESTORE_ALL_CALLER_REGS "popl %ecx;" | ||
1529 | |||
1443 | #define PV_FLAGS_ARG "0" | 1530 | #define PV_FLAGS_ARG "0" |
1444 | #define PV_EXTRA_CLOBBERS | 1531 | #define PV_EXTRA_CLOBBERS |
1445 | #define PV_VEXTRA_CLOBBERS | 1532 | #define PV_VEXTRA_CLOBBERS |
1446 | #else | 1533 | #else |
1534 | /* save and restore all caller-save registers, except return value */ | ||
1535 | #define PV_SAVE_ALL_CALLER_REGS \ | ||
1536 | "push %rcx;" \ | ||
1537 | "push %rdx;" \ | ||
1538 | "push %rsi;" \ | ||
1539 | "push %rdi;" \ | ||
1540 | "push %r8;" \ | ||
1541 | "push %r9;" \ | ||
1542 | "push %r10;" \ | ||
1543 | "push %r11;" | ||
1544 | #define PV_RESTORE_ALL_CALLER_REGS \ | ||
1545 | "pop %r11;" \ | ||
1546 | "pop %r10;" \ | ||
1547 | "pop %r9;" \ | ||
1548 | "pop %r8;" \ | ||
1549 | "pop %rdi;" \ | ||
1550 | "pop %rsi;" \ | ||
1551 | "pop %rdx;" \ | ||
1552 | "pop %rcx;" | ||
1553 | |||
1447 | /* We save some registers, but all of them, that's too much. We clobber all | 1554 | /* We save some registers, but all of them, that's too much. We clobber all |
1448 | * caller saved registers but the argument parameter */ | 1555 | * caller saved registers but the argument parameter */ |
1449 | #define PV_SAVE_REGS "pushq %%rdi;" | 1556 | #define PV_SAVE_REGS "pushq %%rdi;" |
@@ -1453,52 +1560,76 @@ extern struct paravirt_patch_site __parainstructions[], | |||
1453 | #define PV_FLAGS_ARG "D" | 1560 | #define PV_FLAGS_ARG "D" |
1454 | #endif | 1561 | #endif |
1455 | 1562 | ||
1563 | /* | ||
1564 | * Generate a thunk around a function which saves all caller-save | ||
1565 | * registers except for the return value. This allows C functions to | ||
1566 | * be called from assembler code where fewer than normal registers are | ||
1567 | * available. It may also help code generation around calls from C | ||
1568 | * code if the common case doesn't use many registers. | ||
1569 | * | ||
1570 | * When a callee is wrapped in a thunk, the caller can assume that all | ||
1571 | * arg regs and all scratch registers are preserved across the | ||
1572 | * call. The return value in rax/eax will not be saved, even for void | ||
1573 | * functions. | ||
1574 | */ | ||
1575 | #define PV_CALLEE_SAVE_REGS_THUNK(func) \ | ||
1576 | extern typeof(func) __raw_callee_save_##func; \ | ||
1577 | static void *__##func##__ __used = func; \ | ||
1578 | \ | ||
1579 | asm(".pushsection .text;" \ | ||
1580 | "__raw_callee_save_" #func ": " \ | ||
1581 | PV_SAVE_ALL_CALLER_REGS \ | ||
1582 | "call " #func ";" \ | ||
1583 | PV_RESTORE_ALL_CALLER_REGS \ | ||
1584 | "ret;" \ | ||
1585 | ".popsection") | ||
1586 | |||
1587 | /* Get a reference to a callee-save function */ | ||
1588 | #define PV_CALLEE_SAVE(func) \ | ||
1589 | ((struct paravirt_callee_save) { __raw_callee_save_##func }) | ||
1590 | |||
1591 | /* Promise that "func" already uses the right calling convention */ | ||
1592 | #define __PV_IS_CALLEE_SAVE(func) \ | ||
1593 | ((struct paravirt_callee_save) { func }) | ||
1594 | |||
1456 | static inline unsigned long __raw_local_save_flags(void) | 1595 | static inline unsigned long __raw_local_save_flags(void) |
1457 | { | 1596 | { |
1458 | unsigned long f; | 1597 | unsigned long f; |
1459 | 1598 | ||
1460 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1599 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1461 | PARAVIRT_CALL | ||
1462 | PV_RESTORE_REGS) | ||
1463 | : "=a"(f) | 1600 | : "=a"(f) |
1464 | : paravirt_type(pv_irq_ops.save_fl), | 1601 | : paravirt_type(pv_irq_ops.save_fl), |
1465 | paravirt_clobber(CLBR_EAX) | 1602 | paravirt_clobber(CLBR_EAX) |
1466 | : "memory", "cc" PV_VEXTRA_CLOBBERS); | 1603 | : "memory", "cc"); |
1467 | return f; | 1604 | return f; |
1468 | } | 1605 | } |
1469 | 1606 | ||
1470 | static inline void raw_local_irq_restore(unsigned long f) | 1607 | static inline void raw_local_irq_restore(unsigned long f) |
1471 | { | 1608 | { |
1472 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1609 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1473 | PARAVIRT_CALL | ||
1474 | PV_RESTORE_REGS) | ||
1475 | : "=a"(f) | 1610 | : "=a"(f) |
1476 | : PV_FLAGS_ARG(f), | 1611 | : PV_FLAGS_ARG(f), |
1477 | paravirt_type(pv_irq_ops.restore_fl), | 1612 | paravirt_type(pv_irq_ops.restore_fl), |
1478 | paravirt_clobber(CLBR_EAX) | 1613 | paravirt_clobber(CLBR_EAX) |
1479 | : "memory", "cc" PV_EXTRA_CLOBBERS); | 1614 | : "memory", "cc"); |
1480 | } | 1615 | } |
1481 | 1616 | ||
1482 | static inline void raw_local_irq_disable(void) | 1617 | static inline void raw_local_irq_disable(void) |
1483 | { | 1618 | { |
1484 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1619 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1485 | PARAVIRT_CALL | ||
1486 | PV_RESTORE_REGS) | ||
1487 | : | 1620 | : |
1488 | : paravirt_type(pv_irq_ops.irq_disable), | 1621 | : paravirt_type(pv_irq_ops.irq_disable), |
1489 | paravirt_clobber(CLBR_EAX) | 1622 | paravirt_clobber(CLBR_EAX) |
1490 | : "memory", "eax", "cc" PV_EXTRA_CLOBBERS); | 1623 | : "memory", "eax", "cc"); |
1491 | } | 1624 | } |
1492 | 1625 | ||
1493 | static inline void raw_local_irq_enable(void) | 1626 | static inline void raw_local_irq_enable(void) |
1494 | { | 1627 | { |
1495 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1628 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1496 | PARAVIRT_CALL | ||
1497 | PV_RESTORE_REGS) | ||
1498 | : | 1629 | : |
1499 | : paravirt_type(pv_irq_ops.irq_enable), | 1630 | : paravirt_type(pv_irq_ops.irq_enable), |
1500 | paravirt_clobber(CLBR_EAX) | 1631 | paravirt_clobber(CLBR_EAX) |
1501 | : "memory", "eax", "cc" PV_EXTRA_CLOBBERS); | 1632 | : "memory", "eax", "cc"); |
1502 | } | 1633 | } |
1503 | 1634 | ||
1504 | static inline unsigned long __raw_local_irq_save(void) | 1635 | static inline unsigned long __raw_local_irq_save(void) |
@@ -1541,33 +1672,49 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1541 | .popsection | 1672 | .popsection |
1542 | 1673 | ||
1543 | 1674 | ||
1675 | #define COND_PUSH(set, mask, reg) \ | ||
1676 | .if ((~(set)) & mask); push %reg; .endif | ||
1677 | #define COND_POP(set, mask, reg) \ | ||
1678 | .if ((~(set)) & mask); pop %reg; .endif | ||
1679 | |||
1544 | #ifdef CONFIG_X86_64 | 1680 | #ifdef CONFIG_X86_64 |
1545 | #define PV_SAVE_REGS \ | 1681 | |
1546 | push %rax; \ | 1682 | #define PV_SAVE_REGS(set) \ |
1547 | push %rcx; \ | 1683 | COND_PUSH(set, CLBR_RAX, rax); \ |
1548 | push %rdx; \ | 1684 | COND_PUSH(set, CLBR_RCX, rcx); \ |
1549 | push %rsi; \ | 1685 | COND_PUSH(set, CLBR_RDX, rdx); \ |
1550 | push %rdi; \ | 1686 | COND_PUSH(set, CLBR_RSI, rsi); \ |
1551 | push %r8; \ | 1687 | COND_PUSH(set, CLBR_RDI, rdi); \ |
1552 | push %r9; \ | 1688 | COND_PUSH(set, CLBR_R8, r8); \ |
1553 | push %r10; \ | 1689 | COND_PUSH(set, CLBR_R9, r9); \ |
1554 | push %r11 | 1690 | COND_PUSH(set, CLBR_R10, r10); \ |
1555 | #define PV_RESTORE_REGS \ | 1691 | COND_PUSH(set, CLBR_R11, r11) |
1556 | pop %r11; \ | 1692 | #define PV_RESTORE_REGS(set) \ |
1557 | pop %r10; \ | 1693 | COND_POP(set, CLBR_R11, r11); \ |
1558 | pop %r9; \ | 1694 | COND_POP(set, CLBR_R10, r10); \ |
1559 | pop %r8; \ | 1695 | COND_POP(set, CLBR_R9, r9); \ |
1560 | pop %rdi; \ | 1696 | COND_POP(set, CLBR_R8, r8); \ |
1561 | pop %rsi; \ | 1697 | COND_POP(set, CLBR_RDI, rdi); \ |
1562 | pop %rdx; \ | 1698 | COND_POP(set, CLBR_RSI, rsi); \ |
1563 | pop %rcx; \ | 1699 | COND_POP(set, CLBR_RDX, rdx); \ |
1564 | pop %rax | 1700 | COND_POP(set, CLBR_RCX, rcx); \ |
1701 | COND_POP(set, CLBR_RAX, rax) | ||
1702 | |||
1565 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 8) | 1703 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 8) |
1566 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8) | 1704 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8) |
1567 | #define PARA_INDIRECT(addr) *addr(%rip) | 1705 | #define PARA_INDIRECT(addr) *addr(%rip) |
1568 | #else | 1706 | #else |
1569 | #define PV_SAVE_REGS pushl %eax; pushl %edi; pushl %ecx; pushl %edx | 1707 | #define PV_SAVE_REGS(set) \ |
1570 | #define PV_RESTORE_REGS popl %edx; popl %ecx; popl %edi; popl %eax | 1708 | COND_PUSH(set, CLBR_EAX, eax); \ |
1709 | COND_PUSH(set, CLBR_EDI, edi); \ | ||
1710 | COND_PUSH(set, CLBR_ECX, ecx); \ | ||
1711 | COND_PUSH(set, CLBR_EDX, edx) | ||
1712 | #define PV_RESTORE_REGS(set) \ | ||
1713 | COND_POP(set, CLBR_EDX, edx); \ | ||
1714 | COND_POP(set, CLBR_ECX, ecx); \ | ||
1715 | COND_POP(set, CLBR_EDI, edi); \ | ||
1716 | COND_POP(set, CLBR_EAX, eax) | ||
1717 | |||
1571 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4) | 1718 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4) |
1572 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4) | 1719 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4) |
1573 | #define PARA_INDIRECT(addr) *%cs:addr | 1720 | #define PARA_INDIRECT(addr) *%cs:addr |
@@ -1579,15 +1726,15 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1579 | 1726 | ||
1580 | #define DISABLE_INTERRUPTS(clobbers) \ | 1727 | #define DISABLE_INTERRUPTS(clobbers) \ |
1581 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ | 1728 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ |
1582 | PV_SAVE_REGS; \ | 1729 | PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
1583 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ | 1730 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ |
1584 | PV_RESTORE_REGS;) \ | 1731 | PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
1585 | 1732 | ||
1586 | #define ENABLE_INTERRUPTS(clobbers) \ | 1733 | #define ENABLE_INTERRUPTS(clobbers) \ |
1587 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ | 1734 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ |
1588 | PV_SAVE_REGS; \ | 1735 | PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
1589 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ | 1736 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ |
1590 | PV_RESTORE_REGS;) | 1737 | PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
1591 | 1738 | ||
1592 | #define USERGS_SYSRET32 \ | 1739 | #define USERGS_SYSRET32 \ |
1593 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \ | 1740 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \ |
@@ -1617,11 +1764,15 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1617 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ | 1764 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ |
1618 | swapgs) | 1765 | swapgs) |
1619 | 1766 | ||
1767 | /* | ||
1768 | * Note: swapgs is very special, and in practise is either going to be | ||
1769 | * implemented with a single "swapgs" instruction or something very | ||
1770 | * special. Either way, we don't need to save any registers for | ||
1771 | * it. | ||
1772 | */ | ||
1620 | #define SWAPGS \ | 1773 | #define SWAPGS \ |
1621 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ | 1774 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ |
1622 | PV_SAVE_REGS; \ | 1775 | call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs) \ |
1623 | call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs); \ | ||
1624 | PV_RESTORE_REGS \ | ||
1625 | ) | 1776 | ) |
1626 | 1777 | ||
1627 | #define GET_CR2_INTO_RCX \ | 1778 | #define GET_CR2_INTO_RCX \ |
diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h deleted file mode 100644 index 2fbfff88df37..000000000000 --- a/arch/x86/include/asm/pda.h +++ /dev/null | |||
@@ -1,137 +0,0 @@ | |||
1 | #ifndef _ASM_X86_PDA_H | ||
2 | #define _ASM_X86_PDA_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | #include <linux/stddef.h> | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/cache.h> | ||
8 | #include <asm/page.h> | ||
9 | |||
10 | /* Per processor datastructure. %gs points to it while the kernel runs */ | ||
11 | struct x8664_pda { | ||
12 | struct task_struct *pcurrent; /* 0 Current process */ | ||
13 | unsigned long data_offset; /* 8 Per cpu data offset from linker | ||
14 | address */ | ||
15 | unsigned long kernelstack; /* 16 top of kernel stack for current */ | ||
16 | unsigned long oldrsp; /* 24 user rsp for system call */ | ||
17 | int irqcount; /* 32 Irq nesting counter. Starts -1 */ | ||
18 | unsigned int cpunumber; /* 36 Logical CPU number */ | ||
19 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
20 | unsigned long stack_canary; /* 40 stack canary value */ | ||
21 | /* gcc-ABI: this canary MUST be at | ||
22 | offset 40!!! */ | ||
23 | #endif | ||
24 | char *irqstackptr; | ||
25 | short nodenumber; /* number of current node (32k max) */ | ||
26 | short in_bootmem; /* pda lives in bootmem */ | ||
27 | unsigned int __softirq_pending; | ||
28 | unsigned int __nmi_count; /* number of NMI on this CPUs */ | ||
29 | short mmu_state; | ||
30 | short isidle; | ||
31 | struct mm_struct *active_mm; | ||
32 | unsigned apic_timer_irqs; | ||
33 | unsigned irq0_irqs; | ||
34 | unsigned irq_resched_count; | ||
35 | unsigned irq_call_count; | ||
36 | unsigned irq_tlb_count; | ||
37 | unsigned irq_thermal_count; | ||
38 | unsigned irq_threshold_count; | ||
39 | unsigned irq_spurious_count; | ||
40 | } ____cacheline_aligned_in_smp; | ||
41 | |||
42 | extern struct x8664_pda **_cpu_pda; | ||
43 | extern void pda_init(int); | ||
44 | |||
45 | #define cpu_pda(i) (_cpu_pda[i]) | ||
46 | |||
47 | /* | ||
48 | * There is no fast way to get the base address of the PDA, all the accesses | ||
49 | * have to mention %fs/%gs. So it needs to be done this Torvaldian way. | ||
50 | */ | ||
51 | extern void __bad_pda_field(void) __attribute__((noreturn)); | ||
52 | |||
53 | /* | ||
54 | * proxy_pda doesn't actually exist, but tell gcc it is accessed for | ||
55 | * all PDA accesses so it gets read/write dependencies right. | ||
56 | */ | ||
57 | extern struct x8664_pda _proxy_pda; | ||
58 | |||
59 | #define pda_offset(field) offsetof(struct x8664_pda, field) | ||
60 | |||
61 | #define pda_to_op(op, field, val) \ | ||
62 | do { \ | ||
63 | typedef typeof(_proxy_pda.field) T__; \ | ||
64 | if (0) { T__ tmp__; tmp__ = (val); } /* type checking */ \ | ||
65 | switch (sizeof(_proxy_pda.field)) { \ | ||
66 | case 2: \ | ||
67 | asm(op "w %1,%%gs:%c2" : \ | ||
68 | "+m" (_proxy_pda.field) : \ | ||
69 | "ri" ((T__)val), \ | ||
70 | "i"(pda_offset(field))); \ | ||
71 | break; \ | ||
72 | case 4: \ | ||
73 | asm(op "l %1,%%gs:%c2" : \ | ||
74 | "+m" (_proxy_pda.field) : \ | ||
75 | "ri" ((T__)val), \ | ||
76 | "i" (pda_offset(field))); \ | ||
77 | break; \ | ||
78 | case 8: \ | ||
79 | asm(op "q %1,%%gs:%c2": \ | ||
80 | "+m" (_proxy_pda.field) : \ | ||
81 | "ri" ((T__)val), \ | ||
82 | "i"(pda_offset(field))); \ | ||
83 | break; \ | ||
84 | default: \ | ||
85 | __bad_pda_field(); \ | ||
86 | } \ | ||
87 | } while (0) | ||
88 | |||
89 | #define pda_from_op(op, field) \ | ||
90 | ({ \ | ||
91 | typeof(_proxy_pda.field) ret__; \ | ||
92 | switch (sizeof(_proxy_pda.field)) { \ | ||
93 | case 2: \ | ||
94 | asm(op "w %%gs:%c1,%0" : \ | ||
95 | "=r" (ret__) : \ | ||
96 | "i" (pda_offset(field)), \ | ||
97 | "m" (_proxy_pda.field)); \ | ||
98 | break; \ | ||
99 | case 4: \ | ||
100 | asm(op "l %%gs:%c1,%0": \ | ||
101 | "=r" (ret__): \ | ||
102 | "i" (pda_offset(field)), \ | ||
103 | "m" (_proxy_pda.field)); \ | ||
104 | break; \ | ||
105 | case 8: \ | ||
106 | asm(op "q %%gs:%c1,%0": \ | ||
107 | "=r" (ret__) : \ | ||
108 | "i" (pda_offset(field)), \ | ||
109 | "m" (_proxy_pda.field)); \ | ||
110 | break; \ | ||
111 | default: \ | ||
112 | __bad_pda_field(); \ | ||
113 | } \ | ||
114 | ret__; \ | ||
115 | }) | ||
116 | |||
117 | #define read_pda(field) pda_from_op("mov", field) | ||
118 | #define write_pda(field, val) pda_to_op("mov", field, val) | ||
119 | #define add_pda(field, val) pda_to_op("add", field, val) | ||
120 | #define sub_pda(field, val) pda_to_op("sub", field, val) | ||
121 | #define or_pda(field, val) pda_to_op("or", field, val) | ||
122 | |||
123 | /* This is not atomic against other CPUs -- CPU preemption needs to be off */ | ||
124 | #define test_and_clear_bit_pda(bit, field) \ | ||
125 | ({ \ | ||
126 | int old__; \ | ||
127 | asm volatile("btr %2,%%gs:%c3\n\tsbbl %0,%0" \ | ||
128 | : "=r" (old__), "+m" (_proxy_pda.field) \ | ||
129 | : "dIr" (bit), "i" (pda_offset(field)) : "memory");\ | ||
130 | old__; \ | ||
131 | }) | ||
132 | |||
133 | #endif | ||
134 | |||
135 | #define PDA_STACKOFFSET (5*8) | ||
136 | |||
137 | #endif /* _ASM_X86_PDA_H */ | ||
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index ece72053ba63..0b64af4f13ac 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
@@ -2,53 +2,12 @@ | |||
2 | #define _ASM_X86_PERCPU_H | 2 | #define _ASM_X86_PERCPU_H |
3 | 3 | ||
4 | #ifdef CONFIG_X86_64 | 4 | #ifdef CONFIG_X86_64 |
5 | #include <linux/compiler.h> | 5 | #define __percpu_seg gs |
6 | 6 | #define __percpu_mov_op movq | |
7 | /* Same as asm-generic/percpu.h, except that we store the per cpu offset | 7 | #else |
8 | in the PDA. Longer term the PDA and every per cpu variable | 8 | #define __percpu_seg fs |
9 | should be just put into a single section and referenced directly | 9 | #define __percpu_mov_op movl |
10 | from %gs */ | ||
11 | |||
12 | #ifdef CONFIG_SMP | ||
13 | #include <asm/pda.h> | ||
14 | |||
15 | #define __per_cpu_offset(cpu) (cpu_pda(cpu)->data_offset) | ||
16 | #define __my_cpu_offset read_pda(data_offset) | ||
17 | |||
18 | #define per_cpu_offset(x) (__per_cpu_offset(x)) | ||
19 | |||
20 | #endif | 10 | #endif |
21 | #include <asm-generic/percpu.h> | ||
22 | |||
23 | DECLARE_PER_CPU(struct x8664_pda, pda); | ||
24 | |||
25 | /* | ||
26 | * These are supposed to be implemented as a single instruction which | ||
27 | * operates on the per-cpu data base segment. x86-64 doesn't have | ||
28 | * that yet, so this is a fairly inefficient workaround for the | ||
29 | * meantime. The single instruction is atomic with respect to | ||
30 | * preemption and interrupts, so we need to explicitly disable | ||
31 | * interrupts here to achieve the same effect. However, because it | ||
32 | * can be used from within interrupt-disable/enable, we can't actually | ||
33 | * disable interrupts; disabling preemption is enough. | ||
34 | */ | ||
35 | #define x86_read_percpu(var) \ | ||
36 | ({ \ | ||
37 | typeof(per_cpu_var(var)) __tmp; \ | ||
38 | preempt_disable(); \ | ||
39 | __tmp = __get_cpu_var(var); \ | ||
40 | preempt_enable(); \ | ||
41 | __tmp; \ | ||
42 | }) | ||
43 | |||
44 | #define x86_write_percpu(var, val) \ | ||
45 | do { \ | ||
46 | preempt_disable(); \ | ||
47 | __get_cpu_var(var) = (val); \ | ||
48 | preempt_enable(); \ | ||
49 | } while(0) | ||
50 | |||
51 | #else /* CONFIG_X86_64 */ | ||
52 | 11 | ||
53 | #ifdef __ASSEMBLY__ | 12 | #ifdef __ASSEMBLY__ |
54 | 13 | ||
@@ -65,47 +24,26 @@ DECLARE_PER_CPU(struct x8664_pda, pda); | |||
65 | * PER_CPU(cpu_gdt_descr, %ebx) | 24 | * PER_CPU(cpu_gdt_descr, %ebx) |
66 | */ | 25 | */ |
67 | #ifdef CONFIG_SMP | 26 | #ifdef CONFIG_SMP |
68 | #define PER_CPU(var, reg) \ | 27 | #define PER_CPU(var, reg) \ |
69 | movl %fs:per_cpu__##this_cpu_off, reg; \ | 28 | __percpu_mov_op %__percpu_seg:per_cpu__this_cpu_off, reg; \ |
70 | lea per_cpu__##var(reg), reg | 29 | lea per_cpu__##var(reg), reg |
71 | #define PER_CPU_VAR(var) %fs:per_cpu__##var | 30 | #define PER_CPU_VAR(var) %__percpu_seg:per_cpu__##var |
72 | #else /* ! SMP */ | 31 | #else /* ! SMP */ |
73 | #define PER_CPU(var, reg) \ | 32 | #define PER_CPU(var, reg) \ |
74 | movl $per_cpu__##var, reg | 33 | __percpu_mov_op $per_cpu__##var, reg |
75 | #define PER_CPU_VAR(var) per_cpu__##var | 34 | #define PER_CPU_VAR(var) per_cpu__##var |
76 | #endif /* SMP */ | 35 | #endif /* SMP */ |
77 | 36 | ||
78 | #else /* ...!ASSEMBLY */ | 37 | #else /* ...!ASSEMBLY */ |
79 | 38 | ||
80 | /* | 39 | #include <linux/stringify.h> |
81 | * PER_CPU finds an address of a per-cpu variable. | ||
82 | * | ||
83 | * Args: | ||
84 | * var - variable name | ||
85 | * cpu - 32bit register containing the current CPU number | ||
86 | * | ||
87 | * The resulting address is stored in the "cpu" argument. | ||
88 | * | ||
89 | * Example: | ||
90 | * PER_CPU(cpu_gdt_descr, %ebx) | ||
91 | */ | ||
92 | #ifdef CONFIG_SMP | ||
93 | |||
94 | #define __my_cpu_offset x86_read_percpu(this_cpu_off) | ||
95 | 40 | ||
96 | /* fs segment starts at (positive) offset == __per_cpu_offset[cpu] */ | 41 | #ifdef CONFIG_SMP |
97 | #define __percpu_seg "%%fs:" | 42 | #define __percpu_arg(x) "%%"__stringify(__percpu_seg)":%P" #x |
98 | 43 | #define __my_cpu_offset percpu_read(this_cpu_off) | |
99 | #else /* !SMP */ | 44 | #else |
100 | 45 | #define __percpu_arg(x) "%" #x | |
101 | #define __percpu_seg "" | 46 | #endif |
102 | |||
103 | #endif /* SMP */ | ||
104 | |||
105 | #include <asm-generic/percpu.h> | ||
106 | |||
107 | /* We can use this directly for local CPU (faster). */ | ||
108 | DECLARE_PER_CPU(unsigned long, this_cpu_off); | ||
109 | 47 | ||
110 | /* For arch-specific code, we can use direct single-insn ops (they | 48 | /* For arch-specific code, we can use direct single-insn ops (they |
111 | * don't give an lvalue though). */ | 49 | * don't give an lvalue though). */ |
@@ -120,20 +58,25 @@ do { \ | |||
120 | } \ | 58 | } \ |
121 | switch (sizeof(var)) { \ | 59 | switch (sizeof(var)) { \ |
122 | case 1: \ | 60 | case 1: \ |
123 | asm(op "b %1,"__percpu_seg"%0" \ | 61 | asm(op "b %1,"__percpu_arg(0) \ |
124 | : "+m" (var) \ | 62 | : "+m" (var) \ |
125 | : "ri" ((T__)val)); \ | 63 | : "ri" ((T__)val)); \ |
126 | break; \ | 64 | break; \ |
127 | case 2: \ | 65 | case 2: \ |
128 | asm(op "w %1,"__percpu_seg"%0" \ | 66 | asm(op "w %1,"__percpu_arg(0) \ |
129 | : "+m" (var) \ | 67 | : "+m" (var) \ |
130 | : "ri" ((T__)val)); \ | 68 | : "ri" ((T__)val)); \ |
131 | break; \ | 69 | break; \ |
132 | case 4: \ | 70 | case 4: \ |
133 | asm(op "l %1,"__percpu_seg"%0" \ | 71 | asm(op "l %1,"__percpu_arg(0) \ |
134 | : "+m" (var) \ | 72 | : "+m" (var) \ |
135 | : "ri" ((T__)val)); \ | 73 | : "ri" ((T__)val)); \ |
136 | break; \ | 74 | break; \ |
75 | case 8: \ | ||
76 | asm(op "q %1,"__percpu_arg(0) \ | ||
77 | : "+m" (var) \ | ||
78 | : "re" ((T__)val)); \ | ||
79 | break; \ | ||
137 | default: __bad_percpu_size(); \ | 80 | default: __bad_percpu_size(); \ |
138 | } \ | 81 | } \ |
139 | } while (0) | 82 | } while (0) |
@@ -143,17 +86,22 @@ do { \ | |||
143 | typeof(var) ret__; \ | 86 | typeof(var) ret__; \ |
144 | switch (sizeof(var)) { \ | 87 | switch (sizeof(var)) { \ |
145 | case 1: \ | 88 | case 1: \ |
146 | asm(op "b "__percpu_seg"%1,%0" \ | 89 | asm(op "b "__percpu_arg(1)",%0" \ |
147 | : "=r" (ret__) \ | 90 | : "=r" (ret__) \ |
148 | : "m" (var)); \ | 91 | : "m" (var)); \ |
149 | break; \ | 92 | break; \ |
150 | case 2: \ | 93 | case 2: \ |
151 | asm(op "w "__percpu_seg"%1,%0" \ | 94 | asm(op "w "__percpu_arg(1)",%0" \ |
152 | : "=r" (ret__) \ | 95 | : "=r" (ret__) \ |
153 | : "m" (var)); \ | 96 | : "m" (var)); \ |
154 | break; \ | 97 | break; \ |
155 | case 4: \ | 98 | case 4: \ |
156 | asm(op "l "__percpu_seg"%1,%0" \ | 99 | asm(op "l "__percpu_arg(1)",%0" \ |
100 | : "=r" (ret__) \ | ||
101 | : "m" (var)); \ | ||
102 | break; \ | ||
103 | case 8: \ | ||
104 | asm(op "q "__percpu_arg(1)",%0" \ | ||
157 | : "=r" (ret__) \ | 105 | : "=r" (ret__) \ |
158 | : "m" (var)); \ | 106 | : "m" (var)); \ |
159 | break; \ | 107 | break; \ |
@@ -162,13 +110,30 @@ do { \ | |||
162 | ret__; \ | 110 | ret__; \ |
163 | }) | 111 | }) |
164 | 112 | ||
165 | #define x86_read_percpu(var) percpu_from_op("mov", per_cpu__##var) | 113 | #define percpu_read(var) percpu_from_op("mov", per_cpu__##var) |
166 | #define x86_write_percpu(var, val) percpu_to_op("mov", per_cpu__##var, val) | 114 | #define percpu_write(var, val) percpu_to_op("mov", per_cpu__##var, val) |
167 | #define x86_add_percpu(var, val) percpu_to_op("add", per_cpu__##var, val) | 115 | #define percpu_add(var, val) percpu_to_op("add", per_cpu__##var, val) |
168 | #define x86_sub_percpu(var, val) percpu_to_op("sub", per_cpu__##var, val) | 116 | #define percpu_sub(var, val) percpu_to_op("sub", per_cpu__##var, val) |
169 | #define x86_or_percpu(var, val) percpu_to_op("or", per_cpu__##var, val) | 117 | #define percpu_and(var, val) percpu_to_op("and", per_cpu__##var, val) |
118 | #define percpu_or(var, val) percpu_to_op("or", per_cpu__##var, val) | ||
119 | #define percpu_xor(var, val) percpu_to_op("xor", per_cpu__##var, val) | ||
120 | |||
121 | /* This is not atomic against other CPUs -- CPU preemption needs to be off */ | ||
122 | #define x86_test_and_clear_bit_percpu(bit, var) \ | ||
123 | ({ \ | ||
124 | int old__; \ | ||
125 | asm volatile("btr %2,"__percpu_arg(1)"\n\tsbbl %0,%0" \ | ||
126 | : "=r" (old__), "+m" (per_cpu__##var) \ | ||
127 | : "dIr" (bit)); \ | ||
128 | old__; \ | ||
129 | }) | ||
130 | |||
131 | #include <asm-generic/percpu.h> | ||
132 | |||
133 | /* We can use this directly for local CPU (faster). */ | ||
134 | DECLARE_PER_CPU(unsigned long, this_cpu_off); | ||
135 | |||
170 | #endif /* !__ASSEMBLY__ */ | 136 | #endif /* !__ASSEMBLY__ */ |
171 | #endif /* !CONFIG_X86_64 */ | ||
172 | 137 | ||
173 | #ifdef CONFIG_SMP | 138 | #ifdef CONFIG_SMP |
174 | 139 | ||
@@ -195,9 +160,9 @@ do { \ | |||
195 | #define early_per_cpu_ptr(_name) (_name##_early_ptr) | 160 | #define early_per_cpu_ptr(_name) (_name##_early_ptr) |
196 | #define early_per_cpu_map(_name, _idx) (_name##_early_map[_idx]) | 161 | #define early_per_cpu_map(_name, _idx) (_name##_early_map[_idx]) |
197 | #define early_per_cpu(_name, _cpu) \ | 162 | #define early_per_cpu(_name, _cpu) \ |
198 | (early_per_cpu_ptr(_name) ? \ | 163 | *(early_per_cpu_ptr(_name) ? \ |
199 | early_per_cpu_ptr(_name)[_cpu] : \ | 164 | &early_per_cpu_ptr(_name)[_cpu] : \ |
200 | per_cpu(_name, _cpu)) | 165 | &per_cpu(_name, _cpu)) |
201 | 166 | ||
202 | #else /* !CONFIG_SMP */ | 167 | #else /* !CONFIG_SMP */ |
203 | #define DEFINE_EARLY_PER_CPU(_type, _name, _initvalue) \ | 168 | #define DEFINE_EARLY_PER_CPU(_type, _name, _initvalue) \ |
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 178205305ac0..860f1b635c40 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h | |||
@@ -242,64 +242,78 @@ static inline int pmd_large(pmd_t pte) | |||
242 | (_PAGE_PSE | _PAGE_PRESENT); | 242 | (_PAGE_PSE | _PAGE_PRESENT); |
243 | } | 243 | } |
244 | 244 | ||
245 | static inline pte_t pte_set_flags(pte_t pte, pteval_t set) | ||
246 | { | ||
247 | pteval_t v = native_pte_val(pte); | ||
248 | |||
249 | return native_make_pte(v | set); | ||
250 | } | ||
251 | |||
252 | static inline pte_t pte_clear_flags(pte_t pte, pteval_t clear) | ||
253 | { | ||
254 | pteval_t v = native_pte_val(pte); | ||
255 | |||
256 | return native_make_pte(v & ~clear); | ||
257 | } | ||
258 | |||
245 | static inline pte_t pte_mkclean(pte_t pte) | 259 | static inline pte_t pte_mkclean(pte_t pte) |
246 | { | 260 | { |
247 | return __pte(pte_val(pte) & ~_PAGE_DIRTY); | 261 | return pte_clear_flags(pte, _PAGE_DIRTY); |
248 | } | 262 | } |
249 | 263 | ||
250 | static inline pte_t pte_mkold(pte_t pte) | 264 | static inline pte_t pte_mkold(pte_t pte) |
251 | { | 265 | { |
252 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); | 266 | return pte_clear_flags(pte, _PAGE_ACCESSED); |
253 | } | 267 | } |
254 | 268 | ||
255 | static inline pte_t pte_wrprotect(pte_t pte) | 269 | static inline pte_t pte_wrprotect(pte_t pte) |
256 | { | 270 | { |
257 | return __pte(pte_val(pte) & ~_PAGE_RW); | 271 | return pte_clear_flags(pte, _PAGE_RW); |
258 | } | 272 | } |
259 | 273 | ||
260 | static inline pte_t pte_mkexec(pte_t pte) | 274 | static inline pte_t pte_mkexec(pte_t pte) |
261 | { | 275 | { |
262 | return __pte(pte_val(pte) & ~_PAGE_NX); | 276 | return pte_clear_flags(pte, _PAGE_NX); |
263 | } | 277 | } |
264 | 278 | ||
265 | static inline pte_t pte_mkdirty(pte_t pte) | 279 | static inline pte_t pte_mkdirty(pte_t pte) |
266 | { | 280 | { |
267 | return __pte(pte_val(pte) | _PAGE_DIRTY); | 281 | return pte_set_flags(pte, _PAGE_DIRTY); |
268 | } | 282 | } |
269 | 283 | ||
270 | static inline pte_t pte_mkyoung(pte_t pte) | 284 | static inline pte_t pte_mkyoung(pte_t pte) |
271 | { | 285 | { |
272 | return __pte(pte_val(pte) | _PAGE_ACCESSED); | 286 | return pte_set_flags(pte, _PAGE_ACCESSED); |
273 | } | 287 | } |
274 | 288 | ||
275 | static inline pte_t pte_mkwrite(pte_t pte) | 289 | static inline pte_t pte_mkwrite(pte_t pte) |
276 | { | 290 | { |
277 | return __pte(pte_val(pte) | _PAGE_RW); | 291 | return pte_set_flags(pte, _PAGE_RW); |
278 | } | 292 | } |
279 | 293 | ||
280 | static inline pte_t pte_mkhuge(pte_t pte) | 294 | static inline pte_t pte_mkhuge(pte_t pte) |
281 | { | 295 | { |
282 | return __pte(pte_val(pte) | _PAGE_PSE); | 296 | return pte_set_flags(pte, _PAGE_PSE); |
283 | } | 297 | } |
284 | 298 | ||
285 | static inline pte_t pte_clrhuge(pte_t pte) | 299 | static inline pte_t pte_clrhuge(pte_t pte) |
286 | { | 300 | { |
287 | return __pte(pte_val(pte) & ~_PAGE_PSE); | 301 | return pte_clear_flags(pte, _PAGE_PSE); |
288 | } | 302 | } |
289 | 303 | ||
290 | static inline pte_t pte_mkglobal(pte_t pte) | 304 | static inline pte_t pte_mkglobal(pte_t pte) |
291 | { | 305 | { |
292 | return __pte(pte_val(pte) | _PAGE_GLOBAL); | 306 | return pte_set_flags(pte, _PAGE_GLOBAL); |
293 | } | 307 | } |
294 | 308 | ||
295 | static inline pte_t pte_clrglobal(pte_t pte) | 309 | static inline pte_t pte_clrglobal(pte_t pte) |
296 | { | 310 | { |
297 | return __pte(pte_val(pte) & ~_PAGE_GLOBAL); | 311 | return pte_clear_flags(pte, _PAGE_GLOBAL); |
298 | } | 312 | } |
299 | 313 | ||
300 | static inline pte_t pte_mkspecial(pte_t pte) | 314 | static inline pte_t pte_mkspecial(pte_t pte) |
301 | { | 315 | { |
302 | return __pte(pte_val(pte) | _PAGE_SPECIAL); | 316 | return pte_set_flags(pte, _PAGE_SPECIAL); |
303 | } | 317 | } |
304 | 318 | ||
305 | extern pteval_t __supported_pte_mask; | 319 | extern pteval_t __supported_pte_mask; |
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 100ac483a0ba..1c4e247c51fd 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
12 | #include <linux/bitops.h> | 12 | #include <linux/bitops.h> |
13 | #include <linux/threads.h> | 13 | #include <linux/threads.h> |
14 | #include <asm/pda.h> | ||
15 | 14 | ||
16 | extern pud_t level3_kernel_pgt[512]; | 15 | extern pud_t level3_kernel_pgt[512]; |
17 | extern pud_t level3_ident_pgt[512]; | 16 | extern pud_t level3_ident_pgt[512]; |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 091cd8855f2e..656d02ea509b 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -378,6 +378,22 @@ union thread_xstate { | |||
378 | 378 | ||
379 | #ifdef CONFIG_X86_64 | 379 | #ifdef CONFIG_X86_64 |
380 | DECLARE_PER_CPU(struct orig_ist, orig_ist); | 380 | DECLARE_PER_CPU(struct orig_ist, orig_ist); |
381 | |||
382 | union irq_stack_union { | ||
383 | char irq_stack[IRQ_STACK_SIZE]; | ||
384 | /* | ||
385 | * GCC hardcodes the stack canary as %gs:40. Since the | ||
386 | * irq_stack is the object at %gs:0, we reserve the bottom | ||
387 | * 48 bytes of the irq stack for the canary. | ||
388 | */ | ||
389 | struct { | ||
390 | char gs_base[40]; | ||
391 | unsigned long stack_canary; | ||
392 | }; | ||
393 | }; | ||
394 | |||
395 | DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); | ||
396 | DECLARE_PER_CPU(char *, irq_stack_ptr); | ||
381 | #endif | 397 | #endif |
382 | 398 | ||
383 | extern void print_cpu_info(struct cpuinfo_x86 *); | 399 | extern void print_cpu_info(struct cpuinfo_x86 *); |
@@ -752,9 +768,9 @@ extern int sysenter_setup(void); | |||
752 | extern struct desc_ptr early_gdt_descr; | 768 | extern struct desc_ptr early_gdt_descr; |
753 | 769 | ||
754 | extern void cpu_set_gdt(int); | 770 | extern void cpu_set_gdt(int); |
755 | extern void switch_to_new_gdt(void); | 771 | extern void switch_to_new_gdt(int); |
772 | extern void load_percpu_segment(int); | ||
756 | extern void cpu_init(void); | 773 | extern void cpu_init(void); |
757 | extern void init_gdt(int cpu); | ||
758 | 774 | ||
759 | static inline unsigned long get_debugctlmsr(void) | 775 | static inline unsigned long get_debugctlmsr(void) |
760 | { | 776 | { |
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index ebe858cdc8a3..536949749bc2 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h | |||
@@ -100,7 +100,6 @@ extern unsigned long init_pg_tables_start; | |||
100 | extern unsigned long init_pg_tables_end; | 100 | extern unsigned long init_pg_tables_end; |
101 | 101 | ||
102 | #else | 102 | #else |
103 | void __init x86_64_init_pda(void); | ||
104 | void __init x86_64_start_kernel(char *real_mode); | 103 | void __init x86_64_start_kernel(char *real_mode); |
105 | void __init x86_64_start_reservations(char *real_mode_data); | 104 | void __init x86_64_start_reservations(char *real_mode_data); |
106 | 105 | ||
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 19953df61c52..45ef8a1b9d7c 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h | |||
@@ -15,34 +15,8 @@ | |||
15 | # include <asm/io_apic.h> | 15 | # include <asm/io_apic.h> |
16 | # endif | 16 | # endif |
17 | #endif | 17 | #endif |
18 | #include <asm/pda.h> | ||
19 | #include <asm/thread_info.h> | 18 | #include <asm/thread_info.h> |
20 | 19 | #include <asm/cpumask.h> | |
21 | #ifdef CONFIG_X86_64 | ||
22 | |||
23 | extern cpumask_var_t cpu_callin_mask; | ||
24 | extern cpumask_var_t cpu_callout_mask; | ||
25 | extern cpumask_var_t cpu_initialized_mask; | ||
26 | extern cpumask_var_t cpu_sibling_setup_mask; | ||
27 | |||
28 | #else /* CONFIG_X86_32 */ | ||
29 | |||
30 | extern cpumask_t cpu_callin_map; | ||
31 | extern cpumask_t cpu_callout_map; | ||
32 | extern cpumask_t cpu_initialized; | ||
33 | extern cpumask_t cpu_sibling_setup_map; | ||
34 | |||
35 | #define cpu_callin_mask ((struct cpumask *)&cpu_callin_map) | ||
36 | #define cpu_callout_mask ((struct cpumask *)&cpu_callout_map) | ||
37 | #define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) | ||
38 | #define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) | ||
39 | |||
40 | #endif /* CONFIG_X86_32 */ | ||
41 | |||
42 | extern void (*mtrr_hook)(void); | ||
43 | extern void zap_low_mappings(void); | ||
44 | |||
45 | extern int __cpuinit get_local_pda(int cpu); | ||
46 | 20 | ||
47 | extern int smp_num_siblings; | 21 | extern int smp_num_siblings; |
48 | extern unsigned int num_processors; | 22 | extern unsigned int num_processors; |
@@ -50,9 +24,7 @@ extern unsigned int num_processors; | |||
50 | DECLARE_PER_CPU(cpumask_t, cpu_sibling_map); | 24 | DECLARE_PER_CPU(cpumask_t, cpu_sibling_map); |
51 | DECLARE_PER_CPU(cpumask_t, cpu_core_map); | 25 | DECLARE_PER_CPU(cpumask_t, cpu_core_map); |
52 | DECLARE_PER_CPU(u16, cpu_llc_id); | 26 | DECLARE_PER_CPU(u16, cpu_llc_id); |
53 | #ifdef CONFIG_X86_32 | ||
54 | DECLARE_PER_CPU(int, cpu_number); | 27 | DECLARE_PER_CPU(int, cpu_number); |
55 | #endif | ||
56 | 28 | ||
57 | static inline struct cpumask *cpu_sibling_mask(int cpu) | 29 | static inline struct cpumask *cpu_sibling_mask(int cpu) |
58 | { | 30 | { |
@@ -167,8 +139,6 @@ void play_dead_common(void); | |||
167 | void native_send_call_func_ipi(const struct cpumask *mask); | 139 | void native_send_call_func_ipi(const struct cpumask *mask); |
168 | void native_send_call_func_single_ipi(int cpu); | 140 | void native_send_call_func_single_ipi(int cpu); |
169 | 141 | ||
170 | extern void prefill_possible_map(void); | ||
171 | |||
172 | void smp_store_cpu_info(int id); | 142 | void smp_store_cpu_info(int id); |
173 | #define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) | 143 | #define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) |
174 | 144 | ||
@@ -177,10 +147,6 @@ static inline int num_booting_cpus(void) | |||
177 | { | 147 | { |
178 | return cpumask_weight(cpu_callout_mask); | 148 | return cpumask_weight(cpu_callout_mask); |
179 | } | 149 | } |
180 | #else | ||
181 | static inline void prefill_possible_map(void) | ||
182 | { | ||
183 | } | ||
184 | #endif /* CONFIG_SMP */ | 150 | #endif /* CONFIG_SMP */ |
185 | 151 | ||
186 | extern unsigned disabled_cpus __cpuinitdata; | 152 | extern unsigned disabled_cpus __cpuinitdata; |
@@ -191,11 +157,11 @@ extern unsigned disabled_cpus __cpuinitdata; | |||
191 | * from the initial startup. We map APIC_BASE very early in page_setup(), | 157 | * from the initial startup. We map APIC_BASE very early in page_setup(), |
192 | * so this is correct in the x86 case. | 158 | * so this is correct in the x86 case. |
193 | */ | 159 | */ |
194 | #define raw_smp_processor_id() (x86_read_percpu(cpu_number)) | 160 | #define raw_smp_processor_id() (percpu_read(cpu_number)) |
195 | extern int safe_smp_processor_id(void); | 161 | extern int safe_smp_processor_id(void); |
196 | 162 | ||
197 | #elif defined(CONFIG_X86_64_SMP) | 163 | #elif defined(CONFIG_X86_64_SMP) |
198 | #define raw_smp_processor_id() read_pda(cpunumber) | 164 | #define raw_smp_processor_id() (percpu_read(cpu_number)) |
199 | 165 | ||
200 | #define stack_smp_processor_id() \ | 166 | #define stack_smp_processor_id() \ |
201 | ({ \ | 167 | ({ \ |
@@ -205,10 +171,6 @@ extern int safe_smp_processor_id(void); | |||
205 | }) | 171 | }) |
206 | #define safe_smp_processor_id() smp_processor_id() | 172 | #define safe_smp_processor_id() smp_processor_id() |
207 | 173 | ||
208 | #else /* !CONFIG_X86_32_SMP && !CONFIG_X86_64_SMP */ | ||
209 | #define cpu_physical_id(cpu) boot_cpu_physical_apicid | ||
210 | #define safe_smp_processor_id() 0 | ||
211 | #define stack_smp_processor_id() 0 | ||
212 | #endif | 174 | #endif |
213 | 175 | ||
214 | #ifdef CONFIG_X86_LOCAL_APIC | 176 | #ifdef CONFIG_X86_LOCAL_APIC |
@@ -251,11 +213,5 @@ static inline int hard_smp_processor_id(void) | |||
251 | 213 | ||
252 | #endif /* CONFIG_X86_LOCAL_APIC */ | 214 | #endif /* CONFIG_X86_LOCAL_APIC */ |
253 | 215 | ||
254 | #ifdef CONFIG_X86_HAS_BOOT_CPU_ID | ||
255 | extern unsigned char boot_cpu_id; | ||
256 | #else | ||
257 | #define boot_cpu_id 0 | ||
258 | #endif | ||
259 | |||
260 | #endif /* __ASSEMBLY__ */ | 216 | #endif /* __ASSEMBLY__ */ |
261 | #endif /* _ASM_X86_SMP_H */ | 217 | #endif /* _ASM_X86_SMP_H */ |
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h new file mode 100644 index 000000000000..36a700acaf2b --- /dev/null +++ b/arch/x86/include/asm/stackprotector.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef _ASM_STACKPROTECTOR_H | ||
2 | #define _ASM_STACKPROTECTOR_H 1 | ||
3 | |||
4 | #include <asm/tsc.h> | ||
5 | #include <asm/processor.h> | ||
6 | |||
7 | /* | ||
8 | * Initialize the stackprotector canary value. | ||
9 | * | ||
10 | * NOTE: this must only be called from functions that never return, | ||
11 | * and it must always be inlined. | ||
12 | */ | ||
13 | static __always_inline void boot_init_stack_canary(void) | ||
14 | { | ||
15 | u64 canary; | ||
16 | u64 tsc; | ||
17 | |||
18 | /* | ||
19 | * Build time only check to make sure the stack_canary is at | ||
20 | * offset 40 in the pda; this is a gcc ABI requirement | ||
21 | */ | ||
22 | BUILD_BUG_ON(offsetof(union irq_stack_union, stack_canary) != 40); | ||
23 | |||
24 | /* | ||
25 | * We both use the random pool and the current TSC as a source | ||
26 | * of randomness. The TSC only matters for very early init, | ||
27 | * there it already has some randomness on most systems. Later | ||
28 | * on during the bootup the random pool has true entropy too. | ||
29 | */ | ||
30 | get_random_bytes(&canary, sizeof(canary)); | ||
31 | tsc = __native_read_tsc(); | ||
32 | canary += tsc + (tsc << 32UL); | ||
33 | |||
34 | current->stack_canary = canary; | ||
35 | percpu_write(irq_stack_union.stack_canary, canary); | ||
36 | } | ||
37 | |||
38 | #endif | ||
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 8e626ea33a1a..2fcc70bc85f3 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h | |||
@@ -86,27 +86,44 @@ do { \ | |||
86 | , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \ | 86 | , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \ |
87 | "r12", "r13", "r14", "r15" | 87 | "r12", "r13", "r14", "r15" |
88 | 88 | ||
89 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
90 | #define __switch_canary \ | ||
91 | "movq %P[task_canary](%%rsi),%%r8\n\t" \ | ||
92 | "movq %%r8,"__percpu_arg([gs_canary])"\n\t" | ||
93 | #define __switch_canary_oparam \ | ||
94 | , [gs_canary] "=m" (per_cpu_var(irq_stack_union.stack_canary)) | ||
95 | #define __switch_canary_iparam \ | ||
96 | , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) | ||
97 | #else /* CC_STACKPROTECTOR */ | ||
98 | #define __switch_canary | ||
99 | #define __switch_canary_oparam | ||
100 | #define __switch_canary_iparam | ||
101 | #endif /* CC_STACKPROTECTOR */ | ||
102 | |||
89 | /* Save restore flags to clear handle leaking NT */ | 103 | /* Save restore flags to clear handle leaking NT */ |
90 | #define switch_to(prev, next, last) \ | 104 | #define switch_to(prev, next, last) \ |
91 | asm volatile(SAVE_CONTEXT \ | 105 | asm volatile(SAVE_CONTEXT \ |
92 | "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ | 106 | "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \ |
93 | "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ | 107 | "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */ \ |
94 | "call __switch_to\n\t" \ | 108 | "call __switch_to\n\t" \ |
95 | ".globl thread_return\n" \ | 109 | ".globl thread_return\n" \ |
96 | "thread_return:\n\t" \ | 110 | "thread_return:\n\t" \ |
97 | "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \ | 111 | "movq "__percpu_arg([current_task])",%%rsi\n\t" \ |
112 | __switch_canary \ | ||
98 | "movq %P[thread_info](%%rsi),%%r8\n\t" \ | 113 | "movq %P[thread_info](%%rsi),%%r8\n\t" \ |
99 | LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ | 114 | LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ |
100 | "movq %%rax,%%rdi\n\t" \ | 115 | "movq %%rax,%%rdi\n\t" \ |
101 | "jc ret_from_fork\n\t" \ | 116 | "jc ret_from_fork\n\t" \ |
102 | RESTORE_CONTEXT \ | 117 | RESTORE_CONTEXT \ |
103 | : "=a" (last) \ | 118 | : "=a" (last) \ |
119 | __switch_canary_oparam \ | ||
104 | : [next] "S" (next), [prev] "D" (prev), \ | 120 | : [next] "S" (next), [prev] "D" (prev), \ |
105 | [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \ | 121 | [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \ |
106 | [ti_flags] "i" (offsetof(struct thread_info, flags)), \ | 122 | [ti_flags] "i" (offsetof(struct thread_info, flags)), \ |
107 | [tif_fork] "i" (TIF_FORK), \ | 123 | [tif_fork] "i" (TIF_FORK), \ |
108 | [thread_info] "i" (offsetof(struct task_struct, stack)), \ | 124 | [thread_info] "i" (offsetof(struct task_struct, stack)), \ |
109 | [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) \ | 125 | [current_task] "m" (per_cpu_var(current_task)) \ |
126 | __switch_canary_iparam \ | ||
110 | : "memory", "cc" __EXTRA_CLOBBER) | 127 | : "memory", "cc" __EXTRA_CLOBBER) |
111 | #endif | 128 | #endif |
112 | 129 | ||
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 98789647baa9..b46f8ca007b5 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
@@ -194,25 +194,21 @@ static inline struct thread_info *current_thread_info(void) | |||
194 | 194 | ||
195 | #else /* X86_32 */ | 195 | #else /* X86_32 */ |
196 | 196 | ||
197 | #include <asm/pda.h> | 197 | #include <asm/percpu.h> |
198 | #define KERNEL_STACK_OFFSET (5*8) | ||
198 | 199 | ||
199 | /* | 200 | /* |
200 | * macros/functions for gaining access to the thread information structure | 201 | * macros/functions for gaining access to the thread information structure |
201 | * preempt_count needs to be 1 initially, until the scheduler is functional. | 202 | * preempt_count needs to be 1 initially, until the scheduler is functional. |
202 | */ | 203 | */ |
203 | #ifndef __ASSEMBLY__ | 204 | #ifndef __ASSEMBLY__ |
204 | static inline struct thread_info *current_thread_info(void) | 205 | DECLARE_PER_CPU(unsigned long, kernel_stack); |
205 | { | ||
206 | struct thread_info *ti; | ||
207 | ti = (void *)(read_pda(kernelstack) + PDA_STACKOFFSET - THREAD_SIZE); | ||
208 | return ti; | ||
209 | } | ||
210 | 206 | ||
211 | /* do not use in interrupt context */ | 207 | static inline struct thread_info *current_thread_info(void) |
212 | static inline struct thread_info *stack_thread_info(void) | ||
213 | { | 208 | { |
214 | struct thread_info *ti; | 209 | struct thread_info *ti; |
215 | asm("andq %%rsp,%0; " : "=r" (ti) : "0" (~(THREAD_SIZE - 1))); | 210 | ti = (void *)(percpu_read(kernel_stack) + |
211 | KERNEL_STACK_OFFSET - THREAD_SIZE); | ||
216 | return ti; | 212 | return ti; |
217 | } | 213 | } |
218 | 214 | ||
@@ -220,8 +216,8 @@ static inline struct thread_info *stack_thread_info(void) | |||
220 | 216 | ||
221 | /* how to get the thread information struct from ASM */ | 217 | /* how to get the thread information struct from ASM */ |
222 | #define GET_THREAD_INFO(reg) \ | 218 | #define GET_THREAD_INFO(reg) \ |
223 | movq %gs:pda_kernelstack,reg ; \ | 219 | movq PER_CPU_VAR(kernel_stack),reg ; \ |
224 | subq $(THREAD_SIZE-PDA_STACKOFFSET),reg | 220 | subq $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg |
225 | 221 | ||
226 | #endif | 222 | #endif |
227 | 223 | ||
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 0e7bbb549116..d3539f998f88 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h | |||
@@ -113,7 +113,7 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, | |||
113 | __flush_tlb(); | 113 | __flush_tlb(); |
114 | } | 114 | } |
115 | 115 | ||
116 | static inline void native_flush_tlb_others(const cpumask_t *cpumask, | 116 | static inline void native_flush_tlb_others(const struct cpumask *cpumask, |
117 | struct mm_struct *mm, | 117 | struct mm_struct *mm, |
118 | unsigned long va) | 118 | unsigned long va) |
119 | { | 119 | { |
@@ -142,31 +142,28 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, | |||
142 | flush_tlb_mm(vma->vm_mm); | 142 | flush_tlb_mm(vma->vm_mm); |
143 | } | 143 | } |
144 | 144 | ||
145 | void native_flush_tlb_others(const cpumask_t *cpumask, struct mm_struct *mm, | 145 | void native_flush_tlb_others(const struct cpumask *cpumask, |
146 | unsigned long va); | 146 | struct mm_struct *mm, unsigned long va); |
147 | 147 | ||
148 | #define TLBSTATE_OK 1 | 148 | #define TLBSTATE_OK 1 |
149 | #define TLBSTATE_LAZY 2 | 149 | #define TLBSTATE_LAZY 2 |
150 | 150 | ||
151 | #ifdef CONFIG_X86_32 | ||
152 | struct tlb_state { | 151 | struct tlb_state { |
153 | struct mm_struct *active_mm; | 152 | struct mm_struct *active_mm; |
154 | int state; | 153 | int state; |
155 | char __cacheline_padding[L1_CACHE_BYTES-8]; | ||
156 | }; | 154 | }; |
157 | DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate); | 155 | DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate); |
158 | 156 | ||
159 | void reset_lazy_tlbstate(void); | ||
160 | #else | ||
161 | static inline void reset_lazy_tlbstate(void) | 157 | static inline void reset_lazy_tlbstate(void) |
162 | { | 158 | { |
159 | percpu_write(cpu_tlbstate.state, 0); | ||
160 | percpu_write(cpu_tlbstate.active_mm, &init_mm); | ||
163 | } | 161 | } |
164 | #endif | ||
165 | 162 | ||
166 | #endif /* SMP */ | 163 | #endif /* SMP */ |
167 | 164 | ||
168 | #ifndef CONFIG_PARAVIRT | 165 | #ifndef CONFIG_PARAVIRT |
169 | #define flush_tlb_others(mask, mm, va) native_flush_tlb_others(&mask, mm, va) | 166 | #define flush_tlb_others(mask, mm, va) native_flush_tlb_others(mask, mm, va) |
170 | #endif | 167 | #endif |
171 | 168 | ||
172 | static inline void flush_tlb_kernel_range(unsigned long start, | 169 | static inline void flush_tlb_kernel_range(unsigned long start, |
@@ -175,4 +172,6 @@ static inline void flush_tlb_kernel_range(unsigned long start, | |||
175 | flush_tlb_all(); | 172 | flush_tlb_all(); |
176 | } | 173 | } |
177 | 174 | ||
175 | extern void zap_low_mappings(void); | ||
176 | |||
178 | #endif /* _ASM_X86_TLBFLUSH_H */ | 177 | #endif /* _ASM_X86_TLBFLUSH_H */ |
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 4e2f2e0aab27..77cfb2cfb386 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h | |||
@@ -74,6 +74,8 @@ static inline const struct cpumask *cpumask_of_node(int node) | |||
74 | return &node_to_cpumask_map[node]; | 74 | return &node_to_cpumask_map[node]; |
75 | } | 75 | } |
76 | 76 | ||
77 | static inline void setup_node_to_cpumask_map(void) { } | ||
78 | |||
77 | #else /* CONFIG_X86_64 */ | 79 | #else /* CONFIG_X86_64 */ |
78 | 80 | ||
79 | /* Mappings between node number and cpus on that node. */ | 81 | /* Mappings between node number and cpus on that node. */ |
@@ -83,7 +85,8 @@ extern cpumask_t *node_to_cpumask_map; | |||
83 | DECLARE_EARLY_PER_CPU(int, x86_cpu_to_node_map); | 85 | DECLARE_EARLY_PER_CPU(int, x86_cpu_to_node_map); |
84 | 86 | ||
85 | /* Returns the number of the current Node. */ | 87 | /* Returns the number of the current Node. */ |
86 | #define numa_node_id() read_pda(nodenumber) | 88 | DECLARE_PER_CPU(int, node_number); |
89 | #define numa_node_id() percpu_read(node_number) | ||
87 | 90 | ||
88 | #ifdef CONFIG_DEBUG_PER_CPU_MAPS | 91 | #ifdef CONFIG_DEBUG_PER_CPU_MAPS |
89 | extern int cpu_to_node(int cpu); | 92 | extern int cpu_to_node(int cpu); |
@@ -102,10 +105,7 @@ static inline int cpu_to_node(int cpu) | |||
102 | /* Same function but used if called before per_cpu areas are setup */ | 105 | /* Same function but used if called before per_cpu areas are setup */ |
103 | static inline int early_cpu_to_node(int cpu) | 106 | static inline int early_cpu_to_node(int cpu) |
104 | { | 107 | { |
105 | if (early_per_cpu_ptr(x86_cpu_to_node_map)) | 108 | return early_per_cpu(x86_cpu_to_node_map, cpu); |
106 | return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu]; | ||
107 | |||
108 | return per_cpu(x86_cpu_to_node_map, cpu); | ||
109 | } | 109 | } |
110 | 110 | ||
111 | /* Returns a pointer to the cpumask of CPUs on Node 'node'. */ | 111 | /* Returns a pointer to the cpumask of CPUs on Node 'node'. */ |
@@ -122,6 +122,8 @@ static inline cpumask_t node_to_cpumask(int node) | |||
122 | 122 | ||
123 | #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ | 123 | #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ |
124 | 124 | ||
125 | extern void setup_node_to_cpumask_map(void); | ||
126 | |||
125 | /* | 127 | /* |
126 | * Replace default node_to_cpumask_ptr with optimized version | 128 | * Replace default node_to_cpumask_ptr with optimized version |
127 | * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)" | 129 | * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)" |
@@ -192,9 +194,20 @@ extern int __node_distance(int, int); | |||
192 | 194 | ||
193 | #else /* !CONFIG_NUMA */ | 195 | #else /* !CONFIG_NUMA */ |
194 | 196 | ||
195 | #define numa_node_id() 0 | 197 | static inline int numa_node_id(void) |
196 | #define cpu_to_node(cpu) 0 | 198 | { |
197 | #define early_cpu_to_node(cpu) 0 | 199 | return 0; |
200 | } | ||
201 | |||
202 | static inline int cpu_to_node(int cpu) | ||
203 | { | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static inline int early_cpu_to_node(int cpu) | ||
208 | { | ||
209 | return 0; | ||
210 | } | ||
198 | 211 | ||
199 | static inline const cpumask_t *cpumask_of_node(int node) | 212 | static inline const cpumask_t *cpumask_of_node(int node) |
200 | { | 213 | { |
@@ -209,6 +222,8 @@ static inline int node_to_first_cpu(int node) | |||
209 | return first_cpu(cpu_online_map); | 222 | return first_cpu(cpu_online_map); |
210 | } | 223 | } |
211 | 224 | ||
225 | static inline void setup_node_to_cpumask_map(void) { } | ||
226 | |||
212 | /* | 227 | /* |
213 | * Replace default node_to_cpumask_ptr with optimized version | 228 | * Replace default node_to_cpumask_ptr with optimized version |
214 | * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)" | 229 | * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)" |
diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h index 780ba0ab94f9..90f06c25221d 100644 --- a/arch/x86/include/asm/trampoline.h +++ b/arch/x86/include/asm/trampoline.h | |||
@@ -13,6 +13,7 @@ extern unsigned char *trampoline_base; | |||
13 | 13 | ||
14 | extern unsigned long init_rsp; | 14 | extern unsigned long init_rsp; |
15 | extern unsigned long initial_code; | 15 | extern unsigned long initial_code; |
16 | extern unsigned long initial_gs; | ||
16 | 17 | ||
17 | #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE) | 18 | #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE) |
18 | #define TRAMPOLINE_BASE 0x6000 | 19 | #define TRAMPOLINE_BASE 0x6000 |
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h new file mode 100644 index 000000000000..8ac1d7e312f3 --- /dev/null +++ b/arch/x86/include/asm/uv/uv.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef _ASM_X86_UV_UV_H | ||
2 | #define _ASM_X86_UV_UV_H | ||
3 | |||
4 | enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; | ||
5 | |||
6 | #ifdef CONFIG_X86_UV | ||
7 | |||
8 | extern enum uv_system_type get_uv_system_type(void); | ||
9 | extern int is_uv_system(void); | ||
10 | extern void uv_cpu_init(void); | ||
11 | extern void uv_system_init(void); | ||
12 | extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); | ||
13 | extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | ||
14 | struct mm_struct *mm, | ||
15 | unsigned long va, | ||
16 | unsigned int cpu); | ||
17 | |||
18 | #else /* X86_UV */ | ||
19 | |||
20 | static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } | ||
21 | static inline int is_uv_system(void) { return 0; } | ||
22 | static inline void uv_cpu_init(void) { } | ||
23 | static inline void uv_system_init(void) { } | ||
24 | static inline int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip) | ||
25 | { return 1; } | ||
26 | static inline const struct cpumask * | ||
27 | uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, | ||
28 | unsigned long va, unsigned int cpu) | ||
29 | { return cpumask; } | ||
30 | |||
31 | #endif /* X86_UV */ | ||
32 | |||
33 | #endif /* _ASM_X86_UV_UV_H */ | ||
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 50423c7b56b2..9b0e61bf7a88 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h | |||
@@ -325,7 +325,6 @@ static inline void bau_cpubits_clear(struct bau_local_cpumask *dstp, int nbits) | |||
325 | #define cpubit_isset(cpu, bau_local_cpumask) \ | 325 | #define cpubit_isset(cpu, bau_local_cpumask) \ |
326 | test_bit((cpu), (bau_local_cpumask).bits) | 326 | test_bit((cpu), (bau_local_cpumask).bits) |
327 | 327 | ||
328 | extern int uv_flush_tlb_others(cpumask_t *, struct mm_struct *, unsigned long); | ||
329 | extern void uv_bau_message_intr1(void); | 328 | extern void uv_bau_message_intr1(void); |
330 | extern void uv_bau_timeout_intr1(void); | 329 | extern void uv_bau_timeout_intr1(void); |
331 | 330 | ||