diff options
author | Tejun Heo <tj@kernel.org> | 2010-12-17 09:16:46 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-12-17 09:16:46 -0500 |
commit | 275c8b93288ef0c2281e414e069ea8ed4bad03f7 (patch) | |
tree | df906ef901d7719d66944921c7436f5db718dc2f /arch/x86 | |
parent | 909ea96468096b07fbb41aaf69be060d92bd9271 (diff) | |
parent | 8f1d97c79eb65de1d05799d6b81d79cd94169114 (diff) |
Merge branch 'this_cpu_ops' into for-2.6.38
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/crypto/ghash-clmulni-intel_glue.c | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/percpu.h | 43 | ||||
-rw-r--r-- | arch/x86/include/asm/pvclock.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/head_32.S | 4 | ||||
-rw-r--r-- | arch/x86/kernel/pvclock.c | 5 | ||||
-rw-r--r-- | arch/x86/lguest/boot.c | 16 | ||||
-rw-r--r-- | arch/x86/lguest/i386_head.S | 105 | ||||
-rw-r--r-- | arch/x86/xen/time.c | 2 |
8 files changed, 167 insertions, 10 deletions
diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c index cbcc8d8ea93a..7a6e68e4f748 100644 --- a/arch/x86/crypto/ghash-clmulni-intel_glue.c +++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * by the Free Software Foundation. | 10 | * by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/err.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index f899e01a8ac9..38f9e965ff96 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
@@ -177,6 +177,39 @@ do { \ | |||
177 | } \ | 177 | } \ |
178 | } while (0) | 178 | } while (0) |
179 | 179 | ||
180 | /* | ||
181 | * Add return operation | ||
182 | */ | ||
183 | #define percpu_add_return_op(var, val) \ | ||
184 | ({ \ | ||
185 | typeof(var) paro_ret__ = val; \ | ||
186 | switch (sizeof(var)) { \ | ||
187 | case 1: \ | ||
188 | asm("xaddb %0, "__percpu_arg(1) \ | ||
189 | : "+q" (paro_ret__), "+m" (var) \ | ||
190 | : : "memory"); \ | ||
191 | break; \ | ||
192 | case 2: \ | ||
193 | asm("xaddw %0, "__percpu_arg(1) \ | ||
194 | : "+r" (paro_ret__), "+m" (var) \ | ||
195 | : : "memory"); \ | ||
196 | break; \ | ||
197 | case 4: \ | ||
198 | asm("xaddl %0, "__percpu_arg(1) \ | ||
199 | : "+r" (paro_ret__), "+m" (var) \ | ||
200 | : : "memory"); \ | ||
201 | break; \ | ||
202 | case 8: \ | ||
203 | asm("xaddq %0, "__percpu_arg(1) \ | ||
204 | : "+re" (paro_ret__), "+m" (var) \ | ||
205 | : : "memory"); \ | ||
206 | break; \ | ||
207 | default: __bad_percpu_size(); \ | ||
208 | } \ | ||
209 | paro_ret__ += val; \ | ||
210 | paro_ret__; \ | ||
211 | }) | ||
212 | |||
180 | #define percpu_from_op(op, var, constraint) \ | 213 | #define percpu_from_op(op, var, constraint) \ |
181 | ({ \ | 214 | ({ \ |
182 | typeof(var) pfo_ret__; \ | 215 | typeof(var) pfo_ret__; \ |
@@ -300,6 +333,14 @@ do { \ | |||
300 | #define irqsafe_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val) | 333 | #define irqsafe_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val) |
301 | #define irqsafe_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val) | 334 | #define irqsafe_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val) |
302 | 335 | ||
336 | #ifndef CONFIG_M386 | ||
337 | #define __this_cpu_add_return_1(pcp, val) percpu_add_return_op(pcp, val) | ||
338 | #define __this_cpu_add_return_2(pcp, val) percpu_add_return_op(pcp, val) | ||
339 | #define __this_cpu_add_return_4(pcp, val) percpu_add_return_op(pcp, val) | ||
340 | #define this_cpu_add_return_1(pcp, val) percpu_add_return_op(pcp, val) | ||
341 | #define this_cpu_add_return_2(pcp, val) percpu_add_return_op(pcp, val) | ||
342 | #define this_cpu_add_return_4(pcp, val) percpu_add_return_op(pcp, val) | ||
343 | #endif | ||
303 | /* | 344 | /* |
304 | * Per cpu atomic 64 bit operations are only available under 64 bit. | 345 | * Per cpu atomic 64 bit operations are only available under 64 bit. |
305 | * 32 bit must fall back to generic operations. | 346 | * 32 bit must fall back to generic operations. |
@@ -324,6 +365,8 @@ do { \ | |||
324 | #define irqsafe_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) | 365 | #define irqsafe_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) |
325 | #define irqsafe_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val) | 366 | #define irqsafe_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val) |
326 | 367 | ||
368 | #define __this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val) | ||
369 | #define this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val) | ||
327 | #endif | 370 | #endif |
328 | 371 | ||
329 | /* This is not atomic against other CPUs -- CPU preemption needs to be off */ | 372 | /* This is not atomic against other CPUs -- CPU preemption needs to be off */ |
diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index 7f7e577a0e39..31d84acc1512 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h | |||
@@ -11,6 +11,7 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src); | |||
11 | void pvclock_read_wallclock(struct pvclock_wall_clock *wall, | 11 | void pvclock_read_wallclock(struct pvclock_wall_clock *wall, |
12 | struct pvclock_vcpu_time_info *vcpu, | 12 | struct pvclock_vcpu_time_info *vcpu, |
13 | struct timespec *ts); | 13 | struct timespec *ts); |
14 | void pvclock_resume(void); | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, | 17 | * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, |
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index bcece91dd311..f0bea76f6ea5 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -620,13 +620,13 @@ ENTRY(initial_code) | |||
620 | __PAGE_ALIGNED_BSS | 620 | __PAGE_ALIGNED_BSS |
621 | .align PAGE_SIZE_asm | 621 | .align PAGE_SIZE_asm |
622 | #ifdef CONFIG_X86_PAE | 622 | #ifdef CONFIG_X86_PAE |
623 | initial_pg_pmd: | 623 | ENTRY(initial_pg_pmd) |
624 | .fill 1024*KPMDS,4,0 | 624 | .fill 1024*KPMDS,4,0 |
625 | #else | 625 | #else |
626 | ENTRY(initial_page_table) | 626 | ENTRY(initial_page_table) |
627 | .fill 1024,4,0 | 627 | .fill 1024,4,0 |
628 | #endif | 628 | #endif |
629 | initial_pg_fixmap: | 629 | ENTRY(initial_pg_fixmap) |
630 | .fill 1024,4,0 | 630 | .fill 1024,4,0 |
631 | ENTRY(empty_zero_page) | 631 | ENTRY(empty_zero_page) |
632 | .fill 4096,1,0 | 632 | .fill 4096,1,0 |
diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c index 008b91eefa18..42eb3300dfc6 100644 --- a/arch/x86/kernel/pvclock.c +++ b/arch/x86/kernel/pvclock.c | |||
@@ -83,6 +83,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src) | |||
83 | 83 | ||
84 | static atomic64_t last_value = ATOMIC64_INIT(0); | 84 | static atomic64_t last_value = ATOMIC64_INIT(0); |
85 | 85 | ||
86 | void pvclock_resume(void) | ||
87 | { | ||
88 | atomic64_set(&last_value, 0); | ||
89 | } | ||
90 | |||
86 | cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) | 91 | cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) |
87 | { | 92 | { |
88 | struct pvclock_shadow_time shadow; | 93 | struct pvclock_shadow_time shadow; |
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 73b1e1a1f489..4996cf5f73a0 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -531,7 +531,10 @@ static void lguest_write_cr3(unsigned long cr3) | |||
531 | { | 531 | { |
532 | lguest_data.pgdir = cr3; | 532 | lguest_data.pgdir = cr3; |
533 | lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); | 533 | lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); |
534 | cr3_changed = true; | 534 | |
535 | /* These two page tables are simple, linear, and used during boot */ | ||
536 | if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table)) | ||
537 | cr3_changed = true; | ||
535 | } | 538 | } |
536 | 539 | ||
537 | static unsigned long lguest_read_cr3(void) | 540 | static unsigned long lguest_read_cr3(void) |
@@ -703,9 +706,9 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval) | |||
703 | * to forget all of them. Fortunately, this is very rare. | 706 | * to forget all of them. Fortunately, this is very rare. |
704 | * | 707 | * |
705 | * ... except in early boot when the kernel sets up the initial pagetables, | 708 | * ... except in early boot when the kernel sets up the initial pagetables, |
706 | * which makes booting astonishingly slow: 1.83 seconds! So we don't even tell | 709 | * which makes booting astonishingly slow: 48 seconds! So we don't even tell |
707 | * the Host anything changed until we've done the first page table switch, | 710 | * the Host anything changed until we've done the first real page table switch, |
708 | * which brings boot back to 0.25 seconds. | 711 | * which brings boot back to 4.3 seconds. |
709 | */ | 712 | */ |
710 | static void lguest_set_pte(pte_t *ptep, pte_t pteval) | 713 | static void lguest_set_pte(pte_t *ptep, pte_t pteval) |
711 | { | 714 | { |
@@ -1002,7 +1005,7 @@ static void lguest_time_init(void) | |||
1002 | clockevents_register_device(&lguest_clockevent); | 1005 | clockevents_register_device(&lguest_clockevent); |
1003 | 1006 | ||
1004 | /* Finally, we unblock the timer interrupt. */ | 1007 | /* Finally, we unblock the timer interrupt. */ |
1005 | enable_lguest_irq(0); | 1008 | clear_bit(0, lguest_data.blocked_interrupts); |
1006 | } | 1009 | } |
1007 | 1010 | ||
1008 | /* | 1011 | /* |
@@ -1349,9 +1352,6 @@ __init void lguest_init(void) | |||
1349 | */ | 1352 | */ |
1350 | switch_to_new_gdt(0); | 1353 | switch_to_new_gdt(0); |
1351 | 1354 | ||
1352 | /* We actually boot with all memory mapped, but let's say 128MB. */ | ||
1353 | max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT; | ||
1354 | |||
1355 | /* | 1355 | /* |
1356 | * The Host<->Guest Switcher lives at the top of our address space, and | 1356 | * The Host<->Guest Switcher lives at the top of our address space, and |
1357 | * the Host told us how big it is when we made LGUEST_INIT hypercall: | 1357 | * the Host told us how big it is when we made LGUEST_INIT hypercall: |
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 4f420c2f2d55..e7d5382ef263 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <asm/asm-offsets.h> | 4 | #include <asm/asm-offsets.h> |
5 | #include <asm/thread_info.h> | 5 | #include <asm/thread_info.h> |
6 | #include <asm/processor-flags.h> | 6 | #include <asm/processor-flags.h> |
7 | #include <asm/pgtable.h> | ||
7 | 8 | ||
8 | /*G:020 | 9 | /*G:020 |
9 | * Our story starts with the kernel booting into startup_32 in | 10 | * Our story starts with the kernel booting into startup_32 in |
@@ -37,9 +38,113 @@ ENTRY(lguest_entry) | |||
37 | /* Set up the initial stack so we can run C code. */ | 38 | /* Set up the initial stack so we can run C code. */ |
38 | movl $(init_thread_union+THREAD_SIZE),%esp | 39 | movl $(init_thread_union+THREAD_SIZE),%esp |
39 | 40 | ||
41 | call init_pagetables | ||
42 | |||
40 | /* Jumps are relative: we're running __PAGE_OFFSET too low. */ | 43 | /* Jumps are relative: we're running __PAGE_OFFSET too low. */ |
41 | jmp lguest_init+__PAGE_OFFSET | 44 | jmp lguest_init+__PAGE_OFFSET |
42 | 45 | ||
46 | /* | ||
47 | * Initialize page tables. This creates a PDE and a set of page | ||
48 | * tables, which are located immediately beyond __brk_base. The variable | ||
49 | * _brk_end is set up to point to the first "safe" location. | ||
50 | * Mappings are created both at virtual address 0 (identity mapping) | ||
51 | * and PAGE_OFFSET for up to _end. | ||
52 | * | ||
53 | * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they | ||
54 | * don't have a stack at this point, so we can't just use call and ret. | ||
55 | */ | ||
56 | init_pagetables: | ||
57 | #if PTRS_PER_PMD > 1 | ||
58 | #define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD) | ||
59 | #else | ||
60 | #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) | ||
61 | #endif | ||
62 | #define pa(X) ((X) - __PAGE_OFFSET) | ||
63 | |||
64 | /* Enough space to fit pagetables for the low memory linear map */ | ||
65 | MAPPING_BEYOND_END = \ | ||
66 | PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT | ||
67 | #ifdef CONFIG_X86_PAE | ||
68 | |||
69 | /* | ||
70 | * In PAE mode initial_page_table is statically defined to contain | ||
71 | * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 | ||
72 | * entries). The identity mapping is handled by pointing two PGD entries | ||
73 | * to the first kernel PMD. | ||
74 | * | ||
75 | * Note the upper half of each PMD or PTE are always zero at this stage. | ||
76 | */ | ||
77 | |||
78 | #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ | ||
79 | |||
80 | xorl %ebx,%ebx /* %ebx is kept at zero */ | ||
81 | |||
82 | movl $pa(__brk_base), %edi | ||
83 | movl $pa(initial_pg_pmd), %edx | ||
84 | movl $PTE_IDENT_ATTR, %eax | ||
85 | 10: | ||
86 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ | ||
87 | movl %ecx,(%edx) /* Store PMD entry */ | ||
88 | /* Upper half already zero */ | ||
89 | addl $8,%edx | ||
90 | movl $512,%ecx | ||
91 | 11: | ||
92 | stosl | ||
93 | xchgl %eax,%ebx | ||
94 | stosl | ||
95 | xchgl %eax,%ebx | ||
96 | addl $0x1000,%eax | ||
97 | loop 11b | ||
98 | |||
99 | /* | ||
100 | * End condition: we must map up to the end + MAPPING_BEYOND_END. | ||
101 | */ | ||
102 | movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp | ||
103 | cmpl %ebp,%eax | ||
104 | jb 10b | ||
105 | 1: | ||
106 | addl $__PAGE_OFFSET, %edi | ||
107 | movl %edi, pa(_brk_end) | ||
108 | shrl $12, %eax | ||
109 | movl %eax, pa(max_pfn_mapped) | ||
110 | |||
111 | /* Do early initialization of the fixmap area */ | ||
112 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax | ||
113 | movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) | ||
114 | #else /* Not PAE */ | ||
115 | |||
116 | page_pde_offset = (__PAGE_OFFSET >> 20); | ||
117 | |||
118 | movl $pa(__brk_base), %edi | ||
119 | movl $pa(initial_page_table), %edx | ||
120 | movl $PTE_IDENT_ATTR, %eax | ||
121 | 10: | ||
122 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ | ||
123 | movl %ecx,(%edx) /* Store identity PDE entry */ | ||
124 | movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ | ||
125 | addl $4,%edx | ||
126 | movl $1024, %ecx | ||
127 | 11: | ||
128 | stosl | ||
129 | addl $0x1000,%eax | ||
130 | loop 11b | ||
131 | /* | ||
132 | * End condition: we must map up to the end + MAPPING_BEYOND_END. | ||
133 | */ | ||
134 | movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp | ||
135 | cmpl %ebp,%eax | ||
136 | jb 10b | ||
137 | addl $__PAGE_OFFSET, %edi | ||
138 | movl %edi, pa(_brk_end) | ||
139 | shrl $12, %eax | ||
140 | movl %eax, pa(max_pfn_mapped) | ||
141 | |||
142 | /* Do early initialization of the fixmap area */ | ||
143 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax | ||
144 | movl %eax,pa(initial_page_table+0xffc) | ||
145 | #endif | ||
146 | ret | ||
147 | |||
43 | /*G:055 | 148 | /*G:055 |
44 | * We create a macro which puts the assembler code between lgstart_ and lgend_ | 149 | * We create a macro which puts the assembler code between lgstart_ and lgend_ |
45 | * markers. These templates are put in the .text section: they can't be | 150 | * markers. These templates are put in the .text section: they can't be |
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index ef8930f51b09..067759e3d6a5 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c | |||
@@ -426,6 +426,8 @@ void xen_timer_resume(void) | |||
426 | { | 426 | { |
427 | int cpu; | 427 | int cpu; |
428 | 428 | ||
429 | pvclock_resume(); | ||
430 | |||
429 | if (xen_clockevent != &xen_vcpuop_clockevent) | 431 | if (xen_clockevent != &xen_vcpuop_clockevent) |
430 | return; | 432 | return; |
431 | 433 | ||