diff options
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 26 | ||||
-rw-r--r-- | include/asm-powerpc/paca.h | 1 | ||||
-rw-r--r-- | include/asm-powerpc/percpu.h | 56 |
3 files changed, 83 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 0420418f317a..e29b275e09e0 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/unistd.h> | 33 | #include <linux/unistd.h> |
34 | #include <linux/serial.h> | 34 | #include <linux/serial.h> |
35 | #include <linux/serial_8250.h> | 35 | #include <linux/serial_8250.h> |
36 | #include <linux/bootmem.h> | ||
36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
37 | #include <asm/kdump.h> | 38 | #include <asm/kdump.h> |
38 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
@@ -654,3 +655,28 @@ void cpu_die(void) | |||
654 | if (ppc_md.cpu_die) | 655 | if (ppc_md.cpu_die) |
655 | ppc_md.cpu_die(); | 656 | ppc_md.cpu_die(); |
656 | } | 657 | } |
658 | |||
659 | #ifdef CONFIG_SMP | ||
660 | void __init setup_per_cpu_areas(void) | ||
661 | { | ||
662 | int i; | ||
663 | unsigned long size; | ||
664 | char *ptr; | ||
665 | |||
666 | /* Copy section for each CPU (we discard the original) */ | ||
667 | size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES); | ||
668 | #ifdef CONFIG_MODULES | ||
669 | if (size < PERCPU_ENOUGH_ROOM) | ||
670 | size = PERCPU_ENOUGH_ROOM; | ||
671 | #endif | ||
672 | |||
673 | for_each_cpu(i) { | ||
674 | ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size); | ||
675 | if (!ptr) | ||
676 | panic("Cannot allocate cpu data for CPU %d\n", i); | ||
677 | |||
678 | paca[i].data_offset = ptr - __per_cpu_start; | ||
679 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); | ||
680 | } | ||
681 | } | ||
682 | #endif | ||
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 3ae52d9dc9ff..a64b4d425dab 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h | |||
@@ -65,6 +65,7 @@ struct paca_struct { | |||
65 | u64 stab_real; /* Absolute address of segment table */ | 65 | u64 stab_real; /* Absolute address of segment table */ |
66 | u64 stab_addr; /* Virtual address of segment table */ | 66 | u64 stab_addr; /* Virtual address of segment table */ |
67 | void *emergency_sp; /* pointer to emergency stack */ | 67 | void *emergency_sp; /* pointer to emergency stack */ |
68 | u64 data_offset; /* per cpu data offset */ | ||
68 | s16 hw_cpu_id; /* Physical processor number */ | 69 | s16 hw_cpu_id; /* Physical processor number */ |
69 | u8 cpu_start; /* At startup, processor spins until */ | 70 | u8 cpu_start; /* At startup, processor spins until */ |
70 | /* this becomes non-zero. */ | 71 | /* this becomes non-zero. */ |
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h index 06a959d67234..e31922c50e53 100644 --- a/include/asm-powerpc/percpu.h +++ b/include/asm-powerpc/percpu.h | |||
@@ -1 +1,57 @@ | |||
1 | #ifndef _ASM_POWERPC_PERCPU_H_ | ||
2 | #define _ASM_POWERPC_PERCPU_H_ | ||
3 | #ifdef __powerpc64__ | ||
4 | #include <linux/compiler.h> | ||
5 | |||
6 | /* | ||
7 | * Same as asm-generic/percpu.h, except that we store the per cpu offset | ||
8 | * in the paca. Based on the x86-64 implementation. | ||
9 | */ | ||
10 | |||
11 | #ifdef CONFIG_SMP | ||
12 | |||
13 | #include <asm/paca.h> | ||
14 | |||
15 | #define __per_cpu_offset(cpu) (paca[cpu].data_offset) | ||
16 | #define __my_cpu_offset() get_paca()->data_offset | ||
17 | |||
18 | /* Separate out the type, so (int[3], foo) works. */ | ||
19 | #define DEFINE_PER_CPU(type, name) \ | ||
20 | __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name | ||
21 | |||
22 | /* var is in discarded region: offset to particular copy we want */ | ||
23 | #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu))) | ||
24 | #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset())) | ||
25 | |||
26 | /* A macro to avoid #include hell... */ | ||
27 | #define percpu_modcopy(pcpudst, src, size) \ | ||
28 | do { \ | ||
29 | unsigned int __i; \ | ||
30 | for (__i = 0; __i < NR_CPUS; __i++) \ | ||
31 | if (cpu_possible(__i)) \ | ||
32 | memcpy((pcpudst)+__per_cpu_offset(__i), \ | ||
33 | (src), (size)); \ | ||
34 | } while (0) | ||
35 | |||
36 | extern void setup_per_cpu_areas(void); | ||
37 | |||
38 | #else /* ! SMP */ | ||
39 | |||
40 | #define DEFINE_PER_CPU(type, name) \ | ||
41 | __typeof__(type) per_cpu__##name | ||
42 | |||
43 | #define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var)) | ||
44 | #define __get_cpu_var(var) per_cpu__##var | ||
45 | |||
46 | #endif /* SMP */ | ||
47 | |||
48 | #define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name | ||
49 | |||
50 | #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) | ||
51 | #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var) | ||
52 | |||
53 | #else | ||
1 | #include <asm-generic/percpu.h> | 54 | #include <asm-generic/percpu.h> |
55 | #endif | ||
56 | |||
57 | #endif /* _ASM_POWERPC_PERCPU_H_ */ | ||