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_ */ | ||
