aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/cpu/Makefile2
-rw-r--r--arch/x86/kernel/cpu/cmpxchg.c72
-rw-r--r--arch/x86/kernel/cpu/intel.c64
3 files changed, 73 insertions, 65 deletions
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index ee76eaad3001..25b4c063fbf6 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -5,7 +5,7 @@
5obj-y := intel_cacheinfo.o addon_cpuid_features.o 5obj-y := intel_cacheinfo.o addon_cpuid_features.o
6obj-y += proc.o feature_names.o 6obj-y += proc.o feature_names.o
7 7
8obj-$(CONFIG_X86_32) += common.o bugs.o 8obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o
9obj-$(CONFIG_X86_64) += common_64.o bugs_64.o 9obj-$(CONFIG_X86_64) += common_64.o bugs_64.o
10obj-$(CONFIG_X86_32) += amd.o 10obj-$(CONFIG_X86_32) += amd.o
11obj-$(CONFIG_X86_64) += amd_64.o 11obj-$(CONFIG_X86_64) += amd_64.o
diff --git a/arch/x86/kernel/cpu/cmpxchg.c b/arch/x86/kernel/cpu/cmpxchg.c
new file mode 100644
index 000000000000..2056ccf572cc
--- /dev/null
+++ b/arch/x86/kernel/cpu/cmpxchg.c
@@ -0,0 +1,72 @@
1/*
2 * cmpxchg*() fallbacks for CPU not supporting these instructions
3 */
4
5#include <linux/kernel.h>
6#include <linux/smp.h>
7#include <linux/module.h>
8
9#ifndef CONFIG_X86_CMPXCHG
10unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new)
11{
12 u8 prev;
13 unsigned long flags;
14
15 /* Poor man's cmpxchg for 386. Unsuitable for SMP */
16 local_irq_save(flags);
17 prev = *(u8 *)ptr;
18 if (prev == old)
19 *(u8 *)ptr = new;
20 local_irq_restore(flags);
21 return prev;
22}
23EXPORT_SYMBOL(cmpxchg_386_u8);
24
25unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new)
26{
27 u16 prev;
28 unsigned long flags;
29
30 /* Poor man's cmpxchg for 386. Unsuitable for SMP */
31 local_irq_save(flags);
32 prev = *(u16 *)ptr;
33 if (prev == old)
34 *(u16 *)ptr = new;
35 local_irq_restore(flags);
36 return prev;
37}
38EXPORT_SYMBOL(cmpxchg_386_u16);
39
40unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
41{
42 u32 prev;
43 unsigned long flags;
44
45 /* Poor man's cmpxchg for 386. Unsuitable for SMP */
46 local_irq_save(flags);
47 prev = *(u32 *)ptr;
48 if (prev == old)
49 *(u32 *)ptr = new;
50 local_irq_restore(flags);
51 return prev;
52}
53EXPORT_SYMBOL(cmpxchg_386_u32);
54#endif
55
56#ifndef CONFIG_X86_CMPXCHG64
57unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
58{
59 u64 prev;
60 unsigned long flags;
61
62 /* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */
63 local_irq_save(flags);
64 prev = *(u64 *)ptr;
65 if (prev == old)
66 *(u64 *)ptr = new;
67 local_irq_restore(flags);
68 return prev;
69}
70EXPORT_SYMBOL(cmpxchg_486_u64);
71#endif
72
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 5c8959b8a42e..77618c717d76 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -307,69 +307,5 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
307 307
308cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev); 308cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev);
309 309
310#ifndef CONFIG_X86_CMPXCHG
311unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new)
312{
313 u8 prev;
314 unsigned long flags;
315
316 /* Poor man's cmpxchg for 386. Unsuitable for SMP */
317 local_irq_save(flags);
318 prev = *(u8 *)ptr;
319 if (prev == old)
320 *(u8 *)ptr = new;
321 local_irq_restore(flags);
322 return prev;
323}
324EXPORT_SYMBOL(cmpxchg_386_u8);
325
326unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new)
327{
328 u16 prev;
329 unsigned long flags;
330
331 /* Poor man's cmpxchg for 386. Unsuitable for SMP */
332 local_irq_save(flags);
333 prev = *(u16 *)ptr;
334 if (prev == old)
335 *(u16 *)ptr = new;
336 local_irq_restore(flags);
337 return prev;
338}
339EXPORT_SYMBOL(cmpxchg_386_u16);
340
341unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
342{
343 u32 prev;
344 unsigned long flags;
345
346 /* Poor man's cmpxchg for 386. Unsuitable for SMP */
347 local_irq_save(flags);
348 prev = *(u32 *)ptr;
349 if (prev == old)
350 *(u32 *)ptr = new;
351 local_irq_restore(flags);
352 return prev;
353}
354EXPORT_SYMBOL(cmpxchg_386_u32);
355#endif
356
357#ifndef CONFIG_X86_CMPXCHG64
358unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
359{
360 u64 prev;
361 unsigned long flags;
362
363 /* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */
364 local_irq_save(flags);
365 prev = *(u64 *)ptr;
366 if (prev == old)
367 *(u64 *)ptr = new;
368 local_irq_restore(flags);
369 return prev;
370}
371EXPORT_SYMBOL(cmpxchg_486_u64);
372#endif
373
374/* arch_initcall(intel_cpu_init); */ 310/* arch_initcall(intel_cpu_init); */
375 311